1
0

Merge branch 'main' into CST-3620

# Conflicts:
#	src/app/+my-dspace-page/my-dspace-page.module.ts
#	src/app/core/tasks/tasks.service.ts
#	src/app/shared/mydspace-actions/claimed-task/abstract/claimed-task-actions-abstract.component.ts
#	src/app/shared/mydspace-actions/claimed-task/approve/claimed-task-actions-approve.component.spec.ts
#	src/app/shared/mydspace-actions/claimed-task/edit-metadata/claimed-task-actions-edit-metadata.component.spec.ts
#	src/app/shared/mydspace-actions/claimed-task/reject/claimed-task-actions-reject.component.spec.ts
#	src/app/shared/mydspace-actions/claimed-task/return-to-pool/claimed-task-actions-return-to-pool.component.spec.ts
#	src/app/shared/mydspace-actions/claimed-task/switcher/claimed-task-actions-loader.component.spec.ts
#	src/app/shared/mydspace-actions/claimed-task/switcher/claimed-task-actions-loader.component.ts
#	src/app/shared/mydspace-actions/mydspace-actions.ts
#	src/app/shared/mydspace-actions/pool-task/pool-task-actions.component.spec.ts
#	src/app/shared/object-collection/shared/listable-object/listable-object-component-loader.component.spec.ts
#	src/app/shared/object-collection/shared/listable-object/listable-object-component-loader.component.ts
#	src/app/shared/object-detail/my-dspace-result-detail-element/claimed-task-search-result/claimed-task-search-result-detail-element.component.spec.ts
#	src/app/shared/object-detail/my-dspace-result-detail-element/pool-search-result/pool-search-result-detail-element.component.spec.ts
#	src/app/shared/object-list/my-dspace-result-list-element/claimed-search-result/claimed-search-result-list-element.component.spec.ts
#	src/app/shared/object-list/my-dspace-result-list-element/item-search-result/item-search-result-list-element-submission.component.spec.ts
#	src/app/shared/object-list/my-dspace-result-list-element/pool-search-result/pool-search-result-list-element.component.spec.ts
#	src/app/shared/object-list/my-dspace-result-list-element/workflow-item-search-result/workflow-item-search-result-list-element.component.spec.ts
#	src/app/shared/object-list/my-dspace-result-list-element/workspace-item-search-result/workspace-item-search-result-list-element.component.spec.ts
This commit is contained in:
Alessandro Martelli
2021-01-29 16:02:07 +01:00
1090 changed files with 11660 additions and 9745 deletions

View File

@@ -104,7 +104,7 @@ DSPACE_REST_SSL # Whether the angular REST uses SSL [true/false]
The same settings can also be overwritten by setting system environment variables instead, E.g.:
```bash
export DSPACE_HOST=dspace7.4science.cloud
export DSPACE_HOST=api7.dspace.org
```
The priority works as follows: **environment variable** overrides **variable in `.env` file** overrides **`environment.(prod, dev or test).ts`** overrides **`environment.common.ts`**

View File

@@ -17,18 +17,30 @@
"build": {
"builder": "@angular-builders/custom-webpack:browser",
"options": {
"preserveSymlinks": true,
"customWebpackConfig": {
"path": "./webpack/webpack.browser.ts",
"mergeStrategies": {
"loaders": "prepend"
}
},
"allowedCommonJsDependencies": [
"angular2-text-mask",
"cerialize",
"core-js",
"lodash",
"jwt-decode",
"url-parse",
"uuid",
"webfontloader",
"zone.js"
],
"outputPath": "dist/browser",
"index": "src/index.html",
"main": "src/main.browser.ts",
"polyfills": "src/polyfills.ts",
"tsConfig": "tsconfig.app.json",
"aot": false,
"aot": true,
"assets": [
"src/assets",
"src/robots.txt"
@@ -56,8 +68,8 @@
},
{
"type": "anyComponentStyle",
"maximumWarning": "6kb",
"maximumError": "10kb"
"maximumWarning": "200kb",
"maximumError": "300kb"
}
]
}
@@ -156,6 +168,33 @@
}
}
}
},
"serve-ssr": {
"builder": "@nguniversal/builders:ssr-dev-server",
"options": {
"browserTarget": "dspace-angular:build",
"serverTarget": "dspace-angular:server",
"port": 4000
},
"configurations": {
"production": {
"browserTarget": "dspace-angular:build:production",
"serverTarget": "dspace-angular:server:production"
}
}
},
"prerender": {
"builder": "@nguniversal/builders:prerender",
"options": {
"browserTarget": "dspace-angular:build:production",
"serverTarget": "dspace-angular:server:production",
"routes": [
"/"
]
},
"configurations": {
"production": {}
}
}
}
}

View File

@@ -39,7 +39,7 @@ export const environment = {
// The REST API server settings.
rest: {
ssl: true,
host: 'dspace7.4science.cloud',
host: 'api7.dspace.org',
port: 443,
// NOTE: Space is capitalized because 'namespace' is a reserved string in TypeScript
nameSpace: '/server'
@@ -50,7 +50,7 @@ export const environment = {
Alternately you can set the following environment variables. If any of these are set, it will override all configuration files:
```
DSPACE_REST_SSL=true
DSPACE_REST_HOST=dspace7.4science.cloud
DSPACE_REST_HOST=api7.dspace.org
DSPACE_REST_PORT=443
DSPACE_REST_NAMESPACE=/server
```

View File

@@ -15,7 +15,7 @@ export class ProtractorPage {
}
waitUntilNotLoading(): promise.Promise<unknown> {
const loading = element(by.css('.loader'))
const loading = element(by.css('.loader'));
const EC = protractor.ExpectedConditions;
const notLoading = EC.not(EC.presenceOf(loading));
return browser.wait(notLoading, 10000);

View File

@@ -26,7 +26,7 @@ describe('protractor SearchPage', () => {
page.getCurrentScope()
.then((s: string) => {
expect<string>(s).toEqual(scopeString);
})
});
});
});
@@ -41,9 +41,9 @@ describe('protractor SearchPage', () => {
browser.wait(() => {
return browser.getCurrentUrl().then((url: string) => {
return url.indexOf('scope=' + encodeURI(scopeString)) !== -1;
})
})
})
});
});
});
});
});

View File

@@ -8,7 +8,7 @@
"moduleResolution": "node",
"outDir": "../dist/out-tsc-e2e",
"sourceMap": true,
"target": "es5",
"target": "es2018",
"typeRoots": [
"../node_modules/@types"
]

View File

@@ -23,14 +23,16 @@
"build": "ng build",
"build:prod": "yarn run build:ssr",
"build:ssr": "yarn run build:client-and-server-bundles && yarn run compile:server",
"build:client-and-server-bundles": "node --max_old_space_size=8192 node_modules/@angular/cli/bin/ng build --prod && ng run dspace-angular:server:production --bundleDependencies all",
"ng-high-memory": "node --max_old_space_size=8192 node_modules/@angular/cli/bin/ng",
"build:client-and-server-bundles": "npm run ng-high-memory -- build --prod && npm run ng-high-memory -- run dspace-angular:server:production --bundleDependencies true",
"test:watch": "npm-run-all --parallel config:test:watch test",
"test": "node --max_old_space_size=8192 node_modules/@angular/cli/bin/ng test --sourceMap=true --watch=true",
"test:headless": "node --max_old_space_size=8192 node_modules/@angular/cli/bin/ng test --watch=false --sourceMap=true --browsers=ChromeHeadless --code-coverage",
"test": "npm run ng-high-memory -- test --sourceMap=true --watch=true",
"test:headless": "npm run ng-high-memory -- test --watch=false --sourceMap=true --browsers=ChromeHeadless --code-coverage",
"lint": "ng lint",
"lint-fix": "npm run ng-high-memory -- lint --fix=true",
"e2e": "ng e2e",
"e2e:ci": "ng e2e --protractor-config=./e2e/protractor-ci.conf.js",
"compile:server": "webpack --config webpack.server.config.js --progress --colors",
"compile:server": "webpack --config webpack.server.config.js --progress --color",
"serve:ssr": "node dist/server",
"clean:coverage": "rimraf coverage",
"clean:dist": "rimraf dist",
@@ -42,7 +44,8 @@
"clean:prod": "yarn run clean:coverage && yarn run clean:doc && yarn run clean:dist && yarn run clean:log && yarn run clean:json && yarn run clean:bld",
"clean": "yarn run clean:prod && yarn run clean:env && yarn run clean:node",
"clean:env": "rimraf src/environments/environment.ts",
"sync-i18n": "yarn run config:dev && ts-node --project ./tsconfig.ts-node.json scripts/sync-i18n-files.ts"
"sync-i18n": "yarn run config:dev && ts-node --project ./tsconfig.ts-node.json scripts/sync-i18n-files.ts",
"postinstall": "ngcc"
},
"browser": {
"fs": false,
@@ -55,130 +58,130 @@
"minimist": "^1.2.5"
},
"dependencies": {
"@angular/animations": "~8.2.14",
"@angular/cdk": "8.2.3",
"@angular/common": "~8.2.14",
"@angular/compiler": "~8.2.14",
"@angular/core": "~8.2.14",
"@angular/forms": "~8.2.14",
"@angular/platform-browser": "~8.2.14",
"@angular/platform-browser-dynamic": "~8.2.14",
"@angular/platform-server": "~8.2.14",
"@angular/router": "~8.2.14",
"@angular/animations": "~10.2.3",
"@angular/cdk": "^10.2.6",
"@angular/common": "~10.2.3",
"@angular/compiler": "~10.2.3",
"@angular/core": "~10.2.3",
"@angular/forms": "~10.2.3",
"@angular/localize": "10.2.3",
"@angular/platform-browser": "~10.2.3",
"@angular/platform-browser-dynamic": "~10.2.3",
"@angular/platform-server": "~10.2.3",
"@angular/router": "~10.2.3",
"@angularclass/bootloader": "1.0.1",
"@ng-bootstrap/ng-bootstrap": "5.2.1",
"@ng-dynamic-forms/core": "8.1.1",
"@ng-dynamic-forms/ui-ng-bootstrap": "8.1.1",
"@ngrx/effects": "^8.6.0",
"@ngrx/router-store": "^8.6.0",
"@ngrx/store": "^8.6.0",
"@nguniversal/express-engine": "8.2.6",
"@nguniversal/module-map-ngfactory-loader": "v8.2.6",
"@ngx-translate/core": "11.0.1",
"@nicky-lenaers/ngx-scroll-to": "^3.0.1",
"@ng-bootstrap/ng-bootstrap": "7.0.0",
"@ng-dynamic-forms/core": "^12.0.0",
"@ng-dynamic-forms/ui-ng-bootstrap": "^12.0.0",
"@ngrx/effects": "^10.0.1",
"@ngrx/router-store": "^10.0.1",
"@ngrx/store": "^10.0.1",
"@nguniversal/express-engine": "10.1.0",
"@ngx-translate/core": "^13.0.0",
"@nicky-lenaers/ngx-scroll-to": "^9.0.0",
"angular-idle-preload": "3.0.0",
"angular2-text-mask": "9.0.0",
"angulartics2": "7.5.2",
"angulartics2": "^10.0.0",
"bootstrap": "4.3.1",
"caniuse-lite": "^1.0.30000697",
"caniuse-lite": "^1.0.30001165",
"cerialize": "0.1.18",
"cli-progress": "^3.8.0",
"cookie-parser": "1.4.3",
"core-js": "^3.6.4",
"cookie-parser": "1.4.5",
"core-js": "^3.7.0",
"debug-loader": "^0.0.1",
"deepmerge": "^4.2.2",
"express": "4.16.2",
"express": "^4.17.1",
"express-rate-limit": "^5.1.3",
"fast-json-patch": "^2.0.7",
"file-saver": "^1.3.8",
"fast-json-patch": "^3.0.0-1",
"file-saver": "^2.0.5",
"filesize": "^6.1.0",
"font-awesome": "4.7.0",
"https": "1.0.0",
"js-cookie": "2.2.0",
"json5": "^2.1.0",
"jsonschema": "1.2.2",
"jwt-decode": "^2.2.0",
"klaro": "^0.6.3",
"moment": "^2.22.1",
"morgan": "^1.9.1",
"ng-mocks": "^8.1.0",
"js-cookie": "2.2.1",
"json5": "^2.1.3",
"jsonschema": "1.4.0",
"jwt-decode": "^3.1.2",
"klaro": "^0.7.10",
"moment": "^2.29.1",
"morgan": "^1.10.0",
"ng-mocks": "10.5.4",
"ng2-file-upload": "1.4.0",
"ng2-nouislider": "^1.8.2",
"ngx-bootstrap": "^5.3.2",
"ngx-infinite-scroll": "6.0.1",
"ngx-moment": "^3.4.0",
"ngx-pagination": "3.0.3",
"ngx-sortablejs": "^3.1.4",
"nouislider": "^11.0.0",
"pem": "1.13.2",
"postcss-cli": "^6.0.0",
"ngx-infinite-scroll": "^10.0.1",
"ngx-moment": "^5.0.0",
"ngx-pagination": "5.0.0",
"ngx-sortablejs": "^10.0.0",
"nouislider": "^14.6.3",
"pem": "1.14.4",
"postcss-cli": "^8.3.0",
"reflect-metadata": "^0.1.13",
"rxjs": "~6.4.0",
"rxjs-spy": "^7.5.1",
"sass-resources-loader": "^2.0.0",
"sortablejs": "1.7.0",
"tslib": "^1.10.0",
"rxjs": "^6.6.3",
"rxjs-spy": "^7.5.3",
"sass-resources-loader": "^2.1.1",
"sortablejs": "1.10.1",
"tslib": "^2.0.0",
"webfontloader": "1.6.28",
"zone.js": "^0.9.1"
"zone.js": "^0.10.3"
},
"devDependencies": {
"@angular-builders/custom-webpack": "8.4.1",
"@angular-devkit/build-angular": "~0.803.25",
"@angular/cli": "~8.3.25",
"@angular/compiler-cli": "~8.2.14",
"@angular/language-service": "~8.2.14",
"@angular-builders/custom-webpack": "10.0.1",
"@angular-devkit/build-angular": "~0.1002.0",
"@angular/cli": "~10.2.0",
"@angular/compiler-cli": "~10.2.3",
"@angular/language-service": "~10.2.3",
"@fortawesome/fontawesome-free": "^5.5.0",
"@ngrx/store-devtools": "^8.6.0",
"@ngtools/webpack": "^8.3.25",
"@types/deep-freeze": "0.1.1",
"@types/express": "^4.17.0",
"@types/file-saver": "^1.3.0",
"@types/jasmine": "^3.3.9",
"@types/jasminewd2": "~2.0.3",
"@types/js-cookie": "2.1.0",
"@types/lodash": "^4.14.110",
"@types/node": "11.15.3",
"codelyzer": "^5.0.0",
"@ngrx/store-devtools": "^10.0.1",
"@ngtools/webpack": "10.2.0",
"@nguniversal/builders": "~10.1.0",
"@types/deep-freeze": "0.1.2",
"@types/express": "^4.17.9",
"@types/file-saver": "^2.0.1",
"@types/jasmine": "^3.6.2",
"@types/jasminewd2": "~2.0.8",
"@types/js-cookie": "2.2.6",
"@types/lodash": "^4.14.165",
"@types/node": "^14.14.9",
"codelyzer": "^6.0.1",
"compression-webpack-plugin": "^3.0.1",
"copy-webpack-plugin": "^5.1.1",
"css-loader": "3.4.0",
"cssnano": "^4.1.10",
"deep-freeze": "0.0.1",
"dotenv": "^8.2.0",
"fork-ts-checker-webpack-plugin": "^0.4.10",
"html-webpack-plugin": "^3.2.0",
"fork-ts-checker-webpack-plugin": "^6.0.3",
"html-webpack-plugin": "^4.5.0",
"http-proxy-middleware": "^1.0.5",
"jasmine-core": "^3.3.0",
"jasmine-marbles": "0.3.1",
"jasmine-spec-reporter": "~4.2.1",
"karma": "^5.0.9",
"karma-chrome-launcher": "~2.2.0",
"karma-coverage-istanbul-reporter": "~2.0.1",
"karma-jasmine": "2.0.1",
"karma-jasmine-html-reporter": "^1.4.0",
"jasmine-core": "^3.6.0",
"jasmine-marbles": "0.6.0",
"jasmine-spec-reporter": "^6.0.0",
"karma": "^5.2.3",
"karma-chrome-launcher": "^3.1.0",
"karma-coverage-istanbul-reporter": "~3.0.2",
"karma-jasmine": "^4.0.1",
"karma-jasmine-html-reporter": "^1.5.4",
"karma-mocha-reporter": "2.2.5",
"nodemon": "^2.0.2",
"npm-run-all": "^4.1.5",
"optimize-css-assets-webpack-plugin": "^5.0.1",
"optimize-css-assets-webpack-plugin": "^5.0.4",
"postcss-apply": "0.11.0",
"postcss-cssnext": "3.1.0",
"postcss-import": "^12.0.1",
"postcss-loader": "^3.0.0",
"postcss-preset-env": "6.7.0",
"postcss-responsive-type": "1.0.0",
"protractor": "^7.0.0",
"protractor-istanbul-plugin": "2.0.0",
"raw-loader": "0.5.1",
"rimraf": "^3.0.2",
"script-ext-html-webpack-plugin": "2.1.4",
"string-replace-loader": "^2.1.1",
"script-ext-html-webpack-plugin": "2.1.5",
"string-replace-loader": "^2.3.0",
"terser-webpack-plugin": "^2.3.1",
"ts-loader": "^5.2.0",
"ts-node": "^8.8.1",
"tslint": "~5.15.0",
"typescript": "~3.5.3",
"webpack": "^4.0.0",
"tslint": "^6.1.3",
"typescript": "~4.0.5",
"webpack": "^4.44.2",
"webpack-bundle-analyzer": "^3.3.2",
"webpack-cli": "^3.1.0",
"webpack-cli": "^4.2.0",
"webpack-node-externals": "1.7.2"
}
}

233
server.ts
View File

