diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md
index 3e727e2bdf..b4063b0550 100644
--- a/.github/pull_request_template.md
+++ b/.github/pull_request_template.md
@@ -21,8 +21,5 @@ _This checklist provides a reminder of what we are going to look for when review
- [ ] My PR is small in size (e.g. less than 1,000 lines of code, not including comments & specs/tests), or I have provided reasons as to why that's not possible.
- [ ] My PR passes [TSLint](https://palantir.github.io/tslint/) validation using `yarn run lint`
- [ ] My PR includes [TypeDoc](https://typedoc.org/) comments for _all new (or modified) public methods and classes_. It also includes TypeDoc for large or complex private methods.
-- [ ] My PR passes all specs/tests and includes new/updated specs for any bug fixes, improvements or new features. A few reminders about what constitutes good tests:
- * Include tests for different user types (if behavior differs), including: (1) Anonymous user, (2) Logged in user (non-admin), and (3) Administrator.
- * Include tests for error scenarios, e.g. when errors/warnings should appear (or buttons should be disabled).
- * For bug fixes, include a test that reproduces the bug and proves it is fixed. For clarity, it may be useful to provide the test in a separate commit from the bug fix.
+- [ ] My PR passes all specs/tests and includes new/updated specs or tests based on the [Code Testing Guide](https://wiki.lyrasis.org/display/DSPACE/Code+Testing+Guide).
- [ ] If my PR includes new, third-party dependencies (in `package.json`), I've made sure their licenses align with the [DSpace BSD License](https://github.com/DSpace/DSpace/blob/main/LICENSE) based on the [Licensing of Contributions](https://wiki.lyrasis.org/display/DSPACE/Code+Contribution+Guidelines#CodeContributionGuidelines-LicensingofContributions) documentation.
diff --git a/.github/workflows/label_merge_conflicts.yml b/.github/workflows/label_merge_conflicts.yml
new file mode 100644
index 0000000000..dcbab18f1b
--- /dev/null
+++ b/.github/workflows/label_merge_conflicts.yml
@@ -0,0 +1,25 @@
+# This workflow checks open PRs for merge conflicts and labels them when conflicts are found
+name: Check for merge conflicts
+
+# Run whenever the "main" branch is updated
+# NOTE: This means merge conflicts are only checked for when a PR is merged to main.
+on:
+ push:
+ branches:
+ - main
+
+jobs:
+ triage:
+ runs-on: ubuntu-latest
+ steps:
+ # See: https://github.com/mschilde/auto-label-merge-conflicts/
+ - name: Auto-label PRs with merge conflicts
+ uses: mschilde/auto-label-merge-conflicts@v2.0
+ # Add "merge conflict" label if a merge conflict is detected. Remove it when resolved.
+ # Note, the authentication token is created automatically
+ # See: https://docs.github.com/en/actions/configuring-and-managing-workflows/authenticating-with-the-github_token
+ with:
+ CONFLICT_LABEL_NAME: 'merge conflict'
+ GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
+ # Ignore errors
+ continue-on-error: true
diff --git a/.travis.yml b/.travis.yml
index 54b3c4752a..13a159bfd0 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -51,10 +51,10 @@ before_script:
script:
# build app and run all tests
- - ng lint
- - travis_wait yarn run build:prod
- - yarn test:headless
- - yarn run e2e:ci
+ - ng lint || travis_terminate 1;
+ - travis_wait yarn run build:prod || travis_terminate 1;
+ - yarn test:headless || travis_terminate 1;
+ - yarn run e2e:ci || travis_terminate 1;
after_script:
# Shutdown docker after everything runs
diff --git a/angular.json b/angular.json
index 9c55d648b3..d8d8a2dc2e 100644
--- a/angular.json
+++ b/angular.json
@@ -18,7 +18,7 @@
"builder": "@angular-builders/custom-webpack:browser",
"options": {
"customWebpackConfig": {
- "path": "./webpack/webpack.common.ts",
+ "path": "./webpack/webpack.browser.ts",
"mergeStrategies": {
"loaders": "prepend"
}
@@ -30,7 +30,8 @@
"tsConfig": "tsconfig.app.json",
"aot": false,
"assets": [
- "src/assets"
+ "src/assets",
+ "src/robots.txt"
],
"styles": [
"src/styles.scss"
@@ -84,7 +85,7 @@
"builder": "@angular-builders/custom-webpack:karma",
"options": {
"customWebpackConfig": {
- "path": "./webpack/webpack.common.ts",
+ "path": "./webpack/webpack.test.ts",
"mergeStrategies": {
"loaders": "prepend"
}
diff --git a/package.json b/package.json
index c1e5b05010..52afb7c4c0 100644
--- a/package.json
+++ b/package.json
@@ -146,6 +146,7 @@
"dotenv": "^8.2.0",
"fork-ts-checker-webpack-plugin": "^0.4.10",
"html-webpack-plugin": "^3.2.0",
+ "http-proxy-middleware": "^1.0.5",
"jasmine-core": "^3.3.0",
"jasmine-marbles": "0.3.1",
"jasmine-spec-reporter": "~4.2.1",
diff --git a/scripts/set-env.ts b/scripts/set-env.ts
index 5eee22a4be..5570b77218 100644
--- a/scripts/set-env.ts
+++ b/scripts/set-env.ts
@@ -54,6 +54,13 @@ import(environmentFilePath)
function generateEnvironmentFile(file: GlobalConfig): void {
file.production = production;
buildBaseUrls(file);
+
+ // TODO remove workaround in beta 5
+ if (file.rest.nameSpace.match("(.*)/api/?$") !== null) {
+ const newValue = getNameSpace(file.rest.nameSpace);
+ console.log(colors.white.bgMagenta.bold(`The rest.nameSpace property in your environment file or in your DSPACE_REST_NAMESPACE environment variable ends with '/api'.\nThis is deprecated. As '/api' isn't configurable on the rest side, it shouldn't be repeated in every environment file.\nPlease change the rest nameSpace to '${newValue}'`));
+ }
+
const contents = `export const environment = ` + JSON.stringify(file);
writeFile(targetPath, contents, (err) => {
if (err) {
@@ -112,5 +119,16 @@ function getPort(port: number): string {
}
function getNameSpace(nameSpace: string): string {
- return nameSpace ? nameSpace.charAt(0) === '/' ? nameSpace : '/' + nameSpace : '';
+ // TODO remove workaround in beta 5
+ const apiMatches = nameSpace.match("(.*)/api/?$");
+ if (apiMatches != null) {
+ let newValue = '/'
+ if (hasValue(apiMatches[1])) {
+ newValue = apiMatches[1];
+ }
+ return newValue;
+ }
+ else {
+ return nameSpace ? nameSpace.charAt(0) === '/' ? nameSpace : '/' + nameSpace : '';
+ }
}
diff --git a/server.ts b/server.ts
index a5d47d8bd7..99e2b25e1e 100644
--- a/server.ts
+++ b/server.ts
@@ -15,7 +15,6 @@
* import for `ngExpressEngine`.
*/
-import 'zone.js/dist/zone-node';
import 'reflect-metadata';
import 'rxjs';
@@ -33,6 +32,8 @@ import { enableProdMode, NgModuleFactory, Type } from '@angular/core';
import { REQUEST, RESPONSE } from '@nguniversal/express-engine/tokens';
import { environment } from './src/environments/environment';
+import { createProxyMiddleware } from 'http-proxy-middleware';
+import { hasValue } from './src/app/shared/empty.util';
/*
* Set path for the browser application's dist folder
@@ -98,7 +99,6 @@ app.engine('html', (_, options, callback) =>
/*
* Register the view engines for html and ejs
*/
-app.set('view engine', 'ejs');
app.set('view engine', 'html');
/*
@@ -106,6 +106,11 @@ app.set('view engine', 'html');
*/
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
@@ -125,56 +130,27 @@ app.get('*.*', cacheControl, express.static(DIST_FOLDER, { index: false }));
* The callback function to serve server side angular
*/
function ngApp(req, res) {
- // Object to be set to window.dspace when CSR is used
- // this allows us to pass the info in the original request
- // to the dspace7-angular instance running in the client's browser
- const dspace = {
- originalRequest: {
- headers: req.headers,
- body: req.body,
- method: req.method,
- params: req.params,
- reportProgress: req.reportProgress,
- withCredentials: req.withCredentials,
- responseType: req.responseType,
- urlWithParams: req.urlWithParams
- }
- };
-
- // callback function for the case when SSR throws an error.
- function onHandleError(parentZoneDelegate, currentZone, targetZone, error) {
- if (!res._headerSent) {
- console.warn('Error in SSR, serving for direct CSR. Error details : ', error);
- res.sendFile('index.csr.ejs', {
- root: DIST_FOLDER,
- scripts: ``
- });
- }
- }
-
if (environment.universal.preboot) {
- // If preboot is enabled, create a new zone for SSR, and
- // register the error handler for when it throws an error
- Zone.current.fork({ name: 'CSR fallback', onHandleError }).run(() => {
- res.render(DIST_FOLDER + '/index.html', {
- req,
- res,
- preboot: environment.universal.preboot,
- async: environment.universal.async,
- time: environment.universal.time,
- baseUrl: environment.ui.nameSpace,
- originUrl: environment.ui.baseUrl,
- requestUrl: req.originalUrl
- });
- });
+ res.render(DIST_FOLDER + '/index.html', {
+ req,
+ res,
+ preboot: environment.universal.preboot,
+ async: environment.universal.async,
+ time: environment.universal.time,
+ baseUrl: environment.ui.nameSpace,
+ originUrl: environment.ui.baseUrl,
+ requestUrl: req.originalUrl
+ }, (err) => {
+ console.warn('Error in SSR, serving for direct CSR.');
+ if (hasValue(err)) {
+ console.warn('Error details : ', err);
+ }
+ res.sendFile(DIST_FOLDER + '/index.html');
+ })
} else {
- // If preboot is disabled, just serve the client side ejs template and pass it the required
- // variables
+ // If preboot is disabled, just serve the client
console.log('Universal off, serving for direct CSR');
- res.render('index-csr.ejs', {
- root: DIST_FOLDER,
- scripts: ``
- });
+ res.sendFile(DIST_FOLDER + '/index.html');
}
}
diff --git a/src/app/+admin/admin-access-control/admin-access-control-routing-paths.ts b/src/app/+admin/admin-access-control/admin-access-control-routing-paths.ts
new file mode 100644
index 0000000000..2080cb14a7
--- /dev/null
+++ b/src/app/+admin/admin-access-control/admin-access-control-routing-paths.ts
@@ -0,0 +1,8 @@
+import { URLCombiner } from '../../core/url-combiner/url-combiner';
+import { getAccessControlModuleRoute } from '../admin-routing-paths';
+
+export const GROUP_EDIT_PATH = 'groups';
+
+export function getGroupEditRoute(id: string) {
+ return new URLCombiner(getAccessControlModuleRoute(), GROUP_EDIT_PATH, id).toString();
+}
diff --git a/src/app/+admin/admin-access-control/admin-access-control-routing.module.ts b/src/app/+admin/admin-access-control/admin-access-control-routing.module.ts
index f61a3c2f71..d2f2233eee 100644
--- a/src/app/+admin/admin-access-control/admin-access-control-routing.module.ts
+++ b/src/app/+admin/admin-access-control/admin-access-control-routing.module.ts
@@ -3,14 +3,7 @@ import { RouterModule } from '@angular/router';
import { EPeopleRegistryComponent } from './epeople-registry/epeople-registry.component';
import { GroupFormComponent } from './group-registry/group-form/group-form.component';
import { GroupsRegistryComponent } from './group-registry/groups-registry.component';
-import { URLCombiner } from '../../core/url-combiner/url-combiner';
-import { getAccessControlModulePath } from '../admin-routing.module';
-
-export const GROUP_EDIT_PATH = 'groups';
-
-export function getGroupEditPath(id: string) {
- return new URLCombiner(getAccessControlModulePath(), GROUP_EDIT_PATH, id).toString();
-}
+import { GROUP_EDIT_PATH } from './admin-access-control-routing-paths';
@NgModule({
imports: [
diff --git a/src/app/+admin/admin-access-control/epeople-registry/epeople-registry.component.html b/src/app/+admin/admin-access-control/epeople-registry/epeople-registry.component.html
index 20593756c1..9cf733a394 100644
--- a/src/app/+admin/admin-access-control/epeople-registry/epeople-registry.component.html
+++ b/src/app/+admin/admin-access-control/epeople-registry/epeople-registry.component.html
@@ -7,87 +7,88 @@