mirror of
https://github.com/DSpace/dspace-angular.git
synced 2025-10-11 12:03:03 +00:00
Merge branch 'main' into item-back-button
This commit is contained in:
12
.github/workflows/build.yml
vendored
12
.github/workflows/build.yml
vendored
@@ -15,17 +15,19 @@ jobs:
|
|||||||
env:
|
env:
|
||||||
# The ci step will test the dspace-angular code against DSpace REST.
|
# The ci step will test the dspace-angular code against DSpace REST.
|
||||||
# Direct that step to utilize a DSpace REST service that has been started in docker.
|
# Direct that step to utilize a DSpace REST service that has been started in docker.
|
||||||
DSPACE_REST_HOST: localhost
|
DSPACE_REST_HOST: 127.0.0.1
|
||||||
DSPACE_REST_PORT: 8080
|
DSPACE_REST_PORT: 8080
|
||||||
DSPACE_REST_NAMESPACE: '/server'
|
DSPACE_REST_NAMESPACE: '/server'
|
||||||
DSPACE_REST_SSL: false
|
DSPACE_REST_SSL: false
|
||||||
|
# Spin up UI on 127.0.0.1 to avoid host resolution issues in e2e tests with Node 18+
|
||||||
|
DSPACE_UI_HOST: 127.0.0.1
|
||||||
# When Chrome version is specified, we pin to a specific version of Chrome
|
# When Chrome version is specified, we pin to a specific version of Chrome
|
||||||
# Comment this out to use the latest release
|
# Comment this out to use the latest release
|
||||||
#CHROME_VERSION: "90.0.4430.212-1"
|
#CHROME_VERSION: "90.0.4430.212-1"
|
||||||
strategy:
|
strategy:
|
||||||
# Create a matrix of Node versions to test against (in parallel)
|
# Create a matrix of Node versions to test against (in parallel)
|
||||||
matrix:
|
matrix:
|
||||||
node-version: [14.x, 16.x]
|
node-version: [16.x, 18.x]
|
||||||
# Do NOT exit immediately if one matrix job fails
|
# Do NOT exit immediately if one matrix job fails
|
||||||
fail-fast: false
|
fail-fast: false
|
||||||
# These are the actual CI steps to perform per job
|
# These are the actual CI steps to perform per job
|
||||||
@@ -112,7 +114,7 @@ jobs:
|
|||||||
start: yarn run serve:ssr
|
start: yarn run serve:ssr
|
||||||
# Wait for backend & frontend to be available
|
# Wait for backend & frontend to be available
|
||||||
# NOTE: We use the 'sites' REST endpoint to also ensure the database is ready
|
# NOTE: We use the 'sites' REST endpoint to also ensure the database is ready
|
||||||
wait-on: http://localhost:8080/server/api/core/sites, http://localhost:4000
|
wait-on: http://127.0.0.1:8080/server/api/core/sites, http://127.0.0.1:4000
|
||||||
# Wait for 2 mins max for everything to respond
|
# Wait for 2 mins max for everything to respond
|
||||||
wait-on-timeout: 120
|
wait-on-timeout: 120
|
||||||
|
|
||||||
@@ -147,7 +149,7 @@ jobs:
|
|||||||
run: |
|
run: |
|
||||||
nohup yarn run serve:ssr &
|
nohup yarn run serve:ssr &
|
||||||
printf 'Waiting for app to start'
|
printf 'Waiting for app to start'
|
||||||
until curl --output /dev/null --silent --head --fail http://localhost:4000/home; do
|
until curl --output /dev/null --silent --head --fail http://127.0.0.1:4000/home; do
|
||||||
printf '.'
|
printf '.'
|
||||||
sleep 2
|
sleep 2
|
||||||
done
|
done
|
||||||
@@ -158,7 +160,7 @@ jobs:
|
|||||||
# This step also prints entire HTML of homepage for easier debugging if grep fails.
|
# This step also prints entire HTML of homepage for easier debugging if grep fails.
|
||||||
- name: Verify SSR (server-side rendering)
|
- name: Verify SSR (server-side rendering)
|
||||||
run: |
|
run: |
|
||||||
result=$(wget -O- -q http://localhost:4000/home)
|
result=$(wget -O- -q http://127.0.0.1:4000/home)
|
||||||
echo "$result"
|
echo "$result"
|
||||||
echo "$result" | grep -oE "<meta name=\"title\" [^>]*>" | grep DSpace
|
echo "$result" | grep -oE "<meta name=\"title\" [^>]*>" | grep DSpace
|
||||||
|
|
||||||
|
@@ -1,11 +1,15 @@
|
|||||||
# This image will be published as dspace/dspace-angular
|
# This image will be published as dspace/dspace-angular
|
||||||
# See https://github.com/DSpace/dspace-angular/tree/main/docker for usage details
|
# See https://github.com/DSpace/dspace-angular/tree/main/docker for usage details
|
||||||
|
|
||||||
FROM node:14-alpine
|
FROM node:18-alpine
|
||||||
WORKDIR /app
|
WORKDIR /app
|
||||||
ADD . /app/
|
ADD . /app/
|
||||||
EXPOSE 4000
|
EXPOSE 4000
|
||||||
|
|
||||||
|
# Ensure Python and other build tools are available
|
||||||
|
# These are needed to install some node modules, especially on linux/arm64
|
||||||
|
RUN apk add --update python3 make g++ && rm -rf /var/cache/apk/*
|
||||||
|
|
||||||
# We run yarn install with an increased network timeout (5min) to avoid "ESOCKETTIMEDOUT" errors from hub.docker.com
|
# We run yarn install with an increased network timeout (5min) to avoid "ESOCKETTIMEDOUT" errors from hub.docker.com
|
||||||
# See, for example https://github.com/yarnpkg/yarn/issues/5540
|
# See, for example https://github.com/yarnpkg/yarn/issues/5540
|
||||||
RUN yarn install --network-timeout 300000
|
RUN yarn install --network-timeout 300000
|
||||||
|
@@ -35,7 +35,7 @@ https://wiki.lyrasis.org/display/DSDOC7x/Installing+DSpace
|
|||||||
Quick start
|
Quick start
|
||||||
-----------
|
-----------
|
||||||
|
|
||||||
**Ensure you're running [Node](https://nodejs.org) `v14.x` or `v16.x`, [npm](https://www.npmjs.com/) >= `v5.x` and [yarn](https://yarnpkg.com) == `v1.x`**
|
**Ensure you're running [Node](https://nodejs.org) `v16.x` or `v18.x`, [npm](https://www.npmjs.com/) >= `v5.x` and [yarn](https://yarnpkg.com) == `v1.x`**
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
# clone the repo
|
# clone the repo
|
||||||
@@ -90,7 +90,7 @@ Requirements
|
|||||||
------------
|
------------
|
||||||
|
|
||||||
- [Node.js](https://nodejs.org) and [yarn](https://yarnpkg.com)
|
- [Node.js](https://nodejs.org) and [yarn](https://yarnpkg.com)
|
||||||
- Ensure you're running node `v14.x` or `v16.x` and yarn == `v1.x`
|
- Ensure you're running node `v16.x` or `v18.x` and yarn == `v1.x`
|
||||||
|
|
||||||
If you have [`nvm`](https://github.com/creationix/nvm#install-script) or [`nvm-windows`](https://github.com/coreybutler/nvm-windows) installed, which is highly recommended, you can run `nvm install --lts && nvm use` to install and start using the latest Node LTS.
|
If you have [`nvm`](https://github.com/creationix/nvm#install-script) or [`nvm-windows`](https://github.com/coreybutler/nvm-windows) installed, which is highly recommended, you can run `nvm install --lts && nvm use` to install and start using the latest Node LTS.
|
||||||
|
|
||||||
|
@@ -25,12 +25,10 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"allowedCommonJsDependencies": [
|
"allowedCommonJsDependencies": [
|
||||||
"angular2-text-mask",
|
|
||||||
"cerialize",
|
"cerialize",
|
||||||
"core-js",
|
"core-js",
|
||||||
"lodash",
|
"lodash",
|
||||||
"jwt-decode",
|
"jwt-decode",
|
||||||
"url-parse",
|
|
||||||
"uuid",
|
"uuid",
|
||||||
"webfontloader",
|
"webfontloader",
|
||||||
"zone.js"
|
"zone.js"
|
||||||
|
@@ -210,6 +210,11 @@ item:
|
|||||||
undoTimeout: 10000 # 10 seconds
|
undoTimeout: 10000 # 10 seconds
|
||||||
# Show the item access status label in items lists
|
# Show the item access status label in items lists
|
||||||
showAccessStatuses: false
|
showAccessStatuses: false
|
||||||
|
bitstream:
|
||||||
|
# Number of entries in the bitstream list in the item view page.
|
||||||
|
# Rounded to the nearest size in the list of selectable sizes on the
|
||||||
|
# settings menu. See pageSizeOptions in 'pagination-component-options.model.ts'.
|
||||||
|
pageSize: 5
|
||||||
|
|
||||||
# Collection Page Config
|
# Collection Page Config
|
||||||
collection:
|
collection:
|
||||||
|
@@ -5,7 +5,7 @@
|
|||||||
"screenshotsFolder": "cypress/screenshots",
|
"screenshotsFolder": "cypress/screenshots",
|
||||||
"pluginsFile": "cypress/plugins/index.ts",
|
"pluginsFile": "cypress/plugins/index.ts",
|
||||||
"fixturesFolder": "cypress/fixtures",
|
"fixturesFolder": "cypress/fixtures",
|
||||||
"baseUrl": "http://localhost:4000",
|
"baseUrl": "http://127.0.0.1:4000",
|
||||||
"retries": {
|
"retries": {
|
||||||
"runMode": 2,
|
"runMode": 2,
|
||||||
"openMode": 0
|
"openMode": 0
|
||||||
|
@@ -24,8 +24,8 @@ services:
|
|||||||
# __D__ => "-" (e.g. google__D__metadata => google-metadata)
|
# __D__ => "-" (e.g. google__D__metadata => google-metadata)
|
||||||
# dspace.dir, dspace.server.url and dspace.ui.url
|
# dspace.dir, dspace.server.url and dspace.ui.url
|
||||||
dspace__P__dir: /dspace
|
dspace__P__dir: /dspace
|
||||||
dspace__P__server__P__url: http://localhost:8080/server
|
dspace__P__server__P__url: http://127.0.0.1:8080/server
|
||||||
dspace__P__ui__P__url: http://localhost:4000
|
dspace__P__ui__P__url: http://127.0.0.1:4000
|
||||||
# db.url: Ensure we are using the 'dspacedb' image for our database
|
# db.url: Ensure we are using the 'dspacedb' image for our database
|
||||||
db__P__url: 'jdbc:postgresql://dspacedb:5432/dspace'
|
db__P__url: 'jdbc:postgresql://dspacedb:5432/dspace'
|
||||||
# solr.server: Ensure we are using the 'dspacesolr' image for Solr
|
# solr.server: Ensure we are using the 'dspacesolr' image for Solr
|
||||||
|
70
package.json
70
package.json
@@ -54,18 +54,18 @@
|
|||||||
"ts-node": "10.2.1"
|
"ts-node": "10.2.1"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@angular/animations": "~13.2.6",
|
"@angular/animations": "~13.3.12",
|
||||||
"@angular/cdk": "^13.2.6",
|
"@angular/cdk": "^13.2.6",
|
||||||
"@angular/common": "~13.2.6",
|
"@angular/common": "~13.3.12",
|
||||||
"@angular/compiler": "~13.2.6",
|
"@angular/compiler": "~13.3.12",
|
||||||
"@angular/core": "~13.2.6",
|
"@angular/core": "~13.3.12",
|
||||||
"@angular/forms": "~13.2.6",
|
"@angular/forms": "~13.3.12",
|
||||||
"@angular/localize": "13.2.6",
|
"@angular/localize": "13.3.12",
|
||||||
"@angular/platform-browser": "~13.2.6",
|
"@angular/platform-browser": "~13.3.12",
|
||||||
"@angular/platform-browser-dynamic": "~13.2.6",
|
"@angular/platform-browser-dynamic": "~13.3.12",
|
||||||
"@angular/platform-server": "~13.2.6",
|
"@angular/platform-server": "~13.3.12",
|
||||||
"@angular/router": "~13.2.6",
|
"@angular/router": "~13.3.12",
|
||||||
"@babel/runtime": "^7.17.2",
|
"@babel/runtime": "7.17.2",
|
||||||
"@kolkov/ngx-gallery": "^2.0.1",
|
"@kolkov/ngx-gallery": "^2.0.1",
|
||||||
"@material-ui/core": "^4.11.0",
|
"@material-ui/core": "^4.11.0",
|
||||||
"@material-ui/icons": "^4.9.1",
|
"@material-ui/icons": "^4.9.1",
|
||||||
@@ -77,15 +77,15 @@
|
|||||||
"@ngrx/store": "^13.0.2",
|
"@ngrx/store": "^13.0.2",
|
||||||
"@nguniversal/express-engine": "^13.0.2",
|
"@nguniversal/express-engine": "^13.0.2",
|
||||||
"@ngx-translate/core": "^13.0.0",
|
"@ngx-translate/core": "^13.0.0",
|
||||||
"@nicky-lenaers/ngx-scroll-to": "^9.0.0",
|
"@nicky-lenaers/ngx-scroll-to": "^13.0.0",
|
||||||
"@types/grecaptcha": "^3.0.4",
|
"@types/grecaptcha": "^3.0.4",
|
||||||
"angular-idle-preload": "3.0.0",
|
"angular-idle-preload": "3.0.0",
|
||||||
"angulartics2": "^12.0.0",
|
"angulartics2": "^12.0.0",
|
||||||
"axios": "^0.27.2",
|
"axios": "^0.27.2",
|
||||||
"bootstrap": "4.3.1",
|
"bootstrap": "^4.6.1",
|
||||||
"caniuse-lite": "^1.0.30001165",
|
|
||||||
"cerialize": "0.1.18",
|
"cerialize": "0.1.18",
|
||||||
"cli-progress": "^3.8.0",
|
"cli-progress": "^3.8.0",
|
||||||
|
"colors": "^1.4.0",
|
||||||
"compression": "^1.7.4",
|
"compression": "^1.7.4",
|
||||||
"cookie-parser": "1.4.5",
|
"cookie-parser": "1.4.5",
|
||||||
"core-js": "^3.7.0",
|
"core-js": "^3.7.0",
|
||||||
@@ -95,11 +95,8 @@
|
|||||||
"express": "^4.17.1",
|
"express": "^4.17.1",
|
||||||
"express-rate-limit": "^5.1.3",
|
"express-rate-limit": "^5.1.3",
|
||||||
"fast-json-patch": "^3.0.0-1",
|
"fast-json-patch": "^3.0.0-1",
|
||||||
"file-saver": "^2.0.5",
|
|
||||||
"filesize": "^6.1.0",
|
"filesize": "^6.1.0",
|
||||||
"font-awesome": "4.7.0",
|
|
||||||
"http-proxy-middleware": "^1.0.5",
|
"http-proxy-middleware": "^1.0.5",
|
||||||
"https": "1.0.0",
|
|
||||||
"js-cookie": "2.2.1",
|
"js-cookie": "2.2.1",
|
||||||
"js-yaml": "^4.1.0",
|
"js-yaml": "^4.1.0",
|
||||||
"json5": "^2.1.3",
|
"json5": "^2.1.3",
|
||||||
@@ -119,43 +116,38 @@
|
|||||||
"ngx-infinite-scroll": "^10.0.1",
|
"ngx-infinite-scroll": "^10.0.1",
|
||||||
"ngx-pagination": "5.0.0",
|
"ngx-pagination": "5.0.0",
|
||||||
"ngx-sortablejs": "^11.1.0",
|
"ngx-sortablejs": "^11.1.0",
|
||||||
"ngx-ui-switch": "^11.0.1",
|
"ngx-ui-switch": "^13.0.2",
|
||||||
"nouislider": "^14.6.3",
|
"nouislider": "^14.6.3",
|
||||||
"pem": "1.14.4",
|
"pem": "1.14.4",
|
||||||
"postcss-cli": "^9.1.0",
|
|
||||||
"prop-types": "^15.7.2",
|
"prop-types": "^15.7.2",
|
||||||
"react-copy-to-clipboard": "^5.0.1",
|
"react-copy-to-clipboard": "^5.0.1",
|
||||||
"reflect-metadata": "^0.1.13",
|
"reflect-metadata": "^0.1.13",
|
||||||
"rxjs": "^7.5.5",
|
"rxjs": "^7.5.5",
|
||||||
"sanitize-html": "^2.7.2",
|
"sanitize-html": "^2.7.2",
|
||||||
"sortablejs": "1.13.0",
|
"sortablejs": "1.13.0",
|
||||||
"tslib": "^2.0.0",
|
|
||||||
"url-parse": "^1.5.6",
|
|
||||||
"uuid": "^8.3.2",
|
"uuid": "^8.3.2",
|
||||||
"webfontloader": "1.6.28",
|
"webfontloader": "1.6.28",
|
||||||
"zone.js": "~0.11.5"
|
"zone.js": "~0.11.5"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@angular-builders/custom-webpack": "~13.1.0",
|
"@angular-builders/custom-webpack": "~13.1.0",
|
||||||
"@angular-devkit/build-angular": "~13.2.6",
|
"@angular-devkit/build-angular": "~13.3.10",
|
||||||
"@angular-eslint/builder": "13.1.0",
|
"@angular-eslint/builder": "13.1.0",
|
||||||
"@angular-eslint/eslint-plugin": "13.1.0",
|
"@angular-eslint/eslint-plugin": "13.1.0",
|
||||||
"@angular-eslint/eslint-plugin-template": "13.1.0",
|
"@angular-eslint/eslint-plugin-template": "13.1.0",
|
||||||
"@angular-eslint/schematics": "13.1.0",
|
"@angular-eslint/schematics": "13.1.0",
|
||||||
"@angular-eslint/template-parser": "13.1.0",
|
"@angular-eslint/template-parser": "13.1.0",
|
||||||
"@angular/cli": "~13.2.6",
|
"@angular/cli": "~13.3.10",
|
||||||
"@angular/compiler-cli": "~13.2.6",
|
"@angular/compiler-cli": "~13.3.12",
|
||||||
"@angular/language-service": "~13.2.6",
|
"@angular/language-service": "~13.3.12",
|
||||||
"@cypress/schematic": "^1.5.0",
|
"@cypress/schematic": "^1.5.0",
|
||||||
"@fortawesome/fontawesome-free": "^5.5.0",
|
"@fortawesome/fontawesome-free": "^6.2.1",
|
||||||
"@ngrx/store-devtools": "^13.0.2",
|
"@ngrx/store-devtools": "^13.0.2",
|
||||||
"@ngtools/webpack": "^13.2.6",
|
"@ngtools/webpack": "^13.2.6",
|
||||||
"@nguniversal/builders": "^13.0.2",
|
"@nguniversal/builders": "^13.1.1",
|
||||||
"@types/deep-freeze": "0.1.2",
|
"@types/deep-freeze": "0.1.2",
|
||||||
"@types/express": "^4.17.9",
|
"@types/express": "^4.17.9",
|
||||||
"@types/file-saver": "^2.0.1",
|
|
||||||
"@types/jasmine": "~3.6.0",
|
"@types/jasmine": "~3.6.0",
|
||||||
"@types/jasminewd2": "~2.0.8",
|
|
||||||
"@types/js-cookie": "2.2.6",
|
"@types/js-cookie": "2.2.6",
|
||||||
"@types/lodash": "^4.14.165",
|
"@types/lodash": "^4.14.165",
|
||||||
"@types/node": "^14.14.9",
|
"@types/node": "^14.14.9",
|
||||||
@@ -166,26 +158,18 @@
|
|||||||
"compression-webpack-plugin": "^9.2.0",
|
"compression-webpack-plugin": "^9.2.0",
|
||||||
"copy-webpack-plugin": "^6.4.1",
|
"copy-webpack-plugin": "^6.4.1",
|
||||||
"cross-env": "^7.0.3",
|
"cross-env": "^7.0.3",
|
||||||
"css-loader": "^6.2.0",
|
|
||||||
"css-minimizer-webpack-plugin": "^3.4.1",
|
|
||||||
"cssnano": "^5.0.6",
|
|
||||||
"cypress": "9.7.0",
|
"cypress": "9.7.0",
|
||||||
"cypress-axe": "^0.14.0",
|
"cypress-axe": "^0.14.0",
|
||||||
"debug-loader": "^0.0.1",
|
|
||||||
"deep-freeze": "0.0.1",
|
"deep-freeze": "0.0.1",
|
||||||
"dotenv": "^8.2.0",
|
|
||||||
"eslint": "^8.2.0",
|
"eslint": "^8.2.0",
|
||||||
"eslint-plugin-deprecation": "^1.3.2",
|
"eslint-plugin-deprecation": "^1.3.2",
|
||||||
"eslint-plugin-import": "^2.25.4",
|
"eslint-plugin-import": "^2.25.4",
|
||||||
"eslint-plugin-jsdoc": "^38.0.6",
|
"eslint-plugin-jsdoc": "^39.6.4",
|
||||||
"eslint-plugin-lodash": "^7.4.0",
|
"eslint-plugin-lodash": "^7.4.0",
|
||||||
"eslint-plugin-unused-imports": "^2.0.0",
|
"eslint-plugin-unused-imports": "^2.0.0",
|
||||||
"express-static-gzip": "^2.1.5",
|
"express-static-gzip": "^2.1.5",
|
||||||
"fork-ts-checker-webpack-plugin": "^6.0.3",
|
|
||||||
"html-loader": "^1.3.2",
|
|
||||||
"jasmine-core": "^3.8.0",
|
"jasmine-core": "^3.8.0",
|
||||||
"jasmine-marbles": "0.9.2",
|
"jasmine-marbles": "0.9.2",
|
||||||
"jasmine-spec-reporter": "~5.0.0",
|
|
||||||
"karma": "^6.3.14",
|
"karma": "^6.3.14",
|
||||||
"karma-chrome-launcher": "~3.1.0",
|
"karma-chrome-launcher": "~3.1.0",
|
||||||
"karma-coverage-istanbul-reporter": "~3.0.2",
|
"karma-coverage-istanbul-reporter": "~3.0.2",
|
||||||
@@ -193,26 +177,20 @@
|
|||||||
"karma-jasmine-html-reporter": "^1.5.0",
|
"karma-jasmine-html-reporter": "^1.5.0",
|
||||||
"karma-mocha-reporter": "2.2.5",
|
"karma-mocha-reporter": "2.2.5",
|
||||||
"ngx-mask": "^13.1.7",
|
"ngx-mask": "^13.1.7",
|
||||||
"nodemon": "^2.0.15",
|
"nodemon": "^2.0.20",
|
||||||
"postcss": "^8.1",
|
"postcss": "^8.1",
|
||||||
"postcss-apply": "0.12.0",
|
"postcss-apply": "0.12.0",
|
||||||
"postcss-import": "^14.0.0",
|
"postcss-import": "^14.0.0",
|
||||||
"postcss-loader": "^4.0.3",
|
"postcss-loader": "^4.0.3",
|
||||||
"postcss-preset-env": "^7.4.2",
|
"postcss-preset-env": "^7.4.2",
|
||||||
"postcss-responsive-type": "1.0.0",
|
"postcss-responsive-type": "1.0.0",
|
||||||
"protractor": "^7.0.0",
|
|
||||||
"protractor-istanbul-plugin": "2.0.0",
|
|
||||||
"raw-loader": "0.5.1",
|
|
||||||
"react": "^16.14.0",
|
"react": "^16.14.0",
|
||||||
"react-dom": "^16.14.0",
|
"react-dom": "^16.14.0",
|
||||||
"rimraf": "^3.0.2",
|
"rimraf": "^3.0.2",
|
||||||
"rxjs-spy": "^8.0.2",
|
"rxjs-spy": "^8.0.2",
|
||||||
"sass": "~1.32.6",
|
"sass": "~1.33.0",
|
||||||
"sass-loader": "^12.6.0",
|
"sass-loader": "^12.6.0",
|
||||||
"sass-resources-loader": "^2.1.1",
|
"sass-resources-loader": "^2.1.1",
|
||||||
"string-replace-loader": "^3.1.0",
|
|
||||||
"terser-webpack-plugin": "^2.3.1",
|
|
||||||
"ts-loader": "^5.2.0",
|
|
||||||
"ts-node": "^8.10.2",
|
"ts-node": "^8.10.2",
|
||||||
"typescript": "~4.5.5",
|
"typescript": "~4.5.5",
|
||||||
"webpack": "^5.69.1",
|
"webpack": "^5.69.1",
|
||||||
|
@@ -10,6 +10,16 @@ import { MembersListComponent } from './group-registry/group-form/members-list/m
|
|||||||
import { SubgroupsListComponent } from './group-registry/group-form/subgroup-list/subgroups-list.component';
|
import { SubgroupsListComponent } from './group-registry/group-form/subgroup-list/subgroups-list.component';
|
||||||
import { GroupsRegistryComponent } from './group-registry/groups-registry.component';
|
import { GroupsRegistryComponent } from './group-registry/groups-registry.component';
|
||||||
import { FormModule } from '../shared/form/form.module';
|
import { FormModule } from '../shared/form/form.module';
|
||||||
|
import { DYNAMIC_ERROR_MESSAGES_MATCHER, DynamicErrorMessagesMatcher } from '@ng-dynamic-forms/core';
|
||||||
|
import { AbstractControl } from '@angular/forms';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Condition for displaying error messages on email form field
|
||||||
|
*/
|
||||||
|
export const ValidateEmailErrorStateMatcher: DynamicErrorMessagesMatcher =
|
||||||
|
(control: AbstractControl, model: any, hasFocus: boolean) => {
|
||||||
|
return (control.touched && !hasFocus) || (control.errors?.emailTaken && hasFocus);
|
||||||
|
};
|
||||||
|
|
||||||
@NgModule({
|
@NgModule({
|
||||||
imports: [
|
imports: [
|
||||||
@@ -26,6 +36,12 @@ import { FormModule } from '../shared/form/form.module';
|
|||||||
GroupFormComponent,
|
GroupFormComponent,
|
||||||
SubgroupsListComponent,
|
SubgroupsListComponent,
|
||||||
MembersListComponent
|
MembersListComponent
|
||||||
|
],
|
||||||
|
providers: [
|
||||||
|
{
|
||||||
|
provide: DYNAMIC_ERROR_MESSAGES_MATCHER,
|
||||||
|
useValue: ValidateEmailErrorStateMatcher
|
||||||
|
},
|
||||||
]
|
]
|
||||||
})
|
})
|
||||||
/**
|
/**
|
||||||
|
@@ -10,6 +10,7 @@ import { AdminSearchModule } from './admin-search-page/admin-search.module';
|
|||||||
import { AdminSidebarSectionComponent } from './admin-sidebar/admin-sidebar-section/admin-sidebar-section.component';
|
import { AdminSidebarSectionComponent } from './admin-sidebar/admin-sidebar-section/admin-sidebar-section.component';
|
||||||
import { ExpandableAdminSidebarSectionComponent } from './admin-sidebar/expandable-admin-sidebar-section/expandable-admin-sidebar-section.component';
|
import { ExpandableAdminSidebarSectionComponent } from './admin-sidebar/expandable-admin-sidebar-section/expandable-admin-sidebar-section.component';
|
||||||
import { BatchImportPageComponent } from './admin-import-batch-page/batch-import-page.component';
|
import { BatchImportPageComponent } from './admin-import-batch-page/batch-import-page.component';
|
||||||
|
import { UploadModule } from '../shared/upload/upload.module';
|
||||||
|
|
||||||
const ENTRY_COMPONENTS = [
|
const ENTRY_COMPONENTS = [
|
||||||
// put only entry components that use custom decorator
|
// put only entry components that use custom decorator
|
||||||
@@ -25,7 +26,8 @@ const ENTRY_COMPONENTS = [
|
|||||||
AccessControlModule,
|
AccessControlModule,
|
||||||
AdminSearchModule.withEntryComponents(),
|
AdminSearchModule.withEntryComponents(),
|
||||||
AdminWorkflowModuleModule.withEntryComponents(),
|
AdminWorkflowModuleModule.withEntryComponents(),
|
||||||
SharedModule
|
SharedModule,
|
||||||
|
UploadModule,
|
||||||
],
|
],
|
||||||
declarations: [
|
declarations: [
|
||||||
AdminCurationTasksComponent,
|
AdminCurationTasksComponent,
|
||||||
|
@@ -1,14 +1,12 @@
|
|||||||
import { APP_BASE_HREF, CommonModule, DOCUMENT } from '@angular/common';
|
import { APP_BASE_HREF, CommonModule, DOCUMENT } from '@angular/common';
|
||||||
import { HTTP_INTERCEPTORS, HttpClientModule } from '@angular/common/http';
|
import { HTTP_INTERCEPTORS, HttpClientModule } from '@angular/common/http';
|
||||||
import { NgModule } from '@angular/core';
|
import { NgModule } from '@angular/core';
|
||||||
import { AbstractControl } from '@angular/forms';
|
|
||||||
import { BrowserModule } from '@angular/platform-browser';
|
import { BrowserModule } from '@angular/platform-browser';
|
||||||
|
|
||||||
import { NgbModule } from '@ng-bootstrap/ng-bootstrap';
|
import { NgbModule } from '@ng-bootstrap/ng-bootstrap';
|
||||||
import { EffectsModule } from '@ngrx/effects';
|
import { EffectsModule } from '@ngrx/effects';
|
||||||
import { RouterStateSerializer, StoreRouterConnectingModule } from '@ngrx/router-store';
|
import { RouterStateSerializer, StoreRouterConnectingModule } from '@ngrx/router-store';
|
||||||
import { MetaReducer, StoreModule, USER_PROVIDED_META_REDUCERS } from '@ngrx/store';
|
import { MetaReducer, StoreModule, USER_PROVIDED_META_REDUCERS } from '@ngrx/store';
|
||||||
import { DYNAMIC_ERROR_MESSAGES_MATCHER, DYNAMIC_MATCHER_PROVIDERS, DynamicErrorMessagesMatcher } from '@ng-dynamic-forms/core';
|
|
||||||
import { TranslateModule } from '@ngx-translate/core';
|
import { TranslateModule } from '@ngx-translate/core';
|
||||||
import { ScrollToModule } from '@nicky-lenaers/ngx-scroll-to';
|
import { ScrollToModule } from '@nicky-lenaers/ngx-scroll-to';
|
||||||
import { AppRoutingModule } from './app-routing.module';
|
import { AppRoutingModule } from './app-routing.module';
|
||||||
@@ -28,7 +26,6 @@ import { XsrfInterceptor } from './core/xsrf/xsrf.interceptor';
|
|||||||
import { LogInterceptor } from './core/log/log.interceptor';
|
import { LogInterceptor } from './core/log/log.interceptor';
|
||||||
import { EagerThemesModule } from '../themes/eager-themes.module';
|
import { EagerThemesModule } from '../themes/eager-themes.module';
|
||||||
import { APP_CONFIG, AppConfig } from '../config/app-config.interface';
|
import { APP_CONFIG, AppConfig } from '../config/app-config.interface';
|
||||||
import { NgxMaskModule } from 'ngx-mask';
|
|
||||||
import { StoreDevModules } from '../config/store/devtools';
|
import { StoreDevModules } from '../config/store/devtools';
|
||||||
import { RootModule } from './root.module';
|
import { RootModule } from './root.module';
|
||||||
|
|
||||||
@@ -46,14 +43,6 @@ export function getMetaReducers(appConfig: AppConfig): MetaReducer<AppState>[] {
|
|||||||
return appConfig.debug ? [...appMetaReducers, ...debugMetaReducers] : appMetaReducers;
|
return appConfig.debug ? [...appMetaReducers, ...debugMetaReducers] : appMetaReducers;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Condition for displaying error messages on email form field
|
|
||||||
*/
|
|
||||||
export const ValidateEmailErrorStateMatcher: DynamicErrorMessagesMatcher =
|
|
||||||
(control: AbstractControl, model: any, hasFocus: boolean) => {
|
|
||||||
return (control.touched && !hasFocus) || (control.errors?.emailTaken && hasFocus);
|
|
||||||
};
|
|
||||||
|
|
||||||
const IMPORTS = [
|
const IMPORTS = [
|
||||||
CommonModule,
|
CommonModule,
|
||||||
SharedModule,
|
SharedModule,
|
||||||
@@ -64,7 +53,6 @@ const IMPORTS = [
|
|||||||
ScrollToModule.forRoot(),
|
ScrollToModule.forRoot(),
|
||||||
NgbModule,
|
NgbModule,
|
||||||
TranslateModule.forRoot(),
|
TranslateModule.forRoot(),
|
||||||
NgxMaskModule.forRoot(),
|
|
||||||
EffectsModule.forRoot(appEffects),
|
EffectsModule.forRoot(appEffects),
|
||||||
StoreModule.forRoot(appReducers, storeModuleConfig),
|
StoreModule.forRoot(appReducers, storeModuleConfig),
|
||||||
StoreRouterConnectingModule.forRoot(),
|
StoreRouterConnectingModule.forRoot(),
|
||||||
@@ -113,11 +101,6 @@ const PROVIDERS = [
|
|||||||
useClass: LogInterceptor,
|
useClass: LogInterceptor,
|
||||||
multi: true
|
multi: true
|
||||||
},
|
},
|
||||||
{
|
|
||||||
provide: DYNAMIC_ERROR_MESSAGES_MATCHER,
|
|
||||||
useValue: ValidateEmailErrorStateMatcher
|
|
||||||
},
|
|
||||||
...DYNAMIC_MATCHER_PROVIDERS,
|
|
||||||
];
|
];
|
||||||
|
|
||||||
const DECLARATIONS = [
|
const DECLARATIONS = [
|
||||||
|
@@ -10,7 +10,7 @@
|
|||||||
</nav>
|
</nav>
|
||||||
|
|
||||||
<ng-template #breadcrumb let-text="text" let-url="url">
|
<ng-template #breadcrumb let-text="text" let-url="url">
|
||||||
<li class="breadcrumb-item"><div class="breadcrumb-item-limiter"><a [routerLink]="url" class="text-truncate">{{text | translate}}</a></div></li>
|
<li class="breadcrumb-item"><div class="breadcrumb-item-limiter"><a [routerLink]="url" class="text-truncate" [ngbTooltip]="text | translate" placement="bottom" >{{text | translate}}</a></div></li>
|
||||||
</ng-template>
|
</ng-template>
|
||||||
|
|
||||||
<ng-template #activeBreadcrumb let-text="text">
|
<ng-template #activeBreadcrumb let-text="text">
|
||||||
|
@@ -72,6 +72,7 @@ import { MenuItemType } from '../shared/menu/menu-item-type.model';
|
|||||||
id: 'statistics_collection_:id',
|
id: 'statistics_collection_:id',
|
||||||
active: true,
|
active: true,
|
||||||
visible: true,
|
visible: true,
|
||||||
|
index: 2,
|
||||||
model: {
|
model: {
|
||||||
type: MenuItemType.LINK,
|
type: MenuItemType.LINK,
|
||||||
text: 'menu.section.statistics',
|
text: 'menu.section.statistics',
|
||||||
|
@@ -25,7 +25,7 @@ import { ComcolModule } from '../shared/comcol/comcol.module';
|
|||||||
StatisticsModule.forRoot(),
|
StatisticsModule.forRoot(),
|
||||||
EditItemPageModule,
|
EditItemPageModule,
|
||||||
CollectionFormModule,
|
CollectionFormModule,
|
||||||
ComcolModule
|
ComcolModule,
|
||||||
],
|
],
|
||||||
declarations: [
|
declarations: [
|
||||||
CollectionPageComponent,
|
CollectionPageComponent,
|
||||||
@@ -38,7 +38,7 @@ import { ComcolModule } from '../shared/comcol/comcol.module';
|
|||||||
],
|
],
|
||||||
providers: [
|
providers: [
|
||||||
SearchService,
|
SearchService,
|
||||||
]
|
],
|
||||||
})
|
})
|
||||||
export class CollectionPageModule {
|
export class CollectionPageModule {
|
||||||
|
|
||||||
|
@@ -25,7 +25,7 @@ import { ComcolModule } from '../../shared/comcol/comcol.module';
|
|||||||
CollectionFormModule,
|
CollectionFormModule,
|
||||||
ResourcePoliciesModule,
|
ResourcePoliciesModule,
|
||||||
FormModule,
|
FormModule,
|
||||||
ComcolModule
|
ComcolModule,
|
||||||
],
|
],
|
||||||
declarations: [
|
declarations: [
|
||||||
EditCollectionPageComponent,
|
EditCollectionPageComponent,
|
||||||
|
@@ -55,6 +55,7 @@ import { MenuItemType } from '../shared/menu/menu-item-type.model';
|
|||||||
id: 'statistics_community_:id',
|
id: 'statistics_community_:id',
|
||||||
active: true,
|
active: true,
|
||||||
visible: true,
|
visible: true,
|
||||||
|
index: 2,
|
||||||
model: {
|
model: {
|
||||||
type: MenuItemType.LINK,
|
type: MenuItemType.LINK,
|
||||||
text: 'menu.section.statistics',
|
text: 'menu.section.statistics',
|
||||||
|
@@ -36,7 +36,7 @@ const DECLARATIONS = [CommunityPageComponent,
|
|||||||
CommunityPageRoutingModule,
|
CommunityPageRoutingModule,
|
||||||
StatisticsModule.forRoot(),
|
StatisticsModule.forRoot(),
|
||||||
CommunityFormModule,
|
CommunityFormModule,
|
||||||
ComcolModule
|
ComcolModule,
|
||||||
],
|
],
|
||||||
declarations: [
|
declarations: [
|
||||||
...DECLARATIONS
|
...DECLARATIONS
|
||||||
|
@@ -21,7 +21,7 @@ import { ComcolModule } from '../../shared/comcol/comcol.module';
|
|||||||
EditCommunityPageRoutingModule,
|
EditCommunityPageRoutingModule,
|
||||||
CommunityFormModule,
|
CommunityFormModule,
|
||||||
ComcolModule,
|
ComcolModule,
|
||||||
ResourcePoliciesModule
|
ResourcePoliciesModule,
|
||||||
],
|
],
|
||||||
declarations: [
|
declarations: [
|
||||||
EditCommunityPageComponent,
|
EditCommunityPageComponent,
|
||||||
|
@@ -2,15 +2,12 @@ import { CommonModule } from '@angular/common';
|
|||||||
import { HttpClient } from '@angular/common/http';
|
import { HttpClient } from '@angular/common/http';
|
||||||
import { ModuleWithProviders, NgModule, Optional, SkipSelf } from '@angular/core';
|
import { ModuleWithProviders, NgModule, Optional, SkipSelf } from '@angular/core';
|
||||||
|
|
||||||
import { DynamicFormLayoutService, DynamicFormService, DynamicFormValidationService } from '@ng-dynamic-forms/core';
|
|
||||||
import { EffectsModule } from '@ngrx/effects';
|
import { EffectsModule } from '@ngrx/effects';
|
||||||
|
|
||||||
import { Action, StoreConfig, StoreModule } from '@ngrx/store';
|
import { Action, StoreConfig, StoreModule } from '@ngrx/store';
|
||||||
import { MyDSpaceGuard } from '../my-dspace-page/my-dspace.guard';
|
import { MyDSpaceGuard } from '../my-dspace-page/my-dspace.guard';
|
||||||
|
|
||||||
import { isNotEmpty } from '../shared/empty.util';
|
import { isNotEmpty } from '../shared/empty.util';
|
||||||
import { FormBuilderService } from '../shared/form/builder/form-builder.service';
|
|
||||||
import { FormService } from '../shared/form/form.service';
|
|
||||||
import { HostWindowService } from '../shared/host-window.service';
|
import { HostWindowService } from '../shared/host-window.service';
|
||||||
import { MenuService } from '../shared/menu/menu.service';
|
import { MenuService } from '../shared/menu/menu.service';
|
||||||
import { EndpointMockingRestService } from '../shared/mocks/dspace-rest/endpoint-mocking-rest.service';
|
import { EndpointMockingRestService } from '../shared/mocks/dspace-rest/endpoint-mocking-rest.service';
|
||||||
@@ -24,8 +21,6 @@ import { SelectableListService } from '../shared/object-list/selectable-list/sel
|
|||||||
import { ObjectSelectService } from '../shared/object-select/object-select.service';
|
import { ObjectSelectService } from '../shared/object-select/object-select.service';
|
||||||
import { PaginationComponentOptions } from '../shared/pagination/pagination-component-options.model';
|
import { PaginationComponentOptions } from '../shared/pagination/pagination-component-options.model';
|
||||||
import { SidebarService } from '../shared/sidebar/sidebar.service';
|
import { SidebarService } from '../shared/sidebar/sidebar.service';
|
||||||
import { UploaderService } from '../shared/uploader/uploader.service';
|
|
||||||
import { SectionFormOperationsService } from '../submission/sections/form/section-form-operations.service';
|
|
||||||
import { AuthenticatedGuard } from './auth/authenticated.guard';
|
import { AuthenticatedGuard } from './auth/authenticated.guard';
|
||||||
import { AuthStatus } from './auth/models/auth-status.model';
|
import { AuthStatus } from './auth/models/auth-status.model';
|
||||||
import { BrowseService } from './browse/browse.service';
|
import { BrowseService } from './browse/browse.service';
|
||||||
@@ -137,9 +132,6 @@ import {
|
|||||||
import { Registration } from './shared/registration.model';
|
import { Registration } from './shared/registration.model';
|
||||||
import { MetadataSchemaDataService } from './data/metadata-schema-data.service';
|
import { MetadataSchemaDataService } from './data/metadata-schema-data.service';
|
||||||
import { MetadataFieldDataService } from './data/metadata-field-data.service';
|
import { MetadataFieldDataService } from './data/metadata-field-data.service';
|
||||||
import {
|
|
||||||
DsDynamicTypeBindRelationService
|
|
||||||
} from '../shared/form/builder/ds-dynamic-form-ui/ds-dynamic-type-bind-relation.service';
|
|
||||||
import { TokenResponseParsingService } from './auth/token-response-parsing.service';
|
import { TokenResponseParsingService } from './auth/token-response-parsing.service';
|
||||||
import { SubmissionCcLicenseDataService } from './submission/submission-cc-license-data.service';
|
import { SubmissionCcLicenseDataService } from './submission/submission-cc-license-data.service';
|
||||||
import { SubmissionCcLicence } from './submission/models/submission-cc-license.model';
|
import { SubmissionCcLicence } from './submission/models/submission-cc-license.model';
|
||||||
@@ -149,7 +141,6 @@ import { VocabularyEntry } from './submission/vocabularies/models/vocabulary-ent
|
|||||||
import { Vocabulary } from './submission/vocabularies/models/vocabulary.model';
|
import { Vocabulary } from './submission/vocabularies/models/vocabulary.model';
|
||||||
import { VocabularyEntryDetail } from './submission/vocabularies/models/vocabulary-entry-detail.model';
|
import { VocabularyEntryDetail } from './submission/vocabularies/models/vocabulary-entry-detail.model';
|
||||||
import { VocabularyService } from './submission/vocabularies/vocabulary.service';
|
import { VocabularyService } from './submission/vocabularies/vocabulary.service';
|
||||||
import { VocabularyTreeviewService } from '../shared/vocabulary-treeview/vocabulary-treeview.service';
|
|
||||||
import { ConfigurationDataService } from './data/configuration-data.service';
|
import { ConfigurationDataService } from './data/configuration-data.service';
|
||||||
import { ConfigurationProperty } from './shared/configuration-property.model';
|
import { ConfigurationProperty } from './shared/configuration-property.model';
|
||||||
import { ReloadGuard } from './reload/reload.guard';
|
import { ReloadGuard } from './reload/reload.guard';
|
||||||
@@ -210,12 +201,6 @@ const PROVIDERS = [
|
|||||||
DSOResponseParsingService,
|
DSOResponseParsingService,
|
||||||
{ provide: MOCK_RESPONSE_MAP, useValue: mockResponseMap },
|
{ provide: MOCK_RESPONSE_MAP, useValue: mockResponseMap },
|
||||||
{ provide: DspaceRestService, useFactory: restServiceFactory, deps: [MOCK_RESPONSE_MAP, HttpClient] },
|
{ provide: DspaceRestService, useFactory: restServiceFactory, deps: [MOCK_RESPONSE_MAP, HttpClient] },
|
||||||
DynamicFormLayoutService,
|
|
||||||
DynamicFormService,
|
|
||||||
DynamicFormValidationService,
|
|
||||||
FormBuilderService,
|
|
||||||
SectionFormOperationsService,
|
|
||||||
FormService,
|
|
||||||
EPersonDataService,
|
EPersonDataService,
|
||||||
LinkHeadService,
|
LinkHeadService,
|
||||||
HALEndpointService,
|
HALEndpointService,
|
||||||
@@ -244,12 +229,10 @@ const PROVIDERS = [
|
|||||||
SubmissionResponseParsingService,
|
SubmissionResponseParsingService,
|
||||||
SubmissionJsonPatchOperationsService,
|
SubmissionJsonPatchOperationsService,
|
||||||
JsonPatchOperationsBuilder,
|
JsonPatchOperationsBuilder,
|
||||||
UploaderService,
|
|
||||||
UUIDService,
|
UUIDService,
|
||||||
NotificationsService,
|
NotificationsService,
|
||||||
WorkspaceitemDataService,
|
WorkspaceitemDataService,
|
||||||
WorkflowItemDataService,
|
WorkflowItemDataService,
|
||||||
UploaderService,
|
|
||||||
DSpaceObjectDataService,
|
DSpaceObjectDataService,
|
||||||
ConfigurationDataService,
|
ConfigurationDataService,
|
||||||
DSOChangeAnalyzer,
|
DSOChangeAnalyzer,
|
||||||
@@ -266,7 +249,6 @@ const PROVIDERS = [
|
|||||||
ClaimedTaskDataService,
|
ClaimedTaskDataService,
|
||||||
PoolTaskDataService,
|
PoolTaskDataService,
|
||||||
BitstreamDataService,
|
BitstreamDataService,
|
||||||
DsDynamicTypeBindRelationService,
|
|
||||||
EntityTypeDataService,
|
EntityTypeDataService,
|
||||||
ContentSourceResponseParsingService,
|
ContentSourceResponseParsingService,
|
||||||
ItemTemplateDataService,
|
ItemTemplateDataService,
|
||||||
@@ -302,7 +284,6 @@ const PROVIDERS = [
|
|||||||
VocabularyService,
|
VocabularyService,
|
||||||
VocabularyDataService,
|
VocabularyDataService,
|
||||||
VocabularyEntryDetailsDataService,
|
VocabularyEntryDetailsDataService,
|
||||||
VocabularyTreeviewService,
|
|
||||||
SequenceService,
|
SequenceService,
|
||||||
GroupDataService,
|
GroupDataService,
|
||||||
FeedbackDataService,
|
FeedbackDataService,
|
||||||
|
@@ -1,7 +1,17 @@
|
|||||||
|
/**
|
||||||
|
* The contents of this file are subject to the license and copyright
|
||||||
|
* detailed in the LICENSE and NOTICE files at the root of the source
|
||||||
|
* tree and available online at
|
||||||
|
*
|
||||||
|
* http://www.dspace.org/license/
|
||||||
|
*/
|
||||||
|
|
||||||
import { Injectable } from '@angular/core';
|
import { Injectable } from '@angular/core';
|
||||||
|
|
||||||
@Injectable()
|
@Injectable({
|
||||||
export class UploaderService {
|
providedIn: 'root'
|
||||||
|
})
|
||||||
|
export class DragService {
|
||||||
private _overrideDragOverPage = false;
|
private _overrideDragOverPage = false;
|
||||||
|
|
||||||
public overrideDragOverPage() {
|
public overrideDragOverPage() {
|
@@ -40,7 +40,7 @@ export class LocaleService {
|
|||||||
protected translate: TranslateService,
|
protected translate: TranslateService,
|
||||||
protected authService: AuthService,
|
protected authService: AuthService,
|
||||||
protected routeService: RouteService,
|
protected routeService: RouteService,
|
||||||
@Inject(DOCUMENT) private document: any
|
@Inject(DOCUMENT) protected document: any
|
||||||
) {
|
) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -1,12 +1,31 @@
|
|||||||
import { LANG_ORIGIN, LocaleService } from './locale.service';
|
import { LANG_ORIGIN, LocaleService } from './locale.service';
|
||||||
import { Injectable } from '@angular/core';
|
import { Inject, Injectable } from '@angular/core';
|
||||||
import { combineLatest, Observable, of as observableOf } from 'rxjs';
|
import { combineLatest, Observable, of as observableOf } from 'rxjs';
|
||||||
import { map, mergeMap, take } from 'rxjs/operators';
|
import { map, mergeMap, take } from 'rxjs/operators';
|
||||||
import { isEmpty, isNotEmpty } from '../../shared/empty.util';
|
import { hasValue, isEmpty, isNotEmpty } from '../../shared/empty.util';
|
||||||
|
import { NativeWindowRef, NativeWindowService } from '../services/window.service';
|
||||||
|
import { REQUEST } from '@nguniversal/express-engine/tokens';
|
||||||
|
import { CookieService } from '../services/cookie.service';
|
||||||
|
import { TranslateService } from '@ngx-translate/core';
|
||||||
|
import { AuthService } from '../auth/auth.service';
|
||||||
|
import { RouteService } from '../services/route.service';
|
||||||
|
import { DOCUMENT } from '@angular/common';
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class ServerLocaleService extends LocaleService {
|
export class ServerLocaleService extends LocaleService {
|
||||||
|
|
||||||
|
constructor(
|
||||||
|
@Inject(NativeWindowService) protected _window: NativeWindowRef,
|
||||||
|
@Inject(REQUEST) protected req: Request,
|
||||||
|
protected cookie: CookieService,
|
||||||
|
protected translate: TranslateService,
|
||||||
|
protected authService: AuthService,
|
||||||
|
protected routeService: RouteService,
|
||||||
|
@Inject(DOCUMENT) protected document: any
|
||||||
|
) {
|
||||||
|
super(_window, cookie, translate, authService, routeService, document);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the languages list of the user in Accept-Language format
|
* Get the languages list of the user in Accept-Language format
|
||||||
*
|
*
|
||||||
@@ -50,6 +69,10 @@ export class ServerLocaleService extends LocaleService {
|
|||||||
if (isNotEmpty(epersonLang)) {
|
if (isNotEmpty(epersonLang)) {
|
||||||
languages.push(...epersonLang);
|
languages.push(...epersonLang);
|
||||||
}
|
}
|
||||||
|
if (hasValue(this.req.headers['accept-language'])) {
|
||||||
|
languages.push(...this.req.headers['accept-language'].split(',')
|
||||||
|
);
|
||||||
|
}
|
||||||
return languages;
|
return languages;
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
|
@@ -4,7 +4,7 @@ import { RemoteData } from '../../../core/data/remote-data';
|
|||||||
import { Item } from '../../../core/shared/item.model';
|
import { Item } from '../../../core/shared/item.model';
|
||||||
import { map, take, switchMap } from 'rxjs/operators';
|
import { map, take, switchMap } from 'rxjs/operators';
|
||||||
import { ActivatedRoute, Router } from '@angular/router';
|
import { ActivatedRoute, Router } from '@angular/router';
|
||||||
import { UploaderOptions } from '../../../shared/uploader/uploader-options.model';
|
import { UploaderOptions } from '../../../shared/upload/uploader/uploader-options.model';
|
||||||
import { hasValue, isEmpty, isNotEmpty } from '../../../shared/empty.util';
|
import { hasValue, isEmpty, isNotEmpty } from '../../../shared/empty.util';
|
||||||
import { ItemDataService } from '../../../core/data/item-data.service';
|
import { ItemDataService } from '../../../core/data/item-data.service';
|
||||||
import { AuthService } from '../../../core/auth/auth.service';
|
import { AuthService } from '../../../core/auth/auth.service';
|
||||||
@@ -14,7 +14,7 @@ import { PaginatedList } from '../../../core/data/paginated-list.model';
|
|||||||
import { Bundle } from '../../../core/shared/bundle.model';
|
import { Bundle } from '../../../core/shared/bundle.model';
|
||||||
import { BundleDataService } from '../../../core/data/bundle-data.service';
|
import { BundleDataService } from '../../../core/data/bundle-data.service';
|
||||||
import { getFirstSucceededRemoteDataPayload, getFirstCompletedRemoteData } from '../../../core/shared/operators';
|
import { getFirstSucceededRemoteDataPayload, getFirstCompletedRemoteData } from '../../../core/shared/operators';
|
||||||
import { UploaderComponent } from '../../../shared/uploader/uploader.component';
|
import { UploaderComponent } from '../../../shared/upload/uploader/uploader.component';
|
||||||
import { RequestService } from '../../../core/data/request.service';
|
import { RequestService } from '../../../core/data/request.service';
|
||||||
import { getBitstreamModuleRoute } from '../../../app-routing-paths';
|
import { getBitstreamModuleRoute } from '../../../app-routing-paths';
|
||||||
import { getEntityEditRoute } from '../../item-page-routing-paths';
|
import { getEntityEditRoute } from '../../item-page-routing-paths';
|
||||||
|
@@ -18,6 +18,8 @@ import { NotificationsService } from '../../../../shared/notifications/notificat
|
|||||||
import { NotificationsServiceStub } from '../../../../shared/testing/notifications-service.stub';
|
import { NotificationsServiceStub } from '../../../../shared/testing/notifications-service.stub';
|
||||||
import { PaginationService } from '../../../../core/pagination/pagination.service';
|
import { PaginationService } from '../../../../core/pagination/pagination.service';
|
||||||
import { PaginationServiceStub } from '../../../../shared/testing/pagination-service.stub';
|
import { PaginationServiceStub } from '../../../../shared/testing/pagination-service.stub';
|
||||||
|
import { APP_CONFIG } from 'src/config/app-config.interface';
|
||||||
|
import { environment } from 'src/environments/environment';
|
||||||
|
|
||||||
describe('FullFileSectionComponent', () => {
|
describe('FullFileSectionComponent', () => {
|
||||||
let comp: FullFileSectionComponent;
|
let comp: FullFileSectionComponent;
|
||||||
@@ -69,7 +71,8 @@ describe('FullFileSectionComponent', () => {
|
|||||||
providers: [
|
providers: [
|
||||||
{ provide: BitstreamDataService, useValue: bitstreamDataService },
|
{ provide: BitstreamDataService, useValue: bitstreamDataService },
|
||||||
{ provide: NotificationsService, useValue: new NotificationsServiceStub() },
|
{ provide: NotificationsService, useValue: new NotificationsServiceStub() },
|
||||||
{ provide: PaginationService, useValue: paginationService }
|
{ provide: PaginationService, useValue: paginationService },
|
||||||
|
{ provide: APP_CONFIG, useValue: environment },
|
||||||
],
|
],
|
||||||
|
|
||||||
schemas: [NO_ERRORS_SCHEMA]
|
schemas: [NO_ERRORS_SCHEMA]
|
||||||
|
@@ -1,4 +1,4 @@
|
|||||||
import { Component, Input, OnInit } from '@angular/core';
|
import { Component, Inject, Input, OnInit } from '@angular/core';
|
||||||
import { Observable } from 'rxjs';
|
import { Observable } from 'rxjs';
|
||||||
import { BitstreamDataService } from '../../../../core/data/bitstream-data.service';
|
import { BitstreamDataService } from '../../../../core/data/bitstream-data.service';
|
||||||
|
|
||||||
@@ -14,6 +14,7 @@ import { NotificationsService } from '../../../../shared/notifications/notificat
|
|||||||
import { TranslateService } from '@ngx-translate/core';
|
import { TranslateService } from '@ngx-translate/core';
|
||||||
import { hasValue, isEmpty } from '../../../../shared/empty.util';
|
import { hasValue, isEmpty } from '../../../../shared/empty.util';
|
||||||
import { PaginationService } from '../../../../core/pagination/pagination.service';
|
import { PaginationService } from '../../../../core/pagination/pagination.service';
|
||||||
|
import { AppConfig, APP_CONFIG } from 'src/config/app-config.interface';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This component renders the file section of the item
|
* This component renders the file section of the item
|
||||||
@@ -34,26 +35,26 @@ export class FullFileSectionComponent extends FileSectionComponent implements On
|
|||||||
originals$: Observable<RemoteData<PaginatedList<Bitstream>>>;
|
originals$: Observable<RemoteData<PaginatedList<Bitstream>>>;
|
||||||
licenses$: Observable<RemoteData<PaginatedList<Bitstream>>>;
|
licenses$: Observable<RemoteData<PaginatedList<Bitstream>>>;
|
||||||
|
|
||||||
pageSize = 5;
|
|
||||||
originalOptions = Object.assign(new PaginationComponentOptions(), {
|
originalOptions = Object.assign(new PaginationComponentOptions(), {
|
||||||
id: 'obo',
|
id: 'obo',
|
||||||
currentPage: 1,
|
currentPage: 1,
|
||||||
pageSize: this.pageSize
|
pageSize: this.appConfig.item.bitstream.pageSize
|
||||||
});
|
});
|
||||||
|
|
||||||
licenseOptions = Object.assign(new PaginationComponentOptions(), {
|
licenseOptions = Object.assign(new PaginationComponentOptions(), {
|
||||||
id: 'lbo',
|
id: 'lbo',
|
||||||
currentPage: 1,
|
currentPage: 1,
|
||||||
pageSize: this.pageSize
|
pageSize: this.appConfig.item.bitstream.pageSize
|
||||||
});
|
});
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
bitstreamDataService: BitstreamDataService,
|
bitstreamDataService: BitstreamDataService,
|
||||||
protected notificationsService: NotificationsService,
|
protected notificationsService: NotificationsService,
|
||||||
protected translateService: TranslateService,
|
protected translateService: TranslateService,
|
||||||
protected paginationService: PaginationService
|
protected paginationService: PaginationService,
|
||||||
|
@Inject(APP_CONFIG) protected appConfig: AppConfig
|
||||||
) {
|
) {
|
||||||
super(bitstreamDataService, notificationsService, translateService);
|
super(bitstreamDataService, notificationsService, translateService, appConfig);
|
||||||
}
|
}
|
||||||
|
|
||||||
ngOnInit(): void {
|
ngOnInit(): void {
|
||||||
|
@@ -67,6 +67,7 @@ import { OrcidPageGuard } from './orcid-page/orcid-page.guard';
|
|||||||
id: 'statistics_item_:id',
|
id: 'statistics_item_:id',
|
||||||
active: true,
|
active: true,
|
||||||
visible: true,
|
visible: true,
|
||||||
|
index: 2,
|
||||||
model: {
|
model: {
|
||||||
type: MenuItemType.LINK,
|
type: MenuItemType.LINK,
|
||||||
text: 'menu.section.statistics',
|
text: 'menu.section.statistics',
|
||||||
|
@@ -46,6 +46,7 @@ import { OrcidPageComponent } from './orcid-page/orcid-page.component';
|
|||||||
import { NgbAccordionModule } from '@ng-bootstrap/ng-bootstrap';
|
import { NgbAccordionModule } from '@ng-bootstrap/ng-bootstrap';
|
||||||
import { OrcidSyncSettingsComponent } from './orcid-page/orcid-sync-settings/orcid-sync-settings.component';
|
import { OrcidSyncSettingsComponent } from './orcid-page/orcid-sync-settings/orcid-sync-settings.component';
|
||||||
import { OrcidQueueComponent } from './orcid-page/orcid-queue/orcid-queue.component';
|
import { OrcidQueueComponent } from './orcid-page/orcid-queue/orcid-queue.component';
|
||||||
|
import { UploadModule } from '../shared/upload/upload.module';
|
||||||
|
|
||||||
|
|
||||||
const ENTRY_COMPONENTS = [
|
const ENTRY_COMPONENTS = [
|
||||||
@@ -94,7 +95,8 @@ const DECLARATIONS = [
|
|||||||
JournalEntitiesModule.withEntryComponents(),
|
JournalEntitiesModule.withEntryComponents(),
|
||||||
ResearchEntitiesModule.withEntryComponents(),
|
ResearchEntitiesModule.withEntryComponents(),
|
||||||
NgxGalleryModule,
|
NgxGalleryModule,
|
||||||
NgbAccordionModule
|
NgbAccordionModule,
|
||||||
|
UploadModule,
|
||||||
],
|
],
|
||||||
declarations: [
|
declarations: [
|
||||||
...DECLARATIONS,
|
...DECLARATIONS,
|
||||||
|
@@ -17,6 +17,8 @@ import { MetadataFieldWrapperComponent } from '../../../field-components/metadat
|
|||||||
import { createPaginatedList } from '../../../../shared/testing/utils.test';
|
import { createPaginatedList } from '../../../../shared/testing/utils.test';
|
||||||
import { NotificationsService } from '../../../../shared/notifications/notifications.service';
|
import { NotificationsService } from '../../../../shared/notifications/notifications.service';
|
||||||
import { NotificationsServiceStub } from '../../../../shared/testing/notifications-service.stub';
|
import { NotificationsServiceStub } from '../../../../shared/testing/notifications-service.stub';
|
||||||
|
import { APP_CONFIG } from 'src/config/app-config.interface';
|
||||||
|
import { environment } from 'src/environments/environment';
|
||||||
|
|
||||||
describe('FileSectionComponent', () => {
|
describe('FileSectionComponent', () => {
|
||||||
let comp: FileSectionComponent;
|
let comp: FileSectionComponent;
|
||||||
@@ -65,7 +67,8 @@ describe('FileSectionComponent', () => {
|
|||||||
declarations: [FileSectionComponent, VarDirective, FileSizePipe, MetadataFieldWrapperComponent],
|
declarations: [FileSectionComponent, VarDirective, FileSizePipe, MetadataFieldWrapperComponent],
|
||||||
providers: [
|
providers: [
|
||||||
{ provide: BitstreamDataService, useValue: bitstreamDataService },
|
{ provide: BitstreamDataService, useValue: bitstreamDataService },
|
||||||
{ provide: NotificationsService, useValue: new NotificationsServiceStub() }
|
{ provide: NotificationsService, useValue: new NotificationsServiceStub() },
|
||||||
|
{ provide: APP_CONFIG, useValue: environment }
|
||||||
],
|
],
|
||||||
|
|
||||||
schemas: [NO_ERRORS_SCHEMA]
|
schemas: [NO_ERRORS_SCHEMA]
|
||||||
|
@@ -1,4 +1,4 @@
|
|||||||
import { Component, Input, OnInit } from '@angular/core';
|
import { Component, Inject, Input, OnInit } from '@angular/core';
|
||||||
import { BehaviorSubject } from 'rxjs';
|
import { BehaviorSubject } from 'rxjs';
|
||||||
import { BitstreamDataService } from '../../../../core/data/bitstream-data.service';
|
import { BitstreamDataService } from '../../../../core/data/bitstream-data.service';
|
||||||
|
|
||||||
@@ -10,6 +10,7 @@ import { PaginatedList } from '../../../../core/data/paginated-list.model';
|
|||||||
import { NotificationsService } from '../../../../shared/notifications/notifications.service';
|
import { NotificationsService } from '../../../../shared/notifications/notifications.service';
|
||||||
import { TranslateService } from '@ngx-translate/core';
|
import { TranslateService } from '@ngx-translate/core';
|
||||||
import { getFirstCompletedRemoteData } from '../../../../core/shared/operators';
|
import { getFirstCompletedRemoteData } from '../../../../core/shared/operators';
|
||||||
|
import { AppConfig, APP_CONFIG } from 'src/config/app-config.interface';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This component renders the file section of the item
|
* This component renders the file section of the item
|
||||||
@@ -35,13 +36,15 @@ export class FileSectionComponent implements OnInit {
|
|||||||
|
|
||||||
isLastPage: boolean;
|
isLastPage: boolean;
|
||||||
|
|
||||||
pageSize = 5;
|
pageSize: number;
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
protected bitstreamDataService: BitstreamDataService,
|
protected bitstreamDataService: BitstreamDataService,
|
||||||
protected notificationsService: NotificationsService,
|
protected notificationsService: NotificationsService,
|
||||||
protected translateService: TranslateService
|
protected translateService: TranslateService,
|
||||||
|
@Inject(APP_CONFIG) protected appConfig: AppConfig
|
||||||
) {
|
) {
|
||||||
|
this.pageSize = this.appConfig.item.bitstream.pageSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
ngOnInit(): void {
|
ngOnInit(): void {
|
||||||
|
@@ -5,7 +5,7 @@
|
|||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
<div class="modal-body">
|
<div class="modal-body">
|
||||||
<ds-collection-dropdown (selectionChange)="selectObject($event)">
|
<ds-themed-collection-dropdown (selectionChange)="selectObject($event)">
|
||||||
</ds-collection-dropdown>
|
</ds-themed-collection-dropdown>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@@ -128,10 +128,13 @@ describe('CollectionSelectorComponent', () => {
|
|||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
scheduler = getTestScheduler();
|
scheduler = getTestScheduler();
|
||||||
fixture = TestBed.createComponent(CollectionSelectorComponent);
|
fixture = TestBed.overrideComponent(CollectionSelectorComponent, {
|
||||||
|
set: {
|
||||||
|
template: '<ds-collection-dropdown (selectionChange)="selectObject($event)"></ds-collection-dropdown>'
|
||||||
|
}
|
||||||
|
}).createComponent(CollectionSelectorComponent);
|
||||||
component = fixture.componentInstance;
|
component = fixture.componentInstance;
|
||||||
fixture.detectChanges();
|
fixture.detectChanges();
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should create', () => {
|
it('should create', () => {
|
||||||
|
@@ -16,10 +16,10 @@ import { TranslateLoaderMock } from '../../shared/mocks/translate-loader.mock';
|
|||||||
import { NotificationsService } from '../../shared/notifications/notifications.service';
|
import { NotificationsService } from '../../shared/notifications/notifications.service';
|
||||||
import { NotificationsServiceStub } from '../../shared/testing/notifications-service.stub';
|
import { NotificationsServiceStub } from '../../shared/testing/notifications-service.stub';
|
||||||
import { getMockScrollToService } from '../../shared/mocks/scroll-to-service.mock';
|
import { getMockScrollToService } from '../../shared/mocks/scroll-to-service.mock';
|
||||||
import { UploaderService } from '../../shared/uploader/uploader.service';
|
import { DragService } from '../../core/drag.service';
|
||||||
import { HostWindowService } from '../../shared/host-window.service';
|
import { HostWindowService } from '../../shared/host-window.service';
|
||||||
import { HostWindowServiceStub } from '../../shared/testing/host-window-service.stub';
|
import { HostWindowServiceStub } from '../../shared/testing/host-window-service.stub';
|
||||||
import { UploaderComponent } from '../../shared/uploader/uploader.component';
|
import { UploaderComponent } from '../../shared/upload/uploader/uploader.component';
|
||||||
import { HttpXsrfTokenExtractor } from '@angular/common/http';
|
import { HttpXsrfTokenExtractor } from '@angular/common/http';
|
||||||
import { CookieService } from '../../core/services/cookie.service';
|
import { CookieService } from '../../core/services/cookie.service';
|
||||||
import { CookieServiceMock } from '../../shared/mocks/cookie.service.mock';
|
import { CookieServiceMock } from '../../shared/mocks/cookie.service.mock';
|
||||||
@@ -59,7 +59,7 @@ describe('MyDSpaceNewSubmissionComponent test', () => {
|
|||||||
NgbModal,
|
NgbModal,
|
||||||
ChangeDetectorRef,
|
ChangeDetectorRef,
|
||||||
MyDSpaceNewSubmissionComponent,
|
MyDSpaceNewSubmissionComponent,
|
||||||
UploaderService,
|
DragService,
|
||||||
{ provide: HttpXsrfTokenExtractor, useValue: new HttpXsrfTokenExtractorMock('mock-token') },
|
{ provide: HttpXsrfTokenExtractor, useValue: new HttpXsrfTokenExtractorMock('mock-token') },
|
||||||
{ provide: CookieService, useValue: new CookieServiceMock() },
|
{ provide: CookieService, useValue: new CookieServiceMock() },
|
||||||
{ provide: HostWindowService, useValue: new HostWindowServiceStub(800) },
|
{ provide: HostWindowService, useValue: new HostWindowServiceStub(800) },
|
||||||
|
@@ -8,13 +8,13 @@ import { NgbModal } from '@ng-bootstrap/ng-bootstrap';
|
|||||||
import { AuthService } from '../../core/auth/auth.service';
|
import { AuthService } from '../../core/auth/auth.service';
|
||||||
import { DSpaceObject } from '../../core/shared/dspace-object.model';
|
import { DSpaceObject } from '../../core/shared/dspace-object.model';
|
||||||
import { NotificationsService } from '../../shared/notifications/notifications.service';
|
import { NotificationsService } from '../../shared/notifications/notifications.service';
|
||||||
import { UploaderOptions } from '../../shared/uploader/uploader-options.model';
|
import { UploaderOptions } from '../../shared/upload/uploader/uploader-options.model';
|
||||||
import { HALEndpointService } from '../../core/shared/hal-endpoint.service';
|
import { HALEndpointService } from '../../core/shared/hal-endpoint.service';
|
||||||
import { hasValue } from '../../shared/empty.util';
|
import { hasValue } from '../../shared/empty.util';
|
||||||
import { SearchResult } from '../../shared/search/models/search-result.model';
|
import { SearchResult } from '../../shared/search/models/search-result.model';
|
||||||
import { CollectionSelectorComponent } from '../collection-selector/collection-selector.component';
|
import { CollectionSelectorComponent } from '../collection-selector/collection-selector.component';
|
||||||
import { UploaderComponent } from '../../shared/uploader/uploader.component';
|
import { UploaderComponent } from '../../shared/upload/uploader/uploader.component';
|
||||||
import { UploaderError } from '../../shared/uploader/uploader-error.model';
|
import { UploaderError } from '../../shared/upload/uploader/uploader-error.model';
|
||||||
import { Router } from '@angular/router';
|
import { Router } from '@angular/router';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@@ -14,6 +14,7 @@ import { MyDSpaceNewSubmissionDropdownComponent } from './my-dspace-new-submissi
|
|||||||
import { MyDSpaceNewExternalDropdownComponent } from './my-dspace-new-submission/my-dspace-new-external-dropdown/my-dspace-new-external-dropdown.component';
|
import { MyDSpaceNewExternalDropdownComponent } from './my-dspace-new-submission/my-dspace-new-external-dropdown/my-dspace-new-external-dropdown.component';
|
||||||
import { ThemedMyDSpacePageComponent } from './themed-my-dspace-page.component';
|
import { ThemedMyDSpacePageComponent } from './themed-my-dspace-page.component';
|
||||||
import { SearchModule } from '../shared/search/search.module';
|
import { SearchModule } from '../shared/search/search.module';
|
||||||
|
import { UploadModule } from '../shared/upload/upload.module';
|
||||||
|
|
||||||
const DECLARATIONS = [
|
const DECLARATIONS = [
|
||||||
MyDSpacePageComponent,
|
MyDSpacePageComponent,
|
||||||
@@ -30,7 +31,8 @@ const DECLARATIONS = [
|
|||||||
SharedModule,
|
SharedModule,
|
||||||
SearchModule,
|
SearchModule,
|
||||||
MyDspacePageRoutingModule,
|
MyDspacePageRoutingModule,
|
||||||
MyDspaceSearchModule.withEntryComponents()
|
MyDspaceSearchModule.withEntryComponents(),
|
||||||
|
UploadModule,
|
||||||
],
|
],
|
||||||
declarations: DECLARATIONS,
|
declarations: DECLARATIONS,
|
||||||
providers: [
|
providers: [
|
||||||
|
@@ -95,6 +95,10 @@ describe('RegisterEmailComponent', () => {
|
|||||||
comp.form.patchValue({email: 'valid@email.org'});
|
comp.form.patchValue({email: 'valid@email.org'});
|
||||||
expect(comp.form.invalid).toBeFalse();
|
expect(comp.form.invalid).toBeFalse();
|
||||||
});
|
});
|
||||||
|
it('should be valid when uppercase letters are used', () => {
|
||||||
|
comp.form.patchValue({email: 'VALID@email.org'});
|
||||||
|
expect(comp.form.invalid).toBeFalse();
|
||||||
|
});
|
||||||
});
|
});
|
||||||
describe('register', () => {
|
describe('register', () => {
|
||||||
it('should send a registration to the service and on success display a message and return to home', () => {
|
it('should send a registration to the service and on success display a message and return to home', () => {
|
||||||
|
@@ -79,7 +79,9 @@ export class RegisterEmailFormComponent implements OnInit {
|
|||||||
this.form = this.formBuilder.group({
|
this.form = this.formBuilder.group({
|
||||||
email: new FormControl('', {
|
email: new FormControl('', {
|
||||||
validators: [Validators.required,
|
validators: [Validators.required,
|
||||||
Validators.pattern('^[a-z0-9._%+-]+@[a-z0-9.-]+\.[a-z]{2,4}$')
|
// Regex pattern borrowed from HTML5 specs for a valid email address:
|
||||||
|
// https://html.spec.whatwg.org/multipage/input.html#valid-e-mail-address
|
||||||
|
Validators.pattern('^[a-zA-Z0-9.!#$%&\'*+\/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$')
|
||||||
],
|
],
|
||||||
})
|
})
|
||||||
});
|
});
|
||||||
|
@@ -0,0 +1,33 @@
|
|||||||
|
import { CollectionDropdownComponent, CollectionListEntry } from './collection-dropdown.component';
|
||||||
|
import { ThemedComponent } from '../theme-support/themed.component';
|
||||||
|
import { Component, Input, Output, EventEmitter } from '@angular/core';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'ds-themed-collection-dropdown',
|
||||||
|
styleUrls: [],
|
||||||
|
templateUrl: '../../shared/theme-support/themed.component.html',
|
||||||
|
})
|
||||||
|
export class ThemedCollectionDropdownComponent extends ThemedComponent<CollectionDropdownComponent> {
|
||||||
|
|
||||||
|
@Input() entityType: string;
|
||||||
|
|
||||||
|
@Output() searchComplete = new EventEmitter<any>();
|
||||||
|
|
||||||
|
@Output() theOnlySelectable = new EventEmitter<CollectionListEntry>();
|
||||||
|
|
||||||
|
@Output() selectionChange = new EventEmitter<CollectionListEntry>();
|
||||||
|
|
||||||
|
protected inAndOutputNames: (keyof CollectionDropdownComponent & keyof this)[] = ['entityType', 'searchComplete', 'theOnlySelectable', 'selectionChange'];
|
||||||
|
|
||||||
|
protected getComponentName(): string {
|
||||||
|
return 'CollectionDropdownComponent';
|
||||||
|
}
|
||||||
|
|
||||||
|
protected importThemedComponent(themeName: string): Promise<any> {
|
||||||
|
return import(`../../../themes/${themeName}/app/shared/collection-dropdown/collection-dropdown.component`);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected importUnthemedComponent(): Promise<any> {
|
||||||
|
return import(`./collection-dropdown.component`);
|
||||||
|
}
|
||||||
|
}
|
@@ -17,8 +17,8 @@ import { MetadataMap, MetadataValue } from '../../../../core/shared/metadata.mod
|
|||||||
import { ResourceType } from '../../../../core/shared/resource-type';
|
import { ResourceType } from '../../../../core/shared/resource-type';
|
||||||
import { hasValue, isNotEmpty } from '../../../empty.util';
|
import { hasValue, isNotEmpty } from '../../../empty.util';
|
||||||
import { NotificationsService } from '../../../notifications/notifications.service';
|
import { NotificationsService } from '../../../notifications/notifications.service';
|
||||||
import { UploaderOptions } from '../../../uploader/uploader-options.model';
|
import { UploaderOptions } from '../../../upload/uploader/uploader-options.model';
|
||||||
import { UploaderComponent } from '../../../uploader/uploader.component';
|
import { UploaderComponent } from '../../../upload/uploader/uploader.component';
|
||||||
import { Operation } from 'fast-json-patch';
|
import { Operation } from 'fast-json-patch';
|
||||||
import { NoContent } from '../../../../core/shared/NoContent.model';
|
import { NoContent } from '../../../../core/shared/NoContent.model';
|
||||||
import { getFirstCompletedRemoteData } from '../../../../core/shared/operators';
|
import { getFirstCompletedRemoteData } from '../../../../core/shared/operators';
|
||||||
|
@@ -15,6 +15,7 @@ import { ThemedComcolPageBrowseByComponent } from './comcol-page-browse-by/theme
|
|||||||
import { ComcolRoleComponent } from './comcol-forms/edit-comcol-page/comcol-role/comcol-role.component';
|
import { ComcolRoleComponent } from './comcol-forms/edit-comcol-page/comcol-role/comcol-role.component';
|
||||||
import { SharedModule } from '../shared.module';
|
import { SharedModule } from '../shared.module';
|
||||||
import { FormModule } from '../form/form.module';
|
import { FormModule } from '../form/form.module';
|
||||||
|
import { UploadModule } from '../upload/upload.module';
|
||||||
|
|
||||||
const COMPONENTS = [
|
const COMPONENTS = [
|
||||||
ComcolPageContentComponent,
|
ComcolPageContentComponent,
|
||||||
@@ -28,9 +29,7 @@ const COMPONENTS = [
|
|||||||
ComcolPageBrowseByComponent,
|
ComcolPageBrowseByComponent,
|
||||||
ThemedComcolPageBrowseByComponent,
|
ThemedComcolPageBrowseByComponent,
|
||||||
ComcolRoleComponent,
|
ComcolRoleComponent,
|
||||||
|
|
||||||
ThemedComcolPageHandleComponent
|
ThemedComcolPageHandleComponent
|
||||||
|
|
||||||
];
|
];
|
||||||
|
|
||||||
@NgModule({
|
@NgModule({
|
||||||
@@ -40,10 +39,12 @@ const COMPONENTS = [
|
|||||||
imports: [
|
imports: [
|
||||||
CommonModule,
|
CommonModule,
|
||||||
FormModule,
|
FormModule,
|
||||||
SharedModule
|
SharedModule,
|
||||||
|
UploadModule,
|
||||||
],
|
],
|
||||||
exports: [
|
exports: [
|
||||||
...COMPONENTS
|
...COMPONENTS,
|
||||||
|
UploadModule,
|
||||||
]
|
]
|
||||||
})
|
})
|
||||||
export class ComcolModule { }
|
export class ComcolModule { }
|
||||||
|
@@ -1,5 +1,4 @@
|
|||||||
import { Injectable } from '@angular/core';
|
import { Inject, Injectable, InjectionToken } from '@angular/core';
|
||||||
import { setup, show } from 'klaro/dist/klaro-no-translations';
|
|
||||||
import { combineLatest as observableCombineLatest, Observable, of as observableOf } from 'rxjs';
|
import { combineLatest as observableCombineLatest, Observable, of as observableOf } from 'rxjs';
|
||||||
import { AuthService } from '../../core/auth/auth.service';
|
import { AuthService } from '../../core/auth/auth.service';
|
||||||
import { TranslateService } from '@ngx-translate/core';
|
import { TranslateService } from '@ngx-translate/core';
|
||||||
@@ -43,6 +42,17 @@ const cookiePurposeMessagePrefix = 'cookies.consent.purpose.';
|
|||||||
*/
|
*/
|
||||||
const updateDebounce = 300;
|
const updateDebounce = 300;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* By using this injection token instead of importing directly we can keep Klaro out of the main bundle
|
||||||
|
*/
|
||||||
|
const LAZY_KLARO = new InjectionToken<Promise<any>>(
|
||||||
|
'Lazily loaded Klaro',
|
||||||
|
{
|
||||||
|
providedIn: 'root',
|
||||||
|
factory: async () => (await import('klaro')),
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Browser implementation for the KlaroService, representing a service for handling Klaro consent preferences and UI
|
* Browser implementation for the KlaroService, representing a service for handling Klaro consent preferences and UI
|
||||||
*/
|
*/
|
||||||
@@ -65,7 +75,9 @@ export class BrowserKlaroService extends KlaroService {
|
|||||||
private authService: AuthService,
|
private authService: AuthService,
|
||||||
private ePersonService: EPersonDataService,
|
private ePersonService: EPersonDataService,
|
||||||
private configService: ConfigurationDataService,
|
private configService: ConfigurationDataService,
|
||||||
private cookieService: CookieService) {
|
private cookieService: CookieService,
|
||||||
|
@Inject(LAZY_KLARO) private lazyKlaro: Promise<any>,
|
||||||
|
) {
|
||||||
super();
|
super();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -135,8 +147,7 @@ export class BrowserKlaroService extends KlaroService {
|
|||||||
this.translateConfiguration();
|
this.translateConfiguration();
|
||||||
|
|
||||||
this.klaroConfig.services = this.filterConfigServices(servicesToHide);
|
this.klaroConfig.services = this.filterConfigServices(servicesToHide);
|
||||||
|
this.lazyKlaro.then(({ setup }) => setup(this.klaroConfig));
|
||||||
setup(this.klaroConfig);
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -220,7 +231,7 @@ export class BrowserKlaroService extends KlaroService {
|
|||||||
* Show the cookie consent form
|
* Show the cookie consent form
|
||||||
*/
|
*/
|
||||||
showSettings() {
|
showSettings() {
|
||||||
show(this.klaroConfig);
|
this.lazyKlaro.then(({show}) => show(this.klaroConfig));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@@ -9,7 +9,7 @@
|
|||||||
<h3 class="position-relative py-1 my-3 font-weight-normal">
|
<h3 class="position-relative py-1 my-3 font-weight-normal">
|
||||||
<hr>
|
<hr>
|
||||||
<div id="create-community-or-separator" class="text-center position-absolute w-100">
|
<div id="create-community-or-separator" class="text-center position-absolute w-100">
|
||||||
<span class="px-4 bg-white">or</span>
|
<span class="px-4 bg-white">{{'dso-selector.create.community.or-divider' | translate}}</span>
|
||||||
</div>
|
</div>
|
||||||
</h3>
|
</h3>
|
||||||
|
|
||||||
|
@@ -20,7 +20,7 @@ import { FormFieldMetadataValueObject } from '../../../models/form-field-metadat
|
|||||||
import { VocabularyEntry } from '../../../../../../core/submission/vocabularies/models/vocabulary-entry.model';
|
import { VocabularyEntry } from '../../../../../../core/submission/vocabularies/models/vocabulary-entry.model';
|
||||||
import { createTestComponent } from '../../../../../testing/utils.test';
|
import { createTestComponent } from '../../../../../testing/utils.test';
|
||||||
import { DynamicLookupNameModel } from './dynamic-lookup-name.model';
|
import { DynamicLookupNameModel } from './dynamic-lookup-name.model';
|
||||||
import { AuthorityConfidenceStateDirective } from '../../../../../authority-confidence/authority-confidence-state.directive';
|
import { AuthorityConfidenceStateDirective } from '../../../../directives/authority-confidence-state.directive';
|
||||||
import { ObjNgFor } from '../../../../../utils/object-ngfor.pipe';
|
import { ObjNgFor } from '../../../../../utils/object-ngfor.pipe';
|
||||||
import {
|
import {
|
||||||
mockDynamicFormLayoutService,
|
mockDynamicFormLayoutService,
|
||||||
|
@@ -21,11 +21,11 @@ import { DsDynamicOneboxComponent } from './dynamic-onebox.component';
|
|||||||
import { DynamicOneboxModel } from './dynamic-onebox.model';
|
import { DynamicOneboxModel } from './dynamic-onebox.model';
|
||||||
import { FormFieldMetadataValueObject } from '../../../models/form-field-metadata-value.model';
|
import { FormFieldMetadataValueObject } from '../../../models/form-field-metadata-value.model';
|
||||||
import { createTestComponent } from '../../../../../testing/utils.test';
|
import { createTestComponent } from '../../../../../testing/utils.test';
|
||||||
import { AuthorityConfidenceStateDirective } from '../../../../../authority-confidence/authority-confidence-state.directive';
|
import { AuthorityConfidenceStateDirective } from '../../../../directives/authority-confidence-state.directive';
|
||||||
import { ObjNgFor } from '../../../../../utils/object-ngfor.pipe';
|
import { ObjNgFor } from '../../../../../utils/object-ngfor.pipe';
|
||||||
import { VocabularyEntry } from '../../../../../../core/submission/vocabularies/models/vocabulary-entry.model';
|
import { VocabularyEntry } from '../../../../../../core/submission/vocabularies/models/vocabulary-entry.model';
|
||||||
import { createSuccessfulRemoteDataObject$ } from '../../../../../remote-data.utils';
|
import { createSuccessfulRemoteDataObject$ } from '../../../../../remote-data.utils';
|
||||||
import { VocabularyTreeviewComponent } from '../../../../../vocabulary-treeview/vocabulary-treeview.component';
|
import { VocabularyTreeviewComponent } from '../../../../vocabulary-treeview/vocabulary-treeview.component';
|
||||||
import {
|
import {
|
||||||
mockDynamicFormLayoutService,
|
mockDynamicFormLayoutService,
|
||||||
mockDynamicFormValidationService
|
mockDynamicFormValidationService
|
||||||
|
@@ -30,7 +30,7 @@ import { VocabularyEntry } from '../../../../../../core/submission/vocabularies/
|
|||||||
import { PageInfo } from '../../../../../../core/shared/page-info.model';
|
import { PageInfo } from '../../../../../../core/shared/page-info.model';
|
||||||
import { DsDynamicVocabularyComponent } from '../dynamic-vocabulary.component';
|
import { DsDynamicVocabularyComponent } from '../dynamic-vocabulary.component';
|
||||||
import { Vocabulary } from '../../../../../../core/submission/vocabularies/models/vocabulary.model';
|
import { Vocabulary } from '../../../../../../core/submission/vocabularies/models/vocabulary.model';
|
||||||
import { VocabularyTreeviewComponent } from '../../../../../vocabulary-treeview/vocabulary-treeview.component';
|
import { VocabularyTreeviewComponent } from '../../../../vocabulary-treeview/vocabulary-treeview.component';
|
||||||
import { VocabularyEntryDetail } from '../../../../../../core/submission/vocabularies/models/vocabulary-entry-detail.model';
|
import { VocabularyEntryDetail } from '../../../../../../core/submission/vocabularies/models/vocabulary-entry-detail.model';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@@ -16,7 +16,7 @@ import { FormFieldModel } from '../../../models/form-field.model';
|
|||||||
import { FormBuilderService } from '../../../form-builder.service';
|
import { FormBuilderService } from '../../../form-builder.service';
|
||||||
import { FormService } from '../../../../form.service';
|
import { FormService } from '../../../../form.service';
|
||||||
import { FormComponent } from '../../../../form.component';
|
import { FormComponent } from '../../../../form.component';
|
||||||
import { Chips } from '../../../../../chips/models/chips.model';
|
import { Chips } from '../../../../chips/models/chips.model';
|
||||||
import { FormFieldMetadataValueObject } from '../../../models/form-field-metadata-value.model';
|
import { FormFieldMetadataValueObject } from '../../../models/form-field-metadata-value.model';
|
||||||
import { DsDynamicInputModel } from '../ds-dynamic-input.model';
|
import { DsDynamicInputModel } from '../ds-dynamic-input.model';
|
||||||
import { createTestComponent } from '../../../../../testing/utils.test';
|
import { createTestComponent } from '../../../../../testing/utils.test';
|
||||||
|
@@ -19,10 +19,10 @@ import { FormBuilderService } from '../../../form-builder.service';
|
|||||||
import { SubmissionFormsModel } from '../../../../../../core/config/models/config-submission-forms.model';
|
import { SubmissionFormsModel } from '../../../../../../core/config/models/config-submission-forms.model';
|
||||||
import { FormService } from '../../../../form.service';
|
import { FormService } from '../../../../form.service';
|
||||||
import { FormComponent } from '../../../../form.component';
|
import { FormComponent } from '../../../../form.component';
|
||||||
import { Chips } from '../../../../../chips/models/chips.model';
|
import { Chips } from '../../../../chips/models/chips.model';
|
||||||
import { hasValue, isEmpty, isNotEmpty, isNotNull } from '../../../../../empty.util';
|
import { hasValue, isEmpty, isNotEmpty, isNotNull } from '../../../../../empty.util';
|
||||||
import { shrinkInOut } from '../../../../../animations/shrink';
|
import { shrinkInOut } from '../../../../../animations/shrink';
|
||||||
import { ChipsItem } from '../../../../../chips/models/chips-item.model';
|
import { ChipsItem } from '../../../../chips/models/chips-item.model';
|
||||||
import { hasOnlyEmptyProperties } from '../../../../../object.util';
|
import { hasOnlyEmptyProperties } from '../../../../../object.util';
|
||||||
import { VocabularyService } from '../../../../../../core/submission/vocabularies/vocabulary.service';
|
import { VocabularyService } from '../../../../../../core/submission/vocabularies/vocabulary.service';
|
||||||
import { FormFieldMetadataValueObject } from '../../../models/form-field-metadata-value.model';
|
import { FormFieldMetadataValueObject } from '../../../models/form-field-metadata-value.model';
|
||||||
|
@@ -13,7 +13,7 @@ import { VocabularyService } from '../../../../../../core/submission/vocabularie
|
|||||||
import { VocabularyServiceStub } from '../../../../../testing/vocabulary-service.stub';
|
import { VocabularyServiceStub } from '../../../../../testing/vocabulary-service.stub';
|
||||||
import { DsDynamicTagComponent } from './dynamic-tag.component';
|
import { DsDynamicTagComponent } from './dynamic-tag.component';
|
||||||
import { DynamicTagModel } from './dynamic-tag.model';
|
import { DynamicTagModel } from './dynamic-tag.model';
|
||||||
import { Chips } from '../../../../../chips/models/chips.model';
|
import { Chips } from '../../../../chips/models/chips.model';
|
||||||
import { FormFieldMetadataValueObject } from '../../../models/form-field-metadata-value.model';
|
import { FormFieldMetadataValueObject } from '../../../models/form-field-metadata-value.model';
|
||||||
import { VocabularyEntry } from '../../../../../../core/submission/vocabularies/models/vocabulary-entry.model';
|
import { VocabularyEntry } from '../../../../../../core/submission/vocabularies/models/vocabulary-entry.model';
|
||||||
import { createTestComponent } from '../../../../../testing/utils.test';
|
import { createTestComponent } from '../../../../../testing/utils.test';
|
||||||
|
@@ -9,7 +9,7 @@ import isEqual from 'lodash/isEqual';
|
|||||||
|
|
||||||
import { VocabularyService } from '../../../../../../core/submission/vocabularies/vocabulary.service';
|
import { VocabularyService } from '../../../../../../core/submission/vocabularies/vocabulary.service';
|
||||||
import { DynamicTagModel } from './dynamic-tag.model';
|
import { DynamicTagModel } from './dynamic-tag.model';
|
||||||
import { Chips } from '../../../../../chips/models/chips.model';
|
import { Chips } from '../../../../chips/models/chips.model';
|
||||||
import { hasValue, isNotEmpty } from '../../../../../empty.util';
|
import { hasValue, isNotEmpty } from '../../../../../empty.util';
|
||||||
import { environment } from '../../../../../../../environments/environment';
|
import { environment } from '../../../../../../../environments/environment';
|
||||||
import { getFirstSucceededRemoteDataPayload } from '../../../../../../core/shared/operators';
|
import { getFirstSucceededRemoteDataPayload } from '../../../../../../core/shared/operators';
|
||||||
|
@@ -1,4 +1,6 @@
|
|||||||
import { DsDynamicLookupRelationExternalSourceTabComponent } from './dynamic-lookup-relation-external-source-tab.component';
|
import {
|
||||||
|
DsDynamicLookupRelationExternalSourceTabComponent
|
||||||
|
} from './dynamic-lookup-relation-external-source-tab.component';
|
||||||
import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing';
|
import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing';
|
||||||
import { VarDirective } from '../../../../../utils/var.directive';
|
import { VarDirective } from '../../../../../utils/var.directive';
|
||||||
import { TranslateModule } from '@ngx-translate/core';
|
import { TranslateModule } from '@ngx-translate/core';
|
||||||
@@ -6,7 +8,7 @@ import { RouterTestingModule } from '@angular/router/testing';
|
|||||||
import { EventEmitter, NO_ERRORS_SCHEMA } from '@angular/core';
|
import { EventEmitter, NO_ERRORS_SCHEMA } from '@angular/core';
|
||||||
import { PaginatedSearchOptions } from '../../../../../search/models/paginated-search-options.model';
|
import { PaginatedSearchOptions } from '../../../../../search/models/paginated-search-options.model';
|
||||||
import { SearchConfigurationService } from '../../../../../../core/shared/search/search-configuration.service';
|
import { SearchConfigurationService } from '../../../../../../core/shared/search/search-configuration.service';
|
||||||
import { of as observableOf } from 'rxjs';
|
import { of as observableOf, EMPTY } from 'rxjs';
|
||||||
import {
|
import {
|
||||||
createFailedRemoteDataObject$,
|
createFailedRemoteDataObject$,
|
||||||
createPendingRemoteDataObject$,
|
createPendingRemoteDataObject$,
|
||||||
@@ -22,11 +24,13 @@ import { SelectableListService } from '../../../../../object-list/selectable-lis
|
|||||||
import { Item } from '../../../../../../core/shared/item.model';
|
import { Item } from '../../../../../../core/shared/item.model';
|
||||||
import { Collection } from '../../../../../../core/shared/collection.model';
|
import { Collection } from '../../../../../../core/shared/collection.model';
|
||||||
import { RelationshipOptions } from '../../../models/relationship-options.model';
|
import { RelationshipOptions } from '../../../models/relationship-options.model';
|
||||||
import { ExternalSourceEntryImportModalComponent } from './external-source-entry-import-modal/external-source-entry-import-modal.component';
|
|
||||||
import { createPaginatedList } from '../../../../../testing/utils.test';
|
import { createPaginatedList } from '../../../../../testing/utils.test';
|
||||||
import { PaginationService } from '../../../../../../core/pagination/pagination.service';
|
import { PaginationService } from '../../../../../../core/pagination/pagination.service';
|
||||||
import { PaginationServiceStub } from '../../../../../testing/pagination-service.stub';
|
import { PaginationServiceStub } from '../../../../../testing/pagination-service.stub';
|
||||||
import { ItemType } from '../../../../../../core/shared/item-relationships/item-type.model';
|
import { ItemType } from '../../../../../../core/shared/item-relationships/item-type.model';
|
||||||
|
import {
|
||||||
|
ThemedExternalSourceEntryImportModalComponent
|
||||||
|
} from './external-source-entry-import-modal/themed-external-source-entry-import-modal.component';
|
||||||
|
|
||||||
describe('DsDynamicLookupRelationExternalSourceTabComponent', () => {
|
describe('DsDynamicLookupRelationExternalSourceTabComponent', () => {
|
||||||
let component: DsDynamicLookupRelationExternalSourceTabComponent;
|
let component: DsDynamicLookupRelationExternalSourceTabComponent;
|
||||||
@@ -187,12 +191,13 @@ describe('DsDynamicLookupRelationExternalSourceTabComponent', () => {
|
|||||||
|
|
||||||
describe('import', () => {
|
describe('import', () => {
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
spyOn(modalService, 'open').and.returnValue(Object.assign({ componentInstance: Object.assign({ importedObject: new EventEmitter<any>() }) }));
|
spyOn(modalService, 'open').and.returnValue(Object.assign({ componentInstance: Object.assign({ importedObject: new EventEmitter<any>(), compRef$: EMPTY }) }));
|
||||||
|
component.modalRef = modalService.open(ThemedExternalSourceEntryImportModalComponent, { size: 'lg', container: 'ds-dynamic-lookup-relation-modal' });
|
||||||
component.import(externalEntries[0]);
|
component.import(externalEntries[0]);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should open a new ExternalSourceEntryImportModalComponent', () => {
|
it('should open a new ExternalSourceEntryImportModalComponent', () => {
|
||||||
expect(modalService.open).toHaveBeenCalledWith(ExternalSourceEntryImportModalComponent, jasmine.any(Object));
|
expect(modalService.open).toHaveBeenCalledWith(ThemedExternalSourceEntryImportModalComponent, jasmine.any(Object));
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@@ -1,4 +1,4 @@
|
|||||||
import { Component, EventEmitter, Input, OnDestroy, OnInit, Output } from '@angular/core';
|
import { Component, EventEmitter, Input, OnDestroy, OnInit, Output, ComponentRef } from '@angular/core';
|
||||||
import { SEARCH_CONFIG_SERVICE } from '../../../../../../my-dspace-page/my-dspace-page.component';
|
import { SEARCH_CONFIG_SERVICE } from '../../../../../../my-dspace-page/my-dspace-page.component';
|
||||||
import { SearchConfigurationService } from '../../../../../../core/shared/search/search-configuration.service';
|
import { SearchConfigurationService } from '../../../../../../core/shared/search/search-configuration.service';
|
||||||
import { Router } from '@angular/router';
|
import { Router } from '@angular/router';
|
||||||
@@ -16,7 +16,8 @@ import { PaginationComponentOptions } from '../../../../../pagination/pagination
|
|||||||
import { RelationshipOptions } from '../../../models/relationship-options.model';
|
import { RelationshipOptions } from '../../../models/relationship-options.model';
|
||||||
import { NgbModal, NgbModalRef } from '@ng-bootstrap/ng-bootstrap';
|
import { NgbModal, NgbModalRef } from '@ng-bootstrap/ng-bootstrap';
|
||||||
import { ExternalSourceEntryImportModalComponent } from './external-source-entry-import-modal/external-source-entry-import-modal.component';
|
import { ExternalSourceEntryImportModalComponent } from './external-source-entry-import-modal/external-source-entry-import-modal.component';
|
||||||
import { hasValue } from '../../../../../empty.util';
|
import { ThemedExternalSourceEntryImportModalComponent } from './external-source-entry-import-modal/themed-external-source-entry-import-modal.component';
|
||||||
|
import { hasValue, hasValueOperator } from '../../../../../empty.util';
|
||||||
import { SelectableListService } from '../../../../../object-list/selectable-list/selectable-list.service';
|
import { SelectableListService } from '../../../../../object-list/selectable-list/selectable-list.service';
|
||||||
import { Item } from '../../../../../../core/shared/item.model';
|
import { Item } from '../../../../../../core/shared/item.model';
|
||||||
import { Collection } from '../../../../../../core/shared/collection.model';
|
import { Collection } from '../../../../../../core/shared/collection.model';
|
||||||
@@ -114,9 +115,9 @@ export class DsDynamicLookupRelationExternalSourceTabComponent implements OnInit
|
|||||||
modalRef: NgbModalRef;
|
modalRef: NgbModalRef;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Subscription to the modal's importedObject event-emitter
|
* Array to track all subscriptions and unsubscribe them onDestroy
|
||||||
*/
|
*/
|
||||||
importObjectSub: Subscription;
|
protected subs: Subscription[] = [];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The entity types compatible with the given external source
|
* The entity types compatible with the given external source
|
||||||
@@ -161,30 +162,40 @@ export class DsDynamicLookupRelationExternalSourceTabComponent implements OnInit
|
|||||||
* @param entry The entry to import
|
* @param entry The entry to import
|
||||||
*/
|
*/
|
||||||
import(entry) {
|
import(entry) {
|
||||||
this.modalRef = this.modalService.open(ExternalSourceEntryImportModalComponent, {
|
this.modalRef = this.modalService.open(ThemedExternalSourceEntryImportModalComponent, {
|
||||||
size: 'lg',
|
size: 'lg',
|
||||||
container: 'ds-dynamic-lookup-relation-modal'
|
container: 'ds-dynamic-lookup-relation-modal'
|
||||||
});
|
});
|
||||||
const modalComp = this.modalRef.componentInstance;
|
|
||||||
|
const modalComp$ = this.modalRef.componentInstance.compRef$.pipe(
|
||||||
|
hasValueOperator(),
|
||||||
|
map((compRef: ComponentRef<ExternalSourceEntryImportModalComponent>) => compRef.instance)
|
||||||
|
);
|
||||||
|
|
||||||
|
this.subs.push(modalComp$.subscribe((modalComp: ExternalSourceEntryImportModalComponent) => {
|
||||||
modalComp.externalSourceEntry = entry;
|
modalComp.externalSourceEntry = entry;
|
||||||
modalComp.item = this.item;
|
modalComp.item = this.item;
|
||||||
modalComp.collection = this.collection;
|
// modalComp.collection = this.collection;
|
||||||
modalComp.relationship = this.relationship;
|
modalComp.relationship = this.relationship;
|
||||||
modalComp.label = this.label;
|
modalComp.label = this.label;
|
||||||
modalComp.relatedEntityType = this.relatedEntityType;
|
modalComp.relatedEntityType = this.relatedEntityType;
|
||||||
this.importObjectSub = modalComp.importedObject.subscribe((object) => {
|
}));
|
||||||
|
|
||||||
|
this.subs.push(modalComp$.pipe(
|
||||||
|
switchMap((modalComp: ExternalSourceEntryImportModalComponent) => modalComp.importedObject)
|
||||||
|
).subscribe((object) => {
|
||||||
this.selectableListService.selectSingle(this.listId, object);
|
this.selectableListService.selectSingle(this.listId, object);
|
||||||
this.importedObject.emit(object);
|
this.importedObject.emit(object);
|
||||||
});
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Unsubscribe from open subscriptions
|
* Unsubscribe from open subscriptions
|
||||||
*/
|
*/
|
||||||
ngOnDestroy(): void {
|
ngOnDestroy(): void {
|
||||||
if (hasValue(this.importObjectSub)) {
|
this.subs
|
||||||
this.importObjectSub.unsubscribe();
|
.filter((sub) => hasValue(sub))
|
||||||
}
|
.forEach((sub) => sub.unsubscribe());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@@ -0,0 +1,22 @@
|
|||||||
|
import { ExternalSourceEntryImportModalComponent } from './external-source-entry-import-modal.component';
|
||||||
|
import { ThemedComponent } from '../../../../../../theme-support/themed.component';
|
||||||
|
import { Component } from '@angular/core';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'ds-themed-external-source-entry-import-modal',
|
||||||
|
styleUrls: [],
|
||||||
|
templateUrl: '../../../../../../../shared/theme-support/themed.component.html',
|
||||||
|
})
|
||||||
|
export class ThemedExternalSourceEntryImportModalComponent extends ThemedComponent<ExternalSourceEntryImportModalComponent> {
|
||||||
|
protected getComponentName(): string {
|
||||||
|
return 'ExternalSourceEntryImportModalComponent';
|
||||||
|
}
|
||||||
|
|
||||||
|
protected importThemedComponent(themeName: string): Promise<any> {
|
||||||
|
return import(`../../../../../../../../themes/${themeName}/app/shared/form/builder/ds-dynamic-form-ui/relation-lookup-modal/external-source-tab/external-source-entry-import-modal/external-source-entry-import-modal.component`);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected importUnthemedComponent(): Promise<any> {
|
||||||
|
return import(`./external-source-entry-import-modal.component`);
|
||||||
|
}
|
||||||
|
}
|
@@ -3,17 +3,16 @@ import { ChangeDetectorRef, Component, CUSTOM_ELEMENTS_SCHEMA } from '@angular/c
|
|||||||
import { ComponentFixture, fakeAsync, inject, TestBed, tick, waitForAsync, } from '@angular/core/testing';
|
import { ComponentFixture, fakeAsync, inject, TestBed, tick, waitForAsync, } from '@angular/core/testing';
|
||||||
|
|
||||||
import { Chips } from './models/chips.model';
|
import { Chips } from './models/chips.model';
|
||||||
import { UploaderService } from '../uploader/uploader.service';
|
|
||||||
import { ChipsComponent } from './chips.component';
|
import { ChipsComponent } from './chips.component';
|
||||||
import { NgbModule } from '@ng-bootstrap/ng-bootstrap';
|
import { NgbModule } from '@ng-bootstrap/ng-bootstrap';
|
||||||
import { By } from '@angular/platform-browser';
|
import { By } from '@angular/platform-browser';
|
||||||
import { FormFieldMetadataValueObject } from '../form/builder/models/form-field-metadata-value.model';
|
import { FormFieldMetadataValueObject } from '../builder/models/form-field-metadata-value.model';
|
||||||
import { createTestComponent } from '../testing/utils.test';
|
import { createTestComponent } from '../../testing/utils.test';
|
||||||
import { AuthorityConfidenceStateDirective } from '../authority-confidence/authority-confidence-state.directive';
|
import { AuthorityConfidenceStateDirective } from '../directives/authority-confidence-state.directive';
|
||||||
import { TranslateModule } from '@ngx-translate/core';
|
import { TranslateModule } from '@ngx-translate/core';
|
||||||
import { ConfidenceType } from '../../core/shared/confidence-type';
|
import { ConfidenceType } from '../../../core/shared/confidence-type';
|
||||||
import { SortablejsModule } from 'ngx-sortablejs';
|
import { SortablejsModule } from 'ngx-sortablejs';
|
||||||
import { environment } from '../../../environments/environment';
|
import { environment } from '../../../../environments/environment';
|
||||||
|
|
||||||
describe('ChipsComponent test suite', () => {
|
describe('ChipsComponent test suite', () => {
|
||||||
|
|
||||||
@@ -41,7 +40,6 @@ describe('ChipsComponent test suite', () => {
|
|||||||
providers: [
|
providers: [
|
||||||
ChangeDetectorRef,
|
ChangeDetectorRef,
|
||||||
ChipsComponent,
|
ChipsComponent,
|
||||||
UploaderService
|
|
||||||
],
|
],
|
||||||
schemas: [CUSTOM_ELEMENTS_SCHEMA]
|
schemas: [CUSTOM_ELEMENTS_SCHEMA]
|
||||||
});
|
});
|
@@ -5,7 +5,7 @@ import isObject from 'lodash/isObject';
|
|||||||
|
|
||||||
import { Chips } from './models/chips.model';
|
import { Chips } from './models/chips.model';
|
||||||
import { ChipsItem } from './models/chips-item.model';
|
import { ChipsItem } from './models/chips-item.model';
|
||||||
import { UploaderService } from '../uploader/uploader.service';
|
import { DragService } from '../../../core/drag.service';
|
||||||
import { TranslateService } from '@ngx-translate/core';
|
import { TranslateService } from '@ngx-translate/core';
|
||||||
import { Options } from 'sortablejs';
|
import { Options } from 'sortablejs';
|
||||||
import { BehaviorSubject } from 'rxjs';
|
import { BehaviorSubject } from 'rxjs';
|
||||||
@@ -33,7 +33,7 @@ export class ChipsComponent implements OnChanges {
|
|||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
private cdr: ChangeDetectorRef,
|
private cdr: ChangeDetectorRef,
|
||||||
private uploaderService: UploaderService,
|
private dragService: DragService,
|
||||||
private translate: TranslateService) {
|
private translate: TranslateService) {
|
||||||
|
|
||||||
this.options = {
|
this.options = {
|
||||||
@@ -76,12 +76,12 @@ export class ChipsComponent implements OnChanges {
|
|||||||
|
|
||||||
onDragStart(index) {
|
onDragStart(index) {
|
||||||
this.isDragging.next(true);
|
this.isDragging.next(true);
|
||||||
this.uploaderService.overrideDragOverPage();
|
this.dragService.overrideDragOverPage();
|
||||||
this.dragged = index;
|
this.dragged = index;
|
||||||
}
|
}
|
||||||
|
|
||||||
onDragEnd(event) {
|
onDragEnd(event) {
|
||||||
this.uploaderService.allowDragOverPage();
|
this.dragService.allowDragOverPage();
|
||||||
this.dragged = -1;
|
this.dragged = -1;
|
||||||
this.chips.updateOrder();
|
this.chips.updateOrder();
|
||||||
this.isDragging.next(false);
|
this.isDragging.next(false);
|
@@ -1,5 +1,5 @@
|
|||||||
import { ChipsItem, ChipsItemIcon } from './chips-item.model';
|
import { ChipsItem, ChipsItemIcon } from './chips-item.model';
|
||||||
import { FormFieldMetadataValueObject } from '../../form/builder/models/form-field-metadata-value.model';
|
import { FormFieldMetadataValueObject } from '../../builder/models/form-field-metadata-value.model';
|
||||||
|
|
||||||
describe('ChipsItem model test suite', () => {
|
describe('ChipsItem model test suite', () => {
|
||||||
let item: ChipsItem;
|
let item: ChipsItem;
|
@@ -1,9 +1,9 @@
|
|||||||
import isObject from 'lodash/isObject';
|
import isObject from 'lodash/isObject';
|
||||||
import uniqueId from 'lodash/uniqueId';
|
import uniqueId from 'lodash/uniqueId';
|
||||||
import { hasValue, isNotEmpty } from '../../empty.util';
|
import { hasValue, isNotEmpty } from '../../../empty.util';
|
||||||
import { FormFieldMetadataValueObject } from '../../form/builder/models/form-field-metadata-value.model';
|
import { FormFieldMetadataValueObject } from '../../builder/models/form-field-metadata-value.model';
|
||||||
import { ConfidenceType } from '../../../core/shared/confidence-type';
|
import { ConfidenceType } from '../../../../core/shared/confidence-type';
|
||||||
import { PLACEHOLDER_PARENT_METADATA } from '../../form/builder/ds-dynamic-form-ui/ds-dynamic-form-constants';
|
import { PLACEHOLDER_PARENT_METADATA } from '../../builder/ds-dynamic-form-ui/ds-dynamic-form-constants';
|
||||||
|
|
||||||
export interface ChipsItemIcon {
|
export interface ChipsItemIcon {
|
||||||
metadata: string;
|
metadata: string;
|
@@ -1,6 +1,6 @@
|
|||||||
import { Chips } from './chips.model';
|
import { Chips } from './chips.model';
|
||||||
import { ChipsItem } from './chips-item.model';
|
import { ChipsItem } from './chips-item.model';
|
||||||
import { FormFieldMetadataValueObject } from '../../form/builder/models/form-field-metadata-value.model';
|
import { FormFieldMetadataValueObject } from '../../builder/models/form-field-metadata-value.model';
|
||||||
|
|
||||||
describe('Chips model test suite', () => {
|
describe('Chips model test suite', () => {
|
||||||
let items: any[];
|
let items: any[];
|
@@ -3,11 +3,11 @@ import isEqual from 'lodash/isEqual';
|
|||||||
import isObject from 'lodash/isObject';
|
import isObject from 'lodash/isObject';
|
||||||
import { BehaviorSubject } from 'rxjs';
|
import { BehaviorSubject } from 'rxjs';
|
||||||
import { ChipsItem, ChipsItemIcon } from './chips-item.model';
|
import { ChipsItem, ChipsItemIcon } from './chips-item.model';
|
||||||
import { hasValue, isNotEmpty } from '../../empty.util';
|
import { hasValue, isNotEmpty } from '../../../empty.util';
|
||||||
import { MetadataIconConfig } from '../../../../config/submission-config.interface';
|
import { MetadataIconConfig } from '../../../../../config/submission-config.interface';
|
||||||
import { FormFieldMetadataValueObject } from '../../form/builder/models/form-field-metadata-value.model';
|
import { FormFieldMetadataValueObject } from '../../builder/models/form-field-metadata-value.model';
|
||||||
import { VocabularyEntry } from '../../../core/submission/vocabularies/models/vocabulary-entry.model';
|
import { VocabularyEntry } from '../../../../core/submission/vocabularies/models/vocabulary-entry.model';
|
||||||
import { PLACEHOLDER_PARENT_METADATA } from '../../form/builder/ds-dynamic-form-ui/ds-dynamic-form-constants';
|
import { PLACEHOLDER_PARENT_METADATA } from '../../builder/ds-dynamic-form-ui/ds-dynamic-form-constants';
|
||||||
|
|
||||||
export class Chips {
|
export class Chips {
|
||||||
chipsItems: BehaviorSubject<ChipsItem[]>;
|
chipsItems: BehaviorSubject<ChipsItem[]>;
|
@@ -1,3 +1,11 @@
|
|||||||
|
/**
|
||||||
|
* The contents of this file are subject to the license and copyright
|
||||||
|
* detailed in the LICENSE and NOTICE files at the root of the source
|
||||||
|
* tree and available online at
|
||||||
|
*
|
||||||
|
* http://www.dspace.org/license/
|
||||||
|
*/
|
||||||
|
|
||||||
import {
|
import {
|
||||||
AfterViewInit,
|
AfterViewInit,
|
||||||
Directive,
|
Directive,
|
||||||
@@ -13,13 +21,13 @@ import {
|
|||||||
|
|
||||||
import findIndex from 'lodash/findIndex';
|
import findIndex from 'lodash/findIndex';
|
||||||
|
|
||||||
import { VocabularyEntry } from '../../core/submission/vocabularies/models/vocabulary-entry.model';
|
import { VocabularyEntry } from '../../../core/submission/vocabularies/models/vocabulary-entry.model';
|
||||||
import { FormFieldMetadataValueObject } from '../form/builder/models/form-field-metadata-value.model';
|
import { FormFieldMetadataValueObject } from '../builder/models/form-field-metadata-value.model';
|
||||||
import { ConfidenceType } from '../../core/shared/confidence-type';
|
import { ConfidenceType } from '../../../core/shared/confidence-type';
|
||||||
import { isNotEmpty, isNull } from '../empty.util';
|
import { isNotEmpty, isNull } from '../../empty.util';
|
||||||
import { ConfidenceIconConfig } from '../../../config/submission-config.interface';
|
import { ConfidenceIconConfig } from '../../../../config/submission-config.interface';
|
||||||
import { environment } from '../../../environments/environment';
|
import { environment } from '../../../../environments/environment';
|
||||||
import { VocabularyEntryDetail } from '../../core/submission/vocabularies/models/vocabulary-entry-detail.model';
|
import { VocabularyEntryDetail } from '../../../core/submission/vocabularies/models/vocabulary-entry-detail.model';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Directive to add to the element a bootstrap utility class based on metadata confidence value
|
* Directive to add to the element a bootstrap utility class based on metadata confidence value
|
@@ -2,10 +2,7 @@ import { NgModule } from '@angular/core';
|
|||||||
import { CommonModule } from '@angular/common';
|
import { CommonModule } from '@angular/common';
|
||||||
import { FormComponent } from './form.component';
|
import { FormComponent } from './form.component';
|
||||||
import { DsDynamicFormComponent } from './builder/ds-dynamic-form-ui/ds-dynamic-form.component';
|
import { DsDynamicFormComponent } from './builder/ds-dynamic-form-ui/ds-dynamic-form.component';
|
||||||
import {
|
import { DsDynamicFormControlContainerComponent, dsDynamicFormControlMapFn } from './builder/ds-dynamic-form-ui/ds-dynamic-form-control-container.component';
|
||||||
DsDynamicFormControlContainerComponent,
|
|
||||||
dsDynamicFormControlMapFn
|
|
||||||
} from './builder/ds-dynamic-form-ui/ds-dynamic-form-control-container.component';
|
|
||||||
import { DsDynamicListComponent } from './builder/ds-dynamic-form-ui/models/list/dynamic-list.component';
|
import { DsDynamicListComponent } from './builder/ds-dynamic-form-ui/models/list/dynamic-list.component';
|
||||||
import { DsDynamicLookupComponent } from './builder/ds-dynamic-form-ui/models/lookup/dynamic-lookup.component';
|
import { DsDynamicLookupComponent } from './builder/ds-dynamic-form-ui/models/lookup/dynamic-lookup.component';
|
||||||
import { DsDynamicDisabledComponent } from './builder/ds-dynamic-form-ui/models/disabled/dynamic-disabled.component';
|
import { DsDynamicDisabledComponent } from './builder/ds-dynamic-form-ui/models/disabled/dynamic-disabled.component';
|
||||||
@@ -24,12 +21,23 @@ import { DsDynamicLookupRelationExternalSourceTabComponent } from './builder/ds-
|
|||||||
import { SharedModule } from '../shared.module';
|
import { SharedModule } from '../shared.module';
|
||||||
import { TranslateModule } from '@ngx-translate/core';
|
import { TranslateModule } from '@ngx-translate/core';
|
||||||
import { SearchModule } from '../search/search.module';
|
import { SearchModule } from '../search/search.module';
|
||||||
import { DYNAMIC_FORM_CONTROL_MAP_FN, DynamicFormsCoreModule } from '@ng-dynamic-forms/core';
|
import { DYNAMIC_FORM_CONTROL_MAP_FN, DYNAMIC_MATCHER_PROVIDERS, DynamicFormLayoutService, DynamicFormsCoreModule, DynamicFormService, DynamicFormValidationService } from '@ng-dynamic-forms/core';
|
||||||
import { ExistingMetadataListElementComponent } from './builder/ds-dynamic-form-ui/existing-metadata-list-element/existing-metadata-list-element.component';
|
import { ExistingMetadataListElementComponent } from './builder/ds-dynamic-form-ui/existing-metadata-list-element/existing-metadata-list-element.component';
|
||||||
import { ExistingRelationListElementComponent } from './builder/ds-dynamic-form-ui/existing-relation-list-element/existing-relation-list-element.component';
|
import { ExistingRelationListElementComponent } from './builder/ds-dynamic-form-ui/existing-relation-list-element/existing-relation-list-element.component';
|
||||||
import { ExternalSourceEntryImportModalComponent } from './builder/ds-dynamic-form-ui/relation-lookup-modal/external-source-tab/external-source-entry-import-modal/external-source-entry-import-modal.component';
|
import { ExternalSourceEntryImportModalComponent } from './builder/ds-dynamic-form-ui/relation-lookup-modal/external-source-tab/external-source-entry-import-modal/external-source-entry-import-modal.component';
|
||||||
import { CustomSwitchComponent } from './builder/ds-dynamic-form-ui/models/custom-switch/custom-switch.component';
|
import { CustomSwitchComponent } from './builder/ds-dynamic-form-ui/models/custom-switch/custom-switch.component';
|
||||||
import { DynamicFormsNGBootstrapUIModule } from '@ng-dynamic-forms/ui-ng-bootstrap';
|
import { DynamicFormsNGBootstrapUIModule } from '@ng-dynamic-forms/ui-ng-bootstrap';
|
||||||
|
import { ChipsComponent } from './chips/chips.component';
|
||||||
|
import { NumberPickerComponent } from './number-picker/number-picker.component';
|
||||||
|
import { AuthorityConfidenceStateDirective } from './directives/authority-confidence-state.directive';
|
||||||
|
import { SortablejsModule } from 'ngx-sortablejs';
|
||||||
|
import { VocabularyTreeviewComponent } from './vocabulary-treeview/vocabulary-treeview.component';
|
||||||
|
import { VocabularyTreeviewService } from './vocabulary-treeview/vocabulary-treeview.service';
|
||||||
|
import { FormBuilderService } from './builder/form-builder.service';
|
||||||
|
import { DsDynamicTypeBindRelationService } from './builder/ds-dynamic-form-ui/ds-dynamic-type-bind-relation.service';
|
||||||
|
import { FormService } from './form.service';
|
||||||
|
import { NgxMaskModule } from 'ngx-mask';
|
||||||
|
import { ThemedExternalSourceEntryImportModalComponent } from './builder/ds-dynamic-form-ui/relation-lookup-modal/external-source-tab/external-source-entry-import-modal/themed-external-source-entry-import-modal.component';
|
||||||
|
|
||||||
const COMPONENTS = [
|
const COMPONENTS = [
|
||||||
CustomSwitchComponent,
|
CustomSwitchComponent,
|
||||||
@@ -53,12 +61,21 @@ const COMPONENTS = [
|
|||||||
ExistingMetadataListElementComponent,
|
ExistingMetadataListElementComponent,
|
||||||
ExistingRelationListElementComponent,
|
ExistingRelationListElementComponent,
|
||||||
ExternalSourceEntryImportModalComponent,
|
ExternalSourceEntryImportModalComponent,
|
||||||
FormComponent
|
FormComponent,
|
||||||
|
ChipsComponent,
|
||||||
|
NumberPickerComponent,
|
||||||
|
VocabularyTreeviewComponent,
|
||||||
|
ThemedExternalSourceEntryImportModalComponent
|
||||||
|
];
|
||||||
|
|
||||||
|
const DIRECTIVES = [
|
||||||
|
AuthorityConfidenceStateDirective,
|
||||||
];
|
];
|
||||||
|
|
||||||
@NgModule({
|
@NgModule({
|
||||||
declarations: [
|
declarations: [
|
||||||
...COMPONENTS
|
...COMPONENTS,
|
||||||
|
...DIRECTIVES,
|
||||||
],
|
],
|
||||||
imports: [
|
imports: [
|
||||||
CommonModule,
|
CommonModule,
|
||||||
@@ -66,16 +83,27 @@ const COMPONENTS = [
|
|||||||
DynamicFormsNGBootstrapUIModule,
|
DynamicFormsNGBootstrapUIModule,
|
||||||
SearchModule,
|
SearchModule,
|
||||||
SharedModule,
|
SharedModule,
|
||||||
TranslateModule
|
TranslateModule,
|
||||||
|
SortablejsModule,
|
||||||
|
NgxMaskModule.forRoot(),
|
||||||
],
|
],
|
||||||
exports: [
|
exports: [
|
||||||
...COMPONENTS
|
...COMPONENTS,
|
||||||
|
...DIRECTIVES,
|
||||||
],
|
],
|
||||||
providers: [
|
providers: [
|
||||||
{
|
{
|
||||||
provide: DYNAMIC_FORM_CONTROL_MAP_FN,
|
provide: DYNAMIC_FORM_CONTROL_MAP_FN,
|
||||||
useValue: dsDynamicFormControlMapFn
|
useValue: dsDynamicFormControlMapFn
|
||||||
}
|
},
|
||||||
|
...DYNAMIC_MATCHER_PROVIDERS,
|
||||||
|
VocabularyTreeviewService,
|
||||||
|
DynamicFormLayoutService,
|
||||||
|
DynamicFormService,
|
||||||
|
DynamicFormValidationService,
|
||||||
|
FormBuilderService,
|
||||||
|
DsDynamicTypeBindRelationService,
|
||||||
|
FormService,
|
||||||
]
|
]
|
||||||
})
|
})
|
||||||
export class FormModule {
|
export class FormModule {
|
||||||
|
@@ -2,12 +2,11 @@
|
|||||||
import { ChangeDetectorRef, Component, CUSTOM_ELEMENTS_SCHEMA } from '@angular/core';
|
import { ChangeDetectorRef, Component, CUSTOM_ELEMENTS_SCHEMA } from '@angular/core';
|
||||||
import { ComponentFixture, inject, TestBed, waitForAsync, } from '@angular/core/testing';
|
import { ComponentFixture, inject, TestBed, waitForAsync, } from '@angular/core/testing';
|
||||||
|
|
||||||
import { UploaderService } from '../uploader/uploader.service';
|
|
||||||
import { NgbModule } from '@ng-bootstrap/ng-bootstrap';
|
import { NgbModule } from '@ng-bootstrap/ng-bootstrap';
|
||||||
import { By } from '@angular/platform-browser';
|
import { By } from '@angular/platform-browser';
|
||||||
import { NumberPickerComponent } from './number-picker.component';
|
import { NumberPickerComponent } from './number-picker.component';
|
||||||
import { FormsModule, ReactiveFormsModule } from '@angular/forms';
|
import { FormsModule, ReactiveFormsModule } from '@angular/forms';
|
||||||
import { createTestComponent } from '../testing/utils.test';
|
import { createTestComponent } from '../../testing/utils.test';
|
||||||
|
|
||||||
describe('NumberPickerComponent test suite', () => {
|
describe('NumberPickerComponent test suite', () => {
|
||||||
|
|
||||||
@@ -33,7 +32,6 @@ describe('NumberPickerComponent test suite', () => {
|
|||||||
providers: [
|
providers: [
|
||||||
ChangeDetectorRef,
|
ChangeDetectorRef,
|
||||||
NumberPickerComponent,
|
NumberPickerComponent,
|
||||||
UploaderService
|
|
||||||
],
|
],
|
||||||
schemas: [CUSTOM_ELEMENTS_SCHEMA]
|
schemas: [CUSTOM_ELEMENTS_SCHEMA]
|
||||||
});
|
});
|
@@ -1,6 +1,6 @@
|
|||||||
import { ChangeDetectorRef, Component, EventEmitter, Input, OnInit, Output, SimpleChanges, } from '@angular/core';
|
import { ChangeDetectorRef, Component, EventEmitter, Input, OnInit, Output, SimpleChanges, } from '@angular/core';
|
||||||
import { ControlValueAccessor, FormBuilder, NG_VALUE_ACCESSOR } from '@angular/forms';
|
import { ControlValueAccessor, FormBuilder, NG_VALUE_ACCESSOR } from '@angular/forms';
|
||||||
import { isEmpty } from '../empty.util';
|
import { isEmpty } from '../../empty.util';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'ds-number-picker',
|
selector: 'ds-number-picker',
|
@@ -1,7 +1,7 @@
|
|||||||
/* eslint-disable max-classes-per-file */
|
/* eslint-disable max-classes-per-file */
|
||||||
import { BehaviorSubject } from 'rxjs';
|
import { BehaviorSubject } from 'rxjs';
|
||||||
import { VocabularyEntryDetail } from '../../core/submission/vocabularies/models/vocabulary-entry-detail.model';
|
import { VocabularyEntryDetail } from '../../../core/submission/vocabularies/models/vocabulary-entry-detail.model';
|
||||||
import { PageInfo } from '../../core/shared/page-info.model';
|
import { PageInfo } from '../../../core/shared/page-info.model';
|
||||||
|
|
||||||
export const LOAD_MORE = 'LOAD_MORE';
|
export const LOAD_MORE = 'LOAD_MORE';
|
||||||
export const LOAD_MORE_ROOT = 'LOAD_MORE_ROOT';
|
export const LOAD_MORE_ROOT = 'LOAD_MORE_ROOT';
|
@@ -8,18 +8,18 @@ import { TranslateModule } from '@ngx-translate/core';
|
|||||||
import { NgbActiveModal } from '@ng-bootstrap/ng-bootstrap';
|
import { NgbActiveModal } from '@ng-bootstrap/ng-bootstrap';
|
||||||
import { provideMockStore } from '@ngrx/store/testing';
|
import { provideMockStore } from '@ngrx/store/testing';
|
||||||
|
|
||||||
import { createTestComponent } from '../testing/utils.test';
|
import { createTestComponent } from '../../testing/utils.test';
|
||||||
import { VocabularyTreeviewComponent } from './vocabulary-treeview.component';
|
import { VocabularyTreeviewComponent } from './vocabulary-treeview.component';
|
||||||
import { VocabularyTreeviewService } from './vocabulary-treeview.service';
|
import { VocabularyTreeviewService } from './vocabulary-treeview.service';
|
||||||
import { VocabularyEntryDetail } from '../../core/submission/vocabularies/models/vocabulary-entry-detail.model';
|
import { VocabularyEntryDetail } from '../../../core/submission/vocabularies/models/vocabulary-entry-detail.model';
|
||||||
import { TreeviewFlatNode } from './vocabulary-treeview-node.model';
|
import { TreeviewFlatNode } from './vocabulary-treeview-node.model';
|
||||||
import { FormFieldMetadataValueObject } from '../form/builder/models/form-field-metadata-value.model';
|
import { FormFieldMetadataValueObject } from '../builder/models/form-field-metadata-value.model';
|
||||||
import { VocabularyOptions } from '../../core/submission/vocabularies/models/vocabulary-options.model';
|
import { VocabularyOptions } from '../../../core/submission/vocabularies/models/vocabulary-options.model';
|
||||||
import { PageInfo } from '../../core/shared/page-info.model';
|
import { PageInfo } from '../../../core/shared/page-info.model';
|
||||||
import { VocabularyEntry } from '../../core/submission/vocabularies/models/vocabulary-entry.model';
|
import { VocabularyEntry } from '../../../core/submission/vocabularies/models/vocabulary-entry.model';
|
||||||
import { AuthTokenInfo } from '../../core/auth/models/auth-token-info.model';
|
import { AuthTokenInfo } from '../../../core/auth/models/auth-token-info.model';
|
||||||
import { authReducer } from '../../core/auth/auth.reducer';
|
import { authReducer } from '../../../core/auth/auth.reducer';
|
||||||
import { storeModuleConfig } from '../../app.reducer';
|
import { storeModuleConfig } from '../../../app.reducer';
|
||||||
|
|
||||||
describe('VocabularyTreeviewComponent test suite', () => {
|
describe('VocabularyTreeviewComponent test suite', () => {
|
||||||
|
|
@@ -7,17 +7,17 @@ import { Observable, Subscription } from 'rxjs';
|
|||||||
import { select, Store } from '@ngrx/store';
|
import { select, Store } from '@ngrx/store';
|
||||||
import { TranslateService } from '@ngx-translate/core';
|
import { TranslateService } from '@ngx-translate/core';
|
||||||
|
|
||||||
import { VocabularyEntryDetail } from '../../core/submission/vocabularies/models/vocabulary-entry-detail.model';
|
import { VocabularyEntryDetail } from '../../../core/submission/vocabularies/models/vocabulary-entry-detail.model';
|
||||||
import { hasValue, isEmpty, isNotEmpty } from '../empty.util';
|
import { hasValue, isEmpty, isNotEmpty } from '../../empty.util';
|
||||||
import { isAuthenticated } from '../../core/auth/selectors';
|
import { isAuthenticated } from '../../../core/auth/selectors';
|
||||||
import { VocabularyTreeviewService } from './vocabulary-treeview.service';
|
import { VocabularyTreeviewService } from './vocabulary-treeview.service';
|
||||||
import { LOAD_MORE, LOAD_MORE_ROOT, TreeviewFlatNode, TreeviewNode } from './vocabulary-treeview-node.model';
|
import { LOAD_MORE, LOAD_MORE_ROOT, TreeviewFlatNode, TreeviewNode } from './vocabulary-treeview-node.model';
|
||||||
import { VocabularyOptions } from '../../core/submission/vocabularies/models/vocabulary-options.model';
|
import { VocabularyOptions } from '../../../core/submission/vocabularies/models/vocabulary-options.model';
|
||||||
import { PageInfo } from '../../core/shared/page-info.model';
|
import { PageInfo } from '../../../core/shared/page-info.model';
|
||||||
import { VocabularyEntry } from '../../core/submission/vocabularies/models/vocabulary-entry.model';
|
import { VocabularyEntry } from '../../../core/submission/vocabularies/models/vocabulary-entry.model';
|
||||||
import { VocabularyTreeFlattener } from './vocabulary-tree-flattener';
|
import { VocabularyTreeFlattener } from './vocabulary-tree-flattener';
|
||||||
import { VocabularyTreeFlatDataSource } from './vocabulary-tree-flat-data-source';
|
import { VocabularyTreeFlatDataSource } from './vocabulary-tree-flat-data-source';
|
||||||
import { CoreState } from '../../core/core-state.model';
|
import { CoreState } from '../../../core/core-state.model';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Component that show a hierarchical vocabulary in a tree view
|
* Component that show a hierarchical vocabulary in a tree view
|
@@ -5,15 +5,15 @@ import { TranslateLoader, TranslateModule, TranslateService } from '@ngx-transla
|
|||||||
import { cold, getTestScheduler, hot } from 'jasmine-marbles';
|
import { cold, getTestScheduler, hot } from 'jasmine-marbles';
|
||||||
|
|
||||||
import { VocabularyTreeviewService } from './vocabulary-treeview.service';
|
import { VocabularyTreeviewService } from './vocabulary-treeview.service';
|
||||||
import { VocabularyService } from '../../core/submission/vocabularies/vocabulary.service';
|
import { VocabularyService } from '../../../core/submission/vocabularies/vocabulary.service';
|
||||||
import { TranslateLoaderMock } from '../mocks/translate-loader.mock';
|
import { TranslateLoaderMock } from '../../mocks/translate-loader.mock';
|
||||||
import { VocabularyOptions } from '../../core/submission/vocabularies/models/vocabulary-options.model';
|
import { VocabularyOptions } from '../../../core/submission/vocabularies/models/vocabulary-options.model';
|
||||||
import { LOAD_MORE_NODE, LOAD_MORE_ROOT_NODE, TreeviewFlatNode, TreeviewNode } from './vocabulary-treeview-node.model';
|
import { LOAD_MORE_NODE, LOAD_MORE_ROOT_NODE, TreeviewFlatNode, TreeviewNode } from './vocabulary-treeview-node.model';
|
||||||
import { PageInfo } from '../../core/shared/page-info.model';
|
import { PageInfo } from '../../../core/shared/page-info.model';
|
||||||
import { VocabularyEntryDetail } from '../../core/submission/vocabularies/models/vocabulary-entry-detail.model';
|
import { VocabularyEntryDetail } from '../../../core/submission/vocabularies/models/vocabulary-entry-detail.model';
|
||||||
import { buildPaginatedList } from '../../core/data/paginated-list.model';
|
import { buildPaginatedList } from '../../../core/data/paginated-list.model';
|
||||||
import { createSuccessfulRemoteDataObject } from '../remote-data.utils';
|
import { createSuccessfulRemoteDataObject } from '../../remote-data.utils';
|
||||||
import { VocabularyEntry } from '../../core/submission/vocabularies/models/vocabulary-entry.model';
|
import { VocabularyEntry } from '../../../core/submission/vocabularies/models/vocabulary-entry.model';
|
||||||
import { expand, map, switchMap } from 'rxjs/operators';
|
import { expand, map, switchMap } from 'rxjs/operators';
|
||||||
import { from as observableFrom } from 'rxjs';
|
import { from as observableFrom } from 'rxjs';
|
||||||
|
|
@@ -10,17 +10,17 @@ import {
|
|||||||
TreeviewFlatNode,
|
TreeviewFlatNode,
|
||||||
TreeviewNode
|
TreeviewNode
|
||||||
} from './vocabulary-treeview-node.model';
|
} from './vocabulary-treeview-node.model';
|
||||||
import { VocabularyEntry } from '../../core/submission/vocabularies/models/vocabulary-entry.model';
|
import { VocabularyEntry } from '../../../core/submission/vocabularies/models/vocabulary-entry.model';
|
||||||
import { VocabularyService } from '../../core/submission/vocabularies/vocabulary.service';
|
import { VocabularyService } from '../../../core/submission/vocabularies/vocabulary.service';
|
||||||
import { PageInfo } from '../../core/shared/page-info.model';
|
import { PageInfo } from '../../../core/shared/page-info.model';
|
||||||
import { isEmpty, isNotEmpty } from '../empty.util';
|
import { isEmpty, isNotEmpty } from '../../empty.util';
|
||||||
import { VocabularyOptions } from '../../core/submission/vocabularies/models/vocabulary-options.model';
|
import { VocabularyOptions } from '../../../core/submission/vocabularies/models/vocabulary-options.model';
|
||||||
import {
|
import {
|
||||||
getFirstSucceededRemoteDataPayload,
|
getFirstSucceededRemoteDataPayload,
|
||||||
getFirstSucceededRemoteListPayload
|
getFirstSucceededRemoteListPayload
|
||||||
} from '../../core/shared/operators';
|
} from '../../../core/shared/operators';
|
||||||
import { PaginatedList } from '../../core/data/paginated-list.model';
|
import { PaginatedList } from '../../../core/data/paginated-list.model';
|
||||||
import { VocabularyEntryDetail } from '../../core/submission/vocabularies/models/vocabulary-entry-detail.model';
|
import { VocabularyEntryDetail } from '../../../core/submission/vocabularies/models/vocabulary-entry-detail.model';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A service that provides methods to deal with vocabulary tree
|
* A service that provides methods to deal with vocabulary tree
|
@@ -12,8 +12,11 @@ import { ExternalLinkMenuItemComponent } from './menu-item/external-link-menu-it
|
|||||||
const COMPONENTS = [
|
const COMPONENTS = [
|
||||||
MenuSectionComponent,
|
MenuSectionComponent,
|
||||||
MenuComponent,
|
MenuComponent,
|
||||||
LinkMenuItemComponent,
|
];
|
||||||
|
|
||||||
|
const ENTRY_COMPONENTS = [
|
||||||
TextMenuItemComponent,
|
TextMenuItemComponent,
|
||||||
|
LinkMenuItemComponent,
|
||||||
OnClickMenuItemComponent,
|
OnClickMenuItemComponent,
|
||||||
ExternalLinkMenuItemComponent,
|
ExternalLinkMenuItemComponent,
|
||||||
];
|
];
|
||||||
@@ -32,10 +35,12 @@ const PROVIDERS = [
|
|||||||
...MODULES
|
...MODULES
|
||||||
],
|
],
|
||||||
declarations: [
|
declarations: [
|
||||||
...COMPONENTS
|
...COMPONENTS,
|
||||||
|
...ENTRY_COMPONENTS,
|
||||||
],
|
],
|
||||||
providers: [
|
providers: [
|
||||||
...PROVIDERS
|
...PROVIDERS,
|
||||||
|
...ENTRY_COMPONENTS,
|
||||||
],
|
],
|
||||||
exports: [
|
exports: [
|
||||||
...COMPONENTS
|
...COMPONENTS
|
||||||
|
@@ -9,7 +9,7 @@
|
|||||||
<h3 class="position-relative py-1 my-3 font-weight-normal">
|
<h3 class="position-relative py-1 my-3 font-weight-normal">
|
||||||
<hr>
|
<hr>
|
||||||
<div id="create-community-or-separator" class="text-center position-absolute w-100">
|
<div id="create-community-or-separator" class="text-center position-absolute w-100">
|
||||||
<span class="px-4 bg-white">or</span>
|
<span class="px-4 bg-white">{{'dso-selector.' + action + '.' + objectType.toString().toLowerCase() + '.or-divider' | translate}}</span>
|
||||||
</div>
|
</div>
|
||||||
</h3>
|
</h3>
|
||||||
|
|
||||||
|
@@ -17,7 +17,6 @@ import {
|
|||||||
} from '@ng-bootstrap/ng-bootstrap';
|
} from '@ng-bootstrap/ng-bootstrap';
|
||||||
import { MissingTranslationHandler, TranslateModule } from '@ngx-translate/core';
|
import { MissingTranslationHandler, TranslateModule } from '@ngx-translate/core';
|
||||||
import { NgxPaginationModule } from 'ngx-pagination';
|
import { NgxPaginationModule } from 'ngx-pagination';
|
||||||
import { FileUploadModule } from 'ng2-file-upload';
|
|
||||||
import { InfiniteScrollModule } from 'ngx-infinite-scroll';
|
import { InfiniteScrollModule } from 'ngx-infinite-scroll';
|
||||||
import { ConfirmationModalComponent } from './confirmation-modal/confirmation-modal.component';
|
import { ConfirmationModalComponent } from './confirmation-modal/confirmation-modal.component';
|
||||||
import {
|
import {
|
||||||
@@ -29,7 +28,6 @@ import {
|
|||||||
import {
|
import {
|
||||||
ImportBatchSelectorComponent
|
ImportBatchSelectorComponent
|
||||||
} from './dso-selector/modal-wrappers/import-batch-selector/import-batch-selector.component';
|
} from './dso-selector/modal-wrappers/import-batch-selector/import-batch-selector.component';
|
||||||
import { FileDropzoneNoUploaderComponent } from './file-dropzone-no-uploader/file-dropzone-no-uploader.component';
|
|
||||||
import { ItemListElementComponent } from './object-list/item-list-element/item-types/item/item-list-element.component';
|
import { ItemListElementComponent } from './object-list/item-list-element/item-types/item/item-list-element.component';
|
||||||
import { EnumKeysPipe } from './utils/enum-keys-pipe';
|
import { EnumKeysPipe } from './utils/enum-keys-pipe';
|
||||||
import { FileSizePipe } from './utils/file-size-pipe';
|
import { FileSizePipe } from './utils/file-size-pipe';
|
||||||
@@ -72,9 +70,6 @@ import { TruncatePipe } from './utils/truncate.pipe';
|
|||||||
import { TruncatableComponent } from './truncatable/truncatable.component';
|
import { TruncatableComponent } from './truncatable/truncatable.component';
|
||||||
import { TruncatableService } from './truncatable/truncatable.service';
|
import { TruncatableService } from './truncatable/truncatable.service';
|
||||||
import { TruncatablePartComponent } from './truncatable/truncatable-part/truncatable-part.component';
|
import { TruncatablePartComponent } from './truncatable/truncatable-part/truncatable-part.component';
|
||||||
import { UploaderComponent } from './uploader/uploader.component';
|
|
||||||
import { ChipsComponent } from './chips/chips.component';
|
|
||||||
import { NumberPickerComponent } from './number-picker/number-picker.component';
|
|
||||||
import { MockAdminGuard } from './mocks/admin-guard.service.mock';
|
import { MockAdminGuard } from './mocks/admin-guard.service.mock';
|
||||||
import { AlertComponent } from './alert/alert.component';
|
import { AlertComponent } from './alert/alert.component';
|
||||||
import {
|
import {
|
||||||
@@ -110,7 +105,6 @@ import { EmphasizePipe } from './utils/emphasize.pipe';
|
|||||||
import { InputSuggestionsComponent } from './input-suggestions/input-suggestions.component';
|
import { InputSuggestionsComponent } from './input-suggestions/input-suggestions.component';
|
||||||
import { CapitalizePipe } from './utils/capitalize.pipe';
|
import { CapitalizePipe } from './utils/capitalize.pipe';
|
||||||
import { ObjectKeysPipe } from './utils/object-keys-pipe';
|
import { ObjectKeysPipe } from './utils/object-keys-pipe';
|
||||||
import { AuthorityConfidenceStateDirective } from './authority-confidence/authority-confidence-state.directive';
|
|
||||||
import { LangSwitchComponent } from './lang-switch/lang-switch.component';
|
import { LangSwitchComponent } from './lang-switch/lang-switch.component';
|
||||||
import {
|
import {
|
||||||
PlainTextMetadataListElementComponent
|
PlainTextMetadataListElementComponent
|
||||||
@@ -231,7 +225,6 @@ import {
|
|||||||
ImportableListItemControlComponent
|
ImportableListItemControlComponent
|
||||||
} from './object-collection/shared/importable-list-item-control/importable-list-item-control.component';
|
} from './object-collection/shared/importable-list-item-control/importable-list-item-control.component';
|
||||||
import { ItemVersionsComponent } from './item/item-versions/item-versions.component';
|
import { ItemVersionsComponent } from './item/item-versions/item-versions.component';
|
||||||
import { SortablejsModule } from 'ngx-sortablejs';
|
|
||||||
import { LogInContainerComponent } from './log-in/container/log-in-container.component';
|
import { LogInContainerComponent } from './log-in/container/log-in-container.component';
|
||||||
import { LogInShibbolethComponent } from './log-in/methods/shibboleth/log-in-shibboleth.component';
|
import { LogInShibbolethComponent } from './log-in/methods/shibboleth/log-in-shibboleth.component';
|
||||||
import { LogInPasswordComponent } from './log-in/methods/password/log-in-password.component';
|
import { LogInPasswordComponent } from './log-in/methods/password/log-in-password.component';
|
||||||
@@ -257,7 +250,6 @@ import { NgForTrackByIdDirective } from './ng-for-track-by-id.directive';
|
|||||||
import { FileDownloadLinkComponent } from './file-download-link/file-download-link.component';
|
import { FileDownloadLinkComponent } from './file-download-link/file-download-link.component';
|
||||||
import { CollectionDropdownComponent } from './collection-dropdown/collection-dropdown.component';
|
import { CollectionDropdownComponent } from './collection-dropdown/collection-dropdown.component';
|
||||||
import { EntityDropdownComponent } from './entity-dropdown/entity-dropdown.component';
|
import { EntityDropdownComponent } from './entity-dropdown/entity-dropdown.component';
|
||||||
import { VocabularyTreeviewComponent } from './vocabulary-treeview/vocabulary-treeview.component';
|
|
||||||
import { CurationFormComponent } from '../curation-form/curation-form.component';
|
import { CurationFormComponent } from '../curation-form/curation-form.component';
|
||||||
import {
|
import {
|
||||||
PublicationSidebarSearchListElementComponent
|
PublicationSidebarSearchListElementComponent
|
||||||
@@ -292,9 +284,6 @@ import {
|
|||||||
MetadataRepresentationListComponent
|
MetadataRepresentationListComponent
|
||||||
} from '../item-page/simple/metadata-representation-list/metadata-representation-list.component';
|
} from '../item-page/simple/metadata-representation-list/metadata-representation-list.component';
|
||||||
import { RelatedItemsComponent } from '../item-page/simple/related-items/related-items-component';
|
import { RelatedItemsComponent } from '../item-page/simple/related-items/related-items-component';
|
||||||
import { LinkMenuItemComponent } from './menu/menu-item/link-menu-item.component';
|
|
||||||
import { OnClickMenuItemComponent } from './menu/menu-item/onclick-menu-item.component';
|
|
||||||
import { TextMenuItemComponent } from './menu/menu-item/text-menu-item.component';
|
|
||||||
import { SearchNavbarComponent } from '../search-navbar/search-navbar.component';
|
import { SearchNavbarComponent } from '../search-navbar/search-navbar.component';
|
||||||
import { ThemedSearchNavbarComponent } from '../search-navbar/themed-search-navbar.component';
|
import { ThemedSearchNavbarComponent } from '../search-navbar/themed-search-navbar.component';
|
||||||
import {
|
import {
|
||||||
@@ -311,7 +300,6 @@ import { DsSelectComponent } from './ds-select/ds-select.component';
|
|||||||
import { LogInOidcComponent } from './log-in/methods/oidc/log-in-oidc.component';
|
import { LogInOidcComponent } from './log-in/methods/oidc/log-in-oidc.component';
|
||||||
import { ThemedItemListPreviewComponent } from './object-list/my-dspace-result-list-element/item-list-preview/themed-item-list-preview.component';
|
import { ThemedItemListPreviewComponent } from './object-list/my-dspace-result-list-element/item-list-preview/themed-item-list-preview.component';
|
||||||
import { RSSComponent } from './rss-feed/rss.component';
|
import { RSSComponent } from './rss-feed/rss.component';
|
||||||
import { ExternalLinkMenuItemComponent } from './menu/menu-item/external-link-menu-item.component';
|
|
||||||
import { DsoPageOrcidButtonComponent } from './dso-page/dso-page-orcid-button/dso-page-orcid-button.component';
|
import { DsoPageOrcidButtonComponent } from './dso-page/dso-page-orcid-button/dso-page-orcid-button.component';
|
||||||
import { LogInOrcidComponent } from './log-in/methods/orcid/log-in-orcid.component';
|
import { LogInOrcidComponent } from './log-in/methods/orcid/log-in-orcid.component';
|
||||||
import { BrowserOnlyPipe } from './utils/browser-only.pipe';
|
import { BrowserOnlyPipe } from './utils/browser-only.pipe';
|
||||||
@@ -323,16 +311,16 @@ import {
|
|||||||
} from '../item-page/simple/field-components/specific-field/title/item-page-title-field.component';
|
} from '../item-page/simple/field-components/specific-field/title/item-page-title-field.component';
|
||||||
import { MarkdownPipe } from './utils/markdown.pipe';
|
import { MarkdownPipe } from './utils/markdown.pipe';
|
||||||
import { GoogleRecaptchaModule } from '../core/google-recaptcha/google-recaptcha.module';
|
import { GoogleRecaptchaModule } from '../core/google-recaptcha/google-recaptcha.module';
|
||||||
|
import { MenuModule } from './menu/menu.module';
|
||||||
import {
|
import {
|
||||||
ListableNotificationObjectComponent
|
ListableNotificationObjectComponent
|
||||||
} from './object-list/listable-notification-object/listable-notification-object.component';
|
} from './object-list/listable-notification-object/listable-notification-object.component';
|
||||||
import { ItemBackButtonComponent } from './item-back-button/item-back-button.component';
|
|
||||||
import { ThemedItemBackButtonComponent } from './item-back-button/themed-item-back-button.component';
|
import { ThemedItemBackButtonComponent } from './item-back-button/themed-item-back-button.component';
|
||||||
|
import { ThemedCollectionDropdownComponent } from './collection-dropdown/themed-collection-dropdown.component';
|
||||||
|
|
||||||
|
|
||||||
const MODULES = [
|
const MODULES = [
|
||||||
CommonModule,
|
CommonModule,
|
||||||
SortablejsModule,
|
|
||||||
FileUploadModule,
|
|
||||||
FormsModule,
|
FormsModule,
|
||||||
InfiniteScrollModule,
|
InfiniteScrollModule,
|
||||||
NgbNavModule,
|
NgbNavModule,
|
||||||
@@ -349,6 +337,7 @@ const MODULES = [
|
|||||||
DragDropModule,
|
DragDropModule,
|
||||||
CdkTreeModule,
|
CdkTreeModule,
|
||||||
GoogleRecaptchaModule,
|
GoogleRecaptchaModule,
|
||||||
|
MenuModule,
|
||||||
];
|
];
|
||||||
|
|
||||||
const ROOT_MODULES = [
|
const ROOT_MODULES = [
|
||||||
@@ -380,7 +369,6 @@ const COMPONENTS = [
|
|||||||
AuthNavMenuComponent,
|
AuthNavMenuComponent,
|
||||||
ThemedAuthNavMenuComponent,
|
ThemedAuthNavMenuComponent,
|
||||||
UserMenuComponent,
|
UserMenuComponent,
|
||||||
ChipsComponent,
|
|
||||||
DsSelectComponent,
|
DsSelectComponent,
|
||||||
ErrorComponent,
|
ErrorComponent,
|
||||||
FileSectionComponent,
|
FileSectionComponent,
|
||||||
@@ -389,7 +377,6 @@ const COMPONENTS = [
|
|||||||
ThemedLoadingComponent,
|
ThemedLoadingComponent,
|
||||||
LogInComponent,
|
LogInComponent,
|
||||||
LogOutComponent,
|
LogOutComponent,
|
||||||
NumberPickerComponent,
|
|
||||||
ObjectListComponent,
|
ObjectListComponent,
|
||||||
ThemedObjectListComponent,
|
ThemedObjectListComponent,
|
||||||
ObjectDetailComponent,
|
ObjectDetailComponent,
|
||||||
@@ -404,21 +391,14 @@ const COMPONENTS = [
|
|||||||
SidebarFilterComponent,
|
SidebarFilterComponent,
|
||||||
SidebarFilterSelectedOptionComponent,
|
SidebarFilterSelectedOptionComponent,
|
||||||
ThumbnailComponent,
|
ThumbnailComponent,
|
||||||
UploaderComponent,
|
|
||||||
FileDropzoneNoUploaderComponent,
|
|
||||||
ItemListPreviewComponent,
|
ItemListPreviewComponent,
|
||||||
ThemedItemListPreviewComponent,
|
ThemedItemListPreviewComponent,
|
||||||
MyDSpaceItemStatusComponent,
|
MyDSpaceItemStatusComponent,
|
||||||
ItemSubmitterComponent,
|
ItemSubmitterComponent,
|
||||||
ItemDetailPreviewComponent,
|
ItemDetailPreviewComponent,
|
||||||
ItemDetailPreviewFieldComponent,
|
ItemDetailPreviewFieldComponent,
|
||||||
ItemBackButtonComponent,
|
|
||||||
ThemedItemBackButtonComponent,
|
ThemedItemBackButtonComponent,
|
||||||
ClaimedTaskActionsComponent,
|
ClaimedTaskActionsComponent,
|
||||||
ClaimedTaskActionsApproveComponent,
|
|
||||||
ClaimedTaskActionsRejectComponent,
|
|
||||||
ClaimedTaskActionsReturnToPoolComponent,
|
|
||||||
ClaimedTaskActionsEditMetadataComponent,
|
|
||||||
ClaimedTaskActionsLoaderComponent,
|
ClaimedTaskActionsLoaderComponent,
|
||||||
ItemActionsComponent,
|
ItemActionsComponent,
|
||||||
PoolTaskActionsComponent,
|
PoolTaskActionsComponent,
|
||||||
@@ -433,88 +413,30 @@ const COMPONENTS = [
|
|||||||
ValidationSuggestionsComponent,
|
ValidationSuggestionsComponent,
|
||||||
DsoInputSuggestionsComponent,
|
DsoInputSuggestionsComponent,
|
||||||
DSOSelectorComponent,
|
DSOSelectorComponent,
|
||||||
CreateCommunityParentSelectorComponent,
|
|
||||||
ThemedCreateCommunityParentSelectorComponent,
|
|
||||||
CreateCollectionParentSelectorComponent,
|
|
||||||
ThemedCreateCollectionParentSelectorComponent,
|
|
||||||
CreateItemParentSelectorComponent,
|
|
||||||
ThemedCreateItemParentSelectorComponent,
|
|
||||||
EditCommunitySelectorComponent,
|
|
||||||
ThemedEditCommunitySelectorComponent,
|
|
||||||
EditCollectionSelectorComponent,
|
|
||||||
ThemedEditCollectionSelectorComponent,
|
|
||||||
EditItemSelectorComponent,
|
|
||||||
ThemedEditItemSelectorComponent,
|
|
||||||
CommunitySearchResultListElementComponent,
|
|
||||||
CollectionSearchResultListElementComponent,
|
|
||||||
BrowseByComponent,
|
|
||||||
|
|
||||||
CollectionSearchResultGridElementComponent,
|
|
||||||
CommunitySearchResultGridElementComponent,
|
|
||||||
SearchExportCsvComponent,
|
SearchExportCsvComponent,
|
||||||
PageSizeSelectorComponent,
|
PageSizeSelectorComponent,
|
||||||
ListableObjectComponentLoaderComponent,
|
ListableObjectComponentLoaderComponent,
|
||||||
CollectionListElementComponent,
|
|
||||||
CommunityListElementComponent,
|
|
||||||
CollectionGridElementComponent,
|
|
||||||
CommunityGridElementComponent,
|
|
||||||
BrowseByComponent,
|
|
||||||
AbstractTrackableComponent,
|
AbstractTrackableComponent,
|
||||||
ComcolMetadataComponent,
|
ComcolMetadataComponent,
|
||||||
TypeBadgeComponent,
|
TypeBadgeComponent,
|
||||||
AccessStatusBadgeComponent,
|
AccessStatusBadgeComponent,
|
||||||
BrowseByComponent,
|
|
||||||
AbstractTrackableComponent,
|
|
||||||
|
|
||||||
ItemSelectComponent,
|
ItemSelectComponent,
|
||||||
CollectionSelectComponent,
|
CollectionSelectComponent,
|
||||||
MetadataRepresentationLoaderComponent,
|
MetadataRepresentationLoaderComponent,
|
||||||
SelectableListItemControlComponent,
|
SelectableListItemControlComponent,
|
||||||
|
|
||||||
ImportableListItemControlComponent,
|
ImportableListItemControlComponent,
|
||||||
|
|
||||||
LogInShibbolethComponent,
|
|
||||||
LogInOidcComponent,
|
|
||||||
LogInOrcidComponent,
|
|
||||||
LogInPasswordComponent,
|
|
||||||
LogInContainerComponent,
|
LogInContainerComponent,
|
||||||
ItemVersionsComponent,
|
ItemVersionsComponent,
|
||||||
ItemSearchResultListElementComponent,
|
|
||||||
ItemVersionsNoticeComponent,
|
ItemVersionsNoticeComponent,
|
||||||
ModifyItemOverviewComponent,
|
ModifyItemOverviewComponent,
|
||||||
ImpersonateNavbarComponent,
|
ImpersonateNavbarComponent,
|
||||||
FileDownloadLinkComponent,
|
|
||||||
BitstreamDownloadPageComponent,
|
|
||||||
BitstreamRequestACopyPageComponent,
|
|
||||||
CollectionDropdownComponent,
|
|
||||||
EntityDropdownComponent,
|
EntityDropdownComponent,
|
||||||
ExportMetadataSelectorComponent,
|
ExportMetadataSelectorComponent,
|
||||||
ImportBatchSelectorComponent,
|
ImportBatchSelectorComponent,
|
||||||
ExportBatchSelectorComponent,
|
ExportBatchSelectorComponent,
|
||||||
ConfirmationModalComponent,
|
ConfirmationModalComponent,
|
||||||
VocabularyTreeviewComponent,
|
|
||||||
AuthorizedCollectionSelectorComponent,
|
AuthorizedCollectionSelectorComponent,
|
||||||
CurationFormComponent,
|
|
||||||
SearchResultListElementComponent,
|
|
||||||
SearchResultGridElementComponent,
|
|
||||||
ItemListElementComponent,
|
|
||||||
ItemGridElementComponent,
|
|
||||||
ItemSearchResultGridElementComponent,
|
|
||||||
BrowseEntryListElementComponent,
|
|
||||||
SearchResultDetailElementComponent,
|
|
||||||
PlainTextMetadataListElementComponent,
|
|
||||||
ItemMetadataListElementComponent,
|
|
||||||
MetadataRepresentationListElementComponent,
|
|
||||||
ItemMetadataRepresentationListElementComponent,
|
|
||||||
BundleListElementComponent,
|
|
||||||
StartsWithDateComponent,
|
|
||||||
StartsWithTextComponent,
|
|
||||||
SidebarSearchListElementComponent,
|
|
||||||
PublicationSidebarSearchListElementComponent,
|
|
||||||
CollectionSidebarSearchListElementComponent,
|
|
||||||
CommunitySidebarSearchListElementComponent,
|
|
||||||
SearchNavbarComponent,
|
SearchNavbarComponent,
|
||||||
ScopeSelectorModalComponent,
|
|
||||||
ItemPageTitleFieldComponent,
|
ItemPageTitleFieldComponent,
|
||||||
ThemedSearchNavbarComponent,
|
ThemedSearchNavbarComponent,
|
||||||
ListableNotificationObjectComponent,
|
ListableNotificationObjectComponent,
|
||||||
@@ -566,6 +488,7 @@ const ENTRY_COMPONENTS = [
|
|||||||
ClaimedTaskActionsReturnToPoolComponent,
|
ClaimedTaskActionsReturnToPoolComponent,
|
||||||
ClaimedTaskActionsEditMetadataComponent,
|
ClaimedTaskActionsEditMetadataComponent,
|
||||||
CollectionDropdownComponent,
|
CollectionDropdownComponent,
|
||||||
|
ThemedCollectionDropdownComponent,
|
||||||
FileDownloadLinkComponent,
|
FileDownloadLinkComponent,
|
||||||
BitstreamDownloadPageComponent,
|
BitstreamDownloadPageComponent,
|
||||||
BitstreamRequestACopyPageComponent,
|
BitstreamRequestACopyPageComponent,
|
||||||
@@ -574,16 +497,11 @@ const ENTRY_COMPONENTS = [
|
|||||||
ImportBatchSelectorComponent,
|
ImportBatchSelectorComponent,
|
||||||
ExportBatchSelectorComponent,
|
ExportBatchSelectorComponent,
|
||||||
ConfirmationModalComponent,
|
ConfirmationModalComponent,
|
||||||
VocabularyTreeviewComponent,
|
|
||||||
SidebarSearchListElementComponent,
|
SidebarSearchListElementComponent,
|
||||||
PublicationSidebarSearchListElementComponent,
|
PublicationSidebarSearchListElementComponent,
|
||||||
CollectionSidebarSearchListElementComponent,
|
CollectionSidebarSearchListElementComponent,
|
||||||
CommunitySidebarSearchListElementComponent,
|
CommunitySidebarSearchListElementComponent,
|
||||||
LinkMenuItemComponent,
|
|
||||||
OnClickMenuItemComponent,
|
|
||||||
TextMenuItemComponent,
|
|
||||||
ScopeSelectorModalComponent,
|
ScopeSelectorModalComponent,
|
||||||
ExternalLinkMenuItemComponent,
|
|
||||||
ListableNotificationObjectComponent,
|
ListableNotificationObjectComponent,
|
||||||
];
|
];
|
||||||
|
|
||||||
@@ -612,7 +530,6 @@ const DIRECTIVES = [
|
|||||||
DragClickDirective,
|
DragClickDirective,
|
||||||
DebounceDirective,
|
DebounceDirective,
|
||||||
ClickOutsideDirective,
|
ClickOutsideDirective,
|
||||||
AuthorityConfidenceStateDirective,
|
|
||||||
InListValidator,
|
InListValidator,
|
||||||
AutoFocusDirective,
|
AutoFocusDirective,
|
||||||
RoleDirective,
|
RoleDirective,
|
||||||
@@ -635,6 +552,7 @@ const DIRECTIVES = [
|
|||||||
declarations: [
|
declarations: [
|
||||||
...PIPES,
|
...PIPES,
|
||||||
...COMPONENTS,
|
...COMPONENTS,
|
||||||
|
...ENTRY_COMPONENTS,
|
||||||
...DIRECTIVES,
|
...DIRECTIVES,
|
||||||
...SHARED_ITEM_PAGE_COMPONENTS,
|
...SHARED_ITEM_PAGE_COMPONENTS,
|
||||||
ItemVersionsSummaryModalComponent,
|
ItemVersionsSummaryModalComponent,
|
||||||
@@ -647,9 +565,10 @@ const DIRECTIVES = [
|
|||||||
...MODULES,
|
...MODULES,
|
||||||
...PIPES,
|
...PIPES,
|
||||||
...COMPONENTS,
|
...COMPONENTS,
|
||||||
|
...ENTRY_COMPONENTS,
|
||||||
...SHARED_ITEM_PAGE_COMPONENTS,
|
...SHARED_ITEM_PAGE_COMPONENTS,
|
||||||
...DIRECTIVES,
|
...DIRECTIVES,
|
||||||
TranslateModule
|
TranslateModule,
|
||||||
]
|
]
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@@ -71,6 +71,12 @@ describe('ThemedComponent', () => {
|
|||||||
expect((component as any).compRef.instance.testInput).toEqual('changed');
|
expect((component as any).compRef.instance.testInput).toEqual('changed');
|
||||||
});
|
});
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
it(`should set usedTheme to the name of the matched theme`, waitForAsync(() => {
|
||||||
|
fixture.whenStable().then(() => {
|
||||||
|
expect(component.usedTheme).toEqual('custom');
|
||||||
|
});
|
||||||
|
}));
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('when the current theme doesn\'t match a themed component', () => {
|
describe('when the current theme doesn\'t match a themed component', () => {
|
||||||
@@ -92,6 +98,12 @@ describe('ThemedComponent', () => {
|
|||||||
expect((component as any).compRef.instance.testInput).toEqual('changed');
|
expect((component as any).compRef.instance.testInput).toEqual('changed');
|
||||||
});
|
});
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
it(`should set usedTheme to the name of the base theme`, waitForAsync(() => {
|
||||||
|
fixture.whenStable().then(() => {
|
||||||
|
expect(component.usedTheme).toEqual('base');
|
||||||
|
});
|
||||||
|
}));
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('and it extends another theme', () => {
|
describe('and it extends another theme', () => {
|
||||||
@@ -117,6 +129,12 @@ describe('ThemedComponent', () => {
|
|||||||
expect((component as any).compRef.instance.testInput).toEqual('changed');
|
expect((component as any).compRef.instance.testInput).toEqual('changed');
|
||||||
});
|
});
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
it(`should set usedTheme to the name of the base theme`, waitForAsync(() => {
|
||||||
|
fixture.whenStable().then(() => {
|
||||||
|
expect(component.usedTheme).toEqual('base');
|
||||||
|
});
|
||||||
|
}));
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('that does match it', () => {
|
describe('that does match it', () => {
|
||||||
@@ -141,6 +159,12 @@ describe('ThemedComponent', () => {
|
|||||||
expect((component as any).compRef.instance.testInput).toEqual('changed');
|
expect((component as any).compRef.instance.testInput).toEqual('changed');
|
||||||
});
|
});
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
it(`should set usedTheme to the name of the matched theme`, waitForAsync(() => {
|
||||||
|
fixture.whenStable().then(() => {
|
||||||
|
expect(component.usedTheme).toEqual('custom');
|
||||||
|
});
|
||||||
|
}));
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('that extends another theme that doesn\'t match it either', () => {
|
describe('that extends another theme that doesn\'t match it either', () => {
|
||||||
@@ -167,6 +191,12 @@ describe('ThemedComponent', () => {
|
|||||||
expect((component as any).compRef.instance.testInput).toEqual('changed');
|
expect((component as any).compRef.instance.testInput).toEqual('changed');
|
||||||
});
|
});
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
it(`should set usedTheme to the name of the base theme`, waitForAsync(() => {
|
||||||
|
fixture.whenStable().then(() => {
|
||||||
|
expect(component.usedTheme).toEqual('base');
|
||||||
|
});
|
||||||
|
}));
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('that extends another theme that does match it', () => {
|
describe('that extends another theme that does match it', () => {
|
||||||
@@ -193,6 +223,12 @@ describe('ThemedComponent', () => {
|
|||||||
expect((component as any).compRef.instance.testInput).toEqual('changed');
|
expect((component as any).compRef.instance.testInput).toEqual('changed');
|
||||||
});
|
});
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
it(`should set usedTheme to the name of the matched theme`, waitForAsync(() => {
|
||||||
|
fixture.whenStable().then(() => {
|
||||||
|
expect(component.usedTheme).toEqual('custom');
|
||||||
|
});
|
||||||
|
}));
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@@ -8,13 +8,15 @@ import {
|
|||||||
OnDestroy,
|
OnDestroy,
|
||||||
ComponentFactoryResolver,
|
ComponentFactoryResolver,
|
||||||
ChangeDetectorRef,
|
ChangeDetectorRef,
|
||||||
OnChanges
|
OnChanges,
|
||||||
|
HostBinding
|
||||||
} from '@angular/core';
|
} from '@angular/core';
|
||||||
import { hasValue, isNotEmpty } from '../empty.util';
|
import { hasValue, isNotEmpty } from '../empty.util';
|
||||||
import { from as fromPromise, Observable, of as observableOf, Subscription } from 'rxjs';
|
import { from as fromPromise, Observable, of as observableOf, Subscription, BehaviorSubject } from 'rxjs';
|
||||||
import { ThemeService } from './theme.service';
|
import { ThemeService } from './theme.service';
|
||||||
import { catchError, switchMap, map } from 'rxjs/operators';
|
import { catchError, switchMap, map, tap } from 'rxjs/operators';
|
||||||
import { GenericConstructor } from '../../core/shared/generic-constructor';
|
import { GenericConstructor } from '../../core/shared/generic-constructor';
|
||||||
|
import { BASE_THEME_NAME } from './theme.constants';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'ds-themed',
|
selector: 'ds-themed',
|
||||||
@@ -25,11 +27,22 @@ export abstract class ThemedComponent<T> implements OnInit, OnDestroy, OnChanges
|
|||||||
@ViewChild('vcr', { read: ViewContainerRef }) vcr: ViewContainerRef;
|
@ViewChild('vcr', { read: ViewContainerRef }) vcr: ViewContainerRef;
|
||||||
protected compRef: ComponentRef<T>;
|
protected compRef: ComponentRef<T>;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A reference to the themed component. Will start as undefined and emit every time the themed
|
||||||
|
* component is rendered
|
||||||
|
*/
|
||||||
|
public compRef$: BehaviorSubject<ComponentRef<T>> = new BehaviorSubject(undefined);
|
||||||
|
|
||||||
protected lazyLoadSub: Subscription;
|
protected lazyLoadSub: Subscription;
|
||||||
protected themeSub: Subscription;
|
protected themeSub: Subscription;
|
||||||
|
|
||||||
protected inAndOutputNames: (keyof T & keyof this)[] = [];
|
protected inAndOutputNames: (keyof T & keyof this)[] = [];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A data attribute on the ThemedComponent to indicate which theme the rendered component came from.
|
||||||
|
*/
|
||||||
|
@HostBinding('attr.data-used-theme') usedTheme: string;
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
protected resolver: ComponentFactoryResolver,
|
protected resolver: ComponentFactoryResolver,
|
||||||
protected cdr: ChangeDetectorRef,
|
protected cdr: ChangeDetectorRef,
|
||||||
@@ -80,6 +93,7 @@ export abstract class ThemedComponent<T> implements OnInit, OnDestroy, OnChanges
|
|||||||
} else {
|
} else {
|
||||||
// otherwise import and return the default component
|
// otherwise import and return the default component
|
||||||
return fromPromise(this.importUnthemedComponent()).pipe(
|
return fromPromise(this.importUnthemedComponent()).pipe(
|
||||||
|
tap(() => this.usedTheme = BASE_THEME_NAME),
|
||||||
map((unthemedFile: any) => {
|
map((unthemedFile: any) => {
|
||||||
return unthemedFile[this.getComponentName()];
|
return unthemedFile[this.getComponentName()];
|
||||||
})
|
})
|
||||||
@@ -90,6 +104,7 @@ export abstract class ThemedComponent<T> implements OnInit, OnDestroy, OnChanges
|
|||||||
const factory = this.resolver.resolveComponentFactory(constructor);
|
const factory = this.resolver.resolveComponentFactory(constructor);
|
||||||
this.compRef = this.vcr.createComponent(factory);
|
this.compRef = this.vcr.createComponent(factory);
|
||||||
this.connectInputsAndOutputs();
|
this.connectInputsAndOutputs();
|
||||||
|
this.compRef$.next(this.compRef);
|
||||||
this.cdr.markForCheck();
|
this.cdr.markForCheck();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -123,6 +138,7 @@ export abstract class ThemedComponent<T> implements OnInit, OnDestroy, OnChanges
|
|||||||
private resolveThemedComponent(themeName?: string, checkedThemeNames: string[] = []): Observable<any> {
|
private resolveThemedComponent(themeName?: string, checkedThemeNames: string[] = []): Observable<any> {
|
||||||
if (isNotEmpty(themeName)) {
|
if (isNotEmpty(themeName)) {
|
||||||
return fromPromise(this.importThemedComponent(themeName)).pipe(
|
return fromPromise(this.importThemedComponent(themeName)).pipe(
|
||||||
|
tap(() => this.usedTheme = themeName),
|
||||||
catchError(() => {
|
catchError(() => {
|
||||||
// Try the next ancestor theme instead
|
// Try the next ancestor theme instead
|
||||||
const nextTheme = this.themeService.getThemeConfigFor(themeName)?.extends;
|
const nextTheme = this.themeService.getThemeConfigFor(themeName)?.extends;
|
||||||
|
38
src/app/shared/upload/upload.module.ts
Normal file
38
src/app/shared/upload/upload.module.ts
Normal file
@@ -0,0 +1,38 @@
|
|||||||
|
/**
|
||||||
|
* The contents of this file are subject to the license and copyright
|
||||||
|
* detailed in the LICENSE and NOTICE files at the root of the source
|
||||||
|
* tree and available online at
|
||||||
|
*
|
||||||
|
* http://www.dspace.org/license/
|
||||||
|
*/
|
||||||
|
import { NgModule } from '@angular/core';
|
||||||
|
import { CommonModule } from '@angular/common';
|
||||||
|
import { SharedModule } from '../shared.module';
|
||||||
|
import { FileUploadModule } from 'ng2-file-upload';
|
||||||
|
import { UploaderComponent } from './uploader/uploader.component';
|
||||||
|
import { FileDropzoneNoUploaderComponent } from './file-dropzone-no-uploader/file-dropzone-no-uploader.component';
|
||||||
|
|
||||||
|
const COMPONENTS = [
|
||||||
|
UploaderComponent,
|
||||||
|
FileDropzoneNoUploaderComponent,
|
||||||
|
];
|
||||||
|
|
||||||
|
@NgModule({
|
||||||
|
imports: [
|
||||||
|
CommonModule,
|
||||||
|
SharedModule,
|
||||||
|
FileUploadModule,
|
||||||
|
],
|
||||||
|
declarations: [
|
||||||
|
...COMPONENTS,
|
||||||
|
],
|
||||||
|
providers: [
|
||||||
|
...COMPONENTS,
|
||||||
|
],
|
||||||
|
exports: [
|
||||||
|
...COMPONENTS,
|
||||||
|
FileUploadModule,
|
||||||
|
]
|
||||||
|
})
|
||||||
|
export class UploadModule {
|
||||||
|
}
|
@@ -1,4 +1,4 @@
|
|||||||
import { RestRequestMethod } from '../../core/data/rest-request-method';
|
import { RestRequestMethod } from '../../../core/data/rest-request-method';
|
||||||
|
|
||||||
export class UploaderOptions {
|
export class UploaderOptions {
|
||||||
/**
|
/**
|
@@ -1,4 +1,4 @@
|
|||||||
import { MetadataMap } from '../../core/shared/metadata.models';
|
import { MetadataMap } from '../../../core/shared/metadata.models';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Properties to send to the REST API for uploading a bitstream
|
* Properties to send to the REST API for uploading a bitstream
|
@@ -4,16 +4,16 @@ import { ComponentFixture, inject, TestBed, waitForAsync, } from '@angular/core/
|
|||||||
|
|
||||||
import { ScrollToService } from '@nicky-lenaers/ngx-scroll-to';
|
import { ScrollToService } from '@nicky-lenaers/ngx-scroll-to';
|
||||||
|
|
||||||
import { UploaderService } from './uploader.service';
|
import { DragService } from '../../../core/drag.service';
|
||||||
import { UploaderOptions } from './uploader-options.model';
|
import { UploaderOptions } from './uploader-options.model';
|
||||||
import { UploaderComponent } from './uploader.component';
|
import { UploaderComponent } from './uploader.component';
|
||||||
import { FileUploadModule } from 'ng2-file-upload';
|
import { FileUploadModule } from 'ng2-file-upload';
|
||||||
import { TranslateModule } from '@ngx-translate/core';
|
import { TranslateModule } from '@ngx-translate/core';
|
||||||
import { createTestComponent } from '../testing/utils.test';
|
import { createTestComponent } from '../../testing/utils.test';
|
||||||
import { HttpXsrfTokenExtractor } from '@angular/common/http';
|
import { HttpXsrfTokenExtractor } from '@angular/common/http';
|
||||||
import { CookieService } from '../../core/services/cookie.service';
|
import { CookieService } from '../../../core/services/cookie.service';
|
||||||
import { CookieServiceMock } from '../mocks/cookie.service.mock';
|
import { CookieServiceMock } from '../../mocks/cookie.service.mock';
|
||||||
import { HttpXsrfTokenExtractorMock } from '../mocks/http-xsrf-token-extractor.mock';
|
import { HttpXsrfTokenExtractorMock } from '../../mocks/http-xsrf-token-extractor.mock';
|
||||||
|
|
||||||
describe('Chips component', () => {
|
describe('Chips component', () => {
|
||||||
|
|
||||||
@@ -37,7 +37,7 @@ describe('Chips component', () => {
|
|||||||
ChangeDetectorRef,
|
ChangeDetectorRef,
|
||||||
ScrollToService,
|
ScrollToService,
|
||||||
UploaderComponent,
|
UploaderComponent,
|
||||||
UploaderService,
|
DragService,
|
||||||
{ provide: HttpXsrfTokenExtractor, useValue: new HttpXsrfTokenExtractorMock('mock-token') },
|
{ provide: HttpXsrfTokenExtractor, useValue: new HttpXsrfTokenExtractorMock('mock-token') },
|
||||||
{ provide: CookieService, useValue: new CookieServiceMock() },
|
{ provide: CookieService, useValue: new CookieServiceMock() },
|
||||||
],
|
],
|
@@ -6,12 +6,12 @@ import uniqueId from 'lodash/uniqueId';
|
|||||||
import { ScrollToService } from '@nicky-lenaers/ngx-scroll-to';
|
import { ScrollToService } from '@nicky-lenaers/ngx-scroll-to';
|
||||||
|
|
||||||
import { UploaderOptions } from './uploader-options.model';
|
import { UploaderOptions } from './uploader-options.model';
|
||||||
import { hasValue, isNotEmpty, isUndefined } from '../empty.util';
|
import { hasValue, isNotEmpty, isUndefined } from '../../empty.util';
|
||||||
import { UploaderService } from './uploader.service';
|
|
||||||
import { UploaderProperties } from './uploader-properties.model';
|
import { UploaderProperties } from './uploader-properties.model';
|
||||||
import { HttpXsrfTokenExtractor } from '@angular/common/http';
|
import { HttpXsrfTokenExtractor } from '@angular/common/http';
|
||||||
import { XSRF_COOKIE, XSRF_REQUEST_HEADER, XSRF_RESPONSE_HEADER } from '../../core/xsrf/xsrf.interceptor';
|
import { XSRF_COOKIE, XSRF_REQUEST_HEADER, XSRF_RESPONSE_HEADER } from '../../../core/xsrf/xsrf.interceptor';
|
||||||
import { CookieService } from '../../core/services/cookie.service';
|
import { CookieService } from '../../../core/services/cookie.service';
|
||||||
|
import { DragService } from '../../../core/drag.service';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'ds-uploader',
|
selector: 'ds-uploader',
|
||||||
@@ -76,7 +76,7 @@ export class UploaderComponent {
|
|||||||
@HostListener('window:dragover', ['$event'])
|
@HostListener('window:dragover', ['$event'])
|
||||||
onDragOver(event: any) {
|
onDragOver(event: any) {
|
||||||
|
|
||||||
if (this.enableDragOverDocument && this.uploaderService.isAllowedDragOverPage()) {
|
if (this.enableDragOverDocument && this.dragService.isAllowedDragOverPage()) {
|
||||||
// Show drop area on the page
|
// Show drop area on the page
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
if ((event.target as any).tagName !== 'HTML') {
|
if ((event.target as any).tagName !== 'HTML') {
|
||||||
@@ -85,9 +85,13 @@ export class UploaderComponent {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
constructor(private cdr: ChangeDetectorRef, private scrollToService: ScrollToService,
|
constructor(
|
||||||
private uploaderService: UploaderService, private tokenExtractor: HttpXsrfTokenExtractor,
|
private cdr: ChangeDetectorRef,
|
||||||
private cookieService: CookieService) {
|
private scrollToService: ScrollToService,
|
||||||
|
private dragService: DragService,
|
||||||
|
private tokenExtractor: HttpXsrfTokenExtractor,
|
||||||
|
private cookieService: CookieService
|
||||||
|
) {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
@@ -10,7 +10,7 @@
|
|||||||
<tbody>
|
<tbody>
|
||||||
|
|
||||||
<tr>
|
<tr>
|
||||||
<th scope="col"></th>
|
<td></td>
|
||||||
<th scope="col"
|
<th scope="col"
|
||||||
*ngFor="let header of headers"
|
*ngFor="let header of headers"
|
||||||
class="{{header}}-header">
|
class="{{header}}-header">
|
||||||
|
@@ -35,9 +35,9 @@
|
|||||||
class="dropdown-menu"
|
class="dropdown-menu"
|
||||||
id="collectionControlsDropdownMenu"
|
id="collectionControlsDropdownMenu"
|
||||||
aria-labelledby="collectionControlsMenuButton">
|
aria-labelledby="collectionControlsMenuButton">
|
||||||
<ds-collection-dropdown
|
<ds-themed-collection-dropdown
|
||||||
(selectionChange)="onSelect($event)">
|
(selectionChange)="onSelect($event)">
|
||||||
</ds-collection-dropdown>
|
</ds-themed-collection-dropdown>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@@ -10,7 +10,7 @@ import { SubmissionObject } from '../../core/submission/models/submission-object
|
|||||||
import { WorkspaceitemSectionsObject } from '../../core/submission/models/workspaceitem-sections.model';
|
import { WorkspaceitemSectionsObject } from '../../core/submission/models/workspaceitem-sections.model';
|
||||||
|
|
||||||
import { hasValue, isNotEmpty } from '../../shared/empty.util';
|
import { hasValue, isNotEmpty } from '../../shared/empty.util';
|
||||||
import { UploaderOptions } from '../../shared/uploader/uploader-options.model';
|
import { UploaderOptions } from '../../shared/upload/uploader/uploader-options.model';
|
||||||
import { SubmissionObjectEntry } from '../objects/submission-objects.reducer';
|
import { SubmissionObjectEntry } from '../objects/submission-objects.reducer';
|
||||||
import { SectionDataObject } from '../sections/models/section-data.model';
|
import { SectionDataObject } from '../sections/models/section-data.model';
|
||||||
import { SubmissionService } from '../submission.service';
|
import { SubmissionService } from '../submission.service';
|
||||||
|
@@ -28,7 +28,7 @@ import { SubmissionJsonPatchOperationsServiceStub } from '../../../shared/testin
|
|||||||
import { SubmissionJsonPatchOperationsService } from '../../../core/submission/submission-json-patch-operations.service';
|
import { SubmissionJsonPatchOperationsService } from '../../../core/submission/submission-json-patch-operations.service';
|
||||||
import { SharedModule } from '../../../shared/shared.module';
|
import { SharedModule } from '../../../shared/shared.module';
|
||||||
import { createTestComponent } from '../../../shared/testing/utils.test';
|
import { createTestComponent } from '../../../shared/testing/utils.test';
|
||||||
import { UploaderOptions } from '../../../shared/uploader/uploader-options.model';
|
import { UploaderOptions } from '../../../shared/upload/uploader/uploader-options.model';
|
||||||
|
|
||||||
describe('SubmissionUploadFilesComponent Component', () => {
|
describe('SubmissionUploadFilesComponent Component', () => {
|
||||||
|
|
||||||
|
@@ -9,7 +9,7 @@ import { hasValue, isEmpty, isNotEmpty } from '../../../shared/empty.util';
|
|||||||
import { normalizeSectionData } from '../../../core/submission/submission-response-parsing.service';
|
import { normalizeSectionData } from '../../../core/submission/submission-response-parsing.service';
|
||||||
import { SubmissionService } from '../../submission.service';
|
import { SubmissionService } from '../../submission.service';
|
||||||
import { NotificationsService } from '../../../shared/notifications/notifications.service';
|
import { NotificationsService } from '../../../shared/notifications/notifications.service';
|
||||||
import { UploaderOptions } from '../../../shared/uploader/uploader-options.model';
|
import { UploaderOptions } from '../../../shared/upload/uploader/uploader-options.model';
|
||||||
import parseSectionErrors from '../../utils/parseSectionErrors';
|
import parseSectionErrors from '../../utils/parseSectionErrors';
|
||||||
import { SubmissionJsonPatchOperationsService } from '../../../core/submission/submission-json-patch-operations.service';
|
import { SubmissionJsonPatchOperationsService } from '../../../core/submission/submission-json-patch-operations.service';
|
||||||
import { WorkspaceItem } from '../../../core/submission/models/workspaceitem.model';
|
import { WorkspaceItem } from '../../../core/submission/models/workspaceitem.model';
|
||||||
|
@@ -6,11 +6,11 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="modal-body">
|
<div class="modal-body">
|
||||||
<ds-themed-loading *ngIf="isLoading()"></ds-themed-loading>
|
<ds-themed-loading *ngIf="isLoading()"></ds-themed-loading>
|
||||||
<ds-collection-dropdown [ngClass]="{'d-none': isLoading()}"
|
<ds-themed-collection-dropdown [ngClass]="{'d-none': isLoading()}"
|
||||||
(selectionChange)="selectObject($event)"
|
(selectionChange)="selectObject($event)"
|
||||||
(searchComplete)="searchComplete()"
|
(searchComplete)="searchComplete()"
|
||||||
(theOnlySelectable)="theOnlySelectable($event)"
|
(theOnlySelectable)="theOnlySelectable($event)"
|
||||||
[entityType]="entityType">
|
[entityType]="entityType">
|
||||||
</ds-collection-dropdown>
|
</ds-themed-collection-dropdown>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@@ -122,7 +122,7 @@ describe('SubmissionImportExternalCollectionComponent test suite', () => {
|
|||||||
fixture.detectChanges();
|
fixture.detectChanges();
|
||||||
|
|
||||||
fixture.whenStable().then(() => {
|
fixture.whenStable().then(() => {
|
||||||
const dropdownMenu = fixture.debugElement.query(By.css('ds-collection-dropdown')).nativeElement;
|
const dropdownMenu = fixture.debugElement.query(By.css('ds-themed-collection-dropdown')).nativeElement;
|
||||||
expect(dropdownMenu.classList).toContain('d-none');
|
expect(dropdownMenu.classList).toContain('d-none');
|
||||||
});
|
});
|
||||||
}));
|
}));
|
||||||
|
@@ -60,9 +60,11 @@ import { PublisherPolicyComponent } from './sections/sherpa-policies/publisher-p
|
|||||||
import {
|
import {
|
||||||
PublicationInformationComponent
|
PublicationInformationComponent
|
||||||
} from './sections/sherpa-policies/publication-information/publication-information.component';
|
} from './sections/sherpa-policies/publication-information/publication-information.component';
|
||||||
|
import { UploadModule } from '../shared/upload/upload.module';
|
||||||
import {
|
import {
|
||||||
MetadataInformationComponent
|
MetadataInformationComponent
|
||||||
} from './sections/sherpa-policies/metadata-information/metadata-information.component';
|
} from './sections/sherpa-policies/metadata-information/metadata-information.component';
|
||||||
|
import { SectionFormOperationsService } from './sections/form/section-form-operations.service';
|
||||||
|
|
||||||
const ENTRY_COMPONENTS = [
|
const ENTRY_COMPONENTS = [
|
||||||
// put only entry components that use custom decorator
|
// put only entry components that use custom decorator
|
||||||
@@ -114,16 +116,21 @@ const DECLARATIONS = [
|
|||||||
FormModule,
|
FormModule,
|
||||||
NgbModalModule,
|
NgbModalModule,
|
||||||
NgbCollapseModule,
|
NgbCollapseModule,
|
||||||
NgbAccordionModule
|
NgbAccordionModule,
|
||||||
|
UploadModule,
|
||||||
],
|
],
|
||||||
declarations: DECLARATIONS,
|
declarations: DECLARATIONS,
|
||||||
exports: DECLARATIONS,
|
exports: [
|
||||||
|
...DECLARATIONS,
|
||||||
|
FormModule,
|
||||||
|
],
|
||||||
providers: [
|
providers: [
|
||||||
SectionUploadService,
|
SectionUploadService,
|
||||||
SectionsService,
|
SectionsService,
|
||||||
SubmissionUploadsConfigDataService,
|
SubmissionUploadsConfigDataService,
|
||||||
SubmissionAccessesConfigDataService,
|
SubmissionAccessesConfigDataService,
|
||||||
SectionAccessesService,
|
SectionAccessesService,
|
||||||
|
SectionFormOperationsService,
|
||||||
]
|
]
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@@ -3,6 +3,7 @@ import { NgModule } from '@angular/core';
|
|||||||
import { SharedModule } from '../shared/shared.module';
|
import { SharedModule } from '../shared/shared.module';
|
||||||
import { SubmitPageRoutingModule } from './submit-page-routing.module';
|
import { SubmitPageRoutingModule } from './submit-page-routing.module';
|
||||||
import { SubmissionModule } from '../submission/submission.module';
|
import { SubmissionModule } from '../submission/submission.module';
|
||||||
|
import { FormModule } from '../shared/form/form.module';
|
||||||
|
|
||||||
@NgModule({
|
@NgModule({
|
||||||
imports: [
|
imports: [
|
||||||
@@ -10,6 +11,7 @@ import { SubmissionModule } from '../submission/submission.module';
|
|||||||
CommonModule,
|
CommonModule,
|
||||||
SharedModule,
|
SharedModule,
|
||||||
SubmissionModule,
|
SubmissionModule,
|
||||||
|
FormModule,
|
||||||
],
|
],
|
||||||
})
|
})
|
||||||
/**
|
/**
|
||||||
|
@@ -12,7 +12,7 @@ img {
|
|||||||
display: block;
|
display: block;
|
||||||
content: "";
|
content: "";
|
||||||
width: 100%;
|
width: 100%;
|
||||||
padding-top: (297 / 210) * 100%; // A4 ratio
|
padding-top: calc((297 / 210) * 100%); // A4 ratio
|
||||||
}
|
}
|
||||||
> .inner {
|
> .inner {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user