@@ -15,6 +15,7 @@
* import for `ngExpressEngine`.
*/
import 'zone.js/dist/zone-node';
import 'reflect-metadata';
import 'rxjs';
@@ -25,15 +26,15 @@ import * as morgan from 'morgan';
import * as express from 'express';
import * as bodyParser from 'body-parser';
import * as compression from 'compression';
import * as cookieParser from 'cookie-parser';
import { join } from 'path';
import { enableProdMode } from '@angular/core';
import { existsSync } from 'fs';
import { REQUEST, RESPONSE } from '@nguniversal/express-engine/tokens';
import { environment } from './src/environments/environment';
import { createProxyMiddleware } from 'http-proxy-middleware';
import { hasNoValue, hasValue } from './src/app/shared/empty.util';
import { hasValue, hasNoValue } from './src/app/shared/empty.util';
import { APP_BASE_HREF } from '@angular/common';
import { UIServerConfig } from './src/config/ui-server-config.interface';
/*
@@ -41,111 +42,112 @@ import { UIServerConfig } from './src/config/ui-server-config.interface';
*/
const DIST_FOLDER = join(process.cwd(), 'dist/browser');
const indexHtml = existsSync(join(DIST_FOLDER, 'index.html')) ? 'index.html' : 'index';
// * NOTE :: leave this as require() since this file is built Dynamically from webpack
const { ServerAppModuleNgFactory, LAZY_MODULE_MAP, ngExpressEngine, provideModuleMap } = require('./dist/server/main');
const { ServerAppModule, ngExpressEngine } = require('./dist/server/main');
/*
* Create a new express application
*/
const app = express();
const cookieParser = require('cookie-parser');
/*
* If production mode is enabled in the environment file:
* - Enable Angular's production mode
* - Enable compression for response bodies. See [compression](https://github.com/expressjs/compression)
*/
if (environment.production) {
enableProdMode();
app.use(compression());
// The Express app is exported so that it can be used by serverless Functions.
export function app() {
/*
* Create a new express application
*/
const server = express();
/*
* If production mode is enabled in the environment file:
* - Enable Angular's production mode
* - Enable compression for response bodies. See [compression](https://github.com/expressjs/compression)
*/
if (environment.production) {
enableProdMode();
server.use(compression());
}
/*
* Enable request logging
* See [morgan](https://github.com/expressjs/morgan)
*/
server.use(morgan('dev'));
/*
* Add cookie parser middleware
* See [morgan](https://github.com/expressjs/cookie-parser)
*/
server.use(cookieParser());
/*
* Add parser for request bodies
* See [morgan](https://github.com/expressjs/body-parser)
*/
server.use(bodyParser.json());
// Our Universal express-engine (found @ https://github.com/angular/universal/tree/master/modules/express-engine)
server.engine('html', (_, options, callback) =>
ngExpressEngine({
bootstrap: ServerAppModule,
providers: [
{
provide: REQUEST,
useValue: (options as any).req,
},
{
provide: RESPONSE,
useValue: (options as any).req.res,
},
],
})(_, (options as any), callback)
);
/*
* Register the view engines for html and ejs
*/
server.set('view engine', 'html');
/*
* Set views folder path to directory where template files are stored
*/
server.set('views', DIST_FOLDER);
/**
* Proxy the sitemaps
*/
server.use('/sitemap**', createProxyMiddleware({ target: `${environment.rest.baseUrl}/sitemaps`, changeOrigin: true }));
/**
* Checks if the rateLimiter property is present
* When it is present, the rateLimiter will be enabled. When it is undefined, the rateLimiter will be disabled.
*/
if (hasValue((environment.ui as UIServerConfig).rateLimiter)) {
const RateLimit = require('express-rate-limit');
const limiter = new RateLimit({
windowMs: (environment.ui as UIServerConfig).rateLimiter.windowMs,
max: (environment.ui as UIServerConfig).rateLimiter.max
});
server.use(limiter);
}
/*
* Serve static resources (images, i18n messages, …)
*/
server.get('*.*', cacheControl, express.static(DIST_FOLDER, { index: false }));
// Register the ngApp callback function to handle incoming requests
server.get('*', ngApp);
return server;
}
/*
* Enable request logging
* See [morgan](https://github.com/expressjs/morgan)
*/
app.use(morgan('dev'));
/*
* Add cookie parser middleware
* See [morgan](https://github.com/expressjs/cookie-parser)
*/
app.use(cookieParser());
/*
* Add parser for request bodies
* See [morgan](https://github.com/expressjs/body-parser)
*/
app.use(bodyParser.json());
/*
* Render html pages by running angular server side
*/
app.engine('html', (_, options, callback) =>
ngExpressEngine({
bootstrap: ServerAppModuleNgFactory,
providers: [
{
provide: REQUEST,
useValue: (options as any).req,
},
{
provide: RESPONSE,
useValue: (options as any).req.res,
},
provideModuleMap(LAZY_MODULE_MAP)
],
})(_, (options as any), callback)
);
/*
* Register the view engines for html and ejs
*/
app.set('view engine', 'html');
/*
* Set views folder path to directory where template files are stored
*/
app.set('views', DIST_FOLDER);
/**
* Proxy the sitemaps
*/
app.use('/sitemap**', createProxyMiddleware({ target: `${environment.rest.baseUrl}/sitemaps`, changeOrigin: true }));
/*
* Adds a cache control header to the response
* The cache control value can be configured in the environments file and defaults to max-age=60
*/
function cacheControl(req, res, next) {
// instruct browser to revalidate
res.header('Cache-Control', environment.cache.control || 'max-age=60');
next();
}
/**
* Checks if the rateLimiter property is present
* When it is present, the rateLimiter will be enabled. When it is undefined, the rateLimiter will be disabled.
*/
if (hasValue((environment.ui as UIServerConfig).rateLimiter)) {
const RateLimit = require('express-rate-limit');
const limiter = new RateLimit({
windowMs: (environment.ui as UIServerConfig).rateLimiter.windowMs,
max: (environment.ui as UIServerConfig).rateLimiter.max
});
app.use(limiter);
}
/*
* Serve static resources (images, i18n messages, …)
*/
app.get('*.*', cacheControl, express.static(DIST_FOLDER, { index: false }));
/*
* The callback function to serve server side angular
*/
function ngApp(req, res) {
if (environment.universal.preboot) {
res.render(DIST_FOLDER + '/index.html', {
res.render(indexHtml, {
req,
res,
preboot: environment.universal.preboot,
@@ -153,7 +155,8 @@ function ngApp(req, res) {
time: environment.universal.time,
baseUrl: environment.ui.nameSpace,
originUrl: environment.ui.baseUrl,
requestUrl: req.originalUrl
requestUrl: req.originalUrl,
providers: [{ provide: APP_BASE_HREF, useValue: req.baseUrl }]
}, (err, data) => {
if (hasNoValue(err) && hasValue(data)) {
res.send(data);
@@ -164,16 +167,23 @@ function ngApp(req, res) {
}
res.sendFile(DIST_FOLDER + '/index.html');
}
})
});
} else {
// If preboot is disabled, just serve the client
console.log('Universal off, serving for direct CSR');
res.sendFile(DIST_FOLDER + '/index.html');
res.sendFile(indexHtml);
}
}
// Register the ngApp callback function to handle incoming requests
app.get('*', ngApp);
/*
* Adds a cache control header to the response
* The cache control value can be configured in the environments file and defaults to max-age=60
*/
function cacheControl(req, res, next) {
// instruct browser to revalidate
res.header('Cache-Control', environment.cache.control || 'max-age=60');
next();
}
/*
* Callback function for when the server has started
@@ -195,6 +205,17 @@ function createHttpsServer(keys) {
});
}
function run() {
const port = environment.ui.port || 4000;
const host = environment.ui.host || '/';
// Start up the Node server
const server = app();
server.listen(port, host, () => {
serverStarted();
});
}
/*
* If SSL is enabled
* - Read credentials from configuration files
@@ -235,7 +256,7 @@ if (environment.ui.ssl) {
});
}
} else {
app.listen(environment.ui.port, environment.ui.host, () => {
serverStarted();
});
run();
}
export * from './src/main.server';

View File

@@ -1,7 +1,6 @@
import { CommonModule } from '@angular/common';
import { NgModule } from '@angular/core';
import { RouterModule } from '@angular/router';
import { TranslateModule } from '@ngx-translate/core';
import { SharedModule } from '../../shared/shared.module';
import { AdminAccessControlRoutingModule } from './admin-access-control-routing.module';
import { EPeopleRegistryComponent } from './epeople-registry/epeople-registry.component';
@@ -16,7 +15,6 @@ import { GroupsRegistryComponent } from './group-registry/groups-registry.compon
CommonModule,
SharedModule,
RouterModule,
TranslateModule,
AdminAccessControlRoutingModule
],
declarations: [
@@ -26,8 +24,7 @@ import { GroupsRegistryComponent } from './group-registry/groups-registry.compon
GroupFormComponent,
SubgroupsListComponent,
MembersListComponent
],
entryComponents: []
]
})
/**
* This module handles all components related to the access control pages

View File

@@ -46,4 +46,4 @@ export class EPeopleRegistryCancelEPersonAction implements Action {
*/
export type EPeopleRegistryAction
= EPeopleRegistryEditEPersonAction
| EPeopleRegistryCancelEPersonAction
| EPeopleRegistryCancelEPersonAction;

View File

@@ -1,14 +1,13 @@
import { Router } from '@angular/router';
import { of as observableOf } from 'rxjs';
import { Observable, of as observableOf } from 'rxjs';
import { CommonModule } from '@angular/common';
import { NO_ERRORS_SCHEMA } from '@angular/core';
import { async, ComponentFixture, fakeAsync, inject, TestBed, tick } from '@angular/core/testing';
import { ComponentFixture, fakeAsync, TestBed, tick, waitForAsync } from '@angular/core/testing';
import { FormsModule, ReactiveFormsModule } from '@angular/forms';
import { BrowserModule, By } from '@angular/platform-browser';
import { NgbModule } from '@ng-bootstrap/ng-bootstrap';
import { TranslateLoader, TranslateModule, TranslateService } from '@ngx-translate/core';
import { Observable } from 'rxjs/internal/Observable';
import { PaginatedList, buildPaginatedList } from '../../../core/data/paginated-list.model';
import { buildPaginatedList, PaginatedList } from '../../../core/data/paginated-list.model';
import { RemoteData } from '../../../core/data/remote-data';
import { FindListOptions } from '../../../core/data/request.models';
import { EPersonDataService } from '../../../core/eperson/eperson-data.service';
@@ -38,13 +37,18 @@ describe('EPeopleRegistryComponent', () => {
let authorizationService: AuthorizationDataService;
let modalService;
beforeEach(async(() => {
beforeEach(waitForAsync(() => {
mockEPeople = [EPersonMock, EPersonMock2];
ePersonDataServiceStub = {
activeEPerson: null,
allEpeople: mockEPeople,
getEPeople(): Observable<RemoteData<PaginatedList<EPerson>>> {
return createSuccessfulRemoteDataObject$(buildPaginatedList(new PageInfo({ elementsPerPage: this.allEpeople.length, totalElements: this.allEpeople.length, totalPages: 1, currentPage: 1 }), this.allEpeople));
return createSuccessfulRemoteDataObject$(buildPaginatedList(new PageInfo({
elementsPerPage: this.allEpeople.length,
totalElements: this.allEpeople.length,
totalPages: 1,
currentPage: 1
}), this.allEpeople));
},
getActiveEPerson(): Observable<EPerson> {
return observableOf(this.activeEPerson);
@@ -52,20 +56,40 @@ describe('EPeopleRegistryComponent', () => {
searchByScope(scope: string, query: string, options: FindListOptions = {}): Observable<RemoteData<PaginatedList<EPerson>>> {
if (scope === 'email') {
const result = this.allEpeople.find((ePerson: EPerson) => {
return ePerson.email === query
return ePerson.email === query;
});
return createSuccessfulRemoteDataObject$(buildPaginatedList(new PageInfo({ elementsPerPage: [result].length, totalElements: [result].length, totalPages: 1, currentPage: 1 }), [result]));
return createSuccessfulRemoteDataObject$(buildPaginatedList(new PageInfo({
elementsPerPage: [result].length,
totalElements: [result].length,
totalPages: 1,
currentPage: 1
}), [result]));
}
if (scope === 'metadata') {
if (query === '') {
return createSuccessfulRemoteDataObject$(buildPaginatedList(new PageInfo({ elementsPerPage: this.allEpeople.length, totalElements: this.allEpeople.length, totalPages: 1, currentPage: 1 }), this.allEpeople));
return createSuccessfulRemoteDataObject$(buildPaginatedList(new PageInfo({
elementsPerPage: this.allEpeople.length,
totalElements: this.allEpeople.length,
totalPages: 1,
currentPage: 1
}), this.allEpeople));
}
const result = this.allEpeople.find((ePerson: EPerson) => {
return (ePerson.name.includes(query) || ePerson.email.includes(query))
return (ePerson.name.includes(query) || ePerson.email.includes(query));
});
return createSuccessfulRemoteDataObject$(buildPaginatedList(new PageInfo({ elementsPerPage: [result].length, totalElements: [result].length, totalPages: 1, currentPage: 1 }), [result]));
return createSuccessfulRemoteDataObject$(buildPaginatedList(new PageInfo({
elementsPerPage: [result].length,
totalElements: [result].length,
totalPages: 1,
currentPage: 1
}), [result]));
}
return createSuccessfulRemoteDataObject$(buildPaginatedList(new PageInfo({ elementsPerPage: this.allEpeople.length, totalElements: this.allEpeople.length, totalPages: 1, currentPage: 1 }), this.allEpeople));
return createSuccessfulRemoteDataObject$(buildPaginatedList(new PageInfo({
elementsPerPage: this.allEpeople.length,
totalElements: this.allEpeople.length,
totalPages: 1,
currentPage: 1
}), this.allEpeople));
},
deleteEPerson(ePerson: EPerson): Observable<boolean> {
this.allEpeople = this.allEpeople.filter((ePerson2: EPerson) => {
@@ -107,7 +131,7 @@ describe('EPeopleRegistryComponent', () => {
{ provide: AuthorizationDataService, useValue: authorizationService },
{ provide: FormBuilderService, useValue: builderService },
{ provide: Router, useValue: new RouterStub() },
{ provide: RequestService, useValue: jasmine.createSpyObj('requestService', ['removeByHrefSubstring'])}
{ provide: RequestService, useValue: jasmine.createSpyObj('requestService', ['removeByHrefSubstring']) }
],
schemas: [NO_ERRORS_SCHEMA]
}).compileComponents();
@@ -132,7 +156,7 @@ describe('EPeopleRegistryComponent', () => {
expect(ePeopleIdsFound.find((foundEl) => {
return (foundEl.nativeElement.textContent.trim() === ePerson.uuid);
})).toBeTruthy();
})
});
});
describe('search', () => {
@@ -192,7 +216,7 @@ describe('EPeopleRegistryComponent', () => {
expect(component.isEPersonFormShown).toEqual(true);
}
})
});
});
it('EPerson search section is hidden', () => {
@@ -234,12 +258,12 @@ describe('EPeopleRegistryComponent', () => {
});
});
it ('should be disabled', () => {
it('should be disabled', () => {
ePeopleDeleteButton = fixture.debugElement.queryAll(By.css('#epeople tr td div button.delete-button'));
ePeopleDeleteButton.forEach((deleteButton) => {
expect(deleteButton.nativeElement.disabled).toBe(true);
});
})
})
});
});
});

View File

@@ -2,9 +2,8 @@ import { Component, OnDestroy, OnInit } from '@angular/core';
import { FormBuilder } from '@angular/forms';
import { Router } from '@angular/router';
import { TranslateService } from '@ngx-translate/core';
import { BehaviorSubject, combineLatest, Observable } from 'rxjs';
import { Subscription } from 'rxjs/internal/Subscription';
import { map, switchMap, take } from 'rxjs/operators';
import { BehaviorSubject, combineLatest, Observable, Subscription } from 'rxjs';
import { filter, map, switchMap, take } from 'rxjs/operators';
import { PaginatedList, buildPaginatedList } from '../../../core/data/paginated-list.model';
import { RemoteData } from '../../../core/data/remote-data';
import { EPersonDataService } from '../../../core/eperson/eperson-data.service';
@@ -22,7 +21,6 @@ import {
import { ConfirmationModalComponent } from '../../../shared/confirmation-modal/confirmation-modal.component';
import { NgbModal } from '@ng-bootstrap/ng-bootstrap';
import { RequestService } from '../../../core/data/request.service';
import { filter } from 'rxjs/internal/operators/filter';
import { PageInfo } from '../../../core/shared/page-info.model';
import { NoContent } from '../../../core/shared/NoContent.model';
@@ -119,7 +117,7 @@ export class EPeopleRegistryComponent implements OnInit, OnDestroy {
onPageChange(event) {
if (this.config.currentPage !== event) {
this.config.currentPage = event;
this.search({ scope: this.currentSearchScope, query: this.currentSearchQuery })
this.search({ scope: this.currentSearchScope, query: this.currentSearchQuery });
}
}
@@ -163,7 +161,7 @@ export class EPeopleRegistryComponent implements OnInit, OnDestroy {
);
})).pipe(map((dtos: EpersonDtoModel[]) => {
return buildPaginatedList(epeople.pageInfo, dtos);
}))
}));
})).subscribe((value) => {
this.ePeopleDto$.next(value);
this.pageInfoState$.next(value.pageInfo);
@@ -201,7 +199,7 @@ export class EPeopleRegistryComponent implements OnInit, OnDestroy {
this.isEPersonFormShown = true;
}
});
this.scrollToTop()
this.scrollToTop();
}
/**
@@ -225,7 +223,7 @@ export class EPeopleRegistryComponent implements OnInit, OnDestroy {
} else {
this.notificationsService.error('Error occured when trying to delete EPerson with id: ' + ePerson.id + ' with code: ' + restResponse.statusCode + ' and message: ' + restResponse.errorMessage);
}
})
});
}}
});
}

View File

@@ -1,13 +1,12 @@
import { of as observableOf } from 'rxjs';
import { Observable, of as observableOf } from 'rxjs';
import { CommonModule } from '@angular/common';
import { NO_ERRORS_SCHEMA } from '@angular/core';
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing';
import { FormsModule, ReactiveFormsModule } from '@angular/forms';
import { BrowserModule, By } from '@angular/platform-browser';
import { NgbModule } from '@ng-bootstrap/ng-bootstrap';
import { TranslateLoader, TranslateModule } from '@ngx-translate/core';
import { Observable } from 'rxjs/internal/Observable';
import { PaginatedList, buildPaginatedList } from '../../../../core/data/paginated-list.model';
import { buildPaginatedList, PaginatedList } from '../../../../core/data/paginated-list.model';
import { RemoteData } from '../../../../core/data/remote-data';
import { FindListOptions } from '../../../../core/data/request.models';
import { EPersonDataService } from '../../../../core/eperson/eperson-data.service';
@@ -39,7 +38,7 @@ describe('EPersonFormComponent', () => {
let authorizationService: AuthorizationDataService;
let groupsDataService: GroupDataService;
beforeEach(async(() => {
beforeEach(waitForAsync(() => {
mockEPeople = [EPersonMock, EPersonMock2];
ePersonDataServiceStub = {
activeEPerson: null,
@@ -53,7 +52,7 @@ describe('EPersonFormComponent', () => {
searchByScope(scope: string, query: string, options: FindListOptions = {}): Observable<RemoteData<PaginatedList<EPerson>>> {
if (scope === 'email') {
const result = this.allEpeople.find((ePerson: EPerson) => {
return ePerson.email === query
return ePerson.email === query;
});
return createSuccessfulRemoteDataObject$(buildPaginatedList(new PageInfo(), [result]));
}
@@ -62,7 +61,7 @@ describe('EPersonFormComponent', () => {
return createSuccessfulRemoteDataObject$(buildPaginatedList(null, this.allEpeople));
}
const result = this.allEpeople.find((ePerson: EPerson) => {
return (ePerson.name.includes(query) || ePerson.email.includes(query))
return (ePerson.name.includes(query) || ePerson.email.includes(query));
});
return createSuccessfulRemoteDataObject$(buildPaginatedList(new PageInfo(), [result]));
}
@@ -122,7 +121,7 @@ describe('EPersonFormComponent', () => {
{ provide: NotificationsService, useValue: new NotificationsServiceStub() },
{ provide: AuthService, useValue: authService },
{ provide: AuthorizationDataService, useValue: authorizationService },
{ provide: RequestService, useValue: jasmine.createSpyObj('requestService', ['removeByHrefSubstring'])}
{ provide: RequestService, useValue: jasmine.createSpyObj('requestService', ['removeByHrefSubstring']) }
],
schemas: [NO_ERRORS_SCHEMA]
}).compileComponents();
@@ -184,7 +183,7 @@ describe('EPersonFormComponent', () => {
fixture.detectChanges();
});
it('should emit a new eperson using the correct values', async(() => {
it('should emit a new eperson using the correct values', waitForAsync(() => {
fixture.whenStable().then(() => {
expect(component.submitForm.emit).toHaveBeenCalledWith(expected);
});
@@ -196,6 +195,7 @@ describe('EPersonFormComponent', () => {
beforeEach(() => {
expectedWithId = Object.assign(new EPerson(), {
id: 'id',
metadata: {
'eperson.firstname': [
{
@@ -211,13 +211,14 @@ describe('EPersonFormComponent', () => {
email: email,
canLogIn: canLogIn,
requireCertificate: requireCertificate,
_links: undefined
});
spyOn(ePersonDataServiceStub, 'getActiveEPerson').and.returnValue(observableOf(expectedWithId));
component.onSubmit();
fixture.detectChanges();
});
it('should emit the existing eperson using the correct values', async(() => {
it('should emit the existing eperson using the correct values', waitForAsync(() => {
fixture.whenStable().then(() => {
expect(component.submitForm.emit).toHaveBeenCalledWith(expectedWithId);
});
@@ -276,23 +277,23 @@ describe('EPersonFormComponent', () => {
spyOn(component.epersonService, 'getActiveEPerson').and.returnValue(observableOf(eperson));
modalService = (component as any).modalService;
spyOn(modalService, 'open').and.returnValue(Object.assign({ componentInstance: Object.assign({ response: observableOf(true) }) }));
fixture.detectChanges()
fixture.detectChanges();
});
it ('the delete button should be active if the eperson can be deleted', () => {
it('the delete button should be active if the eperson can be deleted', () => {
const deleteButton = fixture.debugElement.query(By.css('.delete-button'));
expect(deleteButton.nativeElement.disabled).toBe(false);
});
it ('the delete button should be disabled if the eperson cannot be deleted', () => {
it('the delete button should be disabled if the eperson cannot be deleted', () => {
component.canDelete$ = observableOf(false);
fixture.detectChanges()
fixture.detectChanges();
const deleteButton = fixture.debugElement.query(By.css('.delete-button'));
expect(deleteButton.nativeElement.disabled).toBe(true);
});
it ('should call the epersonFormComponent delete when clicked on the button' , () => {
it('should call the epersonFormComponent delete when clicked on the button', () => {
spyOn(component, 'delete').and.stub();
spyOn(component.epersonService, 'deleteEPerson').and.returnValue(createSuccessfulRemoteDataObject$('No Content', 204));
const deleteButton = fixture.debugElement.query(By.css('.delete-button'));
@@ -300,14 +301,14 @@ describe('EPersonFormComponent', () => {
expect(component.delete).toHaveBeenCalled();
});
it ('should call the epersonService delete when clicked on the button' , () => {
it('should call the epersonService delete when clicked on the button', () => {
// ePersonDataServiceStub.activeEPerson = eperson;
spyOn(component.epersonService, 'deleteEPerson').and.returnValue(createSuccessfulRemoteDataObject$('No Content', 204));
const deleteButton = fixture.debugElement.query(By.css('.delete-button'));
expect(deleteButton.nativeElement.disabled).toBe(false);
deleteButton.triggerEventHandler('click', null);
fixture.detectChanges()
fixture.detectChanges();
expect(component.epersonService.deleteEPerson).toHaveBeenCalledWith(eperson);
});
})
});
});

View File

@@ -7,8 +7,7 @@ import {
DynamicInputModel
} from '@ng-dynamic-forms/core';
import { TranslateService } from '@ngx-translate/core';
import { Subscription, combineLatest, of } from 'rxjs';
import { Observable } from 'rxjs/internal/Observable';
import { combineLatest, Observable, of, Subscription } from 'rxjs';
import { switchMap, take } from 'rxjs/operators';
import { PaginatedList } from '../../../../core/data/paginated-list.model';
import { RemoteData } from '../../../../core/data/remote-data';
@@ -448,10 +447,10 @@ export class EPersonFormComponent implements OnInit, OnDestroy {
this.notificationsService.error('Error occured when trying to delete EPerson with id: ' + eperson.id + ' with code: ' + restResponse.statusCode + ' and message: ' + restResponse.errorMessage);
}
this.cancelForm.emit();
})
});
}}
});
})
});
}
/**

View File

@@ -1,21 +1,20 @@
import { CommonModule } from '@angular/common';
import { HttpClient } from '@angular/common/http';
import { NO_ERRORS_SCHEMA } from '@angular/core';
import { async, ComponentFixture, inject, TestBed } from '@angular/core/testing';
import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing';
import { FormsModule, ReactiveFormsModule } from '@angular/forms';
import { BrowserModule } from '@angular/platform-browser';
import { ActivatedRoute, Router } from '@angular/router';
import { NgbModule } from '@ng-bootstrap/ng-bootstrap';
import { Store } from '@ngrx/store';
import { TranslateLoader, TranslateModule, TranslateService } from '@ngx-translate/core';
import { of as observableOf } from 'rxjs';
import { Observable } from 'rxjs/internal/Observable';
import { Observable, of as observableOf } from 'rxjs';
import { RemoteDataBuildService } from '../../../../core/cache/builders/remote-data-build.service';
import { ObjectCacheService } from '../../../../core/cache/object-cache.service';
import { DSOChangeAnalyzer } from '../../../../core/data/dso-change-analyzer.service';
import { DSpaceObjectDataService } from '../../../../core/data/dspace-object-data.service';
import { AuthorizationDataService } from '../../../../core/data/feature-authorization/authorization-data.service';
import { PaginatedList, buildPaginatedList } from '../../../../core/data/paginated-list.model';
import { buildPaginatedList, PaginatedList } from '../../../../core/data/paginated-list.model';
import { RemoteData } from '../../../../core/data/remote-data';
import { EPersonDataService } from '../../../../core/eperson/eperson-data.service';
import { GroupDataService } from '../../../../core/eperson/group-data.service';
@@ -53,8 +52,8 @@ describe('GroupFormComponent', () => {
let groupDescription;
let expected;
beforeEach(async(() => {
groups = [GroupMock, GroupMock2]
beforeEach(waitForAsync(() => {
groups = [GroupMock, GroupMock2];
groupName = 'testGroupName';
groupDescription = 'testDescription';
expected = Object.assign(new Group(), {
@@ -79,7 +78,7 @@ describe('GroupFormComponent', () => {
return '/admin/access-control/groups';
},
editGroup(group: Group) {
this.activeGroup = group
this.activeGroup = group;
},
clearGroupsRequests() {
return null;
@@ -104,7 +103,7 @@ describe('GroupFormComponent', () => {
return createSuccessfulRemoteDataObject$(this.createdGroup);
},
searchGroups(query: string): Observable<RemoteData<PaginatedList<Group>>> {
return createSuccessfulRemoteDataObject$(buildPaginatedList(new PageInfo(), []))
return createSuccessfulRemoteDataObject$(buildPaginatedList(new PageInfo(), []));
},
getGroupEditPageRouterLinkWithID(id: string) {
return `group-edit-page-for-${id}`;
@@ -117,7 +116,7 @@ describe('GroupFormComponent', () => {
findByHref(href: string): Observable<RemoteData<DSpaceObject>> {
return null;
}
}
};
builderService = getMockFormBuilderService();
translateService = getMockTranslateService();
router = new RouterMock();
@@ -145,7 +144,10 @@ describe('GroupFormComponent', () => {
{ provide: Store, useValue: {} },
{ provide: RemoteDataBuildService, useValue: {} },
{ provide: HALEndpointService, useValue: {} },
{ provide: ActivatedRoute, useValue: { data: observableOf({ dso: { payload: {} } }), params: observableOf({}) } },
{
provide: ActivatedRoute,
useValue: { data: observableOf({ dso: { payload: {} } }), params: observableOf({}) }
},
{ provide: Router, useValue: router },
{ provide: AuthorizationDataService, useValue: authorizationService },
],
@@ -159,10 +161,6 @@ describe('GroupFormComponent', () => {
fixture.detectChanges();
});
it('should create GroupFormComponent', inject([GroupFormComponent], (comp: GroupFormComponent) => {
expect(comp).toBeDefined();
}));
describe('when submitting the form', () => {
beforeEach(() => {
spyOn(component.submitForm, 'emit');
@@ -175,23 +173,16 @@ describe('GroupFormComponent', () => {
fixture.detectChanges();
});
it('should emit a new group using the correct values', async(() => {
it('should emit a new group using the correct values', waitForAsync(() => {
fixture.whenStable().then(() => {
expect(component.submitForm.emit).toHaveBeenCalledWith(expected);
});
}));
});
describe('with active Group', () => {
let expected2;
beforeEach(() => {
spyOn(groupsDataServiceStub, 'getActiveGroup').and.returnValue(observableOf(expected));
spyOn(groupsDataServiceStub, 'patch').and.returnValue(createSuccessfulRemoteDataObject$(expected));
component.groupName.value = 'newGroupName';
component.onSubmit();
fixture.detectChanges();
});
it('should emit the existing group using the correct new values', async(() => {
const expected2 = Object.assign(new Group(), {
expected2 = Object.assign(new Group(), {
name: 'newGroupName',
metadata: {
'dc.description': [
@@ -201,13 +192,21 @@ describe('GroupFormComponent', () => {
],
},
});
spyOn(groupsDataServiceStub, 'getActiveGroup').and.returnValue(observableOf(expected));
spyOn(groupsDataServiceStub, 'patch').and.returnValue(createSuccessfulRemoteDataObject$(expected2));
component.groupName.value = 'newGroupName';
component.onSubmit();
fixture.detectChanges();
});
it('should emit the existing group using the correct new values', waitForAsync(() => {
fixture.whenStable().then(() => {
expect(component.submitForm.emit).toHaveBeenCalledWith(expected2);
});
}));
it('should emit success notification', () => {
expect(notificationService.success).toHaveBeenCalled();
})
});
});
});

View File

@@ -143,17 +143,17 @@ export class GroupFormComponent implements OnInit, OnDestroy {
initialisePage() {
this.subs.push(this.route.params.subscribe((params) => {
this.setActiveGroup(params.groupId)
this.setActiveGroup(params.groupId);
}));
this.canEdit$ = this.groupDataService.getActiveGroup().pipe(
hasValueOperator(),
switchMap((group: Group) => {
return observableCombineLatest(
this.authorizationService.isAuthorized(FeatureID.CanDelete, hasValue(group) ? group.self : undefined),
this.authorizationService.isAuthorized(FeatureID.CanDelete, isNotEmpty(group) ? group.self : undefined),
this.hasLinkedDSO(group),
(isAuthorized: ObservedValueOf<Observable<boolean>>, hasLinkedDSO: ObservedValueOf<Observable<boolean>>) => {
return isAuthorized && !hasLinkedDSO;
})
});
})
);
observableCombineLatest(
@@ -229,8 +229,10 @@ export class GroupFormComponent implements OnInit, OnDestroy {
},
};
if (group === null) {
console.log('createNewGroup', values);
this.createNewGroup(values);
} else {
console.log('editGroup', group);
this.editGroup(group);
}
}
@@ -289,7 +291,7 @@ export class GroupFormComponent implements OnInit, OnDestroy {
* @param group Group to edit and old values contained within
*/
editGroup(group: Group) {
let operations: Operation[] = []
let operations: Operation[] = [];
if (hasValue(this.groupDescription.value)) {
operations = [...operations, {
@@ -349,7 +351,7 @@ export class GroupFormComponent implements OnInit, OnDestroy {
getRemoteDataPayload())
.subscribe((group: Group) => {
this.groupDataService.editGroup(group);
})
});
}
});
}
@@ -379,11 +381,11 @@ export class GroupFormComponent implements OnInit, OnDestroy {
this.translateService.get(this.messagePrefix + '.notification.deleted.failure.title', { name: group.name }),
this.translateService.get(this.messagePrefix + '.notification.deleted.failure.content', { cause: rd.errorMessage }));
}
})
});
}
}
});
})
});
}
/**
@@ -416,7 +418,7 @@ export class GroupFormComponent implements OnInit, OnDestroy {
if (hasValue(rd) && hasValue(rd.payload)) {
return true;
} else {
return false
return false;
}
}),
catchError(() => observableOf(false)),
@@ -446,7 +448,7 @@ export class GroupFormComponent implements OnInit, OnDestroy {
return this.getLinkedDSO(group).pipe(
map((rd: RemoteData<DSpaceObject>) => {
if (hasValue(rd) && hasValue(rd.payload)) {
const dso = rd.payload
const dso = rd.payload;
switch ((dso as any).type) {
case Community.type.value:
return getCommunityEditRolesRoute(rd.payload.id);
@@ -455,7 +457,7 @@ export class GroupFormComponent implements OnInit, OnDestroy {
}
}
})
)
);
}
}
}

View File

@@ -1,22 +1,14 @@
import { CommonModule } from '@angular/common';
import { NO_ERRORS_SCHEMA } from '@angular/core';
import {
async,
ComponentFixture,
fakeAsync,
flush,
inject,
TestBed,
tick
} from '@angular/core/testing';
import { ComponentFixture, fakeAsync, flush, inject, TestBed, tick, waitForAsync } from '@angular/core/testing';
import { FormsModule, ReactiveFormsModule } from '@angular/forms';
import { BrowserModule, By } from '@angular/platform-browser';
import { Router } from '@angular/router';
import { NgbModule } from '@ng-bootstrap/ng-bootstrap';
import { TranslateLoader, TranslateModule, TranslateService } from '@ngx-translate/core';
import { Observable } from 'rxjs/internal/Observable';
import { Observable, of as observableOf } from 'rxjs';
import { RestResponse } from '../../../../../core/cache/response.models';
import { PaginatedList, buildPaginatedList } from '../../../../../core/data/paginated-list.model';
import { buildPaginatedList, PaginatedList } from '../../../../../core/data/paginated-list.model';
import { RemoteData } from '../../../../../core/data/remote-data';
import { EPersonDataService } from '../../../../../core/eperson/eperson-data.service';
import { GroupDataService } from '../../../../../core/eperson/group-data.service';
@@ -26,7 +18,6 @@ import { PageInfo } from '../../../../../core/shared/page-info.model';
import { FormBuilderService } from '../../../../../shared/form/builder/form-builder.service';
import { NotificationsService } from '../../../../../shared/notifications/notifications.service';
import { GroupMock, GroupMock2 } from '../../../../../shared/testing/group-mock';
import { of as observableOf } from 'rxjs';
import { MembersListComponent } from './members-list.component';
import { EPersonMock, EPersonMock2 } from '../../../../../shared/testing/eperson.mock';
import { createSuccessfulRemoteDataObject$ } from '../../../../../shared/remote-data.utils';
@@ -49,7 +40,7 @@ describe('MembersListComponent', () => {
let epersonMembers;
let subgroupMembers;
beforeEach(async(() => {
beforeEach(waitForAsync(() => {
activeGroup = GroupMock;
epersonMembers = [EPersonMock2];
subgroupMembers = [GroupMock2];
@@ -60,13 +51,13 @@ describe('MembersListComponent', () => {
epersonMembers: epersonMembers,
subgroupMembers: subgroupMembers,
findAllByHref(href: string): Observable<RemoteData<PaginatedList<EPerson>>> {
return createSuccessfulRemoteDataObject$(buildPaginatedList<EPerson>(new PageInfo(), groupsDataServiceStub.getEPersonMembers()))
return createSuccessfulRemoteDataObject$(buildPaginatedList<EPerson>(new PageInfo(), groupsDataServiceStub.getEPersonMembers()));
},
searchByScope(scope: string, query: string): Observable<RemoteData<PaginatedList<EPerson>>> {
if (query === '') {
return createSuccessfulRemoteDataObject$(buildPaginatedList(new PageInfo(), allEPersons))
return createSuccessfulRemoteDataObject$(buildPaginatedList(new PageInfo(), allEPersons));
}
return createSuccessfulRemoteDataObject$(buildPaginatedList(new PageInfo(), []))
return createSuccessfulRemoteDataObject$(buildPaginatedList(new PageInfo(), []));
},
clearEPersonRequests() {
// empty
@@ -91,9 +82,9 @@ describe('MembersListComponent', () => {
},
searchGroups(query: string): Observable<RemoteData<PaginatedList<Group>>> {
if (query === '') {
return createSuccessfulRemoteDataObject$(buildPaginatedList(new PageInfo(), this.allGroups))
return createSuccessfulRemoteDataObject$(buildPaginatedList(new PageInfo(), this.allGroups));
}
return createSuccessfulRemoteDataObject$(buildPaginatedList(new PageInfo(), []))
return createSuccessfulRemoteDataObject$(buildPaginatedList(new PageInfo(), []));
},
addMemberToGroup(parentGroup, eperson: EPerson): Observable<RestResponse> {
this.epersonMembers = [...this.epersonMembers, eperson];
@@ -115,7 +106,7 @@ describe('MembersListComponent', () => {
}
});
if (this.epersonMembers === undefined) {
this.epersonMembers = []
this.epersonMembers = [];
}
return observableOf(new RestResponse(true, 200, 'Success'));
}
@@ -198,8 +189,8 @@ describe('MembersListComponent', () => {
expect(addButton).toBeDefined();
}
}
})
})
});
});
});
});
@@ -220,7 +211,7 @@ describe('MembersListComponent', () => {
expect(addButton).toBeUndefined();
expect(deleteButton).toBeDefined();
}
})
});
});
});
@@ -240,7 +231,7 @@ describe('MembersListComponent', () => {
expect(deleteButton).toBeUndefined();
expect(addButton).toBeDefined();
}
})
});
});
});
});

View File

@@ -115,7 +115,7 @@ export class MembersListComponent implements OnInit, OnDestroy {
this.ePeopleMembersOfGroup = this.ePersonDataService.findAllByHref(this.groupBeingEdited._links.epersons.href, {
currentPage: event,
elementsPerPage: this.config.pageSize
})
});
}
/**
@@ -166,11 +166,11 @@ export class MembersListComponent implements OnInit, OnDestroy {
getFirstSucceededRemoteData(),
getRemoteDataPayload(),
map((listEPeopleInGroup: PaginatedList<EPerson>) => listEPeopleInGroup.page.filter((ePersonInList: EPerson) => ePersonInList.id === possibleMember.id)),
map((epeople: EPerson[]) => epeople.length > 0))
map((epeople: EPerson[]) => epeople.length > 0));
} else {
return observableOf(false);
}
}))
}));
}
/**
@@ -211,7 +211,7 @@ export class MembersListComponent implements OnInit, OnDestroy {
this.ePeopleMembersOfGroup = this.ePersonDataService.findAllByHref(activeGroup._links.epersons.href, {
currentPage: this.configSearch.currentPage,
elementsPerPage: this.configSearch.pageSize
})
});
}
/**
@@ -235,7 +235,7 @@ export class MembersListComponent implements OnInit, OnDestroy {
} else {
this.notificationsService.error(this.translateService.get(this.messagePrefix + '.notification.failure.' + messageSuffix, { name: nameObject }));
}
})
});
}
/**

View File

@@ -1,14 +1,14 @@
import { CommonModule } from '@angular/common';
import { NO_ERRORS_SCHEMA } from '@angular/core';
import { async, ComponentFixture, fakeAsync, flush, inject, TestBed, tick } from '@angular/core/testing';
import { ComponentFixture, fakeAsync, flush, inject, TestBed, tick, waitForAsync } from '@angular/core/testing';
import { FormsModule, ReactiveFormsModule } from '@angular/forms';
import { BrowserModule, By } from '@angular/platform-browser';
import { Router } from '@angular/router';
import { NgbModule } from '@ng-bootstrap/ng-bootstrap';
import { TranslateLoader, TranslateModule, TranslateService } from '@ngx-translate/core';
import { Observable } from 'rxjs/internal/Observable';
import { Observable, of as observableOf } from 'rxjs';
import { RestResponse } from '../../../../../core/cache/response.models';
import { PaginatedList, buildPaginatedList } from '../../../../../core/data/paginated-list.model';
import { buildPaginatedList, PaginatedList } from '../../../../../core/data/paginated-list.model';
import { RemoteData } from '../../../../../core/data/remote-data';
import { GroupDataService } from '../../../../../core/eperson/group-data.service';
import { Group } from '../../../../../core/eperson/models/group.model';
@@ -16,7 +16,6 @@ import { PageInfo } from '../../../../../core/shared/page-info.model';
import { FormBuilderService } from '../../../../../shared/form/builder/form-builder.service';
import { NotificationsService } from '../../../../../shared/notifications/notifications.service';
import { GroupMock, GroupMock2 } from '../../../../../shared/testing/group-mock';
import { of as observableOf } from 'rxjs';
import { SubgroupsListComponent } from './subgroups-list.component';
import { createSuccessfulRemoteDataObject$ } from '../../../../../shared/remote-data.utils';
import { RouterMock } from '../../../../../shared/mocks/router.mock';
@@ -37,7 +36,7 @@ describe('SubgroupsListComponent', () => {
let allGroups;
let routerStub;
beforeEach(async(() => {
beforeEach(waitForAsync(() => {
activeGroup = GroupMock;
subgroups = [GroupMock2];
allGroups = [GroupMock, GroupMock2];
@@ -52,16 +51,16 @@ describe('SubgroupsListComponent', () => {
return this.activeGroup;
},
findAllByHref(href: string): Observable<RemoteData<PaginatedList<Group>>> {
return createSuccessfulRemoteDataObject$(buildPaginatedList<Group>(new PageInfo(), this.subgroups))
return createSuccessfulRemoteDataObject$(buildPaginatedList<Group>(new PageInfo(), this.subgroups));
},
getGroupEditPageRouterLink(group: Group): string {
return '/admin/access-control/groups/' + group.id;
},
searchGroups(query: string): Observable<RemoteData<PaginatedList<Group>>> {
if (query === '') {
return createSuccessfulRemoteDataObject$(buildPaginatedList(new PageInfo(), allGroups))
return createSuccessfulRemoteDataObject$(buildPaginatedList(new PageInfo(), allGroups));
}
return createSuccessfulRemoteDataObject$(buildPaginatedList(new PageInfo(), []))
return createSuccessfulRemoteDataObject$(buildPaginatedList(new PageInfo(), []));
},
addSubGroupToGroup(parentGroup, subgroup: Group): Observable<RestResponse> {
this.subgroups = [...this.subgroups, subgroup];
@@ -127,7 +126,7 @@ describe('SubgroupsListComponent', () => {
expect(groupIdsFound.find((foundEl) => {
return (foundEl.nativeElement.textContent.trim() === group.uuid);
})).toBeTruthy();
})
});
});
describe('if first group delete button is pressed', () => {
@@ -165,7 +164,7 @@ describe('SubgroupsListComponent', () => {
expect(groupIdsFound.find((foundEl) => {
return (foundEl.nativeElement.textContent.trim() === group.uuid);
})).toBeTruthy();
})
});
});
describe('if group is already a subgroup', () => {
@@ -181,7 +180,7 @@ describe('SubgroupsListComponent', () => {
expect(addButton).toBeUndefined();
expect(deleteButton).toBeDefined();
}
})
});
} else {
getSubgroups.map((group: Group) => {
groupsFound.map((foundGroupRowElement) => {
@@ -197,8 +196,8 @@ describe('SubgroupsListComponent', () => {
expect(addButton).toBeDefined();
}
}
})
})
});
});
}
});
});

View File

@@ -131,7 +131,7 @@ export class SubgroupsListComponent implements OnInit, OnDestroy {
getFirstSucceededRemoteData(),
getRemoteDataPayload(),
map((listTotalGroups: PaginatedList<Group>) => listTotalGroups.page.filter((groupInList: Group) => groupInList.id === possibleSubgroup.id)),
map((groups: Group[]) => groups.length > 0))
map((groups: Group[]) => groups.length > 0));
}
} else {
return observableOf(false);
@@ -241,7 +241,7 @@ export class SubgroupsListComponent implements OnInit, OnDestroy {
} else {
this.notificationsService.error(this.translateService.get(this.messagePrefix + '.notification.failure.' + messageSuffix, { name: nameObject }));
}
})
});
}
/**

View File

@@ -46,4 +46,4 @@ export class GroupRegistryCancelGroupAction implements Action {
*/
export type GroupRegistryAction
= GroupRegistryEditGroupAction
| GroupRegistryCancelGroupAction
| GroupRegistryCancelGroupAction;

