Skip to content

Commit

Permalink
Merged in DSC-648-alignment-with-7.3 (pull request DSpace#328)
Browse files Browse the repository at this point in the history
alignment with DSpace 7.3
  • Loading branch information
atarix83 committed Oct 5, 2022
2 parents 14ce8c7 + e8b84db commit 5ed56d1
Show file tree
Hide file tree
Showing 957 changed files with 25,225 additions and 15,025 deletions.
9 changes: 6 additions & 3 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ jobs:
strategy:
# Create a matrix of Node versions to test against (in parallel)
matrix:
node-version: [12.x, 14.x]
node-version: [14.x, 16.x]
# Do NOT exit immediately if one matrix job fails
fail-fast: false
# These are the actual CI steps to perform per job
Expand Down Expand Up @@ -72,18 +72,21 @@ jobs:
- name: Run lint
run: yarn run lint --quiet

- name: Check for circular dependencies
run: yarn run check-circ-deps

- name: Run build
run: yarn run build:prod

- name: Run specs (unit tests)
run: yarn run test:headless

# NOTE: Angular CLI only supports code coverage for specs. See https://github.com/angular/angular-cli/issues/6286
# Upload coverage reports to Codecov (for Node v12 only)
# Upload coverage reports to Codecov (for one version of Node only)
# https://github.com/codecov/codecov-action
- name: Upload coverage to Codecov.io
uses: codecov/codecov-action@v2
if: matrix.node-version == '12.x'
if: matrix.node-version == '16.x'

# Using docker-compose start backend using CI configuration
# and load assetstore from a cached copy
Expand Down
9 changes: 9 additions & 0 deletions .github/workflows/docker.yml
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,10 @@ jobs:
# We turn off 'latest' tag by default.
TAGS_FLAVOR: |
latest=false
# Architectures / Platforms for which we will build Docker images
# If this is a PR, we ONLY build for AMD64. For PRs we only do a sanity check test to ensure Docker builds work.
# If this is NOT a PR (e.g. a tag or merge commit), also build for ARM64.
PLATFORMS: linux/amd64${{ github.event_name != 'pull_request' && ', linux/arm64' || '' }}

steps:
# https://github.com/actions/checkout
Expand All @@ -41,6 +45,10 @@ jobs:
- name: Setup Docker Buildx
uses: docker/setup-buildx-action@v1

# https://github.com/docker/setup-qemu-action
- name: Set up QEMU emulation to build for multiple architectures
uses: docker/setup-qemu-action@v2

# https://github.com/docker/login-action
- name: Login to DockerHub
# Only login if not a PR, as PRs only trigger a Docker build and not a push
Expand Down Expand Up @@ -70,6 +78,7 @@ jobs:
with:
context: .
file: ./Dockerfile
platforms: ${{ env.PLATFORMS }}
# For pull requests, we run the Docker build (to ensure no PR changes break the build),
# but we ONLY do an image push to DockerHub if it's NOT a PR
push: ${{ github.event_name != 'pull_request' }}
Expand Down
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -37,3 +37,5 @@ package-lock.json

.env
/nbproject/

junit.xml
7 changes: 6 additions & 1 deletion Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,9 @@ EXPOSE 4000
# We run yarn install with an increased network timeout (5min) to avoid "ESOCKETTIMEDOUT" errors from hub.docker.com
# See, for example https://github.com/yarnpkg/yarn/issues/5540
RUN yarn install --network-timeout 300000
CMD yarn run start:dev

# On startup, run in DEVELOPMENT mode (this defaults to live reloading enabled, etc).
# Listen / accept connections from all IP addresses.
# NOTE: At this time it is only possible to run Docker container in Production mode
# if you have a public IP. See https://github.com/DSpace/dspace-angular/issues/1485
CMD yarn serve --host 0.0.0.0
9 changes: 6 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ You can find additional information on the DSpace 7 Angular UI on the [wiki](htt
Quick start
-----------

**Ensure you're running [Node](https://nodejs.org) `v12.x`, `v14.x` or `v16.x`, [npm](https://www.npmjs.com/) >= `v5.x` and [yarn](https://yarnpkg.com) == `v1.x`**
**Ensure you're running [Node](https://nodejs.org) `v14.x` or `v16.x`, [npm](https://www.npmjs.com/) >= `v5.x` and [yarn](https://yarnpkg.com) == `v1.x`**

```bash
# clone the repo
Expand Down Expand Up @@ -68,7 +68,7 @@ Requirements
------------

- [Node.js](https://nodejs.org) and [yarn](https://yarnpkg.com)
- Ensure you're running node `v12.x`, `v14.x` or `v16.x` and yarn == `v1.x`
- Ensure you're running node `v14.x` or `v16.x` and yarn == `v1.x`

If you have [`nvm`](https://github.com/creationix/nvm#install-script) or [`nvm-windows`](https://github.com/coreybutler/nvm-windows) installed, which is highly recommended, you can run `nvm install --lts && nvm use` to install and start using the latest Node LTS.

Expand Down Expand Up @@ -308,8 +308,11 @@ All E2E tests must be created under the `./cypress/integration/` folder, and mus
* In the [Cypress Test Runner](https://docs.cypress.io/guides/core-concepts/test-runner), you'll Cypress automatically visit the page. This first test will succeed, as all you are doing is making sure the _page exists_.
* From here, you can use the [Selector Playground](https://docs.cypress.io/guides/core-concepts/test-runner#Selector-Playground) in the Cypress Test Runner window to determine how to tell Cypress to interact with a specific HTML element on that page.
* Most commands start by telling Cypress to [get()](https://docs.cypress.io/api/commands/get) a specific element, using a CSS or jQuery style selector
* It's generally best not to rely on attributes like `class` and `id` in tests, as those are likely to change later on. Instead, you can add a `data-test` attribute to makes it clear that it's required for a test.
* Cypress can then do actions like [click()](https://docs.cypress.io/api/commands/click) an element, or [type()](https://docs.cypress.io/api/commands/type) text in an input field, etc.
* Cypress can also validate that something occurs, using [should()](https://docs.cypress.io/api/commands/should) assertions.
* When running with server-side rendering enabled, the client first receives HTML without the JS; only once the page is rendered client-side do some elements (e.g. a button that toggles a Bootstrap dropdown) become fully interactive. This can trip up Cypress in some cases as it may try to `click` or `type` in an element that's not fully loaded yet, causing tests to fail.
* To work around this issue, define the attributes you use for Cypress selectors as `[attr.data-test]="'button' | ngBrowserOnly"`. This will only show the attribute in CSR HTML, forcing Cypress to wait until CSR is complete before interacting with the element.
* Cypress can also validate that something occurs, using [should()](https://docs.cypress.io/api/commands/should) assertions.
* Any time you save your test file, the Cypress Test Runner will reload & rerun it. This allows you can see your results quickly as you write the tests & correct any broken tests rapidly.
* Cypress also has a great guide on [writing your first test](https://on.cypress.io/writing-first-test) with much more info. Keep in mind, while the examples in the Cypress docs often involve Javascript files (.js), the same examples will work in our Typescript (.ts) e2e tests.
Expand Down
3 changes: 2 additions & 1 deletion angular.json
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,8 @@
"bundleName": "dspace-theme"
}
],
"scripts": []
"scripts": [],
"baseHref": "/"
},
"configurations": {
"development": {
Expand Down
11 changes: 10 additions & 1 deletion config/config.example.yml
Original file line number Diff line number Diff line change
Expand Up @@ -163,6 +163,9 @@ languages:
- code: fi
label: Suomi
active: true
- code: tr
label: Türkçe
active: true
- code: bn
label: বাংলা
active: true
Expand All @@ -176,10 +179,12 @@ browseBy:
# The absolute lowest year to display in the dropdown (only used when no lowest date can be found for all items)
defaultLowerLimit: 1900

# Item Page Config
# Item Config
item:
edit:
undoTimeout: 10000 # 10 seconds
# Show the item access status label in items lists
showAccessStatuses: false

# When the search results are retrieved, for each item type the metadata with a valid authority value are inspected.
# Referenced items will be fetched with a find all by id strategy to avoid individual rest requests
Expand Down Expand Up @@ -259,6 +264,10 @@ themes:
rel: stylesheet
href: "https://fonts.googleapis.com/icon?family=Material+Icons"

# The default bundles that should always be displayed as suggestions when you upload a new bundle
bundle:
- standardBundles: [ ORIGINAL, THUMBNAIL, LICENSE ]

# Whether to enable media viewer for image and/or video Bitstreams (i.e. Bitstreams whose MIME type starts with 'image' or 'video').
# For images, this enables a gallery viewer where you can zoom or page through images.
# For videos, this enables embedded video streaming
Expand Down
8 changes: 4 additions & 4 deletions cypress/integration/my-dspace.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ xdescribe('My DSpace page', () => {
cy.visit('/mydspace');

// Open the New Submission dropdown
cy.get('#dropdownSubmission').click();
cy.get('button[data-test="submission-dropdown"]').click();
// Click on the "Item" type in that dropdown
cy.get('#entityControlsDropdownMenu button[title="none"]').click();

Expand Down Expand Up @@ -98,7 +98,7 @@ xdescribe('My DSpace page', () => {
const id = subpaths[2];

// Click the "Save for Later" button to save this submission
cy.get('button#saveForLater').click();
cy.get('ds-submission-form-footer [data-test="save-for-later"]').click();

// "Save for Later" should send us to MyDSpace
cy.url().should('include', '/mydspace');
Expand All @@ -122,7 +122,7 @@ xdescribe('My DSpace page', () => {
cy.url().should('include', '/workspaceitems/' + id + '/edit');

// Discard our new submission by clicking Discard in Submission form & confirming
cy.get('button#discard').click();
cy.get('ds-submission-form-footer [data-test="discard"]').click();
cy.get('button#discard_submit').click();

// Discarding should send us back to MyDSpace
Expand All @@ -135,7 +135,7 @@ xdescribe('My DSpace page', () => {
cy.visit('/mydspace');

// Open the New Import dropdown
cy.get('#dropdownImport').click();
cy.get('button[data-test="import-dropdown"]').click();
// Click on the "Item" type in that dropdown
cy.get('#importControlsDropdownMenu button[title="none"]').click();

Expand Down
2 changes: 1 addition & 1 deletion cypress/integration/search-page.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ describe('Search Page', () => {

// Click each filter toggle to open *every* filter
// (As we want to scan filter section for accessibility issues as well)
cy.get('.filter-toggle').click({ multiple: true });
cy.get('[data-test="filter-toggle"]').click({ multiple: true });

// Analyze <ds-search-page> for accessibility issues
/* testA11y(
Expand Down
1 change: 1 addition & 0 deletions cypress/integration/submission.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ xdescribe('New Submission page', () => {
cy.get('button#deposit').click();

// A warning alert should display.
cy.get('ds-notification div.alert-success').should('not.exist');
cy.get('ds-notification div.alert-warning').should('be.visible');

// First section should have an exclamation error in the header
Expand Down
2 changes: 1 addition & 1 deletion cypress/support/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ import './commands';
import 'cypress-axe';

// Runs once before the first test in each "block"
before(() => {
beforeEach(() => {
// Pre-agree to all Klaro cookies by setting the klaro-anonymous cookie
// This just ensures it doesn't get in the way of matching other objects in the page.
cy.setCookie('klaro-anonymous', '{%22authentication%22:true%2C%22preferences%22:true%2C%22acknowledgement%22:true%2C%22google-analytics%22:true}');
Expand Down
30 changes: 18 additions & 12 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,11 @@
"start:dev": "ng config cli.cache.environment local && nodemon --exec \"cross-env NODE_ENV=development yarn run serve\"",
"start:prod": "yarn run build:prod && cross-env NODE_ENV=production yarn run serve:ssr",
"start:mirador:prod": "yarn run build:mirador && yarn run start:prod",
"preserve": "yarn base-href",
"serve": "npm run ng-high-memory -- serve -c development",
"serve:ssr": "node dist/server/main",
"analyze": "webpack-bundle-analyzer dist/browser/stats.json",
"build": "ng build -c development",
"build": "ng build --configuration development",
"build:stats": "ng build --stats-json",
"build:ci": "ng config cli.cache.environment ci && yarn run build:ssr",
"build:prod": "yarn run build:ssr",
Expand All @@ -39,6 +40,8 @@
"cypress:open": "cypress open",
"cypress:run": "cypress run",
"env:yaml": "ts-node --project ./tsconfig.ts-node.json scripts/env-to-yaml.ts",
"base-href": "ts-node --project ./tsconfig.ts-node.json scripts/base-href.ts",
"check-circ-deps": "npx madge --exclude '(bitstream|bundle|collection|config-submission-form|eperson|item|version)\\.model\\.ts$' --circular --extensions ts ./",
"deploy": "pm2 start dist/server/main.js",
"predeploy": "npm run build:prod",
"preundeploy": "pm2 stop dist/server/main.js",
Expand Down Expand Up @@ -77,8 +80,8 @@
"@material-ui/core": "^4.11.0",
"@material-ui/icons": "^4.9.1",
"@ng-bootstrap/ng-bootstrap": "^11.0.0",
"@ng-dynamic-forms/core": "^14.0.1",
"@ng-dynamic-forms/ui-ng-bootstrap": "^14.0.1",
"@ng-dynamic-forms/core": "^15.0.0",
"@ng-dynamic-forms/ui-ng-bootstrap": "^15.0.0",
"@ng-util/markdown": "^12.1.2",
"@ngrx/effects": "^13.0.2",
"@ngrx/router-store": "^13.0.2",
Expand All @@ -88,7 +91,8 @@
"@nicky-lenaers/ngx-scroll-to": "^9.0.0",
"@swimlane/ngx-charts": "^16.0.0",
"angular-idle-preload": "3.0.0",
"angulartics2": "^10.0.0",
"angulartics2": "^12.0.0",
"axios": "^0.27.2",
"bootstrap": "4.3.1",
"caniuse-lite": "^1.0.30001165",
"cerialize": "0.1.18",
Expand Down Expand Up @@ -116,7 +120,7 @@
"mirador": "^3.3.0",
"mirador-dl-plugin": "^0.13.0",
"mirador-share-plugin": "^0.11.0",
"moment": "^2.29.1",
"moment": "^2.29.2",
"morgan": "^1.10.0",
"ng-mocks": "^13.1.1",
"ng2-file-upload": "1.4.0",
Expand All @@ -133,13 +137,14 @@
"prop-types": "^15.7.2",
"react-copy-to-clipboard": "^5.0.1",
"reflect-metadata": "^0.1.13",
"rxjs": "^6.6.3",
"rxjs": "^7.5.5",
"sortablejs": "1.13.0",
"tslib": "^2.0.0",
"url-parse": "^1.5.6",
"uuid": "^8.3.2",
"webfontloader": "1.6.28",
"zone.js": "~0.11.5"
"zone.js": "~0.11.5",
"ngx-ui-switch": "^11.0.1"
},
"devDependencies": {
"@angular-builders/custom-webpack": "~13.1.0",
Expand Down Expand Up @@ -168,14 +173,14 @@
"@typescript-eslint/eslint-plugin": "5.11.0",
"@typescript-eslint/parser": "5.11.0",
"axe-core": "^4.3.3",
"compression-webpack-plugin": "^3.0.1",
"compression-webpack-plugin": "^9.2.0",
"copy-webpack-plugin": "^6.4.1",
"cross-env": "^7.0.3",
"css-loader": "^6.2.0",
"css-minimizer-webpack-plugin": "^3.4.1",
"cssnano": "^5.0.6",
"cypress": "9.5.1",
"cypress-axe": "^0.13.0",
"cypress-axe": "^0.14.0",
"debug-loader": "^0.0.1",
"deep-freeze": "0.0.1",
"dotenv": "^8.2.0",
Expand All @@ -184,10 +189,11 @@
"eslint-plugin-import": "^2.25.4",
"eslint-plugin-jsdoc": "^38.0.6",
"eslint-plugin-unused-imports": "^2.0.0",
"express-static-gzip": "^2.1.5",
"fork-ts-checker-webpack-plugin": "^6.0.3",
"html-loader": "^1.3.2",
"jasmine-core": "^3.8.0",
"jasmine-marbles": "0.6.0",
"jasmine-marbles": "0.9.2",
"jasmine-spec-reporter": "~5.0.0",
"karma": "^6.3.14",
"karma-chrome-launcher": "~3.1.0",
Expand All @@ -196,7 +202,7 @@
"karma-jasmine-html-reporter": "^1.5.0",
"karma-mocha-reporter": "2.2.5",
"ngx-export-as": "~1.13.0",
"ngx-mask": "^12.0.0",
"ngx-mask": "^13.1.7",
"nodemon": "^2.0.15",
"postcss": "^8.1",
"postcss-apply": "0.12.0",
Expand All @@ -210,7 +216,7 @@
"react": "^16.14.0",
"react-dom": "^16.14.0",
"rimraf": "^3.0.2",
"rxjs-spy": "^7.5.3",
"rxjs-spy": "^8.0.2",
"sass": "~1.32.6",
"sass-loader": "^12.6.0",
"sass-resources-loader": "^2.1.1",
Expand Down
36 changes: 36 additions & 0 deletions scripts/base-href.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import * as fs from 'fs';
import { join } from 'path';

import { AppConfig } from '../src/config/app-config.interface';
import { buildAppConfig } from '../src/config/config.server';

/**
* Script to set baseHref as `ui.nameSpace` for development mode. Adds `baseHref` to angular.json build options.
*
* Usage (see package.json):
*
* yarn base-href
*/

const appConfig: AppConfig = buildAppConfig();

const angularJsonPath = join(process.cwd(), 'angular.json');

if (!fs.existsSync(angularJsonPath)) {
console.error(`Error:\n${angularJsonPath} does not exist\n`);
process.exit(1);
}

try {
const angularJson = require(angularJsonPath);

const baseHref = `${appConfig.ui.nameSpace}${appConfig.ui.nameSpace.endsWith('/') ? '' : '/'}`;

console.log(`Setting baseHref to ${baseHref} in angular.json`);

angularJson.projects['dspace-angular'].architect.build.options.baseHref = baseHref;

fs.writeFileSync(angularJsonPath, JSON.stringify(angularJson, null, 2) + '\n');
} catch (e) {
console.error(e);
}
10 changes: 7 additions & 3 deletions scripts/sync-i18n-files.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { projectRoot} from '../webpack/helpers';
import { projectRoot } from '../webpack/helpers';

const commander = require('commander');
const fs = require('fs');
const JSON5 = require('json5');
Expand Down Expand Up @@ -119,7 +120,7 @@ function syncFileWithSource(pathToTargetFile, pathToOutputFile) {
outputChunks.forEach(function (chunk) {
progressBar.increment();
chunk.split("\n").forEach(function (line) {
file.write(" " + line + "\n");
file.write((line === '' ? '' : ` ${line}`) + "\n");
});
});
file.write("\n}");
Expand Down Expand Up @@ -192,7 +193,10 @@ function createNewChunkComparingSourceAndTarget(correspondingTargetChunk, source

const targetList = correspondingTargetChunk.split("\n");
const oldKeyValueInTargetComments = getSubStringWithRegex(correspondingTargetChunk, "\\s*\\/\\/\\s*\".*");
const keyValueTarget = targetList[targetList.length - 1];
let keyValueTarget = targetList[targetList.length - 1];
if (!keyValueTarget.endsWith(",")) {
keyValueTarget = keyValueTarget + ",";
}

if (oldKeyValueInTargetComments != null) {
const oldKeyValueUncommented = getSubStringWithRegex(oldKeyValueInTargetComments[0], "\".*")[0];
Expand Down
Loading

0 comments on commit 5ed56d1

Please sign in to comment.