mirror of
https://github.com/DSpace/dspace-angular.git
synced 2025-10-07 10:04:11 +00:00
Merge remote-tracking branch 'upstream/main' into w2p-97425_System-wide-alerts
This commit is contained in:
@@ -6,7 +6,8 @@
|
|||||||
"eslint-plugin-import",
|
"eslint-plugin-import",
|
||||||
"eslint-plugin-jsdoc",
|
"eslint-plugin-jsdoc",
|
||||||
"eslint-plugin-deprecation",
|
"eslint-plugin-deprecation",
|
||||||
"eslint-plugin-unused-imports"
|
"unused-imports",
|
||||||
|
"eslint-plugin-lodash"
|
||||||
],
|
],
|
||||||
"overrides": [
|
"overrides": [
|
||||||
{
|
{
|
||||||
@@ -202,7 +203,13 @@
|
|||||||
"deprecation/deprecation": "warn",
|
"deprecation/deprecation": "warn",
|
||||||
|
|
||||||
"import/order": "off",
|
"import/order": "off",
|
||||||
"import/no-deprecated": "warn"
|
"import/no-deprecated": "warn",
|
||||||
|
"import/no-namespace": "error",
|
||||||
|
"unused-imports/no-unused-imports": "error",
|
||||||
|
"lodash/import-scope": [
|
||||||
|
"error",
|
||||||
|
"method"
|
||||||
|
]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
12
.github/pull_request_template.md
vendored
12
.github/pull_request_template.md
vendored
@@ -1,7 +1,7 @@
|
|||||||
## References
|
## References
|
||||||
_Add references/links to any related issues or PRs. These may include:_
|
_Add references/links to any related issues or PRs. These may include:_
|
||||||
* Fixes #[issue-number]
|
* Fixes #`issue-number` (if this fixes an issue ticket)
|
||||||
* Requires DSpace/DSpace#[pr-number] (if a REST API PR is required to test this)
|
* Requires DSpace/DSpace#`pr-number` (if a REST API PR is required to test this)
|
||||||
|
|
||||||
## Description
|
## Description
|
||||||
Short summary of changes (1-2 sentences).
|
Short summary of changes (1-2 sentences).
|
||||||
@@ -19,8 +19,10 @@ List of changes in this PR:
|
|||||||
_This checklist provides a reminder of what we are going to look for when reviewing your PR. You need not complete this checklist prior to creating your PR (draft PRs are always welcome). If you are unsure about an item in the checklist, don't hesitate to ask. We're here to help!_
|
_This checklist provides a reminder of what we are going to look for when reviewing your PR. You need not complete this checklist prior to creating your PR (draft PRs are always welcome). If you are unsure about an item in the checklist, don't hesitate to ask. We're here to help!_
|
||||||
|
|
||||||
- [ ] 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 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 passes [ESLint](https://eslint.org/) validation using `yarn lint`
|
||||||
- [ ] My PR doesn't introduce circular dependencies
|
- [ ] My PR doesn't introduce circular dependencies (verified via `yarn check-circ-deps`)
|
||||||
- [ ] 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 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 or tests based on the [Code Testing Guide](https://wiki.lyrasis.org/display/DSPACE/Code+Testing+Guide).
|
- [ ] 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.
|
- [ ] If my PR includes new libraries/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.
|
||||||
|
- [ ] If my PR includes new features or configurations, I've provided basic technical documentation in the PR itself.
|
||||||
|
- [ ] If my PR fixes an issue ticket, I've [linked them together](https://docs.github.com/en/issues/tracking-your-work-with-issues/linking-a-pull-request-to-an-issue).
|
||||||
|
29
.github/workflows/build.yml
vendored
29
.github/workflows/build.yml
vendored
@@ -6,34 +6,39 @@ name: Build
|
|||||||
# Run this Build for all pushes / PRs to current branch
|
# Run this Build for all pushes / PRs to current branch
|
||||||
on: [push, pull_request]
|
on: [push, pull_request]
|
||||||
|
|
||||||
|
permissions:
|
||||||
|
contents: read # to fetch code (actions/checkout)
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
tests:
|
tests:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
env:
|
env:
|
||||||
# The ci step will test the dspace-angular code against DSpace REST.
|
# The ci step will test the dspace-angular code against DSpace REST.
|
||||||
# Direct that step to utilize a DSpace REST service that has been started in docker.
|
# Direct that step to utilize a DSpace REST service that has been started in docker.
|
||||||
DSPACE_REST_HOST: localhost
|
DSPACE_REST_HOST: 127.0.0.1
|
||||||
DSPACE_REST_PORT: 8080
|
DSPACE_REST_PORT: 8080
|
||||||
DSPACE_REST_NAMESPACE: '/server'
|
DSPACE_REST_NAMESPACE: '/server'
|
||||||
DSPACE_REST_SSL: false
|
DSPACE_REST_SSL: false
|
||||||
|
# Spin up UI on 127.0.0.1 to avoid host resolution issues in e2e tests with Node 18+
|
||||||
|
DSPACE_UI_HOST: 127.0.0.1
|
||||||
# When Chrome version is specified, we pin to a specific version of Chrome
|
# When Chrome version is specified, we pin to a specific version of Chrome
|
||||||
# Comment this out to use the latest release
|
# Comment this out to use the latest release
|
||||||
#CHROME_VERSION: "90.0.4430.212-1"
|
#CHROME_VERSION: "90.0.4430.212-1"
|
||||||
strategy:
|
strategy:
|
||||||
# Create a matrix of Node versions to test against (in parallel)
|
# Create a matrix of Node versions to test against (in parallel)
|
||||||
matrix:
|
matrix:
|
||||||
node-version: [14.x, 16.x]
|
node-version: [16.x, 18.x]
|
||||||
# Do NOT exit immediately if one matrix job fails
|
# Do NOT exit immediately if one matrix job fails
|
||||||
fail-fast: false
|
fail-fast: false
|
||||||
# These are the actual CI steps to perform per job
|
# These are the actual CI steps to perform per job
|
||||||
steps:
|
steps:
|
||||||
# https://github.com/actions/checkout
|
# https://github.com/actions/checkout
|
||||||
- name: Checkout codebase
|
- name: Checkout codebase
|
||||||
uses: actions/checkout@v2
|
uses: actions/checkout@v3
|
||||||
|
|
||||||
# https://github.com/actions/setup-node
|
# https://github.com/actions/setup-node
|
||||||
- name: Install Node.js ${{ matrix.node-version }}
|
- name: Install Node.js ${{ matrix.node-version }}
|
||||||
uses: actions/setup-node@v2
|
uses: actions/setup-node@v3
|
||||||
with:
|
with:
|
||||||
node-version: ${{ matrix.node-version }}
|
node-version: ${{ matrix.node-version }}
|
||||||
|
|
||||||
@@ -58,7 +63,7 @@ jobs:
|
|||||||
id: yarn-cache-dir-path
|
id: yarn-cache-dir-path
|
||||||
run: echo "::set-output name=dir::$(yarn cache dir)"
|
run: echo "::set-output name=dir::$(yarn cache dir)"
|
||||||
- name: Cache Yarn dependencies
|
- name: Cache Yarn dependencies
|
||||||
uses: actions/cache@v2
|
uses: actions/cache@v3
|
||||||
with:
|
with:
|
||||||
# Cache entire Yarn cache directory (see previous step)
|
# Cache entire Yarn cache directory (see previous step)
|
||||||
path: ${{ steps.yarn-cache-dir-path.outputs.dir }}
|
path: ${{ steps.yarn-cache-dir-path.outputs.dir }}
|
||||||
@@ -85,7 +90,7 @@ jobs:
|
|||||||
# Upload coverage reports to Codecov (for one version of Node only)
|
# Upload coverage reports to Codecov (for one version of Node only)
|
||||||
# https://github.com/codecov/codecov-action
|
# https://github.com/codecov/codecov-action
|
||||||
- name: Upload coverage to Codecov.io
|
- name: Upload coverage to Codecov.io
|
||||||
uses: codecov/codecov-action@v2
|
uses: codecov/codecov-action@v3
|
||||||
if: matrix.node-version == '16.x'
|
if: matrix.node-version == '16.x'
|
||||||
|
|
||||||
# Using docker-compose start backend using CI configuration
|
# Using docker-compose start backend using CI configuration
|
||||||
@@ -100,7 +105,7 @@ jobs:
|
|||||||
# https://github.com/cypress-io/github-action
|
# https://github.com/cypress-io/github-action
|
||||||
# (NOTE: to run these e2e tests locally, just use 'ng e2e')
|
# (NOTE: to run these e2e tests locally, just use 'ng e2e')
|
||||||
- name: Run e2e tests (integration tests)
|
- name: Run e2e tests (integration tests)
|
||||||
uses: cypress-io/github-action@v2
|
uses: cypress-io/github-action@v4
|
||||||
with:
|
with:
|
||||||
# Run tests in Chrome, headless mode
|
# Run tests in Chrome, headless mode
|
||||||
browser: chrome
|
browser: chrome
|
||||||
@@ -109,14 +114,14 @@ jobs:
|
|||||||
start: yarn run serve:ssr
|
start: yarn run serve:ssr
|
||||||
# Wait for backend & frontend to be available
|
# Wait for backend & frontend to be available
|
||||||
# NOTE: We use the 'sites' REST endpoint to also ensure the database is ready
|
# NOTE: We use the 'sites' REST endpoint to also ensure the database is ready
|
||||||
wait-on: http://localhost:8080/server/api/core/sites, http://localhost:4000
|
wait-on: http://127.0.0.1:8080/server/api/core/sites, http://127.0.0.1:4000
|
||||||
# Wait for 2 mins max for everything to respond
|
# Wait for 2 mins max for everything to respond
|
||||||
wait-on-timeout: 120
|
wait-on-timeout: 120
|
||||||
|
|
||||||
# Cypress always creates a video of all e2e tests (whether they succeeded or failed)
|
# Cypress always creates a video of all e2e tests (whether they succeeded or failed)
|
||||||
# Save those in an Artifact
|
# Save those in an Artifact
|
||||||
- name: Upload e2e test videos to Artifacts
|
- name: Upload e2e test videos to Artifacts
|
||||||
uses: actions/upload-artifact@v2
|
uses: actions/upload-artifact@v3
|
||||||
if: always()
|
if: always()
|
||||||
with:
|
with:
|
||||||
name: e2e-test-videos
|
name: e2e-test-videos
|
||||||
@@ -125,7 +130,7 @@ jobs:
|
|||||||
# If e2e tests fail, Cypress creates a screenshot of what happened
|
# If e2e tests fail, Cypress creates a screenshot of what happened
|
||||||
# Save those in an Artifact
|
# Save those in an Artifact
|
||||||
- name: Upload e2e test failure screenshots to Artifacts
|
- name: Upload e2e test failure screenshots to Artifacts
|
||||||
uses: actions/upload-artifact@v2
|
uses: actions/upload-artifact@v3
|
||||||
if: failure()
|
if: failure()
|
||||||
with:
|
with:
|
||||||
name: e2e-test-screenshots
|
name: e2e-test-screenshots
|
||||||
@@ -144,7 +149,7 @@ jobs:
|
|||||||
run: |
|
run: |
|
||||||
nohup yarn run serve:ssr &
|
nohup yarn run serve:ssr &
|
||||||
printf 'Waiting for app to start'
|
printf 'Waiting for app to start'
|
||||||
until curl --output /dev/null --silent --head --fail http://localhost:4000/home; do
|
until curl --output /dev/null --silent --head --fail http://127.0.0.1:4000/home; do
|
||||||
printf '.'
|
printf '.'
|
||||||
sleep 2
|
sleep 2
|
||||||
done
|
done
|
||||||
@@ -155,7 +160,7 @@ jobs:
|
|||||||
# This step also prints entire HTML of homepage for easier debugging if grep fails.
|
# This step also prints entire HTML of homepage for easier debugging if grep fails.
|
||||||
- name: Verify SSR (server-side rendering)
|
- name: Verify SSR (server-side rendering)
|
||||||
run: |
|
run: |
|
||||||
result=$(wget -O- -q http://localhost:4000/home)
|
result=$(wget -O- -q http://127.0.0.1:4000/home)
|
||||||
echo "$result"
|
echo "$result"
|
||||||
echo "$result" | grep -oE "<meta name=\"title\" [^>]*>" | grep DSpace
|
echo "$result" | grep -oE "<meta name=\"title\" [^>]*>" | grep DSpace
|
||||||
|
|
||||||
|
49
.github/workflows/codescan.yml
vendored
Normal file
49
.github/workflows/codescan.yml
vendored
Normal file
@@ -0,0 +1,49 @@
|
|||||||
|
# DSpace CodeQL code scanning configuration for GitHub
|
||||||
|
# https://docs.github.com/en/code-security/code-scanning
|
||||||
|
#
|
||||||
|
# NOTE: Code scanning must be run separate from our default build.yml
|
||||||
|
# because CodeQL requires a fresh build with all tests *disabled*.
|
||||||
|
name: "Code Scanning"
|
||||||
|
|
||||||
|
# Run this code scan for all pushes / PRs to main branch. Also run once a week.
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches: [ main ]
|
||||||
|
pull_request:
|
||||||
|
branches: [ main ]
|
||||||
|
# Don't run if PR is only updating static documentation
|
||||||
|
paths-ignore:
|
||||||
|
- '**/*.md'
|
||||||
|
- '**/*.txt'
|
||||||
|
schedule:
|
||||||
|
- cron: "37 0 * * 1"
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
analyze:
|
||||||
|
name: Analyze Code
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
# Limit permissions of this GitHub action. Can only write to security-events
|
||||||
|
permissions:
|
||||||
|
actions: read
|
||||||
|
contents: read
|
||||||
|
security-events: write
|
||||||
|
|
||||||
|
steps:
|
||||||
|
# https://github.com/actions/checkout
|
||||||
|
- name: Checkout repository
|
||||||
|
uses: actions/checkout@v3
|
||||||
|
|
||||||
|
# Initializes the CodeQL tools for scanning.
|
||||||
|
# https://github.com/github/codeql-action
|
||||||
|
- name: Initialize CodeQL
|
||||||
|
uses: github/codeql-action/init@v2
|
||||||
|
with:
|
||||||
|
languages: javascript
|
||||||
|
|
||||||
|
# Autobuild attempts to build any compiled languages
|
||||||
|
- name: Autobuild
|
||||||
|
uses: github/codeql-action/autobuild@v2
|
||||||
|
|
||||||
|
# Perform GitHub Code Scanning.
|
||||||
|
- name: Perform CodeQL Analysis
|
||||||
|
uses: github/codeql-action/analyze@v2
|
13
.github/workflows/docker.yml
vendored
13
.github/workflows/docker.yml
vendored
@@ -12,6 +12,9 @@ on:
|
|||||||
- 'dspace-**'
|
- 'dspace-**'
|
||||||
pull_request:
|
pull_request:
|
||||||
|
|
||||||
|
permissions:
|
||||||
|
contents: read # to fetch code (actions/checkout)
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
docker:
|
docker:
|
||||||
# Ensure this job never runs on forked repos. It's only executed for 'dspace/dspace-angular'
|
# Ensure this job never runs on forked repos. It's only executed for 'dspace/dspace-angular'
|
||||||
@@ -39,11 +42,11 @@ jobs:
|
|||||||
steps:
|
steps:
|
||||||
# https://github.com/actions/checkout
|
# https://github.com/actions/checkout
|
||||||
- name: Checkout codebase
|
- name: Checkout codebase
|
||||||
uses: actions/checkout@v2
|
uses: actions/checkout@v3
|
||||||
|
|
||||||
# https://github.com/docker/setup-buildx-action
|
# https://github.com/docker/setup-buildx-action
|
||||||
- name: Setup Docker Buildx
|
- name: Setup Docker Buildx
|
||||||
uses: docker/setup-buildx-action@v1
|
uses: docker/setup-buildx-action@v2
|
||||||
|
|
||||||
# https://github.com/docker/setup-qemu-action
|
# https://github.com/docker/setup-qemu-action
|
||||||
- name: Set up QEMU emulation to build for multiple architectures
|
- name: Set up QEMU emulation to build for multiple architectures
|
||||||
@@ -53,7 +56,7 @@ jobs:
|
|||||||
- name: Login to DockerHub
|
- name: Login to DockerHub
|
||||||
# Only login if not a PR, as PRs only trigger a Docker build and not a push
|
# Only login if not a PR, as PRs only trigger a Docker build and not a push
|
||||||
if: github.event_name != 'pull_request'
|
if: github.event_name != 'pull_request'
|
||||||
uses: docker/login-action@v1
|
uses: docker/login-action@v2
|
||||||
with:
|
with:
|
||||||
username: ${{ secrets.DOCKER_USERNAME }}
|
username: ${{ secrets.DOCKER_USERNAME }}
|
||||||
password: ${{ secrets.DOCKER_ACCESS_TOKEN }}
|
password: ${{ secrets.DOCKER_ACCESS_TOKEN }}
|
||||||
@@ -65,7 +68,7 @@ jobs:
|
|||||||
# Get Metadata for docker_build step below
|
# Get Metadata for docker_build step below
|
||||||
- name: Sync metadata (tags, labels) from GitHub to Docker for 'dspace-angular' image
|
- name: Sync metadata (tags, labels) from GitHub to Docker for 'dspace-angular' image
|
||||||
id: meta_build
|
id: meta_build
|
||||||
uses: docker/metadata-action@v3
|
uses: docker/metadata-action@v4
|
||||||
with:
|
with:
|
||||||
images: dspace/dspace-angular
|
images: dspace/dspace-angular
|
||||||
tags: ${{ env.IMAGE_TAGS }}
|
tags: ${{ env.IMAGE_TAGS }}
|
||||||
@@ -74,7 +77,7 @@ jobs:
|
|||||||
# https://github.com/docker/build-push-action
|
# https://github.com/docker/build-push-action
|
||||||
- name: Build and push 'dspace-angular' image
|
- name: Build and push 'dspace-angular' image
|
||||||
id: docker_build
|
id: docker_build
|
||||||
uses: docker/build-push-action@v2
|
uses: docker/build-push-action@v3
|
||||||
with:
|
with:
|
||||||
context: .
|
context: .
|
||||||
file: ./Dockerfile
|
file: ./Dockerfile
|
||||||
|
17
.github/workflows/issue_opened.yml
vendored
17
.github/workflows/issue_opened.yml
vendored
@@ -5,25 +5,22 @@ on:
|
|||||||
issues:
|
issues:
|
||||||
types: [opened]
|
types: [opened]
|
||||||
|
|
||||||
|
permissions: {}
|
||||||
jobs:
|
jobs:
|
||||||
automation:
|
automation:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
# Add the new issue to a project board, if it needs triage
|
# Add the new issue to a project board, if it needs triage
|
||||||
# See https://github.com/marketplace/actions/create-project-card-action
|
# See https://github.com/actions/add-to-project
|
||||||
- name: Add issue to project board
|
- name: Add issue to triage board
|
||||||
# Only add to project board if issue is flagged as "needs triage" or has no labels
|
# Only add to project board if issue is flagged as "needs triage" or has no labels
|
||||||
# NOTE: By default we flag new issues as "needs triage" in our issue template
|
# NOTE: By default we flag new issues as "needs triage" in our issue template
|
||||||
if: (contains(github.event.issue.labels.*.name, 'needs triage') || join(github.event.issue.labels.*.name) == '')
|
if: (contains(github.event.issue.labels.*.name, 'needs triage') || join(github.event.issue.labels.*.name) == '')
|
||||||
uses: technote-space/create-project-card-action@v1
|
uses: actions/add-to-project@v0.3.0
|
||||||
# Note, the authentication token below is an ORG level Secret.
|
# Note, the authentication token below is an ORG level Secret.
|
||||||
# It must be created/recreated manually via a personal access token with "public_repo" and "admin:org" permissions
|
# It must be created/recreated manually via a personal access token with admin:org, project, public_repo permissions
|
||||||
# See: https://docs.github.com/en/actions/configuring-and-managing-workflows/authenticating-with-the-github_token#permissions-for-the-github_token
|
# See: https://docs.github.com/en/actions/configuring-and-managing-workflows/authenticating-with-the-github_token#permissions-for-the-github_token
|
||||||
# This is necessary because the "DSpace Backlog" project is an org level project (i.e. not repo specific)
|
# This is necessary because the "DSpace Backlog" project is an org level project (i.e. not repo specific)
|
||||||
with:
|
with:
|
||||||
GITHUB_TOKEN: ${{ secrets.ORG_PROJECT_TOKEN }}
|
github-token: ${{ secrets.TRIAGE_PROJECT_TOKEN }}
|
||||||
PROJECT: DSpace Backlog
|
project-url: https://github.com/orgs/DSpace/projects/24
|
||||||
COLUMN: Triage
|
|
||||||
CHECK_ORG_PROJECT: true
|
|
||||||
# Ignore errors
|
|
||||||
continue-on-error: true
|
|
||||||
|
27
.github/workflows/label_merge_conflicts.yml
vendored
27
.github/workflows/label_merge_conflicts.yml
vendored
@@ -5,21 +5,32 @@ name: Check for merge conflicts
|
|||||||
# NOTE: This means merge conflicts are only checked for when a PR is merged to main.
|
# NOTE: This means merge conflicts are only checked for when a PR is merged to main.
|
||||||
on:
|
on:
|
||||||
push:
|
push:
|
||||||
branches:
|
branches: [ main ]
|
||||||
- main
|
# So that the `conflict_label_name` is removed if conflicts are resolved,
|
||||||
|
# we allow this to run for `pull_request_target` so that github secrets are available.
|
||||||
|
pull_request_target:
|
||||||
|
types: [ synchronize ]
|
||||||
|
|
||||||
|
permissions: {}
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
triage:
|
triage:
|
||||||
|
# Ensure this job never runs on forked repos. It's only executed for 'dspace/dspace-angular'
|
||||||
|
if: github.repository == 'dspace/dspace-angular'
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
|
permissions:
|
||||||
|
pull-requests: write
|
||||||
steps:
|
steps:
|
||||||
# See: https://github.com/mschilde/auto-label-merge-conflicts/
|
# See: https://github.com/prince-chrismc/label-merge-conflicts-action
|
||||||
- name: Auto-label PRs with merge conflicts
|
- name: Auto-label PRs with merge conflicts
|
||||||
uses: mschilde/auto-label-merge-conflicts@v2.0
|
uses: prince-chrismc/label-merge-conflicts-action@v2
|
||||||
# Add "merge conflict" label if a merge conflict is detected. Remove it when resolved.
|
# Add "merge conflict" label if a merge conflict is detected. Remove it when resolved.
|
||||||
# Note, the authentication token is created automatically
|
# Note, the authentication token is created automatically
|
||||||
# See: https://docs.github.com/en/actions/configuring-and-managing-workflows/authenticating-with-the-github_token
|
# See: https://docs.github.com/en/actions/configuring-and-managing-workflows/authenticating-with-the-github_token
|
||||||
with:
|
with:
|
||||||
CONFLICT_LABEL_NAME: 'merge conflict'
|
conflict_label_name: 'merge conflict'
|
||||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
github_token: ${{ secrets.GITHUB_TOKEN }}
|
||||||
# Ignore errors
|
conflict_comment: |
|
||||||
continue-on-error: true
|
Hi @${author},
|
||||||
|
Conflicts have been detected against the base branch.
|
||||||
|
Please [resolve these conflicts](https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/addressing-merge-conflicts/about-merge-conflicts) as soon as you can. Thanks!
|
46
CONTRIBUTING.md
Normal file
46
CONTRIBUTING.md
Normal file
@@ -0,0 +1,46 @@
|
|||||||
|
# How to Contribute
|
||||||
|
|
||||||
|
DSpace is a community built and supported project. We do not have a centralized development or support team, but have a dedicated group of volunteers who help us improve the software, documentation, resources, etc.
|
||||||
|
|
||||||
|
* [Contribute new code via a Pull Request](#contribute-new-code-via-a-pull-request)
|
||||||
|
* [Contribute documentation](#contribute-documentation)
|
||||||
|
* [Help others on mailing lists or Slack](#help-others-on-mailing-lists-or-slack)
|
||||||
|
* [Join a working or interest group](#join-a-working-or-interest-group)
|
||||||
|
|
||||||
|
## Contribute new code via a Pull Request
|
||||||
|
|
||||||
|
We accept [GitHub Pull Requests (PRs)](https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/proposing-changes-to-your-work-with-pull-requests/creating-a-pull-request-from-a-fork) at any time from anyone.
|
||||||
|
Contributors to each release are recognized in our [Release Notes](https://wiki.lyrasis.org/display/DSDOC7x/Release+Notes).
|
||||||
|
|
||||||
|
Code Contribution Checklist
|
||||||
|
- [ ] PRs _should_ be smaller in size (ideally less than 1,000 lines of code, not including comments & tests)
|
||||||
|
- [ ] PRs **must** pass [ESLint](https://eslint.org/) validation using `yarn lint`
|
||||||
|
- [ ] PRs **must** not introduce circular dependencies (verified via `yarn check-circ-deps`)
|
||||||
|
- [ ] PRs **must** include [TypeDoc](https://typedoc.org/) comments for _all new (or modified) public methods and classes_. Large or complex private methods should also have TypeDoc.
|
||||||
|
- [ ] PRs **must** pass all automated pecs/tests and includes new/updated specs or tests based on the [Code Testing Guide](https://wiki.lyrasis.org/display/DSPACE/Code+Testing+Guide).
|
||||||
|
- [ ] If a PR includes new libraries/dependencies (in `package.json`), then their software licenses **must** align with the [DSpace BSD License](https://github.com/DSpace/dspace-angular/blob/main/LICENSE) based on the [Licensing of Contributions](https://wiki.lyrasis.org/display/DSPACE/Code+Contribution+Guidelines#CodeContributionGuidelines-LicensingofContributions) documentation.
|
||||||
|
- [ ] Basic technical documentation _should_ be provided for any new features or configuration, either in the PR itself or in the DSpace Wiki documentation.
|
||||||
|
- [ ] If a PR fixes an issue ticket, please [link them together](https://docs.github.com/en/issues/tracking-your-work-with-issues/linking-a-pull-request-to-an-issue).
|
||||||
|
|
||||||
|
Additional details on the code contribution process can be found in our [Code Contribution Guidelines](https://wiki.lyrasis.org/display/DSPACE/Code+Contribution+Guidelines)
|
||||||
|
|
||||||
|
## Contribute documentation
|
||||||
|
|
||||||
|
DSpace Documentation is a collaborative effort in a shared Wiki. The latest documentation is at https://wiki.lyrasis.org/display/DSDOC7x
|
||||||
|
|
||||||
|
If you find areas of the DSpace Documentation which you wish to improve, please request a Wiki account by emailing wikihelp@lyrasis.org.
|
||||||
|
Once you have an account setup, contact @tdonohue (via [Slack](https://wiki.lyrasis.org/display/DSPACE/Slack) or email) for access to edit our Documentation.
|
||||||
|
|
||||||
|
## Help others on mailing lists or Slack
|
||||||
|
|
||||||
|
DSpace has our own [Slack](https://wiki.lyrasis.org/display/DSPACE/Slack) community and [Mailing Lists](https://wiki.lyrasis.org/display/DSPACE/Mailing+Lists) where discussions take place and questions are answered.
|
||||||
|
Anyone is welcome to join and help others. We just ask you to follow our [Code of Conduct](https://www.lyrasis.org/about/Pages/Code-of-Conduct.aspx) (adopted via LYRASIS).
|
||||||
|
|
||||||
|
## Join a working or interest group
|
||||||
|
|
||||||
|
Most of the work in building/improving DSpace comes via [Working Groups](https://wiki.lyrasis.org/display/DSPACE/DSpace+Working+Groups) or [Interest Groups](https://wiki.lyrasis.org/display/DSPACE/DSpace+Interest+Groups).
|
||||||
|
|
||||||
|
All working/interest groups are open to anyone to join and participate. A few key groups to be aware of include:
|
||||||
|
|
||||||
|
* [DSpace 7 Working Group](https://wiki.lyrasis.org/display/DSPACE/DSpace+7+Working+Group) - This is the main (mostly volunteer) development team. We meet weekly to review our current development [project board](https://github.com/orgs/DSpace/projects), assigning tickets and/or PRs.
|
||||||
|
* [DSpace Community Advisory Team (DCAT)](https://wiki.lyrasis.org/display/cmtygp/DSpace+Community+Advisory+Team) - This is an interest group for repository managers/administrators. We meet monthly to discuss DSpace, share tips & provide feedback back to developers.
|
@@ -1,11 +1,15 @@
|
|||||||
# This image will be published as dspace/dspace-angular
|
# This image will be published as dspace/dspace-angular
|
||||||
# See https://github.com/DSpace/dspace-angular/tree/main/docker for usage details
|
# See https://github.com/DSpace/dspace-angular/tree/main/docker for usage details
|
||||||
|
|
||||||
FROM node:14-alpine
|
FROM node:18-alpine
|
||||||
WORKDIR /app
|
WORKDIR /app
|
||||||
ADD . /app/
|
ADD . /app/
|
||||||
EXPOSE 4000
|
EXPOSE 4000
|
||||||
|
|
||||||
|
# Ensure Python and other build tools are available
|
||||||
|
# These are needed to install some node modules, especially on linux/arm64
|
||||||
|
RUN apk add --update python3 make g++ && rm -rf /var/cache/apk/*
|
||||||
|
|
||||||
# We run yarn install with an increased network timeout (5min) to avoid "ESOCKETTIMEDOUT" errors from hub.docker.com
|
# We run yarn install with an increased network timeout (5min) to avoid "ESOCKETTIMEDOUT" errors from hub.docker.com
|
||||||
# See, for example https://github.com/yarnpkg/yarn/issues/5540
|
# See, for example https://github.com/yarnpkg/yarn/issues/5540
|
||||||
RUN yarn install --network-timeout 300000
|
RUN yarn install --network-timeout 300000
|
||||||
|
10
README.md
10
README.md
@@ -35,7 +35,7 @@ https://wiki.lyrasis.org/display/DSDOC7x/Installing+DSpace
|
|||||||
Quick start
|
Quick start
|
||||||
-----------
|
-----------
|
||||||
|
|
||||||
**Ensure you're running [Node](https://nodejs.org) `v14.x` or `v16.x`, [npm](https://www.npmjs.com/) >= `v5.x` and [yarn](https://yarnpkg.com) == `v1.x`**
|
**Ensure you're running [Node](https://nodejs.org) `v16.x` or `v18.x`, [npm](https://www.npmjs.com/) >= `v5.x` and [yarn](https://yarnpkg.com) == `v1.x`**
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
# clone the repo
|
# clone the repo
|
||||||
@@ -90,7 +90,7 @@ Requirements
|
|||||||
------------
|
------------
|
||||||
|
|
||||||
- [Node.js](https://nodejs.org) and [yarn](https://yarnpkg.com)
|
- [Node.js](https://nodejs.org) and [yarn](https://yarnpkg.com)
|
||||||
- Ensure you're running node `v14.x` or `v16.x` and yarn == `v1.x`
|
- Ensure you're running node `v16.x` or `v18.x` and yarn == `v1.x`
|
||||||
|
|
||||||
If you have [`nvm`](https://github.com/creationix/nvm#install-script) or [`nvm-windows`](https://github.com/coreybutler/nvm-windows) installed, which is highly recommended, you can run `nvm install --lts && nvm use` to install and start using the latest Node LTS.
|
If you have [`nvm`](https://github.com/creationix/nvm#install-script) or [`nvm-windows`](https://github.com/coreybutler/nvm-windows) installed, which is highly recommended, you can run `nvm install --lts && nvm use` to install and start using the latest Node LTS.
|
||||||
|
|
||||||
@@ -351,7 +351,7 @@ Documentation
|
|||||||
|
|
||||||
Official DSpace documentation is available in the DSpace wiki at https://wiki.lyrasis.org/display/DSDOC7x/
|
Official DSpace documentation is available in the DSpace wiki at https://wiki.lyrasis.org/display/DSDOC7x/
|
||||||
|
|
||||||
Some UI specific configuration documentation is also found in the [`./docs`](docs) folder of htis codebase.
|
Some UI specific configuration documentation is also found in the [`./docs`](docs) folder of this codebase.
|
||||||
|
|
||||||
### Building code documentation
|
### Building code documentation
|
||||||
|
|
||||||
@@ -379,10 +379,10 @@ To get the most out of TypeScript, you'll need a TypeScript-aware editor. We've
|
|||||||
- [Sublime Text](http://www.sublimetext.com/3)
|
- [Sublime Text](http://www.sublimetext.com/3)
|
||||||
- [Typescript-Sublime-Plugin](https://github.com/Microsoft/Typescript-Sublime-plugin#installation)
|
- [Typescript-Sublime-Plugin](https://github.com/Microsoft/Typescript-Sublime-plugin#installation)
|
||||||
|
|
||||||
Collaborating
|
Contributing
|
||||||
-------------
|
-------------
|
||||||
|
|
||||||
See [the guide on the wiki](https://wiki.lyrasis.org/display/DSPACE/DSpace+7+-+Angular+UI+Development#DSpace7-AngularUIDevelopment-Howtocontribute)
|
See [Contributing documentation](CONTRIBUTING.md)
|
||||||
|
|
||||||
File Structure
|
File Structure
|
||||||
--------------
|
--------------
|
||||||
|
@@ -25,12 +25,10 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"allowedCommonJsDependencies": [
|
"allowedCommonJsDependencies": [
|
||||||
"angular2-text-mask",
|
|
||||||
"cerialize",
|
"cerialize",
|
||||||
"core-js",
|
"core-js",
|
||||||
"lodash",
|
"lodash",
|
||||||
"jwt-decode",
|
"jwt-decode",
|
||||||
"url-parse",
|
|
||||||
"uuid",
|
"uuid",
|
||||||
"webfontloader",
|
"webfontloader",
|
||||||
"zone.js"
|
"zone.js"
|
||||||
|
@@ -55,6 +55,8 @@ auth:
|
|||||||
|
|
||||||
# Form settings
|
# Form settings
|
||||||
form:
|
form:
|
||||||
|
# Sets the spellcheck textarea attribute value
|
||||||
|
spellCheck: true
|
||||||
# NOTE: Map server-side validators to comparative Angular form validators
|
# NOTE: Map server-side validators to comparative Angular form validators
|
||||||
validatorMap:
|
validatorMap:
|
||||||
required: required
|
required: required
|
||||||
@@ -143,6 +145,9 @@ languages:
|
|||||||
- code: nl
|
- code: nl
|
||||||
label: Nederlands
|
label: Nederlands
|
||||||
active: true
|
active: true
|
||||||
|
- code: pl
|
||||||
|
label: Polski
|
||||||
|
active: true
|
||||||
- code: pt-PT
|
- code: pt-PT
|
||||||
label: Português
|
label: Português
|
||||||
active: true
|
active: true
|
||||||
@@ -170,6 +175,10 @@ languages:
|
|||||||
- code: el
|
- code: el
|
||||||
label: Ελληνικά
|
label: Ελληνικά
|
||||||
active: true
|
active: true
|
||||||
|
- code: uk
|
||||||
|
label: Yкраї́нська
|
||||||
|
active: true
|
||||||
|
|
||||||
|
|
||||||
# Browse-By Pages
|
# Browse-By Pages
|
||||||
browseBy:
|
browseBy:
|
||||||
@@ -207,6 +216,11 @@ item:
|
|||||||
undoTimeout: 10000 # 10 seconds
|
undoTimeout: 10000 # 10 seconds
|
||||||
# Show the item access status label in items lists
|
# Show the item access status label in items lists
|
||||||
showAccessStatuses: false
|
showAccessStatuses: false
|
||||||
|
bitstream:
|
||||||
|
# Number of entries in the bitstream list in the item view page.
|
||||||
|
# Rounded to the nearest size in the list of selectable sizes on the
|
||||||
|
# settings menu. See pageSizeOptions in 'pagination-component-options.model.ts'.
|
||||||
|
pageSize: 5
|
||||||
|
|
||||||
# Collection Page Config
|
# Collection Page Config
|
||||||
collection:
|
collection:
|
||||||
|
@@ -5,7 +5,7 @@
|
|||||||
"screenshotsFolder": "cypress/screenshots",
|
"screenshotsFolder": "cypress/screenshots",
|
||||||
"pluginsFile": "cypress/plugins/index.ts",
|
"pluginsFile": "cypress/plugins/index.ts",
|
||||||
"fixturesFolder": "cypress/fixtures",
|
"fixturesFolder": "cypress/fixtures",
|
||||||
"baseUrl": "http://localhost:4000",
|
"baseUrl": "http://127.0.0.1:4000",
|
||||||
"retries": {
|
"retries": {
|
||||||
"runMode": 2,
|
"runMode": 2,
|
||||||
"openMode": 0
|
"openMode": 0
|
||||||
|
@@ -4,10 +4,11 @@ import { testA11y } from 'cypress/support/utils';
|
|||||||
|
|
||||||
describe('My DSpace page', () => {
|
describe('My DSpace page', () => {
|
||||||
it('should display recent submissions and pass accessibility tests', () => {
|
it('should display recent submissions and pass accessibility tests', () => {
|
||||||
cy.login(TEST_SUBMIT_USER, TEST_SUBMIT_USER_PASSWORD);
|
|
||||||
|
|
||||||
cy.visit('/mydspace');
|
cy.visit('/mydspace');
|
||||||
|
|
||||||
|
// This page is restricted, so we will be shown the login form. Fill it out & submit.
|
||||||
|
cy.loginViaForm(TEST_SUBMIT_USER, TEST_SUBMIT_USER_PASSWORD);
|
||||||
|
|
||||||
cy.get('ds-my-dspace-page').should('exist');
|
cy.get('ds-my-dspace-page').should('exist');
|
||||||
|
|
||||||
// At least one recent submission should be displayed
|
// At least one recent submission should be displayed
|
||||||
@@ -36,10 +37,11 @@ describe('My DSpace page', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('should have a working detailed view that passes accessibility tests', () => {
|
it('should have a working detailed view that passes accessibility tests', () => {
|
||||||
cy.login(TEST_SUBMIT_USER, TEST_SUBMIT_USER_PASSWORD);
|
|
||||||
|
|
||||||
cy.visit('/mydspace');
|
cy.visit('/mydspace');
|
||||||
|
|
||||||
|
// This page is restricted, so we will be shown the login form. Fill it out & submit.
|
||||||
|
cy.loginViaForm(TEST_SUBMIT_USER, TEST_SUBMIT_USER_PASSWORD);
|
||||||
|
|
||||||
cy.get('ds-my-dspace-page').should('exist');
|
cy.get('ds-my-dspace-page').should('exist');
|
||||||
|
|
||||||
// Click button in sidebar to display detailed view
|
// Click button in sidebar to display detailed view
|
||||||
@@ -61,9 +63,11 @@ describe('My DSpace page', () => {
|
|||||||
|
|
||||||
// NOTE: Deleting existing submissions is exercised by submission.spec.ts
|
// NOTE: Deleting existing submissions is exercised by submission.spec.ts
|
||||||
it('should let you start a new submission & edit in-progress submissions', () => {
|
it('should let you start a new submission & edit in-progress submissions', () => {
|
||||||
cy.login(TEST_SUBMIT_USER, TEST_SUBMIT_USER_PASSWORD);
|
|
||||||
cy.visit('/mydspace');
|
cy.visit('/mydspace');
|
||||||
|
|
||||||
|
// This page is restricted, so we will be shown the login form. Fill it out & submit.
|
||||||
|
cy.loginViaForm(TEST_SUBMIT_USER, TEST_SUBMIT_USER_PASSWORD);
|
||||||
|
|
||||||
// Open the New Submission dropdown
|
// Open the New Submission dropdown
|
||||||
cy.get('button[data-test="submission-dropdown"]').click();
|
cy.get('button[data-test="submission-dropdown"]').click();
|
||||||
// Click on the "Item" type in that dropdown
|
// Click on the "Item" type in that dropdown
|
||||||
@@ -131,9 +135,11 @@ describe('My DSpace page', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('should let you import from external sources', () => {
|
it('should let you import from external sources', () => {
|
||||||
cy.login(TEST_SUBMIT_USER, TEST_SUBMIT_USER_PASSWORD);
|
|
||||||
cy.visit('/mydspace');
|
cy.visit('/mydspace');
|
||||||
|
|
||||||
|
// This page is restricted, so we will be shown the login form. Fill it out & submit.
|
||||||
|
cy.loginViaForm(TEST_SUBMIT_USER, TEST_SUBMIT_USER_PASSWORD);
|
||||||
|
|
||||||
// Open the New Import dropdown
|
// Open the New Import dropdown
|
||||||
cy.get('button[data-test="import-dropdown"]').click();
|
cy.get('button[data-test="import-dropdown"]').click();
|
||||||
// Click on the "Item" type in that dropdown
|
// Click on the "Item" type in that dropdown
|
||||||
|
@@ -6,11 +6,12 @@ describe('New Submission page', () => {
|
|||||||
// NOTE: We already test that new submissions can be started from MyDSpace in my-dspace.spec.ts
|
// NOTE: We already test that new submissions can be started from MyDSpace in my-dspace.spec.ts
|
||||||
|
|
||||||
it('should create a new submission when using /submit path & pass accessibility', () => {
|
it('should create a new submission when using /submit path & pass accessibility', () => {
|
||||||
cy.login(TEST_SUBMIT_USER, TEST_SUBMIT_USER_PASSWORD);
|
|
||||||
|
|
||||||
// Test that calling /submit with collection & entityType will create a new submission
|
// Test that calling /submit with collection & entityType will create a new submission
|
||||||
cy.visit('/submit?collection=' + TEST_SUBMIT_COLLECTION_UUID + '&entityType=none');
|
cy.visit('/submit?collection=' + TEST_SUBMIT_COLLECTION_UUID + '&entityType=none');
|
||||||
|
|
||||||
|
// This page is restricted, so we will be shown the login form. Fill it out & submit.
|
||||||
|
cy.loginViaForm(TEST_SUBMIT_USER, TEST_SUBMIT_USER_PASSWORD);
|
||||||
|
|
||||||
// Should redirect to /workspaceitems, as we've started a new submission
|
// Should redirect to /workspaceitems, as we've started a new submission
|
||||||
cy.url().should('include', '/workspaceitems');
|
cy.url().should('include', '/workspaceitems');
|
||||||
|
|
||||||
@@ -33,11 +34,12 @@ describe('New Submission page', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('should block submission & show errors if required fields are missing', () => {
|
it('should block submission & show errors if required fields are missing', () => {
|
||||||
cy.login(TEST_SUBMIT_USER, TEST_SUBMIT_USER_PASSWORD);
|
|
||||||
|
|
||||||
// Create a new submission
|
// Create a new submission
|
||||||
cy.visit('/submit?collection=' + TEST_SUBMIT_COLLECTION_UUID + '&entityType=none');
|
cy.visit('/submit?collection=' + TEST_SUBMIT_COLLECTION_UUID + '&entityType=none');
|
||||||
|
|
||||||
|
// This page is restricted, so we will be shown the login form. Fill it out & submit.
|
||||||
|
cy.loginViaForm(TEST_SUBMIT_USER, TEST_SUBMIT_USER_PASSWORD);
|
||||||
|
|
||||||
// Attempt an immediate deposit without filling out any fields
|
// Attempt an immediate deposit without filling out any fields
|
||||||
cy.get('button#deposit').click();
|
cy.get('button#deposit').click();
|
||||||
|
|
||||||
@@ -92,11 +94,12 @@ describe('New Submission page', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('should allow for deposit if all required fields completed & file uploaded', () => {
|
it('should allow for deposit if all required fields completed & file uploaded', () => {
|
||||||
cy.login(TEST_SUBMIT_USER, TEST_SUBMIT_USER_PASSWORD);
|
|
||||||
|
|
||||||
// Create a new submission
|
// Create a new submission
|
||||||
cy.visit('/submit?collection=' + TEST_SUBMIT_COLLECTION_UUID + '&entityType=none');
|
cy.visit('/submit?collection=' + TEST_SUBMIT_COLLECTION_UUID + '&entityType=none');
|
||||||
|
|
||||||
|
// This page is restricted, so we will be shown the login form. Fill it out & submit.
|
||||||
|
cy.loginViaForm(TEST_SUBMIT_USER, TEST_SUBMIT_USER_PASSWORD);
|
||||||
|
|
||||||
// Fill out all required fields (Title, Date)
|
// Fill out all required fields (Title, Date)
|
||||||
cy.get('input#dc_title').type('DSpace logo uploaded via e2e tests');
|
cy.get('input#dc_title').type('DSpace logo uploaded via e2e tests');
|
||||||
cy.get('input#dc_date_issued_year').type('2022');
|
cy.get('input#dc_date_issued_year').type('2022');
|
||||||
|
@@ -19,6 +19,14 @@ declare global {
|
|||||||
* @param password password to login as
|
* @param password password to login as
|
||||||
*/
|
*/
|
||||||
login(email: string, password: string): typeof login;
|
login(email: string, password: string): typeof login;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Login via form before accessing the next page. Useful to fill out login
|
||||||
|
* form when a cy.visit() call is to an a page which requires authentication.
|
||||||
|
* @param email email to login as
|
||||||
|
* @param password password to login as
|
||||||
|
*/
|
||||||
|
loginViaForm(email: string, password: string): typeof loginViaForm;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -26,6 +34,8 @@ declare global {
|
|||||||
/**
|
/**
|
||||||
* Login user via REST API directly, and pass authentication token to UI via
|
* Login user via REST API directly, and pass authentication token to UI via
|
||||||
* the UI's dsAuthInfo cookie.
|
* the UI's dsAuthInfo cookie.
|
||||||
|
* WARNING: WHILE THIS METHOD WORKS, OCCASIONALLY RANDOM AUTHENTICATION ERRORS OCCUR.
|
||||||
|
* At this time "loginViaForm()" seems more consistent/stable.
|
||||||
* @param email email to login as
|
* @param email email to login as
|
||||||
* @param password password to login as
|
* @param password password to login as
|
||||||
*/
|
*/
|
||||||
@@ -81,3 +91,20 @@ function login(email: string, password: string): void {
|
|||||||
}
|
}
|
||||||
// Add as a Cypress command (i.e. assign to 'cy.login')
|
// Add as a Cypress command (i.e. assign to 'cy.login')
|
||||||
Cypress.Commands.add('login', login);
|
Cypress.Commands.add('login', login);
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Login user via displayed login form
|
||||||
|
* @param email email to login as
|
||||||
|
* @param password password to login as
|
||||||
|
*/
|
||||||
|
function loginViaForm(email: string, password: string): void {
|
||||||
|
// Enter email
|
||||||
|
cy.get('ds-log-in [data-test="email"]').type(email);
|
||||||
|
// Enter password
|
||||||
|
cy.get('ds-log-in [data-test="password"]').type(password);
|
||||||
|
// Click login button
|
||||||
|
cy.get('ds-log-in [data-test="login-button"]').click();
|
||||||
|
}
|
||||||
|
// Add as a Cypress command (i.e. assign to 'cy.loginViaForm')
|
||||||
|
Cypress.Commands.add('loginViaForm', loginViaForm);
|
@@ -24,8 +24,8 @@ services:
|
|||||||
# __D__ => "-" (e.g. google__D__metadata => google-metadata)
|
# __D__ => "-" (e.g. google__D__metadata => google-metadata)
|
||||||
# dspace.dir, dspace.server.url and dspace.ui.url
|
# dspace.dir, dspace.server.url and dspace.ui.url
|
||||||
dspace__P__dir: /dspace
|
dspace__P__dir: /dspace
|
||||||
dspace__P__server__P__url: http://localhost:8080/server
|
dspace__P__server__P__url: http://127.0.0.1:8080/server
|
||||||
dspace__P__ui__P__url: http://localhost:4000
|
dspace__P__ui__P__url: http://127.0.0.1:4000
|
||||||
# db.url: Ensure we are using the 'dspacedb' image for our database
|
# db.url: Ensure we are using the 'dspacedb' image for our database
|
||||||
db__P__url: 'jdbc:postgresql://dspacedb:5432/dspace'
|
db__P__url: 'jdbc:postgresql://dspacedb:5432/dspace'
|
||||||
# solr.server: Ensure we are using the 'dspacesolr' image for Solr
|
# solr.server: Ensure we are using the 'dspacesolr' image for Solr
|
||||||
|
81
package.json
81
package.json
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "dspace-angular",
|
"name": "dspace-angular",
|
||||||
"version": "7.4.0",
|
"version": "7.5.0-next",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"ng": "ng",
|
"ng": "ng",
|
||||||
"config:watch": "nodemon",
|
"config:watch": "nodemon",
|
||||||
@@ -54,18 +54,18 @@
|
|||||||
"ts-node": "10.2.1"
|
"ts-node": "10.2.1"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@angular/animations": "~13.2.6",
|
"@angular/animations": "~13.3.12",
|
||||||
"@angular/cdk": "^13.2.6",
|
"@angular/cdk": "^13.2.6",
|
||||||
"@angular/common": "~13.2.6",
|
"@angular/common": "~13.3.12",
|
||||||
"@angular/compiler": "~13.2.6",
|
"@angular/compiler": "~13.3.12",
|
||||||
"@angular/core": "~13.2.6",
|
"@angular/core": "~13.3.12",
|
||||||
"@angular/forms": "~13.2.6",
|
"@angular/forms": "~13.3.12",
|
||||||
"@angular/localize": "13.2.6",
|
"@angular/localize": "13.3.12",
|
||||||
"@angular/platform-browser": "~13.2.6",
|
"@angular/platform-browser": "~13.3.12",
|
||||||
"@angular/platform-browser-dynamic": "~13.2.6",
|
"@angular/platform-browser-dynamic": "~13.3.12",
|
||||||
"@angular/platform-server": "~13.2.6",
|
"@angular/platform-server": "~13.3.12",
|
||||||
"@angular/router": "~13.2.6",
|
"@angular/router": "~13.3.12",
|
||||||
"@babel/runtime": "^7.17.2",
|
"@babel/runtime": "7.17.2",
|
||||||
"@kolkov/ngx-gallery": "^2.0.1",
|
"@kolkov/ngx-gallery": "^2.0.1",
|
||||||
"@material-ui/core": "^4.11.0",
|
"@material-ui/core": "^4.11.0",
|
||||||
"@material-ui/icons": "^4.9.1",
|
"@material-ui/icons": "^4.9.1",
|
||||||
@@ -77,15 +77,15 @@
|
|||||||
"@ngrx/store": "^13.0.2",
|
"@ngrx/store": "^13.0.2",
|
||||||
"@nguniversal/express-engine": "^13.0.2",
|
"@nguniversal/express-engine": "^13.0.2",
|
||||||
"@ngx-translate/core": "^13.0.0",
|
"@ngx-translate/core": "^13.0.0",
|
||||||
"@nicky-lenaers/ngx-scroll-to": "^9.0.0",
|
"@nicky-lenaers/ngx-scroll-to": "^13.0.0",
|
||||||
"@types/grecaptcha": "^3.0.4",
|
"@types/grecaptcha": "^3.0.4",
|
||||||
"angular-idle-preload": "3.0.0",
|
"angular-idle-preload": "3.0.0",
|
||||||
"angulartics2": "^12.0.0",
|
"angulartics2": "^12.0.0",
|
||||||
"axios": "^0.27.2",
|
"axios": "^0.27.2",
|
||||||
"bootstrap": "4.3.1",
|
"bootstrap": "^4.6.1",
|
||||||
"caniuse-lite": "^1.0.30001165",
|
|
||||||
"cerialize": "0.1.18",
|
"cerialize": "0.1.18",
|
||||||
"cli-progress": "^3.8.0",
|
"cli-progress": "^3.8.0",
|
||||||
|
"colors": "^1.4.0",
|
||||||
"compression": "^1.7.4",
|
"compression": "^1.7.4",
|
||||||
"cookie-parser": "1.4.5",
|
"cookie-parser": "1.4.5",
|
||||||
"core-js": "^3.7.0",
|
"core-js": "^3.7.0",
|
||||||
@@ -95,98 +95,81 @@
|
|||||||
"express": "^4.17.1",
|
"express": "^4.17.1",
|
||||||
"express-rate-limit": "^5.1.3",
|
"express-rate-limit": "^5.1.3",
|
||||||
"fast-json-patch": "^3.0.0-1",
|
"fast-json-patch": "^3.0.0-1",
|
||||||
"file-saver": "^2.0.5",
|
|
||||||
"filesize": "^6.1.0",
|
"filesize": "^6.1.0",
|
||||||
"font-awesome": "4.7.0",
|
|
||||||
"http-proxy-middleware": "^1.0.5",
|
"http-proxy-middleware": "^1.0.5",
|
||||||
"https": "1.0.0",
|
|
||||||
"js-cookie": "2.2.1",
|
"js-cookie": "2.2.1",
|
||||||
"js-yaml": "^4.1.0",
|
"js-yaml": "^4.1.0",
|
||||||
"json5": "^2.1.3",
|
"json5": "^2.1.3",
|
||||||
"jsonschema": "1.4.0",
|
"jsonschema": "1.4.0",
|
||||||
"jwt-decode": "^3.1.2",
|
"jwt-decode": "^3.1.2",
|
||||||
"klaro": "^0.7.10",
|
"klaro": "^0.7.18",
|
||||||
"lodash": "^4.17.21",
|
"lodash": "^4.17.21",
|
||||||
"markdown-it": "^13.0.1",
|
"markdown-it": "^13.0.1",
|
||||||
"markdown-it-mathjax3": "^4.3.1",
|
"markdown-it-mathjax3": "^4.3.1",
|
||||||
"mirador": "^3.3.0",
|
"mirador": "^3.3.0",
|
||||||
"mirador-dl-plugin": "^0.13.0",
|
"mirador-dl-plugin": "^0.13.0",
|
||||||
"mirador-share-plugin": "^0.11.0",
|
"mirador-share-plugin": "^0.11.0",
|
||||||
"moment": "^2.29.4",
|
|
||||||
"morgan": "^1.10.0",
|
"morgan": "^1.10.0",
|
||||||
"ng-mocks": "^13.1.1",
|
"ng-mocks": "^13.1.1",
|
||||||
"ng2-file-upload": "1.4.0",
|
"ng2-file-upload": "1.4.0",
|
||||||
"ng2-nouislider": "^1.8.3",
|
"ng2-nouislider": "^1.8.3",
|
||||||
"ngx-infinite-scroll": "^10.0.1",
|
"ngx-infinite-scroll": "^10.0.1",
|
||||||
"ngx-moment": "^5.0.0",
|
|
||||||
"ngx-pagination": "5.0.0",
|
"ngx-pagination": "5.0.0",
|
||||||
"ngx-sortablejs": "^11.1.0",
|
"ngx-sortablejs": "^11.1.0",
|
||||||
"ngx-ui-switch": "^11.0.1",
|
"ngx-ui-switch": "^13.0.2",
|
||||||
"nouislider": "^14.6.3",
|
"nouislider": "^14.6.3",
|
||||||
"pem": "1.14.4",
|
"pem": "1.14.4",
|
||||||
"postcss-cli": "^9.1.0",
|
|
||||||
"prop-types": "^15.7.2",
|
"prop-types": "^15.7.2",
|
||||||
"react-copy-to-clipboard": "^5.0.1",
|
"react-copy-to-clipboard": "^5.0.1",
|
||||||
"reflect-metadata": "^0.1.13",
|
"reflect-metadata": "^0.1.13",
|
||||||
"rxjs": "^7.5.5",
|
"rxjs": "^7.5.5",
|
||||||
"sanitize-html": "^2.7.2",
|
"sanitize-html": "^2.7.2",
|
||||||
"sortablejs": "1.13.0",
|
"sortablejs": "1.13.0",
|
||||||
"tslib": "^2.0.0",
|
|
||||||
"url-parse": "^1.5.6",
|
|
||||||
"uuid": "^8.3.2",
|
"uuid": "^8.3.2",
|
||||||
"webfontloader": "1.6.28",
|
"webfontloader": "1.6.28",
|
||||||
"zone.js": "~0.11.5"
|
"zone.js": "~0.11.5"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@angular-builders/custom-webpack": "~13.1.0",
|
"@angular-builders/custom-webpack": "~13.1.0",
|
||||||
"@angular-devkit/build-angular": "~13.2.6",
|
"@angular-devkit/build-angular": "~13.3.10",
|
||||||
"@angular-eslint/builder": "13.1.0",
|
"@angular-eslint/builder": "13.1.0",
|
||||||
"@angular-eslint/eslint-plugin": "13.1.0",
|
"@angular-eslint/eslint-plugin": "13.1.0",
|
||||||
"@angular-eslint/eslint-plugin-template": "13.1.0",
|
"@angular-eslint/eslint-plugin-template": "13.1.0",
|
||||||
"@angular-eslint/schematics": "13.1.0",
|
"@angular-eslint/schematics": "13.1.0",
|
||||||
"@angular-eslint/template-parser": "13.1.0",
|
"@angular-eslint/template-parser": "13.1.0",
|
||||||
"@angular/cli": "~13.2.6",
|
"@angular/cli": "~13.3.10",
|
||||||
"@angular/compiler-cli": "~13.2.6",
|
"@angular/compiler-cli": "~13.3.12",
|
||||||
"@angular/language-service": "~13.2.6",
|
"@angular/language-service": "~13.3.12",
|
||||||
"@cypress/schematic": "^1.5.0",
|
"@cypress/schematic": "^1.5.0",
|
||||||
"@fortawesome/fontawesome-free": "^5.5.0",
|
"@fortawesome/fontawesome-free": "^6.2.1",
|
||||||
"@ngrx/store-devtools": "^13.0.2",
|
"@ngrx/store-devtools": "^13.0.2",
|
||||||
"@ngtools/webpack": "^13.2.6",
|
"@ngtools/webpack": "^13.2.6",
|
||||||
"@nguniversal/builders": "^13.0.2",
|
"@nguniversal/builders": "^13.1.1",
|
||||||
"@types/deep-freeze": "0.1.2",
|
"@types/deep-freeze": "0.1.2",
|
||||||
"@types/express": "^4.17.9",
|
"@types/express": "^4.17.9",
|
||||||
"@types/file-saver": "^2.0.1",
|
|
||||||
"@types/jasmine": "~3.6.0",
|
"@types/jasmine": "~3.6.0",
|
||||||
"@types/jasminewd2": "~2.0.8",
|
|
||||||
"@types/js-cookie": "2.2.6",
|
"@types/js-cookie": "2.2.6",
|
||||||
"@types/lodash": "^4.14.165",
|
"@types/lodash": "^4.14.165",
|
||||||
"@types/node": "^14.14.9",
|
"@types/node": "^14.14.9",
|
||||||
"@types/sanitize-html": "^2.6.2",
|
"@types/sanitize-html": "^2.6.2",
|
||||||
"@typescript-eslint/eslint-plugin": "5.11.0",
|
"@typescript-eslint/eslint-plugin": "5.11.0",
|
||||||
"@typescript-eslint/parser": "5.11.0",
|
"@typescript-eslint/parser": "5.11.0",
|
||||||
"axe-core": "^4.3.3",
|
"axe-core": "^4.4.3",
|
||||||
"compression-webpack-plugin": "^9.2.0",
|
"compression-webpack-plugin": "^9.2.0",
|
||||||
"copy-webpack-plugin": "^6.4.1",
|
"copy-webpack-plugin": "^6.4.1",
|
||||||
"cross-env": "^7.0.3",
|
"cross-env": "^7.0.3",
|
||||||
"css-loader": "^6.2.0",
|
"cypress": "9.7.0",
|
||||||
"css-minimizer-webpack-plugin": "^3.4.1",
|
|
||||||
"cssnano": "^5.0.6",
|
|
||||||
"cypress": "9.5.1",
|
|
||||||
"cypress-axe": "^0.14.0",
|
"cypress-axe": "^0.14.0",
|
||||||
"debug-loader": "^0.0.1",
|
|
||||||
"deep-freeze": "0.0.1",
|
"deep-freeze": "0.0.1",
|
||||||
"dotenv": "^8.2.0",
|
|
||||||
"eslint": "^8.2.0",
|
"eslint": "^8.2.0",
|
||||||
"eslint-plugin-deprecation": "^1.3.2",
|
"eslint-plugin-deprecation": "^1.3.2",
|
||||||
"eslint-plugin-import": "^2.25.4",
|
"eslint-plugin-import": "^2.25.4",
|
||||||
"eslint-plugin-jsdoc": "^38.0.6",
|
"eslint-plugin-jsdoc": "^39.6.4",
|
||||||
|
"eslint-plugin-lodash": "^7.4.0",
|
||||||
"eslint-plugin-unused-imports": "^2.0.0",
|
"eslint-plugin-unused-imports": "^2.0.0",
|
||||||
"express-static-gzip": "^2.1.5",
|
"express-static-gzip": "^2.1.5",
|
||||||
"fork-ts-checker-webpack-plugin": "^6.0.3",
|
|
||||||
"html-loader": "^1.3.2",
|
|
||||||
"jasmine-core": "^3.8.0",
|
"jasmine-core": "^3.8.0",
|
||||||
"jasmine-marbles": "0.9.2",
|
"jasmine-marbles": "0.9.2",
|
||||||
"jasmine-spec-reporter": "~5.0.0",
|
|
||||||
"karma": "^6.3.14",
|
"karma": "^6.3.14",
|
||||||
"karma-chrome-launcher": "~3.1.0",
|
"karma-chrome-launcher": "~3.1.0",
|
||||||
"karma-coverage-istanbul-reporter": "~3.0.2",
|
"karma-coverage-istanbul-reporter": "~3.0.2",
|
||||||
@@ -194,26 +177,20 @@
|
|||||||
"karma-jasmine-html-reporter": "^1.5.0",
|
"karma-jasmine-html-reporter": "^1.5.0",
|
||||||
"karma-mocha-reporter": "2.2.5",
|
"karma-mocha-reporter": "2.2.5",
|
||||||
"ngx-mask": "^13.1.7",
|
"ngx-mask": "^13.1.7",
|
||||||
"nodemon": "^2.0.15",
|
"nodemon": "^2.0.20",
|
||||||
"postcss": "^8.1",
|
"postcss": "^8.1",
|
||||||
"postcss-apply": "0.12.0",
|
"postcss-apply": "0.12.0",
|
||||||
"postcss-import": "^14.0.0",
|
"postcss-import": "^14.0.0",
|
||||||
"postcss-loader": "^4.0.3",
|
"postcss-loader": "^4.0.3",
|
||||||
"postcss-preset-env": "^7.4.2",
|
"postcss-preset-env": "^7.4.2",
|
||||||
"postcss-responsive-type": "1.0.0",
|
"postcss-responsive-type": "1.0.0",
|
||||||
"protractor": "^7.0.0",
|
|
||||||
"protractor-istanbul-plugin": "2.0.0",
|
|
||||||
"raw-loader": "0.5.1",
|
|
||||||
"react": "^16.14.0",
|
"react": "^16.14.0",
|
||||||
"react-dom": "^16.14.0",
|
"react-dom": "^16.14.0",
|
||||||
"rimraf": "^3.0.2",
|
"rimraf": "^3.0.2",
|
||||||
"rxjs-spy": "^8.0.2",
|
"rxjs-spy": "^8.0.2",
|
||||||
"sass": "~1.32.6",
|
"sass": "~1.33.0",
|
||||||
"sass-loader": "^12.6.0",
|
"sass-loader": "^12.6.0",
|
||||||
"sass-resources-loader": "^2.1.1",
|
"sass-resources-loader": "^2.1.1",
|
||||||
"string-replace-loader": "^3.1.0",
|
|
||||||
"terser-webpack-plugin": "^2.3.1",
|
|
||||||
"ts-loader": "^5.2.0",
|
|
||||||
"ts-node": "^8.10.2",
|
"ts-node": "^8.10.2",
|
||||||
"typescript": "~4.5.5",
|
"typescript": "~4.5.5",
|
||||||
"webpack": "^5.69.1",
|
"webpack": "^5.69.1",
|
||||||
|
@@ -1,4 +1,4 @@
|
|||||||
import * as fs from 'fs';
|
import { existsSync, writeFileSync } from 'fs';
|
||||||
import { join } from 'path';
|
import { join } from 'path';
|
||||||
|
|
||||||
import { AppConfig } from '../src/config/app-config.interface';
|
import { AppConfig } from '../src/config/app-config.interface';
|
||||||
@@ -16,7 +16,7 @@ const appConfig: AppConfig = buildAppConfig();
|
|||||||
|
|
||||||
const angularJsonPath = join(process.cwd(), 'angular.json');
|
const angularJsonPath = join(process.cwd(), 'angular.json');
|
||||||
|
|
||||||
if (!fs.existsSync(angularJsonPath)) {
|
if (!existsSync(angularJsonPath)) {
|
||||||
console.error(`Error:\n${angularJsonPath} does not exist\n`);
|
console.error(`Error:\n${angularJsonPath} does not exist\n`);
|
||||||
process.exit(1);
|
process.exit(1);
|
||||||
}
|
}
|
||||||
@@ -30,7 +30,7 @@ try {
|
|||||||
|
|
||||||
angularJson.projects['dspace-angular'].architect.build.options.baseHref = baseHref;
|
angularJson.projects['dspace-angular'].architect.build.options.baseHref = baseHref;
|
||||||
|
|
||||||
fs.writeFileSync(angularJsonPath, JSON.stringify(angularJson, null, 2) + '\n');
|
writeFileSync(angularJsonPath, JSON.stringify(angularJson, null, 2) + '\n');
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.error(e);
|
console.error(e);
|
||||||
}
|
}
|
||||||
|
@@ -1,5 +1,5 @@
|
|||||||
import * as fs from 'fs';
|
import { existsSync, writeFileSync } from 'fs';
|
||||||
import * as yaml from 'js-yaml';
|
import { dump } from 'js-yaml';
|
||||||
import { join } from 'path';
|
import { join } from 'path';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -18,7 +18,7 @@ if (args[0] === undefined) {
|
|||||||
|
|
||||||
const envFullPath = join(process.cwd(), args[0]);
|
const envFullPath = join(process.cwd(), args[0]);
|
||||||
|
|
||||||
if (!fs.existsSync(envFullPath)) {
|
if (!existsSync(envFullPath)) {
|
||||||
console.error(`Error:\n${envFullPath} does not exist\n`);
|
console.error(`Error:\n${envFullPath} does not exist\n`);
|
||||||
process.exit(1);
|
process.exit(1);
|
||||||
}
|
}
|
||||||
@@ -26,10 +26,10 @@ if (!fs.existsSync(envFullPath)) {
|
|||||||
try {
|
try {
|
||||||
const env = require(envFullPath).environment;
|
const env = require(envFullPath).environment;
|
||||||
|
|
||||||
const config = yaml.dump(env);
|
const config = dump(env);
|
||||||
if (args[1]) {
|
if (args[1]) {
|
||||||
const ymlFullPath = join(process.cwd(), args[1]);
|
const ymlFullPath = join(process.cwd(), args[1]);
|
||||||
fs.writeFileSync(ymlFullPath, config);
|
writeFileSync(ymlFullPath, config);
|
||||||
} else {
|
} else {
|
||||||
console.log(config);
|
console.log(config);
|
||||||
}
|
}
|
||||||
|
@@ -1,4 +1,4 @@
|
|||||||
import * as child from 'child_process';
|
import { spawn } from 'child_process';
|
||||||
|
|
||||||
import { AppConfig } from '../src/config/app-config.interface';
|
import { AppConfig } from '../src/config/app-config.interface';
|
||||||
import { buildAppConfig } from '../src/config/config.server';
|
import { buildAppConfig } from '../src/config/config.server';
|
||||||
@@ -9,7 +9,7 @@ const appConfig: AppConfig = buildAppConfig();
|
|||||||
* Calls `ng serve` with the following arguments configured for the UI in the app config: host, port, nameSpace, ssl
|
* Calls `ng serve` with the following arguments configured for the UI in the app config: host, port, nameSpace, ssl
|
||||||
* Any CLI arguments given to this script are patched through to `ng serve` as well.
|
* Any CLI arguments given to this script are patched through to `ng serve` as well.
|
||||||
*/
|
*/
|
||||||
child.spawn(
|
spawn(
|
||||||
`ng serve --host ${appConfig.ui.host} --port ${appConfig.ui.port} --serve-path ${appConfig.ui.nameSpace} --ssl ${appConfig.ui.ssl} ${process.argv.slice(2).join(' ')} --configuration development`,
|
`ng serve --host ${appConfig.ui.host} --port ${appConfig.ui.port} --serve-path ${appConfig.ui.nameSpace} --ssl ${appConfig.ui.ssl} ${process.argv.slice(2).join(' ')} --configuration development`,
|
||||||
{ stdio: 'inherit', shell: true }
|
{ stdio: 'inherit', shell: true }
|
||||||
);
|
);
|
||||||
|
@@ -1,5 +1,5 @@
|
|||||||
import * as http from 'http';
|
import { request } from 'http';
|
||||||
import * as https from 'https';
|
import { request as https_request } from 'https';
|
||||||
|
|
||||||
import { AppConfig } from '../src/config/app-config.interface';
|
import { AppConfig } from '../src/config/app-config.interface';
|
||||||
import { buildAppConfig } from '../src/config/config.server';
|
import { buildAppConfig } from '../src/config/config.server';
|
||||||
@@ -20,7 +20,7 @@ console.log(`...Testing connection to REST API at ${restUrl}...\n`);
|
|||||||
|
|
||||||
// If SSL enabled, test via HTTPS, else via HTTP
|
// If SSL enabled, test via HTTPS, else via HTTP
|
||||||
if (appConfig.rest.ssl) {
|
if (appConfig.rest.ssl) {
|
||||||
const req = https.request(restUrl, (res) => {
|
const req = https_request(restUrl, (res) => {
|
||||||
console.log(`RESPONSE: ${res.statusCode} ${res.statusMessage} \n`);
|
console.log(`RESPONSE: ${res.statusCode} ${res.statusMessage} \n`);
|
||||||
// We will keep reading data until the 'end' event fires.
|
// We will keep reading data until the 'end' event fires.
|
||||||
// This ensures we don't just read the first chunk.
|
// This ensures we don't just read the first chunk.
|
||||||
@@ -39,7 +39,7 @@ if (appConfig.rest.ssl) {
|
|||||||
|
|
||||||
req.end();
|
req.end();
|
||||||
} else {
|
} else {
|
||||||
const req = http.request(restUrl, (res) => {
|
const req = request(restUrl, (res) => {
|
||||||
console.log(`RESPONSE: ${res.statusCode} ${res.statusMessage} \n`);
|
console.log(`RESPONSE: ${res.statusCode} ${res.statusMessage} \n`);
|
||||||
// We will keep reading data until the 'end' event fires.
|
// We will keep reading data until the 'end' event fires.
|
||||||
// This ensures we don't just read the first chunk.
|
// This ensures we don't just read the first chunk.
|
||||||
|
17
server.ts
17
server.ts
@@ -19,14 +19,17 @@ import 'zone.js/node';
|
|||||||
import 'reflect-metadata';
|
import 'reflect-metadata';
|
||||||
import 'rxjs';
|
import 'rxjs';
|
||||||
|
|
||||||
import axios from 'axios';
|
/* eslint-disable import/no-namespace */
|
||||||
import * as pem from 'pem';
|
|
||||||
import * as https from 'https';
|
|
||||||
import * as morgan from 'morgan';
|
import * as morgan from 'morgan';
|
||||||
import * as express from 'express';
|
import * as express from 'express';
|
||||||
import * as bodyParser from 'body-parser';
|
|
||||||
import * as compression from 'compression';
|
import * as compression from 'compression';
|
||||||
import * as expressStaticGzip from 'express-static-gzip';
|
import * as expressStaticGzip from 'express-static-gzip';
|
||||||
|
/* eslint-enable import/no-namespace */
|
||||||
|
|
||||||
|
import axios from 'axios';
|
||||||
|
import { createCertificate } from 'pem';
|
||||||
|
import { createServer } from 'https';
|
||||||
|
import { json } from 'body-parser';
|
||||||
|
|
||||||
import { existsSync, readFileSync } from 'fs';
|
import { existsSync, readFileSync } from 'fs';
|
||||||
import { join } from 'path';
|
import { join } from 'path';
|
||||||
@@ -110,7 +113,7 @@ export function app() {
|
|||||||
* Add parser for request bodies
|
* Add parser for request bodies
|
||||||
* See [morgan](https://github.com/expressjs/body-parser)
|
* See [morgan](https://github.com/expressjs/body-parser)
|
||||||
*/
|
*/
|
||||||
server.use(bodyParser.json());
|
server.use(json());
|
||||||
|
|
||||||
// Our Universal express-engine (found @ https://github.com/angular/universal/tree/master/modules/express-engine)
|
// Our Universal express-engine (found @ https://github.com/angular/universal/tree/master/modules/express-engine)
|
||||||
server.engine('html', (_, options, callback) =>
|
server.engine('html', (_, options, callback) =>
|
||||||
@@ -266,7 +269,7 @@ function serverStarted() {
|
|||||||
* @param keys SSL credentials
|
* @param keys SSL credentials
|
||||||
*/
|
*/
|
||||||
function createHttpsServer(keys) {
|
function createHttpsServer(keys) {
|
||||||
https.createServer({
|
createServer({
|
||||||
key: keys.serviceKey,
|
key: keys.serviceKey,
|
||||||
cert: keys.certificate
|
cert: keys.certificate
|
||||||
}, app).listen(environment.ui.port, environment.ui.host, () => {
|
}, app).listen(environment.ui.port, environment.ui.host, () => {
|
||||||
@@ -320,7 +323,7 @@ function start() {
|
|||||||
|
|
||||||
process.env.NODE_TLS_REJECT_UNAUTHORIZED = '0'; // lgtm[js/disabling-certificate-validation]
|
process.env.NODE_TLS_REJECT_UNAUTHORIZED = '0'; // lgtm[js/disabling-certificate-validation]
|
||||||
|
|
||||||
pem.createCertificate({
|
createCertificate({
|
||||||
days: 1,
|
days: 1,
|
||||||
selfSigned: true
|
selfSigned: true
|
||||||
}, (error, keys) => {
|
}, (error, keys) => {
|
||||||
|
@@ -10,6 +10,16 @@ import { MembersListComponent } from './group-registry/group-form/members-list/m
|
|||||||
import { SubgroupsListComponent } from './group-registry/group-form/subgroup-list/subgroups-list.component';
|
import { SubgroupsListComponent } from './group-registry/group-form/subgroup-list/subgroups-list.component';
|
||||||
import { GroupsRegistryComponent } from './group-registry/groups-registry.component';
|
import { GroupsRegistryComponent } from './group-registry/groups-registry.component';
|
||||||
import { FormModule } from '../shared/form/form.module';
|
import { FormModule } from '../shared/form/form.module';
|
||||||
|
import { DYNAMIC_ERROR_MESSAGES_MATCHER, DynamicErrorMessagesMatcher } from '@ng-dynamic-forms/core';
|
||||||
|
import { AbstractControl } from '@angular/forms';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Condition for displaying error messages on email form field
|
||||||
|
*/
|
||||||
|
export const ValidateEmailErrorStateMatcher: DynamicErrorMessagesMatcher =
|
||||||
|
(control: AbstractControl, model: any, hasFocus: boolean) => {
|
||||||
|
return (control.touched && !hasFocus) || (control.errors?.emailTaken && hasFocus);
|
||||||
|
};
|
||||||
|
|
||||||
@NgModule({
|
@NgModule({
|
||||||
imports: [
|
imports: [
|
||||||
@@ -26,6 +36,12 @@ import { FormModule } from '../shared/form/form.module';
|
|||||||
GroupFormComponent,
|
GroupFormComponent,
|
||||||
SubgroupsListComponent,
|
SubgroupsListComponent,
|
||||||
MembersListComponent
|
MembersListComponent
|
||||||
|
],
|
||||||
|
providers: [
|
||||||
|
{
|
||||||
|
provide: DYNAMIC_ERROR_MESSAGES_MATCHER,
|
||||||
|
useValue: ValidateEmailErrorStateMatcher
|
||||||
|
},
|
||||||
]
|
]
|
||||||
})
|
})
|
||||||
/**
|
/**
|
||||||
|
@@ -46,6 +46,7 @@ import { followLink } from '../../../shared/utils/follow-link-config.model';
|
|||||||
import { NoContent } from '../../../core/shared/NoContent.model';
|
import { NoContent } from '../../../core/shared/NoContent.model';
|
||||||
import { Operation } from 'fast-json-patch';
|
import { Operation } from 'fast-json-patch';
|
||||||
import { ValidateGroupExists } from './validators/group-exists.validator';
|
import { ValidateGroupExists } from './validators/group-exists.validator';
|
||||||
|
import { environment } from '../../../../environments/environment';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'ds-group-form',
|
selector: 'ds-group-form',
|
||||||
@@ -194,6 +195,7 @@ export class GroupFormComponent implements OnInit, OnDestroy {
|
|||||||
label: groupDescription,
|
label: groupDescription,
|
||||||
name: 'groupDescription',
|
name: 'groupDescription',
|
||||||
required: false,
|
required: false,
|
||||||
|
spellCheck: environment.form.spellCheck,
|
||||||
});
|
});
|
||||||
this.formModel = [
|
this.formModel = [
|
||||||
this.groupName,
|
this.groupName,
|
||||||
|
@@ -1,12 +1,8 @@
|
|||||||
import { Location } from '@angular/common';
|
import { Location } from '@angular/common';
|
||||||
import { Component, OnInit } from '@angular/core';
|
import { Component } from '@angular/core';
|
||||||
import { Router } from '@angular/router';
|
import { Router } from '@angular/router';
|
||||||
import { TranslateService } from '@ngx-translate/core';
|
import { TranslateService } from '@ngx-translate/core';
|
||||||
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 { ProcessParameter } from '../../process-page/processes/process-parameter.model';
|
||||||
import { isNotEmpty } from '../../shared/empty.util';
|
import { isNotEmpty } from '../../shared/empty.util';
|
||||||
import { NotificationsService } from '../../shared/notifications/notifications.service';
|
import { NotificationsService } from '../../shared/notifications/notifications.service';
|
||||||
|
@@ -13,32 +13,34 @@
|
|||||||
[paginationOptions]="pageConfig"
|
[paginationOptions]="pageConfig"
|
||||||
[pageInfoState]="(bitstreamFormats | async)?.payload"
|
[pageInfoState]="(bitstreamFormats | async)?.payload"
|
||||||
[collectionSize]="(bitstreamFormats | async)?.payload?.totalElements"
|
[collectionSize]="(bitstreamFormats | async)?.payload?.totalElements"
|
||||||
[hideGear]="true"
|
[hideGear]="false"
|
||||||
[hidePagerWhenSinglePage]="true">
|
[hidePagerWhenSinglePage]="true">
|
||||||
<div class="table-responsive">
|
<div class="table-responsive">
|
||||||
<table id="formats" class="table table-striped table-hover">
|
<table id="formats" class="table table-striped table-hover">
|
||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
<th scope="col"></th>
|
<th scope="col"></th>
|
||||||
<th scope="col">{{'admin.registries.bitstream-formats.table.name' | translate}}</th>
|
<th scope="col">{{'admin.registries.bitstream-formats.table.id' | translate}}</th>
|
||||||
<th scope="col">{{'admin.registries.bitstream-formats.table.mimetype' | translate}}</th>
|
<th scope="col">{{'admin.registries.bitstream-formats.table.name' | translate}}</th>
|
||||||
<th scope="col">{{'admin.registries.bitstream-formats.table.supportLevel.head' | translate}}</th>
|
<th scope="col">{{'admin.registries.bitstream-formats.table.mimetype' | translate}}</th>
|
||||||
</tr>
|
<th scope="col">{{'admin.registries.bitstream-formats.table.supportLevel.head' | translate}}</th>
|
||||||
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
<tr *ngFor="let bitstreamFormat of (bitstreamFormats | async)?.payload?.page">
|
<tr *ngFor="let bitstreamFormat of (bitstreamFormats | async)?.payload?.page">
|
||||||
<td>
|
<td>
|
||||||
<label>
|
<label>
|
||||||
<input type="checkbox"
|
<input type="checkbox"
|
||||||
[checked]="isSelected(bitstreamFormat) | async"
|
[checked]="isSelected(bitstreamFormat) | async"
|
||||||
(change)="selectBitStreamFormat(bitstreamFormat, $event)"
|
(change)="selectBitStreamFormat(bitstreamFormat, $event)"
|
||||||
>
|
>
|
||||||
</label>
|
</label>
|
||||||
</td>
|
</td>
|
||||||
<td><a [routerLink]="['/admin/registries/bitstream-formats', bitstreamFormat.id, 'edit']">{{bitstreamFormat.shortDescription}}</a></td>
|
<td><a [routerLink]="['/admin/registries/bitstream-formats', bitstreamFormat.id, 'edit']">{{bitstreamFormat.id}}</a></td>
|
||||||
<td><a [routerLink]="['/admin/registries/bitstream-formats', bitstreamFormat.id, 'edit']">{{bitstreamFormat.mimetype}} <span *ngIf="bitstreamFormat.internal">({{'admin.registries.bitstream-formats.table.internal' | translate}})</span></a></td>
|
<td><a [routerLink]="['/admin/registries/bitstream-formats', bitstreamFormat.id, 'edit']">{{bitstreamFormat.shortDescription}}</a></td>
|
||||||
<td><a [routerLink]="['/admin/registries/bitstream-formats', bitstreamFormat.id, 'edit']">{{'admin.registries.bitstream-formats.table.supportLevel.'+bitstreamFormat.supportLevel | translate}}</a></td>
|
<td><a [routerLink]="['/admin/registries/bitstream-formats', bitstreamFormat.id, 'edit']">{{bitstreamFormat.mimetype}} <span *ngIf="bitstreamFormat.internal">({{'admin.registries.bitstream-formats.table.internal' | translate}})</span></a></td>
|
||||||
</tr>
|
<td><a [routerLink]="['/admin/registries/bitstream-formats', bitstreamFormat.id, 'edit']">{{'admin.registries.bitstream-formats.table.supportLevel.'+bitstreamFormat.supportLevel | translate}}</a></td>
|
||||||
|
</tr>
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
</div>
|
</div>
|
||||||
|
@@ -129,16 +129,19 @@ describe('BitstreamFormatsComponent', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('should contain the correct formats', () => {
|
it('should contain the correct formats', () => {
|
||||||
const unknownName: HTMLElement = fixture.debugElement.query(By.css('#formats tr:nth-child(1) td:nth-child(2)')).nativeElement;
|
const unknownName: HTMLElement = fixture.debugElement.query(By.css('#formats tr:nth-child(1) td:nth-child(3)')).nativeElement;
|
||||||
expect(unknownName.textContent).toBe('Unknown');
|
expect(unknownName.textContent).toBe('Unknown');
|
||||||
|
|
||||||
const licenseName: HTMLElement = fixture.debugElement.query(By.css('#formats tr:nth-child(2) td:nth-child(2)')).nativeElement;
|
const UUID: HTMLElement = fixture.debugElement.query(By.css('#formats tr:nth-child(1) td:nth-child(2)')).nativeElement;
|
||||||
|
expect(UUID.textContent).toBe('test-uuid-1');
|
||||||
|
|
||||||
|
const licenseName: HTMLElement = fixture.debugElement.query(By.css('#formats tr:nth-child(2) td:nth-child(3)')).nativeElement;
|
||||||
expect(licenseName.textContent).toBe('License');
|
expect(licenseName.textContent).toBe('License');
|
||||||
|
|
||||||
const ccLicenseName: HTMLElement = fixture.debugElement.query(By.css('#formats tr:nth-child(3) td:nth-child(2)')).nativeElement;
|
const ccLicenseName: HTMLElement = fixture.debugElement.query(By.css('#formats tr:nth-child(3) td:nth-child(3)')).nativeElement;
|
||||||
expect(ccLicenseName.textContent).toBe('CC License');
|
expect(ccLicenseName.textContent).toBe('CC License');
|
||||||
|
|
||||||
const adobeName: HTMLElement = fixture.debugElement.query(By.css('#formats tr:nth-child(4) td:nth-child(2)')).nativeElement;
|
const adobeName: HTMLElement = fixture.debugElement.query(By.css('#formats tr:nth-child(4) td:nth-child(3)')).nativeElement;
|
||||||
expect(adobeName.textContent).toBe('Adobe PDF');
|
expect(adobeName.textContent).toBe('Adobe PDF');
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@@ -1,12 +1,11 @@
|
|||||||
import { Component, OnDestroy, OnInit } from '@angular/core';
|
import { Component, OnDestroy, OnInit } from '@angular/core';
|
||||||
import { combineLatest as observableCombineLatest, Observable, zip } from 'rxjs';
|
import { combineLatest as observableCombineLatest, Observable} from 'rxjs';
|
||||||
import { RemoteData } from '../../../core/data/remote-data';
|
import { RemoteData } from '../../../core/data/remote-data';
|
||||||
import { PaginatedList } from '../../../core/data/paginated-list.model';
|
import { PaginatedList } from '../../../core/data/paginated-list.model';
|
||||||
import { PaginationComponentOptions } from '../../../shared/pagination/pagination-component-options.model';
|
import { PaginationComponentOptions } from '../../../shared/pagination/pagination-component-options.model';
|
||||||
import { BitstreamFormat } from '../../../core/shared/bitstream-format.model';
|
import { BitstreamFormat } from '../../../core/shared/bitstream-format.model';
|
||||||
import { BitstreamFormatDataService } from '../../../core/data/bitstream-format-data.service';
|
import { BitstreamFormatDataService } from '../../../core/data/bitstream-format-data.service';
|
||||||
import { map, mergeMap, switchMap, take, toArray } from 'rxjs/operators';
|
import { map, mergeMap, switchMap, take, toArray } from 'rxjs/operators';
|
||||||
import { hasValue } from '../../../shared/empty.util';
|
|
||||||
import { NotificationsService } from '../../../shared/notifications/notifications.service';
|
import { NotificationsService } from '../../../shared/notifications/notifications.service';
|
||||||
import { Router } from '@angular/router';
|
import { Router } from '@angular/router';
|
||||||
import { TranslateService } from '@ngx-translate/core';
|
import { TranslateService } from '@ngx-translate/core';
|
||||||
@@ -29,21 +28,14 @@ export class BitstreamFormatsComponent implements OnInit, OnDestroy {
|
|||||||
*/
|
*/
|
||||||
bitstreamFormats: Observable<RemoteData<PaginatedList<BitstreamFormat>>>;
|
bitstreamFormats: Observable<RemoteData<PaginatedList<BitstreamFormat>>>;
|
||||||
|
|
||||||
/**
|
|
||||||
* The current pagination configuration for the page used by the FindAll method
|
|
||||||
* Currently simply renders all bitstream formats
|
|
||||||
*/
|
|
||||||
config: FindListOptions = Object.assign(new FindListOptions(), {
|
|
||||||
elementsPerPage: 20
|
|
||||||
});
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The current pagination configuration for the page
|
* The current pagination configuration for the page
|
||||||
* Currently simply renders all bitstream formats
|
* Currently simply renders all bitstream formats
|
||||||
*/
|
*/
|
||||||
pageConfig: PaginationComponentOptions = Object.assign(new PaginationComponentOptions(), {
|
pageConfig: PaginationComponentOptions = Object.assign(new PaginationComponentOptions(), {
|
||||||
id: 'rbp',
|
id: 'rbp',
|
||||||
pageSize: 20
|
pageSize: 20,
|
||||||
|
pageSizeOptions: [20, 40, 60, 80, 100]
|
||||||
});
|
});
|
||||||
|
|
||||||
constructor(private notificationsService: NotificationsService,
|
constructor(private notificationsService: NotificationsService,
|
||||||
@@ -51,7 +43,7 @@ export class BitstreamFormatsComponent implements OnInit, OnDestroy {
|
|||||||
private translateService: TranslateService,
|
private translateService: TranslateService,
|
||||||
private bitstreamFormatService: BitstreamFormatDataService,
|
private bitstreamFormatService: BitstreamFormatDataService,
|
||||||
private paginationService: PaginationService,
|
private paginationService: PaginationService,
|
||||||
) {
|
) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -149,7 +141,7 @@ export class BitstreamFormatsComponent implements OnInit, OnDestroy {
|
|||||||
|
|
||||||
ngOnInit(): void {
|
ngOnInit(): void {
|
||||||
|
|
||||||
this.bitstreamFormats = this.paginationService.getFindListOptions(this.pageConfig.id, this.config).pipe(
|
this.bitstreamFormats = this.paginationService.getFindListOptions(this.pageConfig.id, this.pageConfig).pipe(
|
||||||
switchMap((findListOptions: FindListOptions) => {
|
switchMap((findListOptions: FindListOptions) => {
|
||||||
return this.bitstreamFormatService.findAll(findListOptions);
|
return this.bitstreamFormatService.findAll(findListOptions);
|
||||||
})
|
})
|
||||||
|
@@ -15,6 +15,7 @@ import { Router } from '@angular/router';
|
|||||||
import { hasValue, isEmpty } from '../../../../shared/empty.util';
|
import { hasValue, isEmpty } from '../../../../shared/empty.util';
|
||||||
import { TranslateService } from '@ngx-translate/core';
|
import { TranslateService } from '@ngx-translate/core';
|
||||||
import { getBitstreamFormatsModuleRoute } from '../../admin-registries-routing-paths';
|
import { getBitstreamFormatsModuleRoute } from '../../admin-registries-routing-paths';
|
||||||
|
import { environment } from '../../../../../environments/environment';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The component responsible for rendering the form to create/edit a bitstream format
|
* The component responsible for rendering the form to create/edit a bitstream format
|
||||||
@@ -90,6 +91,7 @@ export class FormatFormComponent implements OnInit {
|
|||||||
name: 'description',
|
name: 'description',
|
||||||
label: 'admin.registries.bitstream-formats.edit.description.label',
|
label: 'admin.registries.bitstream-formats.edit.description.label',
|
||||||
hint: 'admin.registries.bitstream-formats.edit.description.hint',
|
hint: 'admin.registries.bitstream-formats.edit.description.hint',
|
||||||
|
spellCheck: environment.form.spellCheck,
|
||||||
|
|
||||||
}),
|
}),
|
||||||
new DynamicSelectModel({
|
new DynamicSelectModel({
|
||||||
|
@@ -19,10 +19,7 @@ import { RestResponse } from '../../../core/cache/response.models';
|
|||||||
import { MetadataSchema } from '../../../core/metadata/metadata-schema.model';
|
import { MetadataSchema } from '../../../core/metadata/metadata-schema.model';
|
||||||
import { createSuccessfulRemoteDataObject$ } from '../../../shared/remote-data.utils';
|
import { createSuccessfulRemoteDataObject$ } from '../../../shared/remote-data.utils';
|
||||||
import { PaginationService } from '../../../core/pagination/pagination.service';
|
import { PaginationService } from '../../../core/pagination/pagination.service';
|
||||||
import { PaginationComponentOptions } from '../../../shared/pagination/pagination-component-options.model';
|
|
||||||
import { SortDirection, SortOptions } from '../../../core/cache/models/sort-options.model';
|
|
||||||
import { PaginationServiceStub } from '../../../shared/testing/pagination-service.stub';
|
import { PaginationServiceStub } from '../../../shared/testing/pagination-service.stub';
|
||||||
import { FindListOptions } from '../../../core/data/find-list-options.model';
|
|
||||||
|
|
||||||
describe('MetadataRegistryComponent', () => {
|
describe('MetadataRegistryComponent', () => {
|
||||||
let comp: MetadataRegistryComponent;
|
let comp: MetadataRegistryComponent;
|
||||||
|
@@ -25,6 +25,7 @@
|
|||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
<th></th>
|
<th></th>
|
||||||
|
<th scope="col">{{'admin.registries.schema.fields.table.id' | translate}}</th>
|
||||||
<th scope="col">{{'admin.registries.schema.fields.table.field' | translate}}</th>
|
<th scope="col">{{'admin.registries.schema.fields.table.field' | translate}}</th>
|
||||||
<th scope="col">{{'admin.registries.schema.fields.table.scopenote' | translate}}</th>
|
<th scope="col">{{'admin.registries.schema.fields.table.scopenote' | translate}}</th>
|
||||||
</tr>
|
</tr>
|
||||||
@@ -39,6 +40,7 @@
|
|||||||
(change)="selectMetadataField(field, $event)">
|
(change)="selectMetadataField(field, $event)">
|
||||||
</label>
|
</label>
|
||||||
</td>
|
</td>
|
||||||
|
<td class="selectable-row" (click)="editField(field)">{{field.id}}</td>
|
||||||
<td class="selectable-row" (click)="editField(field)">{{schema?.prefix}}.{{field.element}}<label *ngIf="field.qualifier">.</label>{{field.qualifier}}</td>
|
<td class="selectable-row" (click)="editField(field)">{{schema?.prefix}}.{{field.element}}<label *ngIf="field.qualifier">.</label>{{field.qualifier}}</td>
|
||||||
<td class="selectable-row" (click)="editField(field)">{{field.scopeNote}}</td>
|
<td class="selectable-row" (click)="editField(field)">{{field.scopeNote}}</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
@@ -23,11 +23,8 @@ import { MetadataSchema } from '../../../core/metadata/metadata-schema.model';
|
|||||||
import { MetadataField } from '../../../core/metadata/metadata-field.model';
|
import { MetadataField } from '../../../core/metadata/metadata-field.model';
|
||||||
import { createSuccessfulRemoteDataObject$ } from '../../../shared/remote-data.utils';
|
import { createSuccessfulRemoteDataObject$ } from '../../../shared/remote-data.utils';
|
||||||
import { VarDirective } from '../../../shared/utils/var.directive';
|
import { VarDirective } from '../../../shared/utils/var.directive';
|
||||||
import { PaginationComponentOptions } from '../../../shared/pagination/pagination-component-options.model';
|
|
||||||
import { SortDirection, SortOptions } from '../../../core/cache/models/sort-options.model';
|
|
||||||
import { PaginationService } from '../../../core/pagination/pagination.service';
|
import { PaginationService } from '../../../core/pagination/pagination.service';
|
||||||
import { PaginationServiceStub } from '../../../shared/testing/pagination-service.stub';
|
import { PaginationServiceStub } from '../../../shared/testing/pagination-service.stub';
|
||||||
import { FindListOptions } from '../../../core/data/find-list-options.model';
|
|
||||||
|
|
||||||
describe('MetadataSchemaComponent', () => {
|
describe('MetadataSchemaComponent', () => {
|
||||||
let comp: MetadataSchemaComponent;
|
let comp: MetadataSchemaComponent;
|
||||||
@@ -169,10 +166,10 @@ describe('MetadataSchemaComponent', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('should contain the correct fields', () => {
|
it('should contain the correct fields', () => {
|
||||||
const editorField: HTMLElement = fixture.debugElement.query(By.css('#metadata-fields tr:nth-child(1) td:nth-child(2)')).nativeElement;
|
const editorField: HTMLElement = fixture.debugElement.query(By.css('#metadata-fields tr:nth-child(1) td:nth-child(3)')).nativeElement;
|
||||||
expect(editorField.textContent).toBe('mock.contributor.editor');
|
expect(editorField.textContent).toBe('mock.contributor.editor');
|
||||||
|
|
||||||
const illustratorField: HTMLElement = fixture.debugElement.query(By.css('#metadata-fields tr:nth-child(2) td:nth-child(2)')).nativeElement;
|
const illustratorField: HTMLElement = fixture.debugElement.query(By.css('#metadata-fields tr:nth-child(2) td:nth-child(3)')).nativeElement;
|
||||||
expect(illustratorField.textContent).toBe('mock.contributor.illustrator');
|
expect(illustratorField.textContent).toBe('mock.contributor.illustrator');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@@ -2,7 +2,7 @@ import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing';
|
|||||||
|
|
||||||
import { MenuService } from '../../../shared/menu/menu.service';
|
import { MenuService } from '../../../shared/menu/menu.service';
|
||||||
import { MenuServiceStub } from '../../../shared/testing/menu-service.stub';
|
import { MenuServiceStub } from '../../../shared/testing/menu-service.stub';
|
||||||
import { CSSVariableService } from '../../../shared/sass-helper/sass-helper.service';
|
import { CSSVariableService } from '../../../shared/sass-helper/css-variable.service';
|
||||||
import { CSSVariableServiceStub } from '../../../shared/testing/css-variable-service.stub';
|
import { CSSVariableServiceStub } from '../../../shared/testing/css-variable-service.stub';
|
||||||
import { Component } from '@angular/core';
|
import { Component } from '@angular/core';
|
||||||
import { NoopAnimationsModule } from '@angular/platform-browser/animations';
|
import { NoopAnimationsModule } from '@angular/platform-browser/animations';
|
||||||
|
@@ -6,7 +6,7 @@ import { ScriptDataService } from '../../core/data/processes/script-data.service
|
|||||||
import { AdminSidebarComponent } from './admin-sidebar.component';
|
import { AdminSidebarComponent } from './admin-sidebar.component';
|
||||||
import { MenuService } from '../../shared/menu/menu.service';
|
import { MenuService } from '../../shared/menu/menu.service';
|
||||||
import { MenuServiceStub } from '../../shared/testing/menu-service.stub';
|
import { MenuServiceStub } from '../../shared/testing/menu-service.stub';
|
||||||
import { CSSVariableService } from '../../shared/sass-helper/sass-helper.service';
|
import { CSSVariableService } from '../../shared/sass-helper/css-variable.service';
|
||||||
import { CSSVariableServiceStub } from '../../shared/testing/css-variable-service.stub';
|
import { CSSVariableServiceStub } from '../../shared/testing/css-variable-service.stub';
|
||||||
import { AuthServiceStub } from '../../shared/testing/auth-service.stub';
|
import { AuthServiceStub } from '../../shared/testing/auth-service.stub';
|
||||||
import { AuthService } from '../../core/auth/auth.service';
|
import { AuthService } from '../../core/auth/auth.service';
|
||||||
@@ -16,7 +16,6 @@ import { NgbModal } from '@ng-bootstrap/ng-bootstrap';
|
|||||||
import { RouterTestingModule } from '@angular/router/testing';
|
import { RouterTestingModule } from '@angular/router/testing';
|
||||||
import { ActivatedRoute } from '@angular/router';
|
import { ActivatedRoute } from '@angular/router';
|
||||||
import { AuthorizationDataService } from '../../core/data/feature-authorization/authorization-data.service';
|
import { AuthorizationDataService } from '../../core/data/feature-authorization/authorization-data.service';
|
||||||
import { FeatureID } from '../../core/data/feature-authorization/feature-id';
|
|
||||||
import createSpy = jasmine.createSpy;
|
import createSpy = jasmine.createSpy;
|
||||||
import { createSuccessfulRemoteDataObject } from '../../shared/remote-data.utils';
|
import { createSuccessfulRemoteDataObject } from '../../shared/remote-data.utils';
|
||||||
import { Item } from '../../core/shared/item.model';
|
import { Item } from '../../core/shared/item.model';
|
||||||
|
@@ -5,7 +5,7 @@ import { AuthService } from '../../core/auth/auth.service';
|
|||||||
import { slideSidebar } from '../../shared/animations/slide';
|
import { slideSidebar } from '../../shared/animations/slide';
|
||||||
import { MenuComponent } from '../../shared/menu/menu.component';
|
import { MenuComponent } from '../../shared/menu/menu.component';
|
||||||
import { MenuService } from '../../shared/menu/menu.service';
|
import { MenuService } from '../../shared/menu/menu.service';
|
||||||
import { CSSVariableService } from '../../shared/sass-helper/sass-helper.service';
|
import { CSSVariableService } from '../../shared/sass-helper/css-variable.service';
|
||||||
import { AuthorizationDataService } from '../../core/data/feature-authorization/authorization-data.service';
|
import { AuthorizationDataService } from '../../core/data/feature-authorization/authorization-data.service';
|
||||||
import { MenuID } from '../../shared/menu/menu-id.model';
|
import { MenuID } from '../../shared/menu/menu-id.model';
|
||||||
import { ActivatedRoute } from '@angular/router';
|
import { ActivatedRoute } from '@angular/router';
|
||||||
@@ -69,7 +69,7 @@ export class AdminSidebarComponent extends MenuComponent implements OnInit {
|
|||||||
*/
|
*/
|
||||||
ngOnInit(): void {
|
ngOnInit(): void {
|
||||||
super.ngOnInit();
|
super.ngOnInit();
|
||||||
this.sidebarWidth = this.variableService.getVariable('sidebarItemsWidth');
|
this.sidebarWidth = this.variableService.getVariable('--ds-sidebar-items-width');
|
||||||
this.authService.isAuthenticated()
|
this.authService.isAuthenticated()
|
||||||
.subscribe((loggedIn: boolean) => {
|
.subscribe((loggedIn: boolean) => {
|
||||||
if (loggedIn) {
|
if (loggedIn) {
|
||||||
|
@@ -3,7 +3,7 @@ import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing';
|
|||||||
import { ExpandableAdminSidebarSectionComponent } from './expandable-admin-sidebar-section.component';
|
import { ExpandableAdminSidebarSectionComponent } from './expandable-admin-sidebar-section.component';
|
||||||
import { MenuService } from '../../../shared/menu/menu.service';
|
import { MenuService } from '../../../shared/menu/menu.service';
|
||||||
import { MenuServiceStub } from '../../../shared/testing/menu-service.stub';
|
import { MenuServiceStub } from '../../../shared/testing/menu-service.stub';
|
||||||
import { CSSVariableService } from '../../../shared/sass-helper/sass-helper.service';
|
import { CSSVariableService } from '../../../shared/sass-helper/css-variable.service';
|
||||||
import { CSSVariableServiceStub } from '../../../shared/testing/css-variable-service.stub';
|
import { CSSVariableServiceStub } from '../../../shared/testing/css-variable-service.stub';
|
||||||
import { of as observableOf } from 'rxjs';
|
import { of as observableOf } from 'rxjs';
|
||||||
import { Component } from '@angular/core';
|
import { Component } from '@angular/core';
|
||||||
|
@@ -2,7 +2,7 @@ import { Component, Inject, Injector, OnInit } from '@angular/core';
|
|||||||
import { rotate } from '../../../shared/animations/rotate';
|
import { rotate } from '../../../shared/animations/rotate';
|
||||||
import { AdminSidebarSectionComponent } from '../admin-sidebar-section/admin-sidebar-section.component';
|
import { AdminSidebarSectionComponent } from '../admin-sidebar-section/admin-sidebar-section.component';
|
||||||
import { slide } from '../../../shared/animations/slide';
|
import { slide } from '../../../shared/animations/slide';
|
||||||
import { CSSVariableService } from '../../../shared/sass-helper/sass-helper.service';
|
import { CSSVariableService } from '../../../shared/sass-helper/css-variable.service';
|
||||||
import { bgColor } from '../../../shared/animations/bgColor';
|
import { bgColor } from '../../../shared/animations/bgColor';
|
||||||
import { MenuService } from '../../../shared/menu/menu.service';
|
import { MenuService } from '../../../shared/menu/menu.service';
|
||||||
import { combineLatest as combineLatestObservable, Observable } from 'rxjs';
|
import { combineLatest as combineLatestObservable, Observable } from 'rxjs';
|
||||||
@@ -65,7 +65,7 @@ export class ExpandableAdminSidebarSectionComponent extends AdminSidebarSectionC
|
|||||||
*/
|
*/
|
||||||
ngOnInit(): void {
|
ngOnInit(): void {
|
||||||
super.ngOnInit();
|
super.ngOnInit();
|
||||||
this.sidebarActiveBg = this.variableService.getVariable('adminSidebarActiveBg');
|
this.sidebarActiveBg = this.variableService.getVariable('--ds-admin-sidebar-active-bg');
|
||||||
this.sidebarCollapsed = this.menuService.isMenuCollapsed(this.menuID);
|
this.sidebarCollapsed = this.menuService.isMenuCollapsed(this.menuID);
|
||||||
this.sidebarPreviewCollapsed = this.menuService.isMenuPreviewCollapsed(this.menuID);
|
this.sidebarPreviewCollapsed = this.menuService.isMenuPreviewCollapsed(this.menuID);
|
||||||
this.expanded = combineLatestObservable(this.active, this.sidebarCollapsed, this.sidebarPreviewCollapsed)
|
this.expanded = combineLatestObservable(this.active, this.sidebarCollapsed, this.sidebarPreviewCollapsed)
|
||||||
|
@@ -10,6 +10,7 @@ import { AdminSearchModule } from './admin-search-page/admin-search.module';
|
|||||||
import { AdminSidebarSectionComponent } from './admin-sidebar/admin-sidebar-section/admin-sidebar-section.component';
|
import { AdminSidebarSectionComponent } from './admin-sidebar/admin-sidebar-section/admin-sidebar-section.component';
|
||||||
import { ExpandableAdminSidebarSectionComponent } from './admin-sidebar/expandable-admin-sidebar-section/expandable-admin-sidebar-section.component';
|
import { ExpandableAdminSidebarSectionComponent } from './admin-sidebar/expandable-admin-sidebar-section/expandable-admin-sidebar-section.component';
|
||||||
import { BatchImportPageComponent } from './admin-import-batch-page/batch-import-page.component';
|
import { BatchImportPageComponent } from './admin-import-batch-page/batch-import-page.component';
|
||||||
|
import { UploadModule } from '../shared/upload/upload.module';
|
||||||
|
|
||||||
const ENTRY_COMPONENTS = [
|
const ENTRY_COMPONENTS = [
|
||||||
// put only entry components that use custom decorator
|
// put only entry components that use custom decorator
|
||||||
@@ -25,7 +26,8 @@ const ENTRY_COMPONENTS = [
|
|||||||
AccessControlModule,
|
AccessControlModule,
|
||||||
AdminSearchModule.withEntryComponents(),
|
AdminSearchModule.withEntryComponents(),
|
||||||
AdminWorkflowModuleModule.withEntryComponents(),
|
AdminWorkflowModuleModule.withEntryComponents(),
|
||||||
SharedModule
|
SharedModule,
|
||||||
|
UploadModule,
|
||||||
],
|
],
|
||||||
declarations: [
|
declarations: [
|
||||||
AdminCurationTasksComponent,
|
AdminCurationTasksComponent,
|
||||||
|
@@ -18,7 +18,7 @@ import { AngularticsProviderMock } from './shared/mocks/angulartics-provider.ser
|
|||||||
import { AuthServiceMock } from './shared/mocks/auth.service.mock';
|
import { AuthServiceMock } from './shared/mocks/auth.service.mock';
|
||||||
import { AuthService } from './core/auth/auth.service';
|
import { AuthService } from './core/auth/auth.service';
|
||||||
import { MenuService } from './shared/menu/menu.service';
|
import { MenuService } from './shared/menu/menu.service';
|
||||||
import { CSSVariableService } from './shared/sass-helper/sass-helper.service';
|
import { CSSVariableService } from './shared/sass-helper/css-variable.service';
|
||||||
import { CSSVariableServiceStub } from './shared/testing/css-variable-service.stub';
|
import { CSSVariableServiceStub } from './shared/testing/css-variable-service.stub';
|
||||||
import { MenuServiceStub } from './shared/testing/menu-service.stub';
|
import { MenuServiceStub } from './shared/testing/menu-service.stub';
|
||||||
import { HostWindowService } from './shared/host-window.service';
|
import { HostWindowService } from './shared/host-window.service';
|
||||||
|
@@ -25,13 +25,12 @@ import { HostWindowState } from './shared/search/host-window.reducer';
|
|||||||
import { NativeWindowRef, NativeWindowService } from './core/services/window.service';
|
import { NativeWindowRef, NativeWindowService } from './core/services/window.service';
|
||||||
import { isAuthenticationBlocking } from './core/auth/selectors';
|
import { isAuthenticationBlocking } from './core/auth/selectors';
|
||||||
import { AuthService } from './core/auth/auth.service';
|
import { AuthService } from './core/auth/auth.service';
|
||||||
import { CSSVariableService } from './shared/sass-helper/sass-helper.service';
|
import { CSSVariableService } from './shared/sass-helper/css-variable.service';
|
||||||
import { environment } from '../environments/environment';
|
import { environment } from '../environments/environment';
|
||||||
import { models } from './core/core.module';
|
import { models } from './core/core.module';
|
||||||
import { ThemeService } from './shared/theme-support/theme.service';
|
import { ThemeService } from './shared/theme-support/theme.service';
|
||||||
import { IdleModalComponent } from './shared/idle-modal/idle-modal.component';
|
import { IdleModalComponent } from './shared/idle-modal/idle-modal.component';
|
||||||
import { distinctNext } from './core/shared/distinct-next';
|
import { distinctNext } from './core/shared/distinct-next';
|
||||||
import { ModalBeforeDismiss } from './shared/interfaces/modal-before-dismiss.interface';
|
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'ds-app',
|
selector: 'ds-app',
|
||||||
@@ -110,18 +109,8 @@ export class AppComponent implements OnInit, AfterViewInit {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private storeCSSVariables() {
|
private storeCSSVariables() {
|
||||||
this.cssService.addCSSVariable('xlMin', '1200px');
|
this.cssService.clearCSSVariables();
|
||||||
this.cssService.addCSSVariable('mdMin', '768px');
|
this.cssService.addCSSVariables(this.cssService.getCSSVariablesFromStylesheets(this.document));
|
||||||
this.cssService.addCSSVariable('lgMin', '576px');
|
|
||||||
this.cssService.addCSSVariable('smMin', '0');
|
|
||||||
this.cssService.addCSSVariable('adminSidebarActiveBg', '#0f1b28');
|
|
||||||
this.cssService.addCSSVariable('sidebarItemsWidth', '250px');
|
|
||||||
this.cssService.addCSSVariable('collapsedSidebarWidth', '53.234px');
|
|
||||||
this.cssService.addCSSVariable('totalSidebarWidth', '303.234px');
|
|
||||||
// const vars = variables.locals || {};
|
|
||||||
// Object.keys(vars).forEach((name: string) => {
|
|
||||||
// this.cssService.addCSSVariable(name, vars[name]);
|
|
||||||
// })
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ngAfterViewInit() {
|
ngAfterViewInit() {
|
||||||
|
@@ -1,14 +1,12 @@
|
|||||||
import { APP_BASE_HREF, CommonModule, DOCUMENT } from '@angular/common';
|
import { APP_BASE_HREF, CommonModule, DOCUMENT } from '@angular/common';
|
||||||
import { HTTP_INTERCEPTORS, HttpClientModule } from '@angular/common/http';
|
import { HTTP_INTERCEPTORS, HttpClientModule } from '@angular/common/http';
|
||||||
import { NgModule } from '@angular/core';
|
import { NgModule } from '@angular/core';
|
||||||
import { AbstractControl } from '@angular/forms';
|
|
||||||
import { BrowserModule } from '@angular/platform-browser';
|
import { BrowserModule } from '@angular/platform-browser';
|
||||||
|
|
||||||
import { NgbModule } from '@ng-bootstrap/ng-bootstrap';
|
import { NgbModule } from '@ng-bootstrap/ng-bootstrap';
|
||||||
import { EffectsModule } from '@ngrx/effects';
|
import { EffectsModule } from '@ngrx/effects';
|
||||||
import { RouterStateSerializer, StoreRouterConnectingModule } from '@ngrx/router-store';
|
import { RouterStateSerializer, StoreRouterConnectingModule } from '@ngrx/router-store';
|
||||||
import { MetaReducer, StoreModule, USER_PROVIDED_META_REDUCERS } from '@ngrx/store';
|
import { MetaReducer, StoreModule, USER_PROVIDED_META_REDUCERS } from '@ngrx/store';
|
||||||
import { DYNAMIC_ERROR_MESSAGES_MATCHER, DYNAMIC_MATCHER_PROVIDERS, DynamicErrorMessagesMatcher } from '@ng-dynamic-forms/core';
|
|
||||||
import { TranslateModule } from '@ngx-translate/core';
|
import { TranslateModule } from '@ngx-translate/core';
|
||||||
import { ScrollToModule } from '@nicky-lenaers/ngx-scroll-to';
|
import { ScrollToModule } from '@nicky-lenaers/ngx-scroll-to';
|
||||||
import { AppRoutingModule } from './app-routing.module';
|
import { AppRoutingModule } from './app-routing.module';
|
||||||
@@ -28,7 +26,6 @@ import { XsrfInterceptor } from './core/xsrf/xsrf.interceptor';
|
|||||||
import { LogInterceptor } from './core/log/log.interceptor';
|
import { LogInterceptor } from './core/log/log.interceptor';
|
||||||
import { EagerThemesModule } from '../themes/eager-themes.module';
|
import { EagerThemesModule } from '../themes/eager-themes.module';
|
||||||
import { APP_CONFIG, AppConfig } from '../config/app-config.interface';
|
import { APP_CONFIG, AppConfig } from '../config/app-config.interface';
|
||||||
import { NgxMaskModule } from 'ngx-mask';
|
|
||||||
import { StoreDevModules } from '../config/store/devtools';
|
import { StoreDevModules } from '../config/store/devtools';
|
||||||
import { RootModule } from './root.module';
|
import { RootModule } from './root.module';
|
||||||
|
|
||||||
@@ -46,14 +43,6 @@ export function getMetaReducers(appConfig: AppConfig): MetaReducer<AppState>[] {
|
|||||||
return appConfig.debug ? [...appMetaReducers, ...debugMetaReducers] : appMetaReducers;
|
return appConfig.debug ? [...appMetaReducers, ...debugMetaReducers] : appMetaReducers;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Condition for displaying error messages on email form field
|
|
||||||
*/
|
|
||||||
export const ValidateEmailErrorStateMatcher: DynamicErrorMessagesMatcher =
|
|
||||||
(control: AbstractControl, model: any, hasFocus: boolean) => {
|
|
||||||
return (control.touched && !hasFocus) || (control.errors?.emailTaken && hasFocus);
|
|
||||||
};
|
|
||||||
|
|
||||||
const IMPORTS = [
|
const IMPORTS = [
|
||||||
CommonModule,
|
CommonModule,
|
||||||
SharedModule,
|
SharedModule,
|
||||||
@@ -64,7 +53,6 @@ const IMPORTS = [
|
|||||||
ScrollToModule.forRoot(),
|
ScrollToModule.forRoot(),
|
||||||
NgbModule,
|
NgbModule,
|
||||||
TranslateModule.forRoot(),
|
TranslateModule.forRoot(),
|
||||||
NgxMaskModule.forRoot(),
|
|
||||||
EffectsModule.forRoot(appEffects),
|
EffectsModule.forRoot(appEffects),
|
||||||
StoreModule.forRoot(appReducers, storeModuleConfig),
|
StoreModule.forRoot(appReducers, storeModuleConfig),
|
||||||
StoreRouterConnectingModule.forRoot(),
|
StoreRouterConnectingModule.forRoot(),
|
||||||
@@ -113,11 +101,6 @@ const PROVIDERS = [
|
|||||||
useClass: LogInterceptor,
|
useClass: LogInterceptor,
|
||||||
multi: true
|
multi: true
|
||||||
},
|
},
|
||||||
{
|
|
||||||
provide: DYNAMIC_ERROR_MESSAGES_MATCHER,
|
|
||||||
useValue: ValidateEmailErrorStateMatcher
|
|
||||||
},
|
|
||||||
...DYNAMIC_MATCHER_PROVIDERS,
|
|
||||||
];
|
];
|
||||||
|
|
||||||
const DECLARATIONS = [
|
const DECLARATIONS = [
|
||||||
|
@@ -1,4 +1,4 @@
|
|||||||
import * as fromRouter from '@ngrx/router-store';
|
import { routerReducer, RouterReducerState } from '@ngrx/router-store';
|
||||||
import { ActionReducerMap, createSelector, MemoizedSelector } from '@ngrx/store';
|
import { ActionReducerMap, createSelector, MemoizedSelector } from '@ngrx/store';
|
||||||
import {
|
import {
|
||||||
ePeopleRegistryReducer,
|
ePeopleRegistryReducer,
|
||||||
@@ -35,7 +35,7 @@ import {
|
|||||||
ObjectSelectionListState,
|
ObjectSelectionListState,
|
||||||
objectSelectionReducer
|
objectSelectionReducer
|
||||||
} from './shared/object-select/object-select.reducer';
|
} from './shared/object-select/object-select.reducer';
|
||||||
import { cssVariablesReducer, CSSVariablesState } from './shared/sass-helper/sass-helper.reducer';
|
import { cssVariablesReducer, CSSVariablesState } from './shared/sass-helper/css-variable.reducer';
|
||||||
|
|
||||||
import { hostWindowReducer, HostWindowState } from './shared/search/host-window.reducer';
|
import { hostWindowReducer, HostWindowState } from './shared/search/host-window.reducer';
|
||||||
import {
|
import {
|
||||||
@@ -53,7 +53,7 @@ import { MenusState } from './shared/menu/menus-state.model';
|
|||||||
import { correlationIdReducer } from './correlation-id/correlation-id.reducer';
|
import { correlationIdReducer } from './correlation-id/correlation-id.reducer';
|
||||||
|
|
||||||
export interface AppState {
|
export interface AppState {
|
||||||
router: fromRouter.RouterReducerState;
|
router: RouterReducerState;
|
||||||
hostWindow: HostWindowState;
|
hostWindow: HostWindowState;
|
||||||
forms: FormState;
|
forms: FormState;
|
||||||
metadataRegistry: MetadataRegistryState;
|
metadataRegistry: MetadataRegistryState;
|
||||||
@@ -75,7 +75,7 @@ export interface AppState {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export const appReducers: ActionReducerMap<AppState> = {
|
export const appReducers: ActionReducerMap<AppState> = {
|
||||||
router: fromRouter.routerReducer,
|
router: routerReducer,
|
||||||
hostWindow: hostWindowReducer,
|
hostWindow: hostWindowReducer,
|
||||||
forms: formReducer,
|
forms: formReducer,
|
||||||
metadataRegistry: metadataRegistryReducer,
|
metadataRegistry: metadataRegistryReducer,
|
||||||
|
@@ -26,7 +26,7 @@ import {
|
|||||||
import { FormGroup } from '@angular/forms';
|
import { FormGroup } from '@angular/forms';
|
||||||
import { TranslateService } from '@ngx-translate/core';
|
import { TranslateService } from '@ngx-translate/core';
|
||||||
import { DynamicCustomSwitchModel } from '../../shared/form/builder/ds-dynamic-form-ui/models/custom-switch/custom-switch.model';
|
import { DynamicCustomSwitchModel } from '../../shared/form/builder/ds-dynamic-form-ui/models/custom-switch/custom-switch.model';
|
||||||
import { cloneDeep } from 'lodash';
|
import cloneDeep from 'lodash/cloneDeep';
|
||||||
import { BitstreamDataService } from '../../core/data/bitstream-data.service';
|
import { BitstreamDataService } from '../../core/data/bitstream-data.service';
|
||||||
import {
|
import {
|
||||||
getAllSucceededRemoteDataPayload,
|
getAllSucceededRemoteDataPayload,
|
||||||
|
@@ -1,5 +1,5 @@
|
|||||||
import { LegacyBitstreamUrlResolver } from './legacy-bitstream-url.resolver';
|
import { LegacyBitstreamUrlResolver } from './legacy-bitstream-url.resolver';
|
||||||
import { of as observableOf, EMPTY } from 'rxjs';
|
import { EMPTY } from 'rxjs';
|
||||||
import { BitstreamDataService } from '../core/data/bitstream-data.service';
|
import { BitstreamDataService } from '../core/data/bitstream-data.service';
|
||||||
import { RemoteData } from '../core/data/remote-data';
|
import { RemoteData } from '../core/data/remote-data';
|
||||||
import { TestScheduler } from 'rxjs/testing';
|
import { TestScheduler } from 'rxjs/testing';
|
||||||
|
@@ -10,7 +10,7 @@
|
|||||||
</nav>
|
</nav>
|
||||||
|
|
||||||
<ng-template #breadcrumb let-text="text" let-url="url">
|
<ng-template #breadcrumb let-text="text" let-url="url">
|
||||||
<li class="breadcrumb-item"><div class="breadcrumb-item-limiter"><a [routerLink]="url" class="text-truncate">{{text | translate}}</a></div></li>
|
<li class="breadcrumb-item"><div class="breadcrumb-item-limiter"><a [routerLink]="url" class="text-truncate" [ngbTooltip]="text | translate" placement="bottom" >{{text | translate}}</a></div></li>
|
||||||
</ng-template>
|
</ng-template>
|
||||||
|
|
||||||
<ng-template #activeBreadcrumb let-text="text">
|
<ng-template #activeBreadcrumb let-text="text">
|
||||||
|
@@ -1,7 +1,6 @@
|
|||||||
import { first } from 'rxjs/operators';
|
import { first } from 'rxjs/operators';
|
||||||
import { BrowseByGuard } from './browse-by-guard';
|
import { BrowseByGuard } from './browse-by-guard';
|
||||||
import { of as observableOf } from 'rxjs';
|
import { of as observableOf } from 'rxjs';
|
||||||
import { BrowseDefinitionDataService } from '../core/browse/browse-definition-data.service';
|
|
||||||
import { createSuccessfulRemoteDataObject$ } from '../shared/remote-data.utils';
|
import { createSuccessfulRemoteDataObject$ } from '../shared/remote-data.utils';
|
||||||
import { BrowseDefinition } from '../core/shared/browse-definition.model';
|
import { BrowseDefinition } from '../core/shared/browse-definition.model';
|
||||||
import { BrowseByDataType } from './browse-by-switcher/browse-by-decorator';
|
import { BrowseByDataType } from './browse-by-switcher/browse-by-decorator';
|
||||||
|
@@ -1,5 +1,6 @@
|
|||||||
import { DynamicFormControlModel, DynamicInputModel, DynamicTextAreaModel } from '@ng-dynamic-forms/core';
|
import { DynamicFormControlModel, DynamicInputModel, DynamicTextAreaModel } from '@ng-dynamic-forms/core';
|
||||||
import { DynamicSelectModelConfig } from '@ng-dynamic-forms/core/lib/model/select/dynamic-select.model';
|
import { DynamicSelectModelConfig } from '@ng-dynamic-forms/core/lib/model/select/dynamic-select.model';
|
||||||
|
import { environment } from '../../../environments/environment';
|
||||||
|
|
||||||
export const collectionFormEntityTypeSelectionConfig: DynamicSelectModelConfig<string> = {
|
export const collectionFormEntityTypeSelectionConfig: DynamicSelectModelConfig<string> = {
|
||||||
id: 'entityType',
|
id: 'entityType',
|
||||||
@@ -26,21 +27,26 @@ export const collectionFormModels: DynamicFormControlModel[] = [
|
|||||||
new DynamicTextAreaModel({
|
new DynamicTextAreaModel({
|
||||||
id: 'description',
|
id: 'description',
|
||||||
name: 'dc.description',
|
name: 'dc.description',
|
||||||
|
spellCheck: environment.form.spellCheck,
|
||||||
}),
|
}),
|
||||||
new DynamicTextAreaModel({
|
new DynamicTextAreaModel({
|
||||||
id: 'abstract',
|
id: 'abstract',
|
||||||
name: 'dc.description.abstract',
|
name: 'dc.description.abstract',
|
||||||
|
spellCheck: environment.form.spellCheck,
|
||||||
}),
|
}),
|
||||||
new DynamicTextAreaModel({
|
new DynamicTextAreaModel({
|
||||||
id: 'rights',
|
id: 'rights',
|
||||||
name: 'dc.rights',
|
name: 'dc.rights',
|
||||||
|
spellCheck: environment.form.spellCheck,
|
||||||
}),
|
}),
|
||||||
new DynamicTextAreaModel({
|
new DynamicTextAreaModel({
|
||||||
id: 'tableofcontents',
|
id: 'tableofcontents',
|
||||||
name: 'dc.description.tableofcontents',
|
name: 'dc.description.tableofcontents',
|
||||||
|
spellCheck: environment.form.spellCheck,
|
||||||
}),
|
}),
|
||||||
new DynamicTextAreaModel({
|
new DynamicTextAreaModel({
|
||||||
id: 'license',
|
id: 'license',
|
||||||
name: 'dc.rights.license',
|
name: 'dc.rights.license',
|
||||||
|
spellCheck: environment.form.spellCheck,
|
||||||
})
|
})
|
||||||
];
|
];
|
||||||
|
@@ -16,7 +16,7 @@ import { Collection } from '../../core/shared/collection.model';
|
|||||||
import { RemoteData } from '../../core/data/remote-data';
|
import { RemoteData } from '../../core/data/remote-data';
|
||||||
import { PaginationComponentOptions } from '../../shared/pagination/pagination-component-options.model';
|
import { PaginationComponentOptions } from '../../shared/pagination/pagination-component-options.model';
|
||||||
import { SortDirection, SortOptions } from '../../core/cache/models/sort-options.model';
|
import { SortDirection, SortOptions } from '../../core/cache/models/sort-options.model';
|
||||||
import { ChangeDetectionStrategy, EventEmitter } from '@angular/core';
|
import { EventEmitter } from '@angular/core';
|
||||||
import { HostWindowService } from '../../shared/host-window.service';
|
import { HostWindowService } from '../../shared/host-window.service';
|
||||||
import { HostWindowServiceStub } from '../../shared/testing/host-window-service.stub';
|
import { HostWindowServiceStub } from '../../shared/testing/host-window-service.stub';
|
||||||
import { By } from '@angular/platform-browser';
|
import { By } from '@angular/platform-browser';
|
||||||
@@ -41,7 +41,7 @@ import {
|
|||||||
} from '../../shared/remote-data.utils';
|
} from '../../shared/remote-data.utils';
|
||||||
import { createPaginatedList } from '../../shared/testing/utils.test';
|
import { createPaginatedList } from '../../shared/testing/utils.test';
|
||||||
import { AuthorizationDataService } from '../../core/data/feature-authorization/authorization-data.service';
|
import { AuthorizationDataService } from '../../core/data/feature-authorization/authorization-data.service';
|
||||||
import { MyDSpacePageComponent, SEARCH_CONFIG_SERVICE } from '../../my-dspace-page/my-dspace-page.component';
|
import { SEARCH_CONFIG_SERVICE } from '../../my-dspace-page/my-dspace-page.component';
|
||||||
import { SearchConfigurationServiceStub } from '../../shared/testing/search-configuration-service.stub';
|
import { SearchConfigurationServiceStub } from '../../shared/testing/search-configuration-service.stub';
|
||||||
import { GroupDataService } from '../../core/eperson/group-data.service';
|
import { GroupDataService } from '../../core/eperson/group-data.service';
|
||||||
import { LinkHeadService } from '../../core/services/link-head.service';
|
import { LinkHeadService } from '../../core/services/link-head.service';
|
||||||
|
@@ -72,6 +72,7 @@ import { MenuItemType } from '../shared/menu/menu-item-type.model';
|
|||||||
id: 'statistics_collection_:id',
|
id: 'statistics_collection_:id',
|
||||||
active: true,
|
active: true,
|
||||||
visible: true,
|
visible: true,
|
||||||
|
index: 2,
|
||||||
model: {
|
model: {
|
||||||
type: MenuItemType.LINK,
|
type: MenuItemType.LINK,
|
||||||
text: 'menu.section.statistics',
|
text: 'menu.section.statistics',
|
||||||
|
@@ -25,7 +25,7 @@ import { ComcolModule } from '../shared/comcol/comcol.module';
|
|||||||
StatisticsModule.forRoot(),
|
StatisticsModule.forRoot(),
|
||||||
EditItemPageModule,
|
EditItemPageModule,
|
||||||
CollectionFormModule,
|
CollectionFormModule,
|
||||||
ComcolModule
|
ComcolModule,
|
||||||
],
|
],
|
||||||
declarations: [
|
declarations: [
|
||||||
CollectionPageComponent,
|
CollectionPageComponent,
|
||||||
@@ -38,7 +38,7 @@ import { ComcolModule } from '../shared/comcol/comcol.module';
|
|||||||
],
|
],
|
||||||
providers: [
|
providers: [
|
||||||
SearchService,
|
SearchService,
|
||||||
]
|
],
|
||||||
})
|
})
|
||||||
export class CollectionPageModule {
|
export class CollectionPageModule {
|
||||||
|
|
||||||
|
@@ -11,11 +11,11 @@
|
|||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<span class="font-weight-bold">{{'collection.source.controls.harvest.last' | translate}}</span>
|
<span class="font-weight-bold">{{'collection.source.controls.harvest.last' | translate}}</span>
|
||||||
<span>{{contentSource?.message ? contentSource?.message : 'collection.source.controls.harvest.no-information'|translate }}</span>
|
<span>{{contentSource?.lastHarvested ? contentSource?.lastHarvested : 'collection.source.controls.harvest.no-information'|translate }}</span>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<span class="font-weight-bold">{{'collection.source.controls.harvest.message' | translate}}</span>
|
<span class="font-weight-bold">{{'collection.source.controls.harvest.message' | translate}}</span>
|
||||||
<span>{{contentSource?.lastHarvested ? contentSource?.lastHarvested : 'collection.source.controls.harvest.no-information'|translate }}</span>
|
<span>{{contentSource?.message ? contentSource?.message: 'collection.source.controls.harvest.no-information'|translate }}</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<button *ngIf="!(testConfigRunning$ |async)" class="btn btn-secondary"
|
<button *ngIf="!(testConfigRunning$ |async)" class="btn btn-secondary"
|
||||||
|
@@ -8,8 +8,7 @@ import {
|
|||||||
DynamicInputModel,
|
DynamicInputModel,
|
||||||
DynamicOptionControlModel,
|
DynamicOptionControlModel,
|
||||||
DynamicRadioGroupModel,
|
DynamicRadioGroupModel,
|
||||||
DynamicSelectModel,
|
DynamicSelectModel
|
||||||
DynamicTextAreaModel
|
|
||||||
} from '@ng-dynamic-forms/core';
|
} from '@ng-dynamic-forms/core';
|
||||||
import { Location } from '@angular/common';
|
import { Location } from '@angular/common';
|
||||||
import { TranslateService } from '@ngx-translate/core';
|
import { TranslateService } from '@ngx-translate/core';
|
||||||
@@ -23,7 +22,7 @@ import { RemoteData } from '../../../core/data/remote-data';
|
|||||||
import { Collection } from '../../../core/shared/collection.model';
|
import { Collection } from '../../../core/shared/collection.model';
|
||||||
import { first, map, switchMap, take } from 'rxjs/operators';
|
import { first, map, switchMap, take } from 'rxjs/operators';
|
||||||
import { ActivatedRoute, Router } from '@angular/router';
|
import { ActivatedRoute, Router } from '@angular/router';
|
||||||
import { cloneDeep } from 'lodash';
|
import cloneDeep from 'lodash/cloneDeep';
|
||||||
import { CollectionDataService } from '../../../core/data/collection-data.service';
|
import { CollectionDataService } from '../../../core/data/collection-data.service';
|
||||||
import { getFirstSucceededRemoteData, getFirstCompletedRemoteData } from '../../../core/shared/operators';
|
import { getFirstSucceededRemoteData, getFirstCompletedRemoteData } from '../../../core/shared/operators';
|
||||||
import { MetadataConfig } from '../../../core/shared/metadata-config.model';
|
import { MetadataConfig } from '../../../core/shared/metadata-config.model';
|
||||||
|
@@ -25,7 +25,7 @@ import { ComcolModule } from '../../shared/comcol/comcol.module';
|
|||||||
CollectionFormModule,
|
CollectionFormModule,
|
||||||
ResourcePoliciesModule,
|
ResourcePoliciesModule,
|
||||||
FormModule,
|
FormModule,
|
||||||
ComcolModule
|
ComcolModule,
|
||||||
],
|
],
|
||||||
declarations: [
|
declarations: [
|
||||||
EditCollectionPageComponent,
|
EditCollectionPageComponent,
|
||||||
|
@@ -13,6 +13,7 @@ import { CommunityDataService } from '../../core/data/community-data.service';
|
|||||||
import { AuthService } from '../../core/auth/auth.service';
|
import { AuthService } from '../../core/auth/auth.service';
|
||||||
import { RequestService } from '../../core/data/request.service';
|
import { RequestService } from '../../core/data/request.service';
|
||||||
import { ObjectCacheService } from '../../core/cache/object-cache.service';
|
import { ObjectCacheService } from '../../core/cache/object-cache.service';
|
||||||
|
import { environment } from '../../../environments/environment';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Form used for creating and editing communities
|
* Form used for creating and editing communities
|
||||||
@@ -52,18 +53,22 @@ export class CommunityFormComponent extends ComColFormComponent<Community> {
|
|||||||
new DynamicTextAreaModel({
|
new DynamicTextAreaModel({
|
||||||
id: 'description',
|
id: 'description',
|
||||||
name: 'dc.description',
|
name: 'dc.description',
|
||||||
|
spellCheck: environment.form.spellCheck,
|
||||||
}),
|
}),
|
||||||
new DynamicTextAreaModel({
|
new DynamicTextAreaModel({
|
||||||
id: 'abstract',
|
id: 'abstract',
|
||||||
name: 'dc.description.abstract',
|
name: 'dc.description.abstract',
|
||||||
|
spellCheck: environment.form.spellCheck,
|
||||||
}),
|
}),
|
||||||
new DynamicTextAreaModel({
|
new DynamicTextAreaModel({
|
||||||
id: 'rights',
|
id: 'rights',
|
||||||
name: 'dc.rights',
|
name: 'dc.rights',
|
||||||
|
spellCheck: environment.form.spellCheck,
|
||||||
}),
|
}),
|
||||||
new DynamicTextAreaModel({
|
new DynamicTextAreaModel({
|
||||||
id: 'tableofcontents',
|
id: 'tableofcontents',
|
||||||
name: 'dc.description.tableofcontents',
|
name: 'dc.description.tableofcontents',
|
||||||
|
spellCheck: environment.form.spellCheck,
|
||||||
}),
|
}),
|
||||||
];
|
];
|
||||||
|
|
||||||
|
@@ -55,6 +55,7 @@ import { MenuItemType } from '../shared/menu/menu-item-type.model';
|
|||||||
id: 'statistics_community_:id',
|
id: 'statistics_community_:id',
|
||||||
active: true,
|
active: true,
|
||||||
visible: true,
|
visible: true,
|
||||||
|
index: 2,
|
||||||
model: {
|
model: {
|
||||||
type: MenuItemType.LINK,
|
type: MenuItemType.LINK,
|
||||||
text: 'menu.section.statistics',
|
text: 'menu.section.statistics',
|
||||||
|
@@ -36,7 +36,7 @@ const DECLARATIONS = [CommunityPageComponent,
|
|||||||
CommunityPageRoutingModule,
|
CommunityPageRoutingModule,
|
||||||
StatisticsModule.forRoot(),
|
StatisticsModule.forRoot(),
|
||||||
CommunityFormModule,
|
CommunityFormModule,
|
||||||
ComcolModule
|
ComcolModule,
|
||||||
],
|
],
|
||||||
declarations: [
|
declarations: [
|
||||||
...DECLARATIONS
|
...DECLARATIONS
|
||||||
|
@@ -21,7 +21,7 @@ import { ComcolModule } from '../../shared/comcol/comcol.module';
|
|||||||
EditCommunityPageRoutingModule,
|
EditCommunityPageRoutingModule,
|
||||||
CommunityFormModule,
|
CommunityFormModule,
|
||||||
ComcolModule,
|
ComcolModule,
|
||||||
ResourcePoliciesModule
|
ResourcePoliciesModule,
|
||||||
],
|
],
|
||||||
declarations: [
|
declarations: [
|
||||||
EditCommunityPageComponent,
|
EditCommunityPageComponent,
|
||||||
|
@@ -17,9 +17,6 @@ import { PageInfo } from '../../core/shared/page-info.model';
|
|||||||
import { HostWindowService } from '../../shared/host-window.service';
|
import { HostWindowService } from '../../shared/host-window.service';
|
||||||
import { HostWindowServiceStub } from '../../shared/testing/host-window-service.stub';
|
import { HostWindowServiceStub } from '../../shared/testing/host-window-service.stub';
|
||||||
import { SelectableListService } from '../../shared/object-list/selectable-list/selectable-list.service';
|
import { SelectableListService } from '../../shared/object-list/selectable-list/selectable-list.service';
|
||||||
import { PaginationComponentOptions } from '../../shared/pagination/pagination-component-options.model';
|
|
||||||
import { SortDirection, SortOptions } from '../../core/cache/models/sort-options.model';
|
|
||||||
import { of as observableOf } from 'rxjs';
|
|
||||||
import { PaginationService } from '../../core/pagination/pagination.service';
|
import { PaginationService } from '../../core/pagination/pagination.service';
|
||||||
import { getMockThemeService } from '../../shared/mocks/theme-service.mock';
|
import { getMockThemeService } from '../../shared/mocks/theme-service.mock';
|
||||||
import { ThemeService } from '../../shared/theme-support/theme.service';
|
import { ThemeService } from '../../shared/theme-support/theme.service';
|
||||||
@@ -29,7 +26,6 @@ import { GroupDataService } from '../../core/eperson/group-data.service';
|
|||||||
import { LinkHeadService } from '../../core/services/link-head.service';
|
import { LinkHeadService } from '../../core/services/link-head.service';
|
||||||
import { ConfigurationDataService } from '../../core/data/configuration-data.service';
|
import { ConfigurationDataService } from '../../core/data/configuration-data.service';
|
||||||
import { SearchConfigurationService } from '../../core/shared/search/search-configuration.service';
|
import { SearchConfigurationService } from '../../core/shared/search/search-configuration.service';
|
||||||
import { SearchServiceStub } from '../../shared/testing/search-service.stub';
|
|
||||||
import { ConfigurationProperty } from '../../core/shared/configuration-property.model';
|
import { ConfigurationProperty } from '../../core/shared/configuration-property.model';
|
||||||
import { createPaginatedList } from '../../shared/testing/utils.test';
|
import { createPaginatedList } from '../../shared/testing/utils.test';
|
||||||
import { SearchConfigurationServiceStub } from '../../shared/testing/search-configuration-service.stub';
|
import { SearchConfigurationServiceStub } from '../../shared/testing/search-configuration-service.stub';
|
||||||
|
@@ -17,9 +17,6 @@ import { HostWindowService } from '../../shared/host-window.service';
|
|||||||
import { HostWindowServiceStub } from '../../shared/testing/host-window-service.stub';
|
import { HostWindowServiceStub } from '../../shared/testing/host-window-service.stub';
|
||||||
import { CommunityDataService } from '../../core/data/community-data.service';
|
import { CommunityDataService } from '../../core/data/community-data.service';
|
||||||
import { SelectableListService } from '../../shared/object-list/selectable-list/selectable-list.service';
|
import { SelectableListService } from '../../shared/object-list/selectable-list/selectable-list.service';
|
||||||
import { PaginationComponentOptions } from '../../shared/pagination/pagination-component-options.model';
|
|
||||||
import { SortDirection, SortOptions } from '../../core/cache/models/sort-options.model';
|
|
||||||
import { of as observableOf } from 'rxjs';
|
|
||||||
import { PaginationService } from '../../core/pagination/pagination.service';
|
import { PaginationService } from '../../core/pagination/pagination.service';
|
||||||
import { getMockThemeService } from '../../shared/mocks/theme-service.mock';
|
import { getMockThemeService } from '../../shared/mocks/theme-service.mock';
|
||||||
import { ThemeService } from '../../shared/theme-support/theme.service';
|
import { ThemeService } from '../../shared/theme-support/theme.service';
|
||||||
|
@@ -7,7 +7,6 @@ import { createSelector } from '@ngrx/store';
|
|||||||
* notation packages up all of the exports into a single object.
|
* notation packages up all of the exports into a single object.
|
||||||
*/
|
*/
|
||||||
import { AuthState } from './auth.reducer';
|
import { AuthState } from './auth.reducer';
|
||||||
import { AppState } from '../../app.reducer';
|
|
||||||
import { CoreState } from '../core-state.model';
|
import { CoreState } from '../core-state.model';
|
||||||
import { coreSelector } from '../core.selectors';
|
import { coreSelector } from '../core.selectors';
|
||||||
|
|
||||||
|
@@ -1,3 +1,4 @@
|
|||||||
|
// eslint-disable-next-line import/no-namespace
|
||||||
import * as deepFreeze from 'deep-freeze';
|
import * as deepFreeze from 'deep-freeze';
|
||||||
import { Operation } from 'fast-json-patch';
|
import { Operation } from 'fast-json-patch';
|
||||||
import { Item } from '../shared/item.model';
|
import { Item } from '../shared/item.model';
|
||||||
|
@@ -1,3 +1,4 @@
|
|||||||
|
// eslint-disable-next-line import/no-namespace
|
||||||
import * as deepFreeze from 'deep-freeze';
|
import * as deepFreeze from 'deep-freeze';
|
||||||
import { RemoveFromObjectCacheAction } from './object-cache.actions';
|
import { RemoveFromObjectCacheAction } from './object-cache.actions';
|
||||||
import { serverSyncBufferReducer } from './server-sync-buffer.reducer';
|
import { serverSyncBufferReducer } from './server-sync-buffer.reducer';
|
||||||
|
@@ -2,15 +2,12 @@ import { CommonModule } from '@angular/common';
|
|||||||
import { HttpClient } from '@angular/common/http';
|
import { HttpClient } from '@angular/common/http';
|
||||||
import { ModuleWithProviders, NgModule, Optional, SkipSelf } from '@angular/core';
|
import { ModuleWithProviders, NgModule, Optional, SkipSelf } from '@angular/core';
|
||||||
|
|
||||||
import { DynamicFormLayoutService, DynamicFormService, DynamicFormValidationService } from '@ng-dynamic-forms/core';
|
|
||||||
import { EffectsModule } from '@ngrx/effects';
|
import { EffectsModule } from '@ngrx/effects';
|
||||||
|
|
||||||
import { Action, StoreConfig, StoreModule } from '@ngrx/store';
|
import { Action, StoreConfig, StoreModule } from '@ngrx/store';
|
||||||
import { MyDSpaceGuard } from '../my-dspace-page/my-dspace.guard';
|
import { MyDSpaceGuard } from '../my-dspace-page/my-dspace.guard';
|
||||||
|
|
||||||
import { isNotEmpty } from '../shared/empty.util';
|
import { isNotEmpty } from '../shared/empty.util';
|
||||||
import { FormBuilderService } from '../shared/form/builder/form-builder.service';
|
|
||||||
import { FormService } from '../shared/form/form.service';
|
|
||||||
import { HostWindowService } from '../shared/host-window.service';
|
import { HostWindowService } from '../shared/host-window.service';
|
||||||
import { MenuService } from '../shared/menu/menu.service';
|
import { MenuService } from '../shared/menu/menu.service';
|
||||||
import { EndpointMockingRestService } from '../shared/mocks/dspace-rest/endpoint-mocking-rest.service';
|
import { EndpointMockingRestService } from '../shared/mocks/dspace-rest/endpoint-mocking-rest.service';
|
||||||
@@ -23,10 +20,7 @@ import { NotificationsService } from '../shared/notifications/notifications.serv
|
|||||||
import { SelectableListService } from '../shared/object-list/selectable-list/selectable-list.service';
|
import { SelectableListService } from '../shared/object-list/selectable-list/selectable-list.service';
|
||||||
import { ObjectSelectService } from '../shared/object-select/object-select.service';
|
import { ObjectSelectService } from '../shared/object-select/object-select.service';
|
||||||
import { PaginationComponentOptions } from '../shared/pagination/pagination-component-options.model';
|
import { PaginationComponentOptions } from '../shared/pagination/pagination-component-options.model';
|
||||||
import { CSSVariableService } from '../shared/sass-helper/sass-helper.service';
|
|
||||||
import { SidebarService } from '../shared/sidebar/sidebar.service';
|
import { SidebarService } from '../shared/sidebar/sidebar.service';
|
||||||
import { UploaderService } from '../shared/uploader/uploader.service';
|
|
||||||
import { SectionFormOperationsService } from '../submission/sections/form/section-form-operations.service';
|
|
||||||
import { AuthenticatedGuard } from './auth/authenticated.guard';
|
import { AuthenticatedGuard } from './auth/authenticated.guard';
|
||||||
import { AuthStatus } from './auth/models/auth-status.model';
|
import { AuthStatus } from './auth/models/auth-status.model';
|
||||||
import { BrowseService } from './browse/browse.service';
|
import { BrowseService } from './browse/browse.service';
|
||||||
@@ -138,9 +132,6 @@ import {
|
|||||||
import { Registration } from './shared/registration.model';
|
import { Registration } from './shared/registration.model';
|
||||||
import { MetadataSchemaDataService } from './data/metadata-schema-data.service';
|
import { MetadataSchemaDataService } from './data/metadata-schema-data.service';
|
||||||
import { MetadataFieldDataService } from './data/metadata-field-data.service';
|
import { MetadataFieldDataService } from './data/metadata-field-data.service';
|
||||||
import {
|
|
||||||
DsDynamicTypeBindRelationService
|
|
||||||
} from '../shared/form/builder/ds-dynamic-form-ui/ds-dynamic-type-bind-relation.service';
|
|
||||||
import { TokenResponseParsingService } from './auth/token-response-parsing.service';
|
import { TokenResponseParsingService } from './auth/token-response-parsing.service';
|
||||||
import { SubmissionCcLicenseDataService } from './submission/submission-cc-license-data.service';
|
import { SubmissionCcLicenseDataService } from './submission/submission-cc-license-data.service';
|
||||||
import { SubmissionCcLicence } from './submission/models/submission-cc-license.model';
|
import { SubmissionCcLicence } from './submission/models/submission-cc-license.model';
|
||||||
@@ -150,7 +141,6 @@ import { VocabularyEntry } from './submission/vocabularies/models/vocabulary-ent
|
|||||||
import { Vocabulary } from './submission/vocabularies/models/vocabulary.model';
|
import { Vocabulary } from './submission/vocabularies/models/vocabulary.model';
|
||||||
import { VocabularyEntryDetail } from './submission/vocabularies/models/vocabulary-entry-detail.model';
|
import { VocabularyEntryDetail } from './submission/vocabularies/models/vocabulary-entry-detail.model';
|
||||||
import { VocabularyService } from './submission/vocabularies/vocabulary.service';
|
import { VocabularyService } from './submission/vocabularies/vocabulary.service';
|
||||||
import { VocabularyTreeviewService } from '../shared/vocabulary-treeview/vocabulary-treeview.service';
|
|
||||||
import { ConfigurationDataService } from './data/configuration-data.service';
|
import { ConfigurationDataService } from './data/configuration-data.service';
|
||||||
import { ConfigurationProperty } from './shared/configuration-property.model';
|
import { ConfigurationProperty } from './shared/configuration-property.model';
|
||||||
import { ReloadGuard } from './reload/reload.guard';
|
import { ReloadGuard } from './reload/reload.guard';
|
||||||
@@ -211,12 +201,6 @@ const PROVIDERS = [
|
|||||||
DSOResponseParsingService,
|
DSOResponseParsingService,
|
||||||
{ provide: MOCK_RESPONSE_MAP, useValue: mockResponseMap },
|
{ provide: MOCK_RESPONSE_MAP, useValue: mockResponseMap },
|
||||||
{ provide: DspaceRestService, useFactory: restServiceFactory, deps: [MOCK_RESPONSE_MAP, HttpClient] },
|
{ provide: DspaceRestService, useFactory: restServiceFactory, deps: [MOCK_RESPONSE_MAP, HttpClient] },
|
||||||
DynamicFormLayoutService,
|
|
||||||
DynamicFormService,
|
|
||||||
DynamicFormValidationService,
|
|
||||||
FormBuilderService,
|
|
||||||
SectionFormOperationsService,
|
|
||||||
FormService,
|
|
||||||
EPersonDataService,
|
EPersonDataService,
|
||||||
LinkHeadService,
|
LinkHeadService,
|
||||||
HALEndpointService,
|
HALEndpointService,
|
||||||
@@ -245,19 +229,16 @@ const PROVIDERS = [
|
|||||||
SubmissionResponseParsingService,
|
SubmissionResponseParsingService,
|
||||||
SubmissionJsonPatchOperationsService,
|
SubmissionJsonPatchOperationsService,
|
||||||
JsonPatchOperationsBuilder,
|
JsonPatchOperationsBuilder,
|
||||||
UploaderService,
|
|
||||||
UUIDService,
|
UUIDService,
|
||||||
NotificationsService,
|
NotificationsService,
|
||||||
WorkspaceitemDataService,
|
WorkspaceitemDataService,
|
||||||
WorkflowItemDataService,
|
WorkflowItemDataService,
|
||||||
UploaderService,
|
|
||||||
DSpaceObjectDataService,
|
DSpaceObjectDataService,
|
||||||
ConfigurationDataService,
|
ConfigurationDataService,
|
||||||
DSOChangeAnalyzer,
|
DSOChangeAnalyzer,
|
||||||
DefaultChangeAnalyzer,
|
DefaultChangeAnalyzer,
|
||||||
ArrayMoveChangeAnalyzer,
|
ArrayMoveChangeAnalyzer,
|
||||||
ObjectSelectService,
|
ObjectSelectService,
|
||||||
CSSVariableService,
|
|
||||||
MenuService,
|
MenuService,
|
||||||
ObjectUpdatesService,
|
ObjectUpdatesService,
|
||||||
SearchService,
|
SearchService,
|
||||||
@@ -268,7 +249,6 @@ const PROVIDERS = [
|
|||||||
ClaimedTaskDataService,
|
ClaimedTaskDataService,
|
||||||
PoolTaskDataService,
|
PoolTaskDataService,
|
||||||
BitstreamDataService,
|
BitstreamDataService,
|
||||||
DsDynamicTypeBindRelationService,
|
|
||||||
EntityTypeDataService,
|
EntityTypeDataService,
|
||||||
ContentSourceResponseParsingService,
|
ContentSourceResponseParsingService,
|
||||||
ItemTemplateDataService,
|
ItemTemplateDataService,
|
||||||
@@ -304,7 +284,6 @@ const PROVIDERS = [
|
|||||||
VocabularyService,
|
VocabularyService,
|
||||||
VocabularyDataService,
|
VocabularyDataService,
|
||||||
VocabularyEntryDetailsDataService,
|
VocabularyEntryDetailsDataService,
|
||||||
VocabularyTreeviewService,
|
|
||||||
SequenceService,
|
SequenceService,
|
||||||
GroupDataService,
|
GroupDataService,
|
||||||
FeedbackDataService,
|
FeedbackDataService,
|
||||||
|
@@ -10,6 +10,7 @@ import { ResourceType } from '../../shared/resource-type';
|
|||||||
import { BaseDataService } from './base-data.service';
|
import { BaseDataService } from './base-data.service';
|
||||||
import { HALDataService } from './hal-data-service.interface';
|
import { HALDataService } from './hal-data-service.interface';
|
||||||
import { dataService, getDataServiceFor } from './data-service.decorator';
|
import { dataService, getDataServiceFor } from './data-service.decorator';
|
||||||
|
import { v4 as uuidv4 } from 'uuid';
|
||||||
|
|
||||||
class TestService extends BaseDataService<any> {
|
class TestService extends BaseDataService<any> {
|
||||||
}
|
}
|
||||||
@@ -28,7 +29,7 @@ let testType;
|
|||||||
|
|
||||||
describe('@dataService/getDataServiceFor', () => {
|
describe('@dataService/getDataServiceFor', () => {
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
testType = new ResourceType('testType-' + new Date().getTime());
|
testType = new ResourceType(`testType-${uuidv4()}`);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should register a resourcetype for a dataservice', () => {
|
it('should register a resourcetype for a dataservice', () => {
|
||||||
|
@@ -3,7 +3,7 @@ import { ChangeAnalyzer } from './change-analyzer';
|
|||||||
import { Injectable } from '@angular/core';
|
import { Injectable } from '@angular/core';
|
||||||
import { DSpaceObject } from '../shared/dspace-object.model';
|
import { DSpaceObject } from '../shared/dspace-object.model';
|
||||||
import { MetadataMap } from '../shared/metadata.models';
|
import { MetadataMap } from '../shared/metadata.models';
|
||||||
import { cloneDeep } from 'lodash';
|
import cloneDeep from 'lodash/cloneDeep';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A class to determine what differs between two
|
* A class to determine what differs between two
|
||||||
|
@@ -1,3 +1,4 @@
|
|||||||
|
// eslint-disable-next-line import/no-namespace
|
||||||
import * as deepFreeze from 'deep-freeze';
|
import * as deepFreeze from 'deep-freeze';
|
||||||
import {
|
import {
|
||||||
AddFieldUpdateAction,
|
AddFieldUpdateAction,
|
||||||
|
@@ -1,3 +1,4 @@
|
|||||||
|
// eslint-disable-next-line import/no-namespace
|
||||||
import * as deepFreeze from 'deep-freeze';
|
import * as deepFreeze from 'deep-freeze';
|
||||||
import {
|
import {
|
||||||
RequestConfigureAction,
|
RequestConfigureAction,
|
||||||
|
@@ -4,7 +4,7 @@ import { HttpHeaders } from '@angular/common/http';
|
|||||||
import { createSelector, MemoizedSelector, select, Store } from '@ngrx/store';
|
import { createSelector, MemoizedSelector, select, Store } from '@ngrx/store';
|
||||||
import { Observable } from 'rxjs';
|
import { Observable } from 'rxjs';
|
||||||
import { filter, map, take, tap } from 'rxjs/operators';
|
import { filter, map, take, tap } from 'rxjs/operators';
|
||||||
import { cloneDeep } from 'lodash';
|
import cloneDeep from 'lodash/cloneDeep';
|
||||||
import { hasValue, isEmpty, isNotEmpty, hasNoValue } from '../../shared/empty.util';
|
import { hasValue, isEmpty, isNotEmpty, hasNoValue } from '../../shared/empty.util';
|
||||||
import { ObjectCacheEntry } from '../cache/object-cache.reducer';
|
import { ObjectCacheEntry } from '../cache/object-cache.reducer';
|
||||||
import { ObjectCacheService } from '../cache/object-cache.service';
|
import { ObjectCacheService } from '../cache/object-cache.service';
|
||||||
|
@@ -1,7 +1,17 @@
|
|||||||
|
/**
|
||||||
|
* The contents of this file are subject to the license and copyright
|
||||||
|
* detailed in the LICENSE and NOTICE files at the root of the source
|
||||||
|
* tree and available online at
|
||||||
|
*
|
||||||
|
* http://www.dspace.org/license/
|
||||||
|
*/
|
||||||
|
|
||||||
import { Injectable } from '@angular/core';
|
import { Injectable } from '@angular/core';
|
||||||
|
|
||||||
@Injectable()
|
@Injectable({
|
||||||
export class UploaderService {
|
providedIn: 'root'
|
||||||
|
})
|
||||||
|
export class DragService {
|
||||||
private _overrideDragOverPage = false;
|
private _overrideDragOverPage = false;
|
||||||
|
|
||||||
public overrideDragOverPage() {
|
public overrideDragOverPage() {
|
@@ -1,3 +1,4 @@
|
|||||||
|
// eslint-disable-next-line import/no-namespace
|
||||||
import * as deepFreeze from 'deep-freeze';
|
import * as deepFreeze from 'deep-freeze';
|
||||||
|
|
||||||
import { indexReducer, MetaIndexState } from './index.reducer';
|
import { indexReducer, MetaIndexState } from './index.reducer';
|
||||||
|
@@ -3,7 +3,6 @@ import { hasValue, isNotEmpty } from '../../shared/empty.util';
|
|||||||
import { coreSelector } from '../core.selectors';
|
import { coreSelector } from '../core.selectors';
|
||||||
import { URLCombiner } from '../url-combiner/url-combiner';
|
import { URLCombiner } from '../url-combiner/url-combiner';
|
||||||
import { IndexState, MetaIndexState } from './index.reducer';
|
import { IndexState, MetaIndexState } from './index.reducer';
|
||||||
import * as parse from 'url-parse';
|
|
||||||
import { IndexName } from './index-name.model';
|
import { IndexName } from './index-name.model';
|
||||||
import { CoreState } from '../core-state.model';
|
import { CoreState } from '../core-state.model';
|
||||||
|
|
||||||
@@ -21,17 +20,21 @@ import { CoreState } from '../core-state.model';
|
|||||||
*/
|
*/
|
||||||
export const getUrlWithoutEmbedParams = (url: string): string => {
|
export const getUrlWithoutEmbedParams = (url: string): string => {
|
||||||
if (isNotEmpty(url)) {
|
if (isNotEmpty(url)) {
|
||||||
const parsed = parse(url);
|
try {
|
||||||
if (isNotEmpty(parsed.query)) {
|
const parsed = new URL(url);
|
||||||
const parts = parsed.query.split(/[?|&]/)
|
if (isNotEmpty(parsed.search)) {
|
||||||
.filter((part: string) => isNotEmpty(part))
|
const parts = parsed.search.split(/[?|&]/)
|
||||||
.filter((part: string) => !(part.startsWith('embed=') || part.startsWith('embed.size=')));
|
.filter((part: string) => isNotEmpty(part))
|
||||||
let args = '';
|
.filter((part: string) => !(part.startsWith('embed=') || part.startsWith('embed.size=')));
|
||||||
if (isNotEmpty(parts)) {
|
let args = '';
|
||||||
args = `?${parts.join('&')}`;
|
if (isNotEmpty(parts)) {
|
||||||
|
args = `?${parts.join('&')}`;
|
||||||
|
}
|
||||||
|
url = new URLCombiner(parsed.origin, parsed.pathname, args).toString();
|
||||||
|
return url;
|
||||||
}
|
}
|
||||||
url = new URLCombiner(parsed.origin, parsed.pathname, args).toString();
|
} catch (e) {
|
||||||
return url;
|
// Ignore parsing errors. By default, we return the original string below.
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -44,15 +47,19 @@ export const getUrlWithoutEmbedParams = (url: string): string => {
|
|||||||
*/
|
*/
|
||||||
export const getEmbedSizeParams = (url: string): { name: string, size: number }[] => {
|
export const getEmbedSizeParams = (url: string): { name: string, size: number }[] => {
|
||||||
if (isNotEmpty(url)) {
|
if (isNotEmpty(url)) {
|
||||||
const parsed = parse(url);
|
try {
|
||||||
if (isNotEmpty(parsed.query)) {
|
const parsed = new URL(url);
|
||||||
return parsed.query.split(/[?|&]/)
|
if (isNotEmpty(parsed.search)) {
|
||||||
.filter((part: string) => isNotEmpty(part))
|
return parsed.search.split(/[?|&]/)
|
||||||
.map((part: string) => part.match(/^embed.size=([^=]+)=(\d+)$/))
|
.filter((part: string) => isNotEmpty(part))
|
||||||
.filter((matches: RegExpMatchArray) => hasValue(matches) && hasValue(matches[1]) && hasValue(matches[2]))
|
.map((part: string) => part.match(/^embed.size=([^=]+)=(\d+)$/))
|
||||||
.map((matches: RegExpMatchArray) => {
|
.filter((matches: RegExpMatchArray) => hasValue(matches) && hasValue(matches[1]) && hasValue(matches[2]))
|
||||||
return { name: matches[1], size: Number(matches[2]) };
|
.map((matches: RegExpMatchArray) => {
|
||||||
});
|
return { name: matches[1], size: Number(matches[2]) };
|
||||||
|
});
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
// Ignore parsing errors. By default, we return an empty result below.
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -1,3 +1,4 @@
|
|||||||
|
// eslint-disable-next-line import/no-namespace
|
||||||
import * as deepFreeze from 'deep-freeze';
|
import * as deepFreeze from 'deep-freeze';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
|
@@ -40,7 +40,7 @@ export class LocaleService {
|
|||||||
protected translate: TranslateService,
|
protected translate: TranslateService,
|
||||||
protected authService: AuthService,
|
protected authService: AuthService,
|
||||||
protected routeService: RouteService,
|
protected routeService: RouteService,
|
||||||
@Inject(DOCUMENT) private document: any
|
@Inject(DOCUMENT) protected document: any
|
||||||
) {
|
) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -1,12 +1,31 @@
|
|||||||
import { LANG_ORIGIN, LocaleService } from './locale.service';
|
import { LANG_ORIGIN, LocaleService } from './locale.service';
|
||||||
import { Injectable } from '@angular/core';
|
import { Inject, Injectable } from '@angular/core';
|
||||||
import { combineLatest, Observable, of as observableOf } from 'rxjs';
|
import { combineLatest, Observable, of as observableOf } from 'rxjs';
|
||||||
import { map, mergeMap, take } from 'rxjs/operators';
|
import { map, mergeMap, take } from 'rxjs/operators';
|
||||||
import { isEmpty, isNotEmpty } from '../../shared/empty.util';
|
import { hasValue, isEmpty, isNotEmpty } from '../../shared/empty.util';
|
||||||
|
import { NativeWindowRef, NativeWindowService } from '../services/window.service';
|
||||||
|
import { REQUEST } from '@nguniversal/express-engine/tokens';
|
||||||
|
import { CookieService } from '../services/cookie.service';
|
||||||
|
import { TranslateService } from '@ngx-translate/core';
|
||||||
|
import { AuthService } from '../auth/auth.service';
|
||||||
|
import { RouteService } from '../services/route.service';
|
||||||
|
import { DOCUMENT } from '@angular/common';
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class ServerLocaleService extends LocaleService {
|
export class ServerLocaleService extends LocaleService {
|
||||||
|
|
||||||
|
constructor(
|
||||||
|
@Inject(NativeWindowService) protected _window: NativeWindowRef,
|
||||||
|
@Inject(REQUEST) protected req: Request,
|
||||||
|
protected cookie: CookieService,
|
||||||
|
protected translate: TranslateService,
|
||||||
|
protected authService: AuthService,
|
||||||
|
protected routeService: RouteService,
|
||||||
|
@Inject(DOCUMENT) protected document: any
|
||||||
|
) {
|
||||||
|
super(_window, cookie, translate, authService, routeService, document);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the languages list of the user in Accept-Language format
|
* Get the languages list of the user in Accept-Language format
|
||||||
*
|
*
|
||||||
@@ -50,6 +69,10 @@ export class ServerLocaleService extends LocaleService {
|
|||||||
if (isNotEmpty(epersonLang)) {
|
if (isNotEmpty(epersonLang)) {
|
||||||
languages.push(...epersonLang);
|
languages.push(...epersonLang);
|
||||||
}
|
}
|
||||||
|
if (hasValue(this.req.headers['accept-language'])) {
|
||||||
|
languages.push(...this.req.headers['accept-language'].split(',')
|
||||||
|
);
|
||||||
|
}
|
||||||
return languages;
|
return languages;
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
|
@@ -1,8 +1,7 @@
|
|||||||
import { filter, map, pairwise } from 'rxjs/operators';
|
import { filter, map, pairwise } from 'rxjs/operators';
|
||||||
import { Injectable } from '@angular/core';
|
import { Injectable } from '@angular/core';
|
||||||
import { Actions, createEffect, ofType } from '@ngrx/effects';
|
import { Actions, createEffect, ofType } from '@ngrx/effects';
|
||||||
import * as fromRouter from '@ngrx/router-store';
|
import { RouterNavigationAction, ROUTER_NAVIGATION } from '@ngrx/router-store';
|
||||||
import { RouterNavigationAction } from '@ngrx/router-store';
|
|
||||||
import { Router } from '@angular/router';
|
import { Router } from '@angular/router';
|
||||||
import { RouteUpdateAction } from './router.actions';
|
import { RouteUpdateAction } from './router.actions';
|
||||||
|
|
||||||
@@ -14,7 +13,7 @@ export class RouterEffects {
|
|||||||
*/
|
*/
|
||||||
routeChange$ = createEffect(() => this.actions$
|
routeChange$ = createEffect(() => this.actions$
|
||||||
.pipe(
|
.pipe(
|
||||||
ofType(fromRouter.ROUTER_NAVIGATION),
|
ofType(ROUTER_NAVIGATION),
|
||||||
pairwise(),
|
pairwise(),
|
||||||
map((actions: RouterNavigationAction[]) =>
|
map((actions: RouterNavigationAction[]) =>
|
||||||
actions.map((navigateAction) => {
|
actions.map((navigateAction) => {
|
||||||
|
@@ -4,7 +4,7 @@ import { ActivatedRoute, NavigationEnd, Params, Router, RouterStateSnapshot, } f
|
|||||||
|
|
||||||
import { combineLatest, Observable } from 'rxjs';
|
import { combineLatest, Observable } from 'rxjs';
|
||||||
import { createSelector, MemoizedSelector, select, Store } from '@ngrx/store';
|
import { createSelector, MemoizedSelector, select, Store } from '@ngrx/store';
|
||||||
import { isEqual } from 'lodash';
|
import isEqual from 'lodash/isEqual';
|
||||||
|
|
||||||
import { AddParameterAction, SetParameterAction, SetParametersAction, SetQueryParameterAction, SetQueryParametersAction } from './route.actions';
|
import { AddParameterAction, SetParameterAction, SetParametersAction, SetQueryParameterAction, SetQueryParametersAction } from './route.actions';
|
||||||
import { coreSelector } from '../core.selectors';
|
import { coreSelector } from '../core.selectors';
|
||||||
|
@@ -3,7 +3,7 @@ import { getMockRequestService } from '../../shared/mocks/request.service.mock';
|
|||||||
import { RequestService } from '../data/request.service';
|
import { RequestService } from '../data/request.service';
|
||||||
import { HALEndpointService } from './hal-endpoint.service';
|
import { HALEndpointService } from './hal-endpoint.service';
|
||||||
import { EndpointMapRequest } from '../data/request.models';
|
import { EndpointMapRequest } from '../data/request.models';
|
||||||
import { combineLatest as observableCombineLatest, Observable, of as observableOf } from 'rxjs';
|
import { combineLatest as observableCombineLatest, of as observableOf } from 'rxjs';
|
||||||
import { environment } from '../../../environments/environment';
|
import { environment } from '../../../environments/environment';
|
||||||
import { RemoteDataBuildService } from '../cache/builders/remote-data-build.service';
|
import { RemoteDataBuildService } from '../cache/builders/remote-data-build.service';
|
||||||
import { createSuccessfulRemoteDataObject$ } from '../../shared/remote-data.utils';
|
import { createSuccessfulRemoteDataObject$ } from '../../shared/remote-data.utils';
|
||||||
|
@@ -5,7 +5,8 @@ import {
|
|||||||
MetadataValueFilter,
|
MetadataValueFilter,
|
||||||
MetadatumViewModel
|
MetadatumViewModel
|
||||||
} from './metadata.models';
|
} from './metadata.models';
|
||||||
import { groupBy, sortBy } from 'lodash';
|
import groupBy from 'lodash/groupBy';
|
||||||
|
import sortBy from 'lodash/sortBy';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Utility class for working with DSpace object metadata.
|
* Utility class for working with DSpace object metadata.
|
||||||
|
@@ -26,6 +26,8 @@ import { SearchConfigurationService } from './search-configuration.service';
|
|||||||
import { PaginationServiceStub } from '../../../shared/testing/pagination-service.stub';
|
import { PaginationServiceStub } from '../../../shared/testing/pagination-service.stub';
|
||||||
import { RequestEntry } from '../../data/request-entry.model';
|
import { RequestEntry } from '../../data/request-entry.model';
|
||||||
import { Angulartics2 } from 'angulartics2';
|
import { Angulartics2 } from 'angulartics2';
|
||||||
|
import { SearchFilterConfig } from '../../../shared/search/models/search-filter-config.model';
|
||||||
|
import anything = jasmine.anything;
|
||||||
|
|
||||||
@Component({ template: '' })
|
@Component({ template: '' })
|
||||||
class DummyComponent {
|
class DummyComponent {
|
||||||
@@ -36,7 +38,7 @@ describe('SearchService', () => {
|
|||||||
let searchService: SearchService;
|
let searchService: SearchService;
|
||||||
const router = new RouterStub();
|
const router = new RouterStub();
|
||||||
const route = new ActivatedRouteStub();
|
const route = new ActivatedRouteStub();
|
||||||
const searchConfigService = {paginationID: 'page-id'};
|
const searchConfigService = { paginationID: 'page-id' };
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
TestBed.configureTestingModule({
|
TestBed.configureTestingModule({
|
||||||
imports: [
|
imports: [
|
||||||
@@ -103,7 +105,8 @@ describe('SearchService', () => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const paginationService = new PaginationServiceStub();
|
const paginationService = new PaginationServiceStub();
|
||||||
const searchConfigService = {paginationID: 'page-id'};
|
const searchConfigService = { paginationID: 'page-id' };
|
||||||
|
const requestService = getMockRequestService();
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
TestBed.configureTestingModule({
|
TestBed.configureTestingModule({
|
||||||
@@ -119,7 +122,7 @@ describe('SearchService', () => {
|
|||||||
providers: [
|
providers: [
|
||||||
{ provide: Router, useValue: router },
|
{ provide: Router, useValue: router },
|
||||||
{ provide: RouteService, useValue: routeServiceStub },
|
{ provide: RouteService, useValue: routeServiceStub },
|
||||||
{ provide: RequestService, useValue: getMockRequestService() },
|
{ provide: RequestService, useValue: requestService },
|
||||||
{ provide: RemoteDataBuildService, useValue: remoteDataBuildService },
|
{ provide: RemoteDataBuildService, useValue: remoteDataBuildService },
|
||||||
{ provide: HALEndpointService, useValue: halService },
|
{ provide: HALEndpointService, useValue: halService },
|
||||||
{ provide: CommunityDataService, useValue: {} },
|
{ provide: CommunityDataService, useValue: {} },
|
||||||
@@ -138,13 +141,13 @@ describe('SearchService', () => {
|
|||||||
|
|
||||||
it('should call the navigate method on the Router with view mode list parameter as a parameter when setViewMode is called', () => {
|
it('should call the navigate method on the Router with view mode list parameter as a parameter when setViewMode is called', () => {
|
||||||
searchService.setViewMode(ViewMode.ListElement);
|
searchService.setViewMode(ViewMode.ListElement);
|
||||||
expect(paginationService.updateRouteWithUrl).toHaveBeenCalledWith('page-id', ['/search'], {page: 1}, { view: ViewMode.ListElement }
|
expect(paginationService.updateRouteWithUrl).toHaveBeenCalledWith('page-id', ['/search'], { page: 1 }, { view: ViewMode.ListElement }
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should call the navigate method on the Router with view mode grid parameter as a parameter when setViewMode is called', () => {
|
it('should call the navigate method on the Router with view mode grid parameter as a parameter when setViewMode is called', () => {
|
||||||
searchService.setViewMode(ViewMode.GridElement);
|
searchService.setViewMode(ViewMode.GridElement);
|
||||||
expect(paginationService.updateRouteWithUrl).toHaveBeenCalledWith('page-id', ['/search'], {page: 1}, { view: ViewMode.GridElement }
|
expect(paginationService.updateRouteWithUrl).toHaveBeenCalledWith('page-id', ['/search'], { page: 1 }, { view: ViewMode.GridElement }
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -191,5 +194,23 @@ describe('SearchService', () => {
|
|||||||
expect((searchService as any).rdb.buildFromHref).toHaveBeenCalledWith(endPoint);
|
expect((searchService as any).rdb.buildFromHref).toHaveBeenCalledWith(endPoint);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe('when getFacetValuesFor is called with a filterQuery', () => {
|
||||||
|
it('should add the encoded filterQuery to the args list', () => {
|
||||||
|
jasmine.getEnv().allowRespy(true);
|
||||||
|
const spyRequest = spyOn((searchService as any), 'request').and.stub();
|
||||||
|
spyOn(requestService, 'send').and.returnValue(true);
|
||||||
|
const searchFilterConfig = new SearchFilterConfig();
|
||||||
|
searchFilterConfig._links = {
|
||||||
|
self: {
|
||||||
|
href: 'https://demo.dspace.org/',
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
searchService.getFacetValuesFor(searchFilterConfig, 1, undefined, 'filter&Query');
|
||||||
|
|
||||||
|
expect(spyRequest).toHaveBeenCalledWith(anything(), 'https://demo.dspace.org?page=0&size=5&prefix=filter%26Query');
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@@ -3,7 +3,6 @@ import { combineLatest as observableCombineLatest, Observable } from 'rxjs';
|
|||||||
import { Injectable, OnDestroy } from '@angular/core';
|
import { Injectable, OnDestroy } from '@angular/core';
|
||||||
import { map, switchMap, take } from 'rxjs/operators';
|
import { map, switchMap, take } from 'rxjs/operators';
|
||||||
import { FollowLinkConfig } from '../../../shared/utils/follow-link-config.model';
|
import { FollowLinkConfig } from '../../../shared/utils/follow-link-config.model';
|
||||||
import { PaginatedList } from '../../data/paginated-list.model';
|
|
||||||
import { ResponseParsingService } from '../../data/parsing.service';
|
import { ResponseParsingService } from '../../data/parsing.service';
|
||||||
import { RemoteData } from '../../data/remote-data';
|
import { RemoteData } from '../../data/remote-data';
|
||||||
import { GetRequest } from '../../data/request.models';
|
import { GetRequest } from '../../data/request.models';
|
||||||
@@ -271,7 +270,7 @@ export class SearchService implements OnDestroy {
|
|||||||
let href;
|
let href;
|
||||||
let args: string[] = [];
|
let args: string[] = [];
|
||||||
if (hasValue(filterQuery)) {
|
if (hasValue(filterQuery)) {
|
||||||
args.push(`prefix=${filterQuery}`);
|
args.push(`prefix=${encodeURIComponent(filterQuery)}`);
|
||||||
}
|
}
|
||||||
if (hasValue(searchOptions)) {
|
if (hasValue(searchOptions)) {
|
||||||
searchOptions = Object.assign(new PaginatedSearchOptions({}), searchOptions, {
|
searchOptions = Object.assign(new PaginatedSearchOptions({}), searchOptions, {
|
||||||
|
@@ -1,6 +1,6 @@
|
|||||||
/* eslint-disable max-classes-per-file */
|
/* eslint-disable max-classes-per-file */
|
||||||
import { EquatableObject, excludeFromEquals, fieldsForEquals } from './equals.decorators';
|
import { EquatableObject, excludeFromEquals, fieldsForEquals } from './equals.decorators';
|
||||||
import { cloneDeep } from 'lodash';
|
import cloneDeep from 'lodash/cloneDeep';
|
||||||
|
|
||||||
class Dog extends EquatableObject<Dog> {
|
class Dog extends EquatableObject<Dog> {
|
||||||
public name: string;
|
public name: string;
|
||||||
|
@@ -1,7 +1,7 @@
|
|||||||
import { CorrelationIdService } from './correlation-id.service';
|
import { CorrelationIdService } from './correlation-id.service';
|
||||||
import { CookieServiceMock } from '../shared/mocks/cookie.service.mock';
|
import { CookieServiceMock } from '../shared/mocks/cookie.service.mock';
|
||||||
import { UUIDService } from '../core/shared/uuid.service';
|
import { UUIDService } from '../core/shared/uuid.service';
|
||||||
import { MockStore, provideMockStore } from '@ngrx/store/testing';
|
import { MockStore } from '@ngrx/store/testing';
|
||||||
import { TestBed } from '@angular/core/testing';
|
import { TestBed } from '@angular/core/testing';
|
||||||
import { Store, StoreModule } from '@ngrx/store';
|
import { Store, StoreModule } from '@ngrx/store';
|
||||||
import { appReducers, AppState, storeModuleConfig } from '../app.reducer';
|
import { appReducers, AppState, storeModuleConfig } from '../app.reducer';
|
||||||
|
@@ -5,7 +5,7 @@ import { getFirstCompletedRemoteData } from '../core/shared/operators';
|
|||||||
import { find, map } from 'rxjs/operators';
|
import { find, map } from 'rxjs/operators';
|
||||||
import { NotificationsService } from '../shared/notifications/notifications.service';
|
import { NotificationsService } from '../shared/notifications/notifications.service';
|
||||||
import { TranslateService } from '@ngx-translate/core';
|
import { TranslateService } from '@ngx-translate/core';
|
||||||
import { hasValue, isEmpty, isNotEmpty, hasNoValue } from '../shared/empty.util';
|
import { hasValue, isEmpty, isNotEmpty } from '../shared/empty.util';
|
||||||
import { RemoteData } from '../core/data/remote-data';
|
import { RemoteData } from '../core/data/remote-data';
|
||||||
import { Router } from '@angular/router';
|
import { Router } from '@angular/router';
|
||||||
import { ProcessDataService } from '../core/data/processes/process-data.service';
|
import { ProcessDataService } from '../core/data/processes/process-data.service';
|
||||||
|
@@ -6,8 +6,7 @@
|
|||||||
<ds-listable-object-component-loader [object]="item" [viewMode]="viewMode" class="pb-4">
|
<ds-listable-object-component-loader [object]="item" [viewMode]="viewMode" class="pb-4">
|
||||||
</ds-listable-object-component-loader>
|
</ds-listable-object-component-loader>
|
||||||
</div>
|
</div>
|
||||||
<button (click)="onLoadMore()" class="btn btn-primary search-button mt-4 float-left ng-tns-c290-40">Load
|
<button (click)="onLoadMore()" class="btn btn-primary search-button mt-4 float-left ng-tns-c290-40"> {{'vocabulary-treeview.load-more' | translate }} ...</button>
|
||||||
more...</button>
|
|
||||||
</div>
|
</div>
|
||||||
<ds-error *ngIf="itemRD?.hasFailed" message="{{'error.recent-submissions' | translate}}"></ds-error>
|
<ds-error *ngIf="itemRD?.hasFailed" message="{{'error.recent-submissions' | translate}}"></ds-error>
|
||||||
<ds-loading *ngIf="!itemRD || itemRD.isLoading" message="{{'loading.recent-submissions' | translate}}">
|
<ds-loading *ngIf="!itemRD || itemRD.isLoading" message="{{'loading.recent-submissions' | translate}}">
|
||||||
|
@@ -17,9 +17,6 @@ import { HostWindowService } from '../../shared/host-window.service';
|
|||||||
import { HostWindowServiceStub } from '../../shared/testing/host-window-service.stub';
|
import { HostWindowServiceStub } from '../../shared/testing/host-window-service.stub';
|
||||||
import { CommunityDataService } from '../../core/data/community-data.service';
|
import { CommunityDataService } from '../../core/data/community-data.service';
|
||||||
import { SelectableListService } from '../../shared/object-list/selectable-list/selectable-list.service';
|
import { SelectableListService } from '../../shared/object-list/selectable-list/selectable-list.service';
|
||||||
import { of as observableOf } from 'rxjs';
|
|
||||||
import { PaginationComponentOptions } from '../../shared/pagination/pagination-component-options.model';
|
|
||||||
import { SortDirection, SortOptions } from '../../core/cache/models/sort-options.model';
|
|
||||||
import { PaginationService } from '../../core/pagination/pagination.service';
|
import { PaginationService } from '../../core/pagination/pagination.service';
|
||||||
import { getMockThemeService } from '../../shared/mocks/theme-service.mock';
|
import { getMockThemeService } from '../../shared/mocks/theme-service.mock';
|
||||||
import { ThemeService } from '../../shared/theme-support/theme.service';
|
import { ThemeService } from '../../shared/theme-support/theme.service';
|
||||||
|
@@ -13,7 +13,7 @@ import { makeStateKey, TransferState } from '@angular/platform-browser';
|
|||||||
import { APP_CONFIG, AppConfig } from '../config/app-config.interface';
|
import { APP_CONFIG, AppConfig } from '../config/app-config.interface';
|
||||||
import { environment } from '../environments/environment';
|
import { environment } from '../environments/environment';
|
||||||
import { AppState } from './app.reducer';
|
import { AppState } from './app.reducer';
|
||||||
import { isEqual } from 'lodash';
|
import isEqual from 'lodash/isEqual';
|
||||||
import { TranslateService } from '@ngx-translate/core';
|
import { TranslateService } from '@ngx-translate/core';
|
||||||
import { LocaleService } from './core/locale/locale.service';
|
import { LocaleService } from './core/locale/locale.service';
|
||||||
import { Angulartics2DSpace } from './statistics/angulartics/dspace-provider';
|
import { Angulartics2DSpace } from './statistics/angulartics/dspace-provider';
|
||||||
|
@@ -4,7 +4,7 @@ import { RemoteData } from '../../../core/data/remote-data';
|
|||||||
import { Item } from '../../../core/shared/item.model';
|
import { Item } from '../../../core/shared/item.model';
|
||||||
import { map, take, switchMap } from 'rxjs/operators';
|
import { map, take, switchMap } from 'rxjs/operators';
|
||||||
import { ActivatedRoute, Router } from '@angular/router';
|
import { ActivatedRoute, Router } from '@angular/router';
|
||||||
import { UploaderOptions } from '../../../shared/uploader/uploader-options.model';
|
import { UploaderOptions } from '../../../shared/upload/uploader/uploader-options.model';
|
||||||
import { hasValue, isEmpty, isNotEmpty } from '../../../shared/empty.util';
|
import { hasValue, isEmpty, isNotEmpty } from '../../../shared/empty.util';
|
||||||
import { ItemDataService } from '../../../core/data/item-data.service';
|
import { ItemDataService } from '../../../core/data/item-data.service';
|
||||||
import { AuthService } from '../../../core/auth/auth.service';
|
import { AuthService } from '../../../core/auth/auth.service';
|
||||||
@@ -14,7 +14,7 @@ import { PaginatedList } from '../../../core/data/paginated-list.model';
|
|||||||
import { Bundle } from '../../../core/shared/bundle.model';
|
import { Bundle } from '../../../core/shared/bundle.model';
|
||||||
import { BundleDataService } from '../../../core/data/bundle-data.service';
|
import { BundleDataService } from '../../../core/data/bundle-data.service';
|
||||||
import { getFirstSucceededRemoteDataPayload, getFirstCompletedRemoteData } from '../../../core/shared/operators';
|
import { getFirstSucceededRemoteDataPayload, getFirstCompletedRemoteData } from '../../../core/shared/operators';
|
||||||
import { UploaderComponent } from '../../../shared/uploader/uploader.component';
|
import { UploaderComponent } from '../../../shared/upload/uploader/uploader.component';
|
||||||
import { RequestService } from '../../../core/data/request.service';
|
import { RequestService } from '../../../core/data/request.service';
|
||||||
import { getBitstreamModuleRoute } from '../../../app-routing-paths';
|
import { getBitstreamModuleRoute } from '../../../app-routing-paths';
|
||||||
import { getEntityEditRoute } from '../../item-page-routing-paths';
|
import { getEntityEditRoute } from '../../item-page-routing-paths';
|
||||||
|
@@ -1,12 +1,11 @@
|
|||||||
import { Observable } from 'rxjs/internal/Observable';
|
|
||||||
import { waitForAsync, ComponentFixture, inject, TestBed } from '@angular/core/testing';
|
import { waitForAsync, ComponentFixture, inject, TestBed } from '@angular/core/testing';
|
||||||
import { Component, NO_ERRORS_SCHEMA } from '@angular/core';
|
import { Component, NO_ERRORS_SCHEMA } from '@angular/core';
|
||||||
import { ActivatedRoute } from '@angular/router';
|
import { ActivatedRoute } from '@angular/router';
|
||||||
import { NoopAnimationsModule } from '@angular/platform-browser/animations';
|
import { NoopAnimationsModule } from '@angular/platform-browser/animations';
|
||||||
import { of as observableOf, of } from 'rxjs';
|
import { of as observableOf } from 'rxjs';
|
||||||
import { TranslateModule } from '@ngx-translate/core';
|
import { TranslateModule } from '@ngx-translate/core';
|
||||||
import { cold } from 'jasmine-marbles';
|
import { cold } from 'jasmine-marbles';
|
||||||
import { ItemAuthorizationsComponent, BitstreamMapValue } from './item-authorizations.component';
|
import { ItemAuthorizationsComponent } from './item-authorizations.component';
|
||||||
import { Bitstream } from '../../../core/shared/bitstream.model';
|
import { Bitstream } from '../../../core/shared/bitstream.model';
|
||||||
import { Bundle } from '../../../core/shared/bundle.model';
|
import { Bundle } from '../../../core/shared/bundle.model';
|
||||||
import { Item } from '../../../core/shared/item.model';
|
import { Item } from '../../../core/shared/item.model';
|
||||||
@@ -14,8 +13,6 @@ import { LinkService } from '../../../core/cache/builders/link.service';
|
|||||||
import { getMockLinkService } from '../../../shared/mocks/link-service.mock';
|
import { getMockLinkService } from '../../../shared/mocks/link-service.mock';
|
||||||
import { createSuccessfulRemoteDataObject, createSuccessfulRemoteDataObject$ } from '../../../shared/remote-data.utils';
|
import { createSuccessfulRemoteDataObject, createSuccessfulRemoteDataObject$ } from '../../../shared/remote-data.utils';
|
||||||
import { createPaginatedList, createTestComponent } from '../../../shared/testing/utils.test';
|
import { createPaginatedList, createTestComponent } from '../../../shared/testing/utils.test';
|
||||||
import { PaginatedList, buildPaginatedList } from '../../../core/data/paginated-list.model';
|
|
||||||
import { PageInfo } from '../../../core/shared/page-info.model';
|
|
||||||
|
|
||||||
describe('ItemAuthorizationsComponent test suite', () => {
|
describe('ItemAuthorizationsComponent test suite', () => {
|
||||||
let comp: ItemAuthorizationsComponent;
|
let comp: ItemAuthorizationsComponent;
|
||||||
|
@@ -1,4 +1,4 @@
|
|||||||
import { isEqual } from 'lodash';
|
import isEqual from 'lodash/isEqual';
|
||||||
import { DSONameService } from '../../../core/breadcrumbs/dso-name.service';
|
import { DSONameService } from '../../../core/breadcrumbs/dso-name.service';
|
||||||
import { Component, OnDestroy, OnInit } from '@angular/core';
|
import { Component, OnDestroy, OnInit } from '@angular/core';
|
||||||
import { ActivatedRoute } from '@angular/router';
|
import { ActivatedRoute } from '@angular/router';
|
||||||
|
@@ -17,10 +17,7 @@ import { createSuccessfulRemoteDataObject$ } from '../../../../../shared/remote-
|
|||||||
import { createPaginatedList } from '../../../../../shared/testing/utils.test';
|
import { createPaginatedList } from '../../../../../shared/testing/utils.test';
|
||||||
import { RequestService } from '../../../../../core/data/request.service';
|
import { RequestService } from '../../../../../core/data/request.service';
|
||||||
import { PaginationService } from '../../../../../core/pagination/pagination.service';
|
import { PaginationService } from '../../../../../core/pagination/pagination.service';
|
||||||
import { PaginationComponentOptions } from '../../../../../shared/pagination/pagination-component-options.model';
|
|
||||||
import { SortDirection, SortOptions } from '../../../../../core/cache/models/sort-options.model';
|
|
||||||
import { PaginationServiceStub } from '../../../../../shared/testing/pagination-service.stub';
|
import { PaginationServiceStub } from '../../../../../shared/testing/pagination-service.stub';
|
||||||
import { FindListOptions } from '../../../../../core/data/find-list-options.model';
|
|
||||||
|
|
||||||
describe('PaginatedDragAndDropBitstreamListComponent', () => {
|
describe('PaginatedDragAndDropBitstreamListComponent', () => {
|
||||||
let comp: PaginatedDragAndDropBitstreamListComponent;
|
let comp: PaginatedDragAndDropBitstreamListComponent;
|
||||||
|
@@ -1,6 +1,6 @@
|
|||||||
import { Component, Input, OnChanges, OnInit, SimpleChanges, ViewChild, ViewContainerRef } from '@angular/core';
|
import { Component, Input, OnChanges, OnInit, SimpleChanges, ViewChild, ViewContainerRef } from '@angular/core';
|
||||||
import { Bitstream } from '../../../../core/shared/bitstream.model';
|
import { Bitstream } from '../../../../core/shared/bitstream.model';
|
||||||
import { cloneDeep } from 'lodash';
|
import cloneDeep from 'lodash/cloneDeep';
|
||||||
import { ObjectUpdatesService } from '../../../../core/data/object-updates/object-updates.service';
|
import { ObjectUpdatesService } from '../../../../core/data/object-updates/object-updates.service';
|
||||||
import { Observable } from 'rxjs';
|
import { Observable } from 'rxjs';
|
||||||
import { BitstreamFormat } from '../../../../core/shared/bitstream-format.model';
|
import { BitstreamFormat } from '../../../../core/shared/bitstream-format.model';
|
||||||
|
@@ -5,7 +5,7 @@ import {
|
|||||||
} from '../../../../core/shared/operators';
|
} from '../../../../core/shared/operators';
|
||||||
import { hasValue, isNotEmpty } from '../../../../shared/empty.util';
|
import { hasValue, isNotEmpty } from '../../../../shared/empty.util';
|
||||||
import { RegistryService } from '../../../../core/registry/registry.service';
|
import { RegistryService } from '../../../../core/registry/registry.service';
|
||||||
import { cloneDeep } from 'lodash';
|
import cloneDeep from 'lodash/cloneDeep';
|
||||||
import { BehaviorSubject, Observable, of as observableOf } from 'rxjs';
|
import { BehaviorSubject, Observable, of as observableOf } from 'rxjs';
|
||||||
import { map } from 'rxjs/operators';
|
import { map } from 'rxjs/operators';
|
||||||
import { ObjectUpdatesService } from '../../../../core/data/object-updates/object-updates.service';
|
import { ObjectUpdatesService } from '../../../../core/data/object-updates/object-updates.service';
|
||||||
|
@@ -3,7 +3,7 @@ import { Item } from '../../../core/shared/item.model';
|
|||||||
import { ItemDataService } from '../../../core/data/item-data.service';
|
import { ItemDataService } from '../../../core/data/item-data.service';
|
||||||
import { ObjectUpdatesService } from '../../../core/data/object-updates/object-updates.service';
|
import { ObjectUpdatesService } from '../../../core/data/object-updates/object-updates.service';
|
||||||
import { ActivatedRoute, Router } from '@angular/router';
|
import { ActivatedRoute, Router } from '@angular/router';
|
||||||
import { cloneDeep } from 'lodash';
|
import cloneDeep from 'lodash/cloneDeep';
|
||||||
import { first, switchMap } from 'rxjs/operators';
|
import { first, switchMap } from 'rxjs/operators';
|
||||||
import { getFirstCompletedRemoteData } from '../../../core/shared/operators';
|
import { getFirstCompletedRemoteData } from '../../../core/shared/operators';
|
||||||
import { RemoteData } from '../../../core/data/remote-data';
|
import { RemoteData } from '../../../core/data/remote-data';
|
||||||
|
@@ -1,18 +1,16 @@
|
|||||||
<ds-metadata-field-wrapper [label]="label | translate">
|
<ds-metadata-field-wrapper [label]="label | translate">
|
||||||
<ng-container *ngFor="let mdValue of mdValues; let last=last;">
|
<ng-container *ngFor="let mdValue of mdValues; let last=last;">
|
||||||
<ng-container *ngTemplateOutlet="(renderMarkdown ? markdown : simple); context: {value: mdValue.value, classes: 'dont-break-out preserve-line-breaks'}">
|
<ng-container *ngTemplateOutlet="(renderMarkdown ? markdown : simple); context: {value: mdValue.value}">
|
||||||
</ng-container>
|
</ng-container>
|
||||||
<span class="separator" *ngIf="!last" [innerHTML]="separator"></span>
|
<span class="separator" *ngIf="!last" [innerHTML]="separator"></span>
|
||||||
</ng-container>
|
</ng-container>
|
||||||
</ds-metadata-field-wrapper>
|
</ds-metadata-field-wrapper>
|
||||||
|
|
||||||
<ng-template #markdown let-value="value" let-classes="classes">
|
<ng-template #markdown let-value="value">
|
||||||
<span class="{{classes}}" [innerHTML]="value | dsMarkdown | async">
|
<span class="dont-break-out" [innerHTML]="value | dsMarkdown | async">
|
||||||
</span>
|
</span>
|
||||||
</ng-template>
|
</ng-template>
|
||||||
|
|
||||||
<ng-template #simple let-value="value" let-classes="classes">
|
<ng-template #simple let-value="value">
|
||||||
<span class="{{classes}}">
|
<span class="dont-break-out preserve-line-breaks">{{value}}</span>
|
||||||
{{value}}
|
|
||||||
</span>
|
|
||||||
</ng-template>
|
</ng-template>
|
||||||
|
@@ -16,11 +16,10 @@ import { MockBitstreamFormat1 } from '../../../../shared/mocks/item.mock';
|
|||||||
import { By } from '@angular/platform-browser';
|
import { By } from '@angular/platform-browser';
|
||||||
import { NotificationsService } from '../../../../shared/notifications/notifications.service';
|
import { NotificationsService } from '../../../../shared/notifications/notifications.service';
|
||||||
import { NotificationsServiceStub } from '../../../../shared/testing/notifications-service.stub';
|
import { NotificationsServiceStub } from '../../../../shared/testing/notifications-service.stub';
|
||||||
import { PaginationComponentOptions } from '../../../../shared/pagination/pagination-component-options.model';
|
|
||||||
import { SortDirection, SortOptions } from '../../../../core/cache/models/sort-options.model';
|
|
||||||
import { PaginationService } from '../../../../core/pagination/pagination.service';
|
import { PaginationService } from '../../../../core/pagination/pagination.service';
|
||||||
import { PaginationServiceStub } from '../../../../shared/testing/pagination-service.stub';
|
import { PaginationServiceStub } from '../../../../shared/testing/pagination-service.stub';
|
||||||
import { FindListOptions } from '../../../../core/data/find-list-options.model';
|
import { APP_CONFIG } from 'src/config/app-config.interface';
|
||||||
|
import { environment } from 'src/environments/environment';
|
||||||
|
|
||||||
describe('FullFileSectionComponent', () => {
|
describe('FullFileSectionComponent', () => {
|
||||||
let comp: FullFileSectionComponent;
|
let comp: FullFileSectionComponent;
|
||||||
@@ -72,7 +71,8 @@ describe('FullFileSectionComponent', () => {
|
|||||||
providers: [
|
providers: [
|
||||||
{ provide: BitstreamDataService, useValue: bitstreamDataService },
|
{ provide: BitstreamDataService, useValue: bitstreamDataService },
|
||||||
{ provide: NotificationsService, useValue: new NotificationsServiceStub() },
|
{ provide: NotificationsService, useValue: new NotificationsServiceStub() },
|
||||||
{ provide: PaginationService, useValue: paginationService }
|
{ provide: PaginationService, useValue: paginationService },
|
||||||
|
{ provide: APP_CONFIG, useValue: environment },
|
||||||
],
|
],
|
||||||
|
|
||||||
schemas: [NO_ERRORS_SCHEMA]
|
schemas: [NO_ERRORS_SCHEMA]
|
||||||
|
@@ -1,4 +1,4 @@
|
|||||||
import { Component, Input, OnInit } from '@angular/core';
|
import { Component, Inject, Input, OnInit } from '@angular/core';
|
||||||
import { Observable } from 'rxjs';
|
import { Observable } from 'rxjs';
|
||||||
import { BitstreamDataService } from '../../../../core/data/bitstream-data.service';
|
import { BitstreamDataService } from '../../../../core/data/bitstream-data.service';
|
||||||
|
|
||||||
@@ -14,6 +14,7 @@ import { NotificationsService } from '../../../../shared/notifications/notificat
|
|||||||
import { TranslateService } from '@ngx-translate/core';
|
import { TranslateService } from '@ngx-translate/core';
|
||||||
import { hasValue, isEmpty } from '../../../../shared/empty.util';
|
import { hasValue, isEmpty } from '../../../../shared/empty.util';
|
||||||
import { PaginationService } from '../../../../core/pagination/pagination.service';
|
import { PaginationService } from '../../../../core/pagination/pagination.service';
|
||||||
|
import { AppConfig, APP_CONFIG } from 'src/config/app-config.interface';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This component renders the file section of the item
|
* This component renders the file section of the item
|
||||||
@@ -34,26 +35,26 @@ export class FullFileSectionComponent extends FileSectionComponent implements On
|
|||||||
originals$: Observable<RemoteData<PaginatedList<Bitstream>>>;
|
originals$: Observable<RemoteData<PaginatedList<Bitstream>>>;
|
||||||
licenses$: Observable<RemoteData<PaginatedList<Bitstream>>>;
|
licenses$: Observable<RemoteData<PaginatedList<Bitstream>>>;
|
||||||
|
|
||||||
pageSize = 5;
|
|
||||||
originalOptions = Object.assign(new PaginationComponentOptions(), {
|
originalOptions = Object.assign(new PaginationComponentOptions(), {
|
||||||
id: 'obo',
|
id: 'obo',
|
||||||
currentPage: 1,
|
currentPage: 1,
|
||||||
pageSize: this.pageSize
|
pageSize: this.appConfig.item.bitstream.pageSize
|
||||||
});
|
});
|
||||||
|
|
||||||
licenseOptions = Object.assign(new PaginationComponentOptions(), {
|
licenseOptions = Object.assign(new PaginationComponentOptions(), {
|
||||||
id: 'lbo',
|
id: 'lbo',
|
||||||
currentPage: 1,
|
currentPage: 1,
|
||||||
pageSize: this.pageSize
|
pageSize: this.appConfig.item.bitstream.pageSize
|
||||||
});
|
});
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
bitstreamDataService: BitstreamDataService,
|
bitstreamDataService: BitstreamDataService,
|
||||||
protected notificationsService: NotificationsService,
|
protected notificationsService: NotificationsService,
|
||||||
protected translateService: TranslateService,
|
protected translateService: TranslateService,
|
||||||
protected paginationService: PaginationService
|
protected paginationService: PaginationService,
|
||||||
|
@Inject(APP_CONFIG) protected appConfig: AppConfig
|
||||||
) {
|
) {
|
||||||
super(bitstreamDataService, notificationsService, translateService);
|
super(bitstreamDataService, notificationsService, translateService, appConfig);
|
||||||
}
|
}
|
||||||
|
|
||||||
ngOnInit(): void {
|
ngOnInit(): void {
|
||||||
|
@@ -67,6 +67,7 @@ import { OrcidPageGuard } from './orcid-page/orcid-page.guard';
|
|||||||
id: 'statistics_item_:id',
|
id: 'statistics_item_:id',
|
||||||
active: true,
|
active: true,
|
||||||
visible: true,
|
visible: true,
|
||||||
|
index: 2,
|
||||||
model: {
|
model: {
|
||||||
type: MenuItemType.LINK,
|
type: MenuItemType.LINK,
|
||||||
text: 'menu.section.statistics',
|
text: 'menu.section.statistics',
|
||||||
|
@@ -46,6 +46,7 @@ import { OrcidPageComponent } from './orcid-page/orcid-page.component';
|
|||||||
import { NgbAccordionModule } from '@ng-bootstrap/ng-bootstrap';
|
import { NgbAccordionModule } from '@ng-bootstrap/ng-bootstrap';
|
||||||
import { OrcidSyncSettingsComponent } from './orcid-page/orcid-sync-settings/orcid-sync-settings.component';
|
import { OrcidSyncSettingsComponent } from './orcid-page/orcid-sync-settings/orcid-sync-settings.component';
|
||||||
import { OrcidQueueComponent } from './orcid-page/orcid-queue/orcid-queue.component';
|
import { OrcidQueueComponent } from './orcid-page/orcid-queue/orcid-queue.component';
|
||||||
|
import { UploadModule } from '../shared/upload/upload.module';
|
||||||
|
|
||||||
|
|
||||||
const ENTRY_COMPONENTS = [
|
const ENTRY_COMPONENTS = [
|
||||||
@@ -94,7 +95,8 @@ const DECLARATIONS = [
|
|||||||
JournalEntitiesModule.withEntryComponents(),
|
JournalEntitiesModule.withEntryComponents(),
|
||||||
ResearchEntitiesModule.withEntryComponents(),
|
ResearchEntitiesModule.withEntryComponents(),
|
||||||
NgxGalleryModule,
|
NgxGalleryModule,
|
||||||
NgbAccordionModule
|
NgbAccordionModule,
|
||||||
|
UploadModule,
|
||||||
],
|
],
|
||||||
declarations: [
|
declarations: [
|
||||||
...DECLARATIONS,
|
...DECLARATIONS,
|
||||||
|
@@ -17,6 +17,8 @@ import { MetadataFieldWrapperComponent } from '../../../field-components/metadat
|
|||||||
import { createPaginatedList } from '../../../../shared/testing/utils.test';
|
import { createPaginatedList } from '../../../../shared/testing/utils.test';
|
||||||
import { NotificationsService } from '../../../../shared/notifications/notifications.service';
|
import { NotificationsService } from '../../../../shared/notifications/notifications.service';
|
||||||
import { NotificationsServiceStub } from '../../../../shared/testing/notifications-service.stub';
|
import { NotificationsServiceStub } from '../../../../shared/testing/notifications-service.stub';
|
||||||
|
import { APP_CONFIG } from 'src/config/app-config.interface';
|
||||||
|
import { environment } from 'src/environments/environment';
|
||||||
|
|
||||||
describe('FileSectionComponent', () => {
|
describe('FileSectionComponent', () => {
|
||||||
let comp: FileSectionComponent;
|
let comp: FileSectionComponent;
|
||||||
@@ -65,7 +67,8 @@ describe('FileSectionComponent', () => {
|
|||||||
declarations: [FileSectionComponent, VarDirective, FileSizePipe, MetadataFieldWrapperComponent],
|
declarations: [FileSectionComponent, VarDirective, FileSizePipe, MetadataFieldWrapperComponent],
|
||||||
providers: [
|
providers: [
|
||||||
{ provide: BitstreamDataService, useValue: bitstreamDataService },
|
{ provide: BitstreamDataService, useValue: bitstreamDataService },
|
||||||
{ provide: NotificationsService, useValue: new NotificationsServiceStub() }
|
{ provide: NotificationsService, useValue: new NotificationsServiceStub() },
|
||||||
|
{ provide: APP_CONFIG, useValue: environment }
|
||||||
],
|
],
|
||||||
|
|
||||||
schemas: [NO_ERRORS_SCHEMA]
|
schemas: [NO_ERRORS_SCHEMA]
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user