View File

@@ -1,6 +1,6 @@
import { CommonModule } from '@angular/common';
import { NO_ERRORS_SCHEMA } from '@angular/core';
import { async, ComponentFixture, fakeAsync, inject, TestBed, tick } from '@angular/core/testing';
import { ComponentFixture, fakeAsync, inject, TestBed, tick, waitForAsync } from '@angular/core/testing';
import { FormsModule, ReactiveFormsModule } from '@angular/forms';
import { BrowserModule, By } from '@angular/platform-browser';
import { Router } from '@angular/router';
@@ -9,7 +9,7 @@ import { TranslateLoader, TranslateModule } from '@ngx-translate/core';
import { Observable, of as observableOf } from 'rxjs';
import { DSpaceObjectDataService } from '../../../core/data/dspace-object-data.service';
import { AuthorizationDataService } from '../../../core/data/feature-authorization/authorization-data.service';
import { PaginatedList, buildPaginatedList } from '../../../core/data/paginated-list.model';
import { buildPaginatedList, PaginatedList } from '../../../core/data/paginated-list.model';
import { RemoteData } from '../../../core/data/remote-data';
import { RequestService } from '../../../core/data/request.service';
import { EPersonDataService } from '../../../core/eperson/eperson-data.service';
@@ -40,18 +40,33 @@ describe('GroupRegistryComponent', () => {
let mockGroups;
let mockEPeople;
beforeEach(async(() => {
beforeEach(waitForAsync(() => {
mockGroups = [GroupMock, GroupMock2];
mockEPeople = [EPersonMock, EPersonMock2];
ePersonDataServiceStub = {
findAllByHref(href: string): Observable<RemoteData<PaginatedList<EPerson>>> {
switch (href) {
case 'https://dspace.4science.it/dspace-spring-rest/api/eperson/groups/testgroupid2/epersons':
return createSuccessfulRemoteDataObject$(buildPaginatedList(new PageInfo({ elementsPerPage: 1, totalElements: 0, totalPages: 0, currentPage: 1 }), []));
return createSuccessfulRemoteDataObject$(buildPaginatedList(new PageInfo({
elementsPerPage: 1,
totalElements: 0,
totalPages: 0,
currentPage: 1
}), []));
case 'https://dspace.4science.it/dspace-spring-rest/api/eperson/groups/testgroupid/epersons':
return createSuccessfulRemoteDataObject$(buildPaginatedList(new PageInfo({ elementsPerPage: 1, totalElements: 1, totalPages: 1, currentPage: 1 }), [EPersonMock]));
return createSuccessfulRemoteDataObject$(buildPaginatedList(new PageInfo({
elementsPerPage: 1,
totalElements: 1,
totalPages: 1,
currentPage: 1
}), [EPersonMock]));
default:
return createSuccessfulRemoteDataObject$(buildPaginatedList(new PageInfo({ elementsPerPage: 1, totalElements: 0, totalPages: 0, currentPage: 1 }), []));
return createSuccessfulRemoteDataObject$(buildPaginatedList(new PageInfo({
elementsPerPage: 1,
totalElements: 0,
totalPages: 0,
currentPage: 1
}), []));
}
}
};
@@ -60,11 +75,26 @@ describe('GroupRegistryComponent', () => {
findAllByHref(href: string): Observable<RemoteData<PaginatedList<Group>>> {
switch (href) {
case 'https://dspace.4science.it/dspace-spring-rest/api/eperson/groups/testgroupid2/groups':
return createSuccessfulRemoteDataObject$(buildPaginatedList(new PageInfo({ elementsPerPage: 1, totalElements: 0, totalPages: 0, currentPage: 1 }), []));
return createSuccessfulRemoteDataObject$(buildPaginatedList(new PageInfo({
elementsPerPage: 1,
totalElements: 0,
totalPages: 0,
currentPage: 1
}), []));
case 'https://dspace.4science.it/dspace-spring-rest/api/eperson/groups/testgroupid/groups':
return createSuccessfulRemoteDataObject$(buildPaginatedList(new PageInfo({ elementsPerPage: 1, totalElements: 1, totalPages: 1, currentPage: 1 }), [GroupMock2]));
return createSuccessfulRemoteDataObject$(buildPaginatedList(new PageInfo({
elementsPerPage: 1,
totalElements: 1,
totalPages: 1,
currentPage: 1
}), [GroupMock2]));
default:
return createSuccessfulRemoteDataObject$(buildPaginatedList(new PageInfo({ elementsPerPage: 1, totalElements: 0, totalPages: 0, currentPage: 1 }), []));
return createSuccessfulRemoteDataObject$(buildPaginatedList(new PageInfo({
elementsPerPage: 1,
totalElements: 0,
totalPages: 0,
currentPage: 1
}), []));
}
},
getGroupEditPageRouterLink(group: Group): string {
@@ -75,19 +105,29 @@ describe('GroupRegistryComponent', () => {
},
searchGroups(query: string): Observable<RemoteData<PaginatedList<Group>>> {
if (query === '') {
return createSuccessfulRemoteDataObject$(buildPaginatedList(new PageInfo({ elementsPerPage: this.allGroups.length, totalElements: this.allGroups.length, totalPages: 1, currentPage: 1 }), this.allGroups));
return createSuccessfulRemoteDataObject$(buildPaginatedList(new PageInfo({
elementsPerPage: this.allGroups.length,
totalElements: this.allGroups.length,
totalPages: 1,
currentPage: 1
}), this.allGroups));
}
const result = this.allGroups.find((group: Group) => {
return (group.id.includes(query))
return (group.id.includes(query));
});
return createSuccessfulRemoteDataObject$(buildPaginatedList(new PageInfo({ elementsPerPage: [result].length, totalElements: [result].length, totalPages: 1, currentPage: 1 }), [result]));
return createSuccessfulRemoteDataObject$(buildPaginatedList(new PageInfo({
elementsPerPage: [result].length,
totalElements: [result].length,
totalPages: 1,
currentPage: 1
}), [result]));
}
};
dsoDataServiceStub = {
findByHref(href: string): Observable<RemoteData<DSpaceObject>> {
return createSuccessfulRemoteDataObject$(undefined);
}
}
};
authorizationService = jasmine.createSpyObj('authorizationService', {
isAuthorized: observableOf(true)
});
@@ -109,7 +149,7 @@ describe('GroupRegistryComponent', () => {
{ provide: RouteService, useValue: routeServiceStub },
{ provide: Router, useValue: new RouterMock() },
{ provide: AuthorizationDataService, useValue: authorizationService },
{ provide: RequestService, useValue: jasmine.createSpyObj('requestService', ['removeByHrefSubstring'])}
{ provide: RequestService, useValue: jasmine.createSpyObj('requestService', ['removeByHrefSubstring']) }
],
schemas: [NO_ERRORS_SCHEMA]
}).compileComponents();
@@ -132,7 +172,7 @@ describe('GroupRegistryComponent', () => {
expect(groupIdsFound.find((foundEl) => {
return (foundEl.nativeElement.textContent.trim() === group.uuid);
})).toBeTruthy();
})
});
});
describe('search', () => {

View File

@@ -2,15 +2,8 @@ import { Component, OnDestroy, OnInit } from '@angular/core';
import { FormBuilder } from '@angular/forms';
import { Router } from '@angular/router';
import { TranslateService } from '@ngx-translate/core';
import {
BehaviorSubject,
combineLatest as observableCombineLatest,
Subscription,
Observable,
of as observableOf
} from 'rxjs';
import { filter } from 'rxjs/internal/operators/filter';
import { ObservedValueOf } from 'rxjs/internal/types';
import { BehaviorSubject, combineLatest as observableCombineLatest, Subscription, Observable, ObservedValueOf, of as observableOf } from 'rxjs';
import { filter } from 'rxjs/operators';
import { catchError, map, switchMap, take } from 'rxjs/operators';
import { DSpaceObjectDataService } from '../../../core/data/dspace-object-data.service';
import { AuthorizationDataService } from '../../../core/data/feature-authorization/authorization-data.service';
@@ -108,7 +101,7 @@ export class GroupsRegistryComponent implements OnInit, OnDestroy {
*/
onPageChange(event) {
this.config.currentPage = event;
this.search({ query: this.currentSearchQuery })
this.search({ query: this.currentSearchQuery });
}
/**
@@ -145,10 +138,10 @@ export class GroupsRegistryComponent implements OnInit, OnDestroy {
groupDtoModel.group = group;
return groupDtoModel;
}
)
);
})).pipe(map((dtos: GroupDtoModel[]) => {
return buildPaginatedList(groups.pageInfo, dtos);
}))
}));
})).subscribe((value: PaginatedList<GroupDtoModel>) => {
this.groupsDto$.next(value);
this.pageInfoState$.next(value.pageInfo);
@@ -170,7 +163,7 @@ export class GroupsRegistryComponent implements OnInit, OnDestroy {
this.translateService.get(this.messagePrefix + 'notification.deleted.failure.title', { name: group.name }),
this.translateService.get(this.messagePrefix + 'notification.deleted.failure.content', { cause: rd.errorMessage }));
}
})
});
}
}
@@ -210,13 +203,7 @@ export class GroupsRegistryComponent implements OnInit, OnDestroy {
*/
hasLinkedDSO(group: Group): Observable<boolean> {
return this.dSpaceObjectDataService.findByHref(group._links.object.href).pipe(
map((rd: RemoteData<DSpaceObject>) => {
if (hasValue(rd) && hasValue(rd.payload)) {
return true;
} else {
return false
}
}),
map((rd: RemoteData<DSpaceObject>) => hasValue(rd) && hasValue(rd.payload)),
catchError(() => observableOf(false)),
);
}

View File

@@ -1,4 +1,4 @@
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing';
import { AdminCurationTasksComponent } from './admin-curation-tasks.component';
import { TranslateModule } from '@ngx-translate/core';
import { CUSTOM_ELEMENTS_SCHEMA } from '@angular/core';
@@ -7,7 +7,7 @@ describe('AdminCurationTasksComponent', () => {
let comp: AdminCurationTasksComponent;
let fixture: ComponentFixture<AdminCurationTasksComponent>;
beforeEach(async(() => {
beforeEach(waitForAsync(() => {
TestBed.configureTestingModule({
imports: [TranslateModule.forRoot()],
declarations: [AdminCurationTasksComponent],

View File

@@ -1,17 +1,14 @@
import { Location } from '@angular/common';
import { NO_ERRORS_SCHEMA } from '@angular/core';
import { async, ComponentFixture, fakeAsync, TestBed } from '@angular/core/testing';
import { ComponentFixture, fakeAsync, TestBed, waitForAsync } from '@angular/core/testing';
import { FormsModule } from '@angular/forms';
import { By } from '@angular/platform-browser';
import { Router } from '@angular/router';
import { RouterTestingModule } from '@angular/router/testing';
import { TranslateModule } from '@ngx-translate/core';
import { of as observableOf } from 'rxjs/internal/observable/of';
import { of as observableOf } from 'rxjs';
import { AuthService } from '../../core/auth/auth.service';
import {
METADATA_IMPORT_SCRIPT_NAME,
ScriptDataService
} from '../../core/data/processes/script-data.service';
import { METADATA_IMPORT_SCRIPT_NAME, ScriptDataService } from '../../core/data/processes/script-data.service';
import { EPerson } from '../../core/eperson/models/eperson.model';
import { ProcessParameter } from '../../process-page/processes/process-parameter.model';
import { NotificationsService } from '../../shared/notifications/notifications.service';
@@ -55,7 +52,7 @@ describe('MetadataImportPageComponent', () => {
});
}
beforeEach(async(() => {
beforeEach(waitForAsync(() => {
init();
TestBed.configureTestingModule({
imports: [

View File

@@ -2,13 +2,10 @@ import { Location } from '@angular/common';
import { Component, OnInit } from '@angular/core';
import { Router } from '@angular/router';
import { TranslateService } from '@ngx-translate/core';
import { Observable } from 'rxjs/internal/Observable';
import { Observable } from 'rxjs';
import { map, switchMap } from 'rxjs/operators';
import { AuthService } from '../../core/auth/auth.service';
import {
METADATA_IMPORT_SCRIPT_NAME,
ScriptDataService
} from '../../core/data/processes/script-data.service';
import { METADATA_IMPORT_SCRIPT_NAME, ScriptDataService } from '../../core/data/processes/script-data.service';
import { EPerson } from '../../core/eperson/models/eperson.model';
import { ProcessParameter } from '../../process-page/processes/process-parameter.model';
import { isNotEmpty } from '../../shared/empty.util';
@@ -84,7 +81,7 @@ export class MetadataImportPageComponent implements OnInit {
Object.assign(new ProcessParameter(), { name: '-e', value: email }),
Object.assign(new ProcessParameter(), { name: '-f', value: this.fileObject.name }),
];
return this.scriptDataService.invoke(METADATA_IMPORT_SCRIPT_NAME, parameterValues, [this.fileObject])
return this.scriptDataService.invoke(METADATA_IMPORT_SCRIPT_NAME, parameterValues, [this.fileObject]);
}
}),
getFirstCompletedRemoteData(),

View File

@@ -28,7 +28,8 @@ import { BITSTREAMFORMATS_MODULE_PATH } from './admin-registries-routing-paths';
{
path: BITSTREAMFORMATS_MODULE_PATH,
resolve: { breadcrumb: I18nBreadcrumbResolver },
loadChildren: './bitstream-formats/bitstream-formats.module#BitstreamFormatsModule',
loadChildren: () => import('./bitstream-formats/bitstream-formats.module')
.then((m) => m.BitstreamFormatsModule),
data: {title: 'admin.registries.bitstream-formats.title', breadcrumbKey: 'admin.registries.bitstream-formats'}
},
])

View File

@@ -4,7 +4,6 @@ import { AdminRegistriesRoutingModule } from './admin-registries-routing.module'
import { CommonModule } from '@angular/common';
import { MetadataSchemaComponent } from './metadata-schema/metadata-schema.component';
import { RouterModule } from '@angular/router';
import { TranslateModule } from '@ngx-translate/core';
import { SharedModule } from '../../shared/shared.module';
import { MetadataSchemaFormComponent } from './metadata-registry/metadata-schema-form/metadata-schema-form.component';
import { MetadataFieldFormComponent } from './metadata-schema/metadata-field-form/metadata-field-form.component';
@@ -15,7 +14,6 @@ import { BitstreamFormatsModule } from './bitstream-formats/bitstream-formats.mo
CommonModule,
SharedModule,
RouterModule,
TranslateModule,
BitstreamFormatsModule,
AdminRegistriesRoutingModule
],
@@ -24,9 +22,6 @@ import { BitstreamFormatsModule } from './bitstream-formats/bitstream-formats.mo
MetadataSchemaComponent,
MetadataSchemaFormComponent,
MetadataFieldFormComponent
],
entryComponents: [
]
})
export class AdminRegistriesModule {

View File

@@ -1,6 +1,6 @@
import { CommonModule } from '@angular/common';
import { CUSTOM_ELEMENTS_SCHEMA } from '@angular/core';
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing';
import { Router } from '@angular/router';
import { RouterTestingModule } from '@angular/router/testing';
import { NgbModule } from '@ng-bootstrap/ng-bootstrap';
@@ -45,9 +45,9 @@ describe('AddBitstreamFormatComponent', () => {
imports: [CommonModule, RouterTestingModule.withRoutes([]), TranslateModule.forRoot(), NgbModule],
declarations: [AddBitstreamFormatComponent],
providers: [
{provide: Router, useValue: router},
{provide: NotificationsService, useValue: notificationService},
{provide: BitstreamFormatDataService, useValue: bitstreamFormatDataService},
{ provide: Router, useValue: router },
{ provide: NotificationsService, useValue: notificationService },
{ provide: BitstreamFormatDataService, useValue: bitstreamFormatDataService },
],
schemas: [CUSTOM_ELEMENTS_SCHEMA]
}).compileComponents();
@@ -61,7 +61,7 @@ describe('AddBitstreamFormatComponent', () => {
};
describe('createBitstreamFormat success', () => {
beforeEach(async(initAsync));
beforeEach(waitForAsync(initAsync));
beforeEach(initBeforeEach);
it('should send the updated form to the service, show a notification and navigate to ', () => {
comp.createBitstreamFormat(bitstreamFormat);
@@ -73,7 +73,7 @@ describe('AddBitstreamFormatComponent', () => {
});
});
describe('createBitstreamFormat error', () => {
beforeEach(async(() => {
beforeEach(waitForAsync(() => {
router = new RouterStub();
notificationService = new NotificationsServiceStub();
bitstreamFormatDataService = jasmine.createSpyObj('bitstreamFormatDataService', {
@@ -85,9 +85,9 @@ describe('AddBitstreamFormatComponent', () => {
imports: [CommonModule, RouterTestingModule.withRoutes([]), TranslateModule.forRoot(), NgbModule],
declarations: [AddBitstreamFormatComponent],
providers: [
{provide: Router, useValue: router},
{provide: NotificationsService, useValue: notificationService},
{provide: BitstreamFormatDataService, useValue: bitstreamFormatDataService},
{ provide: Router, useValue: router },
{ provide: NotificationsService, useValue: notificationService },
{ provide: BitstreamFormatDataService, useValue: bitstreamFormatDataService },
],
schemas: [CUSTOM_ELEMENTS_SCHEMA]
}).compileComponents();

View File

@@ -61,4 +61,4 @@ export class BitstreamFormatsRegistryDeselectAllAction implements Action {
export type BitstreamFormatsRegistryAction
= BitstreamFormatsRegistrySelectAction
| BitstreamFormatsRegistryDeselectAction
| BitstreamFormatsRegistryDeselectAllAction
| BitstreamFormatsRegistryDeselectAllAction;

View File

@@ -1,5 +1,5 @@
import { BitstreamFormatsComponent } from './bitstream-formats.component';
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing';
import { of as observableOf } from 'rxjs';
import { CommonModule } from '@angular/common';
import { RouterTestingModule } from '@angular/router/testing';
@@ -87,7 +87,7 @@ describe('BitstreamFormatsComponent', () => {
bitstreamFormatService = jasmine.createSpyObj('bitstreamFormatService', {
findAll: observableOf(mockFormatsRD),
find: createSuccessfulRemoteDataObject$(mockFormatsList[0]),
getSelectedBitstreamFormats: hot('a', {a: mockFormatsList}),
getSelectedBitstreamFormats: hot('a', { a: mockFormatsList }),
selectBitstreamFormat: {},
deselectBitstreamFormat: {},
deselectAllBitstreamFormats: {},
@@ -99,9 +99,9 @@ describe('BitstreamFormatsComponent', () => {
imports: [CommonModule, RouterTestingModule.withRoutes([]), TranslateModule.forRoot(), NgbModule],
declarations: [BitstreamFormatsComponent, PaginationComponent, EnumKeysPipe],
providers: [
{provide: BitstreamFormatDataService, useValue: bitstreamFormatService},
{provide: HostWindowService, useValue: new HostWindowServiceStub(0)},
{provide: NotificationsService, useValue: notificationsServiceStub}
{ provide: BitstreamFormatDataService, useValue: bitstreamFormatService },
{ provide: HostWindowService, useValue: new HostWindowServiceStub(0) },
{ provide: NotificationsService, useValue: notificationsServiceStub }
]
}).compileComponents();
};
@@ -113,7 +113,7 @@ describe('BitstreamFormatsComponent', () => {
};
describe('Bitstream format page content', () => {
beforeEach(async(initAsync));
beforeEach(waitForAsync(initAsync));
beforeEach(initBeforeEach);
it('should contain four formats', () => {
@@ -137,17 +137,17 @@ describe('BitstreamFormatsComponent', () => {
});
describe('selectBitStreamFormat', () => {
beforeEach(async(initAsync));
beforeEach(waitForAsync(initAsync));
beforeEach(initBeforeEach);
it('should select a bitstreamFormat if it was selected in the event', () => {
const event = {target: {checked: true}};
const event = { target: { checked: true } };
comp.selectBitStreamFormat(bitstreamFormat1, event);
expect(bitstreamFormatService.selectBitstreamFormat).toHaveBeenCalledWith(bitstreamFormat1);
});
it('should deselect a bitstreamFormat if it is deselected in the event', () => {
const event = {target: {checked: false}};
const event = { target: { checked: false } };
comp.selectBitStreamFormat(bitstreamFormat1, event);
@@ -157,7 +157,7 @@ describe('BitstreamFormatsComponent', () => {
spyOn(comp, 'selectBitStreamFormat');
const unknownFormat = fixture.debugElement.query(By.css('#formats tr:nth-child(1) input'));
const event = {target: {checked: true}};
const event = { target: { checked: true } };
unknownFormat.triggerEventHandler('change', event);
expect(comp.selectBitStreamFormat).toHaveBeenCalledWith(bitstreamFormat1, event);
@@ -165,12 +165,12 @@ describe('BitstreamFormatsComponent', () => {
});
describe('isSelected', () => {
beforeEach(async(initAsync));
beforeEach(waitForAsync(initAsync));
beforeEach(initBeforeEach);
it('should return an observable of true if the provided bistream is in the list returned by the service', () => {
const result = comp.isSelected(bitstreamFormat1);
expect(result).toBeObservable(cold('b', {b: true}));
expect(result).toBeObservable(cold('b', { b: true }));
});
it('should return an observable of false if the provided bistream is not in the list returned by the service', () => {
const format = new BitstreamFormat();
@@ -178,12 +178,12 @@ describe('BitstreamFormatsComponent', () => {
const result = comp.isSelected(format);
expect(result).toBeObservable(cold('b', {b: false}));
expect(result).toBeObservable(cold('b', { b: false }));
});
});
describe('deselectAll', () => {
beforeEach(async(initAsync));
beforeEach(waitForAsync(initAsync));
beforeEach(initBeforeEach);
it('should deselect all bitstreamFormats', () => {
comp.deselectAll();
@@ -201,7 +201,7 @@ describe('BitstreamFormatsComponent', () => {
});
describe('deleteFormats success', () => {
beforeEach(async(() => {
beforeEach(waitForAsync(() => {
notificationsServiceStub = new NotificationsServiceStub();
scheduler = getTestScheduler();
@@ -221,9 +221,9 @@ describe('BitstreamFormatsComponent', () => {
imports: [CommonModule, RouterTestingModule.withRoutes([]), TranslateModule.forRoot(), NgbModule],
declarations: [BitstreamFormatsComponent, PaginationComponent, EnumKeysPipe],
providers: [
{provide: BitstreamFormatDataService, useValue: bitstreamFormatService},
{provide: HostWindowService, useValue: new HostWindowServiceStub(0)},
{provide: NotificationsService, useValue: notificationsServiceStub}
{ provide: BitstreamFormatDataService, useValue: bitstreamFormatService },
{ provide: HostWindowService, useValue: new HostWindowServiceStub(0) },
{ provide: NotificationsService, useValue: notificationsServiceStub }
]
}).compileComponents();
}
@@ -247,7 +247,7 @@ describe('BitstreamFormatsComponent', () => {
});
describe('deleteFormats error', () => {
beforeEach(async(() => {
beforeEach(waitForAsync(() => {
notificationsServiceStub = new NotificationsServiceStub();
scheduler = getTestScheduler();
@@ -267,9 +267,9 @@ describe('BitstreamFormatsComponent', () => {
imports: [CommonModule, RouterTestingModule.withRoutes([]), TranslateModule.forRoot(), NgbModule],
declarations: [BitstreamFormatsComponent, PaginationComponent, EnumKeysPipe],
providers: [
{provide: BitstreamFormatDataService, useValue: bitstreamFormatService},
{provide: HostWindowService, useValue: new HostWindowServiceStub(0)},
{provide: NotificationsService, useValue: notificationsServiceStub}
{ provide: BitstreamFormatDataService, useValue: bitstreamFormatService },
{ provide: HostWindowService, useValue: new HostWindowServiceStub(0) },
{ provide: NotificationsService, useValue: notificationsServiceStub }
]
}).compileComponents();
}

View File

@@ -1,7 +1,6 @@
import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { RouterModule } from '@angular/router';
import { TranslateModule } from '@ngx-translate/core';
import { BitstreamFormatsComponent } from './bitstream-formats.component';
import { SharedModule } from '../../../shared/shared.module';
import { FormatFormComponent } from './format-form/format-form.component';
@@ -14,7 +13,6 @@ import { AddBitstreamFormatComponent } from './add-bitstream-format/add-bitstrea
CommonModule,
SharedModule,
RouterModule,
TranslateModule,
BitstreamFormatsRoutingModule
],
declarations: [
@@ -22,8 +20,7 @@ import { AddBitstreamFormatComponent } from './add-bitstream-format/add-bitstrea
EditBitstreamFormatComponent,
AddBitstreamFormatComponent,
FormatFormComponent
],
entryComponents: []
]
})
export class BitstreamFormatsModule {

View File

@@ -1,6 +1,6 @@
import { CommonModule } from '@angular/common';
import { CUSTOM_ELEMENTS_SCHEMA } from '@angular/core';
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing';
import { ActivatedRoute, Router } from '@angular/router';
import { RouterTestingModule } from '@angular/router/testing';
import { NgbModule } from '@ng-bootstrap/ng-bootstrap';
@@ -45,7 +45,7 @@ describe('EditBitstreamFormatComponent', () => {
let bitstreamFormatDataService: BitstreamFormatDataService;
const initAsync = () => {
router = new RouterStub();
router = new RouterStub();
notificationService = new NotificationsServiceStub();
bitstreamFormatDataService = jasmine.createSpyObj('bitstreamFormatDataService', {
updateBitstreamFormat: createSuccessfulRemoteDataObject$({})
@@ -55,10 +55,10 @@ describe('EditBitstreamFormatComponent', () => {
imports: [CommonModule, RouterTestingModule.withRoutes([]), TranslateModule.forRoot(), NgbModule],
declarations: [EditBitstreamFormatComponent],
providers: [
{provide: ActivatedRoute, useValue: routeStub},
{provide: Router, useValue: router},
{provide: NotificationsService, useValue: notificationService},
{provide: BitstreamFormatDataService, useValue: bitstreamFormatDataService},
{ provide: ActivatedRoute, useValue: routeStub },
{ provide: Router, useValue: router },
{ provide: NotificationsService, useValue: notificationService },
{ provide: BitstreamFormatDataService, useValue: bitstreamFormatDataService },
],
schemas: [CUSTOM_ELEMENTS_SCHEMA]
}).compileComponents();
@@ -72,7 +72,7 @@ describe('EditBitstreamFormatComponent', () => {
};
describe('init', () => {
beforeEach(async(initAsync));
beforeEach(waitForAsync(initAsync));
beforeEach(initBeforeEach);
it('should initialise the bitstreamFormat based on the route', () => {
@@ -83,7 +83,7 @@ describe('EditBitstreamFormatComponent', () => {
});
});
describe('updateFormat success', () => {
beforeEach(async(initAsync));
beforeEach(waitForAsync(initAsync));
beforeEach(initBeforeEach);
it('should send the updated form to the service, show a notification and navigate to ', () => {
comp.updateFormat(bitstreamFormat);
@@ -95,8 +95,8 @@ describe('EditBitstreamFormatComponent', () => {
});
});
describe('updateFormat error', () => {
beforeEach(async( () => {
router = new RouterStub();
beforeEach(waitForAsync(() => {
router = new RouterStub();
notificationService = new NotificationsServiceStub();
bitstreamFormatDataService = jasmine.createSpyObj('bitstreamFormatDataService', {
updateBitstreamFormat: createFailedRemoteDataObject$('Error', 500)
@@ -106,10 +106,10 @@ describe('EditBitstreamFormatComponent', () => {
imports: [CommonModule, RouterTestingModule.withRoutes([]), TranslateModule.forRoot(), NgbModule],
declarations: [EditBitstreamFormatComponent],
providers: [
{provide: ActivatedRoute, useValue: routeStub},
{provide: Router, useValue: router},
{provide: NotificationsService, useValue: notificationService},
{provide: BitstreamFormatDataService, useValue: bitstreamFormatDataService},
{ provide: ActivatedRoute, useValue: routeStub },
{ provide: Router, useValue: router },
{ provide: NotificationsService, useValue: notificationService },
{ provide: BitstreamFormatDataService, useValue: bitstreamFormatDataService },
],
schemas: [CUSTOM_ELEMENTS_SCHEMA]
}).compileComponents();

View File

@@ -1,4 +1,4 @@
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing';
import { CommonModule } from '@angular/common';
import { RouterTestingModule } from '@angular/router/testing';
import { TranslateModule } from '@ngx-translate/core';
@@ -43,7 +43,7 @@ describe('FormatFormComponent', () => {
imports: [CommonModule, RouterTestingModule.withRoutes([]), ReactiveFormsModule, FormsModule, TranslateModule.forRoot(), NgbModule],
declarations: [FormatFormComponent],
providers: [
{provide: Router, useValue: router},
{ provide: Router, useValue: router },
],
schemas: [CUSTOM_ELEMENTS_SCHEMA]
}).compileComponents();
@@ -58,7 +58,7 @@ describe('FormatFormComponent', () => {
};
describe('initialise', () => {
beforeEach(async(initAsync));
beforeEach(waitForAsync(initAsync));
beforeEach(initBeforeEach);
it('should initialises the values in the form', () => {
@@ -82,7 +82,7 @@ describe('FormatFormComponent', () => {
});
});
describe('onSubmit', () => {
beforeEach(async(initAsync));
beforeEach(waitForAsync(initAsync));
beforeEach(initBeforeEach);
it('should emit the bitstreamFormat currently present in the form', () => {
@@ -93,7 +93,7 @@ describe('FormatFormComponent', () => {
});
});
describe('onCancel', () => {
beforeEach(async(initAsync));
beforeEach(waitForAsync(initAsync));
beforeEach(initBeforeEach);
it('should navigate back to the bitstream overview', () => {

View File

@@ -4,7 +4,7 @@ import { BitstreamFormatSupportLevel } from '../../../../core/shared/bitstream-f
import {
DynamicCheckboxModel,
DynamicFormArrayModel,
DynamicFormControlLayout, DynamicFormControlLayoutConfig,
DynamicFormControlLayout,
DynamicFormControlModel,
DynamicFormService,
DynamicInputModel,

View File

@@ -1,5 +1,5 @@
import { MetadataRegistryComponent } from './metadata-registry.component';
import { async, ComponentFixture, inject, TestBed } from '@angular/core/testing';
import { ComponentFixture, inject, TestBed, waitForAsync } from '@angular/core/testing';
import { of as observableOf } from 'rxjs';
import { buildPaginatedList } from '../../../core/data/paginated-list.model';
import { TranslateModule } from '@ngx-translate/core';
@@ -51,15 +51,18 @@ describe('MetadataRegistryComponent', () => {
getMetadataSchemas: () => mockSchemas,
getActiveMetadataSchema: () => observableOf(undefined),
getSelectedMetadataSchemas: () => observableOf([]),
editMetadataSchema: (schema) => {},
cancelEditMetadataSchema: () => {},
editMetadataSchema: (schema) => {
},
cancelEditMetadataSchema: () => {
},
deleteMetadataSchema: () => observableOf(new RestResponse(true, 200, 'OK')),
deselectAllMetadataSchema: () => {},
deselectAllMetadataSchema: () => {
},
clearMetadataSchemaRequests: () => observableOf(undefined)
};
/* tslint:enable:no-empty */
beforeEach(async(() => {
beforeEach(waitForAsync(() => {
TestBed.configureTestingModule({
imports: [CommonModule, RouterTestingModule.withRoutes([]), TranslateModule.forRoot(), NgbModule],
declarations: [MetadataRegistryComponent, PaginationComponent, EnumKeysPipe],
@@ -107,13 +110,13 @@ describe('MetadataRegistryComponent', () => {
fixture.detectChanges();
});
it('should start editing the selected schema', async(() => {
it('should start editing the selected schema', waitForAsync(() => {
fixture.whenStable().then(() => {
expect(registryService.editMetadataSchema).toHaveBeenCalledWith(mockSchemasList[0] as MetadataSchema);
});
}));
it('should cancel editing the selected schema when clicked again', async(() => {
it('should cancel editing the selected schema when clicked again', waitForAsync(() => {
spyOn(registryService, 'getActiveMetadataSchema').and.returnValue(observableOf(mockSchemasList[0] as MetadataSchema));
spyOn(registryService, 'cancelEditMetadataSchema');
row.click();
@@ -134,7 +137,7 @@ describe('MetadataRegistryComponent', () => {
fixture.detectChanges();
});
it('should call deleteMetadataSchema with the selected id', async(() => {
it('should call deleteMetadataSchema with the selected id', waitForAsync(() => {
fixture.whenStable().then(() => {
expect(registryService.deleteMetadataSchema).toHaveBeenCalledWith(selectedSchemas[0].id);
});

View File

@@ -1,18 +1,16 @@
import { Component } from '@angular/core';
import { RegistryService } from '../../../core/registry/registry.service';
import { Observable, combineLatest as observableCombineLatest } from 'rxjs';
import { BehaviorSubject, combineLatest as observableCombineLatest, Observable, zip } from 'rxjs';
import { RemoteData } from '../../../core/data/remote-data';
import { PaginatedList } from '../../../core/data/paginated-list.model';
import { PaginationComponentOptions } from '../../../shared/pagination/pagination-component-options.model';
import { filter, map, switchMap, take } from 'rxjs/operators';
import { hasValue } from '../../../shared/empty.util';
import { zip } from 'rxjs/internal/observable/zip';
import { NotificationsService } from '../../../shared/notifications/notifications.service';
import { Router } from '@angular/router';
import { TranslateService } from '@ngx-translate/core';
import { MetadataSchema } from '../../../core/metadata/metadata-schema.model';
import { toFindListOptions } from '../../../shared/pagination/pagination.utils';
import { BehaviorSubject } from 'rxjs/internal/BehaviorSubject';
import { NoContent } from '../../../core/shared/NoContent.model';
import { getFirstCompletedRemoteData } from '../../../core/shared/operators';
@@ -144,7 +142,7 @@ export class MetadataRegistryComponent {
tasks$.push(this.registryService.deleteMetadataSchema(schema.id).pipe(getFirstCompletedRemoteData()));
}
}
zip(...tasks$).subscribe((responses: Array<RemoteData<NoContent>>) => {
zip(...tasks$).subscribe((responses: RemoteData<NoContent>[]) => {
const successResponses = responses.filter((response: RemoteData<NoContent>) => response.hasSucceeded);
const failedResponses = responses.filter((response: RemoteData<NoContent>) => response.hasFailed);
if (successResponses.length > 0) {
@@ -158,7 +156,7 @@ export class MetadataRegistryComponent {
this.forceUpdateSchemas();
});
}
)
);
}
/**
@@ -175,9 +173,9 @@ export class MetadataRegistryComponent {
);
messages.subscribe(([head, content]) => {
if (success) {
this.notificationsService.success(head, content)
this.notificationsService.success(head, content);
} else {
this.notificationsService.error(head, content)
this.notificationsService.error(head, content);
}
});
}

View File

@@ -1,9 +1,13 @@
import {
MetadataRegistryCancelFieldAction,
MetadataRegistryCancelSchemaAction, MetadataRegistryDeselectAllFieldAction,
MetadataRegistryDeselectAllSchemaAction, MetadataRegistryDeselectFieldAction,
MetadataRegistryDeselectSchemaAction, MetadataRegistryEditFieldAction,
MetadataRegistryEditSchemaAction, MetadataRegistrySelectFieldAction,
MetadataRegistryCancelSchemaAction,
MetadataRegistryDeselectAllFieldAction,
MetadataRegistryDeselectAllSchemaAction,
MetadataRegistryDeselectFieldAction,
MetadataRegistryDeselectSchemaAction,
MetadataRegistryEditFieldAction,
MetadataRegistryEditSchemaAction,
MetadataRegistrySelectFieldAction,
MetadataRegistrySelectSchemaAction
} from './metadata-registry.actions';
import { metadataRegistryReducer, MetadataRegistryState } from './metadata-registry.reducers';
@@ -12,6 +16,7 @@ import { MetadataField } from '../../../core/metadata/metadata-field.model';
class NullAction extends MetadataRegistryEditSchemaAction {
type = null;
constructor() {
super(undefined);
}

View File

@@ -1,4 +1,4 @@
import { async, ComponentFixture, inject, TestBed } from '@angular/core/testing';
import { ComponentFixture, inject, TestBed, waitForAsync } from '@angular/core/testing';
import { MetadataSchemaFormComponent } from './metadata-schema-form.component';
import { NO_ERRORS_SCHEMA } from '@angular/core';
@@ -9,7 +9,7 @@ import { NgbModule } from '@ng-bootstrap/ng-bootstrap';
import { EnumKeysPipe } from '../../../../shared/utils/enum-keys-pipe';
import { RegistryService } from '../../../../core/registry/registry.service';
import { FormBuilderService } from '../../../../shared/form/builder/form-builder.service';
import { of as observableOf } from 'rxjs/internal/observable/of';
import { of as observableOf } from 'rxjs';
import { MetadataSchema } from '../../../../core/metadata/metadata-schema.model';
describe('MetadataSchemaFormComponent', () => {
@@ -21,22 +21,24 @@ describe('MetadataSchemaFormComponent', () => {
const registryServiceStub = {
getActiveMetadataSchema: () => observableOf(undefined),
createOrUpdateMetadataSchema: (schema: MetadataSchema) => observableOf(schema),
cancelEditMetadataSchema: () => {},
cancelEditMetadataSchema: () => {
},
clearMetadataSchemaRequests: () => observableOf(undefined)
};
const formBuilderServiceStub = {
createFormGroup: () => {
return {
patchValue: () => {}
patchValue: () => {
}
};
}
};
/* tslint:enable:no-empty */
beforeEach(async(() => {
beforeEach(waitForAsync(() => {
TestBed.configureTestingModule({
imports: [CommonModule, RouterTestingModule.withRoutes([]), TranslateModule.forRoot(), NgbModule],
declarations: [ MetadataSchemaFormComponent, EnumKeysPipe ],
declarations: [MetadataSchemaFormComponent, EnumKeysPipe],
providers: [
{ provide: RegistryService, useValue: registryServiceStub },
{ provide: FormBuilderService, useValue: formBuilderServiceStub }
@@ -77,7 +79,7 @@ describe('MetadataSchemaFormComponent', () => {
fixture.detectChanges();
});
it('should emit a new schema using the correct values', async(() => {
it('should emit a new schema using the correct values', waitForAsync(() => {
fixture.whenStable().then(() => {
expect(component.submitForm.emit).toHaveBeenCalledWith(expected);
});
@@ -97,7 +99,7 @@ describe('MetadataSchemaFormComponent', () => {
fixture.detectChanges();
});
it('should edit the existing schema using the correct values', async(() => {
it('should edit the existing schema using the correct values', waitForAsync(() => {
fixture.whenStable().then(() => {
expect(component.submitForm.emit).toHaveBeenCalledWith(expectedWithId);
});

View File

@@ -10,7 +10,7 @@ import { RegistryService } from '../../../../core/registry/registry.service';
import { FormBuilderService } from '../../../../shared/form/builder/form-builder.service';
import { take } from 'rxjs/operators';
import { TranslateService } from '@ngx-translate/core';
import { combineLatest } from 'rxjs/internal/observable/combineLatest';
import { combineLatest } from 'rxjs';
import { MetadataSchema } from '../../../../core/metadata/metadata-schema.model';
@Component({
@@ -101,14 +101,19 @@ export class MetadataSchemaFormComponent implements OnInit, OnDestroy {
required: true,
});
this.formModel = [
this.namespace,
this.name
new DynamicFormGroupModel(
{
id: 'metadatadataschemagroup',
group:[this.namespace, this.name]
})
];
this.formGroup = this.formBuilderService.createFormGroup(this.formModel);
this.registryService.getActiveMetadataSchema().subscribe((schema) => {
this.formGroup.patchValue({
name: schema != null ? schema.prefix : '',
namespace: schema != null ? schema.namespace : ''
metadatadataschemagroup:{
name: schema != null ? schema.prefix : '',
namespace: schema != null ? schema.namespace : ''
}
});
});
});
@@ -159,8 +164,10 @@ export class MetadataSchemaFormComponent implements OnInit, OnDestroy {
*/
clearFields() {
this.formGroup.patchValue({
prefix: '',
namespace: ''
metadatadataschemagroup:{
prefix: '',
namespace: ''
}
});
}

View File

@@ -1,8 +1,8 @@
import { async, ComponentFixture, inject, TestBed } from '@angular/core/testing';
import { ComponentFixture, inject, TestBed, waitForAsync } from '@angular/core/testing';
import { MetadataFieldFormComponent } from './metadata-field-form.component';
import { RegistryService } from '../../../../core/registry/registry.service';
import { of as observableOf } from 'rxjs/internal/observable/of';
import { of as observableOf } from 'rxjs';
import { CommonModule } from '@angular/common';
import { RouterTestingModule } from '@angular/router/testing';
import { TranslateModule } from '@ngx-translate/core';
@@ -29,23 +29,26 @@ describe('MetadataFieldFormComponent', () => {
getActiveMetadataField: () => observableOf(undefined),
createMetadataField: (field: MetadataField) => observableOf(field),
updateMetadataField: (field: MetadataField) => observableOf(field),
cancelEditMetadataField: () => {},
cancelEditMetadataSchema: () => {},
cancelEditMetadataField: () => {
},
cancelEditMetadataSchema: () => {
},
clearMetadataFieldRequests: () => observableOf(undefined)
};
const formBuilderServiceStub = {
createFormGroup: () => {
return {
patchValue: () => {}
patchValue: () => {
}
};
}
};
/* tslint:enable:no-empty */
beforeEach(async(() => {
beforeEach(waitForAsync(() => {
TestBed.configureTestingModule({
imports: [CommonModule, RouterTestingModule.withRoutes([]), TranslateModule.forRoot(), NgbModule],
declarations: [ MetadataFieldFormComponent, EnumKeysPipe ],
declarations: [MetadataFieldFormComponent, EnumKeysPipe],
providers: [
{ provide: RegistryService, useValue: registryServiceStub },
{ provide: FormBuilderService, useValue: formBuilderServiceStub }
@@ -67,8 +70,8 @@ describe('MetadataFieldFormComponent', () => {
afterEach(() => {
component = null;
registryService = null
})
registryService = null;
});
describe('when submitting the form', () => {
const element = 'fakeElement';
@@ -95,7 +98,7 @@ describe('MetadataFieldFormComponent', () => {
fixture.detectChanges();
});
it('should emit a new field using the correct values', async(() => {
it('should emit a new field using the correct values', waitForAsync(() => {
fixture.whenStable().then(() => {
expect(component.submitForm.emit).toHaveBeenCalledWith(expected);
});
@@ -117,7 +120,7 @@ describe('MetadataFieldFormComponent', () => {
fixture.detectChanges();
});
it('should edit the existing field using the correct values', async(() => {
it('should edit the existing field using the correct values', waitForAsync(() => {
fixture.whenStable().then(() => {
expect(component.submitForm.emit).toHaveBeenCalledWith(expectedWithId);
});

View File

@@ -1,6 +1,7 @@
import { Component, EventEmitter, Input, OnDestroy, OnInit, Output } from '@angular/core';
import {
DynamicFormControlModel,
DynamicFormGroupModel,
DynamicFormLayout,
DynamicInputModel
} from '@ng-dynamic-forms/core';
@@ -9,7 +10,7 @@ import { RegistryService } from '../../../../core/registry/registry.service';
import { FormBuilderService } from '../../../../shared/form/builder/form-builder.service';
import { take } from 'rxjs/operators';
import { TranslateService } from '@ngx-translate/core';
import { combineLatest } from 'rxjs/internal/observable/combineLatest';
import { combineLatest } from 'rxjs';
import { MetadataSchema } from '../../../../core/metadata/metadata-schema.model';
import { MetadataField } from '../../../../core/metadata/metadata-field.model';
@@ -124,16 +125,20 @@ export class MetadataFieldFormComponent implements OnInit, OnDestroy {
required: false,
});
this.formModel = [
this.element,
this.qualifier,
this.scopeNote
new DynamicFormGroupModel(
{
id: 'metadatadatafieldgroup',
group:[this.element, this.qualifier, this.scopeNote]
})
];
this.formGroup = this.formBuilderService.createFormGroup(this.formModel);
this.registryService.getActiveMetadataField().subscribe((field) => {
this.formGroup.patchValue({
element: field != null ? field.element : '',
qualifier: field != null ? field.qualifier : '',
scopeNote: field != null ? field.scopeNote : ''
metadatadatafieldgroup: {
element: field != null ? field.element : '',
qualifier: field != null ? field.qualifier : '',
scopeNote: field != null ? field.scopeNote : ''
}
});
});
});
@@ -186,9 +191,11 @@ export class MetadataFieldFormComponent implements OnInit, OnDestroy {
*/
clearFields() {
this.formGroup.patchValue({
element: '',
qualifier: '',
scopeNote: ''
metadatadatafieldgroup: {
element: '',
qualifier: '',
scopeNote: ''
}
});
}

View File

@@ -1,5 +1,5 @@
import { MetadataSchemaComponent } from './metadata-schema.component';
import { async, ComponentFixture, inject, TestBed } from '@angular/core/testing';
import { ComponentFixture, inject, TestBed, waitForAsync } from '@angular/core/testing';
import { of as observableOf } from 'rxjs';
import { buildPaginatedList } from '../../../core/data/paginated-list.model';
import { TranslateModule } from '@ngx-translate/core';
@@ -108,10 +108,13 @@ describe('MetadataSchemaComponent', () => {
getMetadataSchemaByPrefix: (schemaName: string) => createSuccessfulRemoteDataObject$(mockSchemasList.filter((value) => value.prefix === schemaName)[0]),
getActiveMetadataField: () => observableOf(undefined),
getSelectedMetadataFields: () => observableOf([]),
editMetadataField: (schema) => {},
cancelEditMetadataField: () => {},
editMetadataField: (schema) => {
},
cancelEditMetadataField: () => {
},
deleteMetadataField: () => observableOf(new RestResponse(true, 200, 'OK')),
deselectAllMetadataField: () => {},
deselectAllMetadataField: () => {
},
clearMetadataFieldRequests: () => observableOf(undefined)
};
/* tslint:enable:no-empty */
@@ -122,7 +125,7 @@ describe('MetadataSchemaComponent', () => {
})
});
beforeEach(async(() => {
beforeEach(waitForAsync(() => {
TestBed.configureTestingModule({
imports: [CommonModule, RouterTestingModule.withRoutes([]), TranslateModule.forRoot(), NgbModule],
declarations: [MetadataSchemaComponent, PaginationComponent, EnumKeysPipe, VarDirective],
@@ -175,13 +178,13 @@ describe('MetadataSchemaComponent', () => {
fixture.detectChanges();
});
it('should start editing the selected field', async(() => {
it('should start editing the selected field', waitForAsync(() => {
fixture.whenStable().then(() => {
expect(registryService.editMetadataField).toHaveBeenCalledWith(mockFieldsList[2] as MetadataField);
});
}));
it('should cancel editing the selected field when clicked again', async(() => {
it('should cancel editing the selected field when clicked again', waitForAsync(() => {
spyOn(registryService, 'getActiveMetadataField').and.returnValue(observableOf(mockFieldsList[2] as MetadataField));
spyOn(registryService, 'cancelEditMetadataField');
row.click();
@@ -202,7 +205,7 @@ describe('MetadataSchemaComponent', () => {
fixture.detectChanges();
});
it('should call deleteMetadataField with the selected id', async(() => {
it('should call deleteMetadataField with the selected id', waitForAsync(() => {
fixture.whenStable().then(() => {
expect(registryService.deleteMetadataField).toHaveBeenCalledWith(selectedFields[0].id);
});

View File

@@ -1,24 +1,18 @@
import { Component, OnInit } from '@angular/core';
import { RegistryService } from '../../../core/registry/registry.service';
import { ActivatedRoute, Router } from '@angular/router';
import { Observable, combineLatest as observableCombineLatest } from 'rxjs';
import { BehaviorSubject, combineLatest as observableCombineLatest, combineLatest, Observable, zip } from 'rxjs';
import { RemoteData } from '../../../core/data/remote-data';
import { PaginatedList } from '../../../core/data/paginated-list.model';
import { PaginationComponentOptions } from '../../../shared/pagination/pagination-component-options.model';
import { map, switchMap, take } from 'rxjs/operators';
import { hasValue } from '../../../shared/empty.util';
import { zip } from 'rxjs/internal/observable/zip';
import { NotificationsService } from '../../../shared/notifications/notifications.service';
import { TranslateService } from '@ngx-translate/core';
import { MetadataField } from '../../../core/metadata/metadata-field.model';
import { MetadataSchema } from '../../../core/metadata/metadata-schema.model';
import {
getFirstSucceededRemoteDataPayload,
getFirstCompletedRemoteData
} from '../../../core/shared/operators';
import { getFirstCompletedRemoteData, getFirstSucceededRemoteDataPayload } from '../../../core/shared/operators';
import { toFindListOptions } from '../../../shared/pagination/pagination.utils';
import { BehaviorSubject } from 'rxjs/internal/BehaviorSubject';
import { combineLatest } from 'rxjs/internal/observable/combineLatest';
import { followLink } from '../../../shared/utils/follow-link-config.model';
import { NoContent } from '../../../core/shared/NoContent.model';
@@ -174,7 +168,7 @@ export class MetadataSchemaComponent implements OnInit {
tasks$.push(this.registryService.deleteMetadataField(field.id).pipe(getFirstCompletedRemoteData()));
}
}
zip(...tasks$).subscribe((responses: Array<RemoteData<NoContent>>) => {
zip(...tasks$).subscribe((responses: RemoteData<NoContent>[]) => {
const successResponses = responses.filter((response: RemoteData<NoContent>) => response.hasSucceeded);
const failedResponses = responses.filter((response: RemoteData<NoContent>) => response.hasFailed);
if (successResponses.length > 0) {
@@ -188,7 +182,7 @@ export class MetadataSchemaComponent implements OnInit {
this.forceUpdateFields();
});
}
)
);
}
/**
@@ -205,9 +199,9 @@ export class MetadataSchemaComponent implements OnInit {
);
messages.subscribe(([head, content]) => {
if (success) {
this.notificationsService.success(head, content)
this.notificationsService.success(head, content);
} else {
this.notificationsService.error(head, content)
this.notificationsService.error(head, content);
}
});
}

View File

@@ -13,11 +13,13 @@ import { ACCESS_CONTROL_MODULE_PATH, REGISTRIES_MODULE_PATH } from './admin-rout
RouterModule.forChild([
{
path: REGISTRIES_MODULE_PATH,
loadChildren: './admin-registries/admin-registries.module#AdminRegistriesModule'
loadChildren: () => import('./admin-registries/admin-registries.module')
.then((m) => m.AdminRegistriesModule),
},
{
path: ACCESS_CONTROL_MODULE_PATH,
loadChildren: './admin-access-control/admin-access-control.module#AdminAccessControlModule'
loadChildren: () => import('./admin-access-control/admin-access-control.module')
.then((m) => m.AdminAccessControlModule),
},
{
path: 'search',

View File

@@ -1,4 +1,4 @@
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing';
import { AdminSearchPageComponent } from './admin-search-page.component';
import { NO_ERRORS_SCHEMA } from '@angular/core';
@@ -7,12 +7,12 @@ describe('AdminSearchPageComponent', () => {
let component: AdminSearchPageComponent;
let fixture: ComponentFixture<AdminSearchPageComponent>;
beforeEach(async(() => {
beforeEach(waitForAsync(() => {
TestBed.configureTestingModule({
declarations: [ AdminSearchPageComponent ],
declarations: [AdminSearchPageComponent],
schemas: [NO_ERRORS_SCHEMA]
})
.compileComponents();
.compileComponents();
}));
beforeEach(() => {

View File

@@ -1,4 +1,4 @@
import { Component, OnInit } from '@angular/core';
import { Component } from '@angular/core';
import { Context } from '../../core/shared/context.model';
@Component({

View File

@@ -1,4 +1,4 @@
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing';
import { NoopAnimationsModule } from '@angular/platform-browser/animations';
import { BitstreamDataService } from '../../../../../core/data/bitstream-data.service';
import { mockTruncatableService } from '../../../../../shared/mocks/mock-trucatable.service';
@@ -32,7 +32,7 @@ describe('CollectionAdminSearchResultGridElementComponent', () => {
resolveLink: {}
});
beforeEach(async(() => {
beforeEach(waitForAsync(() => {
init();
TestBed.configureTestingModule({
imports: [
@@ -45,7 +45,7 @@ describe('CollectionAdminSearchResultGridElementComponent', () => {
providers: [
{ provide: TruncatableService, useValue: mockTruncatableService },
{ provide: BitstreamDataService, useValue: {} },
{ provide: LinkService, useValue: linkService}
{ provide: LinkService, useValue: linkService }
]
})
.compileComponents();
@@ -69,5 +69,5 @@ describe('CollectionAdminSearchResultGridElementComponent', () => {
const a = fixture.debugElement.query(By.css('a.edit-link'));
const link = a.nativeElement.href;
expect(link).toContain(getCollectionEditRoute(id));
})
});
});

View File

@@ -1,4 +1,4 @@
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing';
import { NO_ERRORS_SCHEMA } from '@angular/core';
import { NoopAnimationsModule } from '@angular/platform-browser/animations';
@@ -34,7 +34,7 @@ describe('CommunityAdminSearchResultGridElementComponent', () => {
resolveLink: {}
});
beforeEach(async(() => {
beforeEach(waitForAsync(() => {
init();
TestBed.configureTestingModule({
imports: [
@@ -47,7 +47,7 @@ describe('CommunityAdminSearchResultGridElementComponent', () => {
providers: [
{ provide: TruncatableService, useValue: mockTruncatableService },
{ provide: BitstreamDataService, useValue: {} },
{ provide: LinkService, useValue: linkService}
{ provide: LinkService, useValue: linkService }
],
schemas: [NO_ERRORS_SCHEMA]
})
@@ -72,5 +72,5 @@ describe('CommunityAdminSearchResultGridElementComponent', () => {
const a = fixture.debugElement.query(By.css('a.edit-link'));
const link = a.nativeElement.href;
expect(link).toContain(getCommunityEditRoute(id));
})
});
});

View File

@@ -1,8 +1,8 @@
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing';
import { NO_ERRORS_SCHEMA } from '@angular/core';
import { NoopAnimationsModule } from '@angular/platform-browser/animations';
import { TranslateModule } from '@ngx-translate/core';
import { Observable } from 'rxjs/internal/Observable';
import { Observable } from 'rxjs';
import { BitstreamDataService } from '../../../../../core/data/bitstream-data.service';
import { RemoteData } from '../../../../../core/data/remote-data';
import { Bitstream } from '../../../../../core/shared/bitstream.model';
@@ -36,7 +36,7 @@ describe('ItemAdminSearchResultGridElementComponent', () => {
searchResult.indexableObject.uuid = id;
}
beforeEach(async(() => {
beforeEach(waitForAsync(() => {
init();
TestBed.configureTestingModule(
{

View File

@@ -1,7 +1,10 @@
import { Component, ComponentFactoryResolver, ElementRef, OnInit, ViewChild, ViewContainerRef } from '@angular/core';
import { Component, ComponentFactoryResolver, ElementRef, OnInit, ViewChild } from '@angular/core';
import { Item } from '../../../../../core/shared/item.model';
import { ViewMode } from '../../../../../core/shared/view-mode.model';
import { getListableObjectComponent, listableObjectComponent } from '../../../../../shared/object-collection/shared/listable-object/listable-object.decorator';
import {
getListableObjectComponent,
listableObjectComponent
} from '../../../../../shared/object-collection/shared/listable-object/listable-object.decorator';
import { Context } from '../../../../../core/shared/context.model';
import { ItemSearchResult } from '../../../../../shared/object-collection/shared/item-search-result.model';
import { SearchResultGridElementComponent } from '../../../../../shared/object-grid/search-result-grid-element/search-result-grid-element.component';
@@ -60,6 +63,6 @@ export class ItemAdminSearchResultGridElementComponent extends SearchResultGridE
* @returns {GenericConstructor<Component>}
*/
private getComponent(): GenericConstructor<Component> {
return getListableObjectComponent(this.object.getRenderTypes(), ViewMode.GridElement, undefined)
return getListableObjectComponent(this.object.getRenderTypes(), ViewMode.GridElement, undefined);
}
}

View File

@@ -1,4 +1,4 @@
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing';
import { NO_ERRORS_SCHEMA } from '@angular/core';
import { CollectionAdminSearchResultListElementComponent } from './collection-admin-search-result-list-element.component';
@@ -24,7 +24,8 @@ describe('CollectionAdminSearchResultListElementComponent', () => {
searchResult.indexableObject = new Collection();
searchResult.indexableObject.uuid = id;
}
beforeEach(async(() => {
beforeEach(waitForAsync(() => {
init();
TestBed.configureTestingModule({
imports: [
@@ -56,5 +57,5 @@ describe('CollectionAdminSearchResultListElementComponent', () => {
const a = fixture.debugElement.query(By.css('a'));
const link = a.nativeElement.href;
expect(link).toContain(getCollectionEditRoute(id));
})
});
});

View File

@@ -1,4 +1,4 @@
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing';
import { NO_ERRORS_SCHEMA } from '@angular/core';
import { TranslateModule } from '@ngx-translate/core';
@@ -24,7 +24,8 @@ describe('CommunityAdminSearchResultListElementComponent', () => {
searchResult.indexableObject = new Community();
searchResult.indexableObject.uuid = id;
}
beforeEach(async(() => {
beforeEach(waitForAsync(() => {
init();
TestBed.configureTestingModule({
imports: [
@@ -56,5 +57,5 @@ describe('CommunityAdminSearchResultListElementComponent', () => {
const a = fixture.debugElement.query(By.css('a'));
const link = a.nativeElement.href;
expect(link).toContain(getCommunityEditRoute(id));
})
});
});

View File

@@ -1,4 +1,4 @@
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing';
import { NO_ERRORS_SCHEMA } from '@angular/core';
import { TranslateModule } from '@ngx-translate/core';
import { TruncatableService } from '../../../../../shared/truncatable/truncatable.service';
@@ -22,7 +22,7 @@ describe('ItemAdminSearchResultListElementComponent', () => {
searchResult.indexableObject.uuid = id;
}
beforeEach(async(() => {
beforeEach(waitForAsync(() => {
init();
TestBed.configureTestingModule({
imports: [

View File

@@ -1,4 +1,4 @@
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing';
import { NO_ERRORS_SCHEMA } from '@angular/core';
import { TranslateModule } from '@ngx-translate/core';
@@ -9,10 +9,10 @@ import { Item } from '../../../core/shared/item.model';
import { URLCombiner } from '../../../core/url-combiner/url-combiner';
import { getItemEditRoute } from '../../../+item-page/item-page-routing-paths';
import {
ITEM_EDIT_MOVE_PATH,
ITEM_EDIT_DELETE_PATH,
ITEM_EDIT_PUBLIC_PATH,
ITEM_EDIT_MOVE_PATH,
ITEM_EDIT_PRIVATE_PATH,
ITEM_EDIT_PUBLIC_PATH,
ITEM_EDIT_REINSTATE_PATH,
ITEM_EDIT_WITHDRAW_PATH
} from '../../../+item-page/edit-item-page/edit-item-page.routing-paths';
@@ -28,7 +28,8 @@ describe('ItemAdminSearchResultActionsComponent', () => {
item = new Item();
item.uuid = id;
}
beforeEach(async(() => {
beforeEach(waitForAsync(() => {
init();
TestBed.configureTestingModule({
imports: [
@@ -72,8 +73,8 @@ describe('ItemAdminSearchResultActionsComponent', () => {
describe('when the item is not withdrawn', () => {
beforeEach(() => {
component.item.isWithdrawn = false;
fixture.detectChanges();
component.item.isWithdrawn = false;
fixture.detectChanges();
});
it('should render a withdraw button with the correct link', () => {
@@ -140,5 +141,5 @@ describe('ItemAdminSearchResultActionsComponent', () => {
const link = a.nativeElement.href;
expect(link).toContain(new URLCombiner(getItemEditRoute(id), ITEM_EDIT_PUBLIC_PATH).toString());
});
})
});
});

View File

@@ -34,7 +34,7 @@ export class ItemAdminSearchResultActionsComponent {
* Returns the path to the edit page of this item
*/
getEditRoute(): string {
return getItemEditRoute(this.item.uuid)
return getItemEditRoute(this.item.uuid);
}
/**

View File

@@ -0,0 +1,47 @@
import { NgModule } from '@angular/core';
import { SharedModule } from '../../shared/shared.module';
import { AdminSearchPageComponent } from './admin-search-page.component';
import { ItemAdminSearchResultListElementComponent } from './admin-search-results/admin-search-result-list-element/item-search-result/item-admin-search-result-list-element.component';
import { CommunityAdminSearchResultListElementComponent } from './admin-search-results/admin-search-result-list-element/community-search-result/community-admin-search-result-list-element.component';
import { CollectionAdminSearchResultListElementComponent } from './admin-search-results/admin-search-result-list-element/collection-search-result/collection-admin-search-result-list-element.component';
import { ItemAdminSearchResultGridElementComponent } from './admin-search-results/admin-search-result-grid-element/item-search-result/item-admin-search-result-grid-element.component';
import { CommunityAdminSearchResultGridElementComponent } from './admin-search-results/admin-search-result-grid-element/community-search-result/community-admin-search-result-grid-element.component';
import { CollectionAdminSearchResultGridElementComponent } from './admin-search-results/admin-search-result-grid-element/collection-search-result/collection-admin-search-result-grid-element.component';
import { ItemAdminSearchResultActionsComponent } from './admin-search-results/item-admin-search-result-actions.component';
import { JournalEntitiesModule } from '../../entity-groups/journal-entities/journal-entities.module';
import { ResearchEntitiesModule } from '../../entity-groups/research-entities/research-entities.module';
const ENTRY_COMPONENTS = [
// put only entry components that use custom decorator
ItemAdminSearchResultListElementComponent,
CommunityAdminSearchResultListElementComponent,
CollectionAdminSearchResultListElementComponent,
ItemAdminSearchResultGridElementComponent,
CommunityAdminSearchResultGridElementComponent,
CollectionAdminSearchResultGridElementComponent,
ItemAdminSearchResultActionsComponent
];
@NgModule({
imports: [
SharedModule.withEntryComponents(),
JournalEntitiesModule.withEntryComponents(),
ResearchEntitiesModule.withEntryComponents()
],
declarations: [
AdminSearchPageComponent,
...ENTRY_COMPONENTS
]
})
export class AdminSearchModule {
/**
* NOTE: this method allows to resolve issue with components that using a custom decorator
* which are not loaded during CSR otherwise
*/
static withEntryComponents() {
return {
ngModule: SharedModule,
providers: ENTRY_COMPONENTS.map((component) => ({provide: component}))
};
}
}

View File

@@ -1,4 +1,4 @@
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing';
import { MenuService } from '../../../shared/menu/menu.service';
import { MenuServiceStub } from '../../../shared/testing/menu-service.stub';
@@ -17,7 +17,7 @@ describe('AdminSidebarSectionComponent', () => {
const menuService = new MenuServiceStub();
const iconString = 'test';
beforeEach(async(() => {
beforeEach(waitForAsync(() => {
TestBed.configureTestingModule({
imports: [NoopAnimationsModule, RouterTestingModule, TranslateModule.forRoot()],
declarations: [AdminSidebarSectionComponent, TestComponent],

View File

@@ -1,4 +1,4 @@
import { async, ComponentFixture, fakeAsync, TestBed, tick } from '@angular/core/testing';
import { ComponentFixture, fakeAsync, TestBed, tick, waitForAsync } from '@angular/core/testing';
import { NoopAnimationsModule } from '@angular/platform-browser/animations';
import { TranslateModule } from '@ngx-translate/core';
import { ChangeDetectionStrategy, Injector, NO_ERRORS_SCHEMA } from '@angular/core';
@@ -24,7 +24,7 @@ describe('AdminSidebarComponent', () => {
let authorizationService: AuthorizationDataService;
let scriptService;
beforeEach(async(() => {
beforeEach(waitForAsync(() => {
authorizationService = jasmine.createSpyObj('authorizationService', {
isAuthorized: observableOf(true)
});
@@ -33,7 +33,7 @@ describe('AdminSidebarComponent', () => {
imports: [TranslateModule.forRoot(), NoopAnimationsModule, RouterTestingModule],
declarations: [AdminSidebarComponent],
providers: [
{ provide: Injector, useValue: {} },
Injector,
{ provide: MenuService, useValue: menuService },
{ provide: CSSVariableService, useClass: CSSVariableServiceStub },
{ provide: AuthService, useClass: AuthServiceStub },
@@ -72,7 +72,7 @@ describe('AdminSidebarComponent', () => {
it('should set the sidebarClosed to false', () => {
expect(comp.sidebarClosed).toBeFalsy();
})
});
});
describe('when collapsing', () => {
@@ -83,8 +83,8 @@ describe('AdminSidebarComponent', () => {
it('should set the sidebarOpen to false', () => {
expect(comp.sidebarOpen).toBeFalsy();
})
})
});
});
});
describe('finishSlide', () => {
@@ -96,7 +96,7 @@ describe('AdminSidebarComponent', () => {
it('should set the sidebarClosed to true', () => {
expect(comp.sidebarClosed).toBeTruthy();
})
});
});
describe('when collapsing', () => {
@@ -107,8 +107,8 @@ describe('AdminSidebarComponent', () => {
it('should set the sidebarOpen to true', () => {
expect(comp.sidebarOpen).toBeTruthy();
})
})
});
});
});
describe('when the collapse icon is clicked', () => {

View File

@@ -1,14 +1,9 @@
import { Component, Injector, OnInit } from '@angular/core';
import { NgbModal } from '@ng-bootstrap/ng-bootstrap';
import { combineLatest as observableCombineLatest } from 'rxjs';
import { Observable } from 'rxjs/internal/Observable';
import { combineLatest as observableCombineLatest, Observable } from 'rxjs';
import { first, map, take } from 'rxjs/operators';
import { AuthService } from '../../core/auth/auth.service';
import {
METADATA_EXPORT_SCRIPT_NAME,
METADATA_IMPORT_SCRIPT_NAME,
ScriptDataService
} from '../../core/data/processes/script-data.service';
import { ScriptDataService } from '../../core/data/processes/script-data.service';
import { slideHorizontal, slideSidebar } from '../../shared/animations/slide';
import { CreateCollectionParentSelectorComponent } from '../../shared/dso-selector/modal-wrappers/create-collection-parent-selector/create-collection-parent-selector.component';
import { CreateCommunityParentSelectorComponent } from '../../shared/dso-selector/modal-wrappers/create-community-parent-selector/create-community-parent-selector.component';
@@ -16,9 +11,7 @@ import { CreateItemParentSelectorComponent } from '../../shared/dso-selector/mod
import { EditCollectionSelectorComponent } from '../../shared/dso-selector/modal-wrappers/edit-collection-selector/edit-collection-selector.component';
import { EditCommunitySelectorComponent } from '../../shared/dso-selector/modal-wrappers/edit-community-selector/edit-community-selector.component';
import { EditItemSelectorComponent } from '../../shared/dso-selector/modal-wrappers/edit-item-selector/edit-item-selector.component';
import {
ExportMetadataSelectorComponent
} from '../../shared/dso-selector/modal-wrappers/export-metadata-selector/export-metadata-selector.component';
import { ExportMetadataSelectorComponent } from '../../shared/dso-selector/modal-wrappers/export-metadata-selector/export-metadata-selector.component';
import { MenuID, MenuItemType } from '../../shared/menu/initial-menus-state';
import { LinkMenuItemModel } from '../../shared/menu/menu-item/models/link.model';
import { OnClickMenuItemModel } from '../../shared/menu/menu-item/models/onclick.model';

View File

@@ -1,4 +1,4 @@
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing';
import { ExpandableAdminSidebarSectionComponent } from './expandable-admin-sidebar-section.component';
import { MenuService } from '../../../shared/menu/menu.service';
@@ -16,12 +16,12 @@ describe('ExpandableAdminSidebarSectionComponent', () => {
let fixture: ComponentFixture<ExpandableAdminSidebarSectionComponent>;
const menuService = new MenuServiceStub();
const iconString = 'test';
beforeEach(async(() => {
beforeEach(waitForAsync(() => {
TestBed.configureTestingModule({
imports: [NoopAnimationsModule, TranslateModule.forRoot()],
declarations: [ExpandableAdminSidebarSectionComponent, TestComponent],
providers: [
{ provide: 'sectionDataProvider', useValue: {icon: iconString} },
{ provide: 'sectionDataProvider', useValue: { icon: iconString } },
{ provide: MenuService, useValue: menuService },
{ provide: CSSVariableService, useClass: CSSVariableServiceStub },
]
@@ -54,7 +54,10 @@ describe('ExpandableAdminSidebarSectionComponent', () => {
beforeEach(() => {
spyOn(menuService, 'toggleActiveSection');
const sidebarToggler = fixture.debugElement.query(By.css('a.shortcut-icon'));
sidebarToggler.triggerEventHandler('click', {preventDefault: () => {/**/}});
sidebarToggler.triggerEventHandler('click', {
preventDefault: () => {/**/
}
});
});
it('should call toggleActiveSection on the menuService', () => {
@@ -66,7 +69,10 @@ describe('ExpandableAdminSidebarSectionComponent', () => {
beforeEach(() => {
spyOn(menuService, 'toggleActiveSection');
const sidebarToggler = fixture.debugElement.query(By.css('.sidebar-collapsible')).query(By.css('a'));
sidebarToggler.triggerEventHandler('click', {preventDefault: () => {/**/}});
sidebarToggler.triggerEventHandler('click', {
preventDefault: () => {/**/
}
});
});
it('should call toggleActiveSection on the menuService', () => {

View File

@@ -1,4 +1,4 @@
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing';
import { AdminWorkflowPageComponent } from './admin-workflow-page.component';
import { NO_ERRORS_SCHEMA } from '@angular/core';
@@ -7,12 +7,12 @@ describe('AdminSearchPageComponent', () => {
let component: AdminWorkflowPageComponent;
let fixture: ComponentFixture<AdminWorkflowPageComponent>;
beforeEach(async(() => {
beforeEach(waitForAsync(() => {
TestBed.configureTestingModule({
declarations: [ AdminWorkflowPageComponent ],
declarations: [AdminWorkflowPageComponent],
schemas: [NO_ERRORS_SCHEMA]
})
.compileComponents();
.compileComponents();
}));
beforeEach(() => {

View File

@@ -1,4 +1,4 @@
import { Component, OnInit } from '@angular/core';
import { Component } from '@angular/core';
import { Context } from '../../core/shared/context.model';
@Component({

View File

@@ -1,4 +1,4 @@
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing';
import { NO_ERRORS_SCHEMA } from '@angular/core';
import { NoopAnimationsModule } from '@angular/platform-browser/animations';
@@ -32,14 +32,14 @@ describe('WorkflowItemAdminWorkflowGridElementComponent', () => {
function init() {
itemRD$ = createSuccessfulRemoteDataObject$(new Item());
id = '780b2588-bda5-4112-a1cd-0b15000a5339';
object = new WorkflowItemSearchResult()
object = new WorkflowItemSearchResult();
wfi = new WorkflowItem();
wfi.item = itemRD$;
object.indexableObject = wfi;
linkService = getMockLinkService();
}
beforeEach(async(() => {
beforeEach(waitForAsync(() => {
init();
TestBed.configureTestingModule(
{
@@ -51,9 +51,11 @@ describe('WorkflowItemAdminWorkflowGridElementComponent', () => {
],
providers: [
{ provide: LinkService, useValue: linkService },
{ provide: TruncatableService, useValue: {
{
provide: TruncatableService, useValue: {
isCollapsed: () => observableOf(true),
} },
}
},
{ provide: BitstreamDataService, useValue: {} },
],
schemas: [NO_ERRORS_SCHEMA]

View File

@@ -84,7 +84,7 @@ export class WorkflowItemSearchResultAdminWorkflowGridElementComponent extends S
(componentRef.instance as any).listID = this.listID;
componentRef.changeDetectorRef.detectChanges();
}
)
);
}
/**
@@ -92,7 +92,7 @@ export class WorkflowItemSearchResultAdminWorkflowGridElementComponent extends S
* @returns {GenericConstructor<Component>}
*/
private getComponent(item: Item): GenericConstructor<Component> {
return getListableObjectComponent(item.getRenderTypes(), ViewMode.GridElement, undefined)
return getListableObjectComponent(item.getRenderTypes(), ViewMode.GridElement, undefined);
}
}

View File

@@ -1,4 +1,4 @@
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing';
import { NO_ERRORS_SCHEMA } from '@angular/core';
import { NoopAnimationsModule } from '@angular/platform-browser/animations';
@@ -29,14 +29,14 @@ describe('WorkflowItemAdminWorkflowListElementComponent', () => {
function init() {
itemRD$ = createSuccessfulRemoteDataObject$(new Item());
id = '780b2588-bda5-4112-a1cd-0b15000a5339';
object = new WorkflowItemSearchResult()
object = new WorkflowItemSearchResult();
wfi = new WorkflowItem();
wfi.item = itemRD$;
object.indexableObject = wfi;
linkService = getMockLinkService();
}
beforeEach(async(() => {
beforeEach(waitForAsync(() => {
init();
TestBed.configureTestingModule(
{

View File

@@ -1,26 +1,16 @@
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing';
import { NO_ERRORS_SCHEMA } from '@angular/core';
import { TranslateModule } from '@ngx-translate/core';
import { By } from '@angular/platform-browser';
import { RouterTestingModule } from '@angular/router/testing';
import { Item } from '../../../core/shared/item.model';
import { URLCombiner } from '../../../core/url-combiner/url-combiner';
import { WorkflowItemAdminWorkflowActionsComponent } from './workflow-item-admin-workflow-actions.component';
import { WorkflowItem } from '../../../core/submission/models/workflowitem.model';
import {
getWorkflowItemSendBackRoute,
getWorkflowItemDeleteRoute
getWorkflowItemDeleteRoute,
getWorkflowItemSendBackRoute
} from '../../../+workflowitems-edit-page/workflowitems-edit-page-routing-paths';
import { getItemEditRoute } from '../../../+item-page/item-page-routing-paths';
import {
ITEM_EDIT_MOVE_PATH,
ITEM_EDIT_DELETE_PATH,
ITEM_EDIT_PUBLIC_PATH,
ITEM_EDIT_PRIVATE_PATH,
ITEM_EDIT_REINSTATE_PATH,
ITEM_EDIT_WITHDRAW_PATH
} from '../../../+item-page/edit-item-page/edit-item-page.routing-paths';
describe('WorkflowItemAdminWorkflowActionsComponent', () => {
let component: WorkflowItemAdminWorkflowActionsComponent;
@@ -33,7 +23,8 @@ describe('WorkflowItemAdminWorkflowActionsComponent', () => {
wfi = new WorkflowItem();
wfi.id = id;
}
beforeEach(async(() => {
beforeEach(waitForAsync(() => {
init();
TestBed.configureTestingModule({
imports: [

View File

@@ -30,7 +30,7 @@ export class WorkflowItemAdminWorkflowActionsComponent {
*/
getDeleteRoute(): string {
return getWorkflowItemDeleteRoute(this.wfi.id)
return getWorkflowItemDeleteRoute(this.wfi.id);
}
/**

View File

@@ -0,0 +1,39 @@
import { NgModule } from '@angular/core';
import { SharedModule } from '../../shared/shared.module';
import { WorkflowItemSearchResultAdminWorkflowGridElementComponent } from './admin-workflow-search-results/admin-workflow-search-result-grid-element/workflow-item/workflow-item-search-result-admin-workflow-grid-element.component';
import { WorkflowItemAdminWorkflowActionsComponent } from './admin-workflow-search-results/workflow-item-admin-workflow-actions.component';
import { WorkflowItemSearchResultAdminWorkflowListElementComponent } from './admin-workflow-search-results/admin-workflow-search-result-list-element/workflow-item/workflow-item-search-result-admin-workflow-list-element.component';
import { AdminWorkflowPageComponent } from './admin-workflow-page.component';
const ENTRY_COMPONENTS = [
// put only entry components that use custom decorator
WorkflowItemSearchResultAdminWorkflowListElementComponent,
WorkflowItemSearchResultAdminWorkflowGridElementComponent,
];
@NgModule({
imports: [
SharedModule.withEntryComponents()
],
declarations: [
AdminWorkflowPageComponent,
WorkflowItemAdminWorkflowActionsComponent,
...ENTRY_COMPONENTS
],
exports: [
AdminWorkflowPageComponent
]
})
export class AdminWorkflowModuleModule {
/**
* NOTE: this method allows to resolve issue with components that using a custom decorator
* which are not loaded during CSR otherwise
*/
static withEntryComponents() {
return {
ngModule: SharedModule,
providers: ENTRY_COMPONENTS.map((component) => ({provide: component}))
};
}
}

View File

@@ -4,64 +4,42 @@ import { AdminAccessControlModule } from './admin-access-control/admin-access-co
import { MetadataImportPageComponent } from './admin-import-metadata-page/metadata-import-page.component';
import { AdminRegistriesModule } from './admin-registries/admin-registries.module';
import { AdminRoutingModule } from './admin-routing.module';
import { AdminSearchPageComponent } from './admin-search-page/admin-search-page.component';
import { SearchPageModule } from '../+search-page/search-page.module';
import { ItemAdminSearchResultListElementComponent } from './admin-search-page/admin-search-results/admin-search-result-list-element/item-search-result/item-admin-search-result-list-element.component';
import { CommunityAdminSearchResultListElementComponent } from './admin-search-page/admin-search-results/admin-search-result-list-element/community-search-result/community-admin-search-result-list-element.component';
import { CollectionAdminSearchResultListElementComponent } from './admin-search-page/admin-search-results/admin-search-result-list-element/collection-search-result/collection-admin-search-result-list-element.component';
import { ItemAdminSearchResultGridElementComponent } from './admin-search-page/admin-search-results/admin-search-result-grid-element/item-search-result/item-admin-search-result-grid-element.component';
import { CommunityAdminSearchResultGridElementComponent } from './admin-search-page/admin-search-results/admin-search-result-grid-element/community-search-result/community-admin-search-result-grid-element.component';
import { CollectionAdminSearchResultGridElementComponent } from './admin-search-page/admin-search-results/admin-search-result-grid-element/collection-search-result/collection-admin-search-result-grid-element.component';
import { ItemAdminSearchResultActionsComponent } from './admin-search-page/admin-search-results/item-admin-search-result-actions.component';
import { WorkflowItemSearchResultAdminWorkflowGridElementComponent } from './admin-workflow-page/admin-workflow-search-results/admin-workflow-search-result-grid-element/workflow-item/workflow-item-search-result-admin-workflow-grid-element.component';
import { WorkflowItemAdminWorkflowActionsComponent } from './admin-workflow-page/admin-workflow-search-results/workflow-item-admin-workflow-actions.component';
import { WorkflowItemSearchResultAdminWorkflowListElementComponent } from './admin-workflow-page/admin-workflow-search-results/admin-workflow-search-result-list-element/workflow-item/workflow-item-search-result-admin-workflow-list-element.component';
import { AdminWorkflowPageComponent } from './admin-workflow-page/admin-workflow-page.component';
import { AdminCurationTasksComponent } from './admin-curation-tasks/admin-curation-tasks.component';
import { AdminWorkflowModuleModule } from './admin-workflow-page/admin-workflow.module';
import { AdminSearchModule } from './admin-search-page/admin-search.module';
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';
const ENTRY_COMPONENTS = [
// put only entry components that use custom decorator
AdminSidebarSectionComponent,
ExpandableAdminSidebarSectionComponent,
];
@NgModule({
imports: [
AdminRoutingModule,
AdminRegistriesModule,
AdminAccessControlModule,
AdminSearchModule.withEntryComponents(),
AdminWorkflowModuleModule.withEntryComponents(),
SharedModule,
SearchPageModule
],
declarations: [
AdminSearchPageComponent,
AdminWorkflowPageComponent,
ItemAdminSearchResultListElementComponent,
CommunityAdminSearchResultListElementComponent,
CollectionAdminSearchResultListElementComponent,
ItemAdminSearchResultGridElementComponent,
CommunityAdminSearchResultGridElementComponent,
CollectionAdminSearchResultGridElementComponent,
ItemAdminSearchResultActionsComponent,
AdminCurationTasksComponent,
WorkflowItemSearchResultAdminWorkflowListElementComponent,
WorkflowItemSearchResultAdminWorkflowGridElementComponent,
WorkflowItemAdminWorkflowActionsComponent,
MetadataImportPageComponent
],
entryComponents: [
ItemAdminSearchResultListElementComponent,
CommunityAdminSearchResultListElementComponent,
CollectionAdminSearchResultListElementComponent,
ItemAdminSearchResultGridElementComponent,
CommunityAdminSearchResultGridElementComponent,
CollectionAdminSearchResultGridElementComponent,
ItemAdminSearchResultActionsComponent,
WorkflowItemSearchResultAdminWorkflowListElementComponent,
WorkflowItemSearchResultAdminWorkflowGridElementComponent,
WorkflowItemAdminWorkflowActionsComponent,
MetadataImportPageComponent
]
})
export class AdminModule {
/**
* NOTE: this method allows to resolve issue with components that using a custom decorator
* which are not loaded during CSR otherwise
*/
static withEntryComponents() {
return {
ngModule: AdminModule,
providers: ENTRY_COMPONENTS.map((component) => ({provide: component}))
};
}
}

View File

@@ -1,10 +1,10 @@
import { Injectable } from '@angular/core';
import { ActivatedRouteSnapshot, Resolve, RouterStateSnapshot } from '@angular/router';
import { RemoteData } from '../core/data/remote-data';
import { Observable } from 'rxjs/internal/Observable';
import { Observable } from 'rxjs';
import { Bitstream } from '../core/shared/bitstream.model';
import { BitstreamDataService } from '../core/data/bitstream-data.service';
import {followLink, FollowLinkConfig} from '../shared/utils/follow-link-config.model';
import { followLink, FollowLinkConfig } from '../shared/utils/follow-link-config.model';
import { getFirstCompletedRemoteData } from '../core/shared/operators';
/**
@@ -33,7 +33,7 @@ export class BitstreamPageResolver implements Resolve<RemoteData<Bitstream>> {
* The self links defined in this list are expected to be requested somewhere in the near future
* Requesting them as embeds will limit the number of requests
*/
get followLinks(): Array<FollowLinkConfig<Bitstream>> {
get followLinks(): FollowLinkConfig<Bitstream>[] {
return [
followLink('bundle', undefined, true, followLink('item')),
followLink('format')

View File

@@ -1,9 +1,9 @@
import { EditBitstreamPageComponent } from './edit-bitstream-page.component';
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing';
import { TranslateModule } from '@ngx-translate/core';
import { RouterTestingModule } from '@angular/router/testing';
import { of as observableOf } from 'rxjs/internal/observable/of';
import {ActivatedRoute, Router} from '@angular/router';
import { ActivatedRoute, Router } from '@angular/router';
import { of as observableOf } from 'rxjs';
import { DynamicFormControlModel, DynamicFormService } from '@ng-dynamic-forms/core';
import { NotificationsService } from '../../shared/notifications/notifications.service';
import { BitstreamDataService } from '../../core/data/bitstream-data.service';
@@ -18,11 +18,8 @@ import { hasValue } from '../../shared/empty.util';
import { FormControl, FormGroup } from '@angular/forms';
import { FileSizePipe } from '../../shared/utils/file-size-pipe';
import { VarDirective } from '../../shared/utils/var.directive';
import {
createSuccessfulRemoteDataObject,
createSuccessfulRemoteDataObject$
} from '../../shared/remote-data.utils';
import {RouterStub} from '../../shared/testing/router.stub';
import { createSuccessfulRemoteDataObject, createSuccessfulRemoteDataObject$ } from '../../shared/remote-data.utils';
import { RouterStub } from '../../shared/testing/router.stub';
import { getItemEditRoute } from '../../+item-page/item-page-routing-paths';
import { createPaginatedList } from '../../shared/testing/utils.test';
@@ -44,7 +41,7 @@ describe('EditBitstreamPageComponent', () => {
let comp: EditBitstreamPageComponent;
let fixture: ComponentFixture<EditBitstreamPageComponent>;
beforeEach(async(() => {
beforeEach(waitForAsync(() => {
allFormats = [
Object.assign({
id: '1',
@@ -238,7 +235,7 @@ describe('EditBitstreamPageComponent', () => {
});
describe('when navigateToItemEditBitstreams is called, and the component has an itemId', () => {
it('should redirect to the item edit page on the bitstreams tab with the itemId from the component', () => {
comp.itemId = 'some-uuid1'
comp.itemId = 'some-uuid1';
comp.navigateToItemEditBitstreams();
expect(routerStub.navigate).toHaveBeenCalledWith([getItemEditRoute('some-uuid1'), 'bitstreams']);
});

View File

@@ -2,8 +2,7 @@ import { ChangeDetectionStrategy, Component, OnDestroy, OnInit } from '@angular/
import { Bitstream } from '../../core/shared/bitstream.model';
import { ActivatedRoute, Router } from '@angular/router';
import { map, mergeMap, switchMap } from 'rxjs/operators';
import { combineLatest as observableCombineLatest, of as observableOf } from 'rxjs';
import { Subscription } from 'rxjs/internal/Subscription';
import { combineLatest as observableCombineLatest, Observable, of as observableOf, Subscription } from 'rxjs';
import {
DynamicFormControlModel,
DynamicFormGroupModel,
@@ -32,7 +31,6 @@ import { BitstreamFormatSupportLevel } from '../../core/shared/bitstream-format-
import { hasValue, isNotEmpty } from '../../shared/empty.util';
import { Metadata } from '../../core/shared/metadata.utils';
import { Location } from '@angular/common';
import { Observable } from 'rxjs/internal/Observable';
import { RemoteData } from '../../core/data/remote-data';
import { PaginatedList } from '../../core/data/paginated-list.model';
import { getItemEditRoute } from '../../+item-page/item-page-routing-paths';
@@ -328,7 +326,7 @@ export class EditBitstreamPageComponent implements OnInit, OnDestroy {
this.updateFieldTranslations();
})
);
};
}
/**
* Update the current form values with bitstream properties

View File

@@ -1,5 +1,5 @@
import { BrowseByDatePageComponent } from './browse-by-date-page.component';
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing';
import { CommonModule } from '@angular/common';
import { RouterTestingModule } from '@angular/router/testing';
import { TranslateModule } from '@ngx-translate/core';
@@ -10,7 +10,7 @@ import { BrowseService } from '../../core/browse/browse.service';
import { DSpaceObjectDataService } from '../../core/data/dspace-object-data.service';
import { RouterMock } from '../../shared/mocks/router.mock';
import { ChangeDetectorRef, NO_ERRORS_SCHEMA } from '@angular/core';
import { of as observableOf } from 'rxjs/internal/observable/of';
import { of as observableOf } from 'rxjs';
import { ActivatedRouteStub } from '../../shared/testing/active-router.stub';
import { Community } from '../../core/shared/community.model';
import { Item } from '../../core/shared/item.model';
@@ -65,7 +65,7 @@ describe('BrowseByDatePageComponent', () => {
detectChanges: () => fixture.detectChanges()
});
beforeEach(async(() => {
beforeEach(waitForAsync(() => {
TestBed.configureTestingModule({
imports: [CommonModule, RouterTestingModule.withRoutes([]), TranslateModule.forRoot(), NgbModule],
declarations: [BrowseByDatePageComponent, EnumKeysPipe, VarDirective],

View File

@@ -4,7 +4,7 @@ import {
browseParamsToOptions
} from '../+browse-by-metadata-page/browse-by-metadata-page.component';
import { BrowseEntrySearchOptions } from '../../core/browse/browse-entry-search-options.model';
import { combineLatest as observableCombineLatest } from 'rxjs/internal/observable/combineLatest';
import { combineLatest as observableCombineLatest } from 'rxjs';
import { RemoteData } from '../../core/data/remote-data';
import { Item } from '../../core/shared/item.model';
import { hasValue, isNotEmpty } from '../../shared/empty.util';

View File

@@ -1,5 +1,5 @@
import { BrowseByMetadataPageComponent, browseParamsToOptions } from './browse-by-metadata-page.component';
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing';
import { BrowseService } from '../../core/browse/browse.service';
import { CommonModule } from '@angular/common';
import { RouterTestingModule } from '@angular/router/testing';
@@ -8,11 +8,10 @@ import { NgbModule } from '@ng-bootstrap/ng-bootstrap';
import { EnumKeysPipe } from '../../shared/utils/enum-keys-pipe';
import { ActivatedRoute, Router } from '@angular/router';
import { ActivatedRouteStub } from '../../shared/testing/active-router.stub';
import { of as observableOf } from 'rxjs/internal/observable/of';
import { Observable, of as observableOf } from 'rxjs';
import { NO_ERRORS_SCHEMA } from '@angular/core';
import { Observable } from 'rxjs/internal/Observable';
import { RemoteData } from '../../core/data/remote-data';
import { PaginatedList, buildPaginatedList } from '../../core/data/paginated-list.model';
import { buildPaginatedList, PaginatedList } from '../../core/data/paginated-list.model';
import { PageInfo } from '../../core/shared/page-info.model';
import { BrowseEntrySearchOptions } from '../../core/browse/browse-entry-search-options.model';
import { SortDirection } from '../../core/cache/models/sort-options.model';
@@ -83,7 +82,7 @@ describe('BrowseByMetadataPageComponent', () => {
params: observableOf({})
});
beforeEach(async(() => {
beforeEach(waitForAsync(() => {
TestBed.configureTestingModule({
imports: [CommonModule, RouterTestingModule.withRoutes([]), TranslateModule.forRoot(), NgbModule],
declarations: [BrowseByMetadataPageComponent, EnumKeysPipe, VarDirective],
@@ -127,7 +126,7 @@ describe('BrowseByMetadataPageComponent', () => {
comp.items$.subscribe((result) => {
expect(result.payload.page).toEqual(mockItems);
});
})
});
});
describe('when calling browseParamsToOptions', () => {
@@ -152,7 +151,7 @@ describe('BrowseByMetadataPageComponent', () => {
expect(result.sort.direction).toEqual(SortDirection.ASC);
expect(result.sort.field).toEqual('fake-field');
expect(result.scope).toEqual('fake-scope');
})
});
});
});

View File

@@ -1,13 +1,13 @@
import { BrowseBySwitcherComponent } from './browse-by-switcher.component';
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing';
import { NO_ERRORS_SCHEMA } from '@angular/core';
import { ActivatedRoute } from '@angular/router';
import * as decorator from './browse-by-decorator';
import createSpy = jasmine.createSpy;
import { BehaviorSubject } from 'rxjs/internal/BehaviorSubject';
import { BehaviorSubject } from 'rxjs';
import { environment } from '../../../environments/environment';
import createSpy = jasmine.createSpy;
describe('BrowseBySwitcherComponent', () => {
xdescribe('BrowseBySwitcherComponent', () => {
let comp: BrowseBySwitcherComponent;
let fixture: ComponentFixture<BrowseBySwitcherComponent>;
@@ -19,17 +19,17 @@ describe('BrowseBySwitcherComponent', () => {
params: params
};
beforeEach(async(() => {
beforeEach(waitForAsync(() => {
TestBed.configureTestingModule({
declarations: [ BrowseBySwitcherComponent ],
declarations: [BrowseBySwitcherComponent],
providers: [
{ provide: ActivatedRoute, useValue: activatedRouteStub }
],
schemas: [ NO_ERRORS_SCHEMA ]
schemas: [NO_ERRORS_SCHEMA]
}).compileComponents();
}));
beforeEach(async(() => {
beforeEach(waitForAsync(() => {
fixture = TestBed.createComponent(BrowseBySwitcherComponent);
comp = fixture.componentInstance;
spyOnProperty(decorator, 'getComponentByBrowseByType').and.returnValue(createSpy('getComponentByItemType'));

View File

@@ -1,8 +1,8 @@
import { Component, Inject, OnInit } from '@angular/core';
import { Component, OnInit } from '@angular/core';
import { ActivatedRoute } from '@angular/router';
import { Observable } from 'rxjs/internal/Observable';
import { Observable } from 'rxjs';
import { BrowseByTypeConfig } from '../../../config/browse-by-type-config.interface';
import { map, tap } from 'rxjs/operators';
import { map } from 'rxjs/operators';
import { getComponentByBrowseByType } from './browse-by-decorator';
import { environment } from '../../../environments/environment';

View File

@@ -1,8 +1,8 @@
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing';
import { ActivatedRoute, Router } from '@angular/router';
import { Item } from '../../core/shared/item.model';
import { ActivatedRouteStub } from '../../shared/testing/active-router.stub';
import { of as observableOf } from 'rxjs/internal/observable/of';
import { of as observableOf } from 'rxjs';
import { CommonModule } from '@angular/common';
import { RouterTestingModule } from '@angular/router/testing';
import { TranslateModule } from '@ngx-translate/core';
@@ -61,7 +61,7 @@ describe('BrowseByTitlePageComponent', () => {
data: observableOf({ metadata: 'title' })
});
beforeEach(async(() => {
beforeEach(waitForAsync(() => {
TestBed.configureTestingModule({
imports: [CommonModule, RouterTestingModule.withRoutes([]), TranslateModule.forRoot(), NgbModule],
declarations: [BrowseByTitlePageComponent, EnumKeysPipe, VarDirective],

View File

@@ -44,7 +44,7 @@ export class BrowseByTitlePageComponent extends BrowseByMetadataPageComponent {
.subscribe((params) => {
this.browseId = params.id || this.defaultBrowseId;
this.updatePageWithItems(browseParamsToOptions(params, this.paginationConfig, this.sortConfig, this.browseId), undefined);
this.updateParent(params.scope)
this.updateParent(params.scope);
}));
this.updateStartsWithTextOptions();
}

View File

@@ -46,13 +46,13 @@ describe('BrowseByGuard', () => {
.subscribe(
(canActivate) => {
const result = {
title,
id,
metadataField,
collection: name,
field,
value: '"' + value + '"'
};
title,
id,
metadataField,
collection: name,
field,
value: '"' + value + '"'
};
expect(scopedRoute.data).toEqual(result);
expect(canActivate).toEqual(true);
}
@@ -78,13 +78,13 @@ describe('BrowseByGuard', () => {
.subscribe(
(canActivate) => {
const result = {
title,
id,
metadataField,
collection: name,
field,
value: ''
};
title,
id,
metadataField,
collection: name,
field,
value: ''
};
expect(scopedNoValueRoute.data).toEqual(result);
expect(canActivate).toEqual(true);
}
@@ -109,13 +109,13 @@ describe('BrowseByGuard', () => {
.subscribe(
(canActivate) => {
const result = {
title,
id,
metadataField,
collection: '',
field,
value: '"' + value + '"'
};
title,
id,
metadataField,
collection: '',
field,
value: '"' + value + '"'
};
expect(route.data).toEqual(result);
expect(canActivate).toEqual(true);
}

View File

@@ -1,5 +1,5 @@
import { ActivatedRouteSnapshot, CanActivate, RouterStateSnapshot } from '@angular/router';
import { Inject, Injectable } from '@angular/core';
import { Injectable } from '@angular/core';
import { DSpaceObjectDataService } from '../core/data/dspace-object-data.service';
import { hasNoValue, hasValue } from '../shared/empty.util';
import { map } from 'rxjs/operators';

View File

@@ -1,5 +1,5 @@
import { Injectable } from '@angular/core';
import { ActivatedRouteSnapshot, Resolve, RouterStateSnapshot } from '@angular/router';
import { ActivatedRouteSnapshot, RouterStateSnapshot } from '@angular/router';
import { I18nBreadcrumbsService } from '../core/breadcrumbs/i18n-breadcrumbs.service';
import { BreadcrumbConfig } from '../breadcrumbs/breadcrumb/breadcrumb-config.model';
import { I18nBreadcrumbResolver } from '../core/breadcrumbs/i18n-breadcrumb.resolver';

View File

@@ -0,0 +1,21 @@
import { NgModule } from '@angular/core';
import { BrowseByRoutingModule } from './browse-by-routing.module';
import { BrowseByModule } from './browse-by.module';
import { ItemDataService } from '../core/data/item-data.service';
import { BrowseService } from '../core/browse/browse.service';
import { BrowseByGuard } from './browse-by-guard';
@NgModule({
imports: [
BrowseByRoutingModule,
BrowseByModule.withEntryComponents()
],
providers: [
ItemDataService,
BrowseService,
BrowseByGuard
]
})
export class BrowseByPageModule {
}

View File

@@ -1,38 +1,40 @@
import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { BrowseByTitlePageComponent } from './+browse-by-title-page/browse-by-title-page.component';
import { ItemDataService } from '../core/data/item-data.service';
import { SharedModule } from '../shared/shared.module';
import { BrowseByRoutingModule } from './browse-by-routing.module';
import { BrowseService } from '../core/browse/browse.service';
import { BrowseByMetadataPageComponent } from './+browse-by-metadata-page/browse-by-metadata-page.component';
import { BrowseByDatePageComponent } from './+browse-by-date-page/browse-by-date-page.component';
import { BrowseByGuard } from './browse-by-guard';
import { BrowseBySwitcherComponent } from './+browse-by-switcher/browse-by-switcher.component';
const ENTRY_COMPONENTS = [
// put only entry components that use custom decorator
BrowseByTitlePageComponent,
BrowseByMetadataPageComponent,
BrowseByDatePageComponent
];
@NgModule({
imports: [
BrowseByRoutingModule,
CommonModule,
SharedModule
],
declarations: [
BrowseByTitlePageComponent,
BrowseByMetadataPageComponent,
BrowseByDatePageComponent,
BrowseBySwitcherComponent,
...ENTRY_COMPONENTS
],
exports: [
BrowseBySwitcherComponent
],
providers: [
ItemDataService,
BrowseService,
BrowseByGuard
],
entryComponents: [
BrowseByTitlePageComponent,
BrowseByMetadataPageComponent,
BrowseByDatePageComponent
]
})
export class BrowseByModule {
/**
* NOTE: this method allows to resolve issue with components that using a custom decorator
* which are not loaded during CSR otherwise
*/
static withEntryComponents() {
return {
ngModule: SharedModule,
providers: ENTRY_COMPONENTS.map((component) => ({provide: component}))
};
}
}

View File

@@ -0,0 +1,19 @@
import { NgModule } from '@angular/core';
import { CollectionFormComponent } from './collection-form.component';
import { SharedModule } from '../../shared/shared.module';
@NgModule({
imports: [
SharedModule
],
declarations: [
CollectionFormComponent,
],
exports: [
CollectionFormComponent
]
})
export class CollectionFormModule {
}

View File

@@ -1,5 +1,5 @@
import { CollectionItemMapperComponent } from './collection-item-mapper.component';
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing';
import { RouterTestingModule } from '@angular/router/testing';
import { NgbModule } from '@ng-bootstrap/ng-bootstrap';
import { CommonModule } from '@angular/common';
@@ -28,8 +28,7 @@ import { ItemSelectComponent } from '../../shared/object-select/item-select/item
import { ObjectSelectService } from '../../shared/object-select/object-select.service';
import { ObjectSelectServiceStub } from '../../shared/testing/object-select-service.stub';
import { VarDirective } from '../../shared/utils/var.directive';
import { of as observableOf, of } from 'rxjs/internal/observable/of';
import { RestResponse } from '../../core/cache/response.models';
import { of as observableOf, of } from 'rxjs';
import { RouteService } from '../../core/services/route.service';
import { ErrorComponent } from '../../shared/error/error.component';
import { LoadingComponent } from '../../shared/loading/loading.component';
@@ -111,19 +110,19 @@ describe('CollectionItemMapperComponent', () => {
return observableOf('');
},
getQueryParameterValue: () => {
return observableOf('')
return observableOf('');
},
getQueryParamsWithPrefix: () => {
return observableOf('')
return observableOf('');
}
};
const fixedFilterServiceStub = {
getQueryByFilterName: () => {
return observableOf('')
return observableOf('');
}
};
beforeEach(async(() => {
beforeEach(waitForAsync(() => {
TestBed.configureTestingModule({
imports: [CommonModule, FormsModule, RouterTestingModule.withRoutes([]), TranslateModule.forRoot(), NgbModule],
declarations: [CollectionItemMapperComponent, ItemSelectComponent, SearchFormComponent, PaginationComponent, EnumKeysPipe, VarDirective, ErrorComponent, LoadingComponent],
@@ -200,7 +199,7 @@ describe('CollectionItemMapperComponent', () => {
it('should build a solr query to exclude the provided collection', () => {
expect(result).toEqual(expected);
})
});
});
describe('onCancel', () => {

View File

@@ -1,4 +1,4 @@
import { combineLatest as observableCombineLatest, Observable } from 'rxjs';
import { BehaviorSubject, combineLatest as observableCombineLatest, Observable } from 'rxjs';
import { ChangeDetectionStrategy, Component, Inject, OnInit, ViewChild } from '@angular/core';
import { fadeIn, fadeInOut } from '../../shared/animations/fade';
@@ -20,7 +20,6 @@ import { ItemDataService } from '../../core/data/item-data.service';
import { TranslateService } from '@ngx-translate/core';
import { CollectionDataService } from '../../core/data/collection-data.service';
import { isNotEmpty } from '../../shared/empty.util';
import { BehaviorSubject } from 'rxjs/internal/BehaviorSubject';
import { SEARCH_CONFIG_SERVICE } from '../../+my-dspace-page/my-dspace-page.component';
import { SearchConfigurationService } from '../../core/shared/search/search-configuration.service';
import { PaginatedSearchOptions } from '../../shared/search/paginated-search-options.model';
@@ -53,7 +52,7 @@ export class CollectionItemMapperComponent implements OnInit {
* A view on the tabset element
* Used to switch tabs programmatically
*/
@ViewChild('tabs', {static: false}) tabs;
@ViewChild('tabs') tabs;
/**
* The collection to map items to
@@ -127,7 +126,7 @@ export class CollectionItemMapperComponent implements OnInit {
if (shouldUpdate) {
return this.collectionDataService.getMappedItems(collectionRD.payload.id, Object.assign(options, {
sort: this.defaultSortOptions
}),followLink('owningCollection'))
}),followLink('owningCollection'));
}
})
);
@@ -172,10 +171,10 @@ export class CollectionItemMapperComponent implements OnInit {
* @param {Observable<RestResponse[]>} responses$ The responses after adding/removing a mapping
* @param {boolean} remove Whether or not the goal was to remove mappings
*/
private showNotifications(responses$: Observable<Array<RemoteData<NoContent>>>, remove?: boolean) {
private showNotifications(responses$: Observable<RemoteData<NoContent>[]>, remove?: boolean) {
const messageInsertion = remove ? 'unmap' : 'map';
responses$.subscribe((responses: Array<RemoteData<NoContent>>) => {
responses$.subscribe((responses: RemoteData<NoContent>[]) => {
const successful = responses.filter((response: RemoteData<any>) => response.hasSucceeded);
const unsuccessful = responses.filter((response: RemoteData<any>) => response.hasFailed);
if (successful.length > 0) {
@@ -254,7 +253,7 @@ export class CollectionItemMapperComponent implements OnInit {
getRemoteDataPayload(),
take(1)
).subscribe((collection: Collection) => {
this.router.navigate(['/collections/', collection.id])
this.router.navigate(['/collections/', collection.id]);
});
}

View File

@@ -3,9 +3,8 @@ import { ActivatedRouteSnapshot, Router, RouterStateSnapshot } from '@angular/ro
import { Collection } from '../core/shared/collection.model';
import { CollectionPageResolver } from './collection-page.resolver';
import { AuthorizationDataService } from '../core/data/feature-authorization/authorization-data.service';
import { of as observableOf } from 'rxjs';
import { Observable, of as observableOf } from 'rxjs';
import { DsoPageFeatureGuard } from '../core/data/feature-authorization/feature-authorization-guard/dso-page-feature.guard';
import { Observable } from 'rxjs/internal/Observable';
import { FeatureID } from '../core/data/feature-authorization/feature-id';
import { AuthService } from '../core/auth/auth.service';

View File

@@ -13,15 +13,15 @@ export function getCollectionPageRoute(collectionId: string) {
}
export function getCollectionEditRoute(id: string) {
return new URLCombiner(getCollectionModuleRoute(), id, COLLECTION_EDIT_PATH).toString()
return new URLCombiner(getCollectionModuleRoute(), id, COLLECTION_EDIT_PATH).toString();
}
export function getCollectionCreateRoute() {
return new URLCombiner(getCollectionModuleRoute(), COLLECTION_CREATE_PATH).toString()
return new URLCombiner(getCollectionModuleRoute(), COLLECTION_CREATE_PATH).toString();
}
export function getCollectionEditRolesRoute(id) {
return new URLCombiner(getCollectionPageRoute(id), COLLECTION_EDIT_PATH, COLLECTION_EDIT_ROLES_PATH).toString()
return new URLCombiner(getCollectionPageRoute(id), COLLECTION_EDIT_PATH, COLLECTION_EDIT_ROLES_PATH).toString();
}
export const COLLECTION_CREATE_PATH = 'create';

View File

@@ -41,7 +41,8 @@ import { LinkMenuItemModel } from '../shared/menu/menu-item/models/link.model';
children: [
{
path: COLLECTION_EDIT_PATH,
loadChildren: './edit-collection-page/edit-collection-page.module#EditCollectionPageModule',
loadChildren: () => import('./edit-collection-page/edit-collection-page.module')
.then((m) => m.EditCollectionPageModule),
canActivate: [CollectionPageAdministratorGuard]
},
{

View File

@@ -1,7 +1,7 @@
import { ChangeDetectionStrategy, Component, OnInit } from '@angular/core';
import { ActivatedRoute, Router } from '@angular/router';
import { BehaviorSubject, Observable, Subject } from 'rxjs';
import { filter, flatMap, map, startWith, switchMap, take } from 'rxjs/operators';
import { filter, map, mergeMap, startWith, switchMap, take } from 'rxjs/operators';
import { PaginatedSearchOptions } from '../shared/search/paginated-search-options.model';
import { SearchService } from '../core/shared/search/search.service';
import { SortDirection, SortOptions } from '../core/cache/models/sort-options.model';
@@ -15,16 +15,13 @@ import { Bitstream } from '../core/shared/bitstream.model';
import { Collection } from '../core/shared/collection.model';
import { DSpaceObjectType } from '../core/shared/dspace-object-type.model';
import { Item } from '../core/shared/item.model';
import {
getFirstSucceededRemoteData,
redirectOn4xx,
toDSpaceObjectListRD
} from '../core/shared/operators';
import { getFirstSucceededRemoteData, redirectOn4xx, toDSpaceObjectListRD } from '../core/shared/operators';
import { fadeIn, fadeInOut } from '../shared/animations/fade';
import { hasValue, isNotEmpty } from '../shared/empty.util';
import { PaginationComponentOptions } from '../shared/pagination/pagination-component-options.model';
import { AuthService } from '../core/auth/auth.service';
import {PaginationChangeEvent} from '../shared/pagination/paginationChangeEvent.interface';
@Component({
selector: 'ds-collection-page',
@@ -71,7 +68,7 @@ export class CollectionPageComponent implements OnInit {
this.logoRD$ = this.collectionRD$.pipe(
map((rd: RemoteData<Collection>) => rd.payload),
filter((collection: Collection) => hasValue(collection)),
flatMap((collection: Collection) => collection.logo)
mergeMap((collection: Collection) => collection.logo)
);
this.paginationChanges$ = new BehaviorSubject({
@@ -90,7 +87,7 @@ export class CollectionPageComponent implements OnInit {
pagination: dto.paginationConfig,
sort: dto.sortConfig,
dsoTypes: [DSpaceObjectType.ITEM]
})).pipe(toDSpaceObjectListRD()) as Observable<RemoteData<PaginatedList<Item>>>
})).pipe(toDSpaceObjectListRD()) as Observable<RemoteData<PaginatedList<Item>>>;
}),
startWith(undefined) // Make sure switching pages shows loading component
)
@@ -99,20 +96,23 @@ export class CollectionPageComponent implements OnInit {
this.route.queryParams.pipe(take(1)).subscribe((params) => {
this.metadata.processRemoteData(this.collectionRD$);
this.onPaginationChange(params);
})
});
}
isNotEmpty(object: any) {
return isNotEmpty(object);
}
onPaginationChange(event) {
this.paginationConfig.currentPage = +event.page || this.paginationConfig.currentPage;
this.paginationConfig.pageSize = +event.pageSize || this.paginationConfig.pageSize;
this.sortConfig.direction = event.sortDirection || this.sortConfig.direction;
this.sortConfig.field = event.sortField || this.sortConfig.field;
onPaginationChange(event: PaginationChangeEvent) {
this.paginationConfig = Object.assign(new PaginationComponentOptions(), {
currentPage: event.pagination.currentPage || this.paginationConfig.currentPage,
pageSize: event.pagination.pageSize || this.paginationConfig.pageSize,
id: 'collection-page-pagination'
});
this.sortConfig = Object.assign(new SortOptions('dc.date.accessioned', SortDirection.DESC), {
direction: event.sort.direction || this.sortConfig.direction,
field: event.sort.field || this.sortConfig.field
});
this.paginationChanges$.next({
paginationConfig: this.paginationConfig,
sortConfig: this.sortConfig

View File

@@ -6,13 +6,13 @@ import { SharedModule } from '../shared/shared.module';
import { CollectionPageComponent } from './collection-page.component';
import { CollectionPageRoutingModule } from './collection-page-routing.module';
import { CreateCollectionPageComponent } from './create-collection-page/create-collection-page.component';
import { CollectionFormComponent } from './collection-form/collection-form.component';
import { DeleteCollectionPageComponent } from './delete-collection-page/delete-collection-page.component';
import { EditItemTemplatePageComponent } from './edit-item-template-page/edit-item-template-page.component';
import { EditItemPageModule } from '../+item-page/edit-item-page/edit-item-page.module';
import { CollectionItemMapperComponent } from './collection-item-mapper/collection-item-mapper.component';
import { SearchService } from '../core/shared/search/search.service';
import { StatisticsModule } from '../statistics/statistics.module';
import { CollectionFormModule } from './collection-form/collection-form.module';
@NgModule({
imports: [
@@ -20,19 +20,16 @@ import { StatisticsModule } from '../statistics/statistics.module';
SharedModule,
CollectionPageRoutingModule,
StatisticsModule.forRoot(),
EditItemPageModule
EditItemPageModule,
CollectionFormModule
],
declarations: [
CollectionPageComponent,
CreateCollectionPageComponent,
DeleteCollectionPageComponent,
CollectionFormComponent,
EditItemTemplatePageComponent,
CollectionItemMapperComponent
],
exports: [
CollectionFormComponent
],
providers: [
SearchService,
]

View File

@@ -1,5 +1,5 @@
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { ActivatedRoute, Router } from '@angular/router';
import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing';
import { Router } from '@angular/router';
import { TranslateModule } from '@ngx-translate/core';
import { CommonModule } from '@angular/common';
import { RouterTestingModule } from '@angular/router/testing';
@@ -12,13 +12,13 @@ import { CommunityDataService } from '../../core/data/community-data.service';
import { CreateCollectionPageComponent } from './create-collection-page.component';
import { NotificationsService } from '../../shared/notifications/notifications.service';
import { NotificationsServiceStub } from '../../shared/testing/notifications-service.stub';
import {RequestService} from '../../core/data/request.service';
import { RequestService } from '../../core/data/request.service';
describe('CreateCollectionPageComponent', () => {
let comp: CreateCollectionPageComponent;
let fixture: ComponentFixture<CreateCollectionPageComponent>;
beforeEach(async(() => {
beforeEach(waitForAsync(() => {
TestBed.configureTestingModule({
imports: [TranslateModule.forRoot(), SharedModule, CommonModule, RouterTestingModule],
declarations: [CreateCollectionPageComponent],
@@ -46,6 +46,6 @@ describe('CreateCollectionPageComponent', () => {
describe('frontendURL', () => {
it('should have the right frontendURL set', () => {
expect((comp as any).frontendURL).toEqual('/collections/');
})
});
});
});

View File

@@ -1,5 +1,5 @@
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { ActivatedRoute, Router } from '@angular/router';
import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing';
import { ActivatedRoute } from '@angular/router';
import { TranslateModule } from '@ngx-translate/core';
import { CommonModule } from '@angular/common';
import { RouterTestingModule } from '@angular/router/testing';
@@ -9,13 +9,13 @@ import { of as observableOf } from 'rxjs';
import { NotificationsService } from '../../shared/notifications/notifications.service';
import { DeleteCollectionPageComponent } from './delete-collection-page.component';
import { CollectionDataService } from '../../core/data/collection-data.service';
import {RequestService} from '../../core/data/request.service';
import { RequestService } from '../../core/data/request.service';
describe('DeleteCollectionPageComponent', () => {
let comp: DeleteCollectionPageComponent;
let fixture: ComponentFixture<DeleteCollectionPageComponent>;
beforeEach(async(() => {
beforeEach(waitForAsync(() => {
TestBed.configureTestingModule({
imports: [TranslateModule.forRoot(), SharedModule, CommonModule, RouterTestingModule],
declarations: [DeleteCollectionPageComponent],
@@ -38,6 +38,6 @@ describe('DeleteCollectionPageComponent', () => {
describe('frontendURL', () => {
it('should have the right frontendURL set', () => {
expect((comp as any).frontendURL).toEqual('/collections/');
})
});
});
});

View File

@@ -1,6 +1,6 @@
import { CommonModule } from '@angular/common';
import { ChangeDetectorRef, NO_ERRORS_SCHEMA } from '@angular/core';
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing';
import { ActivatedRoute } from '@angular/router';
import { cold } from 'jasmine-marbles';
@@ -35,7 +35,7 @@ describe('CollectionAuthorizationsComponent', () => {
}
};
beforeEach(async(() => {
beforeEach(waitForAsync(() => {
TestBed.configureTestingModule({
imports: [
CommonModule

View File

@@ -1,4 +1,4 @@
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing';
import { TranslateModule } from '@ngx-translate/core';
import { CUSTOM_ELEMENTS_SCHEMA, DebugElement } from '@angular/core';
import { CollectionCurateComponent } from './collection-curate.component';
@@ -20,7 +20,7 @@ describe('CollectionCurateComponent', () => {
metadata: {'dc.title': ['Collection Name'], 'dc.identifier.uri': [ { value: '123456789/1'}]}
});
beforeEach(async(() => {
beforeEach(waitForAsync(() => {
routeStub = {
parent: {
data: observableOf({

View File

@@ -1,11 +1,11 @@
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing';
import { TranslateModule } from '@ngx-translate/core';
import { SharedModule } from '../../../shared/shared.module';
import { CommonModule } from '@angular/common';
import { RouterTestingModule } from '@angular/router/testing';
import { CollectionDataService } from '../../../core/data/collection-data.service';
import { ActivatedRoute, Router } from '@angular/router';
import { of as observableOf } from 'rxjs/internal/observable/of';
import { of as observableOf } from 'rxjs';
import { NO_ERRORS_SCHEMA } from '@angular/core';
import { CollectionMetadataComponent } from './collection-metadata.component';
import { NotificationsService } from '../../../shared/notifications/notifications.service';
@@ -53,7 +53,7 @@ describe('CollectionMetadataComponent', () => {
removeByHrefSubstring: {}
});
beforeEach(async(() => {
beforeEach(waitForAsync(() => {
TestBed.configureTestingModule({
imports: [TranslateModule.forRoot(), SharedModule, CommonModule, RouterTestingModule],
declarations: [CollectionMetadataComponent],

View File

@@ -4,12 +4,11 @@ import { Collection } from '../../../core/shared/collection.model';
import { CollectionDataService } from '../../../core/data/collection-data.service';
import { ActivatedRoute, Router } from '@angular/router';
import { ItemTemplateDataService } from '../../../core/data/item-template-data.service';
import { Observable } from 'rxjs/internal/Observable';
import { combineLatest as combineLatestObservable, Observable } from 'rxjs';
import { RemoteData } from '../../../core/data/remote-data';
import { Item } from '../../../core/shared/item.model';
import { getRemoteDataPayload, getFirstSucceededRemoteData } from '../../../core/shared/operators';
import { switchMap, take } from 'rxjs/operators';
import { combineLatest as combineLatestObservable } from 'rxjs';
import { NotificationsService } from '../../../shared/notifications/notifications.service';
import { TranslateService } from '@ngx-translate/core';
import { ObjectCacheService } from '../../../core/cache/object-cache.service';

Some files were not shown because too many files have changed in this diff Show More