Compare commits

...

891 Commits

Author SHA1 Message Date
Tim Donohue
d9634a84ae Merge pull request #874 from atmire/w2p-72956_delete-eperson
Delete eperson
2020-10-08 12:08:29 -05:00
Tim Donohue
5bf6d0f287 Merge pull request #851 from atmire/usage-reports
Add statistics pages
2020-10-07 12:34:04 -05:00
Samuel
d843230158 Add statistics pages - fix link caching issue 2020-10-07 13:53:20 +02:00
Tim Donohue
bb935be0b6 Merge pull request #866 from atmire/Metadata-edit-patch-error-fix
Metadata edit patch error fix
2020-10-06 09:54:55 -05:00
Raf Ponsaerts
fbe6ec61de [Task 72956] applied feedback to the delete eperson error message 2020-10-02 16:38:19 +02:00
Tim Donohue
03bba0f578 Merge pull request #877 from atmire/remove-api-from-rest-config
remove remaining uses of /api in the rest namespace
2020-09-30 11:33:16 -05:00
Tim Donohue
098eb291b6 Merge pull request #878 from atmire/reomve-circular-dependencies-part-2
Remove circular dependencies part 2
2020-09-30 11:02:57 -05:00
Art Lowel
4f16f21a7d remove remaining uses of /api in the rest namespace 2020-09-30 17:14:31 +02:00
Tim Donohue
6511920d0c Merge pull request #868 from atmire/google-scholar-fixes
Google scholar fixes
2020-09-30 09:48:17 -05:00
Tim Donohue
b4120f2053 Update Codecov settings
This makes patch checks slightly more lenient, as they are not required.
2020-09-30 09:14:23 -05:00
Raf Ponsaerts
2621454cdb [Task 72956] fixed LGTM issue 2020-09-30 15:26:46 +02:00
Raf Ponsaerts
5615390ce5 [Task 72956] fixed EPerson deletion issues with page not refreshing 2020-09-30 14:46:03 +02:00
Art Lowel
3e191bb56e move info module paths to separate file 2020-09-30 13:53:04 +02:00
Raf Ponsaerts
e12559544b Merge remote-tracking branch 'dspace/main' into w2p-72956_delete-eperson
Conflicts:
	src/app/core/data/feature-authorization/feature-id.ts
2020-09-30 13:06:18 +02:00
Raf Ponsaerts
24c07536b0 [Task 72956] fixing tests 2020-09-30 13:01:12 +02:00
Art Lowel
24706f0cc4 remove remaining uses of /api in the rest namespace 2020-09-30 11:15:50 +02:00
Art Lowel
764cfc5d95 add comment to explain rewriteDownloadUrls 2020-09-30 10:44:37 +02:00
Tim Donohue
c67d2e6718 Merge pull request #873 from atmire/w2p-fix-bitstreams-pagination-on-item-page
Fix bug concerning bistream pagination on the item page
2020-09-29 11:51:02 -05:00
Raf Ponsaerts
8a07b3bb2b [Task 72956] fix LGTM issue 2020-09-29 14:20:20 +02:00
Raf Ponsaerts
f6fea087c3 [Task 72956] further development on delete eperson 2020-09-29 14:18:15 +02:00
Samuel
b6ff9369e4 Add statistics pages - move data service and add ds-loading 2020-09-29 14:14:28 +02:00
Kristof De Langhe
15de3a2eeb Merge branch 'main' into w2p-73014_Metadata-edit-patch-error-fix
Conflicts:
	src/app/+item-page/edit-item-page/item-metadata/item-metadata.component.ts
2020-09-24 10:16:01 +02:00
Tim Donohue
6e6253c2d8 Merge pull request #860 from atmire/w2p-71894_metadatafields-byFieldName-search-endpoint
Item edit page metadatafields suggestion & validation
2020-09-23 16:31:38 -05:00
Samuel
6ff9429bc0 Add statistics pages - add support for parameters in menu sections and add id params 2020-09-23 23:28:06 +02:00
Tim Donohue
aa84a56c2b Merge pull request #861 from atmire/Cookie-preferences
Cookie consent preferences
2020-09-23 15:14:24 -05:00
Samuel
e7e408dacb Add statistics pages - feedback 2020-09-23 21:57:53 +02:00
Samuel
b7382de29a Add statistics pages 2020-09-23 21:57:52 +02:00
Tim Donohue
1ef3d40904 Merge pull request #822 from atmire/Features-support-part-2
Features support part 2
2020-09-23 14:37:30 -05:00
Tim Donohue
1fba45a08b Customize Codecov settings 2020-09-23 13:31:53 -05:00
lotte
456551fd94 fixed tests 2020-09-23 16:57:08 +02:00
Tim Donohue
a0414e11bc Merge pull request #872 from tdonohue/replace_coveralls_with_codecov
Switch from Coveralls.io to Codecov.io
2020-09-23 08:36:54 -05:00
Raf Ponsaerts
3de2b50d10 [Task 72956] applied feedback to the deletion of epersons 2020-09-23 15:07:38 +02:00
Yana De Pauw
ddc1cbbd73 73249: Fix message and filter issue 2020-09-23 11:36:10 +02:00
Yana De Pauw
cfadb4314e Remove console.log 2020-09-23 10:57:41 +02:00
Yana De Pauw
dfbbd98862 73249: Fix issues with bitstream pagination on item pages. 2020-09-23 10:57:41 +02:00
Tim Donohue
047fbfee1f Switch from Coveralls.io to Codecov.io 2020-09-22 16:19:07 -05:00
Tim Donohue
6960597381 Merge pull request #871 from atmire/fix-express-error-handler
Ensure CSR fallback only happens on actual errors
2020-09-22 12:43:12 -05:00
Kristof De Langhe
124ed4aff2 71764: LGTM Issue fix 2020-09-22 09:14:07 +02:00
Kristof De Langhe
dd7f34e541 Merge branch 'main' into w2p-71764_Features-support-part-2
Conflicts:
	src/app/+collection-page/collection-page-routing.module.ts
	src/app/+community-page/community-page-routing.module.ts
	src/app/+item-page/edit-item-page/edit-item-page.routing.module.ts
	src/app/+item-page/edit-item-page/item-status/item-status.component.ts
	src/app/+item-page/item-page-routing.module.ts
	src/app/app-routing.module.ts
	src/app/core/core.module.ts
	src/app/shared/log-in/log-in.component.html
	src/app/shared/log-in/log-in.component.spec.ts
	src/app/shared/log-in/log-in.component.ts
2020-09-22 08:36:16 +02:00
Art Lowel
5afd4a6930 ensure CSR fallback only happens on actual errors 2020-09-21 18:41:10 +02:00
Raf Ponsaerts
f8dab74b64 [Task 72956] improvement to the spyOn in EPersonFormComponent test 2020-09-21 14:56:29 +02:00
Raf Ponsaerts
2d2fb0210c [Task 72956] removed console logs 2020-09-21 14:29:04 +02:00
Raf Ponsaerts
05f3b7e7c6 [Task 72956] implemented the deletion of EPerson in the EPerson Form and Registry 2020-09-21 14:24:55 +02:00
lotte
9886ba8dc9 fixed linting errors 2020-09-21 09:12:22 +02:00
lotte
8e04dff09d fixed lgtm issues 2020-09-21 09:05:29 +02:00
Art Lowel
9757e6651e fix test 2020-09-18 18:05:37 +02:00
Art Lowel
47edd9b6d8 add docs on configuring rewriteDownloadUrls 2020-09-18 17:46:49 +02:00
lotte
f96549d5c7 added urlcombiner 2020-09-18 17:46:45 +02:00
lotte
9c01c1b3f3 fixed test issues 2020-09-18 17:46:36 +02:00
lotte
1b10ec63d6 fixed google scholar links, todo: fix tests 2020-09-18 17:46:29 +02:00
Tim Donohue
9f396f7120 Merge pull request #862 from atmire/User-agreement
User agreement
2020-09-17 11:17:43 -05:00
Tim Donohue
54e61e00ce Merge pull request #856 from atmire/Hard-redirect-after-log-in
Hard redirect after log in
2020-09-17 08:25:18 -05:00
Kristof De Langhe
11b62daa44 73014: metadata edit - notification on patch error 2020-09-17 14:24:44 +02:00
Kristof De Langhe
4e10db8a53 72541: user-agreement update to patch 2020-09-17 13:13:32 +02:00
Kristof De Langhe
b68fe23310 72699: Additional test fix 2020-09-17 11:40:30 +02:00
Kristof De Langhe
d5927a76fc 72699: Test fix 2020-09-17 10:49:24 +02:00
Kristof De Langhe
b77dce25ce 72699: Shibboleth login redirect fix 2020-09-17 10:44:10 +02:00
Marie Verdonck
ade3bffcb7 71894: prod build permission issue fix 2020-09-17 10:30:23 +02:00
Tim Donohue
4214ddec8c Merge pull request #863 from atmire/SSR-preboot-and-error-handling
Fixes for preboot and SSR error handling
2020-09-16 16:06:58 -05:00
Marie Verdonck
5db42a6da8 71894: also disable save button if invalid input field 2020-09-16 16:33:38 +02:00
Marie Verdonck
75058a735a 71894: confirm edit metadata button disabled if invalid &
removed unneeded service
2020-09-16 14:50:29 +02:00
Kristof De Langhe
8c4f5002f5 73014: Remove sending patch to cache + small refactoring changes 2020-09-16 12:01:43 +02:00
Kristof De Langhe
2e8a78151e 73014: MetadataPatchOperation refactoring + add operation fix 2020-09-15 17:49:30 +02:00
lotte
5e21c5fd26 Merge branch 'Hard-redirect-after-log-in' into w2p-72635_cookie-preferences 2020-09-15 09:42:09 +02:00
lotte
fc35c9fd67 Merge branch 'Hard-redirect-after-log-in' into w2p-72635_cookie-preferences 2020-09-15 09:39:23 +02:00
Kristof De Langhe
e53548a95a 73014: Item metadata patch tests 2020-09-14 16:53:36 +02:00
Kristof De Langhe
eee57f5b41 73014: MetadataPatchOperationService create patch in two steps to fix remove operation issue 2020-09-14 13:34:30 +02:00
Kristof De Langhe
1647c95600 73014: Create patch from object-updates and send immediate patch for item-metadata-edit 2020-09-11 17:34:37 +02:00
Art Lowel
abab73b909 Merge branch 'Hard-redirect-after-log-in' into User-agreement 2020-09-11 16:54:17 +02:00
Art Lowel
7eb88f9fda Merge branch 'main' into Hard-redirect-after-log-in 2020-09-11 16:52:01 +02:00
Tim Donohue
0be3c61eeb Merge pull request #751 from 4Science/authorities_and_controlled_vocabularies
Refactoring authority framework, value pairs and controlled vocabulary [Angular]
2020-09-11 09:42:37 -05:00
Giuseppe Digilio
e7ef068352 Merge remote-tracking branch 'remotes/origin/main' into authorities_and_controlled_vocabularies 2020-09-11 15:52:58 +02:00
Giuseppe Digilio
c5cb1a2837 [CSTPER-75] Fixed confidence status for linked metadata with authority 2020-09-11 15:38:41 +02:00
Giuseppe Digilio
a178e215f0 Fixed issue with preparing patch operation's value when value has an authority id but is not an instance of VocabularyEntry or FormFieldMetadataValueObject 2020-09-11 15:35:50 +02:00
Giuseppe Digilio
fab0a09727 Fixed issue with adding lookup repeatable fields 2020-09-11 15:33:05 +02:00
Giuseppe Digilio
1e8669a738 Fixed issue with change not detected 2020-09-11 15:30:38 +02:00
lotte
a6dd87f78c updated server.ts to latest fixes 2020-09-09 16:08:01 +02:00
lotte
cced7a2914 fixed preboot issues and error handling 2020-09-09 16:07:19 +02:00
lotte
3f4a0d1fd9 removing proboot option from config 2020-09-09 16:07:19 +02:00
Tim Donohue
4b11e1d9cd Merge pull request #857 from 4Science/issue#819
Issue#819
2020-09-08 09:40:09 -05:00
Kristof De Langhe
b82e840935 72541: Removed unused import 2020-09-08 11:16:12 +02:00
Kristof De Langhe
c5e975601a Merge branch 'w2p-72699_Hard-redirect-after-log-in' into w2p-72541_User-agreement-and-Privacy-statement
Conflicts:
	src/app/app-routing.module.ts
2020-09-08 10:17:44 +02:00
lotte
99b84223e2 fixed lgtm error 2020-09-08 09:26:38 +02:00
lotte
d4027cc1d1 debounce for update requests 2020-09-08 09:13:17 +02:00
lotte
90f0597baa bugfix for users without metadata value for cookie 2020-09-08 09:13:17 +02:00
lotte
48ffb2105f added missing typedoc 2020-09-08 09:13:17 +02:00
lotte
d7f6885232 updated consent configuration 2020-09-08 09:13:17 +02:00
lotte
8d29090f24 small fixes 2020-09-08 09:13:17 +02:00
lotte
c19f49fb96 added tests 2020-09-08 09:13:17 +02:00
lotte
19ca179e7a commit before rebase 2020-09-08 09:13:17 +02:00
lotte
f6e8448164 fixed SSR issue, added code for storing the users cookie consents and restoring them 2020-09-08 09:13:17 +02:00
lotte
b3b934033c added klaro exclusion to webpack/tsconfig 2020-09-08 09:13:17 +02:00
lotte
3e1fb243a1 solving SSR issue 2020-09-08 09:13:17 +02:00
lotte
33aeccdd43 72635: Fixed initialize code and started on storageName 2020-09-08 09:13:17 +02:00
lotte
0b3b82b485 finished basic Klaro setup 2020-09-08 09:13:17 +02:00
lotte
472154c0df 72635: Cookie preferences first committ 2020-09-08 09:13:17 +02:00
Kristof De Langhe
de9f642bf9 72541: Fix tests, remove redundant injection and added JSDocs 2020-09-07 12:01:23 +02:00
Kristof De Langhe
f0940aad57 Merge branch 'w2p-72699_Hard-redirect-after-log-in' into Hard-redirect-after-log-in 2020-09-07 10:30:09 +02:00
Kristof De Langhe
4141ae7ad7 72699: JSDocs 2020-09-07 10:27:39 +02:00
Kristof De Langhe
b89c21ec3b Merge branch 'main' into w2p-72699_Hard-redirect-after-log-in
Conflicts:
	src/app/app-routing.module.ts
2020-09-07 10:22:37 +02:00
Giuseppe Digilio
ac86976115 Disabled EPerson language when sending Accept-Language header 2020-09-07 09:27:38 +02:00
Giuseppe Digilio
6feb344aa0 Revert "Fixed issue with LocaleInterceptor that blocked new request"
This reverts commit a76e0796
2020-09-07 09:26:23 +02:00
Giuseppe Digilio
b58defc0f3 Revert "Fixed issue that emits successful remote data twice with undefined payload in the first one"
This reverts commit 99c0f6ce
2020-09-07 09:26:02 +02:00
Kristof De Langhe
18fdf7585e Merge branch 'w2p-72541_User-agreement-and-Privacy-statement' of https://git.atmire.com/contributions/dspace-angular into w2p-72541_User-agreement-and-Privacy-statement 2020-09-04 17:46:11 +02:00
Kristof De Langhe
aa1b568bf4 72541: Redirect through query param at EndUserAgreement 2020-09-04 17:46:05 +02:00
Tim Donohue
dd037459cf Merge pull request #715 from 4Science/DS-4515_submit-external-source
DS-4515: Start new submission via Search or ID Lookup (i.e. submit external source)
2020-09-04 09:49:55 -05:00
Art Lowel
7997100a7e Merge branch 'w2p-72699_Hard-redirect-after-log-in' into w2p-72541_User-agreement-and-Privacy-statement 2020-09-04 14:35:24 +02:00
Art Lowel
5965f4e929 remove circular dependency 2020-09-04 14:32:13 +02:00
Marie Verdonck
1e82943f4a Remove unused imports 2020-09-04 13:04:57 +02:00
Marie Verdonck
dcbb002630 71894: small fix after rebase 2020-09-04 12:52:15 +02:00
Marie Verdonck
810f009582 71894: position dropdown right underneath input 2020-09-04 12:23:31 +02:00
Marie Verdonck
b602a736de 71894: Refactored exact FieldName search for validator after change endpoint 2020-09-04 12:23:31 +02:00
Art Lowel
10b314cf20 fix tests 2020-09-04 12:23:30 +02:00
Marie Verdonck
1f4ae7a035 71894: refactor with new operator metadataFieldsToString instead of schemaResolved 2020-09-04 12:23:30 +02:00
Marie Verdonck
2ebb1640b4 71894: WIP: fix EditInPlace tests 2020-09-04 12:22:24 +02:00
Marie Verdonck
4a0444d669 71894: mdField validation; TODO: fix EditInPlace tests 2020-09-04 12:22:24 +02:00
Marie Verdonck
a6c0a60bd7 71894: Start of mdField validator; todo: show error & some backend changes 2020-09-04 12:22:24 +02:00
Marie Verdonck
77b2506112 71894: MD field suggestions on edit item page 2020-09-04 12:22:24 +02:00
Kristof De Langhe
bd522038a1 72541: Additional tests and fixes 2020-09-03 17:52:52 +02:00
Kristof De Langhe
eda1a34da5 72541: EndUserAgreementCurrentUserGuard and EndUserAgreementCookieGuard 2020-09-03 17:22:38 +02:00
Kristof De Langhe
a0759098ea Merge branch 'w2p-72699_Hard-redirect-after-log-in' into w2p-72541_User-agreement-and-Privacy-statement
Conflicts:
	src/app/+collection-page/collection-page-routing.module.ts
	src/app/+community-page/community-page-routing.module.ts
	src/app/+item-page/item-page-routing.module.ts
	src/app/+workflowitems-edit-page/workflowitems-edit-page-routing.module.ts
	src/app/app-routing.module.ts
	src/app/core/shared/operators.ts
2020-09-03 16:06:59 +02:00
Giuseppe Digilio
a76e0796c6 Fixed issue with LocaleInterceptor that blocked new request 2020-09-03 14:46:52 +02:00
Giuseppe Digilio
99c0f6ceaa Fixed issue that emits successful remote data twice with undefined payload in the first one 2020-09-03 14:45:10 +02:00
Kristof De Langhe
59def51ebe 72699: LGTM alert fixes 2020-09-03 13:36:16 +02:00
Kristof De Langhe
5e970bcff2 72699: isAuthBlocking$ rename to isNotAuthBlocking$ 2020-09-03 13:32:13 +02:00
Kristof De Langhe
3d08eb0ae1 Merge branch 'main' into w2p-72699_Hard-redirect-after-log-in
Conflicts:
	src/app/app-routing.module.ts
	src/app/shared/log-in/log-in.component.ts
2020-09-03 13:19:36 +02:00
Art Lowel
e9a2b4b368 made the redirect after logging out blocking as well 2020-09-03 12:58:40 +02:00
Giuseppe Digilio
b8138ee3b9 Fixed lint error 2020-09-03 12:27:55 +02:00
Giuseppe Digilio
b15113ad96 Fixed failed test 2020-09-03 11:36:28 +02:00
Giuseppe Digilio
a504b7cbd3 Fixed issue with form field losing confidence value 2020-09-03 11:18:32 +02:00
Kristof De Langhe
306d6d15c5 Merge branch 'w2p-72699_Hard-redirect-after-log-in' into w2p-72541_User-agreement-and-Privacy-statement
Conflicts:
	src/app/app-routing.module.ts
2020-09-03 10:49:06 +02:00
Giuseppe Digilio
7d22bcc59c Merge remote-tracking branch 'remotes/atmire/fix-entities-issue-pr-751' into authorities_and_controlled_vocabularies 2020-09-03 10:07:34 +02:00
Giuseppe Digilio
94119668dd Fixed merge 2020-09-03 09:57:24 +02:00
Giuseppe Digilio
5ebd4fcbc8 Merge remote-tracking branch 'remotes/origin/main' into authorities_and_controlled_vocabularies
# Conflicts:
#	src/app/core/integration/models/authority.value.ts
#	src/app/shared/chips/models/chips-item.model.ts
#	src/app/shared/chips/models/chips.model.ts
#	src/app/shared/form/builder/ds-dynamic-form-ui/ds-dynamic-form-control-container.component.ts
#	src/app/shared/form/builder/ds-dynamic-form-ui/models/relation-group/dynamic-relation-group.components.ts
#	src/app/shared/form/builder/models/form-field-metadata-value.model.ts
2020-09-03 09:36:39 +02:00
Tim Donohue
cd6c5b70c8 Merge pull request #853 from atmire/w2p-72741_upload-section-id
844: Fix file upload to use section ID instead of 'upload'
2020-09-02 15:00:36 -05:00
Tim Donohue
16a68dae42 Merge pull request #855 from atmire/Curation-task-email-parameter-removal
Removal of email option for the curation script
2020-09-02 11:14:34 -05:00
jonas-atmire
be79663df9 Removal of email option for the curation script -> See https://github.com/DSpace/DSpace/pull/2926#pullrequestreview-477868288 for full explanation 2020-09-02 14:59:44 +02:00
Kristof De Langhe
17249e9541 72699: Additional fixes for maintaining and clearing the redirect url on login components 2020-09-01 16:22:16 +02:00
Tim Donohue
f4946003e2 Add action to auto-label PRs with merge conflicts 2020-09-01 09:08:25 -05:00
Art Lowel
f167d5a629 fix issue where combining entities and authority control in the same field wouldn't work 2020-09-01 14:25:50 +02:00
Art Lowel
724e5d1f12 add blocking state to make dealing with log in errors more user friendly 2020-09-01 10:10:39 +02:00
Tim Donohue
bc0be9e235 Merge pull request #850 from atmire/remove-cirular-dependencies
Remove circular dependencies
2020-08-31 15:14:06 -05:00
Yana De Pauw
f222cd8b33 72741: Fix file upload to use section ID instead of 'upload' 2020-08-28 17:24:52 +02:00
Tim Donohue
a63bfdf2fd Merge pull request #845 from atmire/w2p-72444_Support-multiple-dsoType-values-in-discovery
Support multiple dso type values in discovery
2020-08-28 09:05:20 -05:00
Tim Donohue
43ae3fc952 Merge pull request #841 from 4Science/ISSUE_840
Hide EPerson search section in the edit mode
2020-08-28 08:48:05 -05:00
Kristof De Langhe
cb3ef1dde4 72541: End-User-Agreement redirect via store 2020-08-28 13:05:02 +02:00
Art Lowel
bbc7844b5d fix lgtm issues 2020-08-28 11:58:43 +02:00
Kristof De Langhe
76b9fd4702 Merge branch 'w2p-72699_Hard-redirect-after-log-in' into w2p-72541_User-agreement-and-Privacy-statement 2020-08-28 11:46:38 +02:00
Kristof De Langhe
61e0b9efb0 72699: Remove redundant subscribe + fix tests 2020-08-28 11:40:22 +02:00
Art Lowel
21e8879f77 remove circular dependencies 2020-08-28 11:34:17 +02:00
Kristof De Langhe
beca98b441 Merge branch 'w2p-72699_Hard-redirect-after-log-in' into w2p-72541_User-agreement-and-Privacy-statement
Conflicts:
	src/app/app-routing.module.ts
	src/app/core/core.module.ts
2020-08-28 10:40:01 +02:00
Kristof De Langhe
32cf92eba9 72541: Spacing between checkbox and buttons 2020-08-28 10:37:55 +02:00
Marie Verdonck
81fc26b844 72444: Statistics search event dsoType single string & small fix 2020-08-27 15:17:02 +02:00
Kristof De Langhe
a3df6ce474 72699: Remove unnecessary method 2020-08-27 14:56:20 +02:00
Kristof De Langhe
55c45f5f6c 72699: Hard redirect after log in - loading fixes 2020-08-27 14:50:13 +02:00
Marie Verdonck
e9d77c4d2c 72444: statistics searchevent.dsoTypes changed until backend changes
& error on export modal dso selector for item removed, only returns comcols, not items now
& test fixes
2020-08-27 14:37:31 +02:00
Marie Verdonck
e89d064934 multiple dsoType allowed in search & in selector modals 2020-08-27 14:37:31 +02:00
Giuseppe Digilio
92207cf66d Added missing TypeDocs 2020-08-27 09:30:38 +02:00
Kristof De Langhe
7fbae8997d 72699: JSDocs and Test cases 2020-08-26 16:32:03 +02:00
Giuseppe Digilio
4080cce8fd Fixed check for Hierarchical Vocabulary 2020-08-26 15:57:34 +02:00
Giuseppe Digilio
ee2f11f602 Fixed template 2020-08-26 15:33:52 +02:00
Giuseppe Digilio
87bed6d288 Fixed check for vocabulary options on DsDynamicListComponent 2020-08-26 15:24:01 +02:00
Giuseppe Digilio
3178e5578c Fixed issue after merge 2020-08-26 14:45:53 +02:00
Giuseppe Digilio
67bd19a340 Fixed template 2020-08-26 14:42:47 +02:00
Giuseppe Digilio
ab190e381d Fixed test 2020-08-26 14:35:23 +02:00
Kristof De Langhe
7367f91176 72699: Hard redirect after log in 2020-08-26 14:20:47 +02:00
Giuseppe Digilio
4b35828bbe Merge remote-tracking branch 'remotes/origin/main' into authorities_and_controlled_vocabularies
# Conflicts:
#	src/app/shared/shared.module.ts
2020-08-26 13:58:49 +02:00
Giuseppe Digilio
94b4115ecd Removed unintentional fdescribe 2020-08-26 12:53:50 +02:00
Tim Donohue
cc618ebadd Merge pull request #838 from atmire/file-pagination-simple-and-full-item-pages
File pagination simple and full item pages
2020-08-21 16:30:25 -05:00
Luca Giamminonni
547ade276c Hide EPerson search section in the edit mode 2020-08-21 19:01:08 +02:00
Kristof De Langhe
de1e1a70d1 72541: End User Agreement test cases 2020-08-21 16:05:19 +02:00
Kristof De Langhe
ecf75efe99 72541: Renamed end-user-agreement-guard and -service; Add metadata on registry; privacy statement component 2020-08-21 11:22:02 +02:00
Kristof De Langhe
d46355e274 72541: Accepting the End User Agreement + UserAgreementService 2020-08-20 17:28:25 +02:00
Tim Donohue
708b5495c7 Merge pull request #825 from atmire/Add-robots-txt
Add robots.txt
2020-08-20 10:18:08 -05:00
Tim Donohue
0fc757ba4d Add link to Code Testing Guide in PR template 2020-08-20 10:09:05 -05:00
Kristof De Langhe
8768645e4a 72541: InfoModule, EndUserAgreementComponent, UserAgreementGuard 2020-08-19 17:47:33 +02:00
Tim Donohue
6b90ac073c Merge pull request #798 from atmire/Export-Import_metadata_CSV
Export/Import metadata CSV
2020-08-19 10:10:03 -05:00
Raf Ponsaerts
1247088df9 Fixed tslint issues 2020-08-17 16:29:57 +02:00
Raf Ponsaerts
a38d365bab Updated message for the collapse bitstreams for the bitstream pagination on simple item pages 2020-08-17 15:18:25 +02:00
Raf Ponsaerts
18fb47c9b6 [Task 72397] applied feedback on the file section and full file section components 2020-08-17 10:14:05 +02:00
Danilo Di Nuzzo
cfd819cd62 Merge branch 'authorities_and_controlled_vocabularies' of https://github.com/4Science/dspace-angular into authorities_and_controlled_vocabularies 2020-08-14 12:56:57 +02:00
ddinuzzo
3f8a670dcf Merge branch 'main' into authorities_and_controlled_vocabularies 2020-08-14 12:53:38 +02:00
Art Lowel
0a06368340 add a proxy for the sitemaps 2020-08-12 17:31:33 +02:00
Art Lowel
a2fa51cef5 deprecate the use of /api in the rest nameSpace 2020-08-12 14:38:06 +02:00
Danilo Di Nuzzo
66cabcb342 refactory for metadata and collection params 2020-08-12 14:01:29 +02:00
Art Lowel
8f822ba4f7 add robots.txt 2020-08-12 13:20:11 +02:00
Art Lowel
05a92f8e5b refactor webpack config 2020-08-12 13:19:23 +02:00
lotte
82d780b6c2 Fixed PageInfo SSR issue 2020-08-12 11:56:49 +02:00
Raf Ponsaerts
cb7335208f [Task 72397] undo test consoles and fix pagination issue 2020-08-11 13:13:02 +02:00
Raf Ponsaerts
0553f68607 [Task 72397] adding debug consoles and pageSize 2020-08-11 11:58:42 +02:00
Matteo Perelli
25d912b006 Merge with main 2020-08-11 10:01:16 +02:00
Raf Ponsaerts
f6f87a5738 [Task 72397] implemented the bitstream pagination on simple and full item pages 2020-08-07 16:07:33 +02:00
Tim Donohue
f1db0c044b Merge pull request #829 from atmire/Put-dynamic-workflowgroup-links-on-Collections-in-an-array
Put dynamic workflowgroup links on Collections in an array
2020-08-06 15:52:23 -05:00
Tim Donohue
9c83cd9b53 Merge pull request #830 from atmire/submission-repeatable-issue
Fix issue with repeatable scrollable dropdowns in the submission
2020-08-06 15:14:45 -05:00
Tim Donohue
4f608eb3cf Merge pull request #724 from 4Science/CST-3091
DS-4514 start a new submission via file
2020-08-06 08:45:50 -05:00
Kristof De Langhe
42978931de Merge branch 'main' into w2p-71764_Features-support-part-2
Conflicts:
	src/app/core/core.module.ts
2020-08-06 13:50:48 +02:00
Samuel
261f79daab Put dynamic workflowgroup links on Collections in an array - fix lgtm warnings 2020-08-05 16:17:27 +02:00
Art Lowel
d560e08b20 only clone for add events 2020-08-05 16:03:51 +02:00
Art Lowel
8bfccaa624 fix issue where adding multiple fields at the same time to an empty dropdown would only add the last field 2020-08-05 15:37:10 +02:00
Art Lowel
c2fd019ebd fix exception when adding a field for a repeatable dropdown 2020-08-05 13:55:26 +02:00
Samuel
a29de15f71 Put dynamic workflowgroup links on Collections in an array 2020-08-05 12:41:11 +02:00
Danilo Di Nuzzo
6422288207 added TypeDocs on collection selectior component 2020-08-04 11:55:24 +02:00
ddinuzzo
73b5a376b3 Merge branch 'main' into CST-3091 2020-08-04 11:53:35 +02:00
Danilo Di Nuzzo
4a30e5d7d5 fix response for test submission/vocabularies 2020-08-04 09:43:36 +02:00
Danilo Di Nuzzo
9b69aaaa07 added missing unsubscription in onebox component 2020-08-03 16:52:28 +02:00
Marie Verdonck
e06ff5057a lint 2020-08-03 16:26:10 +02:00
Marie Verdonck
4338250d8d abort travis after script fail, to be able to find cause of failure 2020-08-03 16:26:10 +02:00
Marie Verdonck
26905860ba 71712: Test fixes: eventemitter to subject in confirmation modal 2020-08-03 16:26:10 +02:00
Marie Verdonck
3e0f4a54e6 71712: confirmation modal for export + tests &
- request causing error because of issue #756, commented out for now &
- drop event prevention in a HostListener like dragover event
2020-08-03 16:26:10 +02:00
Marie Verdonck
66cdf9dd18 fdescribe removed 2020-08-03 16:25:38 +02:00
Marie Verdonck
e160d46b81 71713: Dropzone without uploader to own component 2020-08-03 16:25:38 +02:00
Marie Verdonck
9e095d09b6 lint fixes 2020-08-03 16:25:38 +02:00
Marie Verdonck
930512efaa 71713: dropzone padding 2020-08-03 16:25:38 +02:00
Marie Verdonck
393bdf0786 71713: restyle dropzone & rewrite antipattern nested subscribes 2020-08-03 16:25:38 +02:00
Marie Verdonck
9ae68fee32 71713: Tests Import metadata CSV page added 2020-08-03 16:25:38 +02:00
Marie Verdonck
2898cbac6d 71713: Import metadata CSV 2020-08-03 16:25:38 +02:00
Marie Verdonck
d295fa422f 71712: Item export no longer redirects & test async fixes 2020-08-03 16:25:09 +02:00
Marie Verdonck
8f28e989a1 71712: Test fixes 2020-08-03 16:25:09 +02:00
Marie Verdonck
311d93efad 71712: Left out the filter for authorized & metadata-export script exists to show export metadata option for now, until #635 is fixed
See https://github.com/DSpace/dspace-angular/issues/635
If uncommented now: in prod mode: button only available after refresh after login; in dev mode: button not available in any way because authorisation request header is not added to script request
2020-08-03 16:25:09 +02:00
Art Lowel
2f946ba2a3 fix issue where the menu wouldn't update if an option was added after the initial render 2020-08-03 16:25:09 +02:00
Marie Verdonck
d2523ade9b 71712: Check script exists with findBy Id & new tests & test fixes 2020-08-03 16:25:09 +02:00
Marie Verdonck
902d4c2330 71712: Export metadata CSV; WIP 2020-08-03 16:25:09 +02:00
ddinuzzo
793698a6d8 Merge branch 'main' into authorities_and_controlled_vocabularies 2020-08-03 11:00:38 +02:00
Tim Donohue
eb9809801f Merge pull request #799 from atmire/w2p-71806_Curation-tasks-UI
Curation Task Admin UI
2020-07-31 14:14:25 -05:00
Giuseppe Digilio
34da1dc055 Removed angular material dependency 2020-07-31 15:18:41 +02:00
Giuseppe Digilio
0582bc5622 Fixed issue when adding repeatable onebox field with vocabulary 2020-07-31 15:17:51 +02:00
Giuseppe Digilio
79db49043f Make metadata and scope properties as optional in the VocabularyOptions 2020-07-31 14:16:20 +02:00
Giuseppe Digilio
2ed144bd1c Fixed wrong links in mock object 2020-07-31 13:37:26 +02:00
Giuseppe Digilio
c9519f44fb Retrieve entries url from vocabulary's link 2020-07-31 13:30:23 +02:00
Giuseppe Digilio
9ced3530ab Added inline comments 2020-07-30 19:13:59 +02:00
Giuseppe Digilio
090fb94c4d Normalized submission section data when retrieving them from item object 2020-07-30 18:50:47 +02:00
Giuseppe Digilio
85506238b3 Fixed issue with form dropdown field which didn't close menu after entry selection 2020-07-30 18:46:17 +02:00
Giuseppe Digilio
1a9d20161c Fixed issue while preparing json patch value in case of array in the JsonPatchOperationsBuilder 2020-07-30 18:43:19 +02:00
Giuseppe Digilio
7dae82cbbd added virtualValue property to FormFieldMetadataValueObject 2020-07-30 18:41:04 +02:00
Giuseppe Digilio
7e7ce7b06e Added check for VocabularyEntry when initializing a controlled vocabulary component's init model 2020-07-30 18:37:45 +02:00
Yana De Pauw
ce5247253c Remove unused imports 2020-07-30 16:01:59 +02:00
Yana De Pauw
90f68eed7e Add check for config properties provided by server 2020-07-30 15:11:42 +02:00
Yana De Pauw
76ad72f536 71806: Use server config for curation tasks 2020-07-30 14:31:59 +02:00
Kristof De Langhe
23354b45c1 71764: Test changes 2020-07-30 11:24:58 +02:00
Kristof De Langhe
adb51bc06c 71764: authorization-data-service remove eperson param unless provided 2020-07-30 11:09:16 +02:00
Tim Donohue
8b639bc7ba Add keyword fixes & reminder to link to REST PR 2020-07-27 10:46:28 -05:00
Giuseppe Digilio
4779dd209e [CST-3092] fix context 2020-07-27 11:15:15 +02:00
Giuseppe Digilio
3f77ffa1e6 [CST-3092] remove margin bottom 2020-07-27 11:14:56 +02:00
Giuseppe Digilio
2529c91868 Merge remote-tracking branch 'remotes/DSpacegithub/main' into DS-4515_submit-external-source 2020-07-27 09:49:33 +02:00
Tim Donohue
1a46031e4d Add comments about syncing with local.cfg
This seems to be a common question of users. Clarifying via comments.
2020-07-24 11:36:52 -05:00
Giuseppe Digilio
a25ab5620f Merge remote-tracking branch 'remotes/origin/main' into authorities_and_controlled_vocabularies 2020-07-23 11:41:03 +02:00
Giuseppe Digilio
fb1b6c7a7a Changed findEntryDetailByValue method name to a properly findEntryDetailById 2020-07-22 17:49:36 +02:00
Giuseppe Digilio
d88a863a0d fixed issue that didn't allow to select tree node after a search 2020-07-22 17:40:03 +02:00
Giuseppe Digilio
47ab023e7a fixed VocabularyTreeviewComponent selector 2020-07-22 17:03:52 +02:00
Tim Donohue
095d5f3299 Merge pull request #541 from atmire/metadata-and-relationships-combined-in-submission
Combining relationships and metadata during submission
2020-07-22 09:26:55 -05:00
lotte
725481687d added test 2020-07-22 11:34:45 +02:00
Yana De Pauw
3e8ff05d2d 71806: Update messages 2020-07-22 10:49:59 +02:00
Yana De Pauw
2162153ae9 71806: Curation tasks UI 2020-07-22 10:49:59 +02:00
lotte
091ec6c917 added missing typedoc + removed console.logs 2020-07-22 10:27:57 +02:00
Giuseppe Digilio
c8c7e92717 Merge remote-tracking branch 'remotes/origin/main' into authorities_and_controlled_vocabularies
# Conflicts:
#	src/app/core/core.module.ts
2020-07-21 18:57:47 +02:00
Giuseppe Digilio
cb11e3c702 Merge remote-tracking branch 'remotes/origin/main' into authorities_and_controlled_vocabularies 2020-07-21 18:55:48 +02:00
Giuseppe Digilio
6fecdfadb2 Fixed issue that redirect always to home page after checking authentication on CSR 2020-07-21 18:53:09 +02:00
Tim Donohue
9d3f58770a Merge pull request #717 from atmire/Features-support
Features support
2020-07-21 11:41:49 -05:00
lotte
ee8ad1293f removed remaining unnecessary imports for lgtm 2020-07-17 10:41:52 +02:00
lotte
a68428cc12 Merge branch 'main' into metadata-and-relationships-combined-in-submission 2020-07-17 10:03:39 +02:00
lotte
d467af4a35 lgtm feedback fixes 2020-07-17 10:01:56 +02:00
Tim Donohue
b3e90cbce9 Merge pull request #792 from atmire/X-Forwarded-For-Interceptor
IP Authentication: X-Forwarded-For Interceptor
2020-07-16 17:18:25 -05:00
Tim Donohue
84451b1f6f Merge pull request #758 from atmire/DS-630-Item_delete_broken
DS 630 - item delete broken
2020-07-16 15:17:32 -05:00
Tim Donohue
cf2759f6ca Update and rename .github/workflows/pull_request_opened.yml to .github/disabled-workflows/pull_request_opened.yml 2020-07-16 14:20:15 -05:00
Giuseppe Digilio
607318f6c5 Fix CommunityDataService's topLinkPath 2020-07-16 19:51:32 +02:00
Giuseppe Digilio
5950fb2e32 Merge remote-tracking branch 'remotes/github4science/master' into DS-4515_submit-external-source 2020-07-16 17:25:21 +02:00
Giuseppe Digilio
efb2922bb3 Merge remote-tracking branch 'remotes/origin/master' into authorities_and_controlled_vocabularies
# Conflicts:
#	src/app/process-page/form/process-form.component.spec.ts
2020-07-16 17:18:20 +02:00
Giuseppe Digilio
c48b817c2d [CST-3092] Changed start message from external source page 2020-07-16 17:02:12 +02:00
Giuseppe Digilio
1c31deb3df [CST-3092] fixed style issue with external source search bar 2020-07-16 17:01:06 +02:00
Giuseppe Digilio
9225819046 [CST-3092] Removed label from New submission and Import buttons 2020-07-16 17:00:14 +02:00
Giuseppe Digilio
57f436e4ff Merge branch 'DS-4515_submit-external-source' of github.com:4Science/dspace-angular into DS-4515_submit-external-source
 Conflicts:
	src/app/submission/import-external/import-external-preview/submission-import-external-preview.component.spec.ts
2020-07-16 14:51:57 +02:00
Giuseppe Digilio
b8abedb5d6 Fixed test 2020-07-16 14:49:03 +02:00
Giuseppe Digilio
dda2668109 Merge remote-tracking branch 'remotes/origin/master' into authorities_and_controlled_vocabularies 2020-07-16 14:36:37 +02:00
Giuseppe Digilio
c7ef818454 [CST-3088] fix ProcessFormComponent test 2020-07-16 14:35:57 +02:00
Giuseppe Digilio
c33a63aa90 [CST-3088] Removed metadata and collection params when making vocabulary requests 2020-07-16 13:13:24 +02:00
Giuseppe Digilio
a283476403 [CST-3088] Fixed travis failure 2020-07-16 13:08:17 +02:00
Samuel
130a58870e Merge branch 'main' into DS-630-Item_delete_broken 2020-07-16 12:27:28 +02:00
Tim Donohue
a38df3811b Update issue templates 2020-07-15 15:10:53 -05:00
Tim Donohue
7ff250fb0b Merge pull request #795 from DSpace/tdonohue-pr-action
Auto Assign new Pull Requests to "main" branch to the PR creator
2020-07-15 15:05:35 -05:00
Tim Donohue
31e97eec9c Merge pull request #796 from DSpace/tdonohue-issue-action
Automatically add new Issues to "DSpace Backlog" project board
2020-07-15 15:05:13 -05:00
Tim Donohue
2959b73632 Create issue_opened.yml 2020-07-15 14:56:00 -05:00
Tim Donohue
5088da484e Create pull_request_opened.yml 2020-07-15 14:53:44 -05:00
Art Lowel
eeec39bf3f remove debug log 2020-07-15 18:16:45 +02:00
Tim Donohue
8d399fdde8 Initial issue templates
Starting with just a bug report & feature request.
2020-07-14 16:48:15 -05:00
Tim Donohue
23001b6d26 Merge pull request #794 from tdonohue/rename_master_to_main
Replace all references to `master` with `main`
2020-07-14 12:02:52 -05:00
Tim Donohue
47e735270b Rename master to main 2020-07-14 10:44:38 -05:00
Kristof De Langhe
b8a5edd2f3 Merge branch 'main' into w2p-71809_Add-server-side-X-Forwarded-For-interceptor 2020-07-14 17:37:30 +02:00
Kristof De Langhe
522ad4b3dc Merge branch 'main' into w2p-71429_Features-support-part-1
Conflicts:
	src/app/process-page/form/process-form.component.spec.ts
2020-07-14 17:36:20 +02:00
Tim Donohue
0da19b7c75 Merge pull request #793 from atmire/project-rename
Renamed project back to dspace-angular
2020-07-14 10:32:32 -05:00
lotte
1d7a9cd78b removed unused ci script from package.json 2020-07-14 16:39:04 +02:00
lotte
d558a056aa updates to travis scripts to prevent timeout 2020-07-14 16:37:26 +02:00
lotte
1bfc12fe9b added travis_wait to yarn ci command 2020-07-14 16:21:41 +02:00
lotte
08484d31ca renamed project to dspace-angular and fixed broken tests 2020-07-14 15:54:41 +02:00
Kristof De Langhe
3afe8c0b1d 71764: ItemStatusComponent BehaviorSubject for updating operations 2020-07-14 15:13:21 +02:00
Kristof De Langhe
35ca785695 Merge branch 'master' into w2p-71809_Add-server-side-X-Forwarded-For-interceptor
Conflicts:
	src/modules/app/server-app.module.ts
2020-07-14 13:35:11 +02:00
Tim Donohue
e5742c49d9 Merge pull request #760 from tdonohue/update_coveralls
Move coveralls step to "after_success" in Travis CI
2020-07-13 15:39:22 -05:00
Tim Donohue
4648348bd1 Remove deprecated "sudo" key. Add new recommended "os" key 2020-07-13 14:08:47 -05:00
Tim Donohue
e94fbfdcd0 Allow for any version of coveralls compatible with 3.0.0 2020-07-13 12:22:31 -05:00
Tim Donohue
6cd6c096e3 Move coveralls to after_success 2020-07-13 12:22:11 -05:00
Tim Donohue
e053607a17 Merge pull request #714 from 4Science/language-header
Language header
2020-07-13 11:40:09 -05:00
Tim Donohue
b05420ea88 Merge pull request #755 from atmire/reset-scroll-position-on-route-change
Reset scroll position on route change
2020-07-13 11:08:28 -05:00
Kristof De Langhe
0fa1e17078 71809: ForwardClientIpInterceptor 2020-07-13 15:47:59 +02:00
Kristof De Langhe
7f6bd680b2 71764: Test fixes 2020-07-10 14:18:01 +02:00
Kristof De Langhe
7787a2d0e9 71764: SiteRegisterGuard + hide register link when unauthorized 2020-07-10 13:14:55 +02:00
Kristof De Langhe
02fb4a4e4e 71764: Refactor DsoPageAdministratorGuard to more abstract DsoPageFeatureGuard and add implementations for WithdrawItem / ReinstateItem guards 2020-07-10 13:14:55 +02:00
Kristof De Langhe
9a666731e6 71764: Hide withdraw and reinstate button depending on authorization 2020-07-10 13:14:55 +02:00
Kristof De Langhe
73370fa00d 71764: DsoPageAdministratorGuard 2020-07-10 13:14:55 +02:00
Kristof De Langhe
5784493279 71429: Move curation task menu section to admin list 2020-07-10 13:14:43 +02:00
Art Lowel
95163aa226 fix issue due to method signature change after merge 2020-07-09 17:24:00 +02:00
Kristof De Langhe
3560bc60aa 71429: isAuthorized check on feature ID + hide impersonate button when unauthorized 2020-07-09 15:46:14 +02:00
Art Lowel
56d8a99c51 Merge pull request #757 from DSpace/dependabot/npm_and_yarn/npm-registry-fetch-4.0.5
Bump npm-registry-fetch from 4.0.3 to 4.0.5
2020-07-09 15:06:51 +02:00
Samuel
5a1b82d93c fix #630 Item delete broken - repair tests 2020-07-08 13:45:53 +02:00
Samuel
52289d8d23 fix #630 Item delete broken - handle items without entity type 2020-07-08 12:27:51 +02:00
dependabot[bot]
797a640814 Bump npm-registry-fetch from 4.0.3 to 4.0.5
Bumps [npm-registry-fetch](https://github.com/npm/registry-fetch) from 4.0.3 to 4.0.5.
- [Release notes](https://github.com/npm/registry-fetch/releases)
- [Changelog](https://github.com/npm/npm-registry-fetch/blob/latest/CHANGELOG.md)
- [Commits](https://github.com/npm/registry-fetch/commits)

Signed-off-by: dependabot[bot] <support@github.com>
2020-07-08 09:00:35 +00:00
Samuel
deabffd429 fix #630 Item delete broken 2020-07-07 14:31:14 +02:00
Art Lowel
a74dafb959 reset scroll position on route change 2020-07-07 09:51:54 +02:00
Danilo Di Nuzzo
d85b0cb1b1 2020-07-06 18:34:03 +02:00
Kristof De Langhe
bfeeb7c13e Merge branch 'master' into w2p-71429_Features-support-part-1
Conflicts:
	src/app/+admin/admin-sidebar/admin-sidebar.component.ts
	src/app/app-routing.module.ts
	src/app/core/core.module.ts
2020-07-06 16:16:17 +02:00
ddinuzzo
5650a4a235 Merge branch 'master' into language-header 2020-07-06 14:46:14 +02:00
Giuseppe Digilio
a38e5cf632 fixed travis failure 2020-07-06 12:30:53 +02:00
Giuseppe Digilio
7c36051fcc fixed travis failure 2020-07-06 11:24:21 +02:00
Giuseppe Digilio
aa265c02a5 [CST-3088] Fixed travis failure 2020-07-06 10:28:23 +02:00
Matteo Perelli
9ec5709410 CI test fix using TestScheduler 2020-07-06 10:28:17 +02:00
Matteo
633dfaaa6d Merge branch 'master' into DS-4515_submit-external-source 2020-07-06 09:16:07 +02:00
Matteo Perelli
d6a5d9d1dd CI test fix, buttons and searchbar style fix and service methods removed 2020-07-06 09:12:18 +02:00
Giuseppe Digilio
58f18737f7 [CST-3088] tried to resolve travis fail 2020-07-03 15:53:29 +02:00
Giuseppe Digilio
2da96aac25 initialized submission object's sections properly on submission submit 2020-07-03 15:43:08 +02:00
Giuseppe Digilio
9015d50f59 Merge remote-tracking branch 'remotes/origin/master' into authorities_and_controlled_vocabularies
# Conflicts:
#	src/app/core/core.module.ts
#	src/app/shared/shared.module.ts
2020-07-03 09:29:59 +02:00
Art Lowel
bd9a6c487f Merge branch 'master' into metadata-and-relationships-combined-in-submission 2020-07-03 09:26:57 +02:00
Tim Donohue
b731301b39 Merge pull request #749 from atmire/Edit-collection-item-template
Edit collection item template
2020-07-02 12:17:05 -05:00
Art Lowel
d6ab8eff45 Merge branch 'master' into metadata-and-relationships-combined-in-submission 2020-07-02 18:29:10 +02:00
Art Lowel
fe785f6d2f fix issue where create com/col guards would redirect to 404 for the wrong reason 2020-07-02 18:28:30 +02:00
Tim Donohue
0eb7eb6962 Merge pull request #703 from atmire/CC-License-Submission-Step
Cc license submission step
2020-07-02 11:22:33 -05:00
Tim Donohue
3fb4be27df Merge pull request #700 from atmire/Fix-context-sensitive-menus
Fix context sensitive menus
2020-07-02 11:14:43 -05:00
Giuseppe Digilio
2238599a7d [CST-3088] remove duplicated test 2020-07-02 17:57:31 +02:00
Art Lowel
4fa8d02fb2 remove unused imports 2020-07-02 17:32:34 +02:00
Art Lowel
a68dfc1c01 Merge branch 'master' into Fix-context-sensitive-menus 2020-07-02 17:18:20 +02:00
Tim Donohue
a414f04e96 Merge pull request #752 from paulo-graca/patch-3
DSPACE_HOST example fix
2020-07-02 09:53:41 -05:00
Tim Donohue
c2298f6fee Merge pull request #636 from atmire/scripts-processes
Scripts & processes admin UI
2020-07-02 09:46:50 -05:00
Giuseppe Digilio
e46ee579a3 reverted i18n files to master version 2020-07-02 16:33:16 +02:00
Paulo Graça
cece770e8f DSPACE_HOST example fix 2020-07-02 14:54:25 +01:00
ddinuzzo
8c5347ab0f Merge branch 'master' into language-header 2020-07-02 14:51:17 +02:00
Kristof De Langhe
d562b19d57 71429: LGTM fixes 2020-07-02 14:28:35 +02:00
Giuseppe Digilio
599ddf4653 [CST-3088] Renamed browseEntries variable to entries 2020-07-02 14:28:12 +02:00
Kristof De Langhe
ba3c8d2b9e Merge branch 'master' into w2p-71429_Features-support-part-1
Conflicts:
	src/app/core/core.module.ts
	src/app/core/eperson/eperson-data.service.ts
2020-07-02 14:26:19 +02:00
Giuseppe Digilio
3f0ab2cf13 [CST-3088] Fixed lint errors 2020-07-02 14:15:16 +02:00
Giuseppe Digilio
2ad62dd3e9 Merge remote-tracking branch 'remotes/origin/master' into authorities_and_controlled_vocabularies
# Conflicts:
#	src/app/core/cache/response.models.ts
#	src/app/core/core.module.ts
#	src/app/core/data/request.models.ts
#	src/app/shared/shared.module.ts
2020-07-02 14:07:18 +02:00
Art Lowel
5e191ff4d1 Merge pull request #722 from DSpace/dependabot/npm_and_yarn/websocket-extensions-0.1.4
Bump websocket-extensions from 0.1.3 to 0.1.4
2020-07-02 13:51:20 +02:00
Samuel
531ef1fb1b Merge branch 'master' into CC-License-Submission-Step 2020-07-02 13:48:38 +02:00
Samuel
f655f5d149 CC License Submission Step - fix error when saving submission 2020-07-02 12:54:27 +02:00
Kristof De Langhe
92e47dee07 65272: AoT Build fix + LGTM fixes 2020-07-02 12:32:21 +02:00
Giuseppe Digilio
30d53c5954 [CST-3088] Renamed DsDynamicTypeaheadComponent to DsDynamicOneboxComponent 2020-07-02 12:14:19 +02:00
Matteo Perelli
e36cb83622 Additional fix for CI tests 2020-07-02 11:50:39 +02:00
Giuseppe Digilio
e8237f196f [CST-3088] added test for hierarchical vocabulary 2020-07-02 11:42:30 +02:00
Kristof De Langhe
b77fd69ac7 Merge branch 'master' into w2p-65272_Edit-collection-item-template
Conflicts:
	src/app/core/auth/auth-request.service.ts
	src/app/core/core.module.ts
2020-07-02 11:39:30 +02:00
Kristof De Langhe
e234c3a44d 65272: Fixed lint error 2020-07-02 11:12:16 +02:00
Kristof De Langhe
6d802f5078 65272: Edit item template - breadcrumb + title 2020-07-02 11:07:41 +02:00
Kristof De Langhe
e9993c8e16 65272: Fixed readonly error + test cases 2020-07-02 10:21:02 +02:00
Matteo
4370f197ec Merge branch 'master' into DS-4515_submit-external-source 2020-07-02 09:47:58 +02:00
Giuseppe Digilio
44381d7653 [CST-3088] fixed code 2020-07-01 22:57:26 +02:00
Tim Donohue
2fe9965411 Merge pull request #716 from atmire/Authorization-for-downloads-of-restricted-bitstreams
Authorization for downloads of restricted bitstreams
2020-07-01 15:43:20 -05:00
Art Lowel
7cfa0f17a5 add support for authorized downloads 2020-07-01 19:00:21 +02:00
Art Lowel
df5d55c246 Merge branch 'Authorization-for-downloads-of-restricted-bitstreams' into scripts-processes 2020-07-01 18:51:23 +02:00
Art Lowel
68ecc7ac31 rename token param to authentication-token 2020-07-01 18:42:24 +02:00
Samuel
9bbdf95bee CC License Submission Step - fix error when changing accepted license 2020-07-01 18:28:48 +02:00
Art Lowel
c36877ae3a remove debug log 2020-07-01 18:19:52 +02:00
Art Lowel
2cffdc8a86 Merge branch 'master' into metadata-and-relationships-combined-in-submission 2020-07-01 16:59:22 +02:00
Tim Donohue
0e1874d269 Merge pull request #707 from atmire/Forgot-Password
Forgot password
2020-07-01 09:49:14 -05:00
Tim Donohue
71ff276079 Merge pull request #687 from atmire/w2p-70504_New-user-registration
New User Registration
2020-07-01 09:48:23 -05:00
Art Lowel
bcd93de708 Merge branch 'master' into metadata-and-relationships-combined-in-submission 2020-07-01 16:44:38 +02:00
Art Lowel
09f1b7e01f disable fetching and querying all fields 2020-07-01 16:40:16 +02:00
Art Lowel
1d0f0b8304 move schema on metadatafields to an observable remotedata 2020-07-01 16:12:15 +02:00
Giuseppe Digilio
7e80bcf9e9 Merge remote-tracking branch 'remotes/origin/master' into authorities_and_controlled_vocabularies
# Conflicts:
#	src/app/core/cache/response.models.ts
#	src/app/core/core.module.ts
#	src/app/shared/shared.module.ts
2020-07-01 16:04:11 +02:00
Giuseppe Digilio
ca42e2280c [CST-3088] added management of hierarchical vocabulary on typeahead component 2020-07-01 16:00:09 +02:00
Giuseppe Digilio
81f0391400 [CST-3088] Fix lint errors 2020-07-01 15:35:29 +02:00
Giuseppe Digilio
e0604026c5 [CST-3088] Added component to show hierarchical vocabulary as a tree 2020-07-01 15:16:14 +02:00
Giuseppe Digilio
ce61addc9b [CST-3088] Added method to retrieve parent and children for a vocabulary entry 2020-07-01 15:13:52 +02:00
Kristof De Langhe
e0990aeb4b 65272: Test fixes 2020-07-01 14:07:15 +02:00
Kristof De Langhe
71da279d2f 70597: Build fix 2020-07-01 13:09:55 +02:00
Kristof De Langhe
5884308037 Merge branch 'master' into w2p-65272_Edit-collection-item-template
Conflicts:
	src/app/+collection-page/edit-collection-page/collection-metadata/collection-metadata.component.spec.ts
	src/app/+item-page/edit-item-page/abstract-item-update/abstract-item-update.component.ts
	src/app/+item-page/edit-item-page/edit-item-page.module.ts
	src/app/+item-page/edit-item-page/item-metadata/item-metadata.component.ts
	src/app/core/core.module.ts
	src/app/core/data/data.service.ts
2020-07-01 11:47:19 +02:00
Kristof De Langhe
9a4f962a21 71504: Remove unused imports 2020-07-01 11:08:22 +02:00
Kristof De Langhe
9f91fd2ad7 Merge branch 'master' into w2p-71504_Authorization-for-downloads-of-restricted-bitstreams
Conflicts:
	src/app/shared/shared.module.ts
2020-07-01 11:05:05 +02:00
Philip Vissenaekens
150d2cbb71 Merge remote-tracking branch 'origin/w2p-70504_New-user-registration' into Forgot-Password 2020-07-01 10:25:03 +02:00
Philip Vissenaekens
d35f2a419e 70504: removed unused import and variables 2020-07-01 10:15:49 +02:00
lotte
5b46ec1570 fixed test issue 2020-06-30 19:06:46 +02:00
Tim Donohue
199d4bf38f Merge pull request #710 from atmire/w2p-70599_Comcol-tree
Community and Collection Tree fixes
2020-06-30 11:09:18 -05:00
Samuel
ea28998bc1 CC License Submission Step - fix tests bis 2020-06-30 17:31:32 +02:00
Danilo Di Nuzzo
722fdc0124 [CST-2877] rm browser lang for SSR reqs 2020-06-30 16:42:58 +02:00
lotte
a8b7035aff fixed issue with validation 2020-06-30 16:02:32 +02:00
lotte
0348d23aac fixed remove parameter bug 2020-06-30 14:28:58 +02:00
lotte
09665dfbe2 solved lint issues, added typedoc, fixed lgtm warnings 2020-06-30 13:44:38 +02:00
lotte
c7994f9d90 Merge branch 'master' into scripts-processes 2020-06-30 13:25:59 +02:00
Giuseppe Digilio
6ef3f685ca Fixed issue with search requests that weren't fetched again after entry cache was expired 2020-06-30 12:42:48 +02:00
Art Lowel
f4387ac212 Merge branch 'master' into metadata-and-relationships-combined-in-submission 2020-06-30 12:06:56 +02:00
Art Lowel
3e6195a124 Merge branch 'master' into metadata-and-relationships-combined-in-submission 2020-06-30 11:49:08 +02:00
Marie Verdonck
f992fe1afd Feedback: - set initial loading moved outside of of NgZone 2020-06-30 10:55:54 +02:00
Marie Verdonck
6433e211a8 Feedback processed: - change so state change behaviourSubjects back in NgZone.run 2020-06-30 10:55:54 +02:00
Marie Verdonck
94e3f2d5e0 Feedback processed: - pagesize comcol changed to 50 &
- loadCommunities inside ngZone.runOutsideAngular
- Chevron size small unexpanded and large expanded when logged in fixed
2020-06-30 10:55:54 +02:00
Ben Bosman
53779cf69e remove console logs 2020-06-30 10:55:54 +02:00
Marie Verdonck
1dfe7ec170 70599: Test fixes comcol tree after changes 2020-06-30 10:55:54 +02:00
Samuel
3f39752550 CC License Submission Step - fix tests 2020-06-30 10:53:56 +02:00
Marie Verdonck
b1e44a7fa5 70599: Improvements comcol tree 2020-06-30 10:49:30 +02:00
Samuel
6ef60351a5 Merge branch 'master' into CC-License-Submission-Step 2020-06-30 10:29:43 +02:00
Danilo Di Nuzzo
99a6bf52ff Merge branch 'master' into CST-3091 2020-06-30 10:25:01 +02:00
dependabot[bot]
31eadf9c94 Bump websocket-extensions from 0.1.3 to 0.1.4
Bumps [websocket-extensions](https://github.com/faye/websocket-extensions-node) from 0.1.3 to 0.1.4.
- [Release notes](https://github.com/faye/websocket-extensions-node/releases)
- [Changelog](https://github.com/faye/websocket-extensions-node/blob/master/CHANGELOG.md)
- [Commits](https://github.com/faye/websocket-extensions-node/compare/0.1.3...0.1.4)

Signed-off-by: dependabot[bot] <support@github.com>
2020-06-30 08:20:00 +00:00
Danilo Di Nuzzo
d611761548 Merge branch 'master' into language-header 2020-06-30 10:17:03 +02:00
Yana De Pauw
fc1ffd0e18 Merge remote-tracking branch 'upstream/master' into w2p-70504_New-user-registration 2020-06-30 10:10:29 +02:00
Yana De Pauw
ea16289013 Merge remote-tracking branch 'upstream/master' into Forgot-Password 2020-06-30 09:49:51 +02:00
Giuseppe Digilio
3225966600 [CST-3088] Created abstract form component to handle vocabularies 2020-06-29 22:20:52 +02:00
Giuseppe Digilio
4cc1a3eecd [CST-3088] Refactored VocabularyService to use VocabularyOptions and added more methods 2020-06-29 22:18:10 +02:00
lotte
1cb0bb72e4 added create-from functionality 2020-06-29 22:17:41 +02:00
Giuseppe Digilio
df26b85c50 [CST-3088] Create abstract response parsing for entries 2020-06-29 22:15:02 +02:00
Tim Donohue
bb4aedc472 Merge pull request #723 from atmire/async-code-in-beforeeach
Wait for async code in beforeEach
2020-06-29 11:33:52 -05:00
Art Lowel
066e6cd142 fixed a number of instances in community-list-service.spec.ts where async code was presumed synchronous 2020-06-29 17:42:16 +02:00
Art Lowel
e119967325 fix issue where beforeEach wouldn't wait for dropBitstream to end 2020-06-29 17:24:00 +02:00
Art Lowel
775becd656 fix issue where hints wouldn't show for non-repeatable fields, and remove commented out bits of code 2020-06-29 15:34:18 +02:00
Yana De Pauw
1a0e5f4098 Merge remote-tracking branch 'upstream/master' into Forgot-Password 2020-06-29 11:45:33 +02:00
Yana De Pauw
2863837bf8 Merge remote-tracking branch 'upstream/master' into w2p-70504_New-user-registration 2020-06-29 10:42:16 +02:00
ddinuzzo
746a72392f Merge branch 'master' into language-header 2020-06-29 09:36:54 +02:00
Matteo
bcb1682e1d Merge branch 'master' into DS-4515_submit-external-source 2020-06-29 09:15:53 +02:00
Tim Donohue
5b82a8a07b Merge pull request #709 from atmire/Simplify-bitstream-drag-and-drop
Simplify bitstream drag and drop
2020-06-26 17:13:04 -05:00
Tim Donohue
ca564b2ad1 Merge pull request #708 from 4Science/CST-3090-collection-dropdown
Collection dropdown on MyDSpace & support enable/disable in Submission UI
2020-06-26 10:58:48 -05:00
Samuel
0888d81310 CC License Submission Step - fix lint issues 2020-06-26 17:30:06 +02:00
Samuel
fd59e02786 Merge branch 'master' into CC-License-Submission-Step 2020-06-26 16:59:48 +02:00
Samuel
02ddf7c8c5 CC License Submission Step - implement contract change 2020-06-26 16:58:45 +02:00
Danilo Di Nuzzo
806843640f [CST-3091] fix close dialog and test 2020-06-26 16:15:16 +02:00
Danilo Di Nuzzo
8df505b4a0 Merge branch 'master' into CST-3091 2020-06-26 15:31:39 +02:00
lotte
32c8d9de03 scripts & processes improvements 2020-06-26 15:27:48 +02:00
Danilo Di Nuzzo
0ca1798537 [CST-3091] fix tests and add new labels 2020-06-26 15:25:58 +02:00
lotte
9677e053f5 solved merge issues 2020-06-26 14:27:28 +02:00
Kristof De Langhe
0c56e0182a Merge branch 'master' into w2p-71380_Simplify-bitstream-drag-and-drop 2020-06-26 14:24:22 +02:00
lotte
6ad7cee7d1 Merge branch 'master' into scripts-processes 2020-06-26 14:14:21 +02:00
Matteo Perelli
e094663a77 Additional fix for CI tests 2020-06-26 11:19:44 +02:00
Kristof De Langhe
9c27be085e Merge branch 'master' into w2p-71504_Authorization-for-downloads-of-restricted-bitstreams
Conflicts:
	src/app/core/core.module.ts
2020-06-26 10:03:07 +02:00
Danilo Di Nuzzo
573968adc0 Merge branch 'CST-3090-collection-dropdown' into CST-3091 2020-06-26 09:56:01 +02:00
Danilo Di Nuzzo
5642a2798a [CST-3090] fix unused import alerts 2020-06-26 09:55:01 +02:00
Danilo Di Nuzzo
e6b0c20377 Merge branch 'CST-3090-collection-dropdown' into CST-3091 2020-06-26 09:44:09 +02:00
Danilo Di Nuzzo
f37de548c0 [CST-3090] fix position of word 'here' 2020-06-26 09:37:43 +02:00
Matteo Perelli
97b4b90585 Additional fix for CI tests 2020-06-26 09:29:11 +02:00
Danilo Di Nuzzo
59564eb44d [CST-3091] add comp collection-selector, fix issue 2020-06-26 09:25:22 +02:00
Kristof De Langhe
f24bd9fe36 71380: Reset page size 2020-06-25 17:52:02 +02:00
Kristof De Langhe
bfdd943d45 71380: Remove redundant code and add subscribable removeByHrefSubstring 2020-06-25 17:51:11 +02:00
Tim Donohue
bb705919f3 Merge pull request #697 from atmire/Refactor-registry-service-and-associated-models
Refactor registry service and associated models
2020-06-25 10:37:16 -05:00
Matteo Perelli
9ada61db28 Multiple call to external source service fix 2020-06-25 16:58:43 +02:00
Giuseppe Digilio
f71fd5737a [CST-3088] Removed authority and integration services 2020-06-25 15:22:20 +02:00
Giuseppe Digilio
63cca76b49 [CST-3088] Replace use of AuthorityService with new VocabularyService 2020-06-25 15:21:44 +02:00
Kristof De Langhe
73c25998e3 71380: Fix loading/cache issue with dropping objects on page 2020-06-25 11:09:37 +02:00
Giuseppe Digilio
3117916d5b [CST-3088] Added vocabularyEntryDetails's methods to VocabularyService 2020-06-24 19:00:13 +02:00
Kristof De Langhe
fcdd1a8ef2 71429: Test fix 2020-06-24 16:40:50 +02:00
Kristof De Langhe
882ff3ea18 71429: Test fixes 2020-06-24 16:08:10 +02:00
Matteo Perelli
ba46f243c8 Test fix for CI 2020-06-24 15:38:45 +02:00
Kristof De Langhe
080ddf8a1f 71429: Unauthorized page fixes 2020-06-24 15:05:24 +02:00
Kristof De Langhe
78a5bd5fce 71429: Unauthorized component 2020-06-24 14:22:28 +02:00
Kristof De Langhe
0cef62ff48 71429: Feedback 2020-06-23 2020-06-24 13:05:58 +02:00
Giuseppe Digilio
c7cf11f421 [CST-3088] Improved VocabularyFindOptions 2020-06-24 12:52:16 +02:00
Danilo Di Nuzzo
c3192047e1 [CST-2877] fix tests 2020-06-24 12:32:33 +02:00
Matteo Perelli
c25085b299 Lint errors fixed 2020-06-24 11:52:34 +02:00
Danilo Di Nuzzo
ea5f727449 [CST-2877] fix method for lang list & add reload after change lang 2020-06-24 10:55:13 +02:00
Giuseppe Digilio
74d1e0bccb Fixed issue with spyOn 2020-06-24 10:48:29 +02:00
Giuseppe Digilio
0f4e881717 Merge branch 'DS-4515_submit-external-source' of github.com:4Science/dspace-angular into DS-4515_submit-external-source 2020-06-24 10:32:06 +02:00
Giuseppe Digilio
1f54094d5a Fixed components import 2020-06-24 10:31:54 +02:00
Matteo Perelli
0b858805f2 Merge branch 'master' into DS-4515_submit-external-source 2020-06-24 10:29:28 +02:00
Matteo Perelli
43f5e08530 External source import completed with tests 2020-06-24 10:16:30 +02:00
Giuseppe Digilio
1156bd3934 [CST-3088] Added vocabulary service and models 2020-06-23 18:17:47 +02:00
Giuseppe Digilio
e1b80bcbaf [CST-3088] changed buildHrefFromFindOptions in the way to use search params while building url 2020-06-23 18:12:02 +02:00
Matteo Perelli
c2c650fa1a External import button added 2020-06-22 20:26:04 +02:00
Matteo Perelli
0e29fbc2ba Fixed conflicts after merge 2020-06-22 20:25:22 +02:00
Matteo Perelli
b4ec056d03 Removing file for conflicts 2020-06-22 20:23:54 +02:00
Matteo Perelli
2f04b6ae83 External source items import new files 2020-06-22 19:59:29 +02:00
Matteo Perelli
e7ef9dab20 External source items import code completed 2020-06-22 19:59:10 +02:00
Danilo Di Nuzzo
d66d5b6a46 [CST-2877] done (angular) 2020-06-22 17:54:37 +02:00
Art Lowel
a49607ed61 restore property that was accidentally removed during merge 2020-06-22 16:46:11 +02:00
Kristof De Langhe
24858fceab 71504: Shortlived tokens + file-download-link test cases 2020-06-22 13:44:16 +02:00
Art Lowel
a281583f6e fix test and lint issues after merge 2020-06-22 12:26:30 +02:00
Art Lowel
05b2489da5 Merge branch 'master' into metadata-and-relationships-combined-in-submission 2020-06-22 11:50:44 +02:00
Kristof De Langhe
b578aa408b 71504: FileDownloadLinkComponent 2020-06-22 11:40:39 +02:00
Kristof De Langhe
bbaaaed4b5 71504: short-lived token for downloading files through FileService 2020-06-19 17:26:11 +02:00
Kristof De Langhe
72381f4083 71429: Feature and Authorization tests 2020-06-19 15:55:25 +02:00
Giuseppe Digilio
2653980beb Merge remote-tracking branch 'remotes/origin/master' into language-header 2020-06-19 11:19:31 +02:00
Kristof De Langhe
4c1b589158 70834: Use data-service's responseMsToLive for searchBy 2020-06-19 11:09:02 +02:00
Tim Donohue
5cef15eb20 Merge pull request #701 from atmire/Misc-edit-community-and-collection-bugs
Misc edit community and collection fixes
2020-06-18 15:13:40 -05:00
Giuseppe Digilio
63cff331d2 Fixed scrollable dropdown 2020-06-18 19:01:34 +02:00
Kristof De Langhe
89afaaa4a5 71429: Abstract FeatureAuthorizationGuard + small fix 2020-06-18 17:39:11 +02:00
Kristof De Langhe
bbbeddc875 71429: SiteAdministratorGuard on admin routes + authorization check on visibility of admin sidebar sections 2020-06-18 17:13:37 +02:00
Matteo Perelli
fb40b8f031 Submission from an external source initial commit 2020-06-18 16:16:31 +02:00
Danilo Di Nuzzo
f841e45019 [CST-3090] fix tests 2020-06-18 15:38:03 +02:00
Samuel
e963aa9af0 CC License Submission Step - feedback 2020-06-18 15:20:55 +02:00
Kristof De Langhe
8350833b61 71429: FeatureType enum and searchBy override 2020-06-18 14:47:59 +02:00
Samuel
0721b844f5 Misc edit community and collection bugs - repair create top level community 2020-06-18 12:25:50 +02:00
Kristof De Langhe
28891211e4 71380: Reset page size 2020-06-18 12:13:32 +02:00
Kristof De Langhe
82a3014af4 71380: drag-and-drop-list customOrder to avoid elements hopping back after drop + freeze fix 2020-06-18 12:11:20 +02:00
Danilo Di Nuzzo
709726e041 [CST-3105] tests 2020-06-18 12:00:30 +02:00
Danilo Di Nuzzo
136e36afab [CST-3105] done 2020-06-18 11:30:45 +02:00
Samuel
baec130cf3 Merge branch 'master' into Misc-edit-community-and-collection-bugs 2020-06-18 11:15:59 +02:00
Danilo Di Nuzzo
f33f391eb3 [CTS-3090] - fix pagination 2020-06-18 10:23:56 +02:00
Kristof De Langhe
ec998fce30 71429: isAuthenticated and canImpersonate$ 2020-06-18 10:04:18 +02:00
Danilo Di Nuzzo
be2d496335 [CTS-3090] update imports 2020-06-17 17:02:27 +02:00
Danilo Di Nuzzo
3b581b93c5 [CST-3090] fix 2020-06-17 16:31:11 +02:00
Kristof De Langhe
39e0c03593 71429: Feature and Authentication Models and Services 2020-06-17 16:27:25 +02:00
Kristof De Langhe
94cd5b5767 Merge branch 'master' into w2p-68067_Fix-context-sensitive-menus 2020-06-17 13:32:49 +02:00
Kristof De Langhe
752cf97787 71380: Fix tests 2020-06-17 13:12:49 +02:00
Danilo Di Nuzzo
294f5e5f31 [CST-3090] fix services name and dropdown 2020-06-17 10:47:46 +02:00
Giuseppe Digilio
efc476ab31 remove unused disabled$ variable 2020-06-16 17:46:24 +02:00
Yana De Pauw
f5959e9857 Merge remote-tracking branch 'upstream/master' into Forgot-Password 2020-06-16 15:58:59 +02:00
Yana De Pauw
e277a72ebf 71304: Fix spec descriptions 2020-06-16 15:58:19 +02:00
Danilo Di Nuzzo
5f0f665501 [CTS-3090] - fix 2020-06-16 15:51:56 +02:00
Danilo Di Nuzzo
be16134329 Merge branch 'master' into CST-3090-collection-dropdown 2020-06-16 15:18:50 +02:00
Danilo Di Nuzzo
9e05072290 [CST-3090] done 2020-06-16 14:26:59 +02:00
Kristof De Langhe
c6ee46fdea 71380: Reset page size back to normal 2020-06-15 17:57:25 +02:00
Kristof De Langhe
16d3d0e063 71380: Remove object updates for drag-and-drop and send out immediate patch requests for bitstream drag-and-drop 2020-06-15 17:48:03 +02:00
Yana De Pauw
6f9f4ec968 71304: Implement Forgot password components 2020-06-15 11:59:25 +02:00
Samuel
b8ab83ce99 Misc edit community and collection bugs - repair test 2020-06-12 13:58:22 +02:00
Samuel
7421eef223 Misc edit community and collection bugs 2020-06-12 09:54:13 +02:00
Samuel
470c21d8d8 Merge branch 'master' into CC-License-Submission-Step 2020-06-12 09:04:29 +02:00
Samuel
3db47f5791 CC License Submission Step 2 - Storing the results - add SubmissionCcLicenceUrl model 2020-06-12 09:04:00 +02:00
Tim Donohue
8b8d7ba91a Merge pull request #702 from 4Science/CSR-auth-guard-issue
Fixed authentication issue with protected page on CSR
2020-06-11 11:12:37 -05:00
Kristof De Langhe
ee9f5ec7f1 70834: MetadataField search responseMsToLive fix 2020-06-11 15:48:26 +02:00
Giuseppe Digilio
c835d9b9c7 fixed test description 2020-06-11 14:44:42 +02:00
Giuseppe Digilio
6bd04c94ec store token on AUTHENTICATED_SUCCESS action 2020-06-11 14:15:19 +02:00
Samuel
6c1e636f5c fix tests 2020-06-11 13:49:48 +02:00
Art Lowel
405815ac5a fix test 2020-06-11 13:49:48 +02:00
Art Lowel
d27034d634 fix issue where the current collection or community would no longer be selected in the new and edit menus 2020-06-11 13:49:48 +02:00
Kristof De Langhe
9a4fc65331 68067: Fix instance field declaration 2020-06-11 10:50:39 +02:00
Tim Donohue
ea26597b6a Merge pull request #689 from atmire/polyfill-error-fix
fix issue with polyfill order in safari and firefox
2020-06-10 14:20:57 -05:00
Tim Donohue
31b6bfc332 Merge pull request #698 from atmire/FileSizePipe-refactor
FileSizePipe refactor
2020-06-10 13:20:06 -05:00
Yana De Pauw
035a4b6e16 Merge remote-tracking branch 'upstream/master' into Forgot-Password 2020-06-10 17:05:37 +02:00
Kristof De Langhe
9f64fedc7b Merge branch 'master' into w2p-68067_Fix-context-sensitive-menus 2020-06-10 13:10:21 +02:00
Kristof De Langhe
ce04825c4a 71174: FileSizePipe 'jedec' standard 2020-06-10 10:32:58 +02:00
Yana De Pauw
ca7a76b80f Implement community feedback
Remove other registration references
Enabled enter submit in registration form
Fixed create-profile password validation to be on debounce
Fixed register page title
2020-06-10 10:15:06 +02:00
Kristof De Langhe
a51a683215 71174: Breadcrumb test fix 2020-06-04 16:30:16 +02:00
Kristof De Langhe
44386823a3 Merge branch 'master' into w2p-70834_Refactor-registry-service-and-associated-models
Conflicts:
	src/app/core/data/data.service.ts
2020-06-04 16:28:56 +02:00
Kristof De Langhe
b79a3d37f3 Merge remote-tracking branch 'dspace/master' into w2p-71174_FileSizePipe-refactor 2020-06-03 10:56:09 +02:00
Kristof De Langhe
f8f0e5f149 71174: FileSizePipe using filesize.js 2020-06-03 10:54:29 +02:00
Art Lowel
bcb77c8dcc remove comment about zone polyfill 2020-06-02 09:21:49 +02:00
Art Lowel
697be3c610 fix issue with polyfill order in safari and firefox 2020-06-02 09:21:49 +02:00
Tim Donohue
9b7a33cc69 Merge pull request #692 from atmire/fix-minimist-vulnerability
Fix minimist vulnerability
2020-06-01 15:25:17 -05:00
Tim Donohue
3ece498b81 Merge pull request #693 from tdonohue/fix_references_to_environment_js
Fix all outdated references to environment.*.js.
2020-06-01 12:59:48 -05:00
Tim Donohue
b1d39feeda Fix compilation bug in environment.dev.ts used by Docker. Add comments 2020-06-01 11:38:29 -05:00
Bram Luyten
ba9996a3b0 Merge pull request #683 from reetagithub/finnish-msg-keys
Add Finnish translations (first set after master rebase)
2020-05-31 14:48:21 +02:00
Bram Luyten
fcb610412d Activating Finnish in environment.common.ts 2020-05-30 18:15:00 +02:00
Tim Donohue
23e8c8b449 Fix all outdated references to environment.*.js. Fix bug in Docker compose too 2020-05-29 16:52:54 -05:00
Tim Donohue
c423b474ab Merge pull request #691 from atmire/w2p-71201_Angular-UI-does-not-properly-logout-when-clicking-logout
Angular UI does not properly log out when clicking logout
2020-05-29 14:42:18 -05:00
Art Lowel
7b4a481f43 update mkdirp and add resolution for minimist 2020-05-29 17:59:13 +02:00
Art Lowel
ce6b259a3a update karma 2020-05-29 17:35:06 +02:00
Art Lowel
db5ade547d update protractor 2020-05-29 17:28:50 +02:00
Art Lowel
2fbf3afd4a replace deprecated postcss-smart-import with postcss-import 2020-05-29 17:22:34 +02:00
Tim Donohue
45247ff07c Merge pull request #645 from 4Science/#601-resource-policies
#601 resource policies
2020-05-29 10:03:10 -05:00
Art Lowel
d869c6282a Merge pull request #660 from DSpace/dependabot/npm_and_yarn/acorn-6.4.1
Bump acorn from 6.4.0 to 6.4.1
2020-05-29 16:56:12 +02:00
dependabot[bot]
d9749c80c4 Bump acorn from 6.4.0 to 6.4.1
Bumps [acorn](https://github.com/acornjs/acorn) from 6.4.0 to 6.4.1.
- [Release notes](https://github.com/acornjs/acorn/releases)
- [Commits](https://github.com/acornjs/acorn/compare/6.4.0...6.4.1)

Signed-off-by: dependabot[bot] <support@github.com>
2020-05-29 13:46:12 +00:00
Tim Donohue
acd6e6079e Merge pull request #677 from atmire/w2p-70901_ui-environment-vars
Fixed issue with environment UI variables being ignored
2020-05-28 10:57:40 -05:00
Tim Donohue
4ae2977ef2 Merge pull request #682 from 4Science/authentication_issue_CSR
Authentication issue csr
2020-05-28 10:54:22 -05:00
Tim Donohue
56ee4bbaa0 Merge pull request #675 from atmire/w2p-70905_Breadcrumb-update-issue
Fix delay in breadcrumb rendering
2020-05-28 10:49:05 -05:00
Yana De Pauw
1295e127fd 71201: Add test 2020-05-28 15:25:48 +02:00
Yana De Pauw
d24c51e1cd 71201: #678 Angular UI does not properly logout when clicking logout 2020-05-28 14:30:56 +02:00
Giuseppe Digilio
7227d5eefd Remove cached search request after result was retrieved 2020-05-28 11:47:26 +02:00
Giuseppe Digilio
f0bf87b7f9 Show edit group button only when resource policy has permissions on group 2020-05-28 11:39:42 +02:00
Yana De Pauw
36acb7578f Fix to breadcrumb related injector issues on edit pages 2020-05-28 10:50:49 +02:00
Yana De Pauw
d483d46370 70905: Breadcrumb update issue 2020-05-28 10:50:49 +02:00
Yana De Pauw
8fc2309d48 Fix rebase issues 2020-05-28 10:34:03 +02:00
Yana De Pauw
bca1e8bdd4 70504: Implement feedback 2020-05-28 09:43:47 +02:00
Yana De Pauw
96d76073ef 70504: fix compile issue 2020-05-28 09:41:16 +02:00
Yana De Pauw
f136ea7d4f 70504: New user registration 2020-05-28 09:41:16 +02:00
Giuseppe Digilio
5421d97bc5 Merge remote-tracking branch 'remotes/origin/master' into authentication_issue_CSR 2020-05-28 09:23:22 +02:00
Giuseppe Digilio
a57d5d7c4f Merge remote-tracking branch 'remotes/origin/master' into #601-resource-policies 2020-05-28 09:22:11 +02:00
lotte
a9cb6aeaa6 added doc to scripts 2020-05-28 09:15:02 +02:00
lotte
f881c2f428 fixed SSR issues 2020-05-28 09:15:01 +02:00
lotte
e7043f8734 changes to server.ts 2020-05-28 09:15:01 +02:00
lotte
e4a83f0704 fixed ui environment vars issue 2020-05-28 09:15:01 +02:00
Tim Donohue
780b8b7db9 Merge pull request #690 from tdonohue/fix_travis_e2e
Quick fix to Travis e2e testing issues (running against a Docker backend)
2020-05-27 17:00:16 -05:00
Tim Donohue
92b1a4477d Fix Docker local.cfg by correcting UI port to 4000 2020-05-27 15:54:33 -05:00
Kristof De Langhe
7b64d6bc31 68067: JSDocs + menu-effects tests 2020-05-26 14:08:54 +02:00
Kristof De Langhe
0b67bd54fb 68067: Refactoring menu-component resolving route menu data to menu effects 2020-05-26 11:54:33 +02:00
Reeta Kuuskoski
5f6fdf00ec Add Finnish translations (first set after master rebase) 2020-05-25 12:56:34 +03:00
Giuseppe Digilio
460e20284e fixed test 2020-05-22 16:50:48 +02:00
Giuseppe Digilio
b61490341e Added missing class in the authentication form to apply style properly 2020-05-22 16:50:06 +02:00
Giuseppe Digilio
4a65051641 Fixed issue with authentication when SSR is disabled 2020-05-22 16:48:51 +02:00
Giuseppe Digilio
1dde3087ff Fixed failed test 2020-05-22 11:36:02 +02:00
Giuseppe Digilio
c5bf8f6267 Merge remote-tracking branch 'remotes/origin/master' into #601-resource-policies
# Conflicts:
#	src/app/shared/shared.module.ts
2020-05-21 19:35:35 +02:00
Tim Donohue
5c7cd4a27d Merge pull request #653 from atmire/Login-as-EPerson
Login as EPerson
2020-05-21 10:10:04 -05:00
Giuseppe Digilio
b41acfdb33 Moved resource policy's group edit link 2020-05-21 12:21:08 +02:00
Giuseppe Digilio
8ef77df651 Fixed issue with resource policies list that was not updated after a delete 2020-05-21 12:19:24 +02:00
Giuseppe Digilio
51620df76c Fixed issue with item edit page 2020-05-21 12:18:17 +02:00
Giuseppe Digilio
09ee329f17 Fixed failed test 2020-05-21 12:17:37 +02:00
Giuseppe Digilio
e1716751d4 Fixed build error 2020-05-20 18:10:17 +02:00
Giuseppe Digilio
b70f8e12f6 Fixed merge with master 2020-05-20 17:05:54 +02:00
Giuseppe Digilio
b5d92590ee Merge remote-tracking branch 'remotes/origin/master' into #601-resource-policies
# Conflicts:
#	src/app/core/eperson/eperson-data.service.spec.ts
#	src/app/core/eperson/group-data.service.spec.ts
#	src/app/shared/shared.module.ts
#	src/app/submission/sections/upload/section-upload.component.spec.ts
2020-05-20 15:37:33 +02:00
Kristof De Langhe
49bb61b2ae 70834: Registry breadcrumbs 2020-05-20 13:59:00 +02:00
Samuel
18007048a3 CC License Submission Step 2 - Storing the results - feedback 2020-05-20 13:55:42 +02:00
Kristof De Langhe
59205b174f 70834: refactor createOrUpdate methods to use existing data-service methods 2020-05-20 12:30:17 +02:00
Kristof De Langhe
79eecc7c76 68067: Route menu data - menu ID 2020-05-19 17:34:56 +02:00
Kristof De Langhe
8761d0ac27 68067: Add unsubscribes on open subscriptions in menu component 2020-05-19 16:46:58 +02:00
Kristof De Langhe
6d88381ead 68067: Route data menu sections - tests 2020-05-19 16:35:36 +02:00
Samuel
1071506133 CC License Submission Step 2 - Storing the results 2020-05-19 16:02:05 +02:00
Samuel
e802185657 CC License Submission Step - fix tests 2020-05-19 16:02:05 +02:00
Samuel
245cb45503 CC License Submission Step 2020-05-19 16:02:05 +02:00
Kristof De Langhe
ff0750d053 68067: Add menu sections through route data 2020-05-19 14:37:17 +02:00
Kristof De Langhe
172d0d986b 68067: JSON.stringify to compare menu section changes 2020-05-19 12:08:59 +02:00
Kristof De Langhe
8b78ed3a97 68067: Fix adding/removing menu sections 2020-05-19 11:11:07 +02:00
Kristof De Langhe
ad26ececbf Merge branch 'master' into Login-as-EPerson
Conflicts:
	src/app/shared/shared.module.ts
2020-05-19 10:01:10 +02:00
Tim Donohue
b28f59f087 Merge pull request #676 from bram-atmire/sync-i18n-fix
Ensuring environment.ts is present before sync-i18n-files invocation
2020-05-18 10:21:51 -05:00
Bram Luyten
03f910b45d Ensuring environment.ts is present before sync-i18n-files invocation 2020-05-18 15:52:16 +02:00
Tim Donohue
64478870c0 Merge pull request #650 from atmire/w2p-70136_workflow-search-ui
Administer Workflow
2020-05-14 10:22:59 -05:00
Kristof De Langhe
ad8f31d44a 70834: Test fixes + data service tests 2020-05-14 11:29:35 +02:00
Kristof De Langhe
e42785a7a4 70834: MetadataSchemaComponent test fix 2020-05-13 17:42:38 +02:00
Kristof De Langhe
0e9d624519 70834: RegistryService test fixes 2020-05-13 17:32:12 +02:00
Kristof De Langhe
c97e3e0515 70834: Metadata schema component refactoring and caching issue fix #2 2020-05-13 16:49:39 +02:00
Kristof De Langhe
cd46f33909 70834: Metadata schema component refactoring and caching issue fix 2020-05-13 13:56:42 +02:00
lotte
1afa906b21 fixed issue with test import 2020-05-12 18:37:28 +02:00
Kristof De Langhe
3894b3615d 70373: Test import fix 2020-05-12 17:20:02 +02:00
lotte
aa9570c776 Merge branch 'master' into metadata-and-relationships-combined-in-submission 2020-05-12 17:19:08 +02:00
lotte
03668e347e added missing typedoc 2020-05-12 17:03:48 +02:00
Kristof De Langhe
f548d5bf20 Merge branch 'master' into Login-as-EPerson
Conflicts:
	src/app/+admin/admin-access-control/epeople-registry/eperson-form/eperson-form.component.spec.ts
	src/app/core/auth/auth.service.spec.ts
	src/app/profile-page/profile-page.component.spec.ts
2020-05-12 16:54:40 +02:00
Kristof De Langhe
7677a673aa 70834: Intermediate commit 2020-05-12 16:36:03 +02:00
lotte
7ced70b7d3 fixed issues with tests 2020-05-12 16:33:42 +02:00
Kristof De Langhe
101f1a76dd 70834: Refactoring registry-service pt1 - removing response-parsing services and using data-services 2020-05-12 14:54:10 +02:00
Giuseppe Digilio
889a91ba52 Fixed merge 2020-05-11 20:28:31 +02:00
Giuseppe Digilio
bdc0304d5a Merge remote-tracking branch 'remotes/origin/master' into language-header
# Conflicts:
#	src/app/app.component.spec.ts
#	src/app/app.component.ts
#	src/app/shared/lang-switch/lang-switch.component.spec.ts
#	src/app/shared/lang-switch/lang-switch.component.ts
2020-05-11 20:09:39 +02:00
Tim Donohue
33be8a4a91 Merge pull request #663 from atmire/resolve-tsconfig-errors-in-spec-files
[Quickfix] Fix IDE issues with spec files
2020-05-11 09:23:07 -05:00
lotte
a58d6da8e0 added jasmine to root tsconfig.json 2020-05-11 15:05:02 +02:00
lotte
6220c51aa6 fixed tests 2020-05-11 13:28:02 +02:00
Kristof De Langhe
67b73ff921 70597: Test fixes 2020-05-11 13:21:01 +02:00
lotte
e8f418b077 Merge branch 'master' into w2p-70136_workflow-search-ui 2020-05-11 11:58:31 +02:00
lotte
a561f37b00 fixed missing comma 2020-05-11 11:29:29 +02:00
lotte
4f7afc578f Merge branch 'master' into scripts-processes 2020-05-11 11:28:52 +02:00
Art Lowel
bb0f28c9c4 Merge pull request #661 from atmire/fix-prod-server-port
Hotfix: use the server port from the environment file
2020-05-08 13:15:19 +02:00
Art Lowel
4580f1b18a use the server port from the environment file 2020-05-08 12:40:31 +02:00
Art Lowel
4fe2c75810 Merge pull request #625 from atmire/angular-cli
Switch to Angular CLI
2020-05-08 09:16:38 +02:00
lotte
b249a91aaa Merge branch 'master' into angular-cli 2020-05-07 16:11:38 +02:00
Kristof De Langhe
f5f4570116 65272: Allow relationship fields to be edited 2020-05-04 17:57:08 +02:00
Kristof De Langhe
b5e1394fce 65272: Post-merge fixes 2020-05-04 17:38:31 +02:00
Kristof De Langhe
07c8c593ec Merge branch 'master' into w2p-65272_Edit-collection-item-template
Conflicts:
	src/app/+collection-page/collection-page-routing.module.ts
	src/app/+item-page/edit-item-page/abstract-item-update/abstract-item-update.component.ts
	src/app/+item-page/edit-item-page/edit-item-page.module.ts
	src/app/+item-page/edit-item-page/item-metadata/item-metadata.component.ts
	src/app/core/cache/server-sync-buffer.effects.ts
	src/app/core/core.module.ts
	src/app/core/data/data.service.ts
	src/app/core/data/dso-change-analyzer.service.ts
	src/app/core/data/object-updates/object-updates.service.ts
2020-05-04 16:36:46 +02:00
Bram Luyten
519046e769 i18n correction English catalog 2020-05-04 15:09:46 +02:00
Bram Luyten
3b30af3e4d i18n correcting two errors in English main catalog 2020-05-04 13:33:55 +02:00
Giuseppe Digilio
bacb778fa7 Fixed resource policy page buttons 2020-04-30 17:25:00 +02:00
Giuseppe Digilio
b338332d13 Added possibility to search for eperson or group while adding a new resource policy 2020-04-30 15:43:52 +02:00
lotte
84d9e4b063 removed debugger; line 2020-04-30 12:35:25 +02:00
lotte
4c48088920 fixed test issues and watch mode for unit tests 2020-04-30 12:13:41 +02:00
Art Lowel
f3ecd3837e fix issue where mydspace would throw an error while loading 2020-04-29 18:07:52 +02:00
lotte
ef91468310 fixed set-env.ts, reverted unnecessary e2e changes, updated travis.yml 2020-04-29 16:28:26 +02:00
Art Lowel
db169826d5 fix issue where the entered value couldn't be used as a query in the entity lookup for oneboxes 2020-04-29 15:18:56 +02:00
Art Lowel
766015d64c use unique list ids for each submission 2020-04-29 15:00:57 +02:00
Art Lowel
2a6e0c796a fix tests 2020-04-29 14:12:45 +02:00
Art Lowel
c87d0895b0 filter out move operations where source and target are the same 2020-04-28 17:52:01 +02:00
Art Lowel
afe394e2a4 Merge branch 'master' into w2p-70237_entities-orgunit-submission-fix 2020-04-28 17:45:29 +02:00
Art Lowel
673926c36b fix tests and lint issues 2020-04-28 16:35:51 +02:00
Art Lowel
df2cc22172 remove clearStateMetaReducer 2020-04-24 14:06:37 +02:00
Art Lowel
c2789dfbf7 fix issue where a hard refresh wouldn't work to clear the state due to the browser caching the html 2020-04-24 13:16:52 +02:00
Giuseppe Digilio
8635209959 Merge remote-tracking branch 'remotes/origin/master' into #601-resource-policies 2020-04-23 17:05:38 +02:00
lotte
7ec7d3a455 reinstated other tests 2020-04-23 14:30:46 +02:00
lotte
0f43ff4fea switched back to port 4000 2020-04-23 14:17:05 +02:00
lotte
f1d1761fd7 sync i18n script 2020-04-23 14:14:29 +02:00
Art Lowel
e4c4a1ecd4 remove debug log 2020-04-23 13:17:13 +02:00
Art Lowel
facd2284d2 fix issue where related entites would be rendered as metadata for one box fields 2020-04-23 13:16:43 +02:00
Art Lowel
adc7649820 fix an issue where a relationship in the submission would keep loading until you click the page 2020-04-22 18:17:08 +02:00
Art Lowel
056bac885d don't show the plus button for repeatable relationship only fields 2020-04-22 18:10:29 +02:00
Art Lowel
3aefa690b9 fix issue where the disabled field would be rendered for each selected relationship 2020-04-22 18:07:20 +02:00
lotte
ce9fed7507 fixing e2e:ci 2020-04-22 16:28:17 +02:00
lotte
51dd1b1b2b changing timeout 2020-04-22 16:07:22 +02:00
Art Lowel
ecf4b165b1 Merge branch 'metadata-and-relationships-combined-in-submission' into w2p-70237_entities-orgunit-submission-fix 2020-04-22 15:51:42 +02:00
lotte
2caf88bebe reset env variables 2020-04-22 15:30:45 +02:00
lotte
2e367cb87c testing e2e on travis 2020-04-22 15:29:52 +02:00
Art Lowel
dd7fc2aa6f fix issue where editing template rows caused invald patch requests 2020-04-22 15:13:12 +02:00
lotte
1465cfca37 Merge branch 'metadata-and-relationships-combined-in-submission' into w2p-70237_entities-orgunit-submission-fix 2020-04-22 11:45:00 +02:00
Art Lowel
53fd559a7c fix issues with deleting of reorderable array items 2020-04-22 09:49:32 +02:00
lotte
2a353efa5f updated environment file 2020-04-22 07:44:29 +02:00
lotte
6196a99a98 fixed tests 2020-04-21 18:41:38 +02:00
lotte
ad4b7fa254 test travis with external rest 2020-04-21 16:39:51 +02:00
lotte
42740809c0 changed tasks into wfi's 2020-04-21 16:27:26 +02:00
lotte
172d3891f0 switched port to test with Travis 2020-04-21 15:16:42 +02:00
lotte
cad9dcaf98 Merge branch 'master' into angular-cli 2020-04-21 13:45:55 +02:00
lotte
267db6ddce updated dockers files 2020-04-21 13:41:30 +02:00
Giuseppe Digilio
616a5fe0bd Added LocaleInterceptor to set Accept-Language header 2020-04-20 20:07:24 +02:00
Giuseppe Digilio
145b26d262 Added LocaleService as localization handler 2020-04-20 20:06:50 +02:00
lotte
c4d02ff67d fixed import 2020-04-17 16:43:01 +02:00
lotte
37e4e63f81 fixed compilation issue with abstract component 2020-04-17 16:26:26 +02:00
lotte
bbac79bdfc fixes after merge 2020-04-17 16:09:26 +02:00
lotte
92dca8d4e8 Merge branch 'master' into angular-cli 2020-04-17 16:09:12 +02:00
lotte
5aa09eb363 fixed compilation issues 2020-04-17 13:13:04 +02:00
Art Lowel
19bd36a80f switch to patch for reorderin 2020-04-17 11:24:10 +02:00
lotte
450bfe6b3f Merge branch 'metadata-and-relationships-combined-in-submission' into w2p-70237_entities-orgunit-submission-fix 2020-04-17 11:09:03 +02:00
lotte
b29161988d fixed broken tests 2020-04-17 11:06:02 +02:00
Giuseppe Digilio
c03146e415 Fixed resource policy's group edit link 2020-04-16 17:12:20 +02:00
Kristof De Langhe
a6d7b6444c 70373: Remove unnecessary route navigate 2020-04-16 15:12:41 +02:00
lotte
cb61b0adda fixed issue in effects and removed unnecessary console logs 2020-04-16 14:23:23 +02:00
Art Lowel
9a68969eec ensure PUTs are always executed after the PATCH for a move operation 2020-04-15 17:13:43 +02:00
Kristof De Langhe
5e94cf379c 70373: AuthService impersonate tests 2020-04-15 16:47:18 +02:00
Giuseppe Digilio
98ade2eb63 Fixed issue with merge 2020-04-15 16:35:29 +02:00
Kristof De Langhe
7df5025aa5 70373: EPerson impersonate tests 2020-04-15 16:23:41 +02:00
Giuseppe Digilio
4deaf145b6 Merge remote-tracking branch 'remotes/origin/master' into #601-resource-policies
# Conflicts:
#	src/app/core/eperson/eperson-data.service.spec.ts
#	src/app/core/eperson/group-data.service.ts
#	src/app/shared/testing/group-mock.ts
2020-04-15 16:18:27 +02:00
Giuseppe Digilio
b81d8ed900 Added test for ResourcePolicyEditComponent 2020-04-15 16:13:38 +02:00
Giuseppe Digilio
4ac3eb5f9b Added test for ResourcePolicyCreateComponent 2020-04-15 16:13:22 +02:00
Giuseppe Digilio
83a1f9d31d Added test for EpersonGroupListComponent 2020-04-15 16:13:06 +02:00
Giuseppe Digilio
ceaa14e9b2 Added test for ResourcePolicyFormComponent 2020-04-15 16:12:35 +02:00
Giuseppe Digilio
ee38de488c Added test for ResourcePoliciesComponent 2020-04-15 16:12:05 +02:00
Giuseppe Digilio
e7d0c96a26 Added test for ItemAuthorizationsComponent 2020-04-15 16:11:24 +02:00
Kristof De Langhe
4cd11bcbca 70373: Fix existing texts 2020-04-15 15:35:41 +02:00
Art Lowel
2c3d8fd031 remove console log 2020-04-15 15:31:06 +02:00
Art Lowel
d02c41c089 ensure cache times are used for all types of requests 2020-04-15 15:04:31 +02:00
Kristof De Langhe
c48bb2cbb0 70373: Stop impersonating button in navbar + clear cookie on logout 2020-04-15 13:08:04 +02:00
Art Lowel
d6087e3620 remove logs, fix lint issues 2020-04-15 11:24:24 +02:00
Kristof De Langhe
e43aa15a70 70373: Store authenticated EPerson ID in store instead of object 2020-04-15 11:14:41 +02:00
Art Lowel
66a996bb0f add i18n label 2020-04-15 10:55:36 +02:00
Art Lowel
634f4e718e don't pass a query value to the modal if it's readonly 2020-04-15 10:50:10 +02:00
Art Lowel
06cc028c80 use namevariants based on config 2020-04-15 10:34:35 +02:00
Giuseppe Digilio
00f2aa5e1c Renamed ResourcePolicyFormComponent's file 2020-04-14 21:13:43 +02:00
Giuseppe Digilio
46498992a7 Renamed ResourcePolicyFormComponent's file 2020-04-14 20:58:58 +02:00
Kristof De Langhe
638793ca5e 70373: Login as EPerson intermediate commit 2020-04-10 17:41:39 +02:00
Art Lowel
44801701c9 populate submission sections with metadata from single effect 2020-04-10 10:12:21 +02:00
lotte
3d482aed26 removed unnecessary import 2020-04-09 16:17:27 +02:00
lotte
76790be925 Merge branch 'master' into w2p-70136_workflow-search-ui 2020-04-09 11:42:09 +02:00
lotte
3ac575c360 fixed messages for Admin Workflow 2020-04-09 11:29:39 +02:00
Art Lowel
6b0f76c012 fix nullpointer 2020-04-09 10:30:20 +02:00
lotte
9cfed06784 fixed caching issue 2020-04-09 10:20:42 +02:00
Art Lowel
e0d4eb7c9c ensure submissionsection state also contains all metadata after a save 2020-04-08 18:14:29 +02:00
lotte
e43f04e564 finished tests 2020-04-08 15:41:55 +02:00
Art Lowel
85bc11176e Merge branch 'request-by-uuid-issue' into metadata-and-relationships-combined-in-submission 2020-04-07 18:33:11 +02:00
lotte
74db9030b0 working on fixes for OrgUnit field in submission 2020-04-07 18:17:37 +02:00
Art Lowel
558b0b688c Merge branch 'request-by-uuid-issue' into metadata-and-relationships-combined-in-submission 2020-04-07 14:06:26 +02:00
Art Lowel
1fd7989a41 fix test and lint 2020-04-07 11:08:20 +02:00
Art Lowel
e5053c85b0 fix lint issues 2020-04-07 09:30:08 +02:00
Giuseppe Digilio
37fe6d2193 Fixed failed test 2020-04-07 09:29:21 +02:00
Giuseppe Digilio
99c1234a7d Disable policyType and action fields in resource policy edit form 2020-04-07 09:26:24 +02:00
Giuseppe Digilio
0b65bdac46 fixed lint error 2020-04-06 20:47:52 +02:00
Giuseppe Digilio
e078071dfb Intermediate commit 2020-04-06 20:36:56 +02:00
Giuseppe Digilio
b210a36e53 Added new date utils 2020-04-06 20:11:37 +02:00
Giuseppe Digilio
4c391bbae4 Fixed issue with delete operation 2020-04-06 20:11:20 +02:00
Art Lowel
493cbc65fe fix issue where reordering wouldn't work for relationships to cached items 2020-04-06 18:35:10 +02:00
Art Lowel
61624bf606 remove PATCH workaround and fix issue where name variants wouldn't be stored in the Item 2020-04-06 18:20:45 +02:00
Art Lowel
807500db41 fix issue where results wouldn't update after a name variant change 2020-04-06 18:11:27 +02:00
lotte
d003400c16 started fixing tests 2020-04-06 17:45:27 +02:00
Art Lowel
2a58f2480a fix issue where requestservice.getByUUID wouldn't work for requests that were never sent because there was already a copy in the cache 2020-04-06 16:40:45 +02:00
Giuseppe Digilio
5cb0570bc0 Added new date utils 2020-04-06 16:27:58 +02:00
Giuseppe Digilio
9339ae2d7c Merge remote-tracking branch 'remotes/origin/master' into #601-resource-policies
# Conflicts:
#	resources/i18n/en.json5
#	src/app/+item-page/edit-item-page/edit-item-page.module.ts
#	src/app/shared/shared.module.ts
2020-04-04 15:59:44 +02:00
Giuseppe Digilio
6314e17f27 Intermediate commit 2020-04-03 20:25:58 +02:00
lotte
de1b57d8d9 workflow delete/sendback 2020-04-03 18:13:22 +02:00
Art Lowel
f64eff42f4 fix a number of issues with name variants 2020-04-03 17:28:13 +02:00
lotte
2eb3d11cd2 debugging issue commit 2020-04-03 16:00:52 +02:00
Art Lowel
62002f94ef only use name variant after modal closes 2020-04-03 10:23:55 +02:00
Giuseppe Digilio
1ac52edbf7 Added create and delete method to resource policy service 2020-04-02 20:50:02 +02:00
Giuseppe Digilio
b9de6a7a7d Changed DataService's create method in the way to accept array of request params 2020-04-02 19:54:30 +02:00
Giuseppe Digilio
41d6255998 Renamed SearchParam class with a generic name RequestParam 2020-04-02 19:19:38 +02:00
Giuseppe Digilio
5a37891184 Merge remote-tracking branch 'remotes/origin/master' into #601-resource-policies
# Conflicts:
#	src/app/shared/shared.module.ts
2020-04-02 19:12:19 +02:00
Giuseppe Digilio
4f14e546a5 Added fallback strategy for DSONameService to get name for dspace object without a dc.tile metadata 2020-04-02 19:10:22 +02:00
Giuseppe Digilio
fab11e9055 Added component to edit and create a resource policy 2020-04-02 18:58:51 +02:00
Giuseppe Digilio
7f6c88164b Added create and edit resource policy link 2020-04-02 18:57:48 +02:00
Giuseppe Digilio
8913a45a6b Added a form field for selected resource policy target eperson/group 2020-04-02 18:54:34 +02:00
Giuseppe Digilio
b603c7fc05 Added a component that show a paginated list of eperson or group 2020-04-02 18:52:53 +02:00
lotte
258b1228f3 replaced wfi components by task components that render wfi's 2020-04-02 17:05:46 +02:00
lotte
f664cf4c90 made timeout longer for e2e 2020-04-02 17:02:14 +02:00
Art Lowel
924e623b6a fix issue where namvariants wouldn't work 2020-04-02 14:14:36 +02:00
lotte
97953912c5 added waiting until loading is done to e2e tests 2020-04-02 11:22:48 +02:00
lotte
b3ba67e31d Merge branch 'master' into angular-cli 2020-04-02 10:36:37 +02:00
lotte
5bb4065580 print html in e2e to debug 2020-04-02 10:27:08 +02:00
Art Lowel
f93df688e4 remove debug logs 2020-04-02 10:23:11 +02:00
Art Lowel
29e6f6f72f fix issue where the first relationship of a type wouldn't be added 2020-04-02 10:22:08 +02:00
lotte
45beb3f93f Added more thens to e2e tests 2020-04-02 09:44:05 +02:00
lotte
6e49ef6859 start of admin workflow ui 2020-04-01 17:04:54 +02:00
Art Lowel
6dbc2ef880 fix lint issue 2020-04-01 15:55:53 +02:00
Art Lowel
285fe2299a fix test after merge 2020-04-01 15:35:33 +02:00
Art Lowel
a2df95a679 fix lint issues 2020-04-01 14:20:00 +02:00
Art Lowel
987e2d98fd Merge branch 'master' into metadata-and-relationships-combined-in-submission 2020-04-01 14:06:06 +02:00
Art Lowel
2989ca4d96 fix issues with repeatable fields 2020-04-01 11:06:31 +02:00
lotte
5bcc700cc9 fixed e2e issue 2020-04-01 10:43:07 +02:00
lotte
4a52513a38 fixed test 2020-03-31 16:11:13 +02:00
lotte
27fcdab8ad fixed non-existing color in setenv script 2020-03-31 15:04:38 +02:00
lotte
894bee2583 added rimraf to dev deps 2020-03-31 13:52:39 +02:00
lotte
69ba0865a8 fixed test files + added clean for environment.ts + fixed set-env script bug 2020-03-31 13:50:12 +02:00
lotte
6b6068ffb8 Merge branch 'master' into angular-cli 2020-03-31 13:49:40 +02:00
lotte
3a73de90ba fixed alignment issue on new process page 2020-03-31 10:00:02 +02:00
lotte
c225c9015e Added messages and menu links + tests 2020-03-30 15:19:22 +02:00
lotte
b666e3f208 70090: Added trail for processes pages 2020-03-30 15:19:22 +02:00
Kristof De Langhe
d4609b87ea 69940: Fix tests 2020-03-30 15:19:22 +02:00
Kristof De Langhe
6b53c448c8 69940: Processes - date format, back button and hiding empty fields 2020-03-30 15:19:22 +02:00
Kristof De Langhe
5e890aca2c 69940: Process detail - Output Files 2020-03-30 15:19:22 +02:00
Kristof De Langhe
3bac6cc1b3 69940: Process files request 2020-03-30 15:19:22 +02:00
Kristof De Langhe
cf492a92c8 69940: Process detail and overview test cases 2020-03-30 15:19:22 +02:00
Kristof De Langhe
b4bb3acb63 69940: Process details intermediate commit #2 2020-03-30 15:19:22 +02:00
Kristof De Langhe
07a5dceed1 69940: Process detail page intermediate commit 2020-03-30 15:19:22 +02:00
Kristof De Langhe
eacc13a95c 69940: Process overview page 2020-03-30 15:19:22 +02:00
Art Lowel
428abc8282 fix file padding and help text color 2020-03-30 15:19:22 +02:00
lotte
e7a5daad18 fixed tests and feedback 2020-03-30 15:19:22 +02:00
lotte
ef3a235178 added tests and typedoc 2020-03-30 15:19:22 +02:00
lotte
e38aec831f fixed file upload, styling, boolean/date/output inputs 2020-03-30 15:19:22 +02:00
lotte
3e4704af0d working on upload functionality 2020-03-30 15:18:07 +02:00
lotte
ee649debfb moved process data services 2020-03-30 15:18:07 +02:00
lotte
68e2a08af2 added switch for parameter types 2020-03-30 15:17:01 +02:00
lotte
7c9c45b7cb added script parameters & route updates 2020-03-30 15:17:01 +02:00
lotte
1cb39cef41 created new process page 2020-03-30 15:17:01 +02:00
Giuseppe Digilio
1f26a7b634 Show the policies for each bundle and bitstream within the item 2020-03-30 12:57:33 +02:00
Giuseppe Digilio
18d38ca737 Implemented resource policies component 2020-03-30 12:36:36 +02:00
Giuseppe Digilio
be8923d572 Added primaryBitstream and bitstreams properties to Bundle model 2020-03-30 11:43:38 +02:00
Giuseppe Digilio
2e94b349f9 Added eperson and group property to ResourcePolicy model 2020-03-30 11:43:02 +02:00
Giuseppe Digilio
1af5958fa9 Added ngFor track by DSO's id directive 2020-03-30 11:40:58 +02:00
Art Lowel
f61f92e1ad add template file, update readme, remove logs 2020-03-27 15:51:54 +01:00
Giuseppe Digilio
e48b8ad147 Fixed issue with accessCondition in SubmissionSectionUploadAccessConditionsComponent 2020-03-27 12:21:53 +01:00
Giuseppe Digilio
e87c173e96 Fixed issue with getSearchEndpoint which make wrong request to endpointMap 2020-03-27 12:19:20 +01:00
Giuseppe Digilio
ac323f48cc Added item authorizations component 2020-03-27 12:17:59 +01:00
lotte
1caec64115 added npm-run-all 2020-03-27 11:02:07 +01:00
lotte
a3b97f7bd9 fixed notification type 2020-03-27 10:10:44 +01:00
lotte
0850c264b6 added nodemon to watch dev environment changes 2020-03-27 10:06:17 +01:00
lotte
1b7fdfc59c removed custom environment files and fixed config build 2020-03-27 09:10:32 +01:00
lotte
e53727248d environment.ts script 2020-03-26 15:30:41 +01:00
Giuseppe Digilio
e396fe054e Refactored Resource Policy service 2020-03-26 14:40:06 +01:00
lotte
1a318b6f7a Fixed path to coverage report 2020-03-19 12:36:36 +01:00
lotte
9043e1375c fixed e2e script that uses docker 2020-03-19 11:46:18 +01:00
lotte
02c67f4ec0 changed travis/docker setup 2020-03-19 10:48:53 +01:00
lotte
c870b3d02c Merge branch 'master' into angular-cli 2020-03-19 10:27:13 +01:00
Art Lowel
56318ad86b fix followLink tests 2020-03-18 18:32:12 +01:00
lotte
dd0396465e fixed tests except for iterator issue in data services 2020-03-18 17:03:19 +01:00
lotte
8bf241c182 angular cli 2020-03-18 16:03:40 +01:00
Art Lowel
a8d5ad9c37 fix adding of metadata only fields, and styling 2020-02-25 17:01:44 +01:00
Art Lowel
644dcf8ce6 Merge branch 'master' into metadata-and-relationships-combined-in-submission 2020-02-24 16:43:18 +01:00
Art Lowel
212d626e36 Merge branch 'followlink-refactor' into metadata-and-relationships-combined-in-submission 2020-02-24 15:17:13 +01:00
Art Lowel
bc8bacab54 Merge branch 'followlink-refactor' into metadata-and-relationships-combined-in-submission 2020-02-24 14:59:28 +01:00
Art Lowel
9d059e190e Merge branch 'master' into metadata-and-relationships-combined-in-submission 2020-02-24 11:42:55 +01:00
lotte
c98a4a1c3f fixes for replacing/moving 2020-02-19 17:04:37 +01:00
lotte
1a6f67d12e reorderable update fix 2020-02-17 13:23:49 +01:00
lotte
1b8cb5b10c workspace item update after move 2020-02-14 16:50:28 +01:00
lotte
6053d0691f bug fix 2020-02-13 08:49:24 +01:00
Kristof De Langhe
46ab613481 65272: Filter autocomplete metadata fields + fix test 2020-02-11 15:48:56 +01:00
Kristof De Langhe
e3facbd8c8 65272: filter relationship metadata when displaying on item-metadata, keep them stored in the object-updates store 2020-02-11 14:55:08 +01:00
Kristof De Langhe
1885845fef 65272: Clear template-item cache on removal 2020-02-07 17:18:51 +01:00
lotte
0f539ea7d7 trying to fix query in submission entities 2020-02-06 16:28:39 +01:00
lotte
2fc1e6e827 disabled thumbnails in entities results 2020-02-06 14:26:15 +01:00
lotte
32f8842af8 Merge branch 'master' into metadata-and-relationships-combined-in-submission 2020-02-06 08:55:04 +01:00
lotte
6cfcff5503 fixed tests in relaitonship service 2020-02-05 16:53:39 +01:00
lotte
405143388c Merge branch 'master' into metadata-and-relationships-combined-in-submission 2020-02-05 10:54:49 +01:00
lotte
fa0a0dd78c fixed relationship effects tests 2020-02-05 10:38:58 +01:00
lotte
34c5d93a98 fixed more tests 2020-02-04 12:36:17 +01:00
lotte
d1b7f07c68 final bug fixing 2020-02-03 14:49:06 +01:00
lotte
360abb78de intermediate commit 2020-02-03 12:58:24 +01:00
lotte
28747314e6 fixed bug with double selection 2020-01-28 11:29:25 +01:00
lotte
6792f75c38 bug fixing 2020-01-24 17:15:14 +01:00
Kristof De Langhe
53355d1fc4 65272: Test fixes 2020-01-23 17:49:41 +01:00
Kristof De Langhe
d98ce7c97e 65272: Logo spacing layout fix 2020-01-23 17:33:25 +01:00
Kristof De Langhe
98937bd240 65272: Missing JSDocs + id and uuid serializing fix for NormalizedTemplateItem 2020-01-23 17:24:46 +01:00
Kristof De Langhe
a714958c04 65272: Object update PUT to PATCH requests + option to add ignored metadata fields to update 2020-01-23 16:49:31 +01:00
Kristof De Langhe
4ae5ee21b1 65272: Edit template item - Empty metadata alert + alignment fixes 2020-01-23 15:59:47 +01:00
Kristof De Langhe
24fc3e6c76 65272: TemplateItem object and normalized version 2020-01-23 15:14:25 +01:00
Kristof De Langhe
4f048f59f7 Merge branch 'master' into w2p-65272_Edit-collection-item-template
Conflicts:
	resources/i18n/en.json5
	src/app/+collection-page/collection-page.module.ts
	src/app/+collection-page/edit-collection-page/collection-metadata/collection-metadata.component.html
	src/app/+collection-page/edit-collection-page/collection-metadata/collection-metadata.component.spec.ts
	src/app/+collection-page/edit-collection-page/collection-metadata/collection-metadata.component.ts
	src/app/core/core.module.ts
	src/app/core/data/data.service.ts
	src/app/shared/shared.module.ts
2020-01-23 14:30:44 +01:00
lotte
8a6fe08c22 drag drop styling 2020-01-22 14:58:37 +01:00
lotte
002813e25e Merge branch 'master' into metadata-and-relationships-combined-in-submission 2020-01-22 09:37:37 +01:00
lotte
ee3de31d69 fixed remaining test issue 2020-01-20 15:15:01 +01:00
lotte
0854701550 fixed tests 2020-01-20 12:44:29 +01:00
lotte
a4d5e0d20e bug fixing 2020-01-17 16:51:05 +01:00
lotte
db96da55d8 Merge branch 'master' into metadata-and-relationships-combined-in-submission 2020-01-17 13:06:16 +01:00
lotte
a449b79746 Merge branch 'reorder-name-variants' into metadata-and-relationships-combined-in-submission 2020-01-16 13:24:19 +01:00
lotte
c92fb9262c fixes for multiple fields 2020-01-16 12:59:19 +01:00
lotte
ab966c08ac Merge branch 'reorder-name-variants' into metadata-and-relationships-combined-in-submission 2020-01-14 16:16:17 +01:00
lotte
e768169add UX improvements 2020-01-14 15:29:21 +01:00
lotte
23d4b16243 made sure added relationships are shown again, resolved issues with duplicate entries + other bug fixes 2020-01-09 16:23:32 +01:00
lotte
3e9eb9eedc fixed relationship specific labels in modal and cleaned up existing code 2020-01-02 13:48:24 +01:00
lotte
3dfba2ad12 fixed strange test issue 2020-01-02 13:22:10 +01:00
lotte
11d3f33276 added input value as query in modal 2019-12-23 15:36:39 +01:00
lotte
2a686a2fc4 fixed spec error 2019-12-23 13:13:57 +01:00
lotte
5778b3ec6d Merge branch 'reorder-name-variants' into metadata-and-relationships-combined-in-submission 2019-12-23 11:49:42 +01:00
lotte
747606b40f fixed linting errors 2019-12-23 09:27:57 +01:00
lotte
c002d8c640 fixed existing tests 2019-12-23 08:47:46 +01:00
lotte
5ef538a9e8 Merge branch 'reorder-name-variants' into metadata-and-relationships-combined-in-submission 2019-12-23 08:31:22 +01:00
lotte
692a4a4a3d cleanup 2019-12-20 15:08:26 +01:00
lotte
aa7b3b7bb4 fixed remove buttons for both relatinoships and metadata 2019-12-16 15:31:14 +01:00
lotte
e3355455af fixed patch move 2019-12-13 16:58:59 +01:00
lotte
b7f18a1275 fixed issues with concat fields and adding repeatable metadata values in submission 2019-12-11 15:28:24 +01:00
Art Lowel
4cdb1370e2 metadata updates are now sent to the server, but the format is still wrong 2019-12-10 18:30:19 +01:00
lotte
b705e4a0f6 updates styling 2019-12-10 16:52:00 +01:00
lotte
55f14b2885 Merge branch 'metadata-and-relationships-combined-in-submission' of https://git.atmire.com/contributions/dspace-angular into metadata-and-relationships-combined-in-submission 2019-12-10 16:16:52 +01:00
lotte
cce9832037 fixed to row fields 2019-12-10 16:16:07 +01:00
Art Lowel
453a2919d1 store reordered relationships to the server 2019-12-10 15:40:56 +01:00
Art Lowel
b728463e56 make reorderables work for empty values 2019-12-10 10:58:47 +01:00
lotte
84bb44ae62 show metadata values in input fields 2019-12-10 10:22:27 +01:00
Art Lowel
9804161ff1 intermediate commit 2019-12-09 18:32:58 +01:00
Art Lowel
a5047f2f76 hide hints for repeated models of the same field, fix typo 2019-12-09 17:10:49 +01:00
lotte
fa40cac7e7 draggable form groups 2019-12-09 16:33:52 +01:00
lotte
e9f002785a draggable form array controls 2019-12-09 13:51:14 +01:00
lotte
6bba88019e changed rendering of values 2019-12-06 17:02:57 +01:00
lotte
28a0654d20 commit with extra wrapper component 2019-12-06 09:17:08 +01:00
Kristof De Langhe
b3371c5c14 Merge branch 'master' into w2p-65272_Edit-collection-item-template
Conflicts:
	resources/i18n/en.json5
	src/app/+collection-page/collection-page-routing.module.ts
	src/app/+collection-page/collection-page.module.ts
	src/app/core/core.module.ts
	src/app/core/data/data.service.ts
	src/app/shared/shared.module.ts
2019-11-29 11:04:06 +01:00
Kristof De Langhe
b3b8ea1dee 65272: item template REST contract endpoint changes 2019-10-14 16:47:35 +02:00
Kristof De Langhe
7fd4b41460 65272: Added test cases 2019-10-04 17:50:53 +02:00
Kristof De Langhe
088304fce7 Merge branch 'w2p-63669_Edit-Col/Com-Tabs' into w2p-65272_Edit-collection-item-template 2019-10-04 15:48:18 +02:00
Kristof De Langhe
cfdc227563 65272: CollectionMetadataComponent test import fixes 2019-10-04 14:46:59 +02:00
Kristof De Langhe
2eae641703 Merge branch 'master' into w2p-65272_Edit-collection-item-template 2019-10-04 13:35:19 +02:00
Kristof De Langhe
90beee9a85 65272: Existing test fixes 2019-10-04 13:34:56 +02:00
Kristof De Langhe
644ab2cfab 65272: JSDocs 2019-10-04 13:05:15 +02:00
Kristof De Langhe
cf8bba7112 65272: Revert testing changes 2019-10-04 12:38:47 +02:00
Kristof De Langhe
ba436a6467 65272: Functional EditItemTemplatePageComponent 2019-10-04 11:46:14 +02:00
Kristof De Langhe
4cc1f55272 65272: EditItemTemplatePageComponent 2019-10-03 17:50:48 +02:00
Kristof De Langhe
cddaf539aa 65272: add, delete and edit button for collection item template 2019-10-03 16:36:07 +02:00
Kristof De Langhe
143604fa4d 65272: Intermediate commit 2019-10-03 15:07:05 +02:00
Kristof De Langhe
ef9976cf09 Merge branch 'w2p-63669_Edit-Col/Com-Tabs' into w2p-65272_Edit-collection-item-template 2019-10-03 14:41:15 +02:00
Kristof De Langhe
12be9101e5 65272: ItemTemplateDataService 2019-10-03 13:16:46 +02:00
1339 changed files with 44082 additions and 19512 deletions

29
.codecov.yml Normal file
View File

@@ -0,0 +1,29 @@
# DSpace configuration for Codecov.io coverage reports
# These override the default YAML settings at
# https://docs.codecov.io/docs/codecov-yaml#section-default-yaml
# Can be validated via instructions at:
# https://docs.codecov.io/docs/codecov-yaml#validate-your-repository-yaml
# Settings related to code coverage analysis
coverage:
status:
# Configuration for project-level checks. This checks how the PR changes overall coverage.
project:
default:
# For each PR, auto compare coverage to previous commit.
# Require that overall (project) coverage does NOT drop more than 0.5%
target: auto
threshold: 0.5%
# Configuration for patch-level checks. This checks the relative coverage of the new PR code ONLY.
patch:
default:
# For each PR, make sure the coverage of the new code is within 1% of current overall coverage.
# We let 'patch' be more lenient as we only require *project* coverage to not drop significantly.
target: auto
threshold: 1%
# Turn PR comments "off". This feature adds the code coverage summary as a
# comment on each PR. See https://docs.codecov.io/docs/pull-request-comments
# However, this same info is available from the Codecov checks in the PR's
# "Checks" tab in GitHub. So, the comment is unnecessary.
comment: false

View File

@@ -1,5 +1,4 @@
# http://editorconfig.org
# Editor configuration, see https://editorconfig.org
root = true
[*]

22
.github/ISSUE_TEMPLATE/bug_report.md vendored Normal file
View File

@@ -0,0 +1,22 @@
---
name: Bug report
about: Create a report to help us improve
title: ''
labels: bug, needs triage
assignees: ''
---
**Describe the bug**
A clear and concise description of what the bug is. Include the version(s) of DSpace where you've seen this problem & what *web browser* you were using. Link to examples if they are public.
**To Reproduce**
Steps to reproduce the behavior:
1. Do this
2. Then this...
**Expected behavior**
A clear and concise description of what you expected to happen.
**Related work**
Link to any related tickets or PRs here.

View File

@@ -0,0 +1,20 @@
---
name: Feature request
about: Suggest a new feature for this project
title: ''
labels: new feature, needs triage
assignees: ''
---
**Is your feature request related to a problem? Please describe.**
A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
**Describe the solution you'd like**
A clear and concise description of what you want to happen.
**Describe alternatives or workarounds you've considered**
A clear and concise description of any alternative solutions or features you've considered.
**Additional context**
Add any other context or screenshots about the feature request here.

View File

@@ -0,0 +1,26 @@
# This workflow runs whenever a new pull request is created
# TEMPORARILY DISABLED. Unfortunately this doesn't work for PRs created from forked repositories (which is how we tend to create PRs).
# There is no known workaround yet. See https://github.community/t/how-to-use-github-token-for-prs-from-forks/16818
name: Pull Request opened
# Only run for newly opened PRs against the "main" branch
on:
pull_request:
types: [opened]
branches:
- main
jobs:
automation:
runs-on: ubuntu-latest
steps:
# Assign the PR to whomever created it. This is useful for visualizing assignments on project boards
# See https://github.com/marketplace/actions/pull-request-assigner
- name: Assign PR to creator
uses: thomaseizinger/assign-pr-creator-action@v1.0.0
# Note, this authentication token is created automatically
# See: https://docs.github.com/en/actions/configuring-and-managing-workflows/authenticating-with-the-github_token
with:
repo-token: ${{ secrets.GITHUB_TOKEN }}
# Ignore errors. It is possible the PR was created by someone who cannot be assigned
continue-on-error: true

View File

@@ -1,7 +1,7 @@
## References
_Add references/links to any related tickets or PRs. These may include:_
* Link to [Angular issue or PR](https://github.com/DSpace/dspace-angular/issues) related to this PR, if any
* Link to [JIRA](https://jira.lyrasis.org/projects/DS/summary) ticket(s), if any
_Add references/links to any related issues or PRs. These may include:_
* Fixes [GitHub issue](https://github.com/DSpace/dspace-angular/issues), if any
* Requires [REST API PR](https://github.com/DSpace/DSpace/pulls), if any
## Description
Short summary of changes (1-2 sentences).
@@ -20,9 +20,7 @@ _This checklist provides a reminder of what we are going to look for when review
- [ ] My PR is small in size (e.g. less than 1,000 lines of code, not including comments & specs/tests), or I have provided reasons as to why that's not possible.
- [ ] My PR passes [TSLint](https://palantir.github.io/tslint/) validation using `yarn run lint`
- [ ] My PR doesn't introduce circular dependencies
- [ ] My PR includes [TypeDoc](https://typedoc.org/) comments for _all new (or modified) public methods and classes_. It also includes TypeDoc for large or complex private methods.
- [ ] My PR passes all specs/tests and includes new/updated specs for any bug fixes, improvements or new features. A few reminders about what constitutes good tests:
* Include tests for different user types (if behavior differs), including: (1) Anonymous user, (2) Logged in user (non-admin), and (3) Administrator.
* Include tests for error scenarios, e.g. when errors/warnings should appear (or buttons should be disabled).
* For bug fixes, include a test that reproduces the bug and proves it is fixed. For clarity, it may be useful to provide the test in a separate commit from the bug fix.
- [ ] 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/master/LICENSE) based on the [Licensing of Contributions](https://wiki.lyrasis.org/display/DSPACE/Code+Contribution+Guidelines#CodeContributionGuidelines-LicensingofContributions) documentation.
- [ ] 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.

29
.github/workflows/issue_opened.yml vendored Normal file
View File

@@ -0,0 +1,29 @@
# This workflow runs whenever a new issue is created
name: Issue opened
on:
issues:
types: [opened]
jobs:
automation:
runs-on: ubuntu-latest
steps:
# Add the new issue to a project board, if it needs triage
# See https://github.com/marketplace/actions/create-project-card-action
- name: Add issue to project board
# 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
if: (contains(github.event.issue.labels.*.name, 'needs triage') || join(github.event.issue.labels.*.name) == '')
uses: technote-space/create-project-card-action@v1
# 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
# 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)
with:
GITHUB_TOKEN: ${{ secrets.ORG_PROJECT_TOKEN }}
PROJECT: DSpace Backlog
COLUMN: Triage
CHECK_ORG_PROJECT: true
# Ignore errors
continue-on-error: true

View File

@@ -0,0 +1,25 @@
# This workflow checks open PRs for merge conflicts and labels them when conflicts are found
name: Check for merge conflicts
# Run whenever the "main" branch is updated
# NOTE: This means merge conflicts are only checked for when a PR is merged to main.
on:
push:
branches:
- main
jobs:
triage:
runs-on: ubuntu-latest
steps:
# See: https://github.com/mschilde/auto-label-merge-conflicts/
- name: Auto-label PRs with merge conflicts
uses: mschilde/auto-label-merge-conflicts@v2.0
# Add "merge conflict" label if a merge conflict is detected. Remove it when resolved.
# Note, the authentication token is created automatically
# See: https://docs.github.com/en/actions/configuring-and-managing-workflows/authenticating-with-the-github_token
with:
CONFLICT_LABEL_NAME: 'merge conflict'
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
# Ignore errors
continue-on-error: true

7
.gitignore vendored
View File

@@ -7,8 +7,9 @@ npm-debug.log
/build/
/config/environment.dev.js
/config/environment.prod.js
/src/environments/environment.ts
/src/environments/environment.dev.ts
/src/environments/environment.prod.ts
/coverage
@@ -36,3 +37,5 @@ yarn-error.log
package-lock.json
.java-version
.env

View File

@@ -1,58 +1,66 @@
sudo: required
os: linux
dist: bionic
env:
# Install the latest docker-compose version for ci testing.
# The default installation in travis is not compatible with the latest docker-compose file version.
COMPOSE_VERSION: 1.24.1
# 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.
DSPACE_REST_HOST: localhost
DSPACE_REST_PORT: 8080
DSPACE_REST_NAMESPACE: '/server/api'
DSPACE_REST_SSL: false
services:
- xvfb
before_install:
# Docker Compose Install
- curl -L https://github.com/docker/compose/releases/download/${COMPOSE_VERSION}/docker-compose-`uname -s`-`uname -m` > docker-compose
- chmod +x docker-compose
- sudo mv docker-compose /usr/local/bin
install:
# update chrome
- wget -q -O - https://dl-ssl.google.com/linux/linux_signing_key.pub | sudo apt-key add -
- sudo sh -c 'echo "deb [arch=amd64] http://dl.google.com/linux/chrome/deb/ stable main" >> /etc/apt/sources.list.d/google-chrome.list'
- sudo apt-get update
- sudo apt-get install google-chrome-stable
# Start up DSpace 7 using the entities database dump
- docker-compose -f ./docker/docker-compose-travis.yml up -d
# Use the dspace-cli image to populate the assetstore. Trigger a discovery and oai update
- docker-compose -f ./docker/cli.yml -f ./docker/cli.assetstore.yml run --rm dspace-cli
- travis_retry yarn install
before_script:
# The following line could be enabled to verify that the rest server is responding.
# Currently, "yarn run build" takes enough time to run to allow the service to be available
#- curl http://localhost:8080/
after_script:
- docker-compose -f ./docker/docker-compose-travis.yml down
language: node_js
# Enable caching for yarn & node_modules
cache:
yarn: true
node_js:
- "10"
- "12"
cache:
yarn: true
# Install latest chrome (for e2e headless testing). Run an update if needed.
addons:
apt:
sources:
- google-chrome
packages:
- google-chrome-stable
update: true
bundler_args: --retry 5
env:
# 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.
DSPACE_REST_HOST: localhost
DSPACE_REST_PORT: 8080
DSPACE_REST_NAMESPACE: '/server'
DSPACE_REST_SSL: false
before_install:
# Check our versions of everything
- echo "Check versions"
- yarn -v
- docker-compose -v
- google-chrome-stable --version
install:
# Start up a test DSpace 7 REST backend using the entities database dump
- docker-compose -f ./docker/docker-compose-travis.yml up -d
# Use the dspace-cli image to populate the assetstore. Triggers a discovery and oai update
- docker-compose -f ./docker/cli.yml -f ./docker/cli.assetstore.yml run --rm dspace-cli
# Install all local dependencies (retry if initially fails)
- travis_retry yarn install
before_script:
- echo "Check Docker containers"
- docker container ls
# The following line could be enabled to verify that the rest server is responding.
#- echo "Check REST API available (via Docker)"
#- curl http://localhost:8080/server/
script:
- yarn run build
- yarn run ci
- cat coverage/lcov.info | ./node_modules/coveralls/bin/coveralls.js
# build app and run all tests
- ng lint || travis_terminate 1;
- travis_wait yarn run build:prod || travis_terminate 1;
- yarn test:headless || travis_terminate 1;
- yarn run e2e:ci || travis_terminate 1;
after_script:
# Shutdown docker after everything runs
- docker-compose -f ./docker/docker-compose-travis.yml down
# After a successful build and test (see 'script'), send code coverage reports to codecov.io
# These code coverage reports are generated by the codecov node module in our package.json
after_success:
- codecov

View File

@@ -4,9 +4,9 @@
FROM node:12-alpine
WORKDIR /app
ADD . /app/
EXPOSE 3000
EXPOSE 4000
# We run yarn install with an increased network timeout (5min) to avoid "ESOCKETTIMEDOUT" errors from hub.docker.com
# See, for example https://github.com/yarnpkg/yarn/issues/5540
RUN yarn install --network-timeout 300000
CMD yarn run watch
CMD yarn run start:dev

View File

@@ -1,4 +1,4 @@
[![Build Status](https://travis-ci.org/DSpace/dspace-angular.svg?branch=master)](https://travis-ci.org/DSpace/dspace-angular) [![Coverage Status](https://coveralls.io/repos/github/DSpace/dspace-angular/badge.svg?branch=master)](https://coveralls.io/github/DSpace/dspace-angular?branch=master) [![Universal Angular](https://img.shields.io/badge/universal-angular2-brightgreen.svg?style=flat)](https://github.com/angular/universal)
[![Build Status](https://travis-ci.com/DSpace/dspace-angular.svg?branch=main)](https://travis-ci.com/DSpace/dspace-angular) [![Coverage Status](https://codecov.io/gh/DSpace/dspace-angular/branch/main/graph/badge.svg)](https://codecov.io/gh/DSpace/dspace-angular) [![Universal Angular](https://img.shields.io/badge/universal-angular2-brightgreen.svg?style=flat)](https://github.com/angular/universal)
dspace-angular
==============
@@ -29,7 +29,7 @@ yarn install
yarn start
```
Then go to [http://localhost:3000](http://localhost:3000) in your browser
Then go to [http://localhost:4000](http://localhost:4000) in your browser
Not sure where to start? watch the training videos linked in the [Introduction to the technology](#introduction-to-the-technology) section below.
@@ -59,13 +59,13 @@ Table of Contents
Introduction to the technology
------------------------------
You can find more information on the technologies used in this project (Angular.io, Typescript, Angular Universal, RxJS, etc) on the [LYRASIS wiki](https://wiki.lyrasis.org/display/DSPACE/DSpace+7+UI+Technology+Stack)
You can find more information on the technologies used in this project (Angular.io, Angular CLI, Typescript, Angular Universal, RxJS, etc) on the [LYRASIS wiki](https://wiki.lyrasis.org/display/DSPACE/DSpace+7+UI+Technology+Stack)
Requirements
------------
- [Node.js](https://nodejs.org), [npm](https://www.npmjs.com/), and [yarn](https://yarnpkg.com)
- Ensure you're running node `v10.x` or `v12.x`, npm >= `v5.x` and yarn >= `v1.x`
- [Node.js](https://nodejs.org) and [yarn](https://yarnpkg.com)
- Ensure you're running node `v10.x` or `v12.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.
@@ -77,25 +77,53 @@ Installing
### Configuring
Default configuration file is located in `config/` folder.
Default configuration file is located in `src/environments/` folder.
To change the default configuration values, create local files that override the parameters you need to change:
To change the default configuration values, create local files that override the parameters you need to change. You can use `environment.template.ts` as a starting point.
- Create a new `environment.dev.js` file in `config/` for `devel` environment;
- Create a new `environment.prod.js` file in `config/` for `production` environment;
- Create a new `environment.dev.ts` file in `src/environments/` for a `development` environment;
- Create a new `environment.prod.ts` file in `src/environments/` for a `production` environment;
To use the configuration parameters in your component:
The server settings can also be overwritten using an environment file.
This file should be called `.env` and be placed in the project root.
The following settings can be overwritten in this file:
```bash
import { GLOBAL_CONFIG, GlobalConfig } from '../config';
DSPACE_HOST # The host name of the angular application
DSPACE_PORT # The port number of the angular application
DSPACE_NAMESPACE # The namespace of the angular application
DSPACE_SSL # Whether the angular application uses SSL [true/false]
constructor(@Inject(GLOBAL_CONFIG) public config: GlobalConfig) {}
DSPACE_REST_HOST # The host name of the REST application
DSPACE_REST_PORT # The port number of the REST application
DSPACE_REST_NAMESPACE # The namespace of the REST application
DSPACE_REST_SSL # Whether the angular REST uses SSL [true/false]
```
The same settings can also be overwritten by setting system environment variables instead, E.g.:
```bash
export DSPACE_HOST=dspace7.4science.cloud
```
The priority works as follows: **environment variable** overrides **variable in `.env` file** overrides **`environment.(prod, dev or test).ts`** overrides **`environment.common.ts`**
#### Using environment variables in code
To use environment variables in a UI component, use:
```typescript
import { environment } from '../environment.ts';
```
This file is generated by the script located in `scripts/set-env.ts`. This script will run automatically before every build, or can be manually triggered using the appropriate `config` script in `package.json`
Running the app
---------------
After you have installed all dependencies you can now run the app. Run `yarn run watch` to start a local server which will watch for changes, rebuild the code, and reload the server for you. You can visit it at `http://localhost:3000`.
After you have installed all dependencies you can now run the app. Run `yarn run start:dev` to start a local server which will watch for changes, rebuild the code, and reload the server for you. You can visit it at `http://localhost:4000`.
### Running in production mode
@@ -115,14 +143,6 @@ yarn run build:prod
This will build the application and put the result in the `dist` folder
### Deploy
```bash
# deploy production in standalone pm2 container
yarn run deploy
# remove production from standalone pm2 container
yarn run undeploy
```
### Running the application with Docker
See [Docker Runtime Options](docker/README.md)
@@ -155,17 +175,15 @@ If you would like to contribute by testing a Pull Request (PR), here's how to do
* Click it, and follow "Step 1" of those instructions to checkout the pull down the PR branch.
2. `yarn run clean` (This resets your local dependencies to ensure you are up-to-date with this PR)
3. `yarn install` (Updates your local dependencies to those in the PR)
4. `yarn start` (Rebuilds the project, and deploys to localhost:3000, by default)
5. At this point, the code from the PR will be deployed to http://localhost:3000. Test it out, and ensure that it does what is described in the PR (or fixes the bug described in the ticket linked to the PR).
4. `yarn start` (Rebuilds the project, and deploys to localhost:4000, by default)
5. At this point, the code from the PR will be deployed to http://localhost:4000. Test it out, and ensure that it does what is described in the PR (or fixes the bug described in the ticket linked to the PR).
Once you have tested the Pull Request, please add a comment and/or approval to the PR to let us know whether you found it to be successful (or not). Thanks!
### Unit Tests
Unit tests use Karma. You can find the configuration file at the same level of this README file:`./karma.conf.js` If you are going to use a remote test enviroment you need to edit the `./karma.conf.js`. Follow the instructions you will find inside it. To executing tests whenever any file changes you can modify the 'autoWatch' option to 'true' and 'singleRun' option to 'false'. A coverage report is also available at: http://localhost:9876/ after you run: `yarn run coverage`.
To correctly run the tests you need to run the build once with: `yarn run build`.
Unit tests use Karma. You can find the configuration file at the same level of this README file:`./karma.conf.js` If you are going to use a remote test environment you need to edit the `./karma.conf.js`. Follow the instructions you will find inside it. To executing tests whenever any file changes you can modify the 'autoWatch' option to 'true' and 'singleRun' option to 'false'. A coverage report is also available at: http://localhost:9876/ after you run: `yarn run coverage`.
The default browser is Google Chrome.
@@ -177,17 +195,13 @@ and run: `yarn run test`
E2E tests use Protractor + Selenium server + browsers. You can find the configuration file at the same level of this README file:`./protractor.conf.js` Protractor is installed as 'local' as a dev dependency.
If you are going to use a remote test enviroment you need to edit the './protractor.conf.js'. Follow the instructions you will find inside it.
If you are going to use a remote test enviroment you need to edit the './e2e//protractor.conf.js'. Follow the instructions you will find inside it.
The default browser is Google Chrome.
Protractor needs a functional instance of the DSpace interface to run the E2E tests, so you need to run:`yarn run watch`
or any command that bring up the DSpace interface.
Place your tests at the following path: `./e2e`
and run: `yarn run e2e`
and run: `ng e2e`
### Continuous Integration (CI) Test
@@ -200,7 +214,7 @@ See [`./docs`](docs) for further documentation.
### Building code documentation
To build the code documentation we use [TYPEDOC](http://typedoc.org). TYPEDOC is a documentation generator for TypeScript projects. It extracts informations from properly formatted comments that can be written within the code files. Follow the instructions [here](http://typedoc.org/guides/doccomments/) to know how to make those comments.
To build the code documentation we use [TYPEDOC](http://typedoc.org). TYPEDOC is a documentation generator for TypeScript projects. It extracts information from properly formatted comments that can be written within the code files. Follow the instructions [here](http://typedoc.org/guides/doccomments/) to know how to make those comments.
Run:`yarn run docs` to produce the documentation that will be available in the 'doc' folder.
@@ -388,7 +402,7 @@ Frequently asked questions
- Where do I write my tests?
- You can write your tests next to your component files. e.g. for `src/app/home/home.component.ts` call it `src/app/home/home.component.spec.ts`
- How do I start the app when I get `EACCES` and `EADDRINUSE` errors?
- The `EADDRINUSE` error means the port `3000` is currently being used and `EACCES` is lack of permission to build files to `./dist/`
- The `EADDRINUSE` error means the port `4000` is currently being used and `EACCES` is lack of permission to build files to `./dist/`
- What are the naming conventions for Angular 2?
- See [the official angular 2 style guide](https://angular.io/styleguide)
- Why is the size of my app larger in development?

View File

@@ -1,13 +1,158 @@
{
"$schema": "./node_modules/@angular/cli/lib/config/schema.json",
"version": 1,
"cli": {
"defaultCollection": "@ngrx/schematics"
},
"newProjectRoot": "projects",
"projects": {
"core": {
"dspace-angular": {
"projectType": "application",
"schematics": {
"@schematics/angular:component": {
"style": "scss"
}
},
"root": "",
"projectType": "application"
"sourceRoot": "src",
"prefix": "ds",
"architect": {
"build": {
"builder": "@angular-builders/custom-webpack:browser",
"options": {
"customWebpackConfig": {
"path": "./webpack/webpack.browser.ts",
"mergeStrategies": {
"loaders": "prepend"
}
},
"outputPath": "dist/browser",
"index": "src/index.html",
"main": "src/main.browser.ts",
"polyfills": "src/polyfills.ts",
"tsConfig": "tsconfig.app.json",
"aot": false,
"assets": [
"src/assets",
"src/robots.txt"
],
"styles": [
"src/styles.scss"
],
"scripts": []
},
"configurations": {
"production": {
"optimization": true,
"outputHashing": "all",
"extractCss": true,
"namedChunks": false,
"aot": true,
"extractLicenses": true,
"vendorChunk": false,
"buildOptimizer": true,
"budgets": [
{
"type": "initial",
"maximumWarning": "3mb",
"maximumError": "5mb"
},
{
"type": "anyComponentStyle",
"maximumWarning": "6kb",
"maximumError": "10kb"
}
]
}
}
},
"serve": {
"builder": "@angular-builders/custom-webpack:dev-server",
"options": {
"browserTarget": "dspace-angular:build",
"port": 4000
},
"configurations": {
"production": {
"browserTarget": "dspace-angular:build:production"
}
}
},
"extract-i18n": {
"builder": "@angular-devkit/build-angular:extract-i18n",
"options": {
"browserTarget": "dspace-angular:build"
}
},
"test": {
"builder": "@angular-builders/custom-webpack:karma",
"options": {
"customWebpackConfig": {
"path": "./webpack/webpack.test.ts",
"mergeStrategies": {
"loaders": "prepend"
}
},
"main": "src/test.ts",
"polyfills": "src/polyfills.ts",
"tsConfig": "tsconfig.spec.json",
"karmaConfig": "karma.conf.js",
"assets": [
"src/assets"
],
"styles": [
"src/styles.scss"
],
"scripts": []
}
},
"lint": {
"builder": "@angular-devkit/build-angular:tslint",
"options": {
"tsConfig": [
"tsconfig.app.json",
"tsconfig.spec.json",
"e2e/tsconfig.json"
],
"exclude": [
"**/node_modules/**"
]
}
},
"e2e": {
"builder": "@angular-devkit/build-angular:protractor",
"options": {
"protractorConfig": "e2e/protractor.conf.js",
"devServerTarget": "dspace-angular:serve"
},
"configurations": {
"production": {
"devServerTarget": "dspace-angular:serve:production"
}
}
},
"server": {
"builder": "@angular-builders/custom-webpack:server",
"options": {
"customWebpackConfig": {
"path": "./webpack/webpack.prod.ts",
"mergeStrategies": {
"loaders": "prepend"
}
},
"outputPath": "dist/server",
"main": "src/main.server.ts",
"tsConfig": "tsconfig.server.json"
},
"configurations": {
"production": {
"sourceMap": false,
"optimization": {
"scripts": false,
"styles": true
}
}
}
}
}
}
}
}
},
"defaultProject": "dspace-angular"
}

View File

@@ -1,17 +0,0 @@
# Copyright 2015-2016, Google, Inc.
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
# [START app_yaml]
runtime: nodejs
env: flex
# [END app_yaml]

11
browserslist Normal file
View File

@@ -0,0 +1,11 @@
# This file is used by the build system to adjust CSS and JS output to support the specified browsers below.
# For additional information regarding the format and rule options, please see:
# https://github.com/browserslist/browserslist#queries
# You can see what browsers were selected by your queries by running:
# npx browserslist
> 0.5%
last 2 versions
Firefox ESR
not IE 9-11 # For IE 9-11 support, remove 'not'.

View File

@@ -1,4 +0,0 @@
// This configuration is currently only being used for unit tests, end-to-end tests use environment.dev.ts
module.exports = {
};

View File

@@ -11,7 +11,7 @@
- Docker compose file that provides a DSpace CLI container to work with a running DSpace REST container.
- cli.assetstore.yml
- Docker compose file that will download and install data into a DSpace REST assetstore. This script points to a default dataset that will be utilized for CI testing.
- environment.dev.js
- environment.dev.ts
- Environment file for running DSpace Angular in Docker
- local.cfg
- Environment file for running the DSpace 7 REST API in Docker.

View File

@@ -11,7 +11,7 @@ version: "3.7"
services:
dspace-cli:
environment:
- AIPZIP=https://github.com/DSpace-Labs/AIP-Files/raw/master/dogAndReport.zip
- AIPZIP=https://github.com/DSpace-Labs/AIP-Files/raw/main/dogAndReport.zip
- ADMIN_EMAIL=test@test.edu
- AIPDIR=/tmp/aip-dir
entrypoint:

View File

@@ -7,7 +7,7 @@ services:
environment:
DSPACE_HOST: dspace-angular
DSPACE_NAMESPACE: /
DSPACE_PORT: '3000'
DSPACE_PORT: '4000'
DSPACE_SSL: "false"
image: dspace/dspace-angular:latest
build:
@@ -16,11 +16,11 @@ services:
networks:
dspacenet:
ports:
- published: 3000
target: 3000
- published: 4000
target: 4000
- published: 9876
target: 9876
stdin_open: true
tty: true
volumes:
- ./environment.dev.js:/app/config/environment.dev.js
- ./environment.dev.ts:/app/src/environments/environment.dev.ts

View File

@@ -1,16 +1,18 @@
/*
/**
* 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/
*/
module.exports = {
// This file is based on environment.template.ts provided by Angular UI
export const environment = {
// Default to using the local REST API (running in Docker)
rest: {
ssl: false,
host: 'localhost',
port: 8080,
// NOTE: Space is capitalized because 'namespace' is a reserved string in TypeScript
nameSpace: '/server/api'
nameSpace: '/server'
}
};

View File

@@ -1,5 +1,6 @@
dspace.dir=/dspace
db.url=jdbc:postgresql://dspacedb:5432/dspace
dspace.server.url=http://localhost:8080/server
dspace.ui.url=http://localhost:4000
dspace.name=DSpace Started with Docker Compose
solr.server=http://dspacesolr:8983/solr

View File

@@ -1,23 +1,23 @@
# Configuration
Default configuration file is located in `config/` folder. All configuration options should be listed in the default configuration file `config/environment.default.js`. Please do not change this file directly! To change the default configuration values, create local files that override the parameters you need to change:
Default configuration file is located in `src/environments/` folder. All configuration options should be listed in the default configuration file `src/environments/environment.common.ts`. Please do not change this file directly! To change the default configuration values, create local files that override the parameters you need to change. You can use `environment.template.ts` as a starting point.
- Create a new `environment.dev.js` file in `config/` for `devel` environment;
- Create a new `environment.prod.js` file in `config/` for `production` environment;
- Create a new `environment.dev.ts` file in `src/environments/` for `development` environment;
- Create a new `environment.prod.ts` file in `src/environments/` for `production` environment;
Some few configuration options can be overridden by setting environment variables. These and the variable names are listed below.
## Nodejs server
When you start dspace-angular on node, it spins up an http server on which it listens for incoming connections. You can define the ip address and port the server should bind itsself to, and if ssl should be enabled not. By default it listens on `localhost:3000`. If you want it to listen on all your network connections, configure it to bind itself to `0.0.0.0`.
When you start dspace-angular on node, it spins up an http server on which it listens for incoming connections. You can define the ip address and port the server should bind itsself to, and if ssl should be enabled not. By default it listens on `localhost:4000`. If you want it to listen on all your network connections, configure it to bind itself to `0.0.0.0`.
To change this configuration, change the options `ui.host`, `ui.port` and `ui.ssl` in the appropriate configuration file (see above):
```
module.exports = {
// Angular Universal server settings.
export const environment = {
// Angular UI settings.
ui: {
ssl: false,
host: 'localhost',
port: 3000,
port: 4000,
nameSpace: '/'
}
};
@@ -27,7 +27,7 @@ Alternately you can set the following environment variables. If any of these are
```
DSPACE_SSL=true
DSPACE_HOST=localhost
DSPACE_PORT=3000
DSPACE_PORT=4000
DSPACE_NAMESPACE=/
```
@@ -35,14 +35,14 @@ Alternately you can set the following environment variables. If any of these are
dspace-angular connects to your DSpace installation by using its REST endpoint. To do so, you have to define the ip address, port and if ssl should be enabled. You can do this in a configuration file (see above) by adding the following options:
```
module.exports = {
export const environment = {
// The REST API server settings.
rest: {
ssl: true,
host: 'dspace7.4science.it',
host: 'dspace7.4science.cloud',
port: 443,
// NOTE: Space is capitalized because 'namespace' is a reserved string in TypeScript
nameSpace: '/dspace-spring-rest/api'
nameSpace: '/server'
}
};
```
@@ -50,9 +50,9 @@ module.exports = {
Alternately you can set the following environment variables. If any of these are set, it will override all configuration files:
```
DSPACE_REST_SSL=true
DSPACE_REST_HOST=localhost
DSPACE_REST_PORT=3000
DSPACE_REST_NAMESPACE=/
DSPACE_REST_HOST=dspace7.4science.cloud
DSPACE_REST_PORT=443
DSPACE_REST_NAMESPACE=/server
```
## Supporting analytics services other than Google Analytics
@@ -62,4 +62,71 @@ Angulartics can be configured to work with a number of other services besides Go
In order to start using one of these services, select it from the [Angulartics Providers page](https://angulartics.github.io/angulartics2/#providers), and follow the instructions on how to configure it.
The Google Analytics script was added in [`main.browser.ts`](https://github.com/DSpace/dspace-angular/blob/ff04760f4af91ac3e7add5e7424a46cb2439e874/src/main.browser.ts#L33) instead of the `<head>` tag in `index.html` to ensure events get sent when the page is shown in a client's browser, and not when it's rendered on the universal server. Likely you'll want to do the same when adding a new service.
The Google Analytics script was added in [`main.browser.ts`](https://github.com/DSpace/dspace-angular/blob/ff04760f4af91ac3e7add5e7424a46cb2439e874/src/main.browser.ts#L33) instead of the `<head>` tag in `index.html` to ensure events get sent when the page is shown in a client's browser, and not when it's rendered on the universal server. Likely you'll want to do the same when adding a new service.
## SEO when hosting REST Api and UI on different servers
Indexers such as Google Scholar require that files are hosted on the same domain as the page that links them. In DSpace 7, Bitstreams are served from the REST server. So if you use different servers for the REST api and the UI you'll want to ensure that Bitstream downloads are proxied through the UI server.
In order to achieve this we'll need to do two things:
- **Proxy the Bitstream downloads through the UI server.** You'll need to put a webserver such as httpd or nginx in front of the UI server in order to achieve this. [Below](#apache-http-server-config) you'll find a section explaining how to do it in httpd.
- **Update the URLs for Bitstream downloads to match the UI server.** This can be done using a setting in the UI environment file.
### UI config
If you set the property `rewriteDownloadUrls` to `true` in your `environment.prod.ts` file, the [origin](https://developer.mozilla.org/en-US/docs/Glossary/Origin) of any download URL will be replaced by the origin of the UI. This will also happen for the `citation_pdf_url` `<meta>` tag on Item pages.
The app will determine the UI origin currently in use, so the external UI URL doesn't need to be configured anywhere and rewrites will still work if you host the UI from multiple domains.
### Apache HTTP Server config
#### Basics
In order to be able to host bitstreams from the UI Server you'll need to enable mod_proxy and add the following to the httpd config of your UI server:
```
ProxyPassMatch "/server/api/core/bitstreams/([^/]+)/content" "http://rest.api/server/api/core/bitstreams/$1/content"
ProxyPassReverse "/server/api/core/bitstreams/([^/]+)/content" "http://rest.api/server/api/core/bitstreams/$1/content"
```
Replace http://rest.api in with the correct origin for your REST server.
The `ProxyPassMatch` line forwards all requests matching the regular expression for a bitstream download URL to the corresponding path on the REST server
The `ProxyPassReverse` ensures that if the REST server were to return redirect response, httpd would also swap out its hostname for the hostname of the UI before forwarding the response to the client.
#### Using HTTPS
If your REST server uses https, you'll need to enable mod_ssl and ensure `SSLProxyEngine on` is part of your UI server's httpd config as well
If the UI hostname doesn't match the CN in the SSL certificate of the REST server (which is likely if they're on different domains), you'll also need to add the following lines
```
SSLProxyCheckPeerCN off
SSLProxyCheckPeerName off
```
These are two names for [the same directive](https://httpd.apache.org/docs/trunk/mod/mod_ssl.html#sslproxycheckpeername) that have been used for various versions of httpd, old versions need the former, then some in-between versions need both, and newer versions only need the latter. Keeping them both doesn't harm anything.
So the entire config becomes:
```
SSLProxyEngine on
SSLProxyCheckPeerCN off
SSLProxyCheckPeerName off
ProxyPassMatch "/server/api/core/bitstreams/([^/]+)/content" "https://rest.api/server/api/core/bitstreams/$1/content"
ProxyPassReverse "/server/api/core/bitstreams/([^/]+)/content" "https://rest.api/server/api/core/bitstreams/$1/content"
```
If you don't want httpd to verify the certificate of the REST server, you can also turn all checks off with the following config:
```
SSLProxyEngine on
SSLProxyVerify none
SSLProxyCheckPeerCN off
SSLProxyCheckPeerName off
SSLProxyCheckPeerExpire off
ProxyPassMatch "/server/api/core/bitstreams/([^/]+)/content" "https://rest.api/server/api/core/bitstreams/$1/content"
ProxyPassReverse "/server/api/core/bitstreams/([^/]+)/content" "https://rest.api/server/api/core/bitstreams/$1/content"
```

View File

@@ -1,16 +0,0 @@
import { browser, element, by } from 'protractor';
export class ProtractorPage {
navigateTo() {
return browser.get('/')
.then(() => browser.waitForAngular());
}
getPageTitleText() {
return browser.getTitle();
}
getHomePageNewsText() {
return element(by.css('ds-home-news')).getText();
}
}

10
e2e/protractor-ci.conf.js Normal file
View File

@@ -0,0 +1,10 @@
const config = require('./protractor.conf').config;
config.capabilities = {
browserName: 'chrome',
chromeOptions: {
args: ['--headless', '--no-sandbox', '--disable-gpu']
}
};
exports.config = config;

View File

@@ -12,10 +12,10 @@ exports.config = {
// Change to 'false' to run tests using a remote Selenium server
directConnect: true,
// Change if the website to test is not on the localhost
baseUrl: 'http://localhost:3000/',
baseUrl: 'http://localhost:4000/',
// -----------------------------------------------------------------
specs: [
'./e2e/**/*.e2e-spec.ts'
'./src/**/*.e2e-spec.ts'
],
// -----------------------------------------------------------------
// Browser and Capabilities: PhantomJS
@@ -67,7 +67,7 @@ exports.config = {
//],
plugins: [{
path: 'node_modules/protractor-istanbul-plugin'
path: '../node_modules/protractor-istanbul-plugin'
}],
framework: 'jasmine',
@@ -79,7 +79,7 @@ exports.config = {
useAllAngular2AppRoots: true,
beforeLaunch: function () {
require('ts-node').register({
project: 'e2e'
project: './e2e/tsconfig.json'
});
},
onPrepare: function () {

View File

@@ -9,11 +9,14 @@ describe('protractor App', () => {
it('should display translated title "DSpace Angular :: Home"', () => {
page.navigateTo();
page.waitUntilNotLoading();
expect<any>(page.getPageTitleText()).toEqual('DSpace Angular :: Home');
});
it('should contain a news section', () => {
page.navigateTo()
.then(() => expect<any>(page.getHomePageNewsText()).toBeDefined());
page.navigateTo();
page.waitUntilNotLoading();
const text = page.getHomePageNewsText();
expect<any>(text).toBeDefined();
});
});

23
e2e/src/app.po.ts Normal file
View File

@@ -0,0 +1,23 @@
import { browser, element, by, protractor, promise } from 'protractor';
export class ProtractorPage {
navigateTo() {
return browser.get('/')
.then(() => browser.waitForAngular());
}
getPageTitleText() {
return browser.getTitle();
}
getHomePageNewsText() {
return element(by.css('ds-home-news')).getText();
}
waitUntilNotLoading(): promise.Promise<unknown> {
const loading = element(by.css('.loader'))
const EC = protractor.ExpectedConditions;
const notLoading = EC.not(EC.presenceOf(loading));
return browser.wait(notLoading, 10000);
}
}

View File

@@ -1,6 +1,5 @@
import { ProtractorPage } from './search-page.po';
import { browser } from 'protractor';
import { promise } from 'selenium-webdriver';
describe('protractor SearchPage', () => {
let page: ProtractorPage;
@@ -23,9 +22,11 @@ describe('protractor SearchPage', () => {
.then(() => page.getRandomScopeOption())
.then((scopeString: string) => {
page.navigateToSearchWithScopeParameter(scopeString);
page.getCurrentScope().then((s: string) => {
expect<string>(s).toEqual(scopeString);
});
page.waitUntilNotLoading();
page.getCurrentScope()
.then((s: string) => {
expect<string>(s).toEqual(scopeString);
})
});
});
@@ -33,13 +34,16 @@ describe('protractor SearchPage', () => {
page.navigateToSearch()
.then(() => page.getRandomScopeOption())
.then((scopeString: string) => {
page.setCurrentScope(scopeString);
page.submitSearchForm();
browser.wait(() => {
return browser.getCurrentUrl().then((url: string) => {
return url.indexOf('scope=' + encodeURI(scopeString)) !== -1;
});
});
page.setCurrentScope(scopeString)
.then(() => page.submitSearchForm())
.then(() => page.waitUntilNotLoading())
.then(() => () => {
browser.wait(() => {
return browser.getCurrentUrl().then((url: string) => {
return url.indexOf('scope=' + encodeURI(scopeString)) !== -1;
})
})
})
});
});

View File

@@ -27,7 +27,7 @@ export class ProtractorPage {
}
setCurrentScope(scope: string) {
element(by.css('#search-form option[value="' + scope + '"]')).click();
return element(by.css('#search-form option[value="' + scope + '"]')).click();
}
setCurrentQuery(query: string) {
@@ -35,7 +35,7 @@ export class ProtractorPage {
}
submitSearchForm() {
element(by.css('#search-form button.search-button')).click();
return element(by.css('#search-form button.search-button')).click();
}
getRandomScopeOption(): promise.Promise<string> {
@@ -46,4 +46,10 @@ export class ProtractorPage {
});
}
waitUntilNotLoading(): promise.Promise<unknown> {
const loading = element(by.css('.loader'));
const EC = protractor.ExpectedConditions;
const notLoading = EC.not(EC.presenceOf(loading));
return browser.wait(notLoading, 10000);
}
}

View File

@@ -1,176 +1,37 @@
/**
* @author: @AngularClass
*/
// Karma configuration file, see link for more information
// https://karma-runner.github.io/1.0/config/configuration-file.html
module.exports = function (config) {
var testWebpackConfig = require('./webpack/webpack.test.js')({
env: 'test'
});
// Uncomment and change to run tests on a remote Selenium server
var webdriverConfig = {
hostname: 'localhost',
port: 4444
};
var configuration = {
client: {
jasmine: {
random: false
}
},
// base path that will be used to resolve all patterns (e.g. files, exclude)
config.set({
basePath: '',
/*
* Frameworks to use
*
* available frameworks: https://npmjs.org/browse/keyword/karma-adapter
*/
frameworks: ['jasmine'],
frameworks: ['jasmine', '@angular-devkit/build-angular'],
plugins: [
require("istanbul-instrumenter-loader"),
require('karma-chrome-launcher'),
require('karma-coverage'),
require("karma-istanbul-preprocessor"),
require('karma-jasmine'),
require('karma-chrome-launcher'),
require('karma-jasmine-html-reporter'),
require('karma-coverage-istanbul-reporter'),
require('@angular-devkit/build-angular/plugins/karma'),
require('karma-mocha-reporter'),
require('karma-phantomjs-launcher'),
require('karma-remap-coverage'),
require('karma-remap-istanbul'),
require('karma-sourcemap-loader'),
require('karma-webdriver-launcher'),
require('karma-webpack')
],
// list of files to exclude
exclude: [],
/*
* list of files / patterns to load in the browser
*
* we are building the test environment in ./spec-bundle.js
*/
files: [{
pattern: './spec-bundle.js',
watched: false,
}],
/*
* preprocess matching files before serving them to the browser
* available preprocessors: https://npmjs.org/browse/keyword/karma-preprocessor
*/
preprocessors: {
'./spec-bundle.js': [
'istanbul',
'webpack',
'sourcemap'
]
client: {
clearContext: false // leave Jasmine Spec Runner output visible in browser
},
// Webpack Config at ./webpack.test.js
webpack: testWebpackConfig,
// save interim raw coverage report in memory
coverageReporter: {
type: 'in-memory'
coverageIstanbulReporter: {
dir: require('path').join(__dirname, './coverage/dspace-angular'),
reports: ['html', 'lcovonly', 'text-summary'],
fixWebpackSourcePaths: true
},
remapCoverageReporter: {
'text-summary': null, // to show summary in console
html: './coverage/html',
cobertura: './coverage/cobertura.xml'
},
remapIstanbulReporter: {
remapOptions: {}, //additional remap options
reports: {
json: './coverage/coverage.json',
lcovonly: './coverage/lcov.info',
html: './coverage/html/',
}
},
/**
* Webpack please don't spam the console when running in karma!
*/
webpackMiddleware: {
/**
* webpack-dev-middleware configuration
* i.e.
*/
noInfo: true,
/**
* and use stats to turn off verbose output
*/
stats: {
/**
* options i.e.
*/
chunks: false
}
},
/*
* test results reporter to use
*
* possible values: 'dots', 'progress'
* available reporters: https://npmjs.org/browse/keyword/karma-reporter
*/
reporters: [
'mocha',
'coverage',
'remap-coverage',
'karma-remap-istanbul'
],
// Karma web server port
port: 9876,
// enable / disable colors in the output (reporters and logs)
colors: true,
/*
* level of logging
* possible values: config.LOG_DISABLE || config.LOG_ERROR || config.LOG_WARN || config.LOG_INFO || config.LOG_DEBUG
*/
logLevel: config.LOG_WARN,
// enable / disable watching file and executing tests whenever any file changes
autoWatch: false,
/*
* start these browsers
* available browser launchers: https://npmjs.org/browse/keyword/karma-launcher
*/
browsers: [
'Chrome'
],
customLaunchers: {
// Remote Selenium Server with Chrome - launcher
'SeleniumChrome': {
base: 'WebDriver',
config: webdriverConfig,
browserName: 'chrome'
},
// Remote Selenium Server with Firefox - launcher
'SeleniumFirefox': {
base: 'WebDriver',
config: webdriverConfig,
browserName: 'firefox'
}
},
reporters: ['mocha', 'kjhtml'],
mochaReporter: {
ignoreSkipped: true
ignoreSkipped: true,
output: 'autowatch'
},
browserNoActivityTimeout: 30000
};
config.set(configuration);
port: 9876,
colors: true,
logLevel: config.LOG_INFO,
autoWatch: true,
browsers: ['Chrome'],
singleRun: false,
restartOnFileChange: true
});
};

5
mock-nodemon.json Normal file
View File

@@ -0,0 +1,5 @@
{
"watch": ["src/environments/mock-environment.ts"],
"ext": "ts",
"exec": "ts-node --project ./tsconfig.ts-node.json scripts/set-mock-env.ts"
}

View File

@@ -1,9 +1,6 @@
{
"watch": [
"dist",
"config",
"src/index.html"
],
"ext": "js ts json html",
"delay": "50"
"watch": ["src/environments"],
"ext": "ts",
"ignore": ["src/environments/environment.ts", "src/environments/mock-environment.ts"],
"exec": "ts-node --project ./tsconfig.ts-node.json scripts/set-env.ts --dev"
}

View File

@@ -1,21 +1,37 @@
{
"name": "dspace-angular",
"version": "0.0.1",
"description": "Angular Universal UI for DSpace",
"repository": {
"type": "git",
"url": "https://github.com/dspace/dspace-angular.git"
},
"license": "BSD-2-Clause",
"engines": {
"node": "10.* || >= 12.*"
},
"resolutions": {
"serialize-javascript": ">= 2.1.2",
"set-value": ">= 2.0.1"
},
"version": "0.0.0",
"scripts": {
"global": "npm install -g @angular/cli marked node-gyp nodemon node-nightly npm-check-updates npm-run-all rimraf typescript ts-node typedoc webpack webpack-bundle-analyzer pm2 rollup",
"ng": "ng",
"config:dev": "ts-node --project ./tsconfig.ts-node.json scripts/set-env.ts --dev",
"config:prod": "ts-node --project ./tsconfig.ts-node.json scripts/set-env.ts --prod",
"config:test": "ts-node --project ./tsconfig.ts-node.json scripts/set-mock-env.ts",
"config:test:watch": "nodemon --config mock-nodemon.json",
"config:dev:watch": "nodemon",
"prestart:dev": "yarn run config:dev",
"prebuild": "yarn run config:dev",
"pretest": "yarn run config:test",
"pretest:watch": "yarn run config:test",
"pretest:headless": "yarn run config:test",
"prebuild:prod": "yarn run config:prod",
"pree2e": "yarn run config:prod",
"pree2e:ci": "yarn run config:prod",
"start": "yarn run start:prod",
"serve": "ts-node --project ./tsconfig.ts-node.json scripts/serve.ts",
"start:dev": "npm-run-all --parallel config:dev:watch serve",
"start:prod": "yarn run build:prod && yarn run serve:ssr",
"build": "ng build",
"build:prod": "yarn run build:ssr",
"build:ssr": "yarn run build:client-and-server-bundles && yarn run compile:server",
"build:client-and-server-bundles": "node --max_old_space_size=8192 node_modules/@angular/cli/bin/ng build --prod && ng run dspace-angular:server:production --bundleDependencies all",
"test:watch": "npm-run-all --parallel config:test:watch test",
"test": "node --max_old_space_size=8192 node_modules/@angular/cli/bin/ng test --sourceMap=true --watch=true",
"test:headless": "node --max_old_space_size=8192 node_modules/@angular/cli/bin/ng test --watch=false --sourceMap=true --browsers=ChromeHeadless --code-coverage",
"lint": "ng lint",
"e2e": "ng e2e",
"e2e:ci": "ng e2e --protractor-config=./e2e/protractor-ci.conf.js",
"compile:server": "webpack --config webpack.server.config.js --progress --colors",
"serve:ssr": "node dist/server",
"clean:coverage": "rimraf coverage",
"clean:dist": "rimraf dist",
"clean:doc": "rimraf doc",
@@ -24,108 +40,68 @@
"clean:bld": "rimraf build",
"clean:node": "rimraf node_modules",
"clean:prod": "yarn run clean:coverage && yarn run clean:doc && yarn run clean:dist && yarn run clean:log && yarn run clean:json && yarn run clean:bld",
"clean": "yarn run clean:prod && yarn run clean:node",
"prebuild": "yarn run clean:bld && yarn run clean:dist",
"prebuild:ci": "yarn run prebuild",
"prebuild:prod": "yarn run prebuild",
"build": "node ./scripts/webpack.js --progress --mode development",
"build:ci": "yarn run syncbuilddir && node ./scripts/webpack.js --env.aot --env.server --mode development && node ./scripts/webpack.js --env.aot --env.client --mode development",
"build:prod": "yarn run syncbuilddir && node ./scripts/webpack.js --env.aot --env.server --mode production && node ./scripts/webpack.js --env.aot --env.client --mode production",
"postbuild:prod": "yarn run rollup",
"rollup": "rollup -c rollup.config.js",
"prestart": "yarn run build:prod",
"prestart:dev": "yarn run build",
"start": "yarn run server",
"start:dev": "yarn run server",
"deploy": "pm2 start dist/server.js",
"predeploy": "npm run build:prod",
"preundeploy": "pm2 stop dist/server.js",
"undeploy": "pm2 delete dist/server.js",
"postundeploy": "npm run clean:dist",
"server": "node dist/server.js",
"server:watch": "nodemon dist/server.js",
"server:watch:debug": "nodemon --debug dist/server.js",
"syncbuilddir": "node ./scripts/sync-build-dir.js",
"webpack:watch": "node ./scripts/webpack.js -w --mode development",
"watch": "yarn run build && npm-run-all -p webpack:watch server:watch",
"watch:debug": "yarn run build && npm-run-all -p webpack:watch server:watch:debug",
"predebug": "yarn run build",
"predebug:server": "yarn run build",
"debug": "node --debug-brk dist/server.js",
"debug:server": "node-nightly --inspect --debug-brk dist/server.js",
"debug:build": "node-nightly --inspect --debug-brk node_modules/webpack/bin/webpack.js --mode development",
"debug:build:prod": "node-nightly --inspect --debug-brk node_modules/webpack/bin/webpack.js --env.aot --env.client --env.server --mode production",
"ci": "yarn run lint && yarn run build:ci && yarn run test:headless && npm-run-all -p -r server e2e",
"protractor": "node node_modules/protractor/bin/protractor",
"pree2e": "yarn run webdriver:update",
"e2e": "yarn run protractor",
"pretest": "yarn run clean:bld",
"pretest:headless": "yarn run pretest",
"pretest:watch": "yarn run pretest",
"test": "karma start --single-run",
"test:headless": "karma start --single-run --browsers ChromeHeadless",
"test:watch": "karma start --no-single-run --auto-watch",
"webdriver:start": "node node_modules/protractor/bin/webdriver-manager start --seleniumPort 4444",
"webdriver:update": "node node_modules/protractor/bin/webdriver-manager update --standalone --gecko false",
"lint": "tslint \"src/**/*.ts\" && tslint \"e2e/**/*.ts\"",
"docs": "typedoc --options typedoc.json ./src/",
"coverage": "http-server -c-1 -o -p 9875 ./coverage",
"postinstall": "yarn run patch-protractor",
"patch-protractor": "ncp node_modules/webdriver-manager node_modules/protractor/node_modules/webdriver-manager",
"sync-i18n": "node ./scripts/sync-i18n-files.js"
"clean": "yarn run clean:prod && yarn run clean:node && yarn run clean:env",
"clean:env": "rimraf src/environments/environment.ts",
"sync-i18n": "yarn run config:dev && ts-node --project ./tsconfig.ts-node.json scripts/sync-i18n-files.ts"
},
"browser": {
"fs": false,
"path": false,
"http": false,
"https": false
},
"private": true,
"resolutions": {
"minimist": "^1.2.5"
},
"dependencies": {
"@angular/animations": "^8.2.14",
"@angular/animations": "~8.2.14",
"@angular/cdk": "8.2.3",
"@angular/cli": "^8.3.25",
"@angular/common": "^8.2.14",
"@angular/core": "^8.2.14",
"@angular/forms": "^8.2.14",
"@angular/platform-browser": "^8.2.14",
"@angular/platform-browser-dynamic": "^8.2.14",
"@angular/platform-server": "^8.2.14",
"@angular/router": "^8.2.14",
"@angular/common": "~8.2.14",
"@angular/compiler": "~8.2.14",
"@angular/core": "~8.2.14",
"@angular/forms": "~8.2.14",
"@angular/platform-browser": "~8.2.14",
"@angular/platform-browser-dynamic": "~8.2.14",
"@angular/platform-server": "~8.2.14",
"@angular/router": "~8.2.14",
"@angularclass/bootloader": "1.0.1",
"@ng-bootstrap/ng-bootstrap": "^5.2.1",
"@ng-bootstrap/ng-bootstrap": "5.2.1",
"@ng-dynamic-forms/core": "8.1.1",
"@ng-dynamic-forms/ui-ng-bootstrap": "8.1.1",
"@ngrx/effects": "^8.6.0",
"@ngrx/router-store": "^8.6.0",
"@ngrx/store": "^8.6.0",
"@nguniversal/express-engine": "^8.2.6",
"@nguniversal/express-engine": "8.2.6",
"@nguniversal/module-map-ngfactory-loader": "v8.2.6",
"@ngx-translate/core": "11.0.1",
"@ngx-translate/http-loader": "4.0.0",
"@nicky-lenaers/ngx-scroll-to": "^3.0.1",
"angular-idle-preload": "3.0.0",
"angular2-text-mask": "9.0.0",
"angulartics2": "7.5.2",
"body-parser": "1.18.2",
"bootstrap": "4.3.1",
"caniuse-lite": "^1.0.30000697",
"cerialize": "0.1.18",
"compression": "1.7.1",
"cli-progress": "^3.8.0",
"cookie-parser": "1.4.3",
"core-js": "^3.6.4",
"debug-loader": "^0.0.1",
"deepmerge": "^4.2.2",
"express": "4.16.2",
"express-session": "1.15.6",
"fast-json-patch": "^2.0.7",
"file-saver": "^1.3.8",
"filesize": "^6.1.0",
"font-awesome": "4.7.0",
"fork-ts-checker-webpack-plugin": "^0.4.10",
"hammerjs": "^2.0.8",
"http-server": "0.11.1",
"https": "1.0.0",
"js-cookie": "2.2.0",
"js.clone": "0.0.3",
"json5": "^2.1.0",
"jsonschema": "1.2.2",
"jwt-decode": "^2.2.0",
"methods": "1.1.2",
"klaro": "^0.6.3",
"moment": "^2.22.1",
"moment-range": "^4.0.2",
"morgan": "^1.9.1",
"ng-mocks": "^8.1.0",
"ng2-file-upload": "1.2.1",
"ng2-file-upload": "1.4.0",
"ng2-nouislider": "^1.8.2",
"ngx-bootstrap": "^5.3.2",
"ngx-infinite-scroll": "6.0.1",
@@ -134,124 +110,75 @@
"ngx-sortablejs": "^3.1.4",
"nouislider": "^11.0.0",
"pem": "1.13.2",
"postcss-cli": "^6.0.0",
"reflect-metadata": "^0.1.13",
"rxjs": "6.5.4",
"rxjs": "~6.4.0",
"rxjs-spy": "^7.5.1",
"sass-resources-loader": "^2.0.0",
"sortablejs": "1.7.0",
"text-mask-core": "5.0.1",
"ts-loader": "^5.2.1",
"ts-md5": "^1.2.4",
"url-parse": "^1.4.7",
"uuid": "^3.2.1",
"tslib": "^1.10.0",
"webfontloader": "1.6.28",
"webpack-cli": "^3.2.0",
"zone.js": "^0.9.1"
},
"devDependencies": {
"@angular-devkit/build-angular": "^0.803.25",
"@angular/compiler": "^8.2.14",
"@angular/compiler-cli": "^8.2.14",
"@angular-builders/custom-webpack": "8.4.1",
"@angular-devkit/build-angular": "~0.803.25",
"@angular/cli": "~8.3.25",
"@angular/compiler-cli": "~8.2.14",
"@angular/language-service": "~8.2.14",
"@fortawesome/fontawesome-free": "^5.5.0",
"@ngrx/entity": "^8.6.0",
"@ngrx/schematics": "^8.6.0",
"@ngrx/store-devtools": "^8.6.0",
"@ngtools/webpack": "^8.3.25",
"@schematics/angular": "^0.7.5",
"@types/acorn": "^4.0.3",
"@types/cookie-parser": "1.4.1",
"@types/deep-freeze": "0.1.1",
"@types/express": "^4.11.1",
"@types/express-serve-static-core": "4.16.0",
"@types/express": "^4.17.0",
"@types/file-saver": "^1.3.0",
"@types/hammerjs": "2.0.35",
"@types/jasmine": "^3.3.9",
"@types/jasminewd2": "~2.0.3",
"@types/js-cookie": "2.1.0",
"@types/json5": "^0.0.30",
"@types/lodash": "^4.14.110",
"@types/memory-cache": "0.2.0",
"@types/mime": "2.0.0",
"@types/node": "^11.11.2",
"@types/serve-static": "1.13.2",
"@types/uuid": "^3.4.3",
"@types/webfontloader": "1.6.29",
"@typescript-eslint/eslint-plugin": "^2.12.0",
"@typescript-eslint/parser": "^2.12.0",
"ajv": "^6.1.1",
"ajv-keywords": "^3.1.0",
"angular2-template-loader": "0.6.2",
"autoprefixer": "^9.1.3",
"caniuse-lite": "^1.0.30000697",
"cli-progress": "^3.3.1",
"codelyzer": "^5.1.0",
"commander": "^3.0.2",
"@types/node": "11.15.3",
"codecov": "^3.7.2",
"codelyzer": "^5.0.0",
"compression-webpack-plugin": "^3.0.1",
"copy-webpack-plugin": "^5.1.1",
"copyfiles": "^2.1.1",
"coveralls": "3.0.0",
"css-loader": "3.4.0",
"cssnano": "^4.1.10",
"deep-freeze": "0.0.1",
"eslint": "^6.7.2",
"exports-loader": "^0.7.0",
"html-webpack-plugin": "3.2.0",
"imports-loader": "0.8.0",
"istanbul-instrumenter-loader": "3.0.1",
"dotenv": "^8.2.0",
"fork-ts-checker-webpack-plugin": "^0.4.10",
"html-webpack-plugin": "^3.2.0",
"http-proxy-middleware": "^1.0.5",
"jasmine-core": "^3.3.0",
"jasmine-marbles": "0.3.1",
"jasmine-spec-reporter": "4.2.1",
"karma": "4.0.1",
"karma-chrome-launcher": "2.2.0",
"karma-cli": "2.0.0",
"karma-coverage": "1.1.2",
"karma-istanbul-preprocessor": "0.0.2",
"jasmine-spec-reporter": "~4.2.1",
"karma": "^5.0.9",
"karma-chrome-launcher": "~2.2.0",
"karma-coverage-istanbul-reporter": "~2.0.1",
"karma-jasmine": "2.0.1",
"karma-jasmine-html-reporter": "^1.4.0",
"karma-mocha-reporter": "2.2.5",
"karma-phantomjs-launcher": "1.0.4",
"karma-remap-coverage": "^0.1.5",
"karma-remap-istanbul": "0.6.0",
"karma-sourcemap-loader": "0.3.7",
"karma-webdriver-launcher": "^1.0.7",
"karma-webpack": "3.0.0",
"ncp": "^2.0.0",
"nodemon": "^1.15.0",
"npm-run-all": "4.1.3",
"nodemon": "^2.0.2",
"npm-run-all": "^4.1.5",
"optimize-css-assets-webpack-plugin": "^5.0.1",
"postcss": "^7.0.2",
"postcss-apply": "0.11.0",
"postcss-cli": "^6.0.0",
"postcss-cssnext": "3.1.0",
"postcss-import": "^12.0.1",
"postcss-loader": "^3.0.0",
"postcss-responsive-type": "1.0.0",
"postcss-smart-import": "0.7.6",
"protractor": "^5.4.2",
"protractor": "^7.0.0",
"protractor-istanbul-plugin": "2.0.0",
"raw-loader": "0.5.1",
"rimraf": "2.6.2",
"rollup": "^0.65.0",
"rollup-plugin-commonjs": "^9.1.6",
"rollup-plugin-node-globals": "1.2.1",
"rollup-plugin-node-resolve": "^3.0.3",
"rollup-plugin-terser": "^2.0.2",
"sass-loader": "7.3.1",
"rimraf": "^3.0.2",
"script-ext-html-webpack-plugin": "2.1.4",
"source-map": "0.7.3",
"source-map-loader": "0.2.4",
"string-replace-loader": "^2.1.1",
"terser-webpack-plugin": "^2.3.1",
"to-string-loader": "1.1.5",
"ts-helpers": "1.1.2",
"ts-node": "4.1.0",
"tslint": "5.11.0",
"typedoc": "^0.9.0",
"typescript": "3.5.3",
"webdriver-manager": "^12.1.7",
"webpack": "^4.29.6",
"ts-loader": "^5.2.0",
"ts-node": "^8.8.1",
"tslint": "~5.15.0",
"typescript": "~3.5.3",
"webpack": "^4.0.0",
"webpack-bundle-analyzer": "^3.3.2",
"webpack-dev-middleware": "3.2.0",
"webpack-dev-server": "^3.1.11",
"webpack-import-glob-loader": "^1.6.3",
"webpack-merge": "4.1.4",
"webpack-cli": "^3.1.0",
"webpack-node-externals": "1.7.2"
}
}

View File

@@ -1,6 +1,6 @@
module.exports = {
plugins: [
require('postcss-smart-import')(),
require('postcss-import')(),
require('postcss-cssnext')(),
require('postcss-apply')(),
require('postcss-responsive-type')()

View File

@@ -1,21 +0,0 @@
import nodeResolve from 'rollup-plugin-node-resolve'
import commonjs from 'rollup-plugin-commonjs';
import terser from 'rollup-plugin-terser'
export default {
input: 'dist/client.js',
output: {
file: 'dist/client.js',
format: 'iife',
},
plugins: [
nodeResolve({
jsnext: true,
module: true
}),
commonjs({
include: 'node_modules/rxjs/**'
}),
terser.terser()
]
}

11
scripts/serve.ts Normal file
View File

@@ -0,0 +1,11 @@
import { environment } from '../src/environments/environment';
import * as child from 'child_process';
/**
* Calls `ng serve` with the following arguments configured for the UI in the environment file: host, port, nameSpace, ssl
*/
child.spawn(
`ng serve --host ${environment.ui.host} --port ${environment.ui.port} --servePath ${environment.ui.nameSpace} --ssl ${environment.ui.ssl}`,
{ stdio:'inherit', shell: true }
);

134
scripts/set-env.ts Normal file
View File

@@ -0,0 +1,134 @@
import { writeFile } from 'fs';
import { environment as commonEnv } from '../src/environments/environment.common';
import { GlobalConfig } from '../src/config/global-config.interface';
import { ServerConfig } from '../src/config/server-config.interface';
import { hasValue } from '../src/app/shared/empty.util';
// Configure Angular `environment.ts` file path
const targetPath = './src/environments/environment.ts';
// Load node modules
const colors = require('colors');
require('dotenv').config();
const merge = require('deepmerge');
const environment = process.argv[2];
let environmentFilePath;
let production = false;
switch (environment) {
case '--prod':
case '--production':
production = true;
console.log(`Building ${colors.red.bold(`production`)} environment`);
environmentFilePath = '../src/environments/environment.prod.ts';
break;
case '--test':
console.log(`Building ${colors.blue.bold(`test`)} environment`);
environmentFilePath = '../src/environments/environment.test.ts';
break;
default:
console.log(`Building ${colors.green.bold(`development`)} environment`);
environmentFilePath = '../src/environments/environment.dev.ts';
}
const processEnv = {
ui: createServerConfig(
process.env.DSPACE_HOST,
process.env.DSPACE_PORT,
process.env.DSPACE_NAMESPACE,
process.env.DSPACE_SSL),
rest: createServerConfig(
process.env.DSPACE_REST_HOST,
process.env.DSPACE_REST_PORT,
process.env.DSPACE_REST_NAMESPACE,
process.env.DSPACE_REST_SSL)
} as GlobalConfig;
import(environmentFilePath)
.then((file) => generateEnvironmentFile(merge.all([commonEnv, file.environment, processEnv])))
.catch(() => {
console.log(colors.yellow.bold(`No specific environment file found for ` + environment));
generateEnvironmentFile(merge(commonEnv, processEnv))
});
function generateEnvironmentFile(file: GlobalConfig): void {
file.production = production;
buildBaseUrls(file);
// TODO remove workaround in beta 5
if (file.rest.nameSpace.match("(.*)/api/?$") !== null) {
file.rest.nameSpace = getNameSpace(file.rest.nameSpace);
console.log(colors.white.bgMagenta.bold(`The rest.nameSpace property in your environment file or in your DSPACE_REST_NAMESPACE environment variable ends with '/api'.\nThis is deprecated. As '/api' isn't configurable on the rest side, it shouldn't be repeated in every environment file.\nPlease change the rest nameSpace to '${file.rest.nameSpace}'`));
}
const contents = `export const environment = ` + JSON.stringify(file);
writeFile(targetPath, contents, (err) => {
if (err) {
throw console.error(err);
} else {
console.log(`Angular ${colors.bold('environment.ts')} file generated correctly at ${colors.bold(targetPath)} \n`);
}
});
}
// allow to override a few important options by environment variables
function createServerConfig(host?: string, port?: string, nameSpace?: string, ssl?: string): ServerConfig {
const result = {} as any;
if (hasValue(host)) {
result.host = host;
}
if (hasValue(nameSpace)) {
result.nameSpace = nameSpace;
}
if (hasValue(port)) {
result.port = Number(port);
}
if (hasValue(ssl)) {
result.ssl = ssl.trim().match(/^(true|1|yes)$/i) ? true : false;
}
return result;
}
function buildBaseUrls(config: GlobalConfig): void {
for (const key in config) {
if (config.hasOwnProperty(key) && config[key].host) {
config[key].baseUrl = [
getProtocol(config[key].ssl),
getHost(config[key].host),
getPort(config[key].port),
getNameSpace(config[key].nameSpace)
].join('');
}
}
}
function getProtocol(ssl: boolean): string {
return ssl ? 'https://' : 'http://';
}
function getHost(host: string): string {
return host;
}
function getPort(port: number): string {
return port ? (port !== 80 && port !== 443) ? ':' + port : '' : '';
}
function getNameSpace(nameSpace: string): string {
// TODO remove workaround in beta 5
const apiMatches = nameSpace.match("(.*)/api/?$");
if (apiMatches != null) {
let newValue = '/'
if (hasValue(apiMatches[1])) {
newValue = apiMatches[1];
}
return newValue;
}
else {
return nameSpace ? nameSpace.charAt(0) === '/' ? nameSpace : '/' + nameSpace : '';
}
}

11
scripts/set-mock-env.ts Normal file
View File

@@ -0,0 +1,11 @@
import { copyFile } from 'fs';
// Configure Angular `environment.ts` file path
const sourcePath = './src/environments/mock-environment.ts';
const targetPath = './src/environments/environment.ts';
// destination.txt will be created or overwritten by default.
copyFile(sourcePath, targetPath, (err) => {
if (err) throw err;
console.log(sourcePath + ' was copied to ' + targetPath);
});

View File

@@ -1,10 +1,9 @@
#!/usr/bin/env node
import { projectRoot} from '../webpack/helpers';
const commander = require('commander');
const fs = require('fs');
const JSON5 = require('json5');
const _cliProgress = require('cli-progress');
const _ = require('lodash');
const {projectRoot} = require('../webpack/helpers');
const program = new commander.Command();
program.version('1.0.0', '-v, --version');
@@ -13,8 +12,8 @@ const NEW_MESSAGE_TODO = '// TODO New key - Add a translation';
const MESSAGE_CHANGED_TODO = '// TODO Source message changed - Revise the translation';
const COMMENTS_CHANGED_TODO = '// TODO Source comments changed - Revise the translation';
const DEFAULT_SOURCE_FILE_LOCATION = 'resources/i18n/en.json5';
const LANGUAGE_FILES_LOCATION = 'resources/i18n';
const DEFAULT_SOURCE_FILE_LOCATION = 'src/assets/i18n/en.json5';
const LANGUAGE_FILES_LOCATION = 'src/assets/i18n';
parseCliInput();

226
server.ts Normal file
View File

@@ -0,0 +1,226 @@
/**
* *** NOTE ON IMPORTING FROM ANGULAR AND NGUNIVERSAL IN THIS FILE ***
*
* If your application uses third-party dependencies, you'll need to
* either use Webpack or the Angular CLI's `bundleDependencies` feature
* in order to adequately package them for use on the server without a
* node_modules directory.
*
* However, due to the nature of the CLI's `bundleDependencies`, importing
* Angular in this file will create a different instance of Angular than
* the version in the compiled application code. This leads to unavoidable
* conflicts. Therefore, please do not explicitly import from @angular or
* @nguniversal in this file. You can export any needed resources
* from your application's main.server.ts file, as seen below with the
* import for `ngExpressEngine`.
*/
import 'reflect-metadata';
import 'rxjs';
import * as fs from 'fs';
import * as pem from 'pem';
import * as https from 'https';
import * as morgan from 'morgan';
import * as express from 'express';
import * as bodyParser from 'body-parser';
import * as compression from 'compression';
import * as cookieParser from 'cookie-parser';
import { join } from 'path';
import { enableProdMode, NgModuleFactory, Type } from '@angular/core';
import { REQUEST, RESPONSE } from '@nguniversal/express-engine/tokens';
import { environment } from './src/environments/environment';
import { createProxyMiddleware } from 'http-proxy-middleware';
import { hasValue, hasNoValue } from './src/app/shared/empty.util';
/*
* Set path for the browser application's dist folder
*/
const DIST_FOLDER = join(process.cwd(), 'dist/browser');
// * NOTE :: leave this as require() since this file is built Dynamically from webpack
const { ServerAppModuleNgFactory, LAZY_MODULE_MAP, ngExpressEngine, provideModuleMap } = require('./dist/server/main');
/*
* Create a new express application
*/
const app = express();
/*
* If production mode is enabled in the environment file:
* - Enable Angular's production mode
* - Enable compression for response bodies. See [compression](https://github.com/expressjs/compression)
*/
if (environment.production) {
enableProdMode();
app.use(compression());
}
/*
* Enable request logging
* See [morgan](https://github.com/expressjs/morgan)
*/
app.use(morgan('dev'));
/*
* Add cookie parser middleware
* See [morgan](https://github.com/expressjs/cookie-parser)
*/
app.use(cookieParser());
/*
* Add parser for request bodies
* See [morgan](https://github.com/expressjs/body-parser)
*/
app.use(bodyParser.json());
/*
* Render html pages by running angular server side
*/
app.engine('html', (_, options, callback) =>
ngExpressEngine({
bootstrap: ServerAppModuleNgFactory,
providers: [
{
provide: REQUEST,
useValue: (options as any).req,
},
{
provide: RESPONSE,
useValue: (options as any).req.res,
},
provideModuleMap(LAZY_MODULE_MAP)
],
})(_, (options as any), callback)
);
/*
* Register the view engines for html and ejs
*/
app.set('view engine', 'html');
/*
* Set views folder path to directory where template files are stored
*/
app.set('views', DIST_FOLDER);
/**
* Proxy the sitemaps
*/
app.use('/sitemap**', createProxyMiddleware({ target: `${environment.rest.baseUrl}/sitemaps`, changeOrigin: true }));
/*
* Adds a cache control header to the response
* The cache control value can be configured in the environments file and defaults to max-age=60
*/
function cacheControl(req, res, next) {
// instruct browser to revalidate
res.header('Cache-Control', environment.cache.control || 'max-age=60');
next();
}
/*
* Serve static resources (images, i18n messages, …)
*/
app.get('*.*', cacheControl, express.static(DIST_FOLDER, { index: false }));
/*
* The callback function to serve server side angular
*/
function ngApp(req, res) {
if (environment.universal.preboot) {
res.render(DIST_FOLDER + '/index.html', {
req,
res,
preboot: environment.universal.preboot,
async: environment.universal.async,
time: environment.universal.time,
baseUrl: environment.ui.nameSpace,
originUrl: environment.ui.baseUrl,
requestUrl: req.originalUrl
}, (err, data) => {
if (hasNoValue(err) && hasValue(data)) {
res.send(data);
} else {
console.warn('Error in SSR, serving for direct CSR.');
if (hasValue(err)) {
console.warn('Error details : ', err);
}
res.sendFile(DIST_FOLDER + '/index.html');
}
})
} else {
// If preboot is disabled, just serve the client
console.log('Universal off, serving for direct CSR');
res.sendFile(DIST_FOLDER + '/index.html');
}
}
// Register the ngApp callback function to handle incoming requests
app.get('*', ngApp);
/*
* Callback function for when the server has started
*/
function serverStarted() {
console.log(`[${new Date().toTimeString()}] Listening at ${environment.ui.baseUrl}`);
}
/*
* Create an HTTPS server with the configured port and host
* @param keys SSL credentials
*/
function createHttpsServer(keys) {
https.createServer({
key: keys.serviceKey,
cert: keys.certificate
}, app).listen(environment.ui.port, environment.ui.host, () => {
serverStarted();
});
}
/*
* If SSL is enabled
* - Read credentials from configuration files
* - Call script to start an HTTPS server with these credentials
* When SSL is disabled
* - Start an HTTP server on the configured port and host
*/
if (environment.ui.ssl) {
let serviceKey;
try {
serviceKey = fs.readFileSync('./config/ssl/key.pem');
} catch (e) {
console.warn('Service key not found at ./config/ssl/key.pem');
}
let certificate;
try {
certificate = fs.readFileSync('./config/ssl/cert.pem');
} catch (e) {
console.warn('Certificate not found at ./config/ssl/key.pem');
}
if (serviceKey && certificate) {
createHttpsServer({
serviceKey: serviceKey,
certificate: certificate
});
} else {
process.env.NODE_TLS_REJECT_UNAUTHORIZED = '0';
pem.createCertificate({
days: 1,
selfSigned: true
}, (error, keys) => {
createHttpsServer(keys);
});
}
} else {
app.listen(environment.ui.port, environment.ui.host, () => {
serverStarted();
});
}

View File

@@ -1,48 +0,0 @@
/**
* @author: @AngularClass
*/
/*
* When testing with webpack and ES6, we have to do some extra
* things to get testing to work right. Because we are gonna write tests
* in ES6 too, we have to compile those as well. That's handled in
* karma.conf.js with the karma-webpack plugin. This is the entry
* file for webpack test. Just like webpack will create a bundle.js
* file for our client, when we run test, it will compile and bundle them
* all here! Crazy huh. So we need to do some setup
*/
Error.stackTraceLimit = Infinity;
require('core-js/es');
require('core-js/features/reflect');
// Typescript emit helpers polyfill
require('ts-helpers');
require('zone.js/dist/zone');
require('zone.js/dist/long-stack-trace-zone');
require('zone.js/dist/proxy'); // since zone.js 0.6.15
require('zone.js/dist/sync-test');
require('zone.js/dist/jasmine-patch'); // put here since zone.js 0.6.14
require('zone.js/dist/async-test');
require('zone.js/dist/fake-async-test');
// RxJS
require('rxjs');
var testing = require('@angular/core/testing');
var browser = require('@angular/platform-browser-dynamic/testing');
testing.TestBed.initTestEnvironment(
browser.BrowserDynamicTestingModule,
browser.platformBrowserDynamicTesting()
);
var tests = require.context('./src', true, /\.spec\.ts$/);
tests.keys().forEach(tests);
// includes all modules into test coverage
const modules = require.context('./src/app', true, /\.module\.ts$/);
modules.keys().forEach(modules);

View File

@@ -0,0 +1,8 @@
import { URLCombiner } from '../../core/url-combiner/url-combiner';
import { getAccessControlModuleRoute } from '../admin-routing-paths';
export const GROUP_EDIT_PATH = 'groups';
export function getGroupEditRoute(id: string) {
return new URLCombiner(getAccessControlModuleRoute(), GROUP_EDIT_PATH, id).toString();
}

View File

@@ -3,14 +3,7 @@ import { RouterModule } from '@angular/router';
import { EPeopleRegistryComponent } from './epeople-registry/epeople-registry.component';
import { GroupFormComponent } from './group-registry/group-form/group-form.component';
import { GroupsRegistryComponent } from './group-registry/groups-registry.component';
import { URLCombiner } from '../../core/url-combiner/url-combiner';
import { getAccessControlModulePath } from '../admin-routing.module';
const GROUP_EDIT_PATH = 'groups';
export function getGroupEditPath(id: string) {
return new URLCombiner(getAccessControlModulePath(), GROUP_EDIT_PATH, id).toString();
}
import { GROUP_EDIT_PATH } from './admin-access-control-routing-paths';
@NgModule({
imports: [

View File

@@ -4,90 +4,91 @@
<h2 id="header" class="border-bottom pb-2">{{labelPrefix + 'head' | translate}}</h2>
<ds-eperson-form *ngIf="isEPersonFormShown" (submitForm)="forceUpdateEPeople()"
<ds-eperson-form *ngIf="isEPersonFormShown" (submitForm)="reset()"
(cancelForm)="isEPersonFormShown = false"></ds-eperson-form>
<div *ngIf="!isEPersonFormShown" class="button-row top d-flex pb-2">
<button class="mr-auto btn btn-success addEPerson-button"
(click)="isEPersonFormShown = true">
<i class="fas fa-plus"></i>
<span class="d-none d-sm-inline">{{labelPrefix + 'button.add' | translate}}</span>
</button>
</div>
<h3 id="search" class="border-bottom pb-2">{{labelPrefix + 'search.head' | translate}}
<button (click)="clearFormAndResetResult();"
class="btn btn-primary float-right">{{labelPrefix + 'button.see-all' | translate}}</button>
</h3>
<form [formGroup]="searchForm" (ngSubmit)="search(searchForm.value)" class="row">
<div class="col-12 col-sm-3">
<select name="scope" id="scope" formControlName="scope" class="form-control" aria-label="Search scope">
<option value="metadata">{{labelPrefix + 'search.scope.metadata' | translate}}</option>
<option value="email">{{labelPrefix + 'search.scope.email' | translate}}</option>
</select>
<div *ngIf="!isEPersonFormShown">
<div class="button-row top d-flex pb-2">
<button class="mr-auto btn btn-success addEPerson-button"
(click)="isEPersonFormShown = true">
<i class="fas fa-plus"></i>
<span class="d-none d-sm-inline">{{labelPrefix + 'button.add' | translate}}</span>
</button>
</div>
<div class="col-sm-9 col-12">
<div class="form-group input-group">
<input type="text" name="query" id="query" formControlName="query"
class="form-control" aria-label="Search input">
<span class="input-group-append">
<button type="submit"
class="search-button btn btn-secondary">{{ labelPrefix + 'search.button' | translate }}</button>
</span>
<h3 id="search" class="border-bottom pb-2">{{labelPrefix + 'search.head' | translate}}
<button (click)="clearFormAndResetResult();"
class="btn btn-primary float-right">{{labelPrefix + 'button.see-all' | translate}}</button>
</h3>
<form [formGroup]="searchForm" (ngSubmit)="search(searchForm.value)" class="row">
<div class="col-12 col-sm-3">
<select name="scope" id="scope" formControlName="scope" class="form-control" aria-label="Search scope">
<option value="metadata">{{labelPrefix + 'search.scope.metadata' | translate}}</option>
<option value="email">{{labelPrefix + 'search.scope.email' | translate}}</option>
</select>
</div>
<div class="col-sm-9 col-12">
<div class="form-group input-group">
<input type="text" name="query" id="query" formControlName="query"
class="form-control" aria-label="Search input">
<span class="input-group-append">
<button type="submit"
class="search-button btn btn-secondary">{{ labelPrefix + 'search.button' | translate }}</button>
</span>
</div>
</div>
</form>
<ds-pagination
*ngIf="(ePeopleDto$ | async)?.totalElements > 0"
[paginationOptions]="config"
[pageInfoState]="pageInfoState$"
[collectionSize]="(pageInfoState$ | async)?.totalElements"
[hideGear]="true"
[hidePagerWhenSinglePage]="true"
(pageChange)="onPageChange($event)">
<div class="table-responsive">
<table id="epeople" class="table table-striped table-hover table-bordered">
<thead>
<tr>
<th scope="col">{{labelPrefix + 'table.id' | translate}}</th>
<th scope="col">{{labelPrefix + 'table.name' | translate}}</th>
<th scope="col">{{labelPrefix + 'table.email' | translate}}</th>
<th>{{labelPrefix + 'table.edit' | translate}}</th>
</tr>
</thead>
<tbody>
<tr *ngFor="let epersonDto of (ePeopleDto$ | async)?.page"
[ngClass]="{'table-primary' : isActive(epersonDto.eperson) | async}">
<td>{{epersonDto.eperson.id}}</td>
<td>{{epersonDto.eperson.name}}</td>
<td>{{epersonDto.eperson.email}}</td>
<td>
<div class="btn-group edit-field">
<button class="delete-button" (click)="toggleEditEPerson(epersonDto.eperson)"
class="btn btn-outline-primary btn-sm access-control-editEPersonButton"
title="{{labelPrefix + 'table.edit.buttons.edit' | translate: {name: epersonDto.eperson.name} }}">
<i class="fas fa-edit fa-fw"></i>
</button>
<button [disabled]="!epersonDto.ableToDelete" (click)="deleteEPerson(epersonDto.eperson)"
class="btn btn-outline-danger btn-sm access-control-deleteEPersonButton"
title="{{labelPrefix + 'table.edit.buttons.remove' | translate: {name: epersonDto.eperson.name} }}">
<i class="fas fa-trash-alt fa-fw"></i>
</button>
</div>
</td>
</tr>
</tbody>
</table>
</div>
</ds-pagination>
<div *ngIf="(pageInfoState$ | async)?.totalElements == 0" class="alert alert-info w-100 mb-2" role="alert">
{{labelPrefix + 'no-items' | translate}}
</div>
</form>
<ds-pagination
*ngIf="(ePeople | async)?.payload?.totalElements > 0"
[paginationOptions]="config"
[pageInfoState]="(ePeople | async)?.payload"
[collectionSize]="(ePeople | async)?.payload?.totalElements"
[hideGear]="true"
[hidePagerWhenSinglePage]="true"
(pageChange)="onPageChange($event)">
<div class="table-responsive">
<table id="epeople" class="table table-striped table-hover table-bordered">
<thead>
<tr>
<th scope="col">{{labelPrefix + 'table.id' | translate}}</th>
<th scope="col">{{labelPrefix + 'table.name' | translate}}</th>
<th scope="col">{{labelPrefix + 'table.email' | translate}}</th>
<th>{{labelPrefix + 'table.edit' | translate}}</th>
</tr>
</thead>
<tbody>
<tr *ngFor="let eperson of (ePeople | async)?.payload?.page"
[ngClass]="{'table-primary' : isActive(eperson) | async}">
<td>{{eperson.id}}</td>
<td>{{eperson.name}}</td>
<td>{{eperson.email}}</td>
<td>
<div class="btn-group edit-field">
<button (click)="toggleEditEPerson(eperson)"
class="btn btn-outline-primary btn-sm access-control-editEPersonButton"
title="{{labelPrefix + 'table.edit.buttons.edit' | translate: {name: eperson.name} }}">
<i class="fas fa-edit fa-fw"></i>
</button>
<button (click)="deleteEPerson(eperson)"
class="btn btn-outline-danger btn-sm access-control-deleteEPersonButton"
title="{{labelPrefix + 'table.edit.buttons.remove' | translate: {name: eperson.name} }}">
<i class="fas fa-trash-alt fa-fw"></i>
</button>
</div>
</td>
</tr>
</tbody>
</table>
</div>
</ds-pagination>
<div *ngIf="(ePeople | async)?.payload?.totalElements == 0" class="alert alert-info w-100 mb-2" role="alert">
{{labelPrefix + 'no-items' | translate}}
</div>
</div>
</div>
</div>

View File

@@ -15,15 +15,17 @@ import { EPersonDataService } from '../../../core/eperson/eperson-data.service';
import { EPerson } from '../../../core/eperson/models/eperson.model';
import { PageInfo } from '../../../core/shared/page-info.model';
import { FormBuilderService } from '../../../shared/form/builder/form-builder.service';
import { getMockFormBuilderService } from '../../../shared/mocks/mock-form-builder-service';
import { MockTranslateLoader } from '../../../shared/mocks/mock-translate-loader';
import { getMockTranslateService } from '../../../shared/mocks/mock-translate.service';
import { NotificationsService } from '../../../shared/notifications/notifications.service';
import { EPersonMock, EPersonMock2 } from '../../../shared/testing/eperson-mock';
import { NotificationsServiceStub } from '../../../shared/testing/notifications-service-stub';
import { RouterStub } from '../../../shared/testing/router-stub';
import { createSuccessfulRemoteDataObject$ } from '../../../shared/testing/utils';
import { EPeopleRegistryComponent } from './epeople-registry.component';
import { EPersonMock, EPersonMock2 } from '../../../shared/testing/eperson.mock';
import { createSuccessfulRemoteDataObject$ } from '../../../shared/remote-data.utils';
import { getMockFormBuilderService } from '../../../shared/mocks/form-builder-service.mock';
import { getMockTranslateService } from '../../../shared/mocks/translate.service.mock';
import { TranslateLoaderMock } from '../../../shared/mocks/translate-loader.mock';
import { NotificationsServiceStub } from '../../../shared/testing/notifications-service.stub';
import { RouterStub } from '../../../shared/testing/router.stub';
import { AuthorizationDataService } from '../../../core/data/feature-authorization/authorization-data.service';
import { RequestService } from '../../../core/data/request.service';
describe('EPeopleRegistryComponent', () => {
let component: EPeopleRegistryComponent;
@@ -33,6 +35,8 @@ describe('EPeopleRegistryComponent', () => {
let mockEPeople;
let ePersonDataServiceStub: any;
let authorizationService: AuthorizationDataService;
let modalService;
beforeEach(async(() => {
mockEPeople = [EPersonMock, EPersonMock2];
@@ -82,6 +86,9 @@ describe('EPeopleRegistryComponent', () => {
return '/admin/access-control/epeople';
}
};
authorizationService = jasmine.createSpyObj('authorizationService', {
isAuthorized: observableOf(true)
});
builderService = getMockFormBuilderService();
translateService = getMockTranslateService();
TestBed.configureTestingModule({
@@ -89,16 +96,18 @@ describe('EPeopleRegistryComponent', () => {
TranslateModule.forRoot({
loader: {
provide: TranslateLoader,
useClass: MockTranslateLoader
useClass: TranslateLoaderMock
}
}),
],
declarations: [EPeopleRegistryComponent],
providers: [EPeopleRegistryComponent,
providers: [
{ provide: EPersonDataService, useValue: ePersonDataServiceStub },
{ provide: NotificationsService, useValue: new NotificationsServiceStub() },
{ provide: AuthorizationDataService, useValue: authorizationService },
{ provide: FormBuilderService, useValue: builderService },
{ provide: Router, useValue: new RouterStub() },
{ provide: RequestService, useValue: jasmine.createSpyObj('requestService', ['removeByHrefSubstring'])}
],
schemas: [NO_ERRORS_SCHEMA]
}).compileComponents();
@@ -107,12 +116,14 @@ describe('EPeopleRegistryComponent', () => {
beforeEach(() => {
fixture = TestBed.createComponent(EPeopleRegistryComponent);
component = fixture.componentInstance;
modalService = (component as any).modalService;
spyOn(modalService, 'open').and.returnValue(Object.assign({ componentInstance: Object.assign({ response: observableOf(true) }) }));
fixture.detectChanges();
});
it('should create EPeopleRegistryComponent', inject([EPeopleRegistryComponent], (comp: EPeopleRegistryComponent) => {
expect(comp).toBeDefined();
}));
it('should create EPeopleRegistryComponent', () => {
expect(component).toBeDefined();
});
it('should display list of ePeople', () => {
const ePeopleIdsFound = fixture.debugElement.queryAll(By.css('#epeople tr td:first-child'));
@@ -175,7 +186,7 @@ describe('EPeopleRegistryComponent', () => {
it('editEPerson form is toggled', () => {
const ePeopleIds = fixture.debugElement.queryAll(By.css('#epeople tr td:first-child'));
ePersonDataServiceStub.getActiveEPerson().subscribe((activeEPerson: EPerson) => {
if (activeEPerson === ePeopleIds[0].nativeElement.textContent) {
if (ePeopleIds[0] && activeEPerson === ePeopleIds[0].nativeElement.textContent) {
expect(component.isEPersonFormShown).toEqual(false);
} else {
expect(component.isEPersonFormShown).toEqual(true);
@@ -183,6 +194,10 @@ describe('EPeopleRegistryComponent', () => {
})
});
it('EPerson search section is hidden', () => {
expect(fixture.debugElement.query(By.css('#search'))).toBeNull();
});
});
});
@@ -211,4 +226,20 @@ describe('EPeopleRegistryComponent', () => {
});
});
describe('delete EPerson button when the isAuthorized returns false', () => {
let ePeopleDeleteButton;
beforeEach(() => {
authorizationService = jasmine.createSpyObj('authorizationService', {
isAuthorized: observableOf(false)
});
});
it ('should be disabled', () => {
ePeopleDeleteButton = fixture.debugElement.queryAll(By.css('#epeople tr td div button.delete-button'));
ePeopleDeleteButton.forEach((deleteButton) => {
expect(deleteButton.nativeElement.disabled).toBe(true);
});
})
})
});

View File

@@ -2,9 +2,9 @@ import { Component, OnDestroy, OnInit } from '@angular/core';
import { FormBuilder } from '@angular/forms';
import { Router } from '@angular/router';
import { TranslateService } from '@ngx-translate/core';
import { Observable } from 'rxjs';
import { BehaviorSubject, combineLatest, Observable } from 'rxjs';
import { Subscription } from 'rxjs/internal/Subscription';
import { map, take } from 'rxjs/operators';
import { map, switchMap, take } from 'rxjs/operators';
import { PaginatedList } from '../../../core/data/paginated-list';
import { RemoteData } from '../../../core/data/remote-data';
import { EPersonDataService } from '../../../core/eperson/eperson-data.service';
@@ -12,6 +12,16 @@ import { EPerson } from '../../../core/eperson/models/eperson.model';
import { hasValue } from '../../../shared/empty.util';
import { NotificationsService } from '../../../shared/notifications/notifications.service';
import { PaginationComponentOptions } from '../../../shared/pagination/pagination-component-options.model';
import { EpersonDtoModel } from '../../../core/eperson/models/eperson-dto.model';
import { FeatureID } from '../../../core/data/feature-authorization/feature-id';
import { AuthorizationDataService } from '../../../core/data/feature-authorization/authorization-data.service';
import { getAllSucceededRemoteDataPayload } from '../../../core/shared/operators';
import { ErrorResponse, RestResponse } from '../../../core/cache/response.models';
import { ConfirmationModalComponent } from '../../../shared/confirmation-modal/confirmation-modal.component';
import { NgbModal } from '@ng-bootstrap/ng-bootstrap';
import { RequestService } from '../../../core/data/request.service';
import { filter } from 'rxjs/internal/operators/filter';
import { PageInfo } from '../../../core/shared/page-info.model';
@Component({
selector: 'ds-epeople-registry',
@@ -28,7 +38,17 @@ export class EPeopleRegistryComponent implements OnInit, OnDestroy {
/**
* A list of all the current EPeople within the repository or the result of the search
*/
ePeople: Observable<RemoteData<PaginatedList<EPerson>>>;
ePeople$: BehaviorSubject<RemoteData<PaginatedList<EPerson>>> = new BehaviorSubject<RemoteData<PaginatedList<EPerson>>>({} as any);
/**
* A BehaviorSubject with the list of EpersonDtoModel objects made from the EPeople in the repository or
* as the result of the search
*/
ePeopleDto$: BehaviorSubject<PaginatedList<EpersonDtoModel>> = new BehaviorSubject<PaginatedList<EpersonDtoModel>>({} as any);
/**
* An observable for the pageInfo, needed to pass to the pagination component
*/
pageInfoState$: BehaviorSubject<PageInfo> = new BehaviorSubject<PageInfo>(undefined);
/**
* Pagination config used to display the list of epeople
@@ -59,8 +79,11 @@ export class EPeopleRegistryComponent implements OnInit, OnDestroy {
constructor(private epersonService: EPersonDataService,
private translateService: TranslateService,
private notificationsService: NotificationsService,
private authorizationService: AuthorizationDataService,
private formBuilder: FormBuilder,
private router: Router) {
private router: Router,
private modalService: NgbModal,
public requestService: RequestService) {
this.currentSearchQuery = '';
this.currentSearchScope = 'metadata';
this.searchForm = this.formBuilder.group(({
@@ -70,6 +93,13 @@ export class EPeopleRegistryComponent implements OnInit, OnDestroy {
}
ngOnInit() {
this.initialisePage();
}
/**
* This method will initialise the page
*/
initialisePage() {
this.isEPersonFormShown = false;
this.search({ scope: this.currentSearchScope, query: this.currentSearchQuery });
this.subs.push(this.epersonService.getActiveEPerson().subscribe((eperson: EPerson) => {
@@ -84,18 +114,10 @@ export class EPeopleRegistryComponent implements OnInit, OnDestroy {
* @param event
*/
onPageChange(event) {
this.config.currentPage = event;
this.search({ scope: this.currentSearchScope, query: this.currentSearchQuery })
}
/**
* Force-update the list of EPeople by first clearing the cache related to EPeople, then performing
* a new REST call
*/
public forceUpdateEPeople() {
this.epersonService.clearEPersonRequests();
this.isEPersonFormShown = false;
this.search({ query: '', scope: 'metadata' })
if (this.config.currentPage !== event) {
this.config.currentPage = event;
this.search({ scope: this.currentSearchScope, query: this.currentSearchQuery })
}
}
/**
@@ -115,10 +137,33 @@ export class EPeopleRegistryComponent implements OnInit, OnDestroy {
this.currentSearchScope = scope;
this.config.currentPage = 1;
}
this.ePeople = this.epersonService.searchByScope(this.currentSearchScope, this.currentSearchQuery, {
this.subs.push(this.epersonService.searchByScope(this.currentSearchScope, this.currentSearchQuery, {
currentPage: this.config.currentPage,
elementsPerPage: this.config.pageSize
});
}).subscribe((peopleRD) => {
this.ePeople$.next(peopleRD)
}
));
this.subs.push(this.ePeople$.pipe(
getAllSucceededRemoteDataPayload(),
switchMap((epeople) => {
return combineLatest(...epeople.page.map((eperson) => {
return this.authorizationService.isAuthorized(FeatureID.CanDelete, hasValue(eperson) ? eperson.self : undefined).pipe(
map((authorized) => {
const epersonDtoModel: EpersonDtoModel = new EpersonDtoModel();
epersonDtoModel.ableToDelete = authorized;
epersonDtoModel.eperson = eperson;
return epersonDtoModel;
})
);
})).pipe(map((dtos: EpersonDtoModel[]) => {
return new PaginatedList(epeople.pageInfo, dtos);
}))
})).subscribe((value) => {
this.ePeopleDto$.next(value);
this.pageInfoState$.next(value.pageInfo);
}));
}
/**
@@ -160,16 +205,26 @@ export class EPeopleRegistryComponent implements OnInit, OnDestroy {
*/
deleteEPerson(ePerson: EPerson) {
if (hasValue(ePerson.id)) {
this.epersonService.deleteEPerson(ePerson).pipe(take(1)).subscribe((success: boolean) => {
if (success) {
this.notificationsService.success(this.translateService.get(this.labelPrefix + 'notification.deleted.success', { name: ePerson.name }));
this.forceUpdateEPeople();
} else {
this.notificationsService.error(this.translateService.get(this.labelPrefix + 'notification.deleted.failure', { name: ePerson.name }));
}
this.epersonService.cancelEditEPerson();
this.isEPersonFormShown = false;
})
const modalRef = this.modalService.open(ConfirmationModalComponent);
modalRef.componentInstance.dso = ePerson;
modalRef.componentInstance.headerLabel = 'confirmation-modal.delete-eperson.header';
modalRef.componentInstance.infoLabel = 'confirmation-modal.delete-eperson.info';
modalRef.componentInstance.cancelLabel = 'confirmation-modal.delete-eperson.cancel';
modalRef.componentInstance.confirmLabel = 'confirmation-modal.delete-eperson.confirm';
modalRef.componentInstance.response.pipe(take(1)).subscribe((confirm: boolean) => {
if (confirm) {
if (hasValue(ePerson.id)) {
this.epersonService.deleteEPerson(ePerson).pipe(take(1)).subscribe((restResponse: RestResponse) => {
if (restResponse.isSuccessful) {
this.notificationsService.success(this.translateService.get(this.labelPrefix + 'notification.deleted.success', { name: ePerson.name }));
this.reset();
} else {
const errorResponse = restResponse as ErrorResponse;
this.notificationsService.error('Error occured when trying to delete EPerson with id: ' + ePerson.id + ' with code: ' + errorResponse.statusCode + ' and message: ' + errorResponse.errorMessage);
}
})
}}
});
}
}
@@ -177,6 +232,10 @@ export class EPeopleRegistryComponent implements OnInit, OnDestroy {
* Unsub all subscriptions
*/
ngOnDestroy(): void {
this.cleanupSubscribes();
}
cleanupSubscribes() {
this.subs.filter((sub) => hasValue(sub)).forEach((sub) => sub.unsubscribe());
}
@@ -199,4 +258,18 @@ export class EPeopleRegistryComponent implements OnInit, OnDestroy {
});
this.search({ query: '' });
}
/**
* This method will ensure that the page gets reset and that the cache is cleared
*/
reset() {
this.epersonService.getBrowseEndpoint().pipe(
switchMap((href) => this.requestService.removeByHrefSubstring(href)),
filter((isCached) => isCached),
take(1)
).subscribe(() => {
this.cleanupSubscribes();
this.initialisePage();
});
}
}

View File

@@ -1,6 +1,6 @@
import { EPersonMock } from '../../../shared/testing/eperson-mock';
import { EPeopleRegistryCancelEPersonAction, EPeopleRegistryEditEPersonAction } from './epeople-registry.actions';
import { ePeopleRegistryReducer, EPeopleRegistryState } from './epeople-registry.reducers';
import { EPersonMock } from '../../../shared/testing/eperson.mock';
const initialState: EPeopleRegistryState = {
editEPerson: null,

View File

@@ -14,6 +14,18 @@
[formLayout]="formLayout"
(cancel)="onCancel()"
(submitForm)="onSubmit()">
<button class="btn btn-light" [disabled]="!(canReset$ | async)">
<i class="fa fa-key"></i> {{'admin.access-control.epeople.actions.reset' | translate}}
</button>
<button class="btn btn-light delete-button" [disabled]="!(canDelete$ | async)" (click)="delete()">
<i class="fa fa-trash"></i> {{'admin.access-control.epeople.actions.delete' | translate}}
</button>
<button *ngIf="!isImpersonated" class="btn btn-light" [ngClass]="{'d-none' : !(canImpersonate$ | async)}" (click)="impersonate()">
<i class="fa fa-user-secret"></i> {{'admin.access-control.epeople.actions.impersonate' | translate}}
</button>
<button *ngIf="isImpersonated" class="btn btn-light" (click)="stopImpersonating()">
<i class="fa fa-user-secret"></i> {{'admin.access-control.epeople.actions.stop-impersonating' | translate}}
</button>
</ds-form>
<div *ngIf="epersonService.getActiveEPerson() | async">

View File

@@ -1,45 +1,44 @@
import { HttpClient } from '@angular/common/http';
import { Store } from '@ngrx/store';
import { of as observableOf } from 'rxjs';
import { CommonModule } from '@angular/common';
import { NO_ERRORS_SCHEMA } from '@angular/core';
import { async, ComponentFixture, inject, TestBed } from '@angular/core/testing';
import { FormsModule, ReactiveFormsModule } from '@angular/forms';
import { BrowserModule } from '@angular/platform-browser';
import { BrowserModule, By } from '@angular/platform-browser';
import { NgbModule } from '@ng-bootstrap/ng-bootstrap';
import { TranslateLoader, TranslateModule, TranslateService } from '@ngx-translate/core';
import { TranslateLoader, TranslateModule } from '@ngx-translate/core';
import { Observable } from 'rxjs/internal/Observable';
import { RemoteDataBuildService } from '../../../../core/cache/builders/remote-data-build.service';
import { ObjectCacheService } from '../../../../core/cache/object-cache.service';
import { RestResponse } from '../../../../core/cache/response.models';
import { DSOChangeAnalyzer } from '../../../../core/data/dso-change-analyzer.service';
import { PaginatedList } from '../../../../core/data/paginated-list';
import { RemoteData } from '../../../../core/data/remote-data';
import { FindListOptions } from '../../../../core/data/request.models';
import { EPersonDataService } from '../../../../core/eperson/eperson-data.service';
import { EPerson } from '../../../../core/eperson/models/eperson.model';
import { HALEndpointService } from '../../../../core/shared/hal-endpoint.service';
import { PageInfo } from '../../../../core/shared/page-info.model';
import { UUIDService } from '../../../../core/shared/uuid.service';
import { FormBuilderService } from '../../../../shared/form/builder/form-builder.service';
import { getMockFormBuilderService } from '../../../../shared/mocks/mock-form-builder-service';
import { getMockTranslateService } from '../../../../shared/mocks/mock-translate.service';
import { NotificationsService } from '../../../../shared/notifications/notifications.service';
import { EPersonMock, EPersonMock2 } from '../../../../shared/testing/eperson-mock';
import { MockTranslateLoader } from '../../../../shared/testing/mock-translate-loader';
import { NotificationsServiceStub } from '../../../../shared/testing/notifications-service-stub';
import { createSuccessfulRemoteDataObject$ } from '../../../../shared/testing/utils';
import { EPeopleRegistryComponent } from '../epeople-registry.component';
import { EPersonFormComponent } from './eperson-form.component';
import { EPersonMock, EPersonMock2 } from '../../../../shared/testing/eperson.mock';
import { createSuccessfulRemoteDataObject$ } from '../../../../shared/remote-data.utils';
import { getMockFormBuilderService } from '../../../../shared/mocks/form-builder-service.mock';
import { NotificationsServiceStub } from '../../../../shared/testing/notifications-service.stub';
import { TranslateLoaderMock } from '../../../../shared/mocks/translate-loader.mock';
import { AuthService } from '../../../../core/auth/auth.service';
import { AuthServiceStub } from '../../../../shared/testing/auth-service.stub';
import { AuthorizationDataService } from '../../../../core/data/feature-authorization/authorization-data.service';
import { GroupDataService } from '../../../../core/eperson/group-data.service';
import { createPaginatedList } from '../../../../shared/testing/utils.test';
import { RequestService } from '../../../../core/data/request.service';
describe('EPersonFormComponent', () => {
let component: EPersonFormComponent;
let fixture: ComponentFixture<EPersonFormComponent>;
let translateService: TranslateService;
let builderService: FormBuilderService;
let mockEPeople;
let ePersonDataServiceStub: any;
let authService: AuthServiceStub;
let authorizationService: AuthorizationDataService;
let groupsDataService: GroupDataService;
beforeEach(async(() => {
mockEPeople = [EPersonMock, EPersonMock2];
@@ -103,29 +102,32 @@ describe('EPersonFormComponent', () => {
}
};
builderService = getMockFormBuilderService();
translateService = getMockTranslateService();
authService = new AuthServiceStub();
authorizationService = jasmine.createSpyObj('authorizationService', {
isAuthorized: observableOf(true)
});
groupsDataService = jasmine.createSpyObj('groupsDataService', {
findAllByHref: createSuccessfulRemoteDataObject$(createPaginatedList([])),
getGroupRegistryRouterLink: ''
});
TestBed.configureTestingModule({
imports: [CommonModule, NgbModule, FormsModule, ReactiveFormsModule, BrowserModule,
TranslateModule.forRoot({
loader: {
provide: TranslateLoader,
useClass: MockTranslateLoader
useClass: TranslateLoaderMock
}
}),
],
declarations: [EPeopleRegistryComponent, EPersonFormComponent],
providers: [EPersonFormComponent,
declarations: [EPersonFormComponent],
providers: [
{ provide: EPersonDataService, useValue: ePersonDataServiceStub },
{ provide: NotificationsService, useValue: new NotificationsServiceStub() },
{ provide: GroupDataService, useValue: groupsDataService },
{ provide: FormBuilderService, useValue: builderService },
{ provide: DSOChangeAnalyzer, useValue: {} },
{ provide: HttpClient, useValue: {} },
{ provide: ObjectCacheService, useValue: {} },
{ provide: UUIDService, useValue: {} },
{ provide: Store, useValue: {} },
{ provide: RemoteDataBuildService, useValue: {} },
{ provide: HALEndpointService, useValue: {} },
EPeopleRegistryComponent
{ provide: NotificationsService, useValue: new NotificationsServiceStub() },
{ provide: AuthService, useValue: authService },
{ provide: AuthorizationDataService, useValue: authorizationService },
{ provide: RequestService, useValue: jasmine.createSpyObj('requestService', ['removeByHrefSubstring'])}
],
schemas: [NO_ERRORS_SCHEMA]
}).compileComponents();
@@ -137,9 +139,9 @@ describe('EPersonFormComponent', () => {
fixture.detectChanges();
});
it('should create EPersonFormComponent', inject([EPersonFormComponent], (comp: EPersonFormComponent) => {
expect(comp).toBeDefined();
}));
it('should create EPersonFormComponent', () => {
expect(component).toBeDefined();
});
describe('when submitting the form', () => {
let firstName;
@@ -228,4 +230,89 @@ describe('EPersonFormComponent', () => {
});
});
describe('impersonate', () => {
let ePersonId;
beforeEach(() => {
spyOn(authService, 'impersonate').and.callThrough();
ePersonId = 'testEPersonId';
component.epersonInitial = Object.assign(new EPerson(), {
id: ePersonId
});
component.impersonate();
});
it('should call authService.impersonate', () => {
expect(authService.impersonate).toHaveBeenCalledWith(ePersonId);
});
it('should set isImpersonated to true', () => {
expect(component.isImpersonated).toBe(true);
});
});
describe('stopImpersonating', () => {
beforeEach(() => {
spyOn(authService, 'stopImpersonatingAndRefresh').and.callThrough();
component.stopImpersonating();
});
it('should call authService.stopImpersonatingAndRefresh', () => {
expect(authService.stopImpersonatingAndRefresh).toHaveBeenCalled();
});
it('should set isImpersonated to false', () => {
expect(component.isImpersonated).toBe(false);
});
});
describe('delete', () => {
let ePersonId;
let eperson: EPerson;
let modalService;
beforeEach(() => {
spyOn(authService, 'impersonate').and.callThrough();
ePersonId = 'testEPersonId';
eperson = EPersonMock;
component.epersonInitial = eperson;
component.canDelete$ = observableOf(true);
spyOn(component.epersonService, 'getActiveEPerson').and.returnValue(observableOf(eperson));
modalService = (component as any).modalService;
spyOn(modalService, 'open').and.returnValue(Object.assign({ componentInstance: Object.assign({ response: observableOf(true) }) }));
fixture.detectChanges()
});
it ('the delete button should be active if the eperson can be deleted', () => {
const deleteButton = fixture.debugElement.query(By.css('.delete-button'));
expect(deleteButton.nativeElement.disabled).toBe(false);
});
it ('the delete button should be disabled if the eperson cannot be deleted', () => {
component.canDelete$ = observableOf(false);
fixture.detectChanges()
const deleteButton = fixture.debugElement.query(By.css('.delete-button'));
expect(deleteButton.nativeElement.disabled).toBe(true);
});
it ('should call the epersonFormComponent delete when clicked on the button' , () => {
spyOn(component, 'delete').and.stub();
spyOn(component.epersonService, 'deleteEPerson').and.returnValue(observableOf(new RestResponse(true, 204, 'No Content')));
const deleteButton = fixture.debugElement.query(By.css('.delete-button'));
deleteButton.triggerEventHandler('click', null);
expect(component.delete).toHaveBeenCalled();
});
it ('should call the epersonService delete when clicked on the button' , () => {
// ePersonDataServiceStub.activeEPerson = eperson;
spyOn(component.epersonService, 'deleteEPerson').and.returnValue(observableOf(new RestResponse(true, 204, 'No Content')));
const deleteButton = fixture.debugElement.query(By.css('.delete-button'));
expect(deleteButton.nativeElement.disabled).toBe(false);
deleteButton.triggerEventHandler('click', null);
fixture.detectChanges()
expect(component.epersonService.deleteEPerson).toHaveBeenCalledWith(eperson);
});
})
});

View File

@@ -7,9 +7,9 @@ import {
DynamicInputModel
} from '@ng-dynamic-forms/core';
import { TranslateService } from '@ngx-translate/core';
import { Subscription, combineLatest } from 'rxjs';
import { Subscription, combineLatest, of } from 'rxjs';
import { Observable } from 'rxjs/internal/Observable';
import { take } from 'rxjs/operators';
import { switchMap, take } from 'rxjs/operators';
import { RestResponse } from '../../../../core/cache/response.models';
import { PaginatedList } from '../../../../core/data/paginated-list';
import { RemoteData } from '../../../../core/data/remote-data';
@@ -22,6 +22,12 @@ import { hasValue } from '../../../../shared/empty.util';
import { FormBuilderService } from '../../../../shared/form/builder/form-builder.service';
import { NotificationsService } from '../../../../shared/notifications/notifications.service';
import { PaginationComponentOptions } from '../../../../shared/pagination/pagination-component-options.model';
import { AuthService } from '../../../../core/auth/auth.service';
import { AuthorizationDataService } from '../../../../core/data/feature-authorization/authorization-data.service';
import { FeatureID } from '../../../../core/data/feature-authorization/feature-id';
import { ConfirmationModalComponent } from '../../../../shared/confirmation-modal/confirmation-modal.component';
import { NgbModal } from '@ng-bootstrap/ng-bootstrap';
import { RequestService } from '../../../../core/data/request.service';
@Component({
selector: 'ds-eperson-form',
@@ -105,6 +111,22 @@ export class EPersonFormComponent implements OnInit, OnDestroy {
*/
@Output() cancelForm: EventEmitter<any> = new EventEmitter();
/**
* Observable whether or not the admin is allowed to reset the EPerson's password
* TODO: Initialize the observable once the REST API supports this (currently hardcoded to return false)
*/
canReset$: Observable<boolean> = of(false);
/**
* Observable whether or not the admin is allowed to delete the EPerson
*/
canDelete$: Observable<boolean>;
/**
* Observable whether or not the admin is allowed to impersonate the EPerson
*/
canImpersonate$: Observable<boolean>;
/**
* List of subscriptions
*/
@@ -129,24 +151,43 @@ export class EPersonFormComponent implements OnInit, OnDestroy {
*/
epersonInitial: EPerson;
/**
* Whether or not this EPerson is currently being impersonated
*/
isImpersonated = false;
constructor(public epersonService: EPersonDataService,
public groupsDataService: GroupDataService,
private formBuilderService: FormBuilderService,
private translateService: TranslateService,
private notificationsService: NotificationsService,) {
private notificationsService: NotificationsService,
private authService: AuthService,
private authorizationService: AuthorizationDataService,
private modalService: NgbModal,
public requestService: RequestService) {
this.subs.push(this.epersonService.getActiveEPerson().subscribe((eperson: EPerson) => {
this.epersonInitial = eperson;
if (hasValue(eperson)) {
this.isImpersonated = this.authService.isImpersonatingUser(eperson.id);
}
}));
}
ngOnInit() {
this.initialisePage();
}
/**
* This method will initialise the page
*/
initialisePage() {
combineLatest(
this.translateService.get(`${this.messagePrefix}.firstName`),
this.translateService.get(`${this.messagePrefix}.lastName`),
this.translateService.get(`${this.messagePrefix}.email`),
this.translateService.get(`${this.messagePrefix}.canLogIn`),
this.translateService.get(`${this.messagePrefix}.requireCertificate`),
this.translateService.get(`${this.messagePrefix}.emailHint`),
this.translateService.get(`${this.messagePrefix}.firstName`),
this.translateService.get(`${this.messagePrefix}.lastName`),
this.translateService.get(`${this.messagePrefix}.email`),
this.translateService.get(`${this.messagePrefix}.canLogIn`),
this.translateService.get(`${this.messagePrefix}.requireCertificate`),
this.translateService.get(`${this.messagePrefix}.emailHint`),
).subscribe(([firstName, lastName, email, canLogIn, requireCertificate, emailHint]) => {
this.firstName = new DynamicInputModel({
id: 'firstName',
@@ -178,19 +219,19 @@ export class EPersonFormComponent implements OnInit, OnDestroy {
hint: emailHint
});
this.canLogIn = new DynamicCheckboxModel(
{
id: 'canLogIn',
label: canLogIn,
name: 'canLogIn',
value: (this.epersonInitial != null ? this.epersonInitial.canLogIn : true)
});
{
id: 'canLogIn',
label: canLogIn,
name: 'canLogIn',
value: (this.epersonInitial != null ? this.epersonInitial.canLogIn : true)
});
this.requireCertificate = new DynamicCheckboxModel(
{
id: 'requireCertificate',
label: requireCertificate,
name: 'requireCertificate',
value: (this.epersonInitial != null ? this.epersonInitial.requireCertificate : false)
});
{
id: 'requireCertificate',
label: requireCertificate,
name: 'requireCertificate',
value: (this.epersonInitial != null ? this.epersonInitial.requireCertificate : false)
});
this.formModel = [
this.firstName,
this.lastName,
@@ -214,6 +255,12 @@ export class EPersonFormComponent implements OnInit, OnDestroy {
requireCertificate: eperson != null ? eperson.requireCertificate : false
});
}));
this.canImpersonate$ = this.epersonService.getActiveEPerson().pipe(
switchMap((eperson) => this.authorizationService.isAuthorized(FeatureID.LoginOnBehalfOf, hasValue(eperson) ? eperson.self : undefined))
);
this.canDelete$ = this.epersonService.getActiveEPerson().pipe(
switchMap((eperson) => this.authorizationService.isAuthorized(FeatureID.CanDelete, hasValue(eperson) ? eperson.self : undefined))
);
});
}
@@ -364,6 +411,51 @@ export class EPersonFormComponent implements OnInit, OnDestroy {
}));
}
/**
* Start impersonating the EPerson
*/
impersonate() {
this.authService.impersonate(this.epersonInitial.id);
this.isImpersonated = true;
}
/**
* Deletes the EPerson from the Repository. The EPerson will be the only that this form is showing.
* It'll either show a success or error message depending on whether the delete was successful or not.
*/
delete() {
this.epersonService.getActiveEPerson().pipe(take(1)).subscribe((eperson: EPerson) => {
const modalRef = this.modalService.open(ConfirmationModalComponent);
modalRef.componentInstance.dso = eperson;
modalRef.componentInstance.headerLabel = 'confirmation-modal.delete-eperson.header';
modalRef.componentInstance.infoLabel = 'confirmation-modal.delete-eperson.info';
modalRef.componentInstance.cancelLabel = 'confirmation-modal.delete-eperson.cancel';
modalRef.componentInstance.confirmLabel = 'confirmation-modal.delete-eperson.confirm';
modalRef.componentInstance.response.pipe(take(1)).subscribe((confirm: boolean) => {
if (confirm) {
if (hasValue(eperson.id)) {
this.epersonService.deleteEPerson(eperson).pipe(take(1)).subscribe((restResponse: RestResponse) => {
if (restResponse.isSuccessful) {
this.notificationsService.success(this.translateService.get(this.labelPrefix + 'notification.deleted.success', { name: eperson.name }));
this.reset();
} else {
this.notificationsService.error('Error occured when trying to delete EPerson with id: ' + eperson.id + ' with code: ' + restResponse.statusCode + ' and message: ' + restResponse.statusText);
}
this.cancelForm.emit();
})
}}
});
})
}
/**
* Stop impersonating the EPerson
*/
stopImpersonating() {
this.authService.stopImpersonatingAndRefresh();
this.isImpersonated = false;
}
/**
* Cancel the current edit when component is destroyed & unsub all subscriptions
*/
@@ -371,4 +463,14 @@ export class EPersonFormComponent implements OnInit, OnDestroy {
this.onCancel();
this.subs.filter((sub) => hasValue(sub)).forEach((sub) => sub.unsubscribe());
}
/**
* This method will ensure that the page gets reset and that the cache is cleared
*/
reset() {
this.epersonService.getActiveEPerson().pipe(take(1)).subscribe((eperson: EPerson) => {
this.requestService.removeByHrefSubstring(eperson.self);
});
this.initialisePage();
}
}

View File

@@ -23,15 +23,15 @@ import { HALEndpointService } from '../../../../core/shared/hal-endpoint.service
import { PageInfo } from '../../../../core/shared/page-info.model';
import { UUIDService } from '../../../../core/shared/uuid.service';
import { FormBuilderService } from '../../../../shared/form/builder/form-builder.service';
import { getMockFormBuilderService } from '../../../../shared/mocks/mock-form-builder-service';
import { MockRouter } from '../../../../shared/mocks/mock-router';
import { getMockTranslateService } from '../../../../shared/mocks/mock-translate.service';
import { NotificationsService } from '../../../../shared/notifications/notifications.service';
import { GroupMock, GroupMock2 } from '../../../../shared/testing/group-mock';
import { MockTranslateLoader } from '../../../../shared/testing/mock-translate-loader';
import { NotificationsServiceStub } from '../../../../shared/testing/notifications-service-stub';
import { createSuccessfulRemoteDataObject$ } from '../../../../shared/testing/utils';
import { GroupFormComponent } from './group-form.component';
import { createSuccessfulRemoteDataObject$ } from '../../../../shared/remote-data.utils';
import { getMockFormBuilderService } from '../../../../shared/mocks/form-builder-service.mock';
import { getMockTranslateService } from '../../../../shared/mocks/translate.service.mock';
import { TranslateLoaderMock } from '../../../../shared/testing/translate-loader.mock';
import { RouterMock } from '../../../../shared/mocks/router.mock';
import { NotificationsServiceStub } from '../../../../shared/testing/notifications-service.stub';
describe('GroupFormComponent', () => {
let component: GroupFormComponent;
@@ -90,13 +90,13 @@ describe('GroupFormComponent', () => {
};
builderService = getMockFormBuilderService();
translateService = getMockTranslateService();
router = new MockRouter();
router = new RouterMock();
TestBed.configureTestingModule({
imports: [CommonModule, NgbModule, FormsModule, ReactiveFormsModule, BrowserModule,
TranslateModule.forRoot({
loader: {
provide: TranslateLoader,
useClass: MockTranslateLoader
useClass: TranslateLoaderMock
}
}),
],

View File

@@ -16,17 +16,17 @@ import { EPerson } from '../../../../../core/eperson/models/eperson.model';
import { Group } from '../../../../../core/eperson/models/group.model';
import { PageInfo } from '../../../../../core/shared/page-info.model';
import { FormBuilderService } from '../../../../../shared/form/builder/form-builder.service';
import { getMockFormBuilderService } from '../../../../../shared/mocks/mock-form-builder-service';
import { MockRouter } from '../../../../../shared/mocks/mock-router';
import { getMockTranslateService } from '../../../../../shared/mocks/mock-translate.service';
import { NotificationsService } from '../../../../../shared/notifications/notifications.service';
import { EPersonMock, EPersonMock2 } from '../../../../../shared/testing/eperson-mock';
import { GroupMock, GroupMock2 } from '../../../../../shared/testing/group-mock';
import { MockTranslateLoader } from '../../../../../shared/testing/mock-translate-loader';
import { NotificationsServiceStub } from '../../../../../shared/testing/notifications-service-stub';
import { of as observableOf } from 'rxjs';
import { createSuccessfulRemoteDataObject$ } from '../../../../../shared/testing/utils';
import { MembersListComponent } from './members-list.component';
import { EPersonMock, EPersonMock2 } from '../../../../../shared/testing/eperson.mock';
import { createSuccessfulRemoteDataObject$ } from '../../../../../shared/remote-data.utils';
import { getMockTranslateService } from '../../../../../shared/mocks/translate.service.mock';
import { getMockFormBuilderService } from '../../../../../shared/mocks/form-builder-service.mock';
import { TranslateLoaderMock } from '../../../../../shared/testing/translate-loader.mock';
import { NotificationsServiceStub } from '../../../../../shared/testing/notifications-service.stub';
import { RouterMock } from '../../../../../shared/mocks/router.mock';
describe('MembersListComponent', () => {
let component: MembersListComponent;
@@ -119,7 +119,7 @@ describe('MembersListComponent', () => {
TranslateModule.forRoot({
loader: {
provide: TranslateLoader,
useClass: MockTranslateLoader
useClass: TranslateLoaderMock
}
}),
],
@@ -129,7 +129,7 @@ describe('MembersListComponent', () => {
{ provide: GroupDataService, useValue: groupsDataServiceStub },
{ provide: NotificationsService, useValue: new NotificationsServiceStub() },
{ provide: FormBuilderService, useValue: builderService },
{ provide: Router, useValue: new MockRouter() },
{ provide: Router, useValue: new RouterMock() },
],
schemas: [NO_ERRORS_SCHEMA]
}).compileComponents();

View File

@@ -14,16 +14,16 @@ import { GroupDataService } from '../../../../../core/eperson/group-data.service
import { Group } from '../../../../../core/eperson/models/group.model';
import { PageInfo } from '../../../../../core/shared/page-info.model';
import { FormBuilderService } from '../../../../../shared/form/builder/form-builder.service';
import { getMockFormBuilderService } from '../../../../../shared/mocks/mock-form-builder-service';
import { MockRouter } from '../../../../../shared/mocks/mock-router';
import { getMockTranslateService } from '../../../../../shared/mocks/mock-translate.service';
import { NotificationsService } from '../../../../../shared/notifications/notifications.service';
import { GroupMock, GroupMock2 } from '../../../../../shared/testing/group-mock';
import { MockTranslateLoader } from '../../../../../shared/testing/mock-translate-loader';
import { NotificationsServiceStub } from '../../../../../shared/testing/notifications-service-stub';
import { of as observableOf } from 'rxjs';
import { createSuccessfulRemoteDataObject$ } from '../../../../../shared/testing/utils';
import { SubgroupsListComponent } from './subgroups-list.component';
import { createSuccessfulRemoteDataObject$ } from '../../../../../shared/remote-data.utils';
import { RouterMock } from '../../../../../shared/mocks/router.mock';
import { getMockFormBuilderService } from '../../../../../shared/mocks/form-builder-service.mock';
import { getMockTranslateService } from '../../../../../shared/mocks/translate.service.mock';
import { TranslateLoaderMock } from '../../../../../shared/testing/translate-loader.mock';
import { NotificationsServiceStub } from '../../../../../shared/testing/notifications-service.stub';
describe('SubgroupsListComponent', () => {
let component: SubgroupsListComponent;
@@ -82,7 +82,7 @@ describe('SubgroupsListComponent', () => {
return observableOf(new RestResponse(true, 200, 'Success'));
}
};
routerStub = new MockRouter();
routerStub = new RouterMock();
builderService = getMockFormBuilderService();
translateService = getMockTranslateService();
TestBed.configureTestingModule({
@@ -90,7 +90,7 @@ describe('SubgroupsListComponent', () => {
TranslateModule.forRoot({
loader: {
provide: TranslateLoader,
useClass: MockTranslateLoader
useClass: TranslateLoaderMock
}
}),
],

View File

@@ -15,15 +15,15 @@ import { EPerson } from '../../../core/eperson/models/eperson.model';
import { Group } from '../../../core/eperson/models/group.model';
import { RouteService } from '../../../core/services/route.service';
import { PageInfo } from '../../../core/shared/page-info.model';
import { MockRouter } from '../../../shared/mocks/mock-router';
import { MockTranslateLoader } from '../../../shared/mocks/mock-translate-loader';
import { NotificationsService } from '../../../shared/notifications/notifications.service';
import { EPersonMock, EPersonMock2 } from '../../../shared/testing/eperson-mock';
import { GroupMock, GroupMock2 } from '../../../shared/testing/group-mock';
import { NotificationsServiceStub } from '../../../shared/testing/notifications-service-stub';
import { routeServiceStub } from '../../../shared/testing/route-service-stub';
import { createSuccessfulRemoteDataObject$ } from '../../../shared/testing/utils';
import { GroupsRegistryComponent } from './groups-registry.component';
import { EPersonMock, EPersonMock2 } from '../../../shared/testing/eperson.mock';
import { createSuccessfulRemoteDataObject$ } from '../../../shared/remote-data.utils';
import { TranslateLoaderMock } from '../../../shared/testing/translate-loader.mock';
import { NotificationsServiceStub } from '../../../shared/testing/notifications-service.stub';
import { routeServiceStub } from '../../../shared/testing/route-service.stub';
import { RouterMock } from '../../../shared/mocks/router.mock';
describe('GroupRegistryComponent', () => {
let component: GroupsRegistryComponent;
@@ -82,7 +82,7 @@ describe('GroupRegistryComponent', () => {
TranslateModule.forRoot({
loader: {
provide: TranslateLoader,
useClass: MockTranslateLoader
useClass: TranslateLoaderMock
}
}),
],
@@ -92,7 +92,7 @@ describe('GroupRegistryComponent', () => {
{ provide: GroupDataService, useValue: groupsDataServiceStub },
{ provide: NotificationsService, useValue: new NotificationsServiceStub() },
{ provide: RouteService, useValue: routeServiceStub },
{ provide: Router, useValue: new MockRouter() },
{ provide: Router, useValue: new RouterMock() },
],
schemas: [NO_ERRORS_SCHEMA]
}).compileComponents();

View File

@@ -47,7 +47,7 @@ export class GroupsRegistryComponent implements OnInit {
// Current search in groups registry
currentSearchQuery: string;
constructor(private groupService: GroupDataService,
constructor(public groupService: GroupDataService,
private ePersonDataService: EPersonDataService,
private translateService: TranslateService,
private notificationsService: NotificationsService,

View File

@@ -0,0 +1,4 @@
<div class="container">
<h2>{{'admin.curation-tasks.header' |translate }}</h2>
<ds-curation-form></ds-curation-form>
</div>

View File

@@ -0,0 +1,28 @@
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { AdminCurationTasksComponent } from './admin-curation-tasks.component';
import { TranslateModule } from '@ngx-translate/core';
import { CUSTOM_ELEMENTS_SCHEMA } from '@angular/core';
describe('AdminCurationTasksComponent', () => {
let comp: AdminCurationTasksComponent;
let fixture: ComponentFixture<AdminCurationTasksComponent>;
beforeEach(async(() => {
TestBed.configureTestingModule({
imports: [TranslateModule.forRoot()],
declarations: [AdminCurationTasksComponent],
schemas: [CUSTOM_ELEMENTS_SCHEMA]
}).compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(AdminCurationTasksComponent);
comp = fixture.componentInstance;
});
describe('init', () => {
it('should initialise the comp', () => {
expect(comp).toBeDefined();
expect(fixture.debugElement.nativeElement.innerHTML).toContain('ds-curation-form');
});
});
});

View File

@@ -0,0 +1,12 @@
import { Component } from '@angular/core';
/**
* Component responsible for rendering the system wide Curation Task UI
*/
@Component({
selector: 'ds-admin-curation-task',
templateUrl: './admin-curation-tasks.component.html',
})
export class AdminCurationTasksComponent {
}

View File

@@ -0,0 +1,15 @@
<div class="container">
<h2 id="header">{{'admin.metadata-import.page.header' | translate}}</h2>
<p>{{'admin.metadata-import.page.help' | translate}}</p>
<ds-file-dropzone-no-uploader
(onFileAdded)="setFile($event)"
[dropMessageLabel]="'admin.metadata-import.page.dropMsg'"
[dropMessageLabelReplacement]="'admin.metadata-import.page.dropMsgReplace'">
</ds-file-dropzone-no-uploader>
<button class="btn btn-secondary" id="backButton"
(click)="this.onReturn();">{{'admin.metadata-import.page.button.return' | translate}}</button>
<button class="btn btn-primary" id="proceedButton"
(click)="this.importMetadata();">{{'admin.metadata-import.page.button.proceed' | translate}}</button>
</div>

View File

@@ -0,0 +1,151 @@
import { Location } from '@angular/common';
import { NO_ERRORS_SCHEMA } from '@angular/core';
import { async, ComponentFixture, fakeAsync, TestBed } from '@angular/core/testing';
import { FormsModule } from '@angular/forms';
import { By } from '@angular/platform-browser';
import { Router } from '@angular/router';
import { RouterTestingModule } from '@angular/router/testing';
import { TranslateModule } from '@ngx-translate/core';
import { of as observableOf } from 'rxjs/internal/observable/of';
import { AuthService } from '../../core/auth/auth.service';
import {
METADATA_IMPORT_SCRIPT_NAME,
ScriptDataService
} from '../../core/data/processes/script-data.service';
import { EPerson } from '../../core/eperson/models/eperson.model';
import { ProcessParameter } from '../../process-page/processes/process-parameter.model';
import { NotificationsService } from '../../shared/notifications/notifications.service';
import { NotificationsServiceStub } from '../../shared/testing/notifications-service.stub';
import { FileValueAccessorDirective } from '../../shared/utils/file-value-accessor.directive';
import { FileValidator } from '../../shared/utils/require-file.validator';
import { MetadataImportPageComponent } from './metadata-import-page.component';
describe('MetadataImportPageComponent', () => {
let comp: MetadataImportPageComponent;
let fixture: ComponentFixture<MetadataImportPageComponent>;
let user;
let notificationService: NotificationsServiceStub;
let scriptService: any;
let router;
let authService;
let locationStub;
function init() {
notificationService = new NotificationsServiceStub();
scriptService = jasmine.createSpyObj('scriptService',
{
invoke: observableOf({
response:
{
isSuccessful: true,
resourceSelfLinks: ['https://localhost:8080/api/core/processes/45']
}
})
}
);
user = Object.assign(new EPerson(), {
id: 'userId',
email: 'user@test.com'
});
authService = jasmine.createSpyObj('authService', {
getAuthenticatedUserFromStore: observableOf(user)
});
router = jasmine.createSpyObj('router', {
navigateByUrl: jasmine.createSpy('navigateByUrl')
});
locationStub = jasmine.createSpyObj('location', {
back: jasmine.createSpy('back')
});
}
beforeEach(async(() => {
init();
TestBed.configureTestingModule({
imports: [
FormsModule,
TranslateModule.forRoot(),
RouterTestingModule.withRoutes([])
],
declarations: [MetadataImportPageComponent, FileValueAccessorDirective, FileValidator],
providers: [
{ provide: NotificationsService, useValue: notificationService },
{ provide: ScriptDataService, useValue: scriptService },
{ provide: Router, useValue: router },
{ provide: AuthService, useValue: authService },
{ provide: Location, useValue: locationStub },
],
schemas: [NO_ERRORS_SCHEMA]
}).compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(MetadataImportPageComponent);
comp = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(comp).toBeTruthy();
});
describe('if back button is pressed', () => {
beforeEach(fakeAsync(() => {
const proceed = fixture.debugElement.query(By.css('#backButton')).nativeElement;
proceed.click();
fixture.detectChanges();
}));
it('should do location.back', () => {
expect(locationStub.back).toHaveBeenCalled();
});
});
describe('if file is set', () => {
let fileMock: File;
beforeEach(() => {
fileMock = new File([''], 'filename.txt', { type: 'text/plain' });
comp.setFile(fileMock);
});
describe('if proceed button is pressed', () => {
beforeEach(fakeAsync(() => {
const proceed = fixture.debugElement.query(By.css('#proceedButton')).nativeElement;
proceed.click();
fixture.detectChanges();
}));
it('metadata-import script is invoked with its -e currentUserEmail, -f fileName and the mockFile', () => {
const parameterValues: ProcessParameter[] = [
Object.assign(new ProcessParameter(), { name: '-e', value: user.email }),
Object.assign(new ProcessParameter(), { name: '-f', value: 'filename.txt' }),
];
expect(scriptService.invoke).toHaveBeenCalledWith(METADATA_IMPORT_SCRIPT_NAME, parameterValues, [fileMock]);
});
it('success notification is shown', () => {
expect(notificationService.success).toHaveBeenCalled();
});
it('redirected to process page', () => {
expect(router.navigateByUrl).toHaveBeenCalledWith('/processes/45');
});
});
describe('if proceed is pressed; but script invoke fails', () => {
beforeEach(fakeAsync(() => {
jasmine.getEnv().allowRespy(true);
spyOn(scriptService, 'invoke').and.returnValue(observableOf({
response:
{
isSuccessful: false,
}
}));
const proceed = fixture.debugElement.query(By.css('#proceedButton')).nativeElement;
proceed.click();
fixture.detectChanges();
}));
it('error notification is shown', () => {
expect(notificationService.error).toHaveBeenCalled();
});
});
});
});

View File

@@ -0,0 +1,106 @@
import { Location } from '@angular/common';
import { Component, OnInit } from '@angular/core';
import { Router } from '@angular/router';
import { TranslateService } from '@ngx-translate/core';
import { Observable } from 'rxjs/internal/Observable';
import { map, switchMap, take } from 'rxjs/operators';
import { AuthService } from '../../core/auth/auth.service';
import { METADATA_IMPORT_SCRIPT_NAME, ScriptDataService } from '../../core/data/processes/script-data.service';
import { RequestEntry } from '../../core/data/request.reducer';
import { EPerson } from '../../core/eperson/models/eperson.model';
import { ProcessParameter } from '../../process-page/processes/process-parameter.model';
import { isNotEmpty } from '../../shared/empty.util';
import { NotificationsService } from '../../shared/notifications/notifications.service';
@Component({
selector: 'ds-metadata-import-page',
templateUrl: './metadata-import-page.component.html'
})
/**
* Component that represents a metadata import page for administrators
*/
export class MetadataImportPageComponent implements OnInit {
/**
* The current value of the file
*/
fileObject: File;
/**
* The authenticated user's email
*/
private currentUserEmail$: Observable<string>;
public constructor(protected authService: AuthService,
private location: Location,
protected translate: TranslateService,
protected notificationsService: NotificationsService,
private scriptDataService: ScriptDataService,
private router: Router) {
}
/**
* Set file
* @param file
*/
setFile(file) {
this.fileObject = file;
}
/**
* Method provided by Angular. Invoked after the constructor.
*/
ngOnInit() {
this.currentUserEmail$ = this.authService.getAuthenticatedUserFromStore().pipe(
map((user: EPerson) => user.email)
);
}
/**
* When return button is pressed go to previous location
*/
public onReturn() {
this.location.back();
}
/**
* Starts import-metadata script with -e currentUserEmail -f fileName (and the selected file)
*/
public importMetadata() {
if (this.fileObject == null) {
this.notificationsService.error(this.translate.get('admin.metadata-import.page.error.addFile'));
} else {
this.currentUserEmail$.pipe(
switchMap((email: string) => {
if (isNotEmpty(email)) {
const parameterValues: ProcessParameter[] = [
Object.assign(new ProcessParameter(), { name: '-e', value: email }),
Object.assign(new ProcessParameter(), { name: '-f', value: this.fileObject.name }),
];
return this.scriptDataService.invoke(METADATA_IMPORT_SCRIPT_NAME, parameterValues, [this.fileObject])
.pipe(
take(1),
map((requestEntry: RequestEntry) => {
if (requestEntry.response.isSuccessful) {
const title = this.translate.get('process.new.notification.success.title');
const content = this.translate.get('process.new.notification.success.content');
this.notificationsService.success(title, content);
const response: any = requestEntry.response;
if (isNotEmpty(response.resourceSelfLinks)) {
const processNumber = response.resourceSelfLinks[0].split('/').pop();
this.router.navigateByUrl('/processes/' + processNumber);
}
} else {
const title = this.translate.get('process.new.notification.error.title');
const content = this.translate.get('process.new.notification.error.content');
this.notificationsService.error(title, content);
}
}));
}
}),
take(1)
).subscribe();
}
}
}

View File

@@ -0,0 +1,8 @@
import { URLCombiner } from '../../core/url-combiner/url-combiner';
import { getRegistriesModuleRoute } from '../admin-routing-paths';
export const BITSTREAMFORMATS_MODULE_PATH = 'bitstream-formats';
export function getBitstreamFormatsModuleRoute() {
return new URLCombiner(getRegistriesModuleRoute(), BITSTREAMFORMATS_MODULE_PATH).toString();
}

View File

@@ -2,28 +2,34 @@ import { MetadataRegistryComponent } from './metadata-registry/metadata-registry
import { RouterModule } from '@angular/router';
import { NgModule } from '@angular/core';
import { MetadataSchemaComponent } from './metadata-schema/metadata-schema.component';
import { URLCombiner } from '../../core/url-combiner/url-combiner';
import { getRegistriesModulePath } from '../admin-routing.module';
const BITSTREAMFORMATS_MODULE_PATH = 'bitstream-formats';
export function getBitstreamFormatsModulePath() {
return new URLCombiner(getRegistriesModulePath(), BITSTREAMFORMATS_MODULE_PATH).toString();
}
import { I18nBreadcrumbResolver } from '../../core/breadcrumbs/i18n-breadcrumb.resolver';
import { BITSTREAMFORMATS_MODULE_PATH } from './admin-registries-routing-paths';
@NgModule({
imports: [
RouterModule.forChild([
{path: 'metadata', component: MetadataRegistryComponent, data: {title: 'admin.registries.metadata.title'}},
{
path: 'metadata/:schemaName',
component: MetadataSchemaComponent,
data: {title: 'admin.registries.schema.title'}
path: 'metadata',
resolve: { breadcrumb: I18nBreadcrumbResolver },
data: {title: 'admin.registries.metadata.title', breadcrumbKey: 'admin.registries.metadata'},
children: [
{
path: '',
component: MetadataRegistryComponent
},
{
path: ':schemaName',
resolve: { breadcrumb: I18nBreadcrumbResolver },
component: MetadataSchemaComponent,
data: {title: 'admin.registries.schema.title', breadcrumbKey: 'admin.registries.schema'}
}
]
},
{
path: BITSTREAMFORMATS_MODULE_PATH,
resolve: { breadcrumb: I18nBreadcrumbResolver },
loadChildren: './bitstream-formats/bitstream-formats.module#BitstreamFormatsModule',
data: {title: 'admin.registries.bitstream-formats.title'}
data: {title: 'admin.registries.bitstream-formats.title', breadcrumbKey: 'admin.registries.bitstream-formats'}
},
])
]

View File

@@ -11,8 +11,8 @@ import { BitstreamFormatDataService } from '../../../../core/data/bitstream-form
import { BitstreamFormatSupportLevel } from '../../../../core/shared/bitstream-format-support-level';
import { BitstreamFormat } from '../../../../core/shared/bitstream-format.model';
import { NotificationsService } from '../../../../shared/notifications/notifications.service';
import { NotificationsServiceStub } from '../../../../shared/testing/notifications-service-stub';
import { RouterStub } from '../../../../shared/testing/router-stub';
import { NotificationsServiceStub } from '../../../../shared/testing/notifications-service.stub';
import { RouterStub } from '../../../../shared/testing/router.stub';
import { AddBitstreamFormatComponent } from './add-bitstream-format.component';
describe('AddBitstreamFormatComponent', () => {

View File

@@ -5,8 +5,8 @@ import { BitstreamFormat } from '../../../../core/shared/bitstream-format.model'
import { BitstreamFormatDataService } from '../../../../core/data/bitstream-format-data.service';
import { RestResponse } from '../../../../core/cache/response.models';
import { NotificationsService } from '../../../../shared/notifications/notifications.service';
import { getBitstreamFormatsModulePath } from '../../admin-registries-routing.module';
import { TranslateService } from '@ngx-translate/core';
import { getBitstreamFormatsModuleRoute } from '../../admin-registries-routing-paths';
/**
* This component renders the page to create a new bitstream format.
@@ -37,7 +37,7 @@ export class AddBitstreamFormatComponent {
if (response.isSuccessful) {
this.notificationService.success(this.translateService.get('admin.registries.bitstream-formats.create.success.head'),
this.translateService.get('admin.registries.bitstream-formats.create.success.content'));
this.router.navigate([getBitstreamFormatsModulePath()]);
this.router.navigate([getBitstreamFormatsModuleRoute()]);
this.bitstreamFormatDataService.clearBitStreamFormatRequests().subscribe();
} else {
this.notificationService.error(this.translateService.get('admin.registries.bitstream-formats.create.failure.head'),

View File

@@ -4,6 +4,7 @@ import { BitstreamFormatsResolver } from './bitstream-formats.resolver';
import { EditBitstreamFormatComponent } from './edit-bitstream-format/edit-bitstream-format.component';
import { BitstreamFormatsComponent } from './bitstream-formats.component';
import { AddBitstreamFormatComponent } from './add-bitstream-format/add-bitstream-format.component';
import { I18nBreadcrumbResolver } from '../../../core/breadcrumbs/i18n-breadcrumb.resolver';
const BITSTREAMFORMAT_EDIT_PATH = ':id/edit';
const BITSTREAMFORMAT_ADD_PATH = 'add';
@@ -17,14 +18,18 @@ const BITSTREAMFORMAT_ADD_PATH = 'add';
},
{
path: BITSTREAMFORMAT_ADD_PATH,
resolve: { breadcrumb: I18nBreadcrumbResolver },
component: AddBitstreamFormatComponent,
data: {breadcrumbKey: 'admin.registries.bitstream-formats.create'}
},
{
path: BITSTREAMFORMAT_EDIT_PATH,
component: EditBitstreamFormatComponent,
resolve: {
bitstreamFormat: BitstreamFormatsResolver
}
bitstreamFormat: BitstreamFormatsResolver,
breadcrumb: I18nBreadcrumbResolver
},
data: {breadcrumbKey: 'admin.registries.bitstream-formats.edit'}
},
])
],

View File

@@ -11,10 +11,10 @@ import { PaginationComponent } from '../../../shared/pagination/pagination.compo
import { NgbModule } from '@ng-bootstrap/ng-bootstrap';
import { EnumKeysPipe } from '../../../shared/utils/enum-keys-pipe';
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 { BitstreamFormatDataService } from '../../../core/data/bitstream-format-data.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 { BitstreamFormat } from '../../../core/shared/bitstream-format.model';
import { BitstreamFormatSupportLevel } from '../../../core/shared/bitstream-format-support-level';
import { cold, getTestScheduler, hot } from 'jasmine-marbles';
@@ -209,7 +209,7 @@ describe('BitstreamFormatsComponent', () => {
selectBitstreamFormat: {},
deselectBitstreamFormat: {},
deselectAllBitstreamFormats: {},
delete: observableOf(true),
delete: observableOf({ isSuccessful: true }),
clearBitStreamFormatRequests: observableOf('cleared')
});

View File

@@ -11,6 +11,7 @@ import { hasValue } from '../../../shared/empty.util';
import { NotificationsService } from '../../../shared/notifications/notifications.service';
import { Router } from '@angular/router';
import { TranslateService } from '@ngx-translate/core';
import { RestResponse } from '../../../core/cache/response.models';
/**
* This component renders a list of bitstream formats
@@ -64,7 +65,7 @@ export class BitstreamFormatsComponent implements OnInit {
const tasks$ = [];
for (const format of formats) {
if (hasValue(format.id)) {
tasks$.push(this.bitstreamFormatService.delete(format.id));
tasks$.push(this.bitstreamFormatService.delete(format.id).pipe(map((response: RestResponse) => response.isSuccessful)));
}
}
zip(...tasks$).subscribe((results: boolean[]) => {

View File

@@ -12,8 +12,8 @@ import { RemoteData } from '../../../../core/data/remote-data';
import { BitstreamFormatSupportLevel } from '../../../../core/shared/bitstream-format-support-level';
import { BitstreamFormat } from '../../../../core/shared/bitstream-format.model';
import { NotificationsService } from '../../../../shared/notifications/notifications.service';
import { NotificationsServiceStub } from '../../../../shared/testing/notifications-service-stub';
import { RouterStub } from '../../../../shared/testing/router-stub';
import { NotificationsServiceStub } from '../../../../shared/testing/notifications-service.stub';
import { RouterStub } from '../../../../shared/testing/router.stub';
import { EditBitstreamFormatComponent } from './edit-bitstream-format.component';
describe('EditBitstreamFormatComponent', () => {

View File

@@ -7,8 +7,8 @@ import { BitstreamFormat } from '../../../../core/shared/bitstream-format.model'
import { BitstreamFormatDataService } from '../../../../core/data/bitstream-format-data.service';
import { RestResponse } from '../../../../core/cache/response.models';
import { NotificationsService } from '../../../../shared/notifications/notifications.service';
import { getBitstreamFormatsModulePath } from '../../admin-registries-routing.module';
import { TranslateService } from '@ngx-translate/core';
import { getBitstreamFormatsModuleRoute } from '../../admin-registries-routing-paths';
/**
* This component renders the edit page of a bitstream format.
@@ -51,7 +51,7 @@ export class EditBitstreamFormatComponent implements OnInit {
if (response.isSuccessful) {
this.notificationService.success(this.translateService.get('admin.registries.bitstream-formats.edit.success.head'),
this.translateService.get('admin.registries.bitstream-formats.edit.success.content'));
this.router.navigate([getBitstreamFormatsModulePath()]);
this.router.navigate([getBitstreamFormatsModuleRoute()]);
} else {
this.notificationService.error('admin.registries.bitstream-formats.edit.failure.head',
'admin.registries.bitstream-formats.create.edit.content');

View File

@@ -3,7 +3,7 @@ import { CommonModule } from '@angular/common';
import { RouterTestingModule } from '@angular/router/testing';
import { TranslateModule } from '@ngx-translate/core';
import { NgbModule } from '@ng-bootstrap/ng-bootstrap';
import { RouterStub } from '../../../../shared/testing/router-stub';
import { RouterStub } from '../../../../shared/testing/router.stub';
import { FormsModule, ReactiveFormsModule } from '@angular/forms';
import { Router } from '@angular/router';
import { FormatFormComponent } from './format-form.component';

View File

@@ -12,9 +12,9 @@ import {
DynamicTextAreaModel
} from '@ng-dynamic-forms/core';
import { Router } from '@angular/router';
import { getBitstreamFormatsModulePath } from '../../admin-registries-routing.module';
import { hasValue, isEmpty } from '../../../../shared/empty.util';
import { TranslateService } from '@ngx-translate/core';
import { getBitstreamFormatsModuleRoute } from '../../admin-registries-routing-paths';
/**
* The component responsible for rendering the form to create/edit a bitstream format
@@ -189,6 +189,6 @@ export class FormatFormComponent implements OnInit {
* Cancels the edit/create action of the bitstream format and navigates back to the bitstream format registry
*/
onCancel() {
this.router.navigate([getBitstreamFormatsModulePath()]);
this.router.navigate([getBitstreamFormatsModuleRoute()]);
}
}

View File

@@ -11,7 +11,6 @@
<ds-pagination
*ngIf="(metadataSchemas | async)?.payload?.totalElements > 0"
[paginationOptions]="config"
[pageInfoState]="(metadataSchemas | async)?.payload"
[collectionSize]="(metadataSchemas | async)?.payload?.totalElements"
[hideGear]="true"
[hidePagerWhenSinglePage]="true"

View File

@@ -10,14 +10,14 @@ import { RegistryService } from '../../../core/registry/registry.service';
import { NgbModule } from '@ng-bootstrap/ng-bootstrap';
import { EnumKeysPipe } from '../../../shared/utils/enum-keys-pipe';
import { PaginationComponent } from '../../../shared/pagination/pagination.component';
import { HostWindowServiceStub } from '../../../shared/testing/host-window-service-stub';
import { HostWindowServiceStub } from '../../../shared/testing/host-window-service.stub';
import { HostWindowService } from '../../../shared/host-window.service';
import { ChangeDetectionStrategy, NO_ERRORS_SCHEMA } from '@angular/core';
import { NotificationsService } from '../../../shared/notifications/notifications.service';
import { NotificationsServiceStub } from '../../../shared/testing/notifications-service-stub';
import { NotificationsServiceStub } from '../../../shared/testing/notifications-service.stub';
import { RestResponse } from '../../../core/cache/response.models';
import { createSuccessfulRemoteDataObject$ } from '../../../shared/testing/utils';
import { MetadataSchema } from '../../../core/metadata/metadata-schema.model';
import { createSuccessfulRemoteDataObject$ } from '../../../shared/remote-data.utils';
describe('MetadataRegistryComponent', () => {
let comp: MetadataRegistryComponent;

View File

@@ -4,7 +4,7 @@ import { Observable, combineLatest as observableCombineLatest } from 'rxjs';
import { RemoteData } from '../../../core/data/remote-data';
import { PaginatedList } from '../../../core/data/paginated-list';
import { PaginationComponentOptions } from '../../../shared/pagination/pagination-component-options.model';
import { map, take } from 'rxjs/operators';
import { filter, map, switchMap, take } from 'rxjs/operators';
import { hasValue } from '../../../shared/empty.util';
import { RestResponse } from '../../../core/cache/response.models';
import { zip } from 'rxjs/internal/observable/zip';
@@ -12,6 +12,8 @@ import { NotificationsService } from '../../../shared/notifications/notification
import { Route, Router } from '@angular/router';
import { TranslateService } from '@ngx-translate/core';
import { MetadataSchema } from '../../../core/metadata/metadata-schema.model';
import { toFindListOptions } from '../../../shared/pagination/pagination.utils';
import { BehaviorSubject } from 'rxjs/internal/BehaviorSubject';
@Component({
selector: 'ds-metadata-registry',
@@ -37,6 +39,11 @@ export class MetadataRegistryComponent {
pageSize: 25
});
/**
* Whether or not the list of MetadataSchemas needs an update
*/
needsUpdate$: BehaviorSubject<boolean> = new BehaviorSubject<boolean>(true);
constructor(private registryService: RegistryService,
private notificationsService: NotificationsService,
private router: Router,
@@ -50,14 +57,17 @@ export class MetadataRegistryComponent {
*/
onPageChange(event) {
this.config.currentPage = event;
this.updateSchemas();
this.forceUpdateSchemas();
}
/**
* Update the list of schemas by fetching it from the rest api or cache
*/
private updateSchemas() {
this.metadataSchemas = this.registryService.getMetadataSchemas(this.config);
this.metadataSchemas = this.needsUpdate$.pipe(
filter((update) => update === true),
switchMap(() => this.registryService.getMetadataSchemas(toFindListOptions(this.config)))
);
}
/**
@@ -65,8 +75,7 @@ export class MetadataRegistryComponent {
* a new REST call
*/
public forceUpdateSchemas() {
this.registryService.clearMetadataSchemaRequests().subscribe();
this.updateSchemas();
this.needsUpdate$.next(true);
}
/**
@@ -125,6 +134,7 @@ export class MetadataRegistryComponent {
* Delete all the selected metadata schemas
*/
deleteSchemas() {
this.registryService.clearMetadataSchemaRequests().subscribe();
this.registryService.getSelectedMetadataSchemas().pipe(take(1)).subscribe(
(schemas) => {
const tasks$ = [];

View File

@@ -21,7 +21,8 @@ describe('MetadataSchemaFormComponent', () => {
const registryServiceStub = {
getActiveMetadataSchema: () => observableOf(undefined),
createOrUpdateMetadataSchema: (schema: MetadataSchema) => observableOf(schema),
cancelEditMetadataSchema: () => {}
cancelEditMetadataSchema: () => {},
clearMetadataSchemaRequests: () => observableOf(undefined)
};
const formBuilderServiceStub = {
createFormGroup: () => {

View File

@@ -128,6 +128,7 @@ export class MetadataSchemaFormComponent implements OnInit, OnDestroy {
* Emit the updated/created schema using the EventEmitter submitForm
*/
onSubmit() {
this.registryService.clearMetadataSchemaRequests().subscribe();
this.registryService.getActiveMetadataSchema().pipe(take(1)).subscribe(
(schema) => {
const values = {
@@ -139,7 +140,7 @@ export class MetadataSchemaFormComponent implements OnInit, OnDestroy {
this.submitForm.emit(newSchema);
});
} else {
this.registryService.createOrUpdateMetadataSchema(Object.assign(new MetadataSchema(), {
this.registryService.createOrUpdateMetadataSchema(Object.assign(new MetadataSchema(), schema, {
id: schema.id,
prefix: (values.prefix ? values.prefix : schema.prefix),
namespace: (values.namespace ? values.namespace : schema.namespace)
@@ -148,6 +149,7 @@ export class MetadataSchemaFormComponent implements OnInit, OnDestroy {
});
}
this.clearFields();
this.registryService.cancelEditMetadataSchema();
}
);
}

View File

@@ -27,9 +27,11 @@ describe('MetadataFieldFormComponent', () => {
/* tslint:disable:no-empty */
const registryServiceStub = {
getActiveMetadataField: () => observableOf(undefined),
createOrUpdateMetadataField: (field: MetadataField) => observableOf(field),
createMetadataField: (field: MetadataField) => observableOf(field),
updateMetadataField: (field: MetadataField) => observableOf(field),
cancelEditMetadataField: () => {},
cancelEditMetadataSchema: () => {},
clearMetadataFieldRequests: () => observableOf(undefined)
};
const formBuilderServiceStub = {
createFormGroup: () => {
@@ -74,7 +76,6 @@ describe('MetadataFieldFormComponent', () => {
const scopeNote = 'fakeScopeNote';
const expected = Object.assign(new MetadataField(), {
schema: metadataSchema,
element: element,
qualifier: qualifier,
scopeNote: scopeNote

View File

@@ -153,22 +153,21 @@ export class MetadataFieldFormComponent implements OnInit, OnDestroy {
* Emit the updated/created field using the EventEmitter submitForm
*/
onSubmit() {
this.registryService.clearMetadataFieldRequests().subscribe();
this.registryService.getActiveMetadataField().pipe(take(1)).subscribe(
(field) => {
const values = {
schema: this.metadataSchema,
element: this.element.value,
qualifier: this.qualifier.value,
scopeNote: this.scopeNote.value
};
if (field == null) {
this.registryService.createOrUpdateMetadataField(Object.assign(new MetadataField(), values)).subscribe((newField) => {
this.registryService.createMetadataField(Object.assign(new MetadataField(), values), this.metadataSchema).subscribe((newField) => {
this.submitForm.emit(newField);
});
} else {
this.registryService.createOrUpdateMetadataField(Object.assign(new MetadataField(), {
this.registryService.updateMetadataField(Object.assign(new MetadataField(), field, {
id: field.id,
schema: this.metadataSchema,
element: (values.element ? values.element : field.element),
qualifier: (values.qualifier ? values.qualifier : field.qualifier),
scopeNote: (values.scopeNote ? values.scopeNote : field.scopeNote)
@@ -177,6 +176,7 @@ export class MetadataFieldFormComponent implements OnInit, OnDestroy {
});
}
this.clearFields();
this.registryService.cancelEditMetadataField();
}
);
}

View File

@@ -1,36 +1,37 @@
<div class="container">
<div class="metadata-schema row">
<div class="col-12">
<div class="col-12" *ngVar="(metadataSchema$ | async) as schema">
<h2 id="header" class="border-bottom pb-2">{{'admin.registries.schema.head' | translate}}: "{{(metadataSchema | async)?.payload?.prefix}}"</h2>
<h2 id="header" class="border-bottom pb-2">{{'admin.registries.schema.head' | translate}}: "{{schema?.prefix}}"</h2>
<p id="description" class="pb-2">{{'admin.registries.schema.description' | translate:namespace }}</p>
<p id="description" class="pb-2">{{'admin.registries.schema.description' | translate:{ namespace: schema?.namespace } }}</p>
<ds-metadata-field-form
[metadataSchema]="(metadataSchema | async)?.payload"
[metadataSchema]="schema"
(submitForm)="forceUpdateFields()"></ds-metadata-field-form>
<h3>{{'admin.registries.schema.fields.head' | translate}}</h3>
<ds-pagination
*ngIf="(metadataFields | async)?.payload?.totalElements > 0"
[paginationOptions]="config"
[pageInfoState]="(metadataFields | async)?.payload"
[collectionSize]="(metadataFields | async)?.payload?.totalElements"
[hideGear]="false"
[hidePagerWhenSinglePage]="true"
(pageChange)="onPageChange($event)">
<div class="table-responsive">
<table id="metadata-fields" class="table table-striped table-hover">
<thead>
<ng-container *ngVar="(metadataFields$ | async)?.payload as fields">
<ds-pagination
*ngIf="fields?.totalElements > 0"
[paginationOptions]="config"
[pageInfoState]="fields"
[collectionSize]="fields?.totalElements"
[hideGear]="false"
[hidePagerWhenSinglePage]="true"
(pageChange)="onPageChange($event)">
<div class="table-responsive">
<table id="metadata-fields" class="table table-striped table-hover">
<thead>
<tr>
<th></th>
<th scope="col">{{'admin.registries.schema.fields.table.field' | translate}}</th>
<th scope="col">{{'admin.registries.schema.fields.table.scopenote' | translate}}</th>
</tr>
</thead>
<tbody>
<tr *ngFor="let field of (metadataFields | async)?.payload?.page"
</thead>
<tbody>
<tr *ngFor="let field of fields?.page"
[ngClass]="{'table-primary' : isActive(field) | async}">
<td>
<label>
@@ -39,22 +40,23 @@
(change)="selectMetadataField(field, $event)">
</label>
</td>
<td class="selectable-row" (click)="editField(field)">{{(metadataSchema | async)?.payload?.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>
</tr>
</tbody>
</table>
</tbody>
</table>
</div>
</ds-pagination>
<div *ngIf="fields?.totalElements == 0" class="alert alert-info w-100 mb-2" role="alert">
{{'admin.registries.schema.fields.no-items' | translate}}
</div>
</ds-pagination>
<div *ngIf="(metadataFields | async)?.payload?.totalElements == 0" class="alert alert-info w-100 mb-2" role="alert">
{{'admin.registries.schema.fields.no-items' | translate}}
</div>
<div>
<button [routerLink]="['/admin/registries/metadata']" class="btn btn-primary">{{'admin.registries.schema.return' | translate}}</button>
<button *ngIf="(metadataFields | async)?.payload?.page?.length > 0" type="submit" class="btn btn-danger float-right" (click)="deleteFields()">{{'admin.registries.schema.fields.table.delete' | translate}}</button>
</div>
<div>
<button [routerLink]="['/admin/registries/metadata']" class="btn btn-primary">{{'admin.registries.schema.return' | translate}}</button>
<button *ngIf="fields?.page?.length > 0" type="submit" class="btn btn-danger float-right" (click)="deleteFields()">{{'admin.registries.schema.fields.table.delete' | translate}}</button>
</div>
</ng-container>
</div>
</div>

View File

@@ -10,18 +10,19 @@ import { RegistryService } from '../../../core/registry/registry.service';
import { NgbModule } from '@ng-bootstrap/ng-bootstrap';
import { EnumKeysPipe } from '../../../shared/utils/enum-keys-pipe';
import { PaginationComponent } from '../../../shared/pagination/pagination.component';
import { HostWindowServiceStub } from '../../../shared/testing/host-window-service-stub';
import { HostWindowServiceStub } from '../../../shared/testing/host-window-service.stub';
import { HostWindowService } from '../../../shared/host-window.service';
import { RouterStub } from '../../../shared/testing/router-stub';
import { RouterStub } from '../../../shared/testing/router.stub';
import { RouterTestingModule } from '@angular/router/testing';
import { ActivatedRouteStub } from '../../../shared/testing/active-router-stub';
import { ActivatedRouteStub } from '../../../shared/testing/active-router.stub';
import { NO_ERRORS_SCHEMA } from '@angular/core';
import { NotificationsService } from '../../../shared/notifications/notifications.service';
import { NotificationsServiceStub } from '../../../shared/testing/notifications-service-stub';
import { NotificationsServiceStub } from '../../../shared/testing/notifications-service.stub';
import { RestResponse } from '../../../core/cache/response.models';
import { MetadataSchema } from '../../../core/metadata/metadata-schema.model';
import { createSuccessfulRemoteDataObject$ } from '../../../shared/testing/utils';
import { MetadataField } from '../../../core/metadata/metadata-field.model';
import { createSuccessfulRemoteDataObject$ } from '../../../shared/remote-data.utils';
import { VarDirective } from '../../../shared/utils/var.directive';
describe('MetadataSchemaComponent', () => {
let comp: MetadataSchemaComponent;
@@ -60,7 +61,7 @@ describe('MetadataSchemaComponent', () => {
element: 'contributor',
qualifier: 'advisor',
scopeNote: null,
schema: mockSchemasList[0]
schema: createSuccessfulRemoteDataObject$(mockSchemasList[0])
},
{
id: 2,
@@ -72,7 +73,7 @@ describe('MetadataSchemaComponent', () => {
element: 'contributor',
qualifier: 'author',
scopeNote: null,
schema: mockSchemasList[0]
schema: createSuccessfulRemoteDataObject$(mockSchemasList[0])
},
{
id: 3,
@@ -84,7 +85,7 @@ describe('MetadataSchemaComponent', () => {
element: 'contributor',
qualifier: 'editor',
scopeNote: 'test scope note',
schema: mockSchemasList[1]
schema: createSuccessfulRemoteDataObject$(mockSchemasList[1])
},
{
id: 4,
@@ -96,15 +97,15 @@ describe('MetadataSchemaComponent', () => {
element: 'contributor',
qualifier: 'illustrator',
scopeNote: null,
schema: mockSchemasList[1]
schema: createSuccessfulRemoteDataObject$(mockSchemasList[1])
}
];
const mockSchemas = createSuccessfulRemoteDataObject$(new PaginatedList(null, mockSchemasList));
/* tslint:disable:no-empty */
const registryServiceStub = {
getMetadataSchemas: () => mockSchemas,
getMetadataFieldsBySchema: (schema: MetadataSchema) => createSuccessfulRemoteDataObject$(new PaginatedList(null, mockFieldsList.filter((value) => value.schema === schema))),
getMetadataSchemaByName: (schemaName: string) => createSuccessfulRemoteDataObject$(mockSchemasList.filter((value) => value.prefix === schemaName)[0]),
getMetadataFieldsBySchema: (schema: MetadataSchema) => createSuccessfulRemoteDataObject$(new PaginatedList(null, mockFieldsList.filter((value) => value.id === 3 || value.id === 4))),
getMetadataSchemaByPrefix: (schemaName: string) => createSuccessfulRemoteDataObject$(mockSchemasList.filter((value) => value.prefix === schemaName)[0]),
getActiveMetadataField: () => observableOf(undefined),
getSelectedMetadataFields: () => observableOf([]),
editMetadataField: (schema) => {},
@@ -124,7 +125,7 @@ describe('MetadataSchemaComponent', () => {
beforeEach(async(() => {
TestBed.configureTestingModule({
imports: [CommonModule, RouterTestingModule.withRoutes([]), TranslateModule.forRoot(), NgbModule],
declarations: [MetadataSchemaComponent, PaginationComponent, EnumKeysPipe],
declarations: [MetadataSchemaComponent, PaginationComponent, EnumKeysPipe, VarDirective],
providers: [
{ provide: RegistryService, useValue: registryServiceStub },
{ provide: ActivatedRoute, useValue: activatedRouteStub },

View File

@@ -5,7 +5,7 @@ import { Observable, combineLatest as observableCombineLatest } from 'rxjs';
import { RemoteData } from '../../../core/data/remote-data';
import { PaginatedList } from '../../../core/data/paginated-list';
import { PaginationComponentOptions } from '../../../shared/pagination/pagination-component-options.model';
import { map, take } from 'rxjs/operators';
import { map, switchMap, take } from 'rxjs/operators';
import { hasValue } from '../../../shared/empty.util';
import { RestResponse } from '../../../core/cache/response.models';
import { zip } from 'rxjs/internal/observable/zip';
@@ -13,6 +13,11 @@ import { NotificationsService } from '../../../shared/notifications/notification
import { TranslateService } from '@ngx-translate/core';
import { MetadataField } from '../../../core/metadata/metadata-field.model';
import { MetadataSchema } from '../../../core/metadata/metadata-schema.model';
import { getFirstSucceededRemoteDataPayload } from '../../../core/shared/operators';
import { toFindListOptions } from '../../../shared/pagination/pagination.utils';
import { BehaviorSubject } from 'rxjs/internal/BehaviorSubject';
import { combineLatest } from 'rxjs/internal/observable/combineLatest';
import { followLink } from '../../../shared/utils/follow-link-config.model';
@Component({
selector: 'ds-metadata-schema',
@@ -24,21 +29,15 @@ import { MetadataSchema } from '../../../core/metadata/metadata-schema.model';
* The admin can create, edit or delete metadata fields here.
*/
export class MetadataSchemaComponent implements OnInit {
/**
* The namespace of the metadata schema
*/
namespace;
/**
* The metadata schema
*/
metadataSchema: Observable<RemoteData<MetadataSchema>>;
metadataSchema$: Observable<MetadataSchema>;
/**
* A list of all the fields attached to this metadata schema
*/
metadataFields: Observable<RemoteData<PaginatedList<MetadataField>>>;
metadataFields$: Observable<RemoteData<PaginatedList<MetadataField>>>;
/**
* Pagination config used to display the list of metadata fields
@@ -49,6 +48,11 @@ export class MetadataSchemaComponent implements OnInit {
pageSizeOptions: [25, 50, 100, 200]
});
/**
* Whether or not the list of MetadataFields needs an update
*/
needsUpdate$: BehaviorSubject<boolean> = new BehaviorSubject<boolean>(true);
constructor(private registryService: RegistryService,
private route: ActivatedRoute,
private notificationsService: NotificationsService,
@@ -68,7 +72,7 @@ export class MetadataSchemaComponent implements OnInit {
* @param params
*/
initialize(params) {
this.metadataSchema = this.registryService.getMetadataSchemaByName(params.schemaName);
this.metadataSchema$ = this.registryService.getMetadataSchemaByPrefix(params.schemaName).pipe(getFirstSucceededRemoteDataPayload());
this.updateFields();
}
@@ -78,18 +82,20 @@ export class MetadataSchemaComponent implements OnInit {
*/
onPageChange(event) {
this.config.currentPage = event;
this.updateFields();
this.forceUpdateFields();
}
/**
* Update the list of fields by fetching it from the rest api or cache
*/
private updateFields() {
this.metadataSchema.subscribe((schemaData) => {
const schema = schemaData.payload;
this.metadataFields = this.registryService.getMetadataFieldsBySchema(schema, this.config);
this.namespace = {namespace: schemaData.payload.namespace};
});
this.metadataFields$ = combineLatest(this.metadataSchema$, this.needsUpdate$).pipe(
switchMap(([schema, update]: [MetadataSchema, boolean]) => {
if (update) {
return this.registryService.getMetadataFieldsBySchema(schema, toFindListOptions(this.config), followLink('schema'));
}
})
);
}
/**
@@ -97,8 +103,7 @@ export class MetadataSchemaComponent implements OnInit {
* a new REST call
*/
public forceUpdateFields() {
this.registryService.clearMetadataFieldRequests().subscribe();
this.updateFields();
this.needsUpdate$.next(true);
}
/**
@@ -157,6 +162,7 @@ export class MetadataSchemaComponent implements OnInit {
* Delete all the selected metadata fields
*/
deleteFields() {
this.registryService.clearMetadataFieldRequests().subscribe();
this.registryService.getSelectedMetadataFields().pipe(take(1)).subscribe(
(fields) => {
const tasks$ = [];

View File

@@ -0,0 +1,13 @@
import { URLCombiner } from '../core/url-combiner/url-combiner';
import { getAdminModuleRoute } from '../app-routing-paths';
export const REGISTRIES_MODULE_PATH = 'registries';
export const ACCESS_CONTROL_MODULE_PATH = 'access-control';
export function getRegistriesModuleRoute() {
return new URLCombiner(getAdminModuleRoute(), REGISTRIES_MODULE_PATH).toString();
}
export function getAccessControlModuleRoute() {
return new URLCombiner(getAdminModuleRoute(), ACCESS_CONTROL_MODULE_PATH).toString();
}

View File

@@ -1,20 +1,12 @@
import { NgModule } from '@angular/core';
import { RouterModule } from '@angular/router';
import { getAdminModulePath } from '../app-routing.module';
import { MetadataImportPageComponent } from './admin-import-metadata-page/metadata-import-page.component';
import { AdminSearchPageComponent } from './admin-search-page/admin-search-page.component';
import { I18nBreadcrumbResolver } from '../core/breadcrumbs/i18n-breadcrumb.resolver';
import { URLCombiner } from '../core/url-combiner/url-combiner';
const REGISTRIES_MODULE_PATH = 'registries';
const ACCESS_CONTROL_MODULE_PATH = 'access-control';
export function getRegistriesModulePath() {
return new URLCombiner(getAdminModulePath(), REGISTRIES_MODULE_PATH).toString();
}
export function getAccessControlModulePath() {
return new URLCombiner(getAdminModulePath(), ACCESS_CONTROL_MODULE_PATH).toString();
}
import { AdminWorkflowPageComponent } from './admin-workflow-page/admin-workflow-page.component';
import { I18nBreadcrumbsService } from '../core/breadcrumbs/i18n-breadcrumbs.service';
import { AdminCurationTasksComponent } from './admin-curation-tasks/admin-curation-tasks.component';
import { ACCESS_CONTROL_MODULE_PATH, REGISTRIES_MODULE_PATH } from './admin-routing-paths';
@NgModule({
imports: [
@@ -32,8 +24,30 @@ export function getAccessControlModulePath() {
resolve: { breadcrumb: I18nBreadcrumbResolver },
component: AdminSearchPageComponent,
data: { title: 'admin.search.title', breadcrumbKey: 'admin.search' }
}
]),
},
{
path: 'workflow',
resolve: { breadcrumb: I18nBreadcrumbResolver },
component: AdminWorkflowPageComponent,
data: { title: 'admin.workflow.title', breadcrumbKey: 'admin.workflow' }
},
{
path: 'curation-tasks',
resolve: { breadcrumb: I18nBreadcrumbResolver },
component: AdminCurationTasksComponent,
data: { title: 'admin.curation-tasks.title', breadcrumbKey: 'admin.curation-tasks' }
},
{
path: 'metadata-import',
resolve: { breadcrumb: I18nBreadcrumbResolver },
component: MetadataImportPageComponent,
data: { title: 'admin.metadata-import.title', breadcrumbKey: 'admin.metadata-import' }
},
])
],
providers: [
I18nBreadcrumbResolver,
I18nBreadcrumbsService
]
})
export class AdminRoutingModule {

View File

@@ -12,7 +12,7 @@ import { CollectionSearchResult } from '../../../../../shared/object-collection/
import { Collection } from '../../../../../core/shared/collection.model';
import { By } from '@angular/platform-browser';
import { RouterTestingModule } from '@angular/router/testing';
import { getCollectionEditPath } from '../../../../../+collection-page/collection-page-routing.module';
import { getCollectionEditRoute } from '../../../../../+collection-page/collection-page-routing-paths';
describe('CollectionAdminSearchResultGridElementComponent', () => {
let component: CollectionAdminSearchResultGridElementComponent;
@@ -61,6 +61,6 @@ describe('CollectionAdminSearchResultGridElementComponent', () => {
it('should render an edit button with the correct link', () => {
const a = fixture.debugElement.query(By.css('a.edit-link'));
const link = a.nativeElement.href;
expect(link).toContain(getCollectionEditPath(id));
expect(link).toContain(getCollectionEditRoute(id));
})
});

View File

@@ -4,8 +4,8 @@ import { listableObjectComponent } from '../../../../../shared/object-collection
import { Context } from '../../../../../core/shared/context.model';
import { CollectionSearchResult } from '../../../../../shared/object-collection/shared/collection-search-result.model';
import { Collection } from '../../../../../core/shared/collection.model';
import { getCollectionEditPath } from '../../../../../+collection-page/collection-page-routing.module';
import { SearchResultGridElementComponent } from '../../../../../shared/object-grid/search-result-grid-element/search-result-grid-element.component';
import { getCollectionEditRoute } from '../../../../../+collection-page/collection-page-routing-paths';
@listableObjectComponent(CollectionSearchResult, ViewMode.GridElement, Context.AdminSearch)
@Component({
@@ -21,6 +21,6 @@ export class CollectionAdminSearchResultGridElementComponent extends SearchResul
ngOnInit() {
super.ngOnInit();
this.editPath = getCollectionEditPath(this.dso.uuid);
this.editPath = getCollectionEditRoute(this.dso.uuid);
}
}

View File

@@ -13,9 +13,9 @@ import { By } from '@angular/platform-browser';
import { RouterTestingModule } from '@angular/router/testing';
import { CommunityAdminSearchResultGridElementComponent } from './community-admin-search-result-grid-element.component';
import { CommunitySearchResult } from '../../../../../shared/object-collection/shared/community-search-result.model';
import { getCommunityEditPath } from '../../../../../+community-page/community-page-routing.module';
import { Community } from '../../../../../core/shared/community.model';
import { CommunityAdminSearchResultListElementComponent } from '../../admin-search-result-list-element/community-search-result/community-admin-search-result-list-element.component';
import { getCommunityEditRoute } from '../../../../../+community-page/community-page-routing-paths';
describe('CommunityAdminSearchResultGridElementComponent', () => {
let component: CommunityAdminSearchResultGridElementComponent;
@@ -65,6 +65,6 @@ describe('CommunityAdminSearchResultGridElementComponent', () => {
it('should render an edit button with the correct link', () => {
const a = fixture.debugElement.query(By.css('a.edit-link'));
const link = a.nativeElement.href;
expect(link).toContain(getCommunityEditPath(id));
expect(link).toContain(getCommunityEditRoute(id));
})
});

View File

@@ -4,8 +4,8 @@ import { listableObjectComponent } from '../../../../../shared/object-collection
import { Context } from '../../../../../core/shared/context.model';
import { CommunitySearchResult } from '../../../../../shared/object-collection/shared/community-search-result.model';
import { Community } from '../../../../../core/shared/community.model';
import { getCommunityEditPath } from '../../../../../+community-page/community-page-routing.module';
import { SearchResultGridElementComponent } from '../../../../../shared/object-grid/search-result-grid-element/search-result-grid-element.component';
import { getCommunityEditRoute } from '../../../../../+community-page/community-page-routing-paths';
@listableObjectComponent(CommunitySearchResult, ViewMode.GridElement, Context.AdminSearch)
@Component({
@@ -21,6 +21,6 @@ export class CommunityAdminSearchResultGridElementComponent extends SearchResult
ngOnInit() {
super.ngOnInit();
this.editPath = getCommunityEditPath(this.dso.uuid);
this.editPath = getCommunityEditRoute(this.dso.uuid);
}
}

View File

@@ -10,7 +10,6 @@ import { Bitstream } from '../../../../../core/shared/bitstream.model';
import { Item } from '../../../../../core/shared/item.model';
import { mockTruncatableService } from '../../../../../shared/mocks/mock-trucatable.service';
import { SharedModule } from '../../../../../shared/shared.module';
import { createSuccessfulRemoteDataObject$ } from '../../../../../shared/testing/utils';
import { TruncatableService } from '../../../../../shared/truncatable/truncatable.service';
import { CollectionElementLinkType } from '../../../../../shared/object-collection/collection-element-link.type';
import { ViewMode } from '../../../../../core/shared/view-mode.model';
@@ -18,6 +17,7 @@ import { By } from '@angular/platform-browser';
import { RouterTestingModule } from '@angular/router/testing';
import { ItemSearchResult } from '../../../../../shared/object-collection/shared/item-search-result.model';
import { ItemAdminSearchResultGridElementComponent } from './item-admin-search-result-grid-element.component';
import { createSuccessfulRemoteDataObject$ } from '../../../../../shared/remote-data.utils';
describe('ItemAdminSearchResultGridElementComponent', () => {
let component: ItemAdminSearchResultGridElementComponent;

View File

@@ -4,16 +4,6 @@ import { ViewMode } from '../../../../../core/shared/view-mode.model';
import { getListableObjectComponent, listableObjectComponent } from '../../../../../shared/object-collection/shared/listable-object/listable-object.decorator';
import { Context } from '../../../../../core/shared/context.model';
import { ItemSearchResult } from '../../../../../shared/object-collection/shared/item-search-result.model';
import { getItemEditPath } from '../../../../../+item-page/item-page-routing.module';
import { URLCombiner } from '../../../../../core/url-combiner/url-combiner';
import {
ITEM_EDIT_DELETE_PATH,
ITEM_EDIT_MOVE_PATH,
ITEM_EDIT_PRIVATE_PATH,
ITEM_EDIT_PUBLIC_PATH,
ITEM_EDIT_REINSTATE_PATH,
ITEM_EDIT_WITHDRAW_PATH
} from '../../../../../+item-page/edit-item-page/edit-item-page.routing.module';
import { SearchResultGridElementComponent } from '../../../../../shared/object-grid/search-result-grid-element/search-result-grid-element.component';
import { TruncatableService } from '../../../../../shared/truncatable/truncatable.service';
import { BitstreamDataService } from '../../../../../core/data/bitstream-data.service';

View File

@@ -10,7 +10,7 @@ import { CollectionSearchResult } from '../../../../../shared/object-collection/
import { Collection } from '../../../../../core/shared/collection.model';
import { By } from '@angular/platform-browser';
import { RouterTestingModule } from '@angular/router/testing';
import { getCollectionEditPath } from '../../../../../+collection-page/collection-page-routing.module';
import { getCollectionEditRoute } from '../../../../../+collection-page/collection-page-routing-paths';
describe('CollectionAdminSearchResultListElementComponent', () => {
let component: CollectionAdminSearchResultListElementComponent;
@@ -55,6 +55,6 @@ describe('CollectionAdminSearchResultListElementComponent', () => {
it('should render an edit button with the correct link', () => {
const a = fixture.debugElement.query(By.css('a'));
const link = a.nativeElement.href;
expect(link).toContain(getCollectionEditPath(id));
expect(link).toContain(getCollectionEditRoute(id));
})
});

View File

@@ -5,7 +5,7 @@ import { Context } from '../../../../../core/shared/context.model';
import { SearchResultListElementComponent } from '../../../../../shared/object-list/search-result-list-element/search-result-list-element.component';
import { CollectionSearchResult } from '../../../../../shared/object-collection/shared/collection-search-result.model';
import { Collection } from '../../../../../core/shared/collection.model';
import { getCollectionEditPath } from '../../../../../+collection-page/collection-page-routing.module';
import { getCollectionEditRoute } from '../../../../../+collection-page/collection-page-routing-paths';
@listableObjectComponent(CollectionSearchResult, ViewMode.ListElement, Context.AdminSearch)
@Component({
@@ -21,6 +21,6 @@ export class CollectionAdminSearchResultListElementComponent extends SearchResul
ngOnInit() {
super.ngOnInit();
this.editPath = getCollectionEditPath(this.dso.uuid);
this.editPath = getCollectionEditRoute(this.dso.uuid);
}
}

View File

@@ -9,8 +9,8 @@ import { By } from '@angular/platform-browser';
import { RouterTestingModule } from '@angular/router/testing';
import { CommunityAdminSearchResultListElementComponent } from './community-admin-search-result-list-element.component';
import { CommunitySearchResult } from '../../../../../shared/object-collection/shared/community-search-result.model';
import { getCommunityEditPath } from '../../../../../+community-page/community-page-routing.module';
import { Community } from '../../../../../core/shared/community.model';
import { getCommunityEditRoute } from '../../../../../+community-page/community-page-routing-paths';
describe('CommunityAdminSearchResultListElementComponent', () => {
let component: CommunityAdminSearchResultListElementComponent;
@@ -55,6 +55,6 @@ describe('CommunityAdminSearchResultListElementComponent', () => {
it('should render an edit button with the correct link', () => {
const a = fixture.debugElement.query(By.css('a'));
const link = a.nativeElement.href;
expect(link).toContain(getCommunityEditPath(id));
expect(link).toContain(getCommunityEditRoute(id));
})
});

View File

@@ -5,7 +5,7 @@ import { Context } from '../../../../../core/shared/context.model';
import { SearchResultListElementComponent } from '../../../../../shared/object-list/search-result-list-element/search-result-list-element.component';
import { CommunitySearchResult } from '../../../../../shared/object-collection/shared/community-search-result.model';
import { Community } from '../../../../../core/shared/community.model';
import { getCommunityEditPath } from '../../../../../+community-page/community-page-routing.module';
import { getCommunityEditRoute } from '../../../../../+community-page/community-page-routing-paths';
@listableObjectComponent(CommunitySearchResult, ViewMode.ListElement, Context.AdminSearch)
@Component({
@@ -21,6 +21,6 @@ export class CommunityAdminSearchResultListElementComponent extends SearchResult
ngOnInit() {
super.ngOnInit();
this.editPath = getCommunityEditPath(this.dso.uuid);
this.editPath = getCommunityEditRoute(this.dso.uuid);
}
}

View File

@@ -1,27 +1,27 @@
<a [ngClass]="{'btn-sm': small}" class="btn btn-light my-1 edit-link" [routerLink]="[getEditPath()]" [title]="'admin.search.item.edit' | translate">
<a [ngClass]="{'btn-sm': small}" class="btn btn-light my-1 edit-link" [routerLink]="[getEditRoute()]" [title]="'admin.search.item.edit' | translate">
<i class="fa fa-edit"></i><span *ngIf="!small" class="d-none d-sm-inline"> {{"admin.search.item.edit" | translate}}</span>
</a>
<a [ngClass]="{'btn-sm': small}" *ngIf="item && !item.isWithdrawn" class="btn btn-light my-1 withdraw-link" [routerLink]="[getWithdrawPath()]" [title]="'admin.search.item.withdraw' | translate">
<a [ngClass]="{'btn-sm': small}" *ngIf="item && !item.isWithdrawn" class="btn btn-light my-1 withdraw-link" [routerLink]="[getWithdrawRoute()]" [title]="'admin.search.item.withdraw' | translate">
<i class="fa fa-ban"></i><span *ngIf="!small" class="d-none d-sm-inline"> {{"admin.search.item.withdraw" | translate}}</span>
</a>
<a [ngClass]="{'btn-sm': small}" *ngIf="item && item.isWithdrawn" class="btn btn-light my-1 reinstate-link" [routerLink]="[getReinstatePath()]" [title]="'admin.search.item.reinstate' | translate">
<a [ngClass]="{'btn-sm': small}" *ngIf="item && item.isWithdrawn" class="btn btn-light my-1 reinstate-link" [routerLink]="[getReinstateRoute()]" [title]="'admin.search.item.reinstate' | translate">
<i class="fa fa-undo"></i><span *ngIf="!small" class="d-none d-sm-inline"> {{"admin.search.item.reinstate" | translate}}</span>
</a>
<a [ngClass]="{'btn-sm': small}" *ngIf="item && item.isDiscoverable" class="btn btn-light my-1 private-link" [routerLink]="[getPrivatePath()]" [title]="'admin.search.item.make-private' | translate">
<a [ngClass]="{'btn-sm': small}" *ngIf="item && item.isDiscoverable" class="btn btn-light my-1 private-link" [routerLink]="[getPrivateRoute()]" [title]="'admin.search.item.make-private' | translate">
<i class="fa fa-eye-slash"></i><span *ngIf="!small" class="d-none d-sm-inline"> {{"admin.search.item.make-private" | translate}}</span>
</a>
<a [ngClass]="{'btn-sm': small}" *ngIf="item && !item.isDiscoverable" class="btn btn-light my-1 public-link" [routerLink]="[getPublicPath()]" [title]="'admin.search.item.make-public' | translate">
<a [ngClass]="{'btn-sm': small}" *ngIf="item && !item.isDiscoverable" class="btn btn-light my-1 public-link" [routerLink]="[getPublicRoute()]" [title]="'admin.search.item.make-public' | translate">
<i class="fa fa-eye"></i><span *ngIf="!small" class="d-none d-sm-inline"> {{"admin.search.item.make-public" | translate}}</span>
</a>
<a [ngClass]="{'btn-sm': small}" class="btn btn-light my-1 delete-link" [routerLink]="[getDeletePath()]" [title]="'admin.search.item.delete' | translate">
<a [ngClass]="{'btn-sm': small}" class="btn btn-light my-1 delete-link" [routerLink]="[getDeleteRoute()]" [title]="'admin.search.item.delete' | translate">
<i class="fa fa-trash"></i><span *ngIf="!small" class="d-none d-sm-inline"> {{"admin.search.item.delete" | translate}}</span>
</a>
<a [ngClass]="{'btn-sm': small}" class="btn btn-light my-1 move-link" [routerLink]="[getMovePath()]" [title]="'admin.search.item.move' | translate">
<a [ngClass]="{'btn-sm': small}" class="btn btn-light my-1 move-link" [routerLink]="[getMoveRoute()]" [title]="'admin.search.item.move' | translate">
<i class="fa fa-arrow-circle-right"></i><span *ngIf="!small" class="d-none d-sm-inline"> {{"admin.search.item.move" | translate}}</span>
</a>

View File

@@ -6,16 +6,16 @@ import { By } from '@angular/platform-browser';
import { RouterTestingModule } from '@angular/router/testing';
import { ItemAdminSearchResultActionsComponent } from './item-admin-search-result-actions.component';
import { Item } from '../../../core/shared/item.model';
import { URLCombiner } from '../../../core/url-combiner/url-combiner';
import { getItemEditRoute } from '../../../+item-page/item-page-routing-paths';
import {
ITEM_EDIT_DELETE_PATH,
ITEM_EDIT_MOVE_PATH,
ITEM_EDIT_PRIVATE_PATH,
ITEM_EDIT_DELETE_PATH,
ITEM_EDIT_PUBLIC_PATH,
ITEM_EDIT_PRIVATE_PATH,
ITEM_EDIT_REINSTATE_PATH,
ITEM_EDIT_WITHDRAW_PATH
} from '../../../+item-page/edit-item-page/edit-item-page.routing.module';
import { getItemEditPath } from '../../../+item-page/item-page-routing.module';
import { URLCombiner } from '../../../core/url-combiner/url-combiner';
} from '../../../+item-page/edit-item-page/edit-item-page.routing-paths';
describe('ItemAdminSearchResultActionsComponent', () => {
let component: ItemAdminSearchResultActionsComponent;
@@ -55,19 +55,19 @@ describe('ItemAdminSearchResultActionsComponent', () => {
it('should render an edit button with the correct link', () => {
const button = fixture.debugElement.query(By.css('a.edit-link'));
const link = button.nativeElement.href;
expect(link).toContain(getItemEditPath(id));
expect(link).toContain(getItemEditRoute(id));
});
it('should render a delete button with the correct link', () => {
const button = fixture.debugElement.query(By.css('a.delete-link'));
const link = button.nativeElement.href;
expect(link).toContain(new URLCombiner(getItemEditPath(id), ITEM_EDIT_DELETE_PATH).toString());
expect(link).toContain(new URLCombiner(getItemEditRoute(id), ITEM_EDIT_DELETE_PATH).toString());
});
it('should render a move button with the correct link', () => {
const a = fixture.debugElement.query(By.css('a.move-link'));
const link = a.nativeElement.href;
expect(link).toContain(new URLCombiner(getItemEditPath(id), ITEM_EDIT_MOVE_PATH).toString());
expect(link).toContain(new URLCombiner(getItemEditRoute(id), ITEM_EDIT_MOVE_PATH).toString());
});
describe('when the item is not withdrawn', () => {
@@ -79,7 +79,7 @@ describe('ItemAdminSearchResultActionsComponent', () => {
it('should render a withdraw button with the correct link', () => {
const a = fixture.debugElement.query(By.css('a.withdraw-link'));
const link = a.nativeElement.href;
expect(link).toContain(new URLCombiner(getItemEditPath(id), ITEM_EDIT_WITHDRAW_PATH).toString());
expect(link).toContain(new URLCombiner(getItemEditRoute(id), ITEM_EDIT_WITHDRAW_PATH).toString());
});
it('should not render a reinstate button with the correct link', () => {
@@ -102,7 +102,7 @@ describe('ItemAdminSearchResultActionsComponent', () => {
it('should render a reinstate button with the correct link', () => {
const a = fixture.debugElement.query(By.css('a.reinstate-link'));
const link = a.nativeElement.href;
expect(link).toContain(new URLCombiner(getItemEditPath(id), ITEM_EDIT_REINSTATE_PATH).toString());
expect(link).toContain(new URLCombiner(getItemEditRoute(id), ITEM_EDIT_REINSTATE_PATH).toString());
});
});
@@ -115,7 +115,7 @@ describe('ItemAdminSearchResultActionsComponent', () => {
it('should render a make private button with the correct link', () => {
const a = fixture.debugElement.query(By.css('a.private-link'));
const link = a.nativeElement.href;
expect(link).toContain(new URLCombiner(getItemEditPath(id), ITEM_EDIT_PRIVATE_PATH).toString());
expect(link).toContain(new URLCombiner(getItemEditRoute(id), ITEM_EDIT_PRIVATE_PATH).toString());
});
it('should not render a make public button with the correct link', () => {
@@ -138,7 +138,7 @@ describe('ItemAdminSearchResultActionsComponent', () => {
it('should render a make private button with the correct link', () => {
const a = fixture.debugElement.query(By.css('a.public-link'));
const link = a.nativeElement.href;
expect(link).toContain(new URLCombiner(getItemEditPath(id), ITEM_EDIT_PUBLIC_PATH).toString());
expect(link).toContain(new URLCombiner(getItemEditRoute(id), ITEM_EDIT_PUBLIC_PATH).toString());
});
})
});

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