Compare commits

...

806 Commits

Author SHA1 Message Date
Tim Donohue
3e6adbba93 Update version tag for release 2024-06-21 14:53:28 -05:00
Tim Donohue
db08e489d9 Merge tag 'dspace-7.6.1' 2024-06-20 14:28:55 -05:00
Tim Donohue
4d13e284cb Merge pull request #3138 from 4Science/task/main/DURACOM-282
Fix error which prevent submitter to deposit a new item
2024-06-20 11:23:25 -05:00
Tim Donohue
fb70b58b9e Merge pull request #3132 from tdonohue/update_latest_ang_17
Bump Angular to 17.3.11 and Angular-CLI to 17.3.8
2024-06-20 07:02:21 -05:00
Giuseppe Digilio
7f8e0a1d1c [DURACOM-282] fix issue with submission edit page when providing a not existing workspaceitem 2024-06-19 15:53:47 +02:00
Giuseppe Digilio
4069cf8168 [DURACOM-282] fix error when discarding submission with no uploaded files 2024-06-19 13:32:58 +02:00
Giuseppe Digilio
eb7fb704bd [DURACOM-282] fix issue with removing duplicated json patch operations, which in some case changed the order in the queue 2024-06-19 13:11:40 +02:00
Tim Donohue
ca61647a7a Merge pull request #3029 from alanorth/i18n-crossref-case
src/assets/i18n: CrossRef → Crossref
2024-06-18 15:36:30 -05:00
Tim Donohue
014377b03b Merge pull request #3077 from t-rodrigues/feat/i18n
Update pt-BR translation for DSpace 8.0 release
2024-06-18 15:28:44 -05:00
Tim Donohue
feeeb8569f Merge pull request #3081 from arvoConsultores/i18n-spanish-update
Spanish translation updated
2024-06-18 15:20:15 -05:00
Tim Donohue
f07c0d492c Merge pull request #3100 from tdonohue/update_openaire_i18n
Minor updates to i18n text for OpenAIRE external sources.
2024-06-18 15:06:29 -05:00
Tim Donohue
55eff73c3f Merge branch 'main-fix-suggestion-target-error' of https://github.com/4Science/dspace-angular into update_latest_ang_17 2024-06-18 13:46:32 -05:00
Thiago Rodrigues
d982d0df6b feat: update pt-BR translation 2024-06-18 15:10:25 -03:00
Thiago Rodrigues
e5cff2c76c Merge branch 'DSpace:main' into feat/i18n 2024-06-18 14:52:34 -03:00
Thiago Rodrigues
20ef8656df Merge branch 'main' into feat/i18n 2024-06-18 14:50:57 -03:00
Giuseppe Digilio
472fa1c473 Fix issue with REFRESH_USER_SUGGESTIONS action 2024-06-18 19:27:54 +02:00
Tim Donohue
cd3c4f2baa Merge pull request #3127 from alexandrevryghem/w2p-113560_edit-item-add-relationships-one-by-one_contribute-main
[Port main] Remove Bitstreams on edit-item-page doesn't work
2024-06-18 12:11:52 -05:00
Tim Donohue
e1a2416a54 Bump webpack from 5.76.1 to 5.90.3 to align with version in @angular-devkit/build-angular 2024-06-18 09:30:14 -05:00
Tim Donohue
90d63024c6 Bump Angular from 17.3.4 to 17.3.11 and Angular-CLI from 17.3.0 to 17.3.8 2024-06-17 17:07:08 -05:00
Tim Donohue
605230db11 Merge pull request #3129 from DSpace/dependabot/npm_and_yarn/ws-7.5.10
Bump ws from 7.5.9 to 7.5.10
2024-06-17 15:32:08 -05:00
dependabot[bot]
45af560496 Bump ws from 7.5.9 to 7.5.10
Bumps [ws](https://github.com/websockets/ws) from 7.5.9 to 7.5.10.
- [Release notes](https://github.com/websockets/ws/releases)
- [Commits](https://github.com/websockets/ws/compare/7.5.9...7.5.10)

---
updated-dependencies:
- dependency-name: ws
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-06-17 19:56:11 +00:00
Tim Donohue
b398e146d9 Merge pull request #3125 from DSpace/dependabot/npm_and_yarn/postcss-8.4.38
Bump postcss from 6.0.23 to 8.4.38
2024-06-17 14:54:23 -05:00
Tim Donohue
4dbb7c9b46 Merge pull request #3124 from DSpace/dependabot/npm_and_yarn/express-4.19.2
Bump express from 4.18.3 to 4.19.2
2024-06-17 14:31:39 -05:00
Tim Donohue
2d8d25d8c2 Merge pull request #2915 from DSpace/dependabot/npm_and_yarn/tar-6.2.1
Bump tar from 6.2.0 to 6.2.1
2024-06-17 13:00:35 -05:00
Alexandre Vryghem
a70817559c 115046: Fixed edit item bitstream tab buttons not updating correctly & removed method calls retuning observables in edit collection's content source tab 2024-06-17 17:58:01 +02:00
Tim Donohue
aecfa53c1a Merge pull request #3123 from DSpace/dependabot/npm_and_yarn/braces-3.0.3
Bump braces from 3.0.2 to 3.0.3
2024-06-17 10:31:14 -05:00
dependabot[bot]
66991bd381 Bump postcss from 6.0.23 to 8.4.38
Bumps [postcss](https://github.com/postcss/postcss) from 6.0.23 to 8.4.38.
- [Release notes](https://github.com/postcss/postcss/releases)
- [Changelog](https://github.com/postcss/postcss/blob/main/CHANGELOG.md)
- [Commits](https://github.com/postcss/postcss/compare/6.0.23...8.4.38)

---
updated-dependencies:
- dependency-name: postcss
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-06-17 15:25:44 +00:00
dependabot[bot]
059d6df7d8 Bump express from 4.18.3 to 4.19.2
Bumps [express](https://github.com/expressjs/express) from 4.18.3 to 4.19.2.
- [Release notes](https://github.com/expressjs/express/releases)
- [Changelog](https://github.com/expressjs/express/blob/master/History.md)
- [Commits](https://github.com/expressjs/express/compare/4.18.3...4.19.2)

---
updated-dependencies:
- dependency-name: express
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-06-17 15:23:45 +00:00
dependabot[bot]
cb71a77daa Bump tar from 6.2.0 to 6.2.1
Bumps [tar](https://github.com/isaacs/node-tar) from 6.2.0 to 6.2.1.
- [Release notes](https://github.com/isaacs/node-tar/releases)
- [Changelog](https://github.com/isaacs/node-tar/blob/main/CHANGELOG.md)
- [Commits](https://github.com/isaacs/node-tar/compare/v6.2.0...v6.2.1)

---
updated-dependencies:
- dependency-name: tar
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-06-17 15:21:38 +00:00
Tim Donohue
8693bc36b5 Merge pull request #3120 from tdonohue/port_3039_to_main
[Port main] Fix - Change color Contrast in cookie settings box
2024-06-17 09:27:35 -05:00
dependabot[bot]
0f83aea4b5 Bump braces from 3.0.2 to 3.0.3
Bumps [braces](https://github.com/micromatch/braces) from 3.0.2 to 3.0.3.
- [Changelog](https://github.com/micromatch/braces/blob/master/CHANGELOG.md)
- [Commits](https://github.com/micromatch/braces/compare/3.0.2...3.0.3)

---
updated-dependencies:
- dependency-name: braces
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-06-16 09:56:04 +00:00
Victor Hugo Duran Santiago
20f31cbee7 Fix - Change color Contrast in cookie settings box 2024-06-14 15:12:42 -05:00
Tim Donohue
bf5e9b9d49 Merge pull request #3067 from Neki-IT/BrowseByAuthorSeriousIssues
Fix "Browse by Author" remaining serious accessibility issues
2024-06-14 14:54:41 -05:00
Tim Donohue
4e93255f01 Merge pull request #3099 from Neki-IT/LoadingSearchResults
Improving accessibility of the ds-loading component
2024-06-14 14:08:55 -05:00
Tim Donohue
50408111ea Merge pull request #3115 from dspace-unimr/fix/#2957-hamburger-menu-hangs-on-keyboard-use
Fixes: Site hangs when selecting items via keyboard from the hamburger menu
2024-06-14 13:56:05 -05:00
Thiago Rodrigues
2c72de148f Merge branch 'DSpace:main' into feat/i18n 2024-06-14 13:26:52 -03:00
Tim Donohue
d71964d440 Merge pull request #3113 from 4Science/task/main/DURACOM-271_coar-fixes-fixed
COAR Notify impossible to send/receive message from another DSpace
2024-06-14 08:59:53 -05:00
Giuseppe Digilio
fe09cb613b [DURACOM-271] Add proper labels for isSupplementedBy and isReferencedBy relationships 2024-06-14 13:17:30 +02:00
Thiago Rodrigues
3950f90469 Merge branch 'DSpace:main' into feat/i18n 2024-06-12 17:54:25 -03:00
Giuseppe Digilio
fb55ad400c [DURACOM-271] Fix suggestion list pagination and add support for multiple sources 2024-06-12 17:47:40 +02:00
Giuseppe Digilio
ecfe7e9fa0 [DURACOM-271] Adjust form button color following application guidelines 2024-06-12 13:30:44 +02:00
Giuseppe Digilio
57a147d71a [DURACOM-271] Remove form validation for patterns 2024-06-12 13:29:03 +02:00
Tim Donohue
f7a14a1145 Merge pull request #3106 from alexandrevryghem/w2p-113560_edit-item-add-relationships-one-by-one_contribute-main
Fixed caching & same entity type relationship with different left/rightwardtype bugs on edit item relationships
2024-06-11 14:43:02 -05:00
Giuseppe Digilio
74e1e67126 [DURACOM-271] Fix error which led to have empty dashboard when new notification is delivered 2024-06-11 18:06:40 +02:00
Giuseppe Digilio
cee07c2e4a [DURACOM-271] Fix test after renaming 2024-06-11 18:02:21 +02:00
Giuseppe Digilio
cfd3b3c79c [DURACOM-271] Add 'announce-relationship' pattern 2024-06-10 16:46:02 +02:00
Alan Orth
ae221df3a4 src/assets/i18n: CrossRef → Crossref
As part of a rebranding in 2015 Crossref started stylizing their
name as "Crossref" instead of "CrossRef".

See: https://www.crossref.org/blog/the-logo-has-landed/
2024-06-08 08:34:43 +03:00
Tim Donohue
1de8423ab7 Merge pull request #3098 from alexandrevryghem/w2p-115434_byLabel-related-entity-type_contribute-main
Fixed item edit relationships with same type name but different entities all being shown under same label
2024-06-07 15:09:32 -05:00
Tim Donohue
67a1ff49a3 Merge pull request #3092 from ahmadmostafa1976/patch-1
Update ar.json5
2024-06-07 14:53:26 -05:00
Giuseppe Digilio
dbcab6fc45 [DURACOM-271] Renamed and reorganized suggestion data services 2024-06-07 16:30:27 +02:00
Alexandre Vryghem
556e04d059 115046: Fixed same type entity relationships with same leftward/rightward type displaying twice 2024-06-07 14:55:08 +02:00
Alexandre Vryghem
4ccd459b1a 115046: Fixed issue where relationsToItems would never emit when an empty array was passed to it 2024-06-07 12:00:14 +02:00
Alexandre Vryghem
3253e0e785 115046: Fixed loading animation not resetting hen closing modal 2024-06-07 12:00:14 +02:00
Alexandre Vryghem
7996b5b60d 115046: Fixed related item not invalidating on relationship deletion & automatically invalidate the isSelected value after updating relationship on item 2024-06-07 12:00:14 +02:00
Yana De Pauw
06665dc31f 115284: Fix issue with same type relationships 2024-06-07 12:00:14 +02:00
Eike Martin Löhden
a4e9a9a4b8 Change key-listener to keydown in order to work on chrome browsers. 2024-06-06 09:42:41 +02:00
Tim Donohue
3fbc3dca6f Merge pull request #2853 from 4Science/main-optimize-metadata-represenation-rendering
Avoid metadata representation element is rendered twice when checking the browse configuration
2024-06-05 15:23:26 -05:00
Tim Donohue
2cfe7c05b9 Merge pull request #2929 from alexandrevryghem/w2p-113901_edit-item-relationships-does-not-display-tilted-relationships_contribute-main
Fixed edit item relationships tab not displaying tilted relationships
2024-06-05 14:43:17 -05:00
Tim Donohue
b02e4b18c2 Merge pull request #3074 from alexandrevryghem/fix-advanced-workflows-throwing-404_contribute-main
Fix advanced workflows throwing 404
2024-06-05 12:05:04 -05:00
Sergio Fernández Celorio
a92fa8d17d Error fixed 2024-06-05 08:56:53 +02:00
Thiago Rodrigues
3b9d4011e6 feat: resolve conflicts 2024-06-04 19:56:05 -03:00
Thiago Rodrigues
18c670606b feat: update pt-BR translation 2024-06-04 19:22:16 -03:00
Thiago Rodrigues
b550a60582 feat: update pt-BR translation 2024-06-04 19:22:16 -03:00
Tim Donohue
b752edadf6 Minor updates to i18n text for OpenAIRE. All OpenAIRE searches return publications 2024-06-04 16:34:59 -05:00
root
e96d64a622 Melhorando acessibilidade do componente ds-loading 2024-06-04 17:23:57 -03:00
Alexandre Vryghem
280795d16d Merge remote-tracking branch 'refs/remotes/upstream/main' into w2p-113901_edit-item-relationships-does-not-display-tilted-relationships_contribute-main
# Conflicts:
#	src/app/item-page/edit-item-page/item-relationships/edit-relationship-list/edit-relationship-list.component.ts
2024-06-02 22:02:19 +02:00
Alexandre Vryghem
e25f2eae55 Merge branch 'w2p-115434_byLabel-related-entity-type_contribute-7.6' into w2p-115434_byLabel-related-entity-type_contribute-main
# Conflicts:
#	src/app/item-page/edit-item-page/item-relationships/edit-relationship-list/edit-relationship-list.component.ts
2024-06-02 21:51:46 +02:00
Tim Donohue
b0a8a50c16 Merge pull request #3097 from tdonohue/port_3061_to_main
[Port main] Hide search text field when number of facet values is less than the maximum
2024-05-31 14:38:20 -05:00
Tim Donohue
bb341a3ea7 Minor fix for scenarios where page is undefined. Fixes a few specs. 2024-05-31 14:11:57 -05:00
Tim Donohue
e3595e5f34 Fix "Async pipe results should not be negated" from lint 2024-05-31 12:53:45 -05:00
Victor Hugo Duran Santiago
44480cba4a Fix - hide search text field in the filter section if the number of facet values does not exceed the maximum number of facet values shown 2024-05-31 12:31:27 -05:00
Victor Hugo Duran Santiago
906b2f5917 Fix - hide search text field in the filter section if the number of facet values does not exceed the maximum number of facet values shown 2024-05-31 12:30:30 -05:00
Tim Donohue
b9a1045e38 Merge pull request #3049 from atmire/w2p-114858_refactor_guards_as_functions-8.0
Fix: Item edit pages not hidden/redirect for anon or non-authorised users
2024-05-31 12:16:47 -05:00
Tim Donohue
ebf9469846 Merge pull request #3060 from alexandrevryghem/w2p-113560_edit-item-add-relationships-one-by-one_contribute-main
Fixed creation & deletion of relationships not working correctly & added same entity type relationship support
2024-05-31 11:49:07 -05:00
Tim Donohue
123b6b7bab Merge pull request #2761 from ybnd/fix-versioning-button
Fix caching issues for versioning
2024-05-30 16:55:17 -05:00
Alexandre Vryghem
62e07e7335 115046: Fixed issue where store operations would sometimes be performed in incorrect order 2024-05-30 17:06:10 +02:00
Alexandre Vryghem
a596af03a4 115046: Fixed incorrect name variant being saved in the store when marking relationship ready for deletion 2024-05-30 17:06:10 +02:00
Alexandre Vryghem
58bcb9b8da 115046: Fixed performance issues in virtual metadata popup 2024-05-30 17:06:10 +02:00
ahmadmostafa1976
3ab5d6dfb6 Update ar.json5 2024-05-30 13:17:44 +03:00
Tim Donohue
a5b9477cc9 Merge pull request #3079 from alexandrevryghem/w2p-115427_fixed-delete-item-page-freezing_contribute-main
Fixed delete item page freezing when having relationships
2024-05-29 15:50:41 -05:00
Tim Donohue
38147340fc Merge pull request #3080 from alexandrevryghem/w2p-115428_fixed-page-size-and-sorting-not-working-on-comcolpages
Fixed page size change and sorting not working on comcol pages
2024-05-29 15:35:32 -05:00
Tim Donohue
1c325cd40a Merge pull request #3062 from atmire/legacy-bitstream-redirect_contribute-main
Made legacy bitstream URLs redirect with 301 status code
2024-05-29 13:38:31 -05:00
Sergio Fernández Celorio
94573f4335 Fix lint errors 2024-05-29 09:38:51 +02:00
Sergio Fernández Celorio
0a957164c9 Spanish translation updated 2024-05-29 09:08:55 +02:00
Thiago Rodrigues
27ddc85c9c feat: update pt-BR translation 2024-05-27 20:53:47 -03:00
Thiago Rodrigues
d58b73af97 feat: update pt-BR translation 2024-05-27 20:37:49 -03:00
Alexandre Vryghem
4d89a11943 115428: Fixed EventEmitter being triggered multiple times because its name was the same as a standard DOM event 2024-05-27 17:22:04 +02:00
Alexandre Vryghem
672219b261 Merge branch 'refs/heads/w2p-115427_fixed-delete-item-page-freezing_contribute-7.6' into w2p-115427_fixed-delete-item-page-freezing_contribute-main 2024-05-27 16:10:08 +02:00
Alexandre Vryghem
b8d9c650f5 115427: Fixed delete item not redirecting when having some virtual metadata that needs to be copied 2024-05-27 16:09:52 +02:00
Alexandre Vryghem
aea39efdf7 Merge branch 'w2p-115427_fixed-delete-item-page-freezing_contribute-7.6' into w2p-115427_fixed-delete-item-page-freezing_contribute-main
Conflicts:
	src/app/item-page/edit-item-page/item-delete/item-delete.component.ts
	src/app/item-page/full/full-item-page.component.spec.ts
	src/app/item-page/full/full-item-page.component.ts
	src/app/item-page/item-page.resolver.spec.ts
	src/app/item-page/item-page.resolver.ts
	src/app/item-page/simple/item-page.component.spec.ts
	src/app/item-page/simple/item-page.component.ts
2024-05-27 14:45:51 +02:00
Alexandre Vryghem
249cac4f27 115427: Fixed edit item pages not redirecting to 404 with invalid id 2024-05-27 13:42:44 +02:00
Alexandre Vryghem
e6086e16ea 115427: Fixed delete item page freezing when it has relationships 2024-05-27 13:42:44 +02:00
Alexandre Vryghem
38916ae5e7 115434: Passed relatedEntityType parameter to byLabel endpoint 2024-05-27 00:27:49 +02:00
Alexandre Vryghem
bd10925411 Merge branch 'refs/heads/legacy-bitstream-redirect-7.6' into legacy-bitstream-redirect_contribute-main
# Conflicts:
#	src/app/bitstream-page/legacy-bitstream-url-redirect.guard.spec.ts
#	src/app/bitstream-page/legacy-bitstream-url-redirect.guard.ts
2024-05-24 15:19:17 +02:00
Alexandre Vryghem
23644e9ec7 114624: Made the legacyBitstreamURLRedirectGuard return false for valid bitstream urls in combination with a HardRedirectService#redirect, this will make ensure the redirect is visible for curl instead of being performed by Angular 2024-05-24 15:06:12 +02:00
Alexandre Vryghem
d7be627c89 115215: Removed hardcoded options in favor of the ones from ClaimedTaskActionsLoaderComponent & AdvancedWorkflowActionsLoaderComponent 2024-05-23 22:02:35 +02:00
Alexandre Vryghem
2d957bfa37 115215: Fixed advanced workflow options (select reviewer & rating) throwing 404 error 2024-05-23 22:02:35 +02:00
lotte
553bada77d 115279: Replaced EndUserAgreeMent guards with functional guards 2024-05-23 15:30:15 +02:00
Alexandre Vryghem
484546e310 Merge branch 'w2p-113901_edit-item-relationships-does-not-display-tilted-relationships' into w2p-113901_edit-item-relationships-does-not-display-tilted-relationships_contribute-main 2024-05-23 12:26:35 +02:00
Alexandre Vryghem
7a9bb4d726 113901: Don't unsubscribe after first succeeded remote data, because otherwise the reRequestOnStale won't work 2024-05-23 11:58:44 +02:00
Zahraa Chreim
ffe30628ec 114858: Fix Com/Coll admins' management functionality for roles/groups 2024-05-23 08:58:37 +03:00
Tim Donohue
659052fcc0 Merge pull request #3069 from 4Science/task/main/DURACOM-263
#2923 - Fixed redirect on new Item version creation
2024-05-22 16:29:38 -05:00
root
ff68eacff3 Correcting a formatting error 2024-05-22 09:12:54 -03:00
Andrea Barbasso
e20c5d84b6 Merge remote-tracking branch 'refs/remotes/github/main' into task/main/DURACOM-263 2024-05-22 11:51:23 +02:00
root
4359361850 DSpace #1176 - Browse by Author serious issues 2024-05-21 17:08:40 -03:00
Tim Donohue
71bc1ad856 Merge pull request #2738 from 4Science/main-restore-hierarchical-tree-original-behaviour
Restore hierarchical tree original behaviour
2024-05-21 12:07:53 -05:00
Simone Ramundi
7581c9b6ea [DURACOM-263] - NEW - fix redirect to submission form on new item version 2024-05-21 18:08:08 +02:00
Andrea Barbasso
e14610914a [DURACOM-263] fix redirect to submission form on new item version creation 2024-05-21 12:31:30 +02:00
Alexandre Vryghem
df80c33e4e 115046: Fixed multiple edit relationship bugs
- Fixed issue making it impossible to add new relationships until the page is refreshed after deleting an existing one (only when you refreshed the page after creating the initial relationship)
- Fixed NPE in DsDynamicLookupRelationModalComponent
- Grouped buttons on relationship page in order to assure that they always have the same behaviour
2024-05-17 20:07:57 +02:00
Alexandre Vryghem
20a9b527ac Merge branch 'legacy-bitstream-redirect-7.6' into legacy-bitstream-redirect_contribute-main
# Conflicts:
#	src/app/bitstream-page/bitstream-page-routing.module.ts
#	src/app/bitstream-page/legacy-bitstream-url.resolver.spec.ts
#	src/app/bitstream-page/legacy-bitstream-url.resolver.ts
2024-05-16 20:47:46 +02:00
Kuno Vercammen
369bd693d4 114624: Refactored legacyBitstreamURL resolver into a guard to set the redirect status code to 301 Moved Permanently 2024-05-16 20:41:34 +02:00
Tim Donohue
d74e672997 Merge pull request #3056 from alexandrevryghem/minor-ui-improvements_contribute-main
Fixed item-edit.cy.ts regularly failing & minor UI improvements
2024-05-16 13:21:46 -05:00
Giuseppe Digilio
0c92934e93 Merge branch 'refs/heads/main' into main-restore-hierarchical-tree-original-behaviour
# Conflicts:
#	src/app/browse-by/browse-by-taxonomy-page/browse-by-taxonomy-page.component.ts
#	src/app/shared/form/builder/ds-dynamic-form-ui/models/onebox/dynamic-onebox.component.ts
#	src/app/shared/form/vocabulary-treeview-modal/vocabulary-treeview-modal.component.spec.ts
#	src/app/shared/form/vocabulary-treeview-modal/vocabulary-treeview-modal.component.ts
#	src/app/shared/form/vocabulary-treeview/vocabulary-treeview.component.spec.ts
#	src/app/shared/form/vocabulary-treeview/vocabulary-treeview.component.ts
#	src/app/shared/form/vocabulary-treeview/vocabulary-treeview.service.ts
#	src/app/shared/search/search-filters/search-filter/search-hierarchy-filter/search-hierarchy-filter.component.ts
2024-05-16 17:08:33 +02:00
Giuseppe Digilio
07a03bfa2d fix after merge 2024-05-16 15:59:48 +02:00
Giuseppe Digilio
1ccc7c624a Merge branch 'refs/heads/main' into main-optimize-metadata-represenation-rendering
# Conflicts:
#	src/app/item-page/simple/field-components/specific-field/item-page-field.component.ts
#	src/app/item-page/simple/metadata-representation-list/metadata-representation-list.component.ts
2024-05-16 15:48:59 +02:00
Tim Donohue
02e91dd383 Merge pull request #3005 from tdonohue/fix_subscription_links
Fix broken links on `/subscriptions` page
2024-05-16 08:34:22 -05:00
Alexandre Vryghem
1338712048 115046: Fixed failing tests & added new test to cover added code
(cherry picked from commit 479adf6519)
2024-05-16 14:42:38 +02:00
Art Lowel
71d033bf50 decrease the number of unnecessary rerenders by checking whether the relationship types have changed
(cherry picked from commit a658bf4531)
2024-05-16 14:10:37 +02:00
Art Lowel
5f74c295d3 fix issue where relationship lists wouldn't update automatically from the second submit onwards
(cherry picked from commit 4541788a34)
2024-05-16 14:00:31 +02:00
Art Lowel
fda14ac568 fix spinners
(cherry picked from commit cb59c05baf)
2024-05-16 14:00:09 +02:00
Art Lowel
65a629387a Merge remote-tracking branch 'alexandre/fix-create-relationship-not-working-between-same-types_contribute-7.6' into w2p-113560_edit-item-add-relationships-one-by-one
(cherry picked from commit 1c50dbf4c6)
2024-05-16 13:52:48 +02:00
Art Lowel
b8a4c83353 fix issue where a submit emitted from the edit relationship modal wouldn't arrive in the edit relationships component
(cherry picked from commit 9f3ee32858)
2024-05-16 13:39:03 +02:00
Art Lowel
814c81b7b7 update test
(cherry picked from commit e4b098e64d)
2024-05-16 13:22:24 +02:00
Art Lowel
17d1f2e6ac also add relationships one by one on the edit item relationships tab
(cherry picked from commit 8e59b7d0b0)
2024-05-16 13:20:45 +02:00
Alexandre Vryghem
56c786d3f7 Added missing alt & replaced remaining dspace logo PNGs with SVGs 2024-05-16 00:08:42 +02:00
Alexandre Vryghem
014944fede Fixed image overflowing outside of notification component 2024-05-16 00:08:42 +02:00
Alexandre Vryghem
77d0f9cd60 Fixed item-edit.cy.ts regularly failing because of aria-required-children for role="row" & added missing roles to edit comcol tabs 2024-05-16 00:08:41 +02:00
Tim Donohue
d8a24686ec Merge pull request #3046 from alexandrevryghem/w2p-109964_fix-vocabulary-options-with-url-as-stored-value_contribute-main
Fix self link don't match warnings for authorization endpoint
2024-05-15 16:49:23 -05:00
Alexandre Vryghem
c2684d3078 Aligned communities search results like collections on md screens 2024-05-15 21:11:28 +02:00
Alexandre Vryghem
83bbb98e4f Fix COAR notify link on the info component 2024-05-15 21:11:28 +02:00
Tim Donohue
13a33cde95 Merge pull request #2706 from rsaraivac/patch-2
Update pt-PT.json5
2024-05-15 12:16:37 -05:00
Tim Donohue
782352d8b5 Merge pull request #2944 from tdonohue/disable_inline_css
Disable `inlineCriticalCss` by default for better SSR performance
2024-05-15 12:06:58 -05:00
Alexandre Vryghem
d3e057e0c2 Merge branch 'w2p-109964_fix-vocabulary-options-with-url-as-stored-value_contribute-7.6' into w2p-109964_fix-vocabulary-options-with-url-as-stored-value_contribute-main 2024-05-15 00:50:56 +02:00
Alexandre Vryghem
b0991db1d4 Don't encode the uri parameter of /api/authz/authorizations/search/object since the returned self link doesn't encode the uri param 2024-05-15 00:48:34 +02:00
Tim Donohue
f59510d27e Merge pull request #2837 from 4Science/DURACOM-235
Enhanced community/colletion logo edit
2024-05-14 14:06:57 -05:00
Ricardo Saraiva
16c5665b31 Update pt-PT.json5
Revision and improvement of some of the already existing translation keys upon reviewers’ suggestions.
2024-05-14 19:15:27 +01:00
Tim Donohue
74f89f2d76 Merge pull request #3028 from sistedes/issue-3019
Add HTML support on system-wide alert (Fixes #3019)
2024-05-14 12:31:18 -05:00
Tim Donohue
d4e4143bf2 Merge pull request #3041 from DSpace/backport-2983-to-main
[Port main] Fix Author search result without co-author
2024-05-14 11:47:18 -05:00
Giuseppe Digilio
b7d454ffc1 [DURACOM-235] fix refactored after merge 2024-05-14 18:44:54 +02:00
Tim Donohue
70cbe16f72 Merge pull request #3025 from techlib/main
Czech DSpace 7 UI translation by NTK
2024-05-14 11:38:05 -05:00
Giuseppe Digilio
78e8fabc7f Merge remote-tracking branch '4scienceGithub/DURACOM-235' into DURACOM-235
# Conflicts:
#	src/app/collection-page/create-collection-page/create-collection-page.component.html
#	src/app/shared/comcol/comcol-forms/create-comcol-page/create-comcol-page.component.ts
2024-05-14 18:22:17 +02:00
Giuseppe Digilio
dbf9d29980 [DURACOM-235] Refactored creation in order to navigate to created object page 2024-05-14 18:15:47 +02:00
Giuseppe Digilio
b689b9f8a5 [DURACOM-235] Fixed home page path 2024-05-14 18:14:43 +02:00
Tim Donohue
517b367605 lint fixes 2024-05-14 11:06:15 -05:00
Tim Donohue
ae10f0a1ef Merge pull request #3040 from atmire/w2p-112198_add-relationship-effects-queue-main
[Port 8.x] Fix for not all CREATE/DELETE Relationship requests coming through, during submission entity lookup
2024-05-14 09:23:36 -05:00
Tim Donohue
3cd69dd1a9 Merge pull request #3007 from tdonohue/reorder_langs
After English, reorder languages alphabetically by language code
2024-05-14 09:14:42 -05:00
NTK
ca7a9cf120 Czech DSpace 7 UI translation by NTK 2024-05-14 01:45:01 +02:00
Oscar Chacón
696a0de1ad Update: replaced logic of allMetadataValues method by allMetadataNoExcludingValues logic
(cherry picked from commit 5e59403779)
2024-05-13 19:19:53 +00:00
Oscar Chacón
55326246b5 Fix trailing spaces and removed console.log
(cherry picked from commit 2530845b9b)
2024-05-13 19:19:53 +00:00
Oscar Chacón
4a608b1358 Fix: author search result without co-author
(cherry picked from commit f055ff6fbd)
2024-05-13 19:19:53 +00:00
Nona Luypaert
245187a179 Merge remote-tracking branch 'atmire-github/w2p-112198_add-relationship-effects-queue' into w2p-112198_add-relationship-effects-queue-main
Conflicts:
	src/app/shared/form/builder/ds-dynamic-form-ui/relation-lookup-modal/relationship.effects.spec.ts
	src/app/shared/form/builder/ds-dynamic-form-ui/relation-lookup-modal/relationship.effects.ts
	src/app/shared/form/builder/ds-dynamic-form-ui/relation-lookup-modal/search-tab/dynamic-lookup-relation-search-tab.component.html
2024-05-13 13:12:02 +02:00
Alexandre Vryghem
c2c832eff9 Merge remote-tracking branch 'alex/minor-ui-improvements_contribute-7.6' 2024-05-12 00:40:42 +02:00
Tim Donohue
3ab9f6a166 Merge pull request #2771 from saschaszott/patch-14
Layout improvement in feedback form page
2024-05-10 16:31:45 -05:00
Tim Donohue
a7e4f7d9a4 Merge pull request #3036 from DSpace/backport-2973-to-main
[Port main] added maxlength and hint to resource policy
2024-05-10 15:59:32 -05:00
Tim Donohue
688390fa08 Merge pull request #3037 from tdonohue/remove_debug_log
Remove unnecessary console.log
2024-05-10 15:59:15 -05:00
Tim Donohue
e6a3c2878c Remove unnecessary console.log 2024-05-10 15:16:48 -05:00
Oscar Chacón
6ac9965bb6 fixed lint errors
(cherry picked from commit f80d1fdc68)
2024-05-10 20:15:33 +00:00
Oscar Chacón
ad8b9806c7 added maxlength and hint to resource policy
(cherry picked from commit f8e0cc6808)
2024-05-10 20:15:32 +00:00
Sascha Szott
b67801f32f Merge branch 'main' into patch-14 2024-05-10 19:34:50 +02:00
Tim Donohue
8b1f46cc53 Merge pull request #2954 from atmire/w2p-104686_Live-import-preview-only-shows-first-mdv-7.6
Live import preview should show all metadata values, not only the first one
2024-05-10 12:28:30 -05:00
Tim Donohue
c2e0d683a4 Merge pull request #2951 from uniba-ub/fix-issue-2947
Fix display of dso names for EPersons
2024-05-10 12:19:56 -05:00
Tim Donohue
c4a7641e62 Merge pull request #2753 from alexandrevryghem/minor-themed-component-fixes_contribute-main
Themed component fixes
2024-05-10 11:18:09 -05:00
Tim Donohue
075700ae0d Merge pull request #2725 from alexandrevryghem/w2p-109964_fix-vocabulary-options-with-url-as-stored-value_contribute-main
Encode all `RequestParam` values
2024-05-10 10:52:50 -05:00
Tim Donohue
739af16f41 Merge pull request #3030 from 4Science/task/main/DURACOM-258
Allow submitter users to accept/ignore suggestions
2024-05-10 09:43:54 -05:00
Zahraa Chreim
ea928378f8 114858: Fix Lint Errors 2024-05-10 17:13:34 +03:00
Zahraa Chreim
f1cac6e385 114858: Add Tests for new Guards - Done 2024-05-10 16:00:27 +03:00
lotte
0eb61dd1de 115016: Fixed tests for 114858 2024-05-10 12:46:18 +02:00
Alisa Ismailati
88ecb25c7b [DURACOM-258] Allow submitters to accept/ignore suggestions 2024-05-10 10:11:59 +02:00
Abel Gómez
af193282da Fix code alignment 2024-05-10 02:10:37 +02:00
Abel Gómez
b9fb4e2159 Add HTML support to system-wide alert banner. Fixes #3019. 2024-05-10 02:09:37 +02:00
Tim Donohue
0afd79132d Merge pull request #3010 from autavares-dev/item-page-cc-license-field
Item page cc license field
2024-05-09 16:42:34 -05:00
Tim Donohue
c18b36988f Merge pull request #3024 from 4Science/task/main/DURACOM-259
[DURACOM-259] add correct metadata
2024-05-09 15:56:38 -05:00
Tim Donohue
6da5c11b5a Merge pull request #2900 from toniprieto/edit-item-authorities-bug-model
Error loading the initial value when editing an authority field in edit item page
2024-05-09 14:57:12 -05:00
Alexandre Vryghem
c24e58eb66 Added ComcolPageContentComponent to custom theme & fixed template urls of CommunityPageSubCollectionListComponent 2024-05-09 21:48:44 +02:00
Zahraa Chreim
16c75beebd 114858: Add Tests for new Guards 2024-05-09 15:28:50 +03:00
FrancescoMolinaro
ddfdf7f1dd [DURACOM-259] add correct metadata 2024-05-09 11:01:04 +02:00
Tim Donohue
6c4ff40020 Merge pull request #3012 from alexandrevryghem/advanced-search_contribute-main
Refactored advanced search to rely on available filters
2024-05-08 17:01:25 -05:00
Alexandre Vryghem
04764e468a Merge branch 'created-themeable-ProfilePageMetadataFormComponent_contribute-7.6' into minor-themed-component-fixes_contribute-main
# Conflicts:
#	src/app/profile-page/profile-page.component.spec.ts
#	src/app/profile-page/profile-page.component.ts
2024-05-08 23:07:08 +02:00
Alexandre Vryghem
83fbf8b02b 114077: Fixed ViewChild not working correctly 2024-05-08 23:00:22 +02:00
Tim Donohue
ceca3bfd80 Merge pull request #2875 from alexandrevryghem/created-metadata-service-for-metadata-operations_contribute-main
Moved MetadataValue methods to separate service
2024-05-08 15:17:19 -05:00
Tim Donohue
b406e71302 Merge pull request #3014 from atmire/w2p-113904_AddSupportForNullUsers
Handle Null Users Gracefully in Process Overview Page
2024-05-08 14:07:15 -05:00
Zahraa Chreim
b83b2dd404 114858: Create dsoPageSingleFeatureGuards for Edit Item and Edit Bitstream Routes 2024-05-08 16:29:15 +03:00
Zahraa Chreim
1ac3edc3f4 114858: Port to 8.0 2024-05-08 15:48:55 +03:00
Zahraa Chreim
17f6c5520a 114858: Merge 'w2p-114645_refactor_guards_as_functions-7.6' into 'w2p-114858_refactor_guards_as_functions-8.0' 2024-05-08 13:18:05 +03:00
Zahraa Chreim
4658ac8a2e 114858: Create and Add Guards to item&bitstream routes 2024-05-08 09:19:04 +03:00
Alexandre Vryghem
4c4531fe1e Custom theme fixes
- Moved PublicationSidebarSearchListElementComponent to correct folder
- Synced standalone imports in the custom theme with src/app
- Pointed custom theme's SearchComponent template to the ones from src/app
2024-05-08 01:33:19 +02:00
Tim Donohue
2aa0f95277 Merge pull request #2979 from tdonohue/add_openaire_keys
Add missing i18n keys for OpenAIRE external sources.
2024-05-07 14:13:17 -05:00
Tim Donohue
2215f5fe3e Merge pull request #3016 from tdonohue/fix_submission_reload
Ensure `item` is also embedded in submission form
2024-05-07 13:53:04 -05:00
Tim Donohue
bf4d04c909 Ensure item is also embedded in submission form 2024-05-07 12:08:25 -05:00
Alexandre Vryghem
fd6d470b3f 111731: Fixed scope not correctly resetting to no scope when clicking on "Search all of DSpace" in the search scope selector 2024-05-07 14:54:48 +02:00
Alexandre Vryghem
ede5f4325a 111731: Force the isActive state to be recalculated when the scope is updated
The BehaviorSubject was necessary because when the result of SearchService#getSelectedValuesForFilter is already cached, the isActive state can be recalculated even before the @Input() scope is updated
2024-05-07 14:22:03 +02:00
Alexandre Vryghem
2dbf69e46b Merge branch 'advanced-search_contribute-7.6' into advanced-search_contribute-main
# Conflicts:
#	src/app/core/shared/search/search-filter.service.ts
#	src/app/core/shared/search/search.service.ts
#	src/app/shared/search/search-filters/search-filter/search-facet-filter/search-facet-filter.component.spec.ts
#	src/app/shared/search/search-filters/search-filter/search-facet-filter/search-facet-filter.component.ts
#	src/app/shared/search/search-filters/search-filter/search-filter.component.spec.ts
#	src/app/shared/search/search-filters/search-filter/search-filter.component.ts
#	src/app/shared/search/search-filters/search-filter/search-hierarchy-filter/search-hierarchy-filter.component.spec.ts
#	src/app/shared/search/search-filters/search-filter/search-range-filter/search-range-filter.component.ts
#	src/app/shared/testing/search-service.stub.ts
2024-05-07 13:42:49 +02:00
Alexandre Vryghem
e66035c896 111731: Minimize all the facets when adding filter through advanced component & filter suggestions 2024-05-07 12:09:47 +02:00
Alexandre Vryghem
1f42f92344 111731: Hide the search facets when there are no facet suggestions & the applied filters of that facet don't have the operator equals, authority or range (because those should be displayed in the facets) 2024-05-07 12:07:40 +02:00
Kuno Vercammen
2d5d4a00ea 113904: Fixed the lint and import problems 2024-05-07 12:04:37 +02:00
Kuno Vercammen
f6bf757619 113904: Small changes 2024-05-07 11:46:31 +02:00
Kuno Vercammen
fda45723cc 113904: Added tests for the getEPersonName function 2024-05-07 11:45:45 +02:00
Kuno Vercammen
596b0dba69 113904: Returning unkown when showing process of deleted user 2024-05-07 11:43:32 +02:00
Alexandre Vryghem
28088bc8c8 111731: Made the code completely dependent on the SearchService#appliedFilters$ instead of relying on the route query parameters 2024-05-07 00:39:33 +02:00
Tim Donohue
d1876a87d3 Merge pull request #2988 from atmire/w2p-105866_Submission-performance-main
Submission performance
2024-05-06 11:02:50 -05:00
Mattia Vianelli
a525b066ce DURACOM-235 Lint fix 2024-05-06 16:47:34 +02:00
Mattia Vianelli
57563ddf96 Merge remote-tracking branch 'refs/remotes/4Science/main' into DURACOM-235
# Conflicts:
#	src/app/collection-page/collection-form/collection-form.component.ts
#	src/app/collection-page/create-collection-page/create-collection-page.component.html
#	src/app/community-page/community-form/community-form.component.ts
#	src/app/community-page/create-community-page/create-community-page.component.html
#	src/app/shared/comcol/comcol-forms/comcol-form/comcol-form.component.spec.ts
#	src/app/shared/comcol/comcol-forms/comcol-form/comcol-form.component.ts
#	src/app/shared/comcol/comcol-forms/edit-comcol-page/comcol-metadata/comcol-metadata.component.spec.ts
#	src/app/shared/comcol/comcol-forms/edit-comcol-page/comcol-metadata/comcol-metadata.component.ts
2024-05-06 16:23:26 +02:00
Alexandre Vryghem
2226cc4d3b Merge branch 'advanced-search_contribute-7.6' into advanced-search_contribute-main 2024-05-05 16:10:26 +02:00
Alexandre Vryghem
58d73875b8 111731: Fixed accessibility issues 2024-05-05 16:00:35 +02:00
Alexandre Vryghem
806b07c084 111731: Fixed tests not mocking SearchConfigurationService 2024-05-05 15:28:54 +02:00
Alexandre Vryghem
e94b094c20 Merge branch 'advanced-search_contribute-7.6' into advanced-search_contribute-main
# Conflicts:
#	src/app/core/shared/search/search-configuration.service.ts
#	src/app/shared/search/advanced-search/advanced-search.component.ts
#	src/app/shared/search/search-sidebar/search-sidebar.component.html
#	src/app/shared/search/search-sidebar/search-sidebar.component.spec.ts
#	src/app/shared/search/search-sidebar/search-sidebar.component.ts
#	src/app/shared/testing/search-configuration-service.stub.ts
2024-05-05 05:43:37 +02:00
Alexandre Vryghem
806430064f 111731: Hide advanced search section when no filters are available and hide it on the home page 2024-05-05 05:19:58 +02:00
Alexandre Vryghem
029359bace 111731: Search page UI fixes
- Hide advanced search when inPlaceSearch is false
- Fixed the search settings being invisible on small screens in the sidebar
- Fixed the view mode buttons not being selected unless the parameter view was defined in the url
2024-05-04 03:05:15 +02:00
Alexandre Vryghem
f5ce79fb54 Merge branch 'use-applied-filter-to-display-label-on-search_contribute-main' into advanced-search_contribute-main
# Conflicts:
#	src/app/shared/search/search-sidebar/search-sidebar.component.html
#	src/app/shared/search/search.component.html
2024-05-04 02:49:02 +02:00
Tim Donohue
c94be6bbf5 Merge pull request #2994 from DSpace/dependabot/npm_and_yarn/ejs-3.1.10
Bump ejs from 3.1.9 to 3.1.10
2024-05-03 16:03:52 -05:00
Tim Donohue
437cc5991e After English, reorder languages alphabetically by code 2024-05-03 15:08:11 -05:00
Tim Donohue
3b536a2856 Merge pull request #2863 from knowledgeWare-Tech/main
Added Arabic Translation
2024-05-03 15:01:58 -05:00
Alfeu Uzai Tavares
cec5892737 Refactor formatting with eslint + prettier 2024-05-03 16:58:33 -03:00
Alfeu Uzai Tavares
6df70370c9 Add CC license component to the simple item page 2024-05-03 16:53:56 -03:00
Tim Donohue
16c06624b1 Merge pull request #2930 from alexandrevryghem/fix-sync-i18n-script_contribute-main
Fix sync-i18n script throwing a compile error & added some missing translation keys
2024-05-03 14:53:36 -05:00
Alfeu Uzai Tavares
fc179a2ff7 Add unit tests for CC license component 2024-05-03 16:49:00 -03:00
Alfeu Uzai Tavares
6858b4b8e8 Add component to show CC license in the item page 2024-05-03 16:48:31 -03:00
Tim Donohue
18611660a5 Merge pull request #2814 from alexandrevryghem/use-applied-filter-to-display-label-on-search_contribute-main
Fixed authority ids being displayed on search page instead of their display value
2024-05-03 14:40:55 -05:00
Tim Donohue
a65f248eb2 Merge pull request #2651 from alexandrevryghem/theme-fixes_contribute-main
Fixed ItemSearchResultListElementComponent not fully themable
2024-05-03 14:02:56 -05:00
Tim Donohue
476e5a5ffe Merge pull request #2831 from pilasou/pilasou-translations-fr
French translations for missing parameters (access control and batch loading)
2024-05-03 11:44:12 -05:00
Tim Donohue
3bb559542d lint fixes 2024-05-03 11:16:59 -05:00
Tim Donohue
b86c7075df Fix broken links on subscriptions page 2024-05-03 11:06:35 -05:00
Tim Donohue
2a422ba9c5 Merge pull request #3004 from tdonohue/fix_3000
Fix `TypeError: Cannot read properties of undefined (reading 'userAgent')`
2024-05-03 10:19:41 -05:00
Tim Donohue
9efcbb20a4 Fix bug where "navigator" may be null in SSR mode 2024-05-03 09:38:02 -05:00
Tim Donohue
efdc357903 Merge pull request #2997 from tdonohue/update_for_runnable_jar
Ensure Docker Compose uses Runnable JAR (Angular)
2024-05-02 16:33:39 -05:00
Alexandre Vryghem
b75f589f36 Merge remote-tracking branch 'upstream/main' into use-applied-filter-to-display-label-on-search_contribute-main
# Conflicts:
#	src/app/shared/search/models/search-query-response.model.ts
#	src/app/shared/search/search-filters/themed-search-filters.component.ts
#	src/app/shared/search/search-sidebar/search-sidebar.component.html
#	src/app/shared/search/search-sidebar/themed-search-sidebar.component.ts
#	src/app/shared/search/search.component.html
2024-05-02 22:32:00 +02:00
Tim Donohue
054043a872 Merge pull request #2980 from atmire/w2p-114599_ClickingSaveOnCreateComColProvidesUserFeedback
Clicking save on create community and collection pages provides user feedback
2024-05-02 15:14:10 -05:00
Alexandre Vryghem
561ccc398e 111731: Used yml config to configure the visibility advanced search component & its filters 2024-05-02 22:03:54 +02:00
Tim Donohue
2260eab12c Sync cli.ingest.yml with same code as in DSpace/DSpace 2024-05-02 11:37:06 -05:00
Tim Donohue
574adc846b Ensure Docker Compose uses Runnable JAR. Minor bug fixes to loadsql per #2966 2024-05-02 11:37:06 -05:00
Alexandre Vryghem
e251c2c341 Merge branch 'advanced-search_contribute-7.6' into advanced-search_contribute-main
# Conflicts:
#	src/app/shared/search-form/search-form.component.spec.ts
#	src/app/shared/search-form/search-form.component.ts
2024-05-02 13:45:48 +02:00
Zahraa Chreim
08028dc152 114645: Add tests for dsoPageSingleFeatureGuard 2024-05-02 14:21:34 +03:00
Zahraa Chreim
45dac71e9b 114645: Add export in dsoPageSomeFeatureGuard and Fix some Lint issues 2024-05-02 14:06:48 +03:00
Kuno Vercammen
20146bdcef 114599: Updated the e2e tests so they succeed 2024-05-02 12:38:12 +02:00
dependabot[bot]
beab40a67a Bump ejs from 3.1.9 to 3.1.10
Bumps [ejs](https://github.com/mde/ejs) from 3.1.9 to 3.1.10.
- [Release notes](https://github.com/mde/ejs/releases)
- [Commits](https://github.com/mde/ejs/compare/v3.1.9...v3.1.10)

---
updated-dependencies:
- dependency-name: ejs
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-05-02 10:37:36 +00:00
Art Lowel
aecf2c7b61 add tests for dsoPageSomeFeatureGuard 2024-05-02 11:22:58 +02:00
Alexandre Vryghem
92cc112ed6 111731: Also minimize the search facets while switching scopes 2024-05-02 11:21:31 +02:00
Kuno Vercammen
6ff3a40929 114599: Adapted the changes after the rebase 2024-05-02 10:21:49 +02:00
Kuno Vercammen
8ac2fe9dcf 114599: Small lint fixes 2024-05-02 10:08:49 +02:00
Kuno Vercammen
fea2ff7b9c 114599: Added loading animation after creating collection or community 2024-05-02 10:08:40 +02:00
Kuno Vercammen
0ac98c5230 114599: Small lint fixes 2024-05-02 10:05:24 +02:00
Kuno Vercammen
9bcd816703 114599: Added e2e test to test the newly added loading component after creating com/col 2024-05-02 10:05:24 +02:00
Kuno Vercammen
fb988610db 114599: Added loading animation after creating collection or community 2024-05-02 10:05:24 +02:00
Alexandre Vryghem
bc35bfb3cd 111731: Refactored SearchFacetFilterWrapperComponent to extend AbstractComponentLoaderComponent 2024-05-02 00:00:47 +02:00
Tim Donohue
0e61cfd0c2 Merge pull request #2933 from atmire/reset-dropdown-values
Reset dropdown values
2024-05-01 16:38:00 -05:00
Alexandre Vryghem
f8759c56ad Merge branch 'use-applied-filter-to-display-label-on-search_contribute-main' into advanced-search_contribute-main
# Conflicts:
#	src/app/core/shared/search/search-configuration.service.spec.ts
#	src/app/core/shared/search/search-filter.service.spec.ts
#	src/app/core/shared/search/search-filter.service.ts
#	src/app/core/shared/search/search.service.ts
#	src/app/shared/search/advanced-search/advanced-search.component.html
#	src/app/shared/search/advanced-search/advanced-search.component.scss
#	src/app/shared/search/advanced-search/advanced-search.component.spec.ts
#	src/app/shared/search/advanced-search/advanced-search.component.ts
#	src/app/shared/search/search-filters/search-filter/search-facet-filter-options/search-facet-option/search-facet-option.component.spec.ts
#	src/app/shared/search/search-filters/search-filter/search-facet-filter-options/search-facet-selected-option/search-facet-selected-option.component.spec.ts
#	src/app/shared/search/search-filters/search-filter/search-facet-filter-options/search-facet-selected-option/search-facet-selected-option.component.ts
#	src/app/shared/search/search-filters/search-filter/search-facet-filter-wrapper/search-facet-filter-wrapper.component.ts
#	src/app/shared/search/search-filters/search-filter/search-facet-filter/search-facet-filter.component.spec.ts
#	src/app/shared/search/search-filters/search-filter/search-facet-filter/search-facet-filter.component.ts
#	src/app/shared/search/search-filters/search-filter/search-filter.actions.ts
#	src/app/shared/search/search-filters/search-filter/search-filter.component.ts
#	src/app/shared/search/search-filters/search-filter/search-filter.reducer.ts
#	src/app/shared/search/search-filters/search-filter/search-hierarchy-filter/search-hierarchy-filter.component.spec.ts
#	src/app/shared/search/search-filters/search-filter/search-hierarchy-filter/search-hierarchy-filter.component.ts
#	src/app/shared/search/search-filters/search-filter/search-range-filter/search-range-filter.component.html
#	src/app/shared/search/search-filters/search-filter/search-range-filter/search-range-filter.component.spec.ts
#	src/app/shared/search/search-filters/search-filter/search-range-filter/search-range-filter.component.ts
#	src/app/shared/search/search-filters/search-filters.component.html
#	src/app/shared/search/search-filters/search-filters.component.ts
#	src/app/shared/search/search-filters/themed-search-filters.component.ts
#	src/app/shared/search/search-labels/search-label-loader/search-label-loader.component.ts
#	src/app/shared/search/search-labels/search-label-loader/search-label-loader.decorator.ts
#	src/app/shared/search/search-labels/search-label-range/search-label-range.component.html
#	src/app/shared/search/search-labels/search-label-range/search-label-range.component.spec.ts
#	src/app/shared/search/search-labels/search-label-range/search-label-range.component.ts
#	src/app/shared/search/search-labels/search-label/search-label.component.html
#	src/app/shared/search/search-labels/search-label/search-label.component.spec.ts
#	src/app/shared/search/search-labels/search-label/search-label.component.ts
#	src/app/shared/search/search-labels/search-labels.component.ts
#	src/app/shared/search/search-sidebar/search-sidebar.component.html
#	src/app/shared/search/search-sidebar/search-sidebar.component.ts
#	src/app/shared/search/search-sidebar/themed-search-sidebar.component.ts
#	src/app/shared/search/search.component.html
#	src/app/shared/search/search.component.ts
#	src/app/shared/search/search.module.ts
#	src/app/shared/testing/search-configuration-service.stub.ts
#	src/assets/i18n/en.json5
2024-05-01 23:34:19 +02:00
Tim Donohue
0607878799 Merge pull request #2640 from hutattedonmyarm/regex-error-messages
More meaningful regex error messages
2024-05-01 16:20:22 -05:00
Tim Donohue
8c5fe13bb9 Merge pull request #2991 from tdonohue/remove_compose_version
Remove obsolete "version" tag from Docker Compose files (Angular version)
2024-05-01 15:04:59 -05:00
Tim Donohue
d6303de877 Remove obsolete "version" tag from compose files 2024-05-01 14:15:45 -05:00
Alexandre Vryghem
da320b5fbc Prevent ItemSearchResult from being recreated at every iteration 2024-05-01 19:10:36 +02:00
Zahraa Chreim
0ec1d28bd1 114645: Fix Lint Errors 2024-05-01 09:51:56 +03:00
Zahraa Chreim
5592be8790 114645: Refactor Class-Based guards tests 2024-05-01 09:46:46 +03:00
Alexandre Vryghem
20e96ac9bc Moved the WorkspaceItemsDeletePageComponent component to the correct folder in the custom theme 2024-04-30 22:56:59 +02:00
Alexandre Vryghem
1fb2b01af9 Merge remote-tracking branch 'upstream/main' into minor-themed-component-fixes_contribute-main
# Conflicts:
#	src/app/item-page/media-viewer/media-viewer.component.html
#	src/themes/custom/app/shared/comcol-page-handle/comcol-page-handle.component.ts
2024-04-30 22:56:40 +02:00
Tim Donohue
81807da35b Merge pull request #2693 from hutattedonmyarm/2687-radio-buttons-type-bind
Enable type-bind for checkbox inputs during submission
2024-04-30 15:13:12 -05:00
Alexandre Vryghem
27a83d6c7e Merge remote-tracking branch 'upstream/main' into theme-fixes_contribute-main 2024-04-30 21:25:36 +02:00
Tim Donohue
41a00e3312 Merge pull request #2976 from 4Science/DURACOM-253
Fix issue with the admin sidebar scrollbar on Firefox/Windows
2024-04-30 12:26:49 -05:00
Tim Donohue
0fa5d189da Merge pull request #2865 from ybnd/poc-eslint-plugin-autofix-selectors
Introduce custom ESLint rules to apply and enforce new themed component selector convention
2024-04-30 12:03:46 -05:00
Alexandre Vryghem
25fd737800 111731: Added missing border to advanced search section 2024-04-30 15:52:29 +02:00
Alexandre Vryghem
f5dc187a93 111731: Minimize the facet filters when updating applied filters 2024-04-30 15:52:29 +02:00
Art Lowel
9b9bcf718f refactor test 2024-04-30 14:33:02 +02:00
Art Lowel
f63aea103d add tests 2024-04-30 14:25:01 +02:00
Alexandre Vryghem
36ac6002cb 111731: Migrated the renderSearchLabelFor to standalone form 2024-04-30 13:48:14 +02:00
Alexandre Vryghem
f40a68f05e Merge remote-tracking branch 'upstream/main' into use-applied-filter-to-display-label-on-search_contribute-main
# Conflicts:
#	src/app/shared/search/search-labels/search-label/search-label.component.html
#	src/app/shared/search/search.component.html
2024-04-30 13:45:38 +02:00
Alexandre Vryghem
fb993477cc Merge branch 'main' into use-applied-filter-to-display-label-on-search_contribute-main
# Conflicts:
#	src/app/shared/search/search-filters/search-filter/search-facet-filter-options/search-facet-option/search-facet-option.component.spec.ts
#	src/app/shared/search/search-filters/search-filter/search-facet-filter-options/search-facet-option/search-facet-option.component.ts
#	src/app/shared/search/search-filters/search-filter/search-facet-filter-options/search-facet-range-option/search-facet-range-option.component.ts
#	src/app/shared/search/search-filters/search-filter/search-facet-filter-options/search-facet-selected-option/search-facet-selected-option.component.spec.ts
#	src/app/shared/search/search-filters/search-filter/search-facet-filter-options/search-facet-selected-option/search-facet-selected-option.component.ts
#	src/app/shared/search/search-filters/search-filter/search-filter.component.ts
#	src/app/shared/search/search-filters/search-filter/search-hierarchy-filter/search-hierarchy-filter.component.ts
#	src/app/shared/search/search-filters/search-filter/search-range-filter/search-range-filter.component.ts
#	src/app/shared/search/search-filters/search-filters.component.ts
#	src/app/shared/search/search-labels/search-label/search-label.component.spec.ts
#	src/app/shared/search/search-labels/search-label/search-label.component.ts
#	src/app/shared/search/search-labels/search-labels.component.ts
#	src/app/shared/search/search-sidebar/search-sidebar.component.ts
#	src/app/shared/search/search.component.html
#	src/app/shared/search/search.component.ts
#	src/app/shared/search/search.module.ts
2024-04-30 11:19:05 +02:00
Zahraa Chreim
7e04231490 114645: Refactor Class-Based guards into Functional guards 2024-04-30 12:04:23 +03:00
Yury Bondarenko
a48d1991f4 Autofix: remove unneeded base component imports
This is part of the themed-component-usages rule; Themed* components already import the base component, we don't need to import both anymore.
You'll see that all of these changes are also reflected in the base component.

Double-checked and this doesn't compromise the fixes from https://github.com/DSpace/dspace-angular/pull/2984
2024-04-30 10:52:40 +02:00
Yury Bondarenko
c9d9e12fa2 Merge remote-tracking branch 'origin/main' into poc-eslint-plugin-autofix-selectors 2024-04-30 10:47:19 +02:00
Alexandre Vryghem
17650612ac Merge remote-tracking branch 'upstream/main' into minor-themed-component-fixes_contribute-main 2024-04-29 23:53:27 +02:00
Tim Donohue
a8f65cea72 Merge pull request #2710 from DSpace/bram-atmire-patch-1-2709
Update robots.txt.ejs
2024-04-29 16:29:18 -05:00
Tim Donohue
13dbd6ba30 Merge pull request #2675 from atmire/multiline-search-filter-badge_main
Multiline selected facet badge on search page
2024-04-29 15:12:46 -05:00
Yana De Pauw
308670a699 [Ticket 2124] Slow response times 2024-04-29 13:07:55 +02:00
Tim Donohue
99bfe13c8e Merge pull request #2985 from atmire/w2p-114596_CreatingTemplateItemResultsInPageWhichNeverFinishesLoading
Fixed the problem that creating template item results in page which never finishes loading
2024-04-26 17:13:05 -05:00
Tim Donohue
3568acc696 Merge pull request #2984 from atmire/w2p-114732_CustomThemeNoLongerWorks
Synced the imports of the custom theme with the imports of the base component so custom theme works again
2024-04-26 16:56:43 -05:00
Kuno Vercammen
c5e3b18014 114624: Added small naming fix to e2e test 2024-04-26 13:40:00 +02:00
Kuno Vercammen
a1fd59f517 114732: Synced the imports of the custom theme with the imports of the base component 2024-04-26 11:19:53 +02:00
Yury Bondarenko
3a0c964a49 Upgrade @angular-eslint & get rid of warning in tests 2024-04-25 12:50:38 +02:00
Yury Bondarenko
348dcc47fd Generated docs should use Unix line endings on Windows 2024-04-25 12:30:53 +02:00
Yury Bondarenko
145a0a04b6 Fix lint plugins & tests on Windows 2024-04-25 11:52:12 +02:00
Alexandre Vryghem
a73b2adeeb Merge remote-tracking branch 'alex/themed-SubmissionUploadFilesComponent_contribute-7.6' into minor-themed-component-fixes_contribute-main
# Conflicts:
#	src/app/submission/submission.module.ts
#	src/themes/custom/lazy-theme.module.ts
2024-04-25 00:45:01 +02:00
Tim Donohue
2870e6ac54 Add missing i18n keys for OpenAIRE external sources. Remove some duplicate keys 2024-04-24 17:12:57 -05:00
Tim Donohue
288a9180aa Merge pull request #2962 from atmire/fix-submission-lost-changes-after-save-8.0.0-next
Fix submission lost changes after save
2024-04-24 16:27:24 -05:00
Yury Bondarenko
671e9f172b Move ESLint plugins to dev dependencies 2024-04-24 19:07:31 +02:00
Alexandre Vryghem
63be2dae54 111731: Fixed search labels not working correctly for non-equals operators 2024-04-24 18:34:42 +02:00
Alexandre Vryghem
c1abeb3aab 111731: Don't show suggestions for filters of type date in advanced search, since they don't add the correct filters 2024-04-24 18:34:42 +02:00
Alexandre Vryghem
b771122297 111731: Reset the advanced search's operator to the first available operator on filter change 2024-04-24 18:34:42 +02:00
Alexandre Vryghem
d40d0b7c9c 111731: Fixed selected filters not being displayed as labels 2024-04-24 18:34:42 +02:00
Art Lowel
af2e0976af move embed item fix to SubmissionJsonPatchOperationsService 2024-04-24 10:54:54 +02:00
Yury Bondarenko
728b561bf4 Optional postinstall script should be cross-platform
There is no cross-platform way to check if the file/directory exists that doesn't depend on adding another NodeJS dependency.
This "skip if failed" approach is more noisy, but it should work everywhere.
2024-04-24 10:54:02 +02:00
Yury Bondarenko
80be4fc8b0 Skip build:lint if installed without source 2024-04-24 10:11:46 +02:00
Max Nuding
0c6dc895db Merge branch 'DSpace:main' into regex-error-messages 2024-04-24 08:37:18 +02:00
Pierre Lasou
1abc796734 Update fr.json5 correcting bad quotation marks 2024-04-23 15:49:08 -04:00
Pierre Lasou
3b98c8c84f Update fr.json5 - adding missing comma 2024-04-23 14:14:55 -04:00
Alexandre Vryghem
8b29a7189b Themed SubmissionUploadFilesComponent 2024-04-23 13:45:04 +02:00
Davide Negretti
44464de25a [DURACOM-253] Fix scrollbar issue on Firefox on Windows 2024-04-23 12:08:18 +02:00
Davide Negretti
f8194ab58b [DURACOM-253] Detect browser and apply browser class 2024-04-23 12:07:57 +02:00
Kuno Vercammen
7767934a5b 114596: Small lint fix 2024-04-23 09:03:12 +02:00
Kuno Vercammen
0ded7a4e03 114596: Added e2e tests for item template page 2024-04-23 08:50:12 +02:00
Alexandre Vryghem
132e1f9524 Minor UI improvements
- Fixed DSO edit menu sometimes displaying underneath header based on header z-index
- Fixed accessibility issue on request a copy page
2024-04-23 02:02:28 +02:00
Alexandre Vryghem
3f922490b4 Merge branch 'minor-themed-component-fixes_contribute-7.6' into minor-themed-component-fixes_contribute-main
# Conflicts:
#	src/app/entity-groups/journal-entities/item-list-elements/search-result-list-elements/journal-issue/journal-issue-search-result-list-element.component.html
#	src/app/entity-groups/journal-entities/item-list-elements/search-result-list-elements/journal-volume/journal-volume-search-result-list-element.component.html
#	src/app/entity-groups/journal-entities/item-list-elements/search-result-list-elements/journal/journal-search-result-list-element.component.html
#	src/app/entity-groups/research-entities/item-list-elements/search-result-list-elements/org-unit/org-unit-search-result-list-element.component.html
#	src/app/entity-groups/research-entities/item-list-elements/search-result-list-elements/person/person-search-result-list-element.component.html
#	src/app/entity-groups/research-entities/item-list-elements/search-result-list-elements/project/project-search-result-list-element.component.html
#	src/app/entity-groups/research-entities/submission/item-list-elements/person/person-search-result-list-submission-element.component.html
#	src/app/shared/object-list/search-result-list-element/item-search-result/item-types/item/item-search-result-list-element.component.html
#	src/app/shared/object-list/sidebar-search-list-element/community/community-sidebar-search-list-element.component.ts
2024-04-22 23:45:32 +02:00
Tim Donohue
d4531055d4 Merge pull request #2966 from tdonohue/update_backend_docker_scripts
Update REST and CI docker compose scripts to sync with 8.0 backend
2024-04-22 16:40:21 -05:00
Alexandre Vryghem
7000035303 Fixed duplicate selectors throwing warnings 2024-04-22 22:41:02 +02:00
Tim Donohue
e13f35eb33 Update README for DSpace 8 2024-04-22 11:32:19 -05:00
Yury Bondarenko
858d69c8ef Merge remote-tracking branch 'origin/main' into poc-eslint-plugin-autofix-selectors 2024-04-22 14:33:04 +02:00
Kuno Vercammen
a7cdf2e97a 114596: Fixed the issue that item template page never loads 2024-04-22 12:56:11 +02:00
Yury Bondarenko
bb10b808f6 Build ESLint plugins after yarn install 2024-04-22 12:42:30 +02:00
Tim Donohue
96cff30c65 Update REST and CI docker compose scripts to sync with 8.0 backend 2024-04-19 16:04:01 -05:00
Tim Donohue
6d582cd39e Merge pull request #2816 from atmire/w2p-111326_fix-status-code-object-not-found-7.4
Return 404 Not Found status code on missing identifiers
2024-04-19 12:07:21 -05:00
Art Lowel
a3540be736 fix lint issues 2024-04-19 18:15:05 +02:00
Tim Donohue
a4387bb38a Merge pull request #2642 from alexandrevryghem/fix-broken-item-mapper-pagination_contribute-main
Fixed pagination issues on item mapper
2024-04-19 10:57:39 -05:00
Art Lowel
d03c640e8c Merge remote-tracking branch 'atmire-github/fix-submission-lost-changes-after-save-7.6' into fix-submission-lost-changes-after-save-8.0.0-next 2024-04-19 17:45:27 +02:00
Tim Donohue
e96ca2f59d Merge pull request #2768 from 4Science/DURACOM-224
Fix infinite scroll
2024-04-19 10:42:45 -05:00
Tim Donohue
489d8fdbc1 Merge pull request #2888 from alexandrevryghem/w2p-112970_added-missing-breadcrumbs_contribute-main
Added missing/incomplete breadcrumbs on create community/collection/item pages
2024-04-19 10:28:04 -05:00
Tim Donohue
57b0efe30f Merge pull request #2945 from alexandrevryghem/home-page-facet-fixes
Fixed home page links being unclickable
2024-04-19 10:14:12 -05:00
Alexandre Vryghem
a5f49babac Merge remote-tracking branch 'upstream/main' into fix-broken-item-mapper-pagination_contribute-main
# Conflicts:
#	src/app/shared/object-list/object-list.component.html
#	src/app/shared/object-select/collection-select/collection-select.component.ts
#	src/app/shared/object-select/item-select/item-select.component.ts
#	src/app/shared/pagination/pagination.component.ts
2024-04-18 22:31:15 +02:00
Alexandre Vryghem
adf995cf36 Merge branch 'fix-broken-item-mapper-pagination_contribute-7.6' into fix-broken-item-mapper-pagination_contribute-main
# Conflicts:
#	src/app/access-control/bulk-access/browse/bulk-access-browse.component.html
#	src/app/access-control/epeople-registry/epeople-registry.component.html
#	src/app/access-control/epeople-registry/eperson-form/eperson-form.component.html
#	src/app/access-control/group-registry/group-form/members-list/members-list.component.html
#	src/app/access-control/group-registry/group-form/subgroup-list/subgroups-list.component.html
#	src/app/process-page/overview/process-overview.component.html
#	src/app/shared/object-select/collection-select/collection-select.component.html
#	src/app/shared/object-select/collection-select/collection-select.component.ts
#	src/app/shared/object-select/item-select/item-select.component.html
#	src/app/shared/object-select/item-select/item-select.component.ts
#	src/app/shared/object-select/object-select/object-select.component.ts
#	src/app/shared/pagination/pagination.component.ts
2024-04-18 21:39:10 +02:00
Alexandre Vryghem
268d2e54fc 108555: Refactored CollectionSelectComponent to not call canSelect every time changes are detected 2024-04-18 21:18:10 +02:00
Alexandre Vryghem
59197cff2d 108555: Refactored ItemSelectComponent to not call canSelect every time changes are detected 2024-04-18 21:18:10 +02:00
Alexandre Vryghem
da31c4f253 108555: Removed pageInfoState Input since it wasn't used and almost all the components gave the incorrect type of data to it 2024-04-18 19:28:01 +02:00
Yury Bondarenko
63090b501b Update README 2024-04-18 15:08:08 +02:00
Yury Bondarenko
f1c25ee344 Fix overindented decorated properties 2024-04-18 13:16:39 +02:00
Yury Bondarenko
eec052fd77 Fix Community stats page selector
Likely a copy/paste leftover
2024-04-18 12:27:55 +02:00
Jens Vannerum
5f89dd27fb 114440: fix test 2024-04-18 11:59:12 +02:00
Yury Bondarenko
dc1053e3f9 Resolve lint issues due to new default rules
We could turn these rules off, but it seems that they indicate some important inconsistencies.

A few cases have been ignored inline because they should be investigated in more detail, which is out of scope for this PR:
- Metadata representation components compare `BrowseByDataType` to a `ResourceType`. Could be related to #2949.
- We assume that dynamic form dates are always represented by strings, but they can also be `Date` or `object` according to the library (see da1742ce05/projects/ng-dynamic-forms/core/src/lib/model/dynamic-date-control.model.ts (L5))
2024-04-18 11:02:04 +02:00
Yury Bondarenko
14a19b2000 Upgrade TSESLint to support TypeScript 5.3.3 2024-04-18 11:02:04 +02:00
Jens Vannerum
b757ca6433 Merge remote-tracking branch 'upstream/main' into w2p-104686_Live-import-preview-only-shows-first-mdv-7.6 2024-04-18 10:50:21 +02:00
Marie Verdonck
00d7b8322d 104686: Live Import preview only shows first metadata value per field 2024-04-18 02:08:20 +02:00
Gantner, Florian Klaus
97fade00a4 extend eperson render type for display of dso name
https://github.com/DSpace/dspace-angular/issues/2947
2024-04-17 17:59:10 +02:00
Yury Bondarenko
efec114df3 Auto-migrate to fix new ds-themed-* usages 2024-04-17 14:44:07 +02:00
Yury Bondarenko
2e9acc3885 Merge remote-tracking branch 'origin/main' into poc-eslint-plugin-autofix-selectors 2024-04-17 14:40:45 +02:00
Alexandre Vryghem
3a13ea8618 Merge remote-tracking branch 'upstream/main' into theme-fixes_contribute-main
# Conflicts:
#	src/app/shared/object-collection/shared/listable-object/listable-object-component-loader.component.spec.ts
2024-04-17 00:22:43 +02:00
Alexandre Vryghem
9bdf265f32 Home page facet refactor fixes 2024-04-17 00:07:37 +02:00
lotte
5859fc175a Merge remote-tracking branch 'origin/main' into multiline-search-filter-badge_main 2024-04-16 18:18:29 +02:00
Tim Donohue
ee174747c2 Disable inlineCriticalCss by default for better SSR performance 2024-04-15 16:13:41 -05:00
Tim Donohue
0a1764c65a Merge pull request #2934 from 4Science/DURACOM-248-ANGULAR-17
Upgrade to angular 17
2024-04-15 15:15:10 -05:00
Tim Donohue
a16139c285 Merge pull request #2931 from dspace-unimr/fix-#2918-new-user-registration-does-not-work
Add check for registration verification to the register email form.
2024-04-15 11:37:49 -05:00
Jens Vannerum
b48db7df32 Merge remote-tracking branch 'upstream/main' into w2p-111326_fix-status-code-object-not-found-7.4 2024-04-15 14:47:06 +02:00
Giuseppe Digilio
bd9e58038d [DURACOM-248] Upgrade to latest Angular minor release 2024-04-15 13:18:06 +02:00
Andrea Barbasso
93bcd92b0a [DURACOM-248] lint fix 2024-04-15 12:31:18 +02:00
Giuseppe Digilio
3344344531 Merge remote-tracking branch '4scienceGithub/DURACOM-248-ANGULAR-17' into DURACOM-248-ANGULAR-17 2024-04-15 12:13:34 +02:00
Alexandre Vryghem
8d1d04ed58 111731: Added theme support to renderSearchLabelFor 2024-04-15 12:07:39 +02:00
Alexandre Vryghem
7eb26582db 111731: Added apply filter functionality 2024-04-15 12:07:39 +02:00
Alexandre Vryghem
3cdf426594 111731: Fixed search filter input suggestions not resetting the page number by moving that logic to the search configuration service 2024-04-15 12:07:38 +02:00
Andreas Awouters
31d3ab0811 113319: Fix dropdown component spec
(cherry picked from commit 70357803e86caabc6357b7cbec9db1ef8edd2a56)
2024-04-15 11:23:09 +02:00
Andreas Awouters
1580acb7be 113319: Add dropdown entry to clear selection
(cherry picked from commit 13d1547b3dbf5d4cd74617d6327044da798ed44e)
2024-04-15 11:23:00 +02:00
Andrea Barbasso
d6595daa9b [DURACOM-248] move tests 2024-04-15 11:21:36 +02:00
Andrea Barbasso
87cff6c907 [DURACOM-248] set function call result in a class attribute 2024-04-15 09:43:38 +02:00
Andrea Barbasso
c485f108a1 [DURACOM-248] move element version table row logic to a component 2024-04-15 09:27:29 +02:00
Eike Martin Löhden
36b92004b2 Add check for registration verification to the register email form. 2024-04-15 07:31:10 +02:00
Mohamed Ali
159b0c29de Added Arabic Translation 2024-04-15 01:52:32 +02:00
Alexandre Vryghem
59f913b98b Made dso-selector placeholder types translatable 2024-04-14 22:54:37 +02:00
Alexandre Vryghem
0ba1b26318 Fixed sync-i18n script not working anymore
This is caused by the typescript 4.4 update that changed the catch type from any to unknown
2024-04-14 22:54:36 +02:00
Alexandre Vryghem
ac40726b18 Merge branch 'created-themeable-ProfilePageMetadataFormComponent_contribute-7.6' into minor-themed-component-fixes_contribute-main
# Conflicts:
#	src/app/profile-page/profile-page.module.ts
#	src/themes/custom/lazy-theme.module.ts
2024-04-14 15:14:17 +02:00
Alexandre Vryghem
f5f00ca24a 114077: Made ProfilePageMetadataFormComponent themeable 2024-04-14 14:46:35 +02:00
Alexandre Vryghem
68e52bcee4 Merge remote-tracking branch 'upstream/main' into minor-themed-component-fixes_contribute-main
# Conflicts:
#	src/app/admin/admin-routes.ts
2024-04-13 19:35:51 +02:00
Alexandre Vryghem
74f8757ae1 Merge remote-tracking branch 'upstream/main' into minor-themed-component-fixes_contribute-main
# Conflicts:
#	src/app/admin/admin-routes.ts
2024-04-13 18:53:19 +02:00
Alexandre Vryghem
10d90c3110 Merge remote-tracking branch 'upstream/main' into theme-fixes_contribute-main
# Conflicts:
#	src/app/shared/object-collection/shared/listable-object/listable-object-component-loader.component.spec.ts
#	src/app/shared/object-list/item-list-element/item-types/item/item-list-element.component.spec.ts
2024-04-13 18:50:10 +02:00
Alexandre Vryghem
36e5617679 Merge branch 'main' into created-metadata-service-for-metadata-operations_contribute-main
# Conflicts:
#	src/app/core/metadata/metadata.service.spec.ts
#	src/modules/app/browser-init.service.ts
2024-04-13 18:31:05 +02:00
Alexandre Vryghem
33d3ff0c44 111731: Integrated the FilterInputSuggestionsComponent in the advanced search facets to show input suggestions (only works for filters that are also part of the facets) 2024-04-13 03:26:44 +02:00
Alexandre Vryghem
89eb314fe7 111731: Moved findSuggestions logic to SearchFilterService in order to reuse it in the advanced search component 2024-04-13 03:26:43 +02:00
Alexandre Vryghem
b9fa479519 111731: Created new advanced search component 2024-04-13 03:26:43 +02:00
Tim Donohue
c13d23da9c Merge pull request #2844 from alexandrevryghem/fix-home-page-issues
Fixed home page issues
2024-04-12 14:13:20 -05:00
Tim Donohue
4d59c13f7e Merge pull request #2926 from IgorBaptist4/typo_role
typo in role name
2024-04-12 13:58:23 -05:00
IgorBaptist4
ad114daff8 typo in role name 2024-04-12 15:49:11 -03:00
Tim Donohue
d29d3ca423 Merge pull request #2905 from atmire/w2p-113500_submission-describe-warning_contribution
Fix for submission describe warning contribution bug
2024-04-12 12:20:33 -05:00
Giuseppe Digilio
e99d41abe0 Merge remote-tracking branch '4scienceGithub/DURACOM-248-ANGULAR-17' into DURACOM-248-ANGULAR-17 2024-04-12 16:56:31 +02:00
Andrea Barbasso
9f75c3986f [DURACOM-248] add elvis operator to getRemoteDataPayload 2024-04-12 16:52:36 +02:00
Giuseppe Digilio
74a53b7694 [DURACOM-248] Create structural directive for rendering elements on browser only 2024-04-12 16:16:16 +02:00
Yury Bondarenko
e5ba482871 Merge remote-tracking branch 'origin/main' into fix-versioning-button 2024-04-12 11:48:37 +02:00
Giuseppe Digilio
9e23917381 Merge branch 'refs/heads/main' into DURACOM-248-ANGULAR-17
# Conflicts:
#	server.ts
#	src/config/universal-config.interface.ts
#	src/environments/environment.production.ts
#	src/environments/environment.ts
2024-04-12 09:04:48 +02:00
Alexandre Vryghem
e10630f131 Added functionality to disable COAR notify support link in footer
Also fixed error that showed a blank page instead of a 404 when disabling EULA/Privacy Policy pages
2024-04-12 01:38:34 +02:00
Alexandre Vryghem
2ef2e9b334 Fixed minor alignment issue of comcol names on /community-list 2024-04-12 00:39:41 +02:00
Giuseppe Digilio
2bbf584a45 [DURACOM-248] Fix e2e test execution 2024-04-11 20:59:57 +02:00
Giuseppe Digilio
d7d8067006 [DURACOM-247] Refactoring SSR configuration in order to align it with new nomenclature 2024-04-11 18:14:34 +02:00
Giuseppe Digilio
7b1f264812 [DURACOM-248] Fix lint 2024-04-11 18:03:30 +02:00
Alexandre Vryghem
97f70d897e Merge branch 'w2p-112970_added-missing-breadcrumbs_contribute-7.4' into w2p-112970_added-missing-breadcrumbs_contribute-main
# Conflicts:
#	src/app/collection-page/collection-page-routing.module.ts
#	src/app/community-page/community-page-routing.module.ts
2024-04-11 00:18:51 +02:00
Alexandre Vryghem
4251630ab8 112970: Always rerun resolvers on url change for create comcol pages 2024-04-11 00:18:04 +02:00
Alexandre Vryghem
5f8033a111 Merge remote-tracking branch 'upstream/main' into w2p-112970_added-missing-breadcrumbs_contribute-main
# Conflicts:
#	src/app/collection-page/collection-page-routes.ts
#	src/app/community-page/community-page-routes.ts
#	src/app/core/breadcrumbs/community-breadcrumb.resolver.ts
#	src/app/core/breadcrumbs/dso-breadcrumb.resolver.spec.ts
#	src/app/core/breadcrumbs/dso-breadcrumb.resolver.ts
#	src/app/core/submission/resolver/submission-object.resolver.ts
#	src/app/workflowitems-edit-page/item-from-workflow.resolver.spec.ts
#	src/app/workflowitems-edit-page/item-from-workflow.resolver.ts
#	src/app/workflowitems-edit-page/workflowitems-edit-page-routes.ts
#	src/app/workspaceitems-edit-page/item-from-workspace.resolver.spec.ts
#	src/app/workspaceitems-edit-page/item-from-workspace.resolver.ts
#	src/app/workspaceitems-edit-page/workspaceitems-edit-page-routes.ts
2024-04-11 00:04:42 +02:00
Tim Donohue
39d2a753db Merge pull request #2782 from alexandrevryghem/fix-font-awesome-5-icons_contribute-7.6
Fixed Font Awesome CSS Pseudo-elements not rendering in v6.x
2024-04-10 16:51:37 -05:00
Alexandre Vryghem
b2c14df8f7 Moved home COAR functionality to separate component 2024-04-10 23:31:07 +02:00
Alexandre Vryghem
fcabea0ac5 Hide the reset filters button on the home page & fixed spacing issue when showDiscoverFilters is disabled 2024-04-10 22:57:24 +02:00
Alexandre Vryghem
ca167a2321 Prevent /api/eperson/profiles/{userId} to be called when unauthenticated 2024-04-10 22:57:24 +02:00
Alexandre Vryghem
08027bb753 Fixed home news facets sidebar & home content section alignment when facets are disabled 2024-04-10 22:57:24 +02:00
Tim Donohue
a3894a1734 Merge pull request #2859 from 4Science/DURACOM-195-fixes
Header, navbar, and admin sidebar refactoring (minor fixes)
2024-04-10 14:34:36 -05:00
Tim Donohue
26ecc03584 Merge pull request #2897 from 4Science/DURACOM-247
Fixes for #2891 #2889
2024-04-10 12:17:03 -05:00
Tim Donohue
10db33bcea Docker build IDs must all be unique to avoid image conflicts. Ensure no builds use a generic name like "dspace-angular". 2024-04-09 14:52:27 -05:00
Giuseppe Digilio
a8fcfa2550 Merge branch 'refs/heads/DURACOM-247' into DURACOM-248-ANGULAR-17 2024-04-09 09:29:19 +02:00
Giuseppe Digilio
b2f94b515a [DURACOM-247] Fix lint 2024-04-08 23:08:04 +02:00
Giuseppe Digilio
883ceeae27 [DURACOM-247] Refactored by using a map of promises 2024-04-08 23:04:47 +02:00
Giuseppe Digilio
115445a6ab [DURACOM-247] Move local variable within if statement 2024-04-08 22:25:01 +02:00
Tim Donohue
0c006ba49b Merge pull request #2910 from tdonohue/update_actions
Update all GitHub Actions & add token for Codecov.io
2024-04-08 14:44:43 -05:00
Giuseppe Digilio
2a3a13e293 [DURACOM-247] Refactored by providing the map of promises 2024-04-08 19:21:20 +02:00
Tim Donohue
54f1ce4b78 Ensure all artifacts have a unique name by appending Node version to each 2024-04-08 11:14:30 -05:00
Tim Donohue
2e92ee752d Update all GitHub Actions. Add newly required CODECOV_TOKEN to codecov action 2024-04-08 10:22:04 -05:00
lotte
903af2ccdb 113500: Fixed lint issues 2024-04-08 10:40:45 +02:00
Tim Donohue
330925f861 Update version tag for development of next release 2024-04-05 17:33:58 -05:00
Toni Prieto
07d30ff931 Create the model before displaying the vocabulary fields in edit item page 2024-04-05 15:48:27 +02:00
Giuseppe Digilio
aac61785d3 [DURACOM-247] Add condition to check function is not null 2024-04-05 12:23:18 +02:00
akoscomp
93bf085274 [DURACOM-248] update yarn.lock 2024-04-05 10:00:12 +02:00
Giuseppe Digilio
297b5f504c Merge branch 'main' into DURACOM-248-ANGULAR-17
# Conflicts:
#	yarn.lock
2024-04-05 09:56:18 +02:00
Giuseppe Digilio
d2ec558ac2 [DURACOM-247] Move check for initialized token to request effects 2024-04-05 09:43:47 +02:00
Yury Bondarenko
1b113569ca Merge remote-tracking branch 'origin/main' into poc-eslint-plugin-autofix-selectors 2024-04-04 18:38:54 +02:00
Giuseppe Digilio
40204328ad [DURACOM-247] Resolve CodeQL alert 2024-04-04 18:21:38 +02:00
Yury Bondarenko
ac48a49273 Merge remote-tracking branch 'origin/main' into poc-eslint-plugin-autofix-selectors 2024-04-04 18:15:28 +02:00
Alexandre Vryghem
d9a6f6d018 Merge branch 'w2p-112970_added-missing-breadcrumbs_contribute-7.4' into main 2024-04-04 16:07:02 +02:00
Alexandre Vryghem
60d93e653f 113938: Added missing comcol structure to workspace/workflow item breadcrumbs 2024-04-04 12:07:29 +02:00
lotte
bff5de066b Merge branch 'w2p-113500_submission-describe-warning-7.6' into w2p-113500_submission-describe-warning_contribution 2024-04-03 19:05:34 +02:00
Yury Bondarenko
b99d9030cd Fix stray Angular 17 dependency 2024-04-03 12:36:46 +02:00
Alexandre Vryghem
fb8733ca0b 113901: Store the retrieved Relationships in the store
This needs to be done here too, since tilted relationships won't be returned by the api/core/items/{uuid}/relationships endpoint
2024-04-02 17:39:44 +02:00
Yury Bondarenko
c4b32febc1 Explain themed-component-classes rule 2024-03-29 10:52:55 +01:00
Yury Bondarenko
08a5443cc2 Add generated docs to source 2024-03-29 10:47:04 +01:00
Yury Bondarenko
515e5f00cf Improve documentation 2024-03-29 10:46:20 +01:00
Yury Bondarenko
2c68589416 Move generated documentation to docs/lint/ 2024-03-29 10:12:57 +01:00
Yury Bondarenko
a6e093038c Manual fix: use base components in unit test templates
`Themed*` components should be used in the actual codebase to ensure we retain theme support.
However, in unit tests these components won't work without a fully-functional `ThemeService` & `Store`.

For this reason, the lint plugin allows `ds-base-*` selectors in unit test templates.
2024-03-28 18:52:06 +01:00
Yury Bondarenko
762e4616cc Manual fix: sync removed imports between tests and components
The automatic migration made it so HTML always uses the `Themed*` component, and it must therefore be imported in all standalone components that use it.
Afterwards, many unit tests fail because the removed imports no longer match up (can't inject `ThemeService`).

While we could try to support this as part of the automatic migration, there are too many edge cases for this to be consistent.
2024-03-28 18:52:06 +01:00
Yury Bondarenko
0b9741d252 Manual fix: update i/o for ThemedConfigurationSearchPageComponent
Fixes compile-time errors due to out-of-sync inputs and outputs between ThemedConfigurationSearchPageComponent and SearchComponent

(note that this is was an existing problem in the source code that flew under the radar until we flipped the selector convention!)
2024-03-28 18:52:06 +01:00
Yury Bondarenko
6051b82821 Automatically migrate to new themeable component convention 2024-03-28 18:33:46 +01:00
Yury Bondarenko
e40b6ae612 Update plugins to support standalone components
- ThemedComponent wrappers should always import their base component. This ensures that it's always enough to only import the wrapper when we use it.
- This implies that all themeable components must be standalone

→ added rules to enforce this
→ updated usage rule to improve declaration/import handling
2024-03-28 18:33:46 +01:00
Giuseppe Digilio
abae9b9246 [DURACOM-234] WIP fix SSR 2024-03-28 16:37:42 +01:00
Giuseppe Digilio
3cb000db7c Merge branch 'DURACOM-234' into DURACOM-234-ANGULAR-17
# Conflicts:
#	src/main.server.ts
2024-03-27 14:22:42 +01:00
lotte
722bd6f7f5 113500: Fixed lint error 2024-03-27 14:15:20 +01:00
lotte
4e0046022b 113500: Fixed tests after bugfix 2024-03-27 14:07:55 +01:00
lotte
993ce1ab16 113500: Fix for warning on first describe step 2024-03-27 13:27:44 +01:00
Alexandre Vryghem
c476c4b343 Merge branch 'main' into minor-themed-component-fixes_contribute-main 2024-03-25 00:14:45 +01:00
Alexandre Vryghem
147b9f2efb Merge branch 'main' into minor-themed-component-fixes_contribute-main 2024-03-24 23:56:23 +01:00
Alexandre Vryghem
babe936c30 Merge branch 'w2p-109964_fix-vocabulary-options-with-url-as-stored-value_contribute-7.6' into w2p-109964_fix-vocabulary-options-with-url-as-stored-value_contribute-main
# Conflicts:
#	src/app/core/data/relationship-data.service.ts
#	src/app/core/data/relationship-type-data.service.ts
#	src/app/core/eperson/eperson-data.service.spec.ts
#	src/app/core/statistics/usage-report-data.service.ts
#	src/app/core/submission/submission-cc-license-url-data.service.ts
#	src/app/core/submission/workspaceitem-data.service.ts
2024-03-24 15:17:57 +01:00
Alexandre Vryghem
d5cf236938 Refactored code to always encode the RequestParams 2024-03-24 13:32:25 +01:00
Alexandre Vryghem
548cc2d670 Merge remote-tracking branch 'upstream/main' into created-metadata-service-for-metadata-operations_contribute-main 2024-03-22 16:19:27 +01:00
Giuseppe Digilio
73ffa703cb Merge branch 'DURACOM-234' into DURACOM-234-ANGULAR-17 2024-03-21 17:41:58 +01:00
Yury Bondarenko
568574585b Workaround/document edge case where node can't be found by token 2024-03-21 10:35:04 +01:00
Yury Bondarenko
6e22b5376a Make rules more type-safe 2024-03-21 10:11:04 +01:00
Yury Bondarenko
b0758c23e5 Enforce plugin structure and generate documentation 2024-03-21 10:11:04 +01:00
Yury Bondarenko
e83a0cd741 Fix lint lint issues 2024-03-21 10:11:04 +01:00
Yury Bondarenko
ae50780e28 Enable linting for the lint plugins 2024-03-21 10:11:04 +01:00
Yury Bondarenko
9a27db3835 Lint e2e tests, enforce selectors 2024-03-21 10:11:04 +01:00
Yury Bondarenko
13e9808df2 Don't enforce ThemedComponent selectors in test HTML 2024-03-21 10:11:04 +01:00
Yury Bondarenko
3937be13f2 Custom ESLint rules to enforce new ThemedComponent selector convention
The following cases are covered:
- ThemedComponent wrapper selectors must not start with ds-themed-
- Base component selectors must start with ds-base-
- Themed component selectors must start with ds-themed-
- The ThemedComponent wrapper must always be used in HTML
- The ThemedComponent wrapper must be used in TypeScript _where appropriate_:
  - Required
    - Explicit usages (e.g. modal instantiation, routing modules, ...)
    - By.css selector queries (in order to align with the HTML rule)
  - Unchecked
    - Non-routing modules (to ensure the components can be declared)
    - ViewChild hooks (since they need to attach to the underlying component)

All rules work with --fix to automatically migrate to the new convention
This covers most of the codebase, but minor manual adjustment are needed afterwards
2024-03-21 10:11:04 +01:00
Alexandre Vryghem
692bb991a0 112970: Added missing breadcrumbs to create community/collection pages 2024-03-19 12:06:39 +01:00
Alexandre Vryghem
eb5acf8603 Merge branch 'w2p-112807_theme-ItemDetailPreviewFieldComponent' into minor-themed-component-fixes_contribute-main
# Conflicts:
#	src/app/my-dspace-page/my-dspace-search.module.ts
#	src/themes/custom/lazy-theme.module.ts
2024-03-16 16:16:32 +01:00
Alexandre Vryghem
7b19047a10 113169: Moved the MetadataValue#isVirtual & MetadataValue#virtualValue to the new MetadataService 2024-03-15 17:12:34 +01:00
Andrea Barbasso
1516389a76 update store 2024-03-15 16:27:42 +01:00
Andrea Barbasso
8138882efb update dependencies 2024-03-15 16:27:00 +01:00
Alexandre Vryghem
179e7e0543 113169: Renamed the service in charge of adding metadata head tags to you HTML to HeadTagService & made its methods protected to make it easier to override them 2024-03-15 16:12:22 +01:00
Andrea Barbasso
035a62c723 run ng update @angular/core@17 @angular/cli@17 --force 2024-03-15 15:55:21 +01:00
Andrea Barbasso
6dced44443 update dependencies 2024-03-15 15:51:35 +01:00
Alexandre Vryghem
e18c22e4e0 Merge remote-tracking branch 'upstream/main' into use-applied-filter-to-display-label-on-search_contribute-main
Conflicts:
	src/app/core/services/route.service.spec.ts
	src/app/core/shared/search/search-configuration.service.spec.ts
	src/app/core/shared/search/search-configuration.service.ts
	src/app/core/shared/search/search-filter.service.ts
	src/app/shared/search/models/search-query-response.model.ts
	src/app/shared/search/search-filters/search-filter/search-facet-filter-options/search-facet-option/search-facet-option.component.spec.ts
	src/app/shared/search/search-filters/search-filter/search-facet-filter-options/search-facet-option/search-facet-option.component.ts
	src/app/shared/search/search-filters/search-filter/search-facet-filter-options/search-facet-range-option/search-facet-range-option.component.spec.ts
	src/app/shared/search/search-filters/search-filter/search-facet-filter-options/search-facet-range-option/search-facet-range-option.component.ts
	src/app/shared/search/search-filters/search-filter/search-facet-filter-options/search-facet-selected-option/search-facet-selected-option.component.spec.ts
	src/app/shared/search/search-filters/search-filter/search-facet-filter-options/search-facet-selected-option/search-facet-selected-option.component.ts
	src/app/shared/search/search-filters/search-filter/search-facet-filter-wrapper/search-facet-filter-wrapper.component.ts
	src/app/shared/search/search-filters/search-filter/search-facet-filter/search-facet-filter.component.spec.ts
	src/app/shared/search/search-filters/search-filter/search-facet-filter/search-facet-filter.component.ts
	src/app/shared/search/search-filters/search-filter/search-filter.component.ts
	src/app/shared/search/search-filters/search-filter/search-hierarchy-filter/search-hierarchy-filter.component.spec.ts
	src/app/shared/search/search-filters/search-filter/search-hierarchy-filter/search-hierarchy-filter.component.ts
	src/app/shared/search/search-filters/search-filter/search-range-filter/search-range-filter.component.spec.ts
	src/app/shared/search/search-filters/search-filter/search-range-filter/search-range-filter.component.ts
	src/app/shared/search/search-filters/search-filters.component.ts
	src/app/shared/search/search-filters/themed-search-filters.component.ts
	src/app/shared/search/search-labels/search-label/search-label.component.spec.ts
	src/app/shared/search/search-labels/search-label/search-label.component.ts
	src/app/shared/search/search-labels/search-labels.component.ts
	src/app/shared/search/search-sidebar/search-sidebar.component.html
	src/app/shared/search/search-sidebar/search-sidebar.component.ts
	src/app/shared/search/search-sidebar/themed-search-sidebar.component.ts
	src/app/shared/search/search.component.ts
	src/app/shared/search/search.module.ts
	src/app/shared/testing/search-configuration-service.stub.ts
2024-03-14 18:01:52 +01:00
Giuseppe Digilio
6e4589b8c3 Merge branch 'main' into main-optimize-metadata-represenation-rendering
# Conflicts:
#	src/app/item-page/simple/field-components/specific-field/item-page-field.component.ts
#	src/app/item-page/simple/metadata-representation-list/metadata-representation-list.component.ts
2024-03-13 16:18:28 +01:00
max.nuding
6aacc1232c Fix spec imports 2024-03-13 15:17:22 +01:00
max.nuding
dbf2964160 Fix linting issues 2024-03-13 15:11:55 +01:00
max.nuding
5e44b7e9fe Merge branch 'main' into regex-error-messages 2024-03-13 14:49:51 +01:00
Nona Luypaert
6764006253 112807: Theme ItemDetailPreviewFieldComponent 2024-03-11 11:58:01 +01:00
Alexandre Vryghem
c23500b7fa Merge remote-tracking branch 'alex/create-themable-comcolpage-content_contribute-7.4' into minor-themed-component-fixes_contribute-main
# Conflicts:
#	src/app/browse-by/browse-by-metadata-page/browse-by-metadata-page.component.html
#	src/app/collection-page/collection-page.component.html
#	src/app/community-page/community-page.component.html
#	src/app/shared/comcol/comcol.module.ts
2024-03-09 14:40:48 +01:00
Alexandre Vryghem
bb490f827b Merge remote-tracking branch 'contributions/w2p-107950_themed-metadata-import-page-component' into minor-themed-component-fixes_contribute-main
# Conflicts:
#	src/app/admin/admin-routing.module.ts
#	src/app/admin/admin.module.ts
#	src/themes/custom/lazy-theme.module.ts
2024-03-09 14:19:47 +01:00
Alexandre Vryghem
a18bcb7493 Merge remote-tracking branch 'alex/memory-leak-fixes_contribute-7.6' into minor-themed-component-fixes_contribute-main
# Conflicts:
#	src/app/item-page/edit-item-page/item-bitstreams/item-edit-bitstream-bundle/item-edit-bitstream-bundle.component.ts
#	src/app/item-page/edit-item-page/item-bitstreams/item-edit-bitstream-drag-handle/item-edit-bitstream-drag-handle.component.ts
#	src/app/item-page/edit-item-page/item-bitstreams/item-edit-bitstream/item-edit-bitstream.component.ts
2024-03-09 13:53:27 +01:00
Alexandre Vryghem
c2c9d28ff2 Merge branch 'minor-themed-component-fixes_contribute-7.6' into minor-themed-component-fixes_contribute-main
# Conflicts:
#	src/themes/custom/app/shared/comcol-page-browse-by/comcol-page-browse-by.component.ts
#	src/themes/custom/app/shared/comcol-page-handle/comcol-page-handle.component.ts
#	src/themes/custom/lazy-theme.module.ts
2024-03-09 13:51:41 +01:00
Alexandre Vryghem
a6a9e93167 Merge remote-tracking branch 'upstream/main' into theme-fixes_contribute-main
# Conflicts:
#	src/app/shared/object-collection/shared/listable-object/listable-object-component-loader.component.spec.ts
#	src/app/shared/object-list/item-list-element/item-types/item/item-list-element.component.spec.ts
#	src/app/shared/object-list/item-list-element/item-types/item/item-list-element.component.ts
2024-03-09 04:24:05 +01:00
Alexandre Vryghem
d8a8235846 Merge remote-tracking branch 'upstream/main' into fix-broken-item-mapper-pagination_contribute-main
# Conflicts:
#	src/app/collection-page/collection-item-mapper/collection-item-mapper.component.ts
2024-03-09 04:11:39 +01:00
Jens Vannerum
f9c8103266 111326: update to new lint standards 2024-03-08 17:14:01 +01:00
Jens Vannerum
dbd9bf6f32 Merge remote-tracking branch 'dspaceMain/main' into w2p-111326_fix-status-code-object-not-found-7.4 2024-03-08 16:55:42 +01:00
Davide Negretti
e2fa27fc74 [DURACOM-195] fixes (align with 7.x) 2024-03-07 19:31:05 +01:00
Yury Bondarenko
c8954da9f7 Merge remote-tracking branch 'origin/main' into fix-versioning-button 2024-03-07 10:10:45 +01:00
Giuseppe Digilio
91de2e78bc Avoid metadata representation element is rendered twice when checking the browse configuration 2024-03-05 17:18:25 +01:00
Vincenzo Mecca
794eb6bc59 [DSC-1111] [DURACOM-235] Fixes item cache refresh in comcol-form 2024-03-04 12:04:47 +01:00
lotte
a63a69defc Merge remote-tracking branch 'origin/main' into multiline-search-filter-badge_main 2024-03-04 10:49:01 +01:00
Yury Bondarenko
0f465ac960 Merge remote-tracking branch 'origin/main' into fix-versioning-button 2024-03-01 12:19:08 +01:00
Alexandre Vryghem
ae745ac48c Merge branch 'memory-leak-fixes_contribute-7.4' into memory-leak-fixes_contribute-7.6 2024-02-29 19:55:05 +01:00
Alexandre Vryghem
7abf37cbea Fixed some components not destroying their ViewContainerRef 2024-02-29 19:45:55 +01:00
Mattia Vianelli
a059c31bad DURACOM-235 Update comcol-metadata.component.ts and tests 2024-02-26 12:18:35 +01:00
Pierre Lasou
46df7e805e Update fr.json5 to adresse reviewer feedback 2024-02-23 13:32:06 -05:00
Giuseppe Digilio
9d490451d1 [DURACOM-235] improvement of redirects logic 2024-02-23 12:04:46 +01:00
Pierre Lasou
c4548e63ca Update fr.json5 to add batch upload labels
Addition of batch upload labels (ZIP, SAF)
2024-02-22 16:06:43 -05:00
Pierre Lasou
e747520646 Update fr.json5 to add access conditions labels
Changes to the labels related to access control and access conditions.
2024-02-22 15:35:18 -05:00
Mattia Vianelli
be452316a8 DURACOM-235 Removed extra navigation that was breaking community edit behaviour 2024-02-22 11:16:36 +01:00
Mattia Vianelli
3b884fedb1 Merge remote-tracking branch 'remotes/origin/main' into DURACOM-235 2024-02-21 17:32:36 +01:00
Jens Vannerum
ab90c7a733 111326: return not found status code on missing identifiers 2024-02-21 15:38:23 +01:00
Mattia Vianelli
e3b19e4e9f DURACOM-235 added missing import and service 2024-02-21 13:12:58 +01:00
Mattia Vianelli
e71b54c79d DSC-1111 Fixed issue on create comcol 2024-02-20 17:23:48 +01:00
Mattia Vianelli
95a9d2aa47 Removed unused parts 2024-02-19 14:34:51 +01:00
Mattia Vianelli
901234777b DSC-1111 Removed unused method 2024-02-19 14:32:30 +01:00
Mattia Vianelli
ea1a8db8e9 DSC-1111 These 2 changes with the finish emit is needed, else when changing logo and then editing a field we do not get the notification and the navigateToHomePage 2024-02-19 14:32:29 +01:00
Mattia Vianelli
0b3536de8c DSC-1111 Removed left over label 2024-02-19 14:32:29 +01:00
Mattia Vianelli
e6fe9dd391 DSC-1111 Working uploader, cache refresh and retrieve for the updated dso containing the logo, new confirmationmodal 2024-02-19 14:32:29 +01:00
Giuseppe Digilio
795b0a37b4 [DSC-1111] Fix issue with wrong cache reference 2024-02-19 14:32:29 +01:00
Andrea Barbasso
378d0b2a29 Revert "[DSC-1111] fix deletion - upload - deletion flow"
This reverts commit 618151faaf88ea8366c4243dab33a628582cc98c.
2024-02-19 14:32:29 +01:00
Andrea Barbasso
f48eb5dcb8 [DSC-1111] fix deletion - upload - deletion flow 2024-02-19 14:32:29 +01:00
Mattia Vianelli
8165b5feee DSC-1111 Moved logo update to a specific method instead of the generic onsubmit 2024-02-19 14:32:28 +01:00
Giuseppe Digilio
6d98bf9d3a [DSC-1111] Start implementation refactoring 2024-02-19 14:32:27 +01:00
Andrea Barbasso
b017f9ad16 [DSC-1111] fix logo not showing after upload 2024-02-19 14:32:27 +01:00
Sondissimo
0086cf78e9 DSC-1111 Synced with main 2024-02-19 14:32:27 +01:00
Sondissimo
dd5e4de97a DSC-1111 Button is now type button, the trailing space has been removed 2024-02-19 14:27:49 +01:00
Sondissimo
2ae82fb07a DSC-1111 Provided buttons next to the logo delete to save changes in the edit community page, also now the file upload is started automatically 2024-02-19 14:27:49 +01:00
Sondissimo
ab52cdb158 DSC-1111 Provided buttons next to the logo upload/delete to save changes in the edit community page 2024-02-19 14:27:49 +01:00
Nona Luypaert
325728de8f 112198: Ensure relationship requests are sent one by one
- remove (de)select all buttons in DynamicLookupRelationSearchTab
- add requestQueue to RelationshipEffects
2024-02-19 11:09:05 +01:00
Alexandre Vryghem
7bf0983328 Fixed component still using the old ds-thumbnail 2024-02-18 21:04:24 +01:00
Alexandre Vryghem
8bf7e4fb5a Added ItemListPreviewComponent template to custom theme 2024-02-18 21:04:24 +01:00
Alexandre Vryghem
5d123277b0 Moved custom theme ComcolPageBrowseByComponent & ComcolPageHandleComponent to their correct folder 2024-02-18 21:03:23 +01:00
Alexandre Vryghem
7ee425e4a3 111103: Added SearchComponent to custom theme in order to easily theme it 2024-02-18 21:03:22 +01:00
Alexandre Vryghem
737195c223 110889: Made the SearchLabelLoaderComponent extend AbstractComponentLoaderComponent 2024-02-17 00:05:02 +01:00
Alexandre Vryghem
386a1c92b7 Merge branch 'use-applied-filter-to-display-label-on-search_contribute-7.6' into use-applied-filter-to-display-label-on-search_contribute-main 2024-02-16 21:56:33 +01:00
Alexandre Vryghem
5ec0880d7d 110889: Added the new EventEmitters to the ThemedSearchFiltersComponent & ThemedSearchSidebarComponent 2024-02-16 21:55:17 +01:00
Alexandre Vryghem
32ff1dbe13 Merge remote-tracking branch 'upstream/main' into use-applied-filter-to-display-label-on-search_contribute-main
# Conflicts:
#	src/app/core/shared/search/search-filter.service.ts
#	src/app/shared/search/search-filters/search-filter/search-facet-filter-wrapper/search-facet-filter-wrapper.component.ts
#	src/app/shared/search/search-filters/search-filter/search-facet-filter/search-facet-filter.component.spec.ts
#	src/app/shared/search/search-filters/search-filter/search-facet-filter/search-facet-filter.component.ts
#	src/app/shared/search/search-filters/search-filter/search-filter.component.ts
#	src/app/shared/search/search-filters/search-filter/search-hierarchy-filter/search-hierarchy-filter.component.spec.ts
#	src/app/shared/search/search-filters/search-filter/search-hierarchy-filter/search-hierarchy-filter.component.ts
#	src/app/shared/search/search-filters/search-filter/search-range-filter/search-range-filter.component.spec.ts
#	src/app/shared/search/search-filters/search-filter/search-range-filter/search-range-filter.component.ts
#	src/app/shared/search/search-filters/search-filters.component.html
2024-02-16 21:37:05 +01:00
Alexandre Vryghem
e9fe0a3cb8 Merge branch 'use-applied-filter-to-display-label-on-search_contribute-7.6' into use-applied-filter-to-display-label-on-search_contribute-main 2024-02-15 19:48:59 +01:00
Alexandre Vryghem
f655777bd6 Merge branch 'use-applied-filter-to-display-label-on-search_contribute-7.4' into use-applied-filter-to-display-label-on-search_contribute-7.6
# Conflicts:
#	src/app/shared/search/search-filters/search-filter/search-facet-filter-options/search-facet-option/search-facet-option.component.html
#	src/app/shared/search/search-filters/search-filter/search-facet-filter-options/search-facet-option/search-facet-option.component.spec.ts
#	src/app/shared/search/search-filters/search-filter/search-facet-filter-options/search-facet-selected-option/search-facet-selected-option.component.html
#	src/app/shared/search/search-filters/search-filter/search-hierarchy-filter/search-hierarchy-filter.component.spec.ts
#	src/app/shared/search/search-filters/search-filter/search-range-filter/search-range-filter.component.ts
#	src/app/shared/search/search-labels/search-label/search-label.component.spec.ts
#	src/app/shared/search/search-labels/search-label/search-label.component.ts
#	src/app/shared/search/search-labels/search-labels.component.ts
#	src/app/shared/search/search-sidebar/search-sidebar.component.html
#	src/app/shared/search/search.component.html
#	src/app/shared/search/search.component.ts
#	src/app/shared/search/search.module.ts
2024-02-15 15:23:17 +01:00
Alexandre Vryghem
a6675b8983 111731: Remove empty arrays from query Params, since they can cause the labels to temporarily display undefined for a few milliseconds 2024-02-15 13:21:36 +01:00
Alexandre Vryghem
47f89a6f9d 111731: Moved common remove/add queryParam logic for facet option/label to routeService 2024-02-15 13:21:36 +01:00
Alexandre Vryghem
dca62d6eb1 111731: Fixed double requests being sent when selecting a range with the absolute min/max (1950/current year)
This was caused because the search labels updated the query parameters, even when they were already updated by the facets
2024-02-15 13:21:36 +01:00
Alexandre Vryghem
10dfedd0a2 111731: Created search label loader and created new date label component 2024-02-15 13:21:36 +01:00
Alexandre Vryghem
9d40225feb 111731: Also emit the AppliedFilter for date values 2024-02-15 13:21:36 +01:00
Alexandre Vryghem
58a15329ac 111731: Renamed variables for clarity 2024-02-15 13:21:35 +01:00
Alexandre Vryghem
eb33ae7cb8 111731: Simplified retrieveFilterValues by removing the RemoteData around all the FacetValues since they were not used 2024-02-15 13:21:35 +01:00
Alexandre Vryghem
f95c941c49 111731: Simplified the response of the retrieveFilterValues#facetValues$ by removing the page option 2024-02-15 13:21:35 +01:00
Alexandre Vryghem
1eadb412a6 111731: Made the SearchLabelComponent use the AppliedFilter to display the label instead of value 2024-02-15 13:21:35 +01:00
Alexandre Vryghem
61e94664c8 111731: Display the authority label in the search labels 2024-02-15 13:21:34 +01:00
Alexandre Vryghem
10c98957a6 Merge remote-tracking branch 'upstream/main' into theme-fixes_contribute-main
# Conflicts:
#	src/app/shared/mydspace-actions/claimed-task/switcher/claimed-task-actions-loader.component.ts
#	src/app/shared/object-collection/shared/listable-object/listable-object-component-loader.component.spec.ts
2024-02-10 00:19:53 +01:00
Alexandre Vryghem
b34d90deff 111731: Display the authority label in the search facets 2024-02-08 12:55:56 +01:00
Alexandre Vryghem
a0d98be6d7 Merge branch 'theme-fixes_contribute-7.4' into theme-fixes_contribute-7.6 2024-02-07 13:49:32 +01:00
Alexandre Vryghem
04cf1419ea 111679: Restored missing inAndOutputNames on ClaimedTaskActionsLoaderComponent 2024-02-07 13:43:50 +01:00
Yury Bondarenko
53bb38f713 Merge remote-tracking branch 'ybnd/fix-versioning-button-7.6' into fix-versioning-button 2024-02-07 11:52:14 +01:00
Yury Bondarenko
adb2e31026 Always wait for correct draft status, fix spelling 2024-02-07 11:13:53 +01:00
Yury Bondarenko
9f39358efb Clean up VersionHistoryDataService changes 2024-02-07 10:50:16 +01:00
Art Lowel
06025e42e0 embed the item to submission patch request to fix issue where the submission form would revert to the previous data on save 2024-02-06 16:53:30 +01:00
Alexandre Vryghem
01f97a623f 111373: Fixed Font Awesome CSS Pseudo-elements for v6.x 2024-01-30 11:08:59 +01:00
Alexandre Vryghem
106182d5fd 111321: Made ComColPageContentComponent themeable 2024-01-26 11:35:13 +01:00
Sascha Szott
a238a28376 improved layout of feedback form (increase vertical spacing) 2024-01-25 17:16:48 +01:00
Andrea Barbasso
2afa473cfb [DURACOM-224] fix infinite scroll 2024-01-23 17:19:50 +01:00
Nona Luypaert
22b596b3aa 107950: Theme MetadataImportPageComponent 2024-01-22 15:19:49 +01:00
Yury Bondarenko
591cf03249 Merge remote-tracking branch 'origin/main' into fix-versioning-button 2024-01-22 14:56:17 +01:00
Yury Bondarenko
9960b93f58 Fix cache invalidation for versioning 2024-01-22 14:56:00 +01:00
Giuseppe Digilio
585c49caef [DURACOM-208] add showAdd flag in vocabulary-treeview-modal.component 2024-01-11 13:34:26 +01:00
Giuseppe Digilio
1fd0d35d9b Merge branch 'main' into main-restore-hierarchical-tree-original-behaviour
# Conflicts:
#	src/app/shared/form/vocabulary-treeview/vocabulary-treeview.component.html
#	src/app/shared/form/vocabulary-treeview/vocabulary-treeview.component.ts
2024-01-10 15:09:13 +01:00
Bram Luyten
fbd35296f0 Update robots.txt.ejs
Fix for issue #2709
2023-12-12 11:16:39 +01:00
Ricardo Saraiva
c4142e7a80 Update pt-PT.json5 2023-12-09 19:02:20 +00:00
Ricardo Saraiva
6c5e971dc1 Update pt-PT.json5 2023-12-09 18:50:21 +00:00
Ricardo Saraiva
3262e00d6e Update pt-PT.json5 2023-12-09 18:46:05 +00:00
Ricardo Saraiva
38eacf31bf Update pt-PT.json5 2023-12-09 18:41:06 +00:00
Ricardo Saraiva
18085698b2 Update pt-PT.json5
Addition of new translation keys (following DSpace 7.6.1 release) & revision/improvement of some of the already existing.
2023-12-09 18:22:02 +00:00
Ricardo Saraiva
02792d28bc Update pt-PT.json5
Addition of new translation keys (following DSpace 7.6.1 release) & revision/improvement of some of the already existing.
2023-12-09 18:05:38 +00:00
max.nuding
8de483a308 enable type-bind for checkbox inputs during submission 2023-12-06 09:57:43 +01:00
lotte
b11fa60d15 Merge branch 'w2p-108595_multiline-search-filter-badge' into multiline-search-filter-badge_main 2023-11-30 12:14:51 +01:00
lotte
a026c65a3c Removed unnecessary change 2023-11-30 12:14:24 +01:00
lotte
40c13e6869 Merge remote-tracking branch 'origin/main' into multiline-search-filter-badge_main 2023-11-30 10:53:16 +01:00
lotte
f4dc8ca3d2 108595: fix for overflowing search filter badge selection 2023-11-28 19:17:23 +01:00
Giuseppe Digilio
a989bebf50 [DURACOM-208] Remove unused dependency 2023-11-22 19:34:15 +01:00
Giuseppe Digilio
9268ef9853 [DURACOM-208] Restore functionality to open the tree on the given item 2023-11-22 15:43:51 +01:00
Giuseppe Digilio
1197474009 [DURACOM-208] Add a property to be able to provide description message 2023-11-22 15:42:51 +01:00
Alexandre Vryghem
d00fc5d9d3 108586: Fixed ItemListElementComponent not pointing to the ItemSearchResultListElementComponent from the themes folder when present 2023-11-18 11:51:59 +01:00
Alexandre Vryghem
45e8977db7 Fixed pagination issues on item mapper 2023-11-15 23:31:54 +01:00
Tim Donohue
d8ed267e5f Update version tag for release 2023-11-15 14:33:16 -06:00
max.nuding
b5dbaada49 Remove unnecessary import 2023-11-15 13:43:16 +01:00
max.nuding
0ae2b52c72 Fix tests to include translationservice dependency 2023-11-15 13:27:58 +01:00
max.nuding
cb7b8b3d22 Submission form now displays custom messages for regex validated fields if they exist 2023-11-15 10:51:01 +01:00
Tim Donohue
fdcaeb592c Merge pull request #2639 from tdonohue/port_2610_to_dspace-7_x
[Port dspace-7_x] Fixed menu not updating when a new sub section is added after rendering has already completed
2023-11-13 17:00:20 -06:00
Tim Donohue
8872fd3340 Merge pull request #2638 from DSpace/backport-2633-to-dspace-7_x
[Port dspace-7_x] Edit-item view: random order of buttons in status tab
2023-11-13 16:51:21 -06:00
Tim Donohue
959d592394 Merge pull request #2637 from DSpace/backport-2632-to-dspace-7_x
[Port dspace-7_x] Fixes "some item edit pages are accessible by anonymous users"
2023-11-13 16:40:19 -06:00
Alexandre Vryghem
c98e8f6504 107902: Created test case for 2f26e686cc 2023-11-13 16:36:05 -06:00
Kristof De Langhe
e293f3db52 107685: menu-component re-render section on store update 2023-11-13 16:35:16 -06:00
Vlad Nouski
651b6a7d76 refactor: code
(cherry picked from commit fbbbc18844)
2023-11-13 22:05:45 +00:00
Vlad Nouski
dd554590b1 fix: random order of buttons in status tab
(cherry picked from commit 35f8b55f58)
2023-11-13 22:05:45 +00:00
Tim Donohue
0a3502e9cc Merge pull request #2636 from DSpace/backport-2562-to-dspace-7_x
[Port dspace-7_x] Fix match theme by handle with canonical prefix https://hdl.handle.net/ not working
2023-11-13 16:00:02 -06:00
Vlad Nouski
94866cab45 [DURACOM-202] refactor: code
(cherry picked from commit 6f64db1645)
2023-11-13 20:34:42 +00:00
Vlad Nouski
a5a59dcf8b [DURACOM-202] refactor: code
(cherry picked from commit b6d515ff09)
2023-11-13 20:34:42 +00:00
Vlad Nouski
8f9a358afb [DURACOM-202] feature: item edit pages are accessible by administrator
(cherry picked from commit ccf1cc4547)
2023-11-13 20:34:42 +00:00
Alexandre Vryghem
0cd72e4917 107671: Fixed theme matching by handle not working in production mode
(cherry picked from commit 7529ed8b35)
2023-11-13 20:21:10 +00:00
Alexandre Vryghem
1222ed45ca 107671: Fixed bug where config property would still sometimes be undefined whey calling the ngOnDestroy in the ThemedComponent
(cherry picked from commit 4e54cca600)
2023-11-13 20:21:10 +00:00
Alexandre Vryghem
27f3fc310f 107671: Split Theme model & ThemeConfig classes in separate files to prevent circular dependencies
(cherry picked from commit da8880e5ba)
2023-11-13 20:21:10 +00:00
Alexandre Vryghem
d3fdfebde1 107671: Fix handle theme not working with canonical prefix https://hdl.handle.net/
(cherry picked from commit a7faf7d449)
2023-11-13 20:21:10 +00:00
Tim Donohue
626cc30738 Merge pull request #2635 from DSpace/backport-2579-to-dspace-7_x
[Port dspace-7_x] adding new access-status-list-element-badge css classes
2023-11-13 13:19:23 -06:00
Tim Donohue
64364c9ddb Merge pull request #2634 from DSpace/backport-2630-to-dspace-7_x
[Port dspace-7_x] Fix handle redirect not working with custom nameSpace
2023-11-13 13:18:52 -06:00
Paulo Graça
a276f415a8 adding ngOnDestroy for dealing with unsubscribe
(cherry picked from commit 75b788d05b)
2023-11-13 17:30:28 +00:00
Paulo Graça
59c4d59e45 remove replaceAll and use an object property
(cherry picked from commit c7eae9242a)
2023-11-13 17:30:28 +00:00
Paulo Graça
a12488c827 new accessStatusClass atribute
(cherry picked from commit 6378dbec4a)
2023-11-13 17:30:28 +00:00
Paulo Graça
ff03243298 Create new access-status-badge.component.scss
(cherry picked from commit 3bf2eb1997)
2023-11-13 17:30:28 +00:00
Paulo Graça
116bfbded1 adding new access-status-list-element-badge css classes
(cherry picked from commit e847e4ef51)
2023-11-13 17:30:28 +00:00
Alexandre Vryghem
68cdd120c9 Fix handle redirect not working with custom nameSpace
(cherry picked from commit b894dce3b0)
2023-11-13 17:22:53 +00:00
Tim Donohue
7d5c4560cd Merge pull request #2629 from tdonohue/port_2620_to_dspace-7_x
[Port dspace-7_x] Fix for repeatable date field labels
2023-11-10 17:20:40 -06:00
Tim Donohue
755e89dffa Merge pull request #2628 from DSpace/backport-2625-to-dspace-7_x
[Port dspace-7_x] Bump axios from 0.27.2 to 1.6.0
2023-11-10 17:15:22 -06:00
lotte
8458d589b2 Fixed test 2023-11-10 16:40:31 -06:00
lotte
30ce8440e1 108045: Fix for repeatable date field labels 2023-11-10 16:39:38 -06:00
dependabot[bot]
c8d98ec0b1 Bump axios from 0.27.2 to 1.6.0
Bumps [axios](https://github.com/axios/axios) from 0.27.2 to 1.6.0.
- [Release notes](https://github.com/axios/axios/releases)
- [Changelog](https://github.com/axios/axios/blob/v1.x/CHANGELOG.md)
- [Commits](https://github.com/axios/axios/compare/v0.27.2...v1.6.0)

---
updated-dependencies:
- dependency-name: axios
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
(cherry picked from commit ef9f31d3c6)
2023-11-10 22:23:44 +00:00
Tim Donohue
6975fd15d5 Merge pull request #2627 from DSpace/backport-2545-to-dspace-7_x
[Port dspace-7_x] Fix "Edit Group" page always requests all member Subgroups & EPersons
2023-11-10 15:14:27 -06:00
Tim Donohue
d305e6096a Address feedback. Run empty search on init. Reorder sections to list current members before add members (for both eperson and groups)
(cherry picked from commit 9117ac005f)
2023-11-10 19:03:47 +00:00
Tim Donohue
37ae09acd1 Remove seemingly unnecessary page reload after new search.
(cherry picked from commit d163db13f2)
2023-11-10 19:03:47 +00:00
Tim Donohue
8cc36d7056 Refactor subgroups-list component's "search()" to act same as member-list component's "search()". Avoids reloading the page as frequently.
(cherry picked from commit 2eb1a17e4e)
2023-11-10 19:03:47 +00:00
Tim Donohue
4a1f2a1b75 Refactor members-list and subgroups-list components to use new isNotMemberOf endpoints (via services)
(cherry picked from commit 8a10888d2a)
2023-11-10 19:03:47 +00:00
Tim Donohue
1f1dc59f8b Fix subgroups-list specs so they align with new members-list specs
(cherry picked from commit 64f968b246)
2023-11-10 19:03:47 +00:00
Tim Donohue
f0b4239df9 Also remove unnecessary EpersonDtoModel from extending ReviewersListComponent. Remove "memberOfGroup" from EpersonDtoModel as it is no longer used
(cherry picked from commit b598f1b5ca)
2023-11-10 19:03:47 +00:00
Tim Donohue
753a31f7f4 Remove unnecessary EpersonDtoModel. Rework code and tests to use EPerson instead.
(cherry picked from commit bffae54b10)
2023-11-10 19:03:47 +00:00
Tim Donohue
ac6a7be7aa Remove "isMemberOfGroup()" from members-list component.
(cherry picked from commit 43d37196fb)
2023-11-10 19:03:47 +00:00
Tim Donohue
c02cfff8da Fix bug where linked Community/Collection info was sometimes listed many times in a row
(cherry picked from commit 229236634a)
2023-11-10 19:03:47 +00:00
Tim Donohue
d7ccce1f8f Remove isSubgroupOfGroup() functionality as it loads every subgroup at once. Bad peformance for large groups
(cherry picked from commit 97479a2945)
2023-11-10 19:03:47 +00:00
Tim Donohue
139446118b Limit getMembers() and getSubgroups() to only fetching one object. These lists are only used to find the size of each
(cherry picked from commit 0da7c15f2e)
2023-11-10 19:03:47 +00:00
Tim Donohue
787feae631 Merge pull request #2626 from tdonohue/port_2607_to_dspace-7_x
[Port dspace-7_x] Added skip to main content button
2023-11-10 11:43:15 -06:00
Alexandre Vryghem
e545c42aae Added skip to main content button 2023-11-10 10:59:57 -06:00
Tim Donohue
d166b5e37a Merge pull request #2623 from DSpace/backport-2611-to-dspace-7_x
[Port dspace-7_x] Communities & Collections tree browser updates - Replaced #2597
2023-11-10 09:55:38 -06:00
Tim Donohue
61ded72183 Merge pull request #2616 from DSpace/backport-2574-to-dspace-7_x
[Port dspace-7_x] Support type-bind of elements based on repeatable list type-bound element (CHECKBOX_GROUP)
2023-11-10 09:15:59 -06:00
William Welling
b6d8c7d18e Filter expanded nodes by id
Co-Authored-By: Art Lowel <1567693+artlowel@users.noreply.github.com>
(cherry picked from commit dc2ef989e6)
2023-11-10 15:14:28 +00:00
William Welling
1d0ca04992 Update condition to render show more node
`loadingNode` ends up being the current `node` after clicking it preventing it from rendering when more pages available.

Update community list component spec

Make the show more flat node id unique

The nodes with same id are conflicting when added to the tree. Clicking on the second with same id places the show more button under the wrong branch and expands the wrong page.

(cherry picked from commit 11d3771e72)
2023-11-10 15:14:28 +00:00
Tim Donohue
34b91a7dea Merge pull request #2617 from DSpace/backport-2594-to-dspace-7_x
[Port dspace-7_x] Media viewer controls rendered behind DSpace header
2023-11-10 06:49:12 -06:00
Tim Donohue
203dcbebda Merge pull request #2612 from DSpace/backport-2596-to-dspace-7_x
[Port dspace-7_x] Fix cache issue when depositing a submission
2023-11-09 16:53:28 -06:00
Davide Negretti
c6ade09e4a [DURACOM-180] Prevent header from covering media viewer controls (base theme)
(cherry picked from commit c042cd8d11)
2023-11-09 22:44:28 +00:00
Davide Negretti
5f46b638e4 [DURACOM-180] Prevent header from covering media viewer controls (dspace theme)
(cherry picked from commit 0208a78437)
2023-11-09 22:44:28 +00:00
Davide Negretti
0d0c2dac17 [DURACOM-195] Simplify vertical spacing in header and breadcrumbs
(cherry picked from commit a3e6d9b09a)
2023-11-09 22:44:28 +00:00
Andreas Mahnke
bc21085398 Support type-bind of elements based on repeatable list type-bound element (CHECKBOX_GROUP)
(cherry picked from commit 09aaa46875)
2023-11-09 22:04:12 +00:00
Tim Donohue
137a83e7f1 Merge pull request #2614 from DSpace/backport-2595-to-dspace-7_x
[Port dspace-7_x] Add UI nameSpace context path to Mirador viewer path
2023-11-09 13:40:03 -06:00
Alan Orth
31ee580047 Merge pull request #2615 from DSpace/backport-2602-to-dspace-7_x
[Port dspace-7_x] Support for freetext values in submission for vocabulary controlled `onebox` and `tag` types
2023-11-09 22:39:53 +03:00
Jens Vannerum
e815b1d938 108055: add user input to tag list
(cherry picked from commit aac58e612d)
2023-11-09 18:56:37 +00:00
Jens Vannerum
a758848146 108055: fix issue 8686: unable to enter freetext values in the submission form for vocabulary
(cherry picked from commit 0dcf6cb885)
2023-11-09 18:56:37 +00:00
William Welling
fba30781de Add UI nameSpace context path to Mirador viewer path
(cherry picked from commit 3228c457a3)
2023-11-09 17:45:22 +00:00
Giuseppe Digilio
4b4c1dc08a [DURACOM-197] Fix cache issue when depositing a submission
(cherry picked from commit f992ff6671)
2023-11-09 17:31:52 +00:00
Tim Donohue
5eb62e22eb Merge pull request #2605 from DSpace/backport-2364-to-dspace-7_x
[Port dspace-7_x] Utility gap-* classes for flexbox
2023-11-08 16:57:59 -06:00
Tim Donohue
fbe4732450 Merge pull request #2590 from marcoaureliocardoso/dspace-7_x
fix(pt-BR.json5): fix and update the language file
2023-11-08 16:49:38 -06:00
Davide Negretti
c5f22ab959 [DURACOM-177] Use gap-* classes on navbar buttons
(cherry picked from commit a35629536e)
2023-11-08 22:15:29 +00:00
Davide Negretti
75e45cc8c2 [DURACOM-177] gap-* classes
(cherry picked from commit 930a381e4a)
2023-11-08 22:15:29 +00:00
Tim Donohue
5bb451a649 Merge pull request #2604 from DSpace/backport-2603-to-dspace-7_x
[Port dspace-7_x] Fix e2e tests by running in production mode & using a user-agent for statistics
2023-11-08 13:13:21 -06:00
Tim Donohue
042c0f06f1 Specify user agent to avoid being detected as a "bot" by backend
(cherry picked from commit 72cda41731)
2023-11-08 18:25:13 +00:00
Tim Donohue
f3f87dc928 Ensure e2e tests run in production mode
(cherry picked from commit 7dcaae8465)
2023-11-08 18:25:13 +00:00
Tim Donohue
4a10d37d0d Merge pull request #2598 from DSpace/backport-2593-to-dspace-7_x
[Port dspace-7_x] Fix "Submission input type date doesn't work properly once a value has been set"
2023-11-03 15:56:55 -05:00
Alisa Ismailati
c99487babc [DURACOM-194] fixed year input value on input type date
(cherry picked from commit c412c1fa13)
2023-11-03 20:15:37 +00:00
Alisa Ismailati
e54723aa85 Merged in DSC-106 (pull request #643)
[DSC-106] Date input usable via keyboard using tab

Approved-by: Vincenzo Mecca
(cherry picked from commit 543b4ad576)
2023-11-03 20:15:37 +00:00
Marco Aurelio Cardoso
8b48a0b118 fix(pt-BR.json5): fix and update the language file and previous errors
Fix and update the pt-BR language file and the previous errors
2023-10-29 07:18:04 -03:00
Marco Aurelio Cardoso
e1494c0518 fix(pt-BR.json5): fix and update the language file
Fix and update the pt-BR language file
2023-10-29 06:49:20 -03:00
Tim Donohue
701c6e36b0 Merge pull request #2589 from DSpace/backport-2580-to-dspace-7_x
[Port dspace-7_x]   Check cssRules before css variables are read from stylesheet (again)
2023-10-27 13:51:12 -05:00
Gantner, Florian Klaus
c6b66b62e3 more error-prone check of cssRules existence before css variables are get from stylesheet
check the existence off cssRules property before the variables are readed from this stylesheet
https://github.com/DSpace/dspace-angular/issues/2450

(cherry picked from commit 4dd334f2e7)
2023-10-27 15:28:08 +00:00
Tim Donohue
6a182c32e1 Merge pull request #2585 from tdonohue/port_2442_to_7x
[Port dspace-7_x] New themed components & minor CSS fixes
2023-10-26 16:56:03 -05:00
Alexandre Vryghem
b8079a350c New themed components & minor CSS fixes (#2442)
* 100839: Created themeable BrowseByComponent

* 100839: Added themed BrowseByComponent to custom theme

* 100839: Added themed BrowseEntryListElementComponent to custom theme

* Added PersonComponent to custom theme

* Themed LogInComponent

* Fix focus on navbar using different color

* Fix ccLicense checkbox margin

* Fix long search facets name not displaying correctly

* Removed RecentItemListComponent's unnecessary float causing alignment issues when adding components underneath it

* Themed RegisterEmailFormComponent
2023-10-26 16:07:24 -05:00
Tim Donohue
3e9f3aba92 Merge pull request #2584 from DSpace/backport-2441-to-dspace-7_x
[Port dspace-7_x] Minor css variables fixes for header & navbar
2023-10-26 15:02:26 -05:00
Alexandre Vryghem
e548ebcb5a Added new variables for the expandable navbar section
(cherry picked from commit 2ca2a3881f)
2023-10-26 19:03:08 +00:00
Alexandre Vryghem
166444fc50 Fixed breadcrumb padding using incorrect syntax
(cherry picked from commit 6c48238fa2)
2023-10-26 19:03:08 +00:00
Alexandre Vryghem
a40e26985d Fixed header bg color not being set in default (no) theme
(cherry picked from commit 14b1ce5e50)
2023-10-26 19:03:08 +00:00
Alexandre Vryghem
72dcfddff1 Added support for changing the color of the navbar
(cherry picked from commit f6649e1c38)
2023-10-26 19:03:08 +00:00
Tim Donohue
b9f60fa627 Merge pull request #2583 from DSpace/backport-2506-to-dspace-7_x
[Port dspace-7_x] allow insertion of multi-line scope notes in MD field registry
2023-10-26 13:25:32 -05:00
Tim Donohue
97b22c63f8 Merge pull request #2391 from alexandrevryghem/split-eperson-administration-page_contribute-maintenance-7.6
Created separate ePerson pages for create/edit
2023-10-26 13:23:15 -05:00
Sascha Szott
163661a956 allow to insert multi-line scope notes in MD field registry
(cherry picked from commit 5bc5dd859e)
2023-10-26 16:56:44 +00:00
Tim Donohue
f8671e7d4b Merge pull request #2581 from DSpace/backport-2542-to-dspace-7_x
[Port dspace-7_x] Fix i18n labels and alignment in vocabulary-treeview
2023-10-26 11:24:11 -05:00
Tim Donohue
673f81759e Merge pull request #2464 from alexandrevryghem/i18n-cache-busting_contribute-7.6
i18n production improvements
2023-10-26 11:22:36 -05:00
Davide Negretti
e10a08ecfa [DURACOM-190] Fix alignment in vocabulary-treeview
(cherry picked from commit feb2b2be53)
2023-10-26 15:35:38 +00:00
Davide Negretti
00eb24c39d [DURACOM-190] Fix i18n labels in vocabulary-treeview
(cherry picked from commit b321d6f727)
2023-10-26 15:35:38 +00:00
Tim Donohue
3b6dd66680 Merge pull request #2458 from atmire/backport-2423-to-dspace-7_x
[Port to dspace-7_x] Fix inherit policies at item move (Angular)
2023-10-25 16:38:44 -05:00
Tim Donohue
d6951dc8e3 Merge pull request #2576 from tdonohue/port_2362_to_7x
[Port dspace-7_x] Making user menu component themeable
2023-10-25 16:06:50 -05:00
Tim Donohue
1d2cdf75e6 Merge pull request #2575 from tdonohue/port_2530_to_7x
[Port to dspace-7_x] Fix display LogInComponent turning blank when entering wrong username/password combination
2023-10-25 15:18:20 -05:00
Eike Martin Löhden
4945460382 Removed default value from inExpandableNavbar. 2023-10-25 15:16:01 -05:00
Eike Martin Löhden
2ec90b8273 Included user-menu component in custom theme. 2023-10-25 15:15:54 -05:00
Eike Martin Löhden
a4aecce865 Replaced tags for ds-user-menu. 2023-10-25 15:15:48 -05:00
Eike Martin Löhden
de826634c8 Corrected missing semicolon. 2023-10-25 15:15:41 -05:00
Eike Martin Löhden
d04d9fd250 Added themed-user-menu component. 2023-10-25 15:15:25 -05:00
Alexandre Vryghem
86657108dd Merge branch 'fix-display-order-authentication-methods_contribute-7.4' into fix-display-order-authentication-methods_contribute-7.6
# Conflicts:
#	src/app/shared/log-in/log-in.component.html
#	src/app/shared/log-in/log-in.component.ts
2023-10-25 14:27:09 -05:00
Alan Orth
73f21f21e7 Merge pull request #2571 from DSpace/backport-2553-to-dspace-7_x
[Port dspace-7_x] Added Serbian Cyrillic translation and corrected Serbian Latin translаtion
2023-10-24 22:47:50 +03:00
imilos
5ab69af71e Added Serbian cyrilic translation and corrected Serbian latin translation.
(cherry picked from commit aa9e12dcfe)
2023-10-24 18:02:41 +00:00
imilos
884e113168 Added Serbian cyrilic translation and corrected Serbian latin translation.
(cherry picked from commit ad12e5a7f2)
2023-10-24 18:02:41 +00:00
Alan Orth
a92aa05049 Merge pull request #2566 from DSpace/backport-2527-to-dspace-7_x
[Port dspace-7_x] Minor header button improvements
2023-10-23 21:57:44 +03:00
Alexandre Vryghem
d7dba4bfcf Fixed invalid html structure the ExpandableNavbarSectionComponent had an ul tag containing non-li tags
(cherry picked from commit fa56d5dfb7)
2023-10-23 17:50:43 +00:00
Alexandre Vryghem
e82a1ebedb Applied same gap between header icons in the dspace theme and made the search field non-focusable when collapsed
(cherry picked from commit 58d31dd73f)
2023-10-23 17:50:43 +00:00
Alexandre Vryghem
d7f1d37e41 Themed LangSwitchComponent
(cherry picked from commit f9b4460e70)
2023-10-23 17:50:43 +00:00
Alexandre Vryghem
d6de6fee6c Use gap instead of individual paddings for header icons
(cherry picked from commit 9f2a1d048b)
2023-10-23 17:50:43 +00:00
Tim Donohue
7dd9156375 Merge pull request #2564 from DSpace/backport-2561-to-dspace-7_x
[Port dspace-7_x] Fix RequestService test sometimes failing in CICD
2023-10-23 10:00:35 -05:00
Alexandre Vryghem
8428b0549b Fix RequestService test failing because of different lastUpdated time
(cherry picked from commit fb315335c9)
2023-10-23 13:56:07 +00:00
Tim Donohue
33c2c98757 Merge pull request #2560 from DSpace/backport-2439-to-dspace-7_x
[Port dspace-7_x] Fix Request-a-Copy grant form optional message not optional in form validation
2023-10-20 15:14:08 -05:00
Agustina Martinez
e9b70e34d5 Update email-request-copy.component.html
Message is optional: remove req in [disabled]

(cherry picked from commit 94c756d52d)
2023-10-20 20:13:00 +00:00
Tim Donohue
c3ee2ca6c1 Merge pull request #2559 from DSpace/backport-2558-to-dspace-7_x
[Port dspace-7_x] Revert 2454 "Check cssRules before css variables are read from stylesheet"
2023-10-20 12:07:43 -05:00
Tim Donohue
2834ac33a4 Revert "Check cssRules before css variables are read from stylesheet (#2454)"
This reverts commit fa79c358c0.

(cherry picked from commit 6f73b65d53)
2023-10-20 17:07:13 +00:00
Tim Donohue
1eeed36036 Merge pull request #2552 from DSpace/backport-2549-to-dspace-7_x
[Port dspace-7_x] Bump @babel/traverse from 7.21.4 to 7.23.2
2023-10-20 09:57:08 -05:00
dependabot[bot]
bc0629e004 Bump @babel/traverse from 7.21.4 to 7.23.2
Bumps [@babel/traverse](https://github.com/babel/babel/tree/HEAD/packages/babel-traverse) from 7.21.4 to 7.23.2.
- [Release notes](https://github.com/babel/babel/releases)
- [Changelog](https://github.com/babel/babel/blob/main/CHANGELOG.md)
- [Commits](https://github.com/babel/babel/commits/v7.23.2/packages/babel-traverse)

---
updated-dependencies:
- dependency-name: "@babel/traverse"
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
(cherry picked from commit 97f7a5e82a)
2023-10-19 21:45:57 +00:00
Alexandre Vryghem
d473fcdf16 Merge branch 'split-eperson-administration-page_contribute-7.6' into split-eperson-administration-page_contribute-maintenance-7.6 2023-10-19 23:01:48 +02:00
Tim Donohue
c25b80abdd Merge pull request #2504 from atmire/Angular-SRR-menu-issues
Fix Angular SSR menu issues
2023-10-19 10:19:27 -05:00
Alan Orth
b5f942b71d Merge pull request #2547 from DSpace/backport-2454-to-dspace-7_x
[Port dspace-7_x] Check cssRules before css variables are read from stylesheet
2023-10-17 22:50:14 +03:00
Gantner, Florian Klaus
21dcef0a42 checkstyle remove unused extra lines
(cherry picked from commit 5f8a9dea34)
2023-10-17 19:17:51 +00:00
Gantner, Florian Klaus
c4a60abd65 check cssRules existence before css variables are get from stylesheet
(cherry picked from commit 367cda2de0)
2023-10-17 19:17:51 +00:00
Alan Orth
fd850164f5 Merge pull request #2546 from DSpace/backport-2534-to-dspace-7_x
[Port dspace-7_x] Bump postcss from 8.4.23 to 8.4.31
2023-10-16 14:20:07 +03:00
dependabot[bot]
8f881dbb52 Bump postcss from 8.4.23 to 8.4.31
Bumps [postcss](https://github.com/postcss/postcss) from 8.4.23 to 8.4.31.
- [Release notes](https://github.com/postcss/postcss/releases)
- [Changelog](https://github.com/postcss/postcss/blob/main/CHANGELOG.md)
- [Commits](https://github.com/postcss/postcss/compare/8.4.23...8.4.31)

---
updated-dependencies:
- dependency-name: postcss
  dependency-type: direct:development
...

Signed-off-by: dependabot[bot] <support@github.com>
(cherry picked from commit 3c5079e9ce)
2023-10-16 07:36:28 +00:00
Alexandre Vryghem
a419956e2a Merge remote-tracking branch 'upstream/dspace-7_x' into split-eperson-administration-page_contribute-maintenance-7.6
# Conflicts:
#	src/app/access-control/epeople-registry/eperson-form/eperson-form.component.html
2023-10-14 17:38:26 +02:00
Alan Orth
3cb23c18e7 Merge pull request #2536 from atmire/issue-2535_hide-add-more-button-submission-if-no-disabled-sections-7.x
Issue 2535 hide add more button submission if no disabled sections 7.x
2023-10-12 09:46:14 +03:00
Alan Orth
59be2ae907 Merge pull request #2543 from DSpace/backport-2531-to-dspace-7_x
[Port dspace-7_x] Fix browse by visual bug
2023-10-12 09:17:48 +03:00
Jens Vannerum
15d2880ca4 Fix browse by visual bug
(cherry picked from commit d0b4e15db4)
2023-10-11 19:04:20 +00:00
Pascal-Nicolas Becker
c03cd03274 Merge pull request #2541 from DSpace/backport-2537-to-dspace-7_x
[Port dspace-7_x] Translate community as 'Bereich' in de.json5
2023-10-11 05:33:28 +02:00
Janne Jensen
ec86bc12bd translate community as 'Bereich' in de.json5
(cherry picked from commit 0139670371)
2023-10-10 20:40:03 +00:00
Marie Verdonck
77dd72b6ef Merge branch 'issue-2535_hide-add-more-button-submission-if-no-disabled-sections-7.4' into issue-2535_hide-add-more-button-submission-if-no-disabled-sections-7.x 2023-10-04 17:30:45 +02:00
Marie Verdonck
709848ee25 Issue#2535: Hide add more button in submission if no disabled sections 2023-10-04 17:27:04 +02:00
Alan Orth
980e254d9a Merge pull request #2528 from DSpace/backport-2385-to-dspace-7_x
[Port dspace-7_x] Move subscription button to DSO edit menu
2023-09-27 10:56:27 +03:00
Yury Bondarenko
6d195f5ffa Update DSO edit menu resolver tests
- Abstract away the different "subsections" ~ DSO type (the tests should not care about this)
  Instead, retrieve sections of interest by ID & assert whether they're there & how they should look
- Test separately for Communities, Collections & Items
- Test newly added menu section

(cherry picked from commit 18b7a9c7de)
2023-09-27 07:02:24 +00:00
Yury Bondarenko
578a427f46 Move subscription button to DSO edit menu
(cherry picked from commit c9558167b2)
2023-09-27 07:02:24 +00:00
Alan Orth
506579cd23 Merge pull request #2510 from atmire/fix-mutliple-api-calls-on-route-change
Fix multiple api calls on route change
2023-09-27 08:12:47 +03:00
Alan Orth
19eec6ac31 Merge pull request #2526 from DSpace/backport-2525-to-dspace-7_x
[Port dspace-7_x] Fix mouse cursor on language dropdown menu
2023-09-26 22:09:17 +03:00
Davide Negretti
2aab4265a5 [DURACOM-185] Fix pointer on language dropdown menu
(cherry picked from commit 6b5708cffd)
2023-09-26 18:40:11 +00:00
Art Lowel
67a6f58865 Merge branch 'fix-mutliple-api-calls-on-route-change-7.6' into fix-mutliple-api-calls-on-route-change 2023-09-26 16:56:17 +02:00
Art Lowel
d02c5397f8 Merge branch 'fix-mutliple-api-calls-on-route-change-7.6' into fix-mutliple-api-calls-on-route-change 2023-09-26 14:44:39 +02:00
DSpace Bot
77efe52f4a [Port dspace-7_x] Fix missing or wrong Italian translations (#2522)
[DURACOM-184] fix missing or wrong Italian translations

---------

Co-authored-by: Andrea Barbasso <´andrea.barbasso@4science.com´>
2023-09-26 11:04:49 +03:00
Alan Orth
83beb5474e Merge pull request #2521 from DSpace/backport-2473-to-dspace-7_x
[Port dspace-7_x] Fix some routes not using the correct baseHref
2023-09-26 10:51:51 +03:00
DSpace Bot
1c38d9259a [Port dspace-7_x] Serbian (Latin) translation (#2520)
* Serbian (latin) translation added.

---------

Co-authored-by: imilos <imilos@gmail.com>
2023-09-26 10:08:07 +03:00
Alexandre Vryghem
d6d5a2891c Fix routes not working with baseHref
(cherry picked from commit 18febff7a6)
2023-09-26 07:07:20 +00:00
Hrafn Malmquist
abd6c01a98 Merge pull request #2502 from alanorth/undo-text-capitalize
Don't capitalize metadata values in search
2023-09-26 00:19:07 +01:00
DSpace Bot
f77d01c01f [Port dspace-7_x] Update fi.json5 (#2516)
* Update fi.json5

Two last translations to the Finnish file.

(cherry picked from commit c3a908bccb)
2023-09-25 12:53:45 +03:00
Tim Donohue
fd3f1628ee Merge pull request #2514 from DSpace/backport-2505-to-dspace-7_x
[Port dspace-7_x] remove obsolete label element in metadata-schema.component.html
2023-09-22 14:53:04 -05:00
Sascha Szott
c7fe310d81 removed trailing whitespaces as suggested by reviewer
(cherry picked from commit 43f19e7d91)
2023-09-22 17:57:54 +00:00
Sascha Szott
742b2d920a remove obsolete label element in metadata-schema.component.html
(cherry picked from commit 6847c30e58)
2023-09-22 17:57:54 +00:00
Art Lowel
7a8e2206ae Merge branch 'fix-mutliple-api-calls-on-route-change-7.6' into fix-mutliple-api-calls-on-route-change 2023-09-22 12:01:24 +02:00
Art Lowel
0104f81d54 Merge branch 'fix-mutliple-api-calls-on-route-change-7.6' into fix-mutliple-api-calls-on-route-change 2023-09-22 10:48:46 +02:00
Alan Orth
47029c0a78 src/app/shared/search: don't capitalize metadata values
Don't capitalize metadata values for display purposes.
2023-09-19 07:42:23 +03:00
Yana De Pauw
5a5f71a3d9 Merge remote-tracking branch 'upstream/dspace-7_x' into Angular-SRR-menu-issues 2023-09-18 16:49:36 +02:00
Yana De Pauw
3e8d180f1b 106974: Angular SSR menu issues 2023-09-18 16:43:32 +02:00
Tim Donohue
2d733732f6 Merge pull request #2498 from DSpace/backport-2451-to-dspace-7_x
[Port dspace-7_x] Graceful shutdown on SIGINT (e.g. from 'pm2 stop').
2023-09-14 12:29:23 -05:00
Mark H. Wood
d6cabd1d01 Document a modified method as required by PR guidelines.
(cherry picked from commit bf9b2b82e1)
2023-09-14 16:07:36 +00:00
Mark H. Wood
46e2f4e22c Properly await termination.
(cherry picked from commit 4449737aed)
2023-09-14 16:07:36 +00:00
Mark H. Wood
15c2af5fbf Graceful shutdown on SIGINT (e.g. from 'pm2 stop').
(cherry picked from commit 6709c3bb5f)
2023-09-14 16:07:36 +00:00
Tim Donohue
a37e0f29b7 Merge pull request #2497 from DSpace/backport-2493-to-dspace-7_x
[Port dspace-7_x] Correct text of help info on edit group page
2023-09-14 11:01:38 -05:00
Tim Donohue
b423b49cac Correct text of help info on edit group page
(cherry picked from commit 49247430e5)
2023-09-14 15:07:21 +00:00
Tim Donohue
bdf7414392 Merge pull request #2488 from alexandrevryghem/fix-display-order-authentication-methods_contribute-7.6
[Port dspace-7_x] Made it possible to reorder the login methods
2023-09-11 16:40:43 -05:00
Tim Donohue
459a43184a Merge pull request #2486 from DSpace/backport-2421-to-dspace-7_x
[Port dspace-7_x] 🚸remove thumbnail from file-upload section and show bitstream format …
2023-09-08 16:13:14 -05:00
Alan Orth
cd93c6eecd Merge pull request #2487 from DSpace/backport-2445-to-dspace-7_x
[Port dspace-7_x] Fix to Metadata Registry create new metadata schema doesn't appear without reload #1081
2023-09-08 23:29:50 +03:00
Hugo Dominguez
161d7e069b 🎨 revert format
(cherry picked from commit 3e5524de69)
2023-09-08 19:50:25 +00:00
Hugo Dominguez
e3ea2cb2b0 🐛 fix bug of caching when add new schema
(cherry picked from commit 9fb9e5848c)
2023-09-08 19:50:25 +00:00
Hugo Dominguez
8d295419c7 ♻️ refactor chain of observables to avoid async issues
(cherry picked from commit 2dc9fd44d7)
2023-09-08 19:50:25 +00:00
Tim Donohue
22538f30dc Update workspaceitem-section-upload-file.model.ts
Fix code comment

(cherry picked from commit 01c8a4d9c3)
2023-09-08 19:33:55 +00:00
Hugo Dominguez
5daf993451 🎨revert unnecessary format
(cherry picked from commit 13e4052c4d)
2023-09-08 19:33:55 +00:00
Hugo Dominguez
b7b3db5ba8 🚸remove thumbnail from file-upload section and show bitstream format and checksum
(cherry picked from commit 4c8ec8a4f2)
2023-09-08 19:33:55 +00:00
Tim Donohue
a0a8607628 Merge pull request #2484 from DSpace/backport-2412-to-dspace-7_x
[Port dspace-7_x] remove redundant cache default values from server.ts
2023-09-08 11:40:43 -05:00
Sascha Szott
3a465ac452 remove redundant cache default values from server.ts
(cherry picked from commit e53abcb69e)
2023-09-08 15:44:21 +00:00
Tim Donohue
97b2eb7a7c Merge pull request #2404 from alexandrevryghem/fix-setStaleByHrefSubtring-not-emitting-after-all-requests-were-stale_contribute-maintenance-7.6
[Port dspace-7_x] Fix `setStaleByHrefSubstring` not emitting true when all requests are stale
2023-09-07 14:39:33 -05:00
Tim Donohue
b46390c315 Merge pull request #2396 from alexandrevryghem/w2p-104312_pass-query-to-external-search-tabs_contribute-maintenance-7.6
[Port dspace-7_x] Search query is not set by default when opening an external sources tab
2023-09-07 12:49:47 -05:00
Tim Donohue
d14e258b5b Merge pull request #2483 from DSpace/backport-2470-to-dspace-7_x
[Port dspace-7_x] Minor pt-PT translation fixes
2023-09-07 11:15:21 -05:00
José Carvalho
1622b25aac Minor pt-PT translation fixes
(cherry picked from commit a6c1120700)
2023-09-07 15:35:02 +00:00
Tim Donohue
d95fa43c6b Merge pull request #2479 from DSpace/backport-2366-to-dspace-7_x
[Port dspace-7_x] CSV export fixes
2023-09-06 16:08:21 -05:00
Kristof De Langhe
4918ff212c 104189: CSV export add fixedFilter
(cherry picked from commit 45ad5f7316)
2023-09-06 19:53:01 +00:00
Kristof De Langhe
c2790584bd 104189: Allow CSV export on related entity search
(cherry picked from commit cac1407f08)
2023-09-06 19:53:01 +00:00
Tim Donohue
162cf94772 Merge pull request #2478 from DSpace/backport-2361-to-dspace-7_x
[Port dspace-7_x] Fix tree not updating when switching between "Browse by Vocabulary" pages
2023-09-06 09:22:00 -05:00
Nona Luypaert
92e0b6dddf Fix VocabularyTreeview not updating + i18n for nsi
(cherry picked from commit b5a70e8f95)
2023-09-05 22:14:44 +00:00
Tim Donohue
5b646af818 Merge pull request #2477 from DSpace/backport-2457-to-dspace-7_x
[Port dspace-7_x] config/config.example.yml: fix example syntax
2023-09-05 16:25:23 -05:00
Alan Orth
8363273f58 config/config.example.yml: fix example syntax
As of DSpace Angular 7.2 the syntax has changed from TypeScript to
YAML.

(cherry picked from commit 9e46b5310b)
2023-09-05 21:24:21 +00:00
Alan Orth
5f5d11cc0b Merge pull request #2476 from DSpace/backport-2432-to-dspace-7_x
[Port dspace-7_x] Fix to Value of dropdown changes automatically on item submission page
2023-09-05 20:16:37 +03:00
Hugo Dominguez
eb38b5877e change test event, click by mousedown on dynamic-scrollable-dropdown.component.spec.ts
(cherry picked from commit 25479e1794)
2023-09-05 17:15:51 +00:00
Hugo Dominguez
f88638e9fe 🐛 Fix Value of dropdown changes automatically on item submission page
(cherry picked from commit 651305952d)
2023-09-05 17:15:51 +00:00
Tim Donohue
cd350ddf5f Merge pull request #2472 from DSpace/backport-2448-to-dspace-7_x
[Port dspace-7_x] Spanish translation updated to 7.6
2023-09-05 09:48:32 -05:00
Alan Orth
2987ad05be Merge pull request #2474 from DSpace/backport-2444-to-dspace-7_x
[Port dspace-7_x] Fix to Mobile navbar hamburger menu doesn't work in Firefox/Safari #2372
2023-09-05 12:01:31 +03:00
Hugo Dominguez
9afbd8d746 🐛 fix when navbar expands on firefox
(cherry picked from commit 60706720e4)
2023-09-05 09:00:34 +00:00
Sergio Fernández Celorio
a4eaf02a47 Some lint errors fixed
(cherry picked from commit 1885638ba6)
2023-09-01 19:05:02 +00:00
Sergio Fernández Celorio
d1ebf07456 Spanish translation updated to 7.6
(cherry picked from commit 4cc4192e93)
2023-09-01 19:05:02 +00:00
Tim Donohue
02c47c3234 Merge pull request #2469 from DSpace/backport-2468-to-dspace-7_x
[Port dspace-7_x] Minor Accessibility Fixes & Enable accessibility scan on more pages
2023-08-30 10:31:36 -05:00
Tim Donohue
63c752b3f4 Fix heading order accessibility issue in search filters/facets
(cherry picked from commit 276d80895e)
2023-08-30 14:40:51 +00:00
Tim Donohue
6df76515ba Minor fixes to cypress tests
(cherry picked from commit 70a7bbe3cb)
2023-08-30 14:40:51 +00:00
Tim Donohue
3cdcdaf475 Fix accessibility of date sliders by adding aria-labels
(cherry picked from commit 2a881791ba)
2023-08-30 14:40:51 +00:00
Tim Donohue
b90d102e5e Update ng2-nouislider and nouislider to latest versions
(cherry picked from commit 91d8b7e4f7)
2023-08-30 14:40:51 +00:00
Tim Donohue
13ead8174a Fix heading order issue with item page & update accessibility tests to prove it now passes
(cherry picked from commit ba244bf6b1)
2023-08-30 14:40:51 +00:00
Tim Donohue
a7a807c0bb Enable excessibility checking of login menu, and remove unnecessary exclusion from header
(cherry picked from commit 339ed63734)
2023-08-30 14:40:51 +00:00
Tim Donohue
baecf2ac11 Reenable accessibility check fixed in #2251
(cherry picked from commit 158ebb0e32)
2023-08-30 14:40:51 +00:00
Tim Donohue
7ebdc43ca2 Update to latest axe-core
(cherry picked from commit 50899f1d1b)
2023-08-30 14:40:51 +00:00
Tim Donohue
13c0cb48ed Update to latest cypress
(cherry picked from commit 68a3323fca)
2023-08-30 14:40:51 +00:00
Alan Orth
6639594f7e Merge pull request #2465 from DSpace/backport-2463-to-dspace-7_x
[Port dspace-7_x] Fix to Pagination position is retained between searches #2159
2023-08-29 11:27:09 +03:00
Alexandre Vryghem
07a2e333ca Implemented i18n cache busting 2023-08-28 21:24:03 +02:00
Tim Donohue
af8c599497 Merge pull request #2466 from DSpace/backport-2447-to-dspace-7_x
[Port dspace-7_x] 2251 accessibility issues on the community list page
2023-08-28 14:13:02 -05:00
Alan Orth
0542e9b2fd Merge pull request #2467 from DSpace/backport-2399-to-dspace-7_x
[Port dspace-7_x] fix(i18n): curation-task.task.registerdoi.label
2023-08-28 21:07:04 +03:00
Mirko Scherf
2a55e36082 fix(i18m): curation-task.task.registerdoi.label
changed curation-task.task.register-doi.label back to
curation-task.task.registerdoi.label and added German translation

(cherry picked from commit 0ec72f679b)
2023-08-28 18:02:28 +00:00
Hrafn Malmquist
8a5d6897c4 Reorder instance method to come after member declaration
(cherry picked from commit e59913acab)
2023-08-28 14:44:18 +00:00
Hrafn Malmquist
e89a277702 Improve documentation
(cherry picked from commit d9b6e9d81f)
2023-08-28 14:44:18 +00:00
Hrafn Malmquist
9fc4e213df Add trackby function so cdktree can differentiate between new and old nodes
(cherry picked from commit 5f71de885b)
2023-08-28 14:44:18 +00:00
Hrafn Malmquist
46ac61dcac Replace h2 with a h1
(cherry picked from commit 05c53ad1d4)
2023-08-28 14:44:18 +00:00
Hrafn Malmquist
eef98d70c3 Replace h5 with a span
(cherry picked from commit 5ef4a827f5)
2023-08-28 14:44:18 +00:00
Hugo Dominguez
5c669fb1b7 add first page condition when search submit
(cherry picked from commit 044230209c)
2023-08-28 14:33:34 +00:00
Hugo Dominguez
a343991e74 🐛 go to first page after submit search
(cherry picked from commit 88a7088b47)
2023-08-28 14:33:34 +00:00
Tim Donohue
83de2c5769 Merge pull request #2462 from tdonohue/port_2395
[Port dspace-7_x] Fix themed components duplicating themself when switching themes
2023-08-25 13:28:03 -05:00
Alexandre Vryghem
8b57a2f6af Merge branch 'fix-ngonchanges-not-working-for-themed-components_contribute-7.2' into fix-ngonchanges-not-working-for-themed-components_contribute-7.4
# Conflicts:
#	src/app/app.component.ts
2023-08-25 12:34:10 -05:00
Alexandre Vryghem
7352d9e273 Reset to base theme when no default theme is set and leaving UUID/handle theme 2023-08-25 12:22:51 -05:00
Alexandre Vryghem
4e14bc0b78 101577: Ensure the component is always destroyed before rendering the new component 2023-08-25 12:22:32 -05:00
Alexandre Vryghem
0e289b3f39 103176: Fix vcr not being defined yet in OnInit hook 2023-08-25 12:19:30 -05:00
Koen Pauwels
815425c101 Fix lint issue. 2023-08-25 10:18:09 +02:00
Alan Orth
6ad641f4e2 Merge pull request #2460 from DSpace/backport-2434-to-dspace-7_x
[Port dspace-7_x] Input type list doesn't work correctly if multiple value-pairs have the same pair value
2023-08-25 10:37:33 +03:00
Alexandre Vryghem
7f00253d3d 105265: Made the DsDynamicListComponent's checkbox & radio buttons ids unique for each metadata field to prevent other value-pairs having the same id
(cherry picked from commit 4c419e1eee)
2023-08-25 06:17:16 +00:00
Tim Donohue
03d17678e2 Merge pull request #2459 from DSpace/backport-2449-to-dspace-7_x
[Port dspace-7_x] Update pl.json5
2023-08-24 16:03:53 -05:00
Michał Dykas
0efb95825d Update pl.json5 fix test 2 spaces instead of 1
(cherry picked from commit f58a7a2e9b)
2023-08-24 19:58:39 +00:00
Michał Dykas
95cde220e6 Update pl.json5 fix issues from tests
(cherry picked from commit 93299ec83d)
2023-08-24 19:58:39 +00:00
Michał Dykas
964066056c Update pl.json5
Translation update of 2 spaces instead of 3

(cherry picked from commit cfd753f928)
2023-08-24 19:58:39 +00:00
Michał Dykas
22db36f938 Update pl.json5
Update from 7.4 to 7.6 version

(cherry picked from commit b439ab4484)
2023-08-24 19:58:39 +00:00
Tim Donohue
9df4d660e7 Merge pull request #2453 from tdonohue/fix_demo_urls_7_x
[Port dspace-7_x] Replace mentions of demo7.dspace.org and api7.dspace.org with new demo URLs
2023-08-24 12:41:02 -05:00
Koen Pauwels
a5b30ea3c2 103818 Adjusted "Inherit policies" tooltip 2023-08-24 15:27:52 +02:00
Koen Pauwels
2078b7593a 103818 Add warning tooltip to "Inherit policies" checkbox on item move page 2023-08-24 15:27:52 +02:00
Tim Donohue
fe8429ebbe Enable new skip merge commit feature 2023-08-23 17:08:44 -05:00
Tim Donohue
8feeedfc3a Merge pull request #2455 from DSpace/backport-2438-to-dspace-7_x
[Port dspace-7_x] 2437 Correct and clarify commented-out code in several custom components
2023-08-23 16:07:17 -05:00
Hardy Pottinger
3292222e47 fix lint error in workflow-item-send-back.component.ts
(cherry picked from commit 518cc714f2)
2023-08-23 19:50:22 +00:00
Hardy Pottinger
36868c06f0 2437 Correct and clarify commented-out code in several custom components
- Correct the path in commented-out code in the custom theme's
  components
- Clarify that the workflow-item-sen-back.component.scss file is a stub
- It has no corresponding SCSS file in the base theme

(cherry picked from commit 0906234a29)
2023-08-23 19:50:22 +00:00
Tim Donohue
5853e49bd0 Update default configs to use https://demo.dspace.org/server/ 2023-08-22 16:44:10 -05:00
Tim Donohue
2fd53c7ad2 Replace mentions of demo7.dspace.org and api7.dspace.org with demo or sandbox 2023-08-22 16:38:00 -05:00
Tim Donohue
63345a335a Merge pull request #2428 from DSpace/backport-2409-to-dspace-7_x
[Port dspace-7_x] Bump word-wrap from 1.2.3 to 1.2.5
2023-08-09 10:07:14 -05:00
dependabot[bot]
bbb50f2858 Bump word-wrap from 1.2.3 to 1.2.5
Bumps [word-wrap](https://github.com/jonschlinkert/word-wrap) from 1.2.3 to 1.2.5.
- [Release notes](https://github.com/jonschlinkert/word-wrap/releases)
- [Commits](https://github.com/jonschlinkert/word-wrap/compare/1.2.3...1.2.5)

---
updated-dependencies:
- dependency-name: word-wrap
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
(cherry picked from commit 2fec33e70a)
2023-08-08 21:42:41 +00:00
Tim Donohue
3e31c1eee3 Merge pull request #2427 from tdonohue/port_2048
[Port dspace-7_x] ProcessDetailComponent test improvement
2023-08-08 16:25:21 -05:00
Kristof De Langhe
cfcf93ecf8 104126: ProcessDetailComponent test improvement 2023-08-08 15:08:49 -05:00
Tim Donohue
74c2f3d9bb Merge pull request #2405 from alexandrevryghem/fix-collection-form-bugs_contribute-maintenance-7.6
[Port dspace-7_x] Fix minor collection form bugs
2023-08-04 12:48:34 -05:00
Tim Donohue
f22fcc7b3c Merge pull request #2420 from tdonohue/port_2388
[Port dspace-7_x] fix(i18n): add and update missing status strings
2023-08-04 12:25:44 -05:00
Mirko Scherf
c3b9a1d5c6 fix(i18n): add and update missing status strings
New strings for status filter entries:
search.filters.namedresourcetype.*
Refactored strings introduced with #2068 (refactor badged),
e.g. mydspace.status.archived -> mydspace.status.mydspaceArchived
2023-08-04 11:19:55 -05:00
Alan Orth
d072ae7027 Merge pull request #2419 from DSpace/backport-2378-to-dspace-7_x
[Port dspace-7_x] Show error message from the password validation response
2023-08-04 16:04:15 +03:00
milanmajchrak
f746d45ac1 Show error message from the error response
(cherry picked from commit e6546b4499)
2023-08-04 12:21:30 +00:00
Tim Donohue
1fd917dd4a Merge pull request #2418 from DSpace/backport-2344-to-dspace-7_x
[Port dspace-7_x] Catch and handle unsuccessful "convert rels to items" responses
2023-08-03 16:38:44 -05:00
Tim Donohue
99e349b91f Merge pull request #2392 from alexandrevryghem/fix-mathjax-displaying-twiced-in-ui_contribute-maintenance-7.6
[Port dspace-7_x] Fixed MathJax code being displayed twice by `dsMarkdown` pipe
2023-08-03 16:09:56 -05:00
Kim Shepherd
a7ed053d15 catch and handle unsuccessful "convert rels to items" responses
(cherry picked from commit a35b7d8356)
2023-08-03 20:03:27 +00:00
Tim Donohue
99c6dd1829 Merge pull request #2347 from alanorth/finnish-language-strings
src/assets/i18n: update Finnish language strings
2023-08-03 12:56:22 -05:00
Tim Donohue
0a48b09bd7 Merge pull request #2416 from tdonohue/port_of_2381
[Port dspace-7_x] refactor: rename aletr-type.ts to alert-type.ts
2023-08-03 12:37:18 -05:00
Mirko Scherf
0dc74165dc refactor: rename aletr-type.ts to alert-type.ts 2023-08-03 11:51:48 -05:00
Tim Donohue
9cbb634245 Merge pull request #2415 from DSpace/backport-2363-to-dspace-7_x
[Port dspace-7_x] Bump semver from 5.7.1 to 5.7.2
2023-08-02 15:55:32 -05:00
dependabot[bot]
7c379db7ee Bump semver from 5.7.1 to 5.7.2
Bumps [semver](https://github.com/npm/node-semver) from 5.7.1 to 5.7.2.
- [Release notes](https://github.com/npm/node-semver/releases)
- [Changelog](https://github.com/npm/node-semver/blob/v5.7.2/CHANGELOG.md)
- [Commits](https://github.com/npm/node-semver/compare/v5.7.1...v5.7.2)

---
updated-dependencies:
- dependency-name: semver
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
(cherry picked from commit 0b0c60e38c)
2023-08-02 20:06:40 +00:00
Alan Orth
1b9656b135 src/assets/i18n: update Finnish language strings
Contributed by Reeta Kuukoski from the National Library of Finland.
2023-07-31 12:32:14 +03:00
Tim Donohue
85acdcb9c5 Merge pull request #2407 from DSpace/backport-2406-to-dspace-7_x
[Port dspace-7_x] Add GitHub action to automatically create a port PR (based on label) & minor bug fixes
2023-07-28 15:25:02 -05:00
Tim Donohue
867ae9c341 Minor update to label_merge_conflicts to ignore any errors (seem random at this time)
(cherry picked from commit d75d12b423)
2023-07-28 20:11:29 +00:00
Tim Donohue
4965bdee5f Add action to automatically create a port PR when specified
(cherry picked from commit 338b63ebb8)
2023-07-28 20:11:29 +00:00
Tim Donohue
4f0e1d6de1 Merge pull request #2369 from tdonohue/port_2358_2359
Port recent GitHub Actions changes to dspace-7_x branch
2023-07-14 16:56:32 -05:00
Tim Donohue
1809f0585c Split docker images into separate jobs to run in parallel. Ensure 'main' codebase is tagged as 'latest' 2023-07-14 15:41:57 -05:00
Tim Donohue
a484379f69 Ensure codescan and label_merge_conflicts run on maintenance branches 2023-07-14 15:41:41 -05:00
Tim Donohue
7bf4da55cf Enable Pull Request Opened action to assign PRs to their creator 2023-07-14 15:41:26 -05:00
Alan Orth
a079ed729c Merge pull request #2354 from alanorth/request-copy-component-path
src/app: fix path to deny-request-copy component
2023-07-06 20:45:56 +03:00
Alan Orth
3a48ed390b src/app: fix path to deny-request-copy component
The themed-deny-request-copy.component erroneously includes the cus-
tom theme's deny-request-copy component instead of its own.

Closes: https://github.com/DSpace/dspace-angular/issues/2351
2023-07-06 20:41:52 +03:00
1269 changed files with 34491 additions and 24130 deletions

View File

@@ -11,7 +11,13 @@
"eslint-plugin-jsonc",
"eslint-plugin-rxjs",
"eslint-plugin-simple-import-sort",
"eslint-plugin-import-newlines"
"eslint-plugin-import-newlines",
"eslint-plugin-jsonc",
"dspace-angular-ts",
"dspace-angular-html"
],
"ignorePatterns": [
"lint/test/fixture"
],
"overrides": [
{
@@ -21,7 +27,8 @@
"parserOptions": {
"project": [
"./tsconfig.json",
"./cypress/tsconfig.json"
"./cypress/tsconfig.json",
"./lint/tsconfig.json"
],
"createDefaultProgram": true
},
@@ -38,7 +45,10 @@
"error",
2,
{
"SwitchCase": 1
"SwitchCase": 1,
"ignoredNodes": [
"ClassBody.body > PropertyDefinition[decorators.length > 0] > .key"
]
}
],
"max-classes-per-file": [
@@ -212,6 +222,15 @@
"@typescript-eslint/no-unsafe-return": "off",
"@typescript-eslint/restrict-template-expressions": "off",
"@typescript-eslint/require-await": "off",
"@typescript-eslint/no-base-to-string": [
"error",
{
"ignoredTypeNames": [
"ResourceType",
"Error"
]
}
],
"deprecation/deprecation": "warn",
@@ -238,7 +257,12 @@
"method"
],
"rxjs/no-nested-subscribe": "off" // todo: go over _all_ cases
"rxjs/no-nested-subscribe": "off", // todo: go over _all_ cases
// Custom DSpace Angular rules
"dspace-angular-ts/themed-component-classes": "error",
"dspace-angular-ts/themed-component-selectors": "error",
"dspace-angular-ts/themed-component-usages": "error"
}
},
{
@@ -253,7 +277,10 @@
"createDefaultProgram": true
},
"rules": {
"prefer-const": "off"
"prefer-const": "off",
// Custom DSpace Angular rules
"dspace-angular-ts/themed-component-usages": "error"
}
},
{
@@ -262,7 +289,11 @@
],
"extends": [
"plugin:@angular-eslint/template/recommended"
]
],
"rules": {
// Custom DSpace Angular rules
"dspace-angular-html/themed-component-usages": "error"
}
},
{
"files": [

5
.gitattributes vendored
View File

@@ -13,4 +13,7 @@
*.css eol=lf
*.scss eol=lf
*.html eol=lf
*.svg eol=lf
*.svg eol=lf
# Generated documentation should have LF line endings to reduce git noise
docs/lint/**/*.md eol=lf

View File

@@ -74,7 +74,7 @@ jobs:
id: yarn-cache-dir-path
run: echo "dir=$(yarn cache dir)" >> $GITHUB_OUTPUT
- name: Cache Yarn dependencies
uses: actions/cache@v3
uses: actions/cache@v4
with:
# Cache entire Yarn cache directory (see previous step)
path: ${{ steps.yarn-cache-dir-path.outputs.dir }}
@@ -85,8 +85,14 @@ jobs:
- name: Install Yarn dependencies
run: yarn install --frozen-lockfile
- name: Build lint plugins
run: yarn run build:lint
- name: Run lint plugin tests
run: yarn run test:lint:nobuild
- name: Run lint
run: yarn run lint --quiet
run: yarn run lint:nobuild --quiet
- name: Check for circular dependencies
run: yarn run check-circ-deps
@@ -101,10 +107,10 @@ jobs:
# so that it can be shared with the 'codecov' job (see below)
# NOTE: Angular CLI only supports code coverage for specs. See https://github.com/angular/angular-cli/issues/6286
- name: Upload code coverage report to Artifact
uses: actions/upload-artifact@v3
uses: actions/upload-artifact@v4
if: matrix.node-version == '18.x'
with:
name: dspace-angular coverage report
name: coverage-report-${{ matrix.node-version }}
path: 'coverage/dspace-angular/lcov.info'
retention-days: 14
@@ -135,19 +141,19 @@ jobs:
# Cypress always creates a video of all e2e tests (whether they succeeded or failed)
# Save those in an Artifact
- name: Upload e2e test videos to Artifacts
uses: actions/upload-artifact@v3
uses: actions/upload-artifact@v4
if: always()
with:
name: e2e-test-videos
name: e2e-test-videos-${{ matrix.node-version }}
path: cypress/videos
# If e2e tests fail, Cypress creates a screenshot of what happened
# Save those in an Artifact
- name: Upload e2e test failure screenshots to Artifacts
uses: actions/upload-artifact@v3
uses: actions/upload-artifact@v4
if: failure()
with:
name: e2e-test-screenshots
name: e2e-test-screenshots-${{ matrix.node-version }}
path: cypress/screenshots
- name: Stop app (in case it stays up after e2e tests)
@@ -197,7 +203,7 @@ jobs:
# Download artifacts from previous 'tests' job
- name: Download coverage artifacts
uses: actions/download-artifact@v3
uses: actions/download-artifact@v4
# Now attempt upload to Codecov using its action.
# NOTE: We use a retry action to retry the Codecov upload if it fails the first time.
@@ -207,11 +213,12 @@ jobs:
- name: Upload coverage to Codecov.io
uses: Wandalen/wretry.action@v1.3.0
with:
action: codecov/codecov-action@v3
action: codecov/codecov-action@v4
# Ensure codecov-action throws an error when it fails to upload
# This allows us to auto-restart the action if an error is thrown
with: |
fail_ci_if_error: true
token: ${{ secrets.CODECOV_TOKEN }}
# Try re-running action 5 times max
attempt_limit: 5
# Run again in 30 seconds

View File

@@ -28,7 +28,7 @@ jobs:
# Use the reusable-docker-build.yml script from DSpace/DSpace repo to build our Docker image
uses: DSpace/DSpace/.github/workflows/reusable-docker-build.yml@main
with:
build_id: dspace-angular
build_id: dspace-angular-dev
image_name: dspace/dspace-angular
dockerfile_path: ./Dockerfile
secrets:

View File

@@ -16,7 +16,7 @@ jobs:
# 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: actions/add-to-project@v0.5.0
uses: actions/add-to-project@v1.0.0
# Note, the authentication token below is an ORG level Secret.
# It must be created/recreated manually via a personal access token with admin:org, project, public_repo permissions
# See: https://docs.github.com/en/actions/configuring-and-managing-workflows/authenticating-with-the-github_token#permissions-for-the-github_token

View File

@@ -21,4 +21,4 @@ jobs:
# Assign the PR to whomever created it. This is useful for visualizing assignments on project boards
# See https://github.com/toshimaru/auto-author-assign
- name: Assign PR to creator
uses: toshimaru/auto-author-assign@v2.0.1
uses: toshimaru/auto-author-assign@v2.1.0

1
.gitignore vendored
View File

@@ -1,4 +1,5 @@
/.angular/cache
/.nx
/__build__
/__server_build__
/node_modules

View File

@@ -109,22 +109,22 @@
"serve": {
"builder": "@angular-builders/custom-webpack:dev-server",
"options": {
"browserTarget": "dspace-angular:build",
"buildTarget": "dspace-angular:build",
"port": 4000
},
"configurations": {
"development": {
"browserTarget": "dspace-angular:build:development"
"buildTarget": "dspace-angular:build:development"
},
"production": {
"browserTarget": "dspace-angular:build:production"
"buildTarget": "dspace-angular:build:production"
}
}
},
"extract-i18n": {
"builder": "@angular-devkit/build-angular:extract-i18n",
"options": {
"browserTarget": "dspace-angular:build"
"buildTarget": "dspace-angular:build"
}
},
"test": {
@@ -217,23 +217,23 @@
}
},
"serve-ssr": {
"builder": "@nguniversal/builders:ssr-dev-server",
"builder": "@angular-devkit/build-angular:ssr-dev-server",
"options": {
"browserTarget": "dspace-angular:build",
"buildTarget": "dspace-angular:build",
"serverTarget": "dspace-angular:server",
"port": 4000
},
"configurations": {
"production": {
"browserTarget": "dspace-angular:build:production",
"buildTarget": "dspace-angular:build:production",
"serverTarget": "dspace-angular:server:production"
}
}
},
"prerender": {
"builder": "@nguniversal/builders:prerender",
"builder": "@angular-devkit/build-angular:prerender",
"options": {
"browserTarget": "dspace-angular:build:production",
"buildTarget": "dspace-angular:build:production",
"serverTarget": "dspace-angular:server:production",
"routes": [
"/"
@@ -266,6 +266,8 @@
"options": {
"lintFilePatterns": [
"src/**/*.ts",
"cypress/**/*.ts",
"lint/**/*.ts",
"src/**/*.html",
"src/**/*.json5"
]

View File

@@ -202,6 +202,12 @@ languages:
- code: en
label: English
active: true
- code: ar
label: العربية
active: true
- code: bn
label: বাংলা
active: true
- code: ca
label: Català
active: true
@@ -211,24 +217,36 @@ languages:
- code: de
label: Deutsch
active: true
- code: el
label: Ελληνικά
active: true
- code: es
label: Español
active: true
- code: fi
label: Suomi
active: true
- code: fr
label: Français
active: true
- code: gd
label: Gàidhlig
active: true
- code: it
label: Italiano
active: true
- code: lv
label: Latviešu
- code: hi
label: हिंदी
active: true
- code: hu
label: Magyar
active: true
- code: it
label: Italiano
active: true
- code: kk
label: Қазақ
active: true
- code: lv
label: Latviešu
active: true
- code: nl
label: Nederlands
active: true
@@ -244,8 +262,8 @@ languages:
- code: sr-lat
label: Srpski (lat)
active: true
- code: fi
label: Suomi
- code: sr-cyr
label: Српски
active: true
- code: sv
label: Svenska
@@ -253,27 +271,12 @@ languages:
- code: tr
label: Türkçe
active: true
- code: vi
label: Tiếng Việt
active: true
- code: kk
label: Қазақ
active: true
- code: bn
label: বাংলা
active: true
- code: hi
label: हिंदी
active: true
- code: el
label: Ελληνικά
active: true
- code: sr-cyr
label: Српски
active: true
- code: uk
label: раї́нська
active: true
- code: vi
label: Tiếng Việt
active: true
# Browse-By Pages
@@ -407,10 +410,11 @@ mediaViewer:
# Whether the end user agreement is required before users use the repository.
# If enabled, the user will be required to accept the agreement before they can use the repository.
# And whether the privacy statement should exist or not.
# And whether the privacy statement/COAR notify support page should exist or not.
info:
enableEndUserAgreement: true
enablePrivacyStatement: true
enableCOARNotifySupport: true
# Whether to enable Markdown (https://commonmark.org/) and MathJax (https://www.mathjax.org/)
# display in supported metadata fields. By default, only dc.description.abstract is supported.

View File

@@ -0,0 +1,13 @@
beforeEach(() => {
cy.visit('/collections/create?parent='.concat(Cypress.env('DSPACE_TEST_COMMUNITY')));
cy.loginViaForm(Cypress.env('DSPACE_TEST_ADMIN_USER'), Cypress.env('DSPACE_TEST_ADMIN_PASSWORD'));
});
it('should show loading component while saving', () => {
const title = 'Test Collection Title';
cy.get('#title').type(title);
cy.get('button[type="submit"]').click();
cy.get('ds-loading').should('be.visible');
});

View File

@@ -0,0 +1,13 @@
beforeEach(() => {
cy.visit('/communities/create');
cy.loginViaForm(Cypress.env('DSPACE_TEST_ADMIN_USER'), Cypress.env('DSPACE_TEST_ADMIN_PASSWORD'));
});
it('should show loading component while saving', () => {
const title = 'Test Community Title';
cy.get('#title').type(title);
cy.get('button[type="submit"]').click();
cy.get('ds-loading').should('be.visible');
});

View File

@@ -18,6 +18,11 @@ describe('Edit Item > Edit Metadata tab', () => {
// <ds-edit-item-page> tag must be loaded
cy.get('ds-edit-item-page').should('be.visible');
// wait for all the ds-dso-edit-metadata-value components to be rendered
cy.get('ds-dso-edit-metadata-value div[role="row"]').each(($row: HTMLDivElement) => {
cy.wrap($row).find('div[role="cell"]').should('be.visible');
});
// Analyze <ds-edit-item-page> for accessibility issues
testA11y('ds-edit-item-page');
});

View File

@@ -0,0 +1,15 @@
const ADD_TEMPLATE_ITEM_PAGE = '/collections/'.concat(Cypress.env('DSPACE_TEST_COLLECTION')).concat('/itemtemplate');
describe('Item Template', () => {
beforeEach(() => {
cy.visit(ADD_TEMPLATE_ITEM_PAGE);
cy.loginViaForm(Cypress.env('DSPACE_TEST_ADMIN_USER'), Cypress.env('DSPACE_TEST_ADMIN_PASSWORD'));
});
it('should load properly', () => {
cy.contains('.ds-header-row .lbl-cell', 'Field', { timeout: 10000 }).should('exist').should('be.visible');
cy.contains('.ds-header-row b', 'Value', { timeout: 10000 }).should('exist').should('be.visible');
cy.contains('.ds-header-row b', 'Lang', { timeout: 10000 }).should('exist').should('be.visible');
cy.contains('.ds-header-row b', 'Edit', { timeout: 10000 }).should('exist').should('be.visible');
});
});

View File

@@ -3,31 +3,31 @@ import { testA11y } from 'cypress/support/utils';
const page = {
openLoginMenu() {
// Click the "Log In" dropdown menu in header
cy.get('ds-themed-header [data-test="login-menu"]').click();
cy.get('ds-header [data-test="login-menu"]').click();
},
openUserMenu() {
// Once logged in, click the User menu in header
cy.get('ds-themed-header [data-test="user-menu"]').click();
cy.get('ds-header [data-test="user-menu"]').click();
},
submitLoginAndPasswordByPressingButton(email, password) {
// Enter email
cy.get('ds-themed-header [data-test="email"]').type(email);
cy.get('ds-header [data-test="email"]').type(email);
// Enter password
cy.get('ds-themed-header [data-test="password"]').type(password);
cy.get('ds-header [data-test="password"]').type(password);
// Click login button
cy.get('ds-themed-header [data-test="login-button"]').click();
cy.get('ds-header [data-test="login-button"]').click();
},
submitLoginAndPasswordByPressingEnter(email, password) {
// In opened Login modal, fill out email & password, then click Enter
cy.get('ds-themed-header [data-test="email"]').type(email);
cy.get('ds-themed-header [data-test="password"]').type(password);
cy.get('ds-themed-header [data-test="password"]').type('{enter}');
cy.get('ds-header [data-test="email"]').type(email);
cy.get('ds-header [data-test="password"]').type(password);
cy.get('ds-header [data-test="password"]').type('{enter}');
},
submitLogoutByPressingButton() {
// This is the POST command that will actually log us out
cy.intercept('POST', '/server/api/authn/logout').as('logout');
// Click logout button
cy.get('ds-themed-header [data-test="logout-button"]').click();
cy.get('ds-header [data-test="logout-button"]').click();
// Wait until above POST command responds before continuing
// (This ensures next action waits until logout completes)
cy.wait('@logout');
@@ -102,10 +102,10 @@ describe('Login Modal', () => {
page.openLoginMenu();
// Registration link should be visible
cy.get('ds-themed-header [data-test="register"]').should('be.visible');
cy.get('ds-header [data-test="register"]').should('be.visible');
// Click registration link & you should go to registration page
cy.get('ds-themed-header [data-test="register"]').click();
cy.get('ds-header [data-test="register"]').click();
cy.location('pathname').should('eq', '/register');
cy.get('ds-register-email').should('exist');
@@ -119,10 +119,10 @@ describe('Login Modal', () => {
page.openLoginMenu();
// Forgot password link should be visible
cy.get('ds-themed-header [data-test="forgot"]').should('be.visible');
cy.get('ds-header [data-test="forgot"]').should('be.visible');
// Click link & you should go to Forgot Password page
cy.get('ds-themed-header [data-test="forgot"]').click();
cy.get('ds-header [data-test="forgot"]').click();
cy.location('pathname').should('eq', '/forgot');
cy.get('ds-forgot-email').should('exist');

View File

@@ -1,15 +1,15 @@
const page = {
fillOutQueryInNavBar(query) {
// Click the magnifying glass
cy.get('ds-themed-header [data-test="header-search-icon"]').click();
cy.get('ds-header [data-test="header-search-icon"]').click();
// Fill out a query in input that appears
cy.get('ds-themed-header [data-test="header-search-box"]').type(query);
cy.get('ds-header [data-test="header-search-box"]').type(query);
},
submitQueryByPressingEnter() {
cy.get('ds-themed-header [data-test="header-search-box"]').type('{enter}');
cy.get('ds-header [data-test="header-search-box"]').type('{enter}');
},
submitQueryByPressingIcon() {
cy.get('ds-themed-header [data-test="header-search-icon"]').click();
cy.get('ds-header [data-test="header-search-icon"]').click();
},
};

View File

@@ -137,7 +137,7 @@ describe('New Submission page', () => {
// Upload our DSpace logo via drag & drop onto submission form
// cy.get('div#section_upload')
cy.get('div.ds-document-drop-zone').selectFile('src/assets/images/dspace-logo.png', {
cy.get('div.ds-document-drop-zone').selectFile('src/assets/images/dspace-logo.svg', {
action: 'drag-drop',
});

View File

@@ -4,10 +4,11 @@
"**/*.ts"
],
"compilerOptions": {
"sourceMap": false,
"types": [
"cypress",
"cypress-axe",
"node"
]
}
}
}

View File

@@ -20,7 +20,7 @@ the Docker compose scripts in this 'docker' folder.
### Dockerfile
This Dockerfile is used to build a *development* DSpace 7 Angular UI image, published as 'dspace/dspace-angular'
This Dockerfile is used to build a *development* DSpace Angular UI image, published as 'dspace/dspace-angular'
```
docker build -t dspace/dspace-angular:latest .
@@ -46,11 +46,11 @@ A default/demo version of this image is built *automatically*.
## 'docker' directory
- docker-compose.yml
- Starts DSpace Angular with Docker Compose from the current branch. This file assumes that a DSpace 7 REST instance will also be started in Docker.
- Starts DSpace Angular with Docker Compose from the current branch. This file assumes that a DSpace REST instance will also be started in Docker.
- docker-compose-rest.yml
- Runs a published instance of the DSpace 7 REST API - persists data in Docker volumes
- Runs a published instance of the DSpace REST API - persists data in Docker volumes
- docker-compose-ci.yml
- Runs a published instance of the DSpace 7 REST API for CI testing. The database is re-populated from a SQL dump on each startup.
- Runs a published instance of the DSpace REST API for CI testing. The database is re-populated from a SQL dump on each startup.
- cli.yml
- Docker compose file that provides a DSpace CLI container to work with a running DSpace REST container.
- cli.assetstore.yml
@@ -71,7 +71,7 @@ docker-compose -f docker/docker-compose.yml build
This command provides a quick way to start both the frontend & backend from this single codebase
```
docker-compose -p d7 -f docker/docker-compose.yml -f docker/docker-compose-rest.yml up -d
docker-compose -p d8 -f docker/docker-compose.yml -f docker/docker-compose-rest.yml up -d
```
Keep in mind, you may also start the backend by cloning the 'DSpace/DSpace' GitHub repository separately. See the next section.
@@ -86,14 +86,14 @@ _The system will be started in 2 steps. Each step shares the same docker network
From 'DSpace/DSpace' clone (build first as needed):
```
docker-compose -p d7 up -d
docker-compose -p d8 up -d
```
NOTE: More detailed instructions on starting the backend via Docker can be found in the [Docker Compose instructions for the Backend](https://github.com/DSpace/DSpace/blob/main/dspace/src/main/docker-compose/README.md).
From 'DSpace/dspace-angular' clone (build first as needed)
```
docker-compose -p d7 -f docker/docker-compose.yml up -d
docker-compose -p d8 -f docker/docker-compose.yml up -d
```
At this point, you should be able to access the UI from http://localhost:4000,
@@ -107,19 +107,19 @@ This allows you to run the Angular UI in *production* mode, pointing it at the d
```
docker-compose -f docker/docker-compose-dist.yml pull
docker-compose -f docker/docker-compose-dist.yml build
docker-compose -p d7 -f docker/docker-compose-dist.yml up -d
docker-compose -p d8 -f docker/docker-compose-dist.yml up -d
```
## Ingest test data from AIPDIR
Create an administrator
```
docker-compose -p d7 -f docker/cli.yml run --rm dspace-cli create-administrator -e test@test.edu -f admin -l user -p admin -c en
docker-compose -p d8 -f docker/cli.yml run --rm dspace-cli create-administrator -e test@test.edu -f admin -l user -p admin -c en
```
Load content from AIP files
```
docker-compose -p d7 -f docker/cli.yml -f ./docker/cli.ingest.yml run --rm dspace-cli
docker-compose -p d8 -f docker/cli.yml -f ./docker/cli.ingest.yml run --rm dspace-cli
```
## Alternative Ingest - Use Entities dataset
@@ -127,12 +127,12 @@ _Delete your docker volumes or use a unique project (-p) name_
Start DSpace with Database Content from a database dump
```
docker-compose -p d7 -f docker/docker-compose.yml -f docker/docker-compose-rest.yml -f docker/db.entities.yml up -d
docker-compose -p d8 -f docker/docker-compose.yml -f docker/docker-compose-rest.yml -f docker/db.entities.yml up -d
```
Load assetstore content and trigger a re-index of the repository
```
docker-compose -p d7 -f docker/cli.yml -f docker/cli.assetstore.yml run --rm dspace-cli
docker-compose -p d8 -f docker/cli.yml -f docker/cli.assetstore.yml run --rm dspace-cli
```
## End to end testing of the REST API (runs in GitHub Actions CI).
@@ -140,5 +140,5 @@ _In this instance, only the REST api runs in Docker using the Entities dataset.
This command is only really useful for testing our Continuous Integration process.
```
docker-compose -p d7ci -f docker/docker-compose-ci.yml up -d
docker-compose -p d8ci -f docker/docker-compose-ci.yml up -d
```

View File

@@ -12,8 +12,6 @@
# https://github.com/DSpace/DSpace/blob/main/dspace/src/main/docker-compose/cli.assetstore.yml
#
# Therefore, it should be kept in sync with that file
version: "3.7"
services:
dspace-cli:
environment:

View File

@@ -12,8 +12,6 @@
# https://github.com/DSpace/DSpace/blob/main/dspace/src/main/docker-compose/cli.ingest.yml
#
# Therefore, it should be kept in sync with that file
version: "3.7"
services:
dspace-cli:
environment:
@@ -34,5 +32,7 @@ services:
/dspace/bin/dspace packager -r -a -t AIP -e $${ADMIN_EMAIL} -f -u SITE*.zip
/dspace/bin/dspace database update-sequences
touch /dspace/solr/search/conf/reindex.flag
/dspace/bin/dspace index-discovery
/dspace/bin/dspace oai import
/dspace/bin/dspace oai clean-cache

View File

@@ -12,7 +12,6 @@
# https://github.com/DSpace/DSpace/blob/main/docker-compose-cli.yml
#
# Therefore, it should be kept in sync with that file
version: "3.7"
networks:
# Default to using network named 'dspacenet' from docker-compose-rest.yml.
# Its full name will be prepended with the project name (e.g. "-p d7" means it will be named "d7_dspacenet")

View File

@@ -12,11 +12,9 @@
# https://github.com/DSpace/DSpace/blob/main/dspace/src/main/docker-compose/db.entities.yml
#
# # Therefore, it should be kept in sync with that file
version: "3.7"
services:
dspacedb:
image: dspace/dspace-postgres-pgcrypto:loadsql
image: dspace/dspace-postgres-pgcrypto::${DSPACE_VER:-latest}-loadsql
environment:
# This LOADSQL should be kept in sync with the URL in DSpace/DSpace
# This SQL is available from https://github.com/DSpace-Labs/AIP-Files/releases/tag/demo-entities-data
@@ -29,23 +27,11 @@ services:
# 3. (Custom for Entities) enable Entity-specific collection submission mappings in item-submission.xml
# This 'sed' command inserts the sample configurations specific to the Entities data set, see:
# https://github.com/DSpace/DSpace/blob/main/dspace/config/item-submission.xml#L36-L49
# 4. Finally, start Tomcat
# 4. Finally, start DSpace
entrypoint:
- /bin/bash
- '-c'
- |
while (!</dev/tcp/dspacedb/5432) > /dev/null 2>&1; do sleep 1; done;
/dspace/bin/dspace database migrate ignored
sed -i '/name-map collection-handle="default".*/a \\n <name-map collection-handle="123456789/3" submission-name="Publication"/> \
<name-map collection-handle="123456789/4" submission-name="Publication"/> \
<name-map collection-handle="123456789/281" submission-name="Publication"/> \
<name-map collection-handle="123456789/5" submission-name="Publication"/> \
<name-map collection-handle="123456789/8" submission-name="OrgUnit"/> \
<name-map collection-handle="123456789/6" submission-name="Person"/> \
<name-map collection-handle="123456789/279" submission-name="Person"/> \
<name-map collection-handle="123456789/7" submission-name="Project"/> \
<name-map collection-handle="123456789/280" submission-name="Project"/> \
<name-map collection-handle="123456789/28" submission-name="Journal"/> \
<name-map collection-handle="123456789/29" submission-name="JournalVolume"/> \
<name-map collection-handle="123456789/30" submission-name="JournalIssue"/>' /dspace/config/item-submission.xml
catalina.sh run
java -jar /dspace/webapps/server-boot.jar --dspace.dir=/dspace

View File

@@ -10,7 +10,6 @@
# This is used by our GitHub CI at .github/workflows/build.yml
# It is based heavily on the Backend's Docker Compose:
# https://github.com/DSpace/DSpace/blob/main/docker-compose.yml
version: '3.7'
networks:
dspacenet:
services:
@@ -33,6 +32,7 @@ services:
# Tell Statistics to commit all views immediately instead of waiting on Solr's autocommit.
# This allows us to generate statistics in e2e tests so that statistics pages can be tested thoroughly.
solr__D__statistics__P__autoCommit: 'false'
LOGGING_CONFIG: /dspace/config/log4j2-container.xml
image: "${DOCKER_OWNER:-dspace}/dspace:${DSPACE_VER:-latest-test}"
depends_on:
- dspacedb
@@ -48,27 +48,31 @@ services:
# Ensure that the database is ready BEFORE starting tomcat
# 1. While a TCP connection to dspacedb port 5432 is not available, continue to sleep
# 2. Then, run database migration to init database tables (including any out-of-order ignored migrations, if any)
# 3. Finally, start Tomcat
# 3. Finally, start DSpace
entrypoint:
- /bin/bash
- '-c'
- |
while (!</dev/tcp/dspacedb/5432) > /dev/null 2>&1; do sleep 1; done;
/dspace/bin/dspace database migrate ignored
catalina.sh run
java -jar /dspace/webapps/server-boot.jar --dspace.dir=/dspace
# DSpace database container
# NOTE: This is customized to use our loadsql image, so that we are using a database with existing test data
dspacedb:
container_name: dspacedb
image: "${DOCKER_OWNER:-dspace}/dspace-postgres-pgcrypto:${DSPACE_VER:-latest}-loadsql"
environment:
# This LOADSQL should be kept in sync with the LOADSQL in
# https://github.com/DSpace/DSpace/blob/main/dspace/src/main/docker-compose/db.entities.yml
# This SQL is available from https://github.com/DSpace-Labs/AIP-Files/releases/tag/demo-entities-data
LOADSQL: https://github.com/DSpace-Labs/AIP-Files/releases/download/demo-entities-data/dspace7-entities-data.sql
PGDATA: /pgdata
image: dspace/dspace-postgres-pgcrypto:loadsql
POSTGRES_PASSWORD: dspace
networks:
- dspacenet
ports:
- published: 5432
target: 5432
stdin_open: true
tty: true
volumes:
@@ -105,6 +109,8 @@ services:
cp -r /opt/solr/server/solr/configsets/statistics/* statistics
precreate-core qaevent /opt/solr/server/solr/configsets/qaevent
cp -r /opt/solr/server/solr/configsets/qaevent/* qaevent
precreate-core suggestion /opt/solr/server/solr/configsets/suggestion
cp -r /opt/solr/server/solr/configsets/suggestion/* suggestion
exec solr -f
volumes:
assetstore:

View File

@@ -8,7 +8,6 @@
# Docker Compose for running the DSpace Angular UI dist build
# for previewing with the DSpace Demo site backend
version: '3.7'
networks:
dspacenet:
services:

View File

@@ -10,7 +10,6 @@
# This is based heavily on the docker-compose.yml that is available in the DSpace/DSpace
# (Backend) at:
# https://github.com/DSpace/DSpace/blob/main/docker-compose.yml
version: '3.7'
networks:
dspacenet:
ipam:
@@ -29,8 +28,9 @@ services:
# __D__ => "-" (e.g. google__D__metadata => google-metadata)
# dspace.dir, dspace.server.url, dspace.ui.url and dspace.name
dspace__P__dir: /dspace
dspace__P__server__P__url: http://localhost:8080/server
dspace__P__ui__P__url: http://localhost:4000
# Uncomment to set a non-default value for dspace.server.url or dspace.ui.url
# dspace__P__server__P__url: http://localhost:8080/server
# dspace__P__ui__P__url: http://localhost:4000
dspace__P__name: 'DSpace Started with Docker Compose'
# db.url: Ensure we are using the 'dspacedb' image for our database
db__P__url: 'jdbc:postgresql://dspacedb:5432/dspace'
@@ -39,6 +39,7 @@ services:
# proxies.trusted.ipranges: This setting is required for a REST API running in Docker to trust requests
# from the host machine. This IP range MUST correspond to the 'dspacenet' subnet defined above.
proxies__P__trusted__P__ipranges: '172.23.0'
LOGGING_CONFIG: /dspace/config/log4j2-container.xml
image: "${DOCKER_OWNER:-dspace}/dspace:${DSPACE_VER:-latest-test}"
depends_on:
- dspacedb
@@ -50,24 +51,27 @@ services:
stdin_open: true
tty: true
volumes:
# Keep DSpace assetstore directory between reboots
- assetstore:/dspace/assetstore
# Ensure that the database is ready BEFORE starting tomcat
# 1. While a TCP connection to dspacedb port 5432 is not available, continue to sleep
# 2. Then, run database migration to init database tables
# 3. Finally, start Tomcat
# 3. Finally, start DSpace
entrypoint:
- /bin/bash
- '-c'
- |
while (!</dev/tcp/dspacedb/5432) > /dev/null 2>&1; do sleep 1; done;
/dspace/bin/dspace database migrate
catalina.sh run
java -jar /dspace/webapps/server-boot.jar --dspace.dir=/dspace
# DSpace database container
dspacedb:
container_name: dspacedb
# Uses a custom Postgres image with pgcrypto installed
image: "${DOCKER_OWNER:-dspace}/dspace-postgres-pgcrypto:${DSPACE_VER:-latest}"
environment:
PGDATA: /pgdata
image: "${DOCKER_OWNER:-dspace}/dspace-postgres-pgcrypto:${DSPACE_VER:-latest}"
POSTGRES_PASSWORD: dspace
networks:
- dspacenet
ports:
@@ -113,6 +117,8 @@ services:
cp -r /opt/solr/server/solr/configsets/statistics/* statistics
precreate-core qaevent /opt/solr/server/solr/configsets/qaevent
cp -r /opt/solr/server/solr/configsets/qaevent/* qaevent
precreate-core suggestion /opt/solr/server/solr/configsets/suggestion
cp -r /opt/solr/server/solr/configsets/suggestion/* suggestion
exec solr -f
volumes:
assetstore:

View File

@@ -9,7 +9,6 @@
# Docker Compose for running the DSpace Angular UI for testing/development
# Requires also running a REST API backend (either locally or remotely),
# for example via 'docker-compose-rest.yml'
version: '3.7'
networks:
dspacenet:
services:

4
docs/lint/html/index.md Normal file
View File

@@ -0,0 +1,4 @@
[DSpace ESLint plugins](../../../lint/README.md) > HTML rules
_______
- [`dspace-angular-html/themed-component-usages`](./rules/themed-component-usages.md): Themeable components should be used via the selector of their `ThemedComponent` wrapper class

View File

@@ -0,0 +1,110 @@
[DSpace ESLint plugins](../../../../lint/README.md) > [HTML rules](../index.md) > `dspace-angular-html/themed-component-usages`
_______
Themeable components should be used via the selector of their `ThemedComponent` wrapper class
This ensures that custom themes can correctly override _all_ instances of this component.
The only exception to this rule are unit tests, where we may want to use the base component in order to keep the test setup simple.
_______
[Source code](../../../../lint/src/rules/html/themed-component-usages.ts)
### Examples
#### Valid code
##### use no-prefix selectors in HTML templates
```html
<ds-test-themeable/>
<ds-test-themeable></ds-test-themeable>
<ds-test-themeable [test]="something"></ds-test-themeable>
```
##### use no-prefix selectors in TypeScript templates
```html
@Component({
template: '<ds-test-themeable></ds-test-themeable>'
})
class Test {
}
```
##### use no-prefix selectors in TypeScript test templates
Filename: `lint/test/fixture/src/test.spec.ts`
```html
@Component({
template: '<ds-test-themeable></ds-test-themeable>'
})
class Test {
}
```
##### base selectors are also allowed in TypeScript test templates
Filename: `lint/test/fixture/src/test.spec.ts`
```html
@Component({
template: '<ds-base-test-themeable></ds-base-test-themeable>'
})
class Test {
}
```
#### Invalid code &amp; automatic fixes
##### themed override selectors are not allowed in HTML templates
```html
<ds-themed-test-themeable/>
<ds-themed-test-themeable></ds-themed-test-themeable>
<ds-themed-test-themeable [test]="something"></ds-themed-test-themeable>
```
Will produce the following error(s):
```
Themeable components should be used via their ThemedComponent wrapper's selector
Themeable components should be used via their ThemedComponent wrapper's selector
Themeable components should be used via their ThemedComponent wrapper's selector
```
Result of `yarn lint --fix`:
```html
<ds-test-themeable/>
<ds-test-themeable></ds-test-themeable>
<ds-test-themeable [test]="something"></ds-test-themeable>
```
##### base selectors are not allowed in HTML templates
```html
<ds-base-test-themeable/>
<ds-base-test-themeable></ds-base-test-themeable>
<ds-base-test-themeable [test]="something"></ds-base-test-themeable>
```
Will produce the following error(s):
```
Themeable components should be used via their ThemedComponent wrapper's selector
Themeable components should be used via their ThemedComponent wrapper's selector
Themeable components should be used via their ThemedComponent wrapper's selector
```
Result of `yarn lint --fix`:
```html
<ds-test-themeable/>
<ds-test-themeable></ds-test-themeable>
<ds-test-themeable [test]="something"></ds-test-themeable>
```

6
docs/lint/ts/index.md Normal file
View File

@@ -0,0 +1,6 @@
[DSpace ESLint plugins](../../../lint/README.md) > TypeScript rules
_______
- [`dspace-angular-ts/themed-component-classes`](./rules/themed-component-classes.md): Formatting rules for themeable component classes
- [`dspace-angular-ts/themed-component-selectors`](./rules/themed-component-selectors.md): Themeable component selectors should follow the DSpace convention
- [`dspace-angular-ts/themed-component-usages`](./rules/themed-component-usages.md): Themeable components should be used via their `ThemedComponent` wrapper class

View File

@@ -0,0 +1,257 @@
[DSpace ESLint plugins](../../../../lint/README.md) > [TypeScript rules](../index.md) > `dspace-angular-ts/themed-component-classes`
_______
Formatting rules for themeable component classes
- All themeable components must be standalone.
- The base component must always be imported in the `ThemedComponent` wrapper. This ensures that it is always sufficient to import just the wrapper whenever we use the component.
_______
[Source code](../../../../lint/src/rules/ts/themed-component-classes.ts)
### Examples
#### Valid code
##### Regular non-themeable component
```typescript
@Component({
selector: 'ds-something',
standalone: true,
})
class Something {
}
```
##### Base component
```typescript
@Component({
selector: 'ds-base-test-themable',
standalone: true,
})
class TestThemeableTomponent {
}
```
##### Wrapper component
Filename: `lint/test/fixture/src/app/test/themed-test-themeable.component.ts`
```typescript
@Component({
selector: 'ds-test-themable',
standalone: true,
imports: [
TestThemeableComponent,
],
})
class ThemedTestThemeableTomponent extends ThemedComponent<TestThemeableComponent> {
}
```
##### Override component
Filename: `lint/test/fixture/src/themes/test/app/test/test-themeable.component.ts`
```typescript
@Component({
selector: 'ds-themed-test-themable',
standalone: true,
})
class Override extends BaseComponent {
}
```
#### Invalid code &amp; automatic fixes
##### Base component must be standalone
```typescript
@Component({
selector: 'ds-base-test-themable',
})
class TestThemeableComponent {
}
```
Will produce the following error(s):
```
Themeable components must be standalone
```
Result of `yarn lint --fix`:
```typescript
@Component({
selector: 'ds-base-test-themable',
standalone: true,
})
class TestThemeableComponent {
}
```
##### Wrapper component must be standalone and import base component
Filename: `lint/test/fixture/src/app/test/themed-test-themeable.component.ts`
```typescript
@Component({
selector: 'ds-test-themable',
})
class ThemedTestThemeableComponent extends ThemedComponent<TestThemeableComponent> {
}
```
Will produce the following error(s):
```
Themeable component wrapper classes must be standalone and import the base class
```
Result of `yarn lint --fix`:
```typescript
@Component({
selector: 'ds-test-themable',
standalone: true,
imports: [TestThemeableComponent],
})
class ThemedTestThemeableComponent extends ThemedComponent<TestThemeableComponent> {
}
```
##### Wrapper component must import base component (array present but empty)
Filename: `lint/test/fixture/src/app/test/themed-test-themeable.component.ts`
```typescript
@Component({
selector: 'ds-test-themable',
standalone: true,
imports: [],
})
class ThemedTestThemeableComponent extends ThemedComponent<TestThemeableComponent> {
}
```
Will produce the following error(s):
```
Themed component wrapper classes must only import the base class
```
Result of `yarn lint --fix`:
```typescript
@Component({
selector: 'ds-test-themable',
standalone: true,
imports: [TestThemeableComponent],
})
class ThemedTestThemeableComponent extends ThemedComponent<TestThemeableComponent> {
}
```
##### Wrapper component must import base component (array is wrong)
Filename: `lint/test/fixture/src/app/test/themed-test-themeable.component.ts`
```typescript
import { SomethingElse } from './somewhere-else';
@Component({
selector: 'ds-test-themable',
standalone: true,
imports: [
SomethingElse,
],
})
class ThemedTestThemeableComponent extends ThemedComponent<TestThemeableComponent> {
}
```
Will produce the following error(s):
```
Themed component wrapper classes must only import the base class
```
Result of `yarn lint --fix`:
```typescript
import { SomethingElse } from './somewhere-else';
@Component({
selector: 'ds-test-themable',
standalone: true,
imports: [TestThemeableComponent],
})
class ThemedTestThemeableComponent extends ThemedComponent<TestThemeableComponent> {
}
```
##### Wrapper component must import base component (array is wrong)
Filename: `lint/test/fixture/src/app/test/themed-test-themeable.component.ts`
```typescript
import { Something, SomethingElse } from './somewhere-else';
@Component({
selector: 'ds-test-themable',
standalone: true,
imports: [
SomethingElse,
],
})
class ThemedTestThemeableComponent extends ThemedComponent<TestThemeableComponent> {
}
```
Will produce the following error(s):
```
Themed component wrapper classes must only import the base class
```
Result of `yarn lint --fix`:
```typescript
import { Something, SomethingElse } from './somewhere-else';
@Component({
selector: 'ds-test-themable',
standalone: true,
imports: [TestThemeableComponent],
})
class ThemedTestThemeableComponent extends ThemedComponent<TestThemeableComponent> {
}
```
##### Override component must be standalone
Filename: `lint/test/fixture/src/themes/test/app/test/test-themeable.component.ts`
```typescript
@Component({
selector: 'ds-themed-test-themable',
})
class Override extends BaseComponent {
}
```
Will produce the following error(s):
```
Themeable components must be standalone
```
Result of `yarn lint --fix`:
```typescript
@Component({
selector: 'ds-themed-test-themable',
standalone: true,
})
class Override extends BaseComponent {
}
```

View File

@@ -0,0 +1,156 @@
[DSpace ESLint plugins](../../../../lint/README.md) > [TypeScript rules](../index.md) > `dspace-angular-ts/themed-component-selectors`
_______
Themeable component selectors should follow the DSpace convention
Each themeable component is comprised of a base component, a wrapper component and any number of themed components
- Base components should have a selector starting with `ds-base-`
- Themed components should have a selector starting with `ds-themed-`
- Wrapper components should have a selector starting with `ds-`, but not `ds-base-` or `ds-themed-`
- This is the regular DSpace selector prefix
- **When making a regular component themeable, its selector prefix should be changed to `ds-base-`, and the new wrapper's component should reuse the previous selector**
Unit tests are exempt from this rule, because they may redefine components using the same class name as other themeable components elsewhere in the source.
_______
[Source code](../../../../lint/src/rules/ts/themed-component-selectors.ts)
### Examples
#### Valid code
##### Regular non-themeable component selector
```typescript
@Component({
selector: 'ds-something',
})
class Something {
}
```
##### Themeable component selector should replace the original version, unthemed version should be changed to ds-base-
```typescript
@Component({
selector: 'ds-base-something',
})
class Something {
}
@Component({
selector: 'ds-something',
})
class ThemedSomething extends ThemedComponent<Something> {
}
@Component({
selector: 'ds-themed-something',
})
class OverrideSomething extends Something {
}
```
##### Other themed component wrappers should not interfere
```typescript
@Component({
selector: 'ds-something',
})
class Something {
}
@Component({
selector: 'ds-something-else',
})
class ThemedSomethingElse extends ThemedComponent<SomethingElse> {
}
```
#### Invalid code &amp; automatic fixes
##### Wrong selector for base component
Filename: `lint/test/fixture/src/app/test/test-themeable.component.ts`
```typescript
@Component({
selector: 'ds-something',
})
class TestThemeableComponent {
}
```
Will produce the following error(s):
```
Unthemed version of themeable component should have a selector starting with 'ds-base-'
```
Result of `yarn lint --fix`:
```typescript
@Component({
selector: 'ds-base-something',
})
class TestThemeableComponent {
}
```
##### Wrong selector for wrapper component
Filename: `lint/test/fixture/src/app/test/themed-test-themeable.component.ts`
```typescript
@Component({
selector: 'ds-themed-something',
})
class ThemedTestThemeableComponent extends ThemedComponent<TestThemeableComponent> {
}
```
Will produce the following error(s):
```
Themed component wrapper of themeable component shouldn't have a selector starting with 'ds-themed-'
```
Result of `yarn lint --fix`:
```typescript
@Component({
selector: 'ds-something',
})
class ThemedTestThemeableComponent extends ThemedComponent<TestThemeableComponent> {
}
```
##### Wrong selector for theme override
Filename: `lint/test/fixture/src/themes/test/app/test/test-themeable.component.ts`
```typescript
@Component({
selector: 'ds-something',
})
class TestThememeableComponent extends BaseComponent {
}
```
Will produce the following error(s):
```
Theme override of themeable component should have a selector starting with 'ds-themed-'
```
Result of `yarn lint --fix`:
```typescript
@Component({
selector: 'ds-themed-something',
})
class TestThememeableComponent extends BaseComponent {
}
```

View File

@@ -0,0 +1,332 @@
[DSpace ESLint plugins](../../../../lint/README.md) > [TypeScript rules](../index.md) > `dspace-angular-ts/themed-component-usages`
_______
Themeable components should be used via their `ThemedComponent` wrapper class
This ensures that custom themes can correctly override _all_ instances of this component.
There are a few exceptions where the base class can still be used:
- Class declaration expressions (otherwise we can't declare, extend or override the class in the first place)
- Angular modules (except for routing modules)
- Angular `@ViewChild` decorators
- Type annotations
_______
[Source code](../../../../lint/src/rules/ts/themed-component-usages.ts)
### Examples
#### Valid code
##### allow wrapper class usages
```typescript
import { ThemedTestThemeableComponent } from './app/test/themed-test-themeable.component';
const config = {
a: ThemedTestThemeableComponent,
b: ChipsComponent,
}
```
##### allow base class in class declaration
```typescript
export class TestThemeableComponent {
}
```
##### allow inheriting from base class
```typescript
import { TestThemeableComponent } from './app/test/test-themeable.component';
export class ThemedAdminSidebarComponent extends ThemedComponent<TestThemeableComponent> {
}
```
##### allow base class in ViewChild
```typescript
import { TestThemeableComponent } from './app/test/test-themeable.component';
export class Something {
@ViewChild(TestThemeableComponent) test: TestThemeableComponent;
}
```
##### allow wrapper selectors in test queries
Filename: `lint/test/fixture/src/app/test/test.component.spec.ts`
```typescript
By.css('ds-themeable');
By.css('#test > ds-themeable > #nest');
```
##### allow wrapper selectors in cypress queries
Filename: `lint/test/fixture/src/app/test/test.component.cy.ts`
```typescript
By.css('ds-themeable');
By.css('#test > ds-themeable > #nest');
```
#### Invalid code &amp; automatic fixes
##### disallow direct usages of base class
```typescript
import { TestThemeableComponent } from './app/test/test-themeable.component';
import { TestComponent } from './app/test/test.component';
const config = {
a: TestThemeableComponent,
b: TestComponent,
}
```
Will produce the following error(s):
```
Themeable components should be used via their ThemedComponent wrapper
Themeable components should be used via their ThemedComponent wrapper
```
Result of `yarn lint --fix`:
```typescript
import { ThemedTestThemeableComponent } from './app/test/themed-test-themeable.component';
import { TestComponent } from './app/test/test.component';
const config = {
a: ThemedTestThemeableComponent,
b: TestComponent,
}
```
##### disallow direct usages of base class, keep other imports
```typescript
import { Something, TestThemeableComponent } from './app/test/test-themeable.component';
import { TestComponent } from './app/test/test.component';
const config = {
a: TestThemeableComponent,
b: TestComponent,
c: Something,
}
```
Will produce the following error(s):
```
Themeable components should be used via their ThemedComponent wrapper
Themeable components should be used via their ThemedComponent wrapper
```
Result of `yarn lint --fix`:
```typescript
import { Something } from './app/test/test-themeable.component';
import { ThemedTestThemeableComponent } from './app/test/themed-test-themeable.component';
import { TestComponent } from './app/test/test.component';
const config = {
a: ThemedTestThemeableComponent,
b: TestComponent,
c: Something,
}
```
##### handle array replacements correctly
```typescript
const DECLARATIONS = [
Something,
TestThemeableComponent,
Something,
ThemedTestThemeableComponent,
];
```
Will produce the following error(s):
```
Themeable components should be used via their ThemedComponent wrapper
```
Result of `yarn lint --fix`:
```typescript
const DECLARATIONS = [
Something,
Something,
ThemedTestThemeableComponent,
];
```
##### disallow override selector in test queries
Filename: `lint/test/fixture/src/app/test/test.component.spec.ts`
```typescript
By.css('ds-themed-themeable');
By.css('#test > ds-themed-themeable > #nest');
```
Will produce the following error(s):
```
Themeable components should be used via their ThemedComponent wrapper
Themeable components should be used via their ThemedComponent wrapper
```
Result of `yarn lint --fix`:
```typescript
By.css('ds-themeable');
By.css('#test > ds-themeable > #nest');
```
##### disallow base selector in test queries
Filename: `lint/test/fixture/src/app/test/test.component.spec.ts`
```typescript
By.css('ds-base-themeable');
By.css('#test > ds-base-themeable > #nest');
```
Will produce the following error(s):
```
Themeable components should be used via their ThemedComponent wrapper
Themeable components should be used via their ThemedComponent wrapper
```
Result of `yarn lint --fix`:
```typescript
By.css('ds-themeable');
By.css('#test > ds-themeable > #nest');
```
##### disallow override selector in cypress queries
Filename: `lint/test/fixture/src/app/test/test.component.cy.ts`
```typescript
cy.get('ds-themed-themeable');
cy.get('#test > ds-themed-themeable > #nest');
```
Will produce the following error(s):
```
Themeable components should be used via their ThemedComponent wrapper
Themeable components should be used via their ThemedComponent wrapper
```
Result of `yarn lint --fix`:
```typescript
cy.get('ds-themeable');
cy.get('#test > ds-themeable > #nest');
```
##### disallow base selector in cypress queries
Filename: `lint/test/fixture/src/app/test/test.component.cy.ts`
```typescript
cy.get('ds-base-themeable');
cy.get('#test > ds-base-themeable > #nest');
```
Will produce the following error(s):
```
Themeable components should be used via their ThemedComponent wrapper
Themeable components should be used via their ThemedComponent wrapper
```
Result of `yarn lint --fix`:
```typescript
cy.get('ds-themeable');
cy.get('#test > ds-themeable > #nest');
```
##### edge case: unable to find usage node through usage token, but import is still flagged and fixed
Filename: `lint/test/fixture/src/themes/test/app/test/other-themeable.component.ts`
```typescript
import { Component } from '@angular/core';
import { Context } from './app/core/shared/context.model';
import { TestThemeableComponent } from '../../../../app/test/test-themeable.component';
@Component({
standalone: true,
imports: [TestThemeableComponent],
})
export class UsageComponent {
}
```
Will produce the following error(s):
```
Themeable components should be used via their ThemedComponent wrapper
Themeable components should be used via their ThemedComponent wrapper
```
Result of `yarn lint --fix`:
```typescript
import { Component } from '@angular/core';
import { Context } from './app/core/shared/context.model';
import { ThemedTestThemeableComponent } from '../../../../app/test/themed-test-themeable.component';
@Component({
standalone: true,
imports: [ThemedTestThemeableComponent],
})
export class UsageComponent {
}
```
##### edge case edge case: both are imported, only wrapper is retained
Filename: `lint/test/fixture/src/themes/test/app/test/other-themeable.component.ts`
```typescript
import { Component } from '@angular/core';
import { Context } from './app/core/shared/context.model';
import { TestThemeableComponent } from '../../../../app/test/test-themeable.component';
import { ThemedTestThemeableComponent } from '../../../../app/test/themed-test-themeable.component';
@Component({
standalone: true,
imports: [TestThemeableComponent, ThemedTestThemeableComponent],
})
export class UsageComponent {
}
```
Will produce the following error(s):
```
Themeable components should be used via their ThemedComponent wrapper
Themeable components should be used via their ThemedComponent wrapper
```
Result of `yarn lint --fix`:
```typescript
import { Component } from '@angular/core';
import { Context } from './app/core/shared/context.model';
import { ThemedTestThemeableComponent } from '../../../../app/test/themed-test-themeable.component';
@Component({
standalone: true,
imports: [ThemedTestThemeableComponent],
})
export class UsageComponent {
}
```

3
lint/.gitignore vendored Normal file
View File

@@ -0,0 +1,3 @@
/dist/
/coverage/
/node-modules/

50
lint/README.md Normal file
View File

@@ -0,0 +1,50 @@
# DSpace ESLint plugins
Custom ESLint rules for DSpace Angular peculiarities.
## Usage
These plugins are included with the rest of our ESLint configuration in [.eslintc.json](../.eslintrc.json). Individual rules can be configured or disabled there, like usual.
- In order for the new rules to be picked up by your IDE, you should first run `yarn build:lint` to build the plugins.
- This will also happen automatically each time `yarn lint` is run.
## Documentation
The rules are split up into plugins by language:
- [TypeScript rules](../docs/lint/ts/index.md)
- [HTML rules](../docs/lint/html/index.md)
> Run `yarn docs:lint` to generate this documentation!
## Developing
### Overview
- All rules are written in TypeScript and compiled into [`dist`](./dist)
- The plugins are linked into the main project dependencies from here
- These directories already contain the necessary `package.json` files to mark them as ESLint plugins
- Rule source files are structured, so they can be imported all in one go
- Each rule must export the following:
- `Messages`: an Enum of error message IDs
- `info`: metadata about this rule (name, description, messages, options, ...)
- `rule`: the implementation of the rule
- `tests`: the tests for this rule, as a set of valid/invalid code snippets. These snippets are used as example in the documentation.
- New rules should be added to their plugin's `index.ts`
- Some useful links
- [Developing ESLint plugins](https://eslint.org/docs/latest/extend/plugins)
- [Custom rules in typescript-eslint](https://typescript-eslint.io/developers/custom-rules)
- [Angular ESLint](https://github.com/angular-eslint/angular-eslint)
### Parsing project metadata in advance ~ TypeScript AST
While it is possible to retain persistent state between files during the linting process, it becomes quite complicated if the content of one file determines how we want to lint another file.
Because the two files may be linted out of order, we may not know whether the first file is wrong before we pass by the second. This means that we cannot report or fix the issue, because the first file is already detached from the linting context.
For example, we cannot consistently determine which components are themeable (i.e. have a `ThemedComponent` wrapper) while linting.
To work around this issue, we construct a registry of themeable components _before_ linting anything.
- We don't have a good way to hook into the ESLint parser at this time
- Instead, we leverage the actual TypeScript AST parser
- Retrieve all `ThemedComponent` wrapper files by the pattern of their path (`themed-*.component.ts`)
- Determine the themed component they're linked to (by the actual type annotation/import path, since filenames are prone to errors)
- Store metadata describing these component pairs in a global registry that can be shared between rules
- This only needs to happen once, and only takes a fraction of a second (for ~100 themeable components)

6
lint/dist/src/rules/html/package.json vendored Normal file
View File

@@ -0,0 +1,6 @@
{
"name": "eslint-plugin-dspace-angular-html",
"version": "0.0.0",
"main": "./index.js",
"private": true
}

6
lint/dist/src/rules/ts/package.json vendored Normal file
View File

@@ -0,0 +1,6 @@
{
"name": "eslint-plugin-dspace-angular-ts",
"version": "0.0.0",
"main": "./index.js",
"private": true
}

85
lint/generate-docs.ts Normal file
View File

@@ -0,0 +1,85 @@
/**
* The contents of this file are subject to the license and copyright
* detailed in the LICENSE and NOTICE files at the root of the source
* tree and available online at
*
* http://www.dspace.org/license/
*/
import {
existsSync,
mkdirSync,
readFileSync,
rmSync,
writeFileSync,
} from 'fs';
import { join } from 'path';
import { default as htmlPlugin } from './src/rules/html';
import { default as tsPlugin } from './src/rules/ts';
const templates = new Map();
function lazyEJS(path: string, data: object): string {
if (!templates.has(path)) {
templates.set(path, require('ejs').compile(readFileSync(path).toString()));
}
return templates.get(path)(data).replace(/\r\n/g, '\n');
}
const docsDir = join('docs', 'lint');
const tsDir = join(docsDir, 'ts');
const htmlDir = join(docsDir, 'html');
if (existsSync(docsDir)) {
rmSync(docsDir, { recursive: true });
}
mkdirSync(join(tsDir, 'rules'), { recursive: true });
mkdirSync(join(htmlDir, 'rules'), { recursive: true });
function template(name: string): string {
return join('lint', 'src', 'util', 'templates', name);
}
// TypeScript docs
writeFileSync(
join(tsDir, 'index.md'),
lazyEJS(template('index.ejs'), {
plugin: tsPlugin,
rules: tsPlugin.index.map(rule => rule.info),
}),
);
for (const rule of tsPlugin.index) {
writeFileSync(
join(tsDir, 'rules', rule.info.name + '.md'),
lazyEJS(template('rule.ejs'), {
plugin: tsPlugin,
rule: rule.info,
tests: rule.tests,
}),
);
}
// HTML docs
writeFileSync(
join(htmlDir, 'index.md'),
lazyEJS(template('index.ejs'), {
plugin: htmlPlugin,
rules: htmlPlugin.index.map(rule => rule.info),
}),
);
for (const rule of htmlPlugin.index) {
writeFileSync(
join(htmlDir, 'rules', rule.info.name + '.md'),
lazyEJS(template('rule.ejs'), {
plugin: htmlPlugin,
rule: rule.info,
tests: rule.tests,
}),
);
}

7
lint/jasmine.json Normal file
View File

@@ -0,0 +1,7 @@
{
"spec_files": ["**/*.spec.js"],
"spec_dir": "lint/dist/test",
"helpers": [
"./test/helpers.js"
]
}

View File

@@ -0,0 +1,22 @@
/**
* 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/
*/
/* eslint-disable import/no-namespace */
import {
bundle,
RuleExports,
} from '../../util/structure';
import * as themedComponentUsages from './themed-component-usages';
const index = [
themedComponentUsages,
] as unknown as RuleExports[];
export = {
parser: require('@angular-eslint/template-parser'),
...bundle('dspace-angular-html', 'HTML', index),
};

View File

@@ -0,0 +1,191 @@
/**
* The contents of this file are subject to the license and copyright
* detailed in the LICENSE and NOTICE files at the root of the source
* tree and available online at
*
* http://www.dspace.org/license/
*/
import { TmplAstElement } from '@angular-eslint/bundled-angular-compiler';
import { TemplateParserServices } from '@angular-eslint/utils';
import {
ESLintUtils,
TSESLint,
} from '@typescript-eslint/utils';
import { fixture } from '../../../test/fixture';
import {
DSpaceESLintRuleInfo,
NamedTests,
} from '../../util/structure';
import {
DISALLOWED_THEME_SELECTORS,
fixSelectors,
} from '../../util/theme-support';
import {
getFilename,
getSourceCode,
} from '../../util/typescript';
export enum Message {
WRONG_SELECTOR = 'mustUseThemedWrapperSelector',
}
export const info = {
name: 'themed-component-usages',
meta: {
docs: {
description: `Themeable components should be used via the selector of their \`ThemedComponent\` wrapper class
This ensures that custom themes can correctly override _all_ instances of this component.
The only exception to this rule are unit tests, where we may want to use the base component in order to keep the test setup simple.
`,
},
type: 'problem',
fixable: 'code',
schema: [],
messages: {
[Message.WRONG_SELECTOR]: 'Themeable components should be used via their ThemedComponent wrapper\'s selector',
},
},
defaultOptions: [],
} as DSpaceESLintRuleInfo;
export const rule = ESLintUtils.RuleCreator.withoutDocs({
...info,
create(context: TSESLint.RuleContext<Message, unknown[]>) {
if (getFilename(context).includes('.spec.ts')) {
// skip inline templates in unit tests
return {};
}
const parserServices = getSourceCode(context).parserServices as TemplateParserServices;
return {
[`Element$1[name = /^${DISALLOWED_THEME_SELECTORS}/]`](node: TmplAstElement) {
const { startSourceSpan, endSourceSpan } = node;
const openStart = startSourceSpan.start.offset as number;
context.report({
messageId: Message.WRONG_SELECTOR,
loc: parserServices.convertNodeSourceSpanToLoc(startSourceSpan),
fix(fixer) {
const oldSelector = node.name;
const newSelector = fixSelectors(oldSelector);
const ops = [
fixer.replaceTextRange([openStart + 1, openStart + 1 + oldSelector.length], newSelector),
];
// make sure we don't mangle self-closing tags
if (endSourceSpan !== null && startSourceSpan.end.offset !== endSourceSpan.end.offset) {
const closeStart = endSourceSpan.start.offset as number;
const closeEnd = endSourceSpan.end.offset as number;
ops.push(fixer.replaceTextRange([closeStart + 2, closeEnd - 1], newSelector));
}
return ops;
},
});
},
};
},
});
export const tests = {
plugin: info.name,
valid: [
{
name: 'use no-prefix selectors in HTML templates',
code: `
<ds-test-themeable/>
<ds-test-themeable></ds-test-themeable>
<ds-test-themeable [test]="something"></ds-test-themeable>
`,
},
{
name: 'use no-prefix selectors in TypeScript templates',
code: `
@Component({
template: '<ds-test-themeable></ds-test-themeable>'
})
class Test {
}
`,
},
{
name: 'use no-prefix selectors in TypeScript test templates',
filename: fixture('src/test.spec.ts'),
code: `
@Component({
template: '<ds-test-themeable></ds-test-themeable>'
})
class Test {
}
`,
},
{
name: 'base selectors are also allowed in TypeScript test templates',
filename: fixture('src/test.spec.ts'),
code: `
@Component({
template: '<ds-base-test-themeable></ds-base-test-themeable>'
})
class Test {
}
`,
},
],
invalid: [
{
name: 'themed override selectors are not allowed in HTML templates',
code: `
<ds-themed-test-themeable/>
<ds-themed-test-themeable></ds-themed-test-themeable>
<ds-themed-test-themeable [test]="something"></ds-themed-test-themeable>
`,
errors: [
{
messageId: Message.WRONG_SELECTOR,
},
{
messageId: Message.WRONG_SELECTOR,
},
{
messageId: Message.WRONG_SELECTOR,
},
],
output: `
<ds-test-themeable/>
<ds-test-themeable></ds-test-themeable>
<ds-test-themeable [test]="something"></ds-test-themeable>
`,
},
{
name: 'base selectors are not allowed in HTML templates',
code: `
<ds-base-test-themeable/>
<ds-base-test-themeable></ds-base-test-themeable>
<ds-base-test-themeable [test]="something"></ds-base-test-themeable>
`,
errors: [
{
messageId: Message.WRONG_SELECTOR,
},
{
messageId: Message.WRONG_SELECTOR,
},
{
messageId: Message.WRONG_SELECTOR,
},
],
output: `
<ds-test-themeable/>
<ds-test-themeable></ds-test-themeable>
<ds-test-themeable [test]="something"></ds-test-themeable>
`,
},
],
} as NamedTests;
export default rule;

View File

@@ -0,0 +1,25 @@
/**
* The contents of this file are subject to the license and copyright
* detailed in the LICENSE and NOTICE files at the root of the source
* tree and available online at
*
* http://www.dspace.org/license/
*/
import {
bundle,
RuleExports,
} from '../../util/structure';
/* eslint-disable import/no-namespace */
import * as themedComponentClasses from './themed-component-classes';
import * as themedComponentSelectors from './themed-component-selectors';
import * as themedComponentUsages from './themed-component-usages';
const index = [
themedComponentClasses,
themedComponentSelectors,
themedComponentUsages,
] as unknown as RuleExports[];
export = {
...bundle('dspace-angular-ts', 'TypeScript', index),
};

View File

@@ -0,0 +1,382 @@
/**
* The contents of this file are subject to the license and copyright
* detailed in the LICENSE and NOTICE files at the root of the source
* tree and available online at
*
* http://www.dspace.org/license/
*/
import {
ESLintUtils,
TSESLint,
TSESTree,
} from '@typescript-eslint/utils';
import { fixture } from '../../../test/fixture';
import {
getComponentImportNode,
getComponentInitializer,
getComponentStandaloneNode,
} from '../../util/angular';
import { appendObjectProperties } from '../../util/fix';
import { DSpaceESLintRuleInfo } from '../../util/structure';
import {
getBaseComponentClassName,
inThemedComponentOverrideFile,
isThemeableComponent,
isThemedComponentWrapper,
} from '../../util/theme-support';
import { getFilename } from '../../util/typescript';
export enum Message {
NOT_STANDALONE = 'mustBeStandalone',
NOT_STANDALONE_IMPORTS_BASE = 'mustBeStandaloneAndImportBase',
WRAPPER_IMPORTS_BASE = 'wrapperShouldImportBase',
}
export const info = {
name: 'themed-component-classes',
meta: {
docs: {
description: `Formatting rules for themeable component classes
- All themeable components must be standalone.
- The base component must always be imported in the \`ThemedComponent\` wrapper. This ensures that it is always sufficient to import just the wrapper whenever we use the component.
`,
},
type: 'problem',
fixable: 'code',
schema: [],
messages: {
[Message.NOT_STANDALONE]: 'Themeable components must be standalone',
[Message.NOT_STANDALONE_IMPORTS_BASE]: 'Themeable component wrapper classes must be standalone and import the base class',
[Message.WRAPPER_IMPORTS_BASE]: 'Themed component wrapper classes must only import the base class',
},
},
defaultOptions: [],
} as DSpaceESLintRuleInfo;
export const rule = ESLintUtils.RuleCreator.withoutDocs({
...info,
create(context: TSESLint.RuleContext<Message, unknown[]>) {
const filename = getFilename(context);
if (filename.endsWith('.spec.ts')) {
return {};
}
function enforceStandalone(decoratorNode: TSESTree.Decorator, withBaseImport = false) {
const standaloneNode = getComponentStandaloneNode(decoratorNode);
if (standaloneNode === undefined) {
// We may need to add these properties in one go
if (!withBaseImport) {
context.report({
messageId: Message.NOT_STANDALONE,
node: decoratorNode,
fix(fixer) {
const initializer = getComponentInitializer(decoratorNode);
return appendObjectProperties(context, fixer, initializer, ['standalone: true']);
},
});
}
} else if (!standaloneNode.value) {
context.report({
messageId: Message.NOT_STANDALONE,
node: standaloneNode,
fix(fixer) {
return fixer.replaceText(standaloneNode, 'true');
},
});
}
if (withBaseImport) {
const baseClass = getBaseComponentClassName(decoratorNode);
if (baseClass === undefined) {
return;
}
const importsNode = getComponentImportNode(decoratorNode);
if (importsNode === undefined) {
if (standaloneNode === undefined) {
context.report({
messageId: Message.NOT_STANDALONE_IMPORTS_BASE,
node: decoratorNode,
fix(fixer) {
const initializer = getComponentInitializer(decoratorNode);
return appendObjectProperties(context, fixer, initializer, ['standalone: true', `imports: [${baseClass}]`]);
},
});
} else {
context.report({
messageId: Message.WRAPPER_IMPORTS_BASE,
node: decoratorNode,
fix(fixer) {
const initializer = getComponentInitializer(decoratorNode);
return appendObjectProperties(context, fixer, initializer, [`imports: [${baseClass}]`]);
},
});
}
} else {
// If we have an imports node, standalone: true will be enforced by another rule
const imports = importsNode.elements.map(e => (e as TSESTree.Identifier).name);
if (!imports.includes(baseClass) || imports.length > 1) {
// The wrapper should _only_ import the base component
context.report({
messageId: Message.WRAPPER_IMPORTS_BASE,
node: importsNode,
fix(fixer) {
// todo: this may leave unused imports, but that's better than mangling things
return fixer.replaceText(importsNode, `[${baseClass}]`);
},
});
}
}
}
}
return {
'ClassDeclaration > Decorator[expression.callee.name = "Component"]'(node: TSESTree.Decorator) {
const classNode = node.parent as TSESTree.ClassDeclaration;
const className = classNode.id?.name;
if (className === undefined) {
return;
}
if (isThemedComponentWrapper(node)) {
enforceStandalone(node, true);
} else if (inThemedComponentOverrideFile(filename)) {
enforceStandalone(node);
} else if (isThemeableComponent(className)) {
enforceStandalone(node);
}
},
};
},
});
export const tests = {
plugin: info.name,
valid: [
{
name: 'Regular non-themeable component',
code: `
@Component({
selector: 'ds-something',
standalone: true,
})
class Something {
}
`,
},
{
name: 'Base component',
code: `
@Component({
selector: 'ds-base-test-themable',
standalone: true,
})
class TestThemeableTomponent {
}
`,
},
{
name: 'Wrapper component',
filename: fixture('src/app/test/themed-test-themeable.component.ts'),
code: `
@Component({
selector: 'ds-test-themable',
standalone: true,
imports: [
TestThemeableComponent,
],
})
class ThemedTestThemeableTomponent extends ThemedComponent<TestThemeableComponent> {
}
`,
},
{
name: 'Override component',
filename: fixture('src/themes/test/app/test/test-themeable.component.ts'),
code: `
@Component({
selector: 'ds-themed-test-themable',
standalone: true,
})
class Override extends BaseComponent {
}
`,
},
],
invalid: [
{
name: 'Base component must be standalone',
code: `
@Component({
selector: 'ds-base-test-themable',
})
class TestThemeableComponent {
}
`,
errors:[
{
messageId: Message.NOT_STANDALONE,
},
],
output: `
@Component({
selector: 'ds-base-test-themable',
standalone: true,
})
class TestThemeableComponent {
}
`,
},
{
name: 'Wrapper component must be standalone and import base component',
filename: fixture('src/app/test/themed-test-themeable.component.ts'),
code: `
@Component({
selector: 'ds-test-themable',
})
class ThemedTestThemeableComponent extends ThemedComponent<TestThemeableComponent> {
}
`,
errors:[
{
messageId: Message.NOT_STANDALONE_IMPORTS_BASE,
},
],
output: `
@Component({
selector: 'ds-test-themable',
standalone: true,
imports: [TestThemeableComponent],
})
class ThemedTestThemeableComponent extends ThemedComponent<TestThemeableComponent> {
}
`,
},
{
name: 'Wrapper component must import base component (array present but empty)',
filename: fixture('src/app/test/themed-test-themeable.component.ts'),
code: `
@Component({
selector: 'ds-test-themable',
standalone: true,
imports: [],
})
class ThemedTestThemeableComponent extends ThemedComponent<TestThemeableComponent> {
}
`,
errors:[
{
messageId: Message.WRAPPER_IMPORTS_BASE,
},
],
output: `
@Component({
selector: 'ds-test-themable',
standalone: true,
imports: [TestThemeableComponent],
})
class ThemedTestThemeableComponent extends ThemedComponent<TestThemeableComponent> {
}
`,
},
{
name: 'Wrapper component must import base component (array is wrong)',
filename: fixture('src/app/test/themed-test-themeable.component.ts'),
code: `
import { SomethingElse } from './somewhere-else';
@Component({
selector: 'ds-test-themable',
standalone: true,
imports: [
SomethingElse,
],
})
class ThemedTestThemeableComponent extends ThemedComponent<TestThemeableComponent> {
}
`,
errors:[
{
messageId: Message.WRAPPER_IMPORTS_BASE,
},
],
output: `
import { SomethingElse } from './somewhere-else';
@Component({
selector: 'ds-test-themable',
standalone: true,
imports: [TestThemeableComponent],
})
class ThemedTestThemeableComponent extends ThemedComponent<TestThemeableComponent> {
}
`,
}, {
name: 'Wrapper component must import base component (array is wrong)',
filename: fixture('src/app/test/themed-test-themeable.component.ts'),
code: `
import { Something, SomethingElse } from './somewhere-else';
@Component({
selector: 'ds-test-themable',
standalone: true,
imports: [
SomethingElse,
],
})
class ThemedTestThemeableComponent extends ThemedComponent<TestThemeableComponent> {
}
`,
errors:[
{
messageId: Message.WRAPPER_IMPORTS_BASE,
},
],
output: `
import { Something, SomethingElse } from './somewhere-else';
@Component({
selector: 'ds-test-themable',
standalone: true,
imports: [TestThemeableComponent],
})
class ThemedTestThemeableComponent extends ThemedComponent<TestThemeableComponent> {
}
`,
},
{
name: 'Override component must be standalone',
filename: fixture('src/themes/test/app/test/test-themeable.component.ts'),
code: `
@Component({
selector: 'ds-themed-test-themable',
})
class Override extends BaseComponent {
}
`,
errors:[
{
messageId: Message.NOT_STANDALONE,
},
],
output: `
@Component({
selector: 'ds-themed-test-themable',
standalone: true,
})
class Override extends BaseComponent {
}
`,
},
],
};

View File

@@ -0,0 +1,257 @@
/**
* The contents of this file are subject to the license and copyright
* detailed in the LICENSE and NOTICE files at the root of the source
* tree and available online at
*
* http://www.dspace.org/license/
*/
import {
ESLintUtils,
TSESLint,
TSESTree,
} from '@typescript-eslint/utils';
import { fixture } from '../../../test/fixture';
import { getComponentSelectorNode } from '../../util/angular';
import { stringLiteral } from '../../util/misc';
import { DSpaceESLintRuleInfo } from '../../util/structure';
import {
inThemedComponentOverrideFile,
isThemeableComponent,
isThemedComponentWrapper,
} from '../../util/theme-support';
import { getFilename } from '../../util/typescript';
export enum Message {
BASE = 'wrongSelectorUnthemedComponent',
WRAPPER = 'wrongSelectorThemedComponentWrapper',
THEMED = 'wrongSelectorThemedComponentOverride',
}
export const info = {
name: 'themed-component-selectors',
meta: {
docs: {
description: `Themeable component selectors should follow the DSpace convention
Each themeable component is comprised of a base component, a wrapper component and any number of themed components
- Base components should have a selector starting with \`ds-base-\`
- Themed components should have a selector starting with \`ds-themed-\`
- Wrapper components should have a selector starting with \`ds-\`, but not \`ds-base-\` or \`ds-themed-\`
- This is the regular DSpace selector prefix
- **When making a regular component themeable, its selector prefix should be changed to \`ds-base-\`, and the new wrapper's component should reuse the previous selector**
Unit tests are exempt from this rule, because they may redefine components using the same class name as other themeable components elsewhere in the source.
`,
},
type: 'problem',
schema: [],
fixable: 'code',
messages: {
[Message.BASE]: 'Unthemed version of themeable component should have a selector starting with \'ds-base-\'',
[Message.WRAPPER]: 'Themed component wrapper of themeable component shouldn\'t have a selector starting with \'ds-themed-\'',
[Message.THEMED]: 'Theme override of themeable component should have a selector starting with \'ds-themed-\'',
},
},
defaultOptions: [],
} as DSpaceESLintRuleInfo;
export const rule = ESLintUtils.RuleCreator.withoutDocs({
...info,
create(context: TSESLint.RuleContext<Message, unknown[]>) {
const filename = getFilename(context);
if (filename.endsWith('.spec.ts')) {
return {};
}
function enforceWrapperSelector(selectorNode: TSESTree.StringLiteral) {
if (selectorNode?.value.startsWith('ds-themed-')) {
context.report({
messageId: Message.WRAPPER,
node: selectorNode,
fix(fixer) {
return fixer.replaceText(selectorNode, stringLiteral(selectorNode.value.replace('ds-themed-', 'ds-')));
},
});
}
}
function enforceBaseSelector(selectorNode: TSESTree.StringLiteral) {
if (!selectorNode?.value.startsWith('ds-base-')) {
context.report({
messageId: Message.BASE,
node: selectorNode,
fix(fixer) {
return fixer.replaceText(selectorNode, stringLiteral(selectorNode.value.replace('ds-', 'ds-base-')));
},
});
}
}
function enforceThemedSelector(selectorNode: TSESTree.StringLiteral) {
if (!selectorNode?.value.startsWith('ds-themed-')) {
context.report({
messageId: Message.THEMED,
node: selectorNode,
fix(fixer) {
return fixer.replaceText(selectorNode, stringLiteral(selectorNode.value.replace('ds-', 'ds-themed-')));
},
});
}
}
return {
'ClassDeclaration > Decorator[expression.callee.name = "Component"]'(node: TSESTree.Decorator) {
const selectorNode = getComponentSelectorNode(node);
if (selectorNode === undefined) {
return;
}
const selector = selectorNode?.value;
const classNode = node.parent as TSESTree.ClassDeclaration;
const className = classNode.id?.name;
if (selector === undefined || className === undefined) {
return;
}
if (isThemedComponentWrapper(node)) {
enforceWrapperSelector(selectorNode);
} else if (inThemedComponentOverrideFile(filename)) {
enforceThemedSelector(selectorNode);
} else if (isThemeableComponent(className)) {
enforceBaseSelector(selectorNode);
}
},
};
},
});
export const tests = {
plugin: info.name,
valid: [
{
name: 'Regular non-themeable component selector',
code: `
@Component({
selector: 'ds-something',
})
class Something {
}
`,
},
{
name: 'Themeable component selector should replace the original version, unthemed version should be changed to ds-base-',
code: `
@Component({
selector: 'ds-base-something',
})
class Something {
}
@Component({
selector: 'ds-something',
})
class ThemedSomething extends ThemedComponent<Something> {
}
@Component({
selector: 'ds-themed-something',
})
class OverrideSomething extends Something {
}
`,
},
{
name: 'Other themed component wrappers should not interfere',
code: `
@Component({
selector: 'ds-something',
})
class Something {
}
@Component({
selector: 'ds-something-else',
})
class ThemedSomethingElse extends ThemedComponent<SomethingElse> {
}
`,
},
],
invalid: [
{
name: 'Wrong selector for base component',
filename: fixture('src/app/test/test-themeable.component.ts'),
code: `
@Component({
selector: 'ds-something',
})
class TestThemeableComponent {
}
`,
errors: [
{
messageId: Message.BASE,
},
],
output: `
@Component({
selector: 'ds-base-something',
})
class TestThemeableComponent {
}
`,
},
{
name: 'Wrong selector for wrapper component',
filename: fixture('src/app/test/themed-test-themeable.component.ts'),
code: `
@Component({
selector: 'ds-themed-something',
})
class ThemedTestThemeableComponent extends ThemedComponent<TestThemeableComponent> {
}
`,
errors: [
{
messageId: Message.WRAPPER,
},
],
output: `
@Component({
selector: 'ds-something',
})
class ThemedTestThemeableComponent extends ThemedComponent<TestThemeableComponent> {
}
`,
},
{
name: 'Wrong selector for theme override',
filename: fixture('src/themes/test/app/test/test-themeable.component.ts'),
code: `
@Component({
selector: 'ds-something',
})
class TestThememeableComponent extends BaseComponent {
}
`,
errors: [
{
messageId: Message.THEMED,
},
],
output: `
@Component({
selector: 'ds-themed-something',
})
class TestThememeableComponent extends BaseComponent {
}
`,
},
],
};
export default rule;

View File

@@ -0,0 +1,502 @@
/**
* The contents of this file are subject to the license and copyright
* detailed in the LICENSE and NOTICE files at the root of the source
* tree and available online at
*
* http://www.dspace.org/license/
*/
import {
ESLintUtils,
TSESLint,
TSESTree,
} from '@typescript-eslint/utils';
import { fixture } from '../../../test/fixture';
import {
removeWithCommas,
replaceOrRemoveArrayIdentifier,
} from '../../util/fix';
import { DSpaceESLintRuleInfo } from '../../util/structure';
import {
allThemeableComponents,
DISALLOWED_THEME_SELECTORS,
fixSelectors,
getThemeableComponentByBaseClass,
isAllowedUnthemedUsage,
} from '../../util/theme-support';
import {
findImportSpecifier,
findUsages,
findUsagesByName,
getFilename,
relativePath,
} from '../../util/typescript';
export enum Message {
WRONG_CLASS = 'mustUseThemedWrapperClass',
WRONG_IMPORT = 'mustImportThemedWrapper',
WRONG_SELECTOR = 'mustUseThemedWrapperSelector',
BASE_IN_MODULE = 'baseComponentNotNeededInModule',
}
export const info = {
name: 'themed-component-usages',
meta: {
docs: {
description: `Themeable components should be used via their \`ThemedComponent\` wrapper class
This ensures that custom themes can correctly override _all_ instances of this component.
There are a few exceptions where the base class can still be used:
- Class declaration expressions (otherwise we can't declare, extend or override the class in the first place)
- Angular modules (except for routing modules)
- Angular \`@ViewChild\` decorators
- Type annotations
`,
},
type: 'problem',
schema: [],
fixable: 'code',
messages: {
[Message.WRONG_CLASS]: 'Themeable components should be used via their ThemedComponent wrapper',
[Message.WRONG_IMPORT]: 'Themeable components should be used via their ThemedComponent wrapper',
[Message.WRONG_SELECTOR]: 'Themeable components should be used via their ThemedComponent wrapper',
[Message.BASE_IN_MODULE]: 'Base themeable components shouldn\'t be declared in modules',
},
},
defaultOptions: [],
} as DSpaceESLintRuleInfo;
export const rule = ESLintUtils.RuleCreator.withoutDocs({
...info,
create(context: TSESLint.RuleContext<Message, unknown[]>) {
const filename = getFilename(context);
function handleUnthemedUsagesInTypescript(node: TSESTree.Identifier) {
if (isAllowedUnthemedUsage(node)) {
return;
}
const entry = getThemeableComponentByBaseClass(node.name);
if (entry === undefined) {
// this should never happen
throw new Error(`No such themeable component in registry: '${node.name}'`);
}
context.report({
messageId: Message.WRONG_CLASS,
node: node,
fix(fixer) {
if (node.parent.type === TSESTree.AST_NODE_TYPES.ArrayExpression) {
return replaceOrRemoveArrayIdentifier(context, fixer, node, entry.wrapperClass);
} else {
return fixer.replaceText(node, entry.wrapperClass);
}
},
});
}
function handleThemedSelectorQueriesInTests(node: TSESTree.Literal) {
context.report({
node,
messageId: Message.WRONG_SELECTOR,
fix(fixer){
const newSelector = fixSelectors(node.raw);
return fixer.replaceText(node, newSelector);
},
});
}
function handleUnthemedImportsInTypescript(specifierNode: TSESTree.ImportSpecifier) {
const allUsages = findUsages(context, specifierNode.local);
const badUsages = allUsages.filter(usage => !isAllowedUnthemedUsage(usage));
if (badUsages.length === 0) {
return;
}
const importedNode = specifierNode.imported;
const declarationNode = specifierNode.parent as TSESTree.ImportDeclaration;
const entry = getThemeableComponentByBaseClass(importedNode.name);
if (entry === undefined) {
// this should never happen
throw new Error(`No such themeable component in registry: '${importedNode.name}'`);
}
context.report({
messageId: Message.WRONG_IMPORT,
node: importedNode,
fix(fixer) {
const ops = [];
const wrapperImport = findImportSpecifier(context, entry.wrapperClass);
if (findUsagesByName(context, entry.wrapperClass).length === 0) {
// Wrapper is not present in this file, safe to add import
const newImportLine = `import { ${entry.wrapperClass} } from '${relativePath(filename, entry.wrapperPath)}';`;
if (declarationNode.specifiers.length === 1) {
if (allUsages.length === badUsages.length) {
ops.push(fixer.replaceText(declarationNode, newImportLine));
} else if (wrapperImport === undefined) {
ops.push(fixer.insertTextAfter(declarationNode, '\n' + newImportLine));
}
} else {
ops.push(...removeWithCommas(context, fixer, specifierNode));
if (wrapperImport === undefined) {
ops.push(fixer.insertTextAfter(declarationNode, '\n' + newImportLine));
}
}
} else {
// Wrapper already present in the file, remove import instead
if (allUsages.length === badUsages.length) {
if (declarationNode.specifiers.length === 1) {
// Make sure we remove the newline as well
ops.push(fixer.removeRange([declarationNode.range[0], declarationNode.range[1] + 1]));
} else {
ops.push(...removeWithCommas(context, fixer, specifierNode));
}
}
}
return ops;
},
});
}
// ignore tests and non-routing modules
if (filename.endsWith('.spec.ts')) {
return {
[`CallExpression[callee.object.name = "By"][callee.property.name = "css"] > Literal:first-child[value = /.*${DISALLOWED_THEME_SELECTORS}.*/]`]: handleThemedSelectorQueriesInTests,
};
} else if (filename.endsWith('.cy.ts')) {
return {
[`CallExpression[callee.object.name = "cy"][callee.property.name = "get"] > Literal:first-child[value = /.*${DISALLOWED_THEME_SELECTORS}.*/]`]: handleThemedSelectorQueriesInTests,
};
} else if (
filename.match(/(?!src\/themes\/).*(?!routing).module.ts$/)
|| filename.match(/themed-.+\.component\.ts$/)
) {
// do nothing
return {};
} else {
return allThemeableComponents().reduce(
(rules, entry) => {
return {
...rules,
[`:not(:matches(ClassDeclaration, ImportSpecifier)) > Identifier[name = "${entry.baseClass}"]`]: handleUnthemedUsagesInTypescript,
[`ImportSpecifier[imported.name = "${entry.baseClass}"]`]: handleUnthemedImportsInTypescript,
};
}, {},
);
}
},
});
export const tests = {
plugin: info.name,
valid: [
{
name: 'allow wrapper class usages',
code: `
import { ThemedTestThemeableComponent } from './app/test/themed-test-themeable.component';
const config = {
a: ThemedTestThemeableComponent,
b: ChipsComponent,
}
`,
},
{
name: 'allow base class in class declaration',
code: `
export class TestThemeableComponent {
}
`,
},
{
name: 'allow inheriting from base class',
code: `
import { TestThemeableComponent } from './app/test/test-themeable.component';
export class ThemedAdminSidebarComponent extends ThemedComponent<TestThemeableComponent> {
}
`,
},
{
name: 'allow base class in ViewChild',
code: `
import { TestThemeableComponent } from './app/test/test-themeable.component';
export class Something {
@ViewChild(TestThemeableComponent) test: TestThemeableComponent;
}
`,
},
{
name: 'allow wrapper selectors in test queries',
filename: fixture('src/app/test/test.component.spec.ts'),
code: `
By.css('ds-themeable');
By.css('#test > ds-themeable > #nest');
`,
},
{
name: 'allow wrapper selectors in cypress queries',
filename: fixture('src/app/test/test.component.cy.ts'),
code: `
By.css('ds-themeable');
By.css('#test > ds-themeable > #nest');
`,
},
],
invalid: [
{
name: 'disallow direct usages of base class',
code: `
import { TestThemeableComponent } from './app/test/test-themeable.component';
import { TestComponent } from './app/test/test.component';
const config = {
a: TestThemeableComponent,
b: TestComponent,
}
`,
errors: [
{
messageId: Message.WRONG_IMPORT,
},
{
messageId: Message.WRONG_CLASS,
},
],
output: `
import { ThemedTestThemeableComponent } from './app/test/themed-test-themeable.component';
import { TestComponent } from './app/test/test.component';
const config = {
a: ThemedTestThemeableComponent,
b: TestComponent,
}
`,
},
{
name: 'disallow direct usages of base class, keep other imports',
code: `
import { Something, TestThemeableComponent } from './app/test/test-themeable.component';
import { TestComponent } from './app/test/test.component';
const config = {
a: TestThemeableComponent,
b: TestComponent,
c: Something,
}
`,
errors: [
{
messageId: Message.WRONG_IMPORT,
},
{
messageId: Message.WRONG_CLASS,
},
],
output: `
import { Something } from './app/test/test-themeable.component';
import { ThemedTestThemeableComponent } from './app/test/themed-test-themeable.component';
import { TestComponent } from './app/test/test.component';
const config = {
a: ThemedTestThemeableComponent,
b: TestComponent,
c: Something,
}
`,
},
{
name: 'handle array replacements correctly',
code: `
const DECLARATIONS = [
Something,
TestThemeableComponent,
Something,
ThemedTestThemeableComponent,
];
`,
errors: [
{
messageId: Message.WRONG_CLASS,
},
],
output: `
const DECLARATIONS = [
Something,
Something,
ThemedTestThemeableComponent,
];
`,
},
{
name: 'disallow override selector in test queries',
filename: fixture('src/app/test/test.component.spec.ts'),
code: `
By.css('ds-themed-themeable');
By.css('#test > ds-themed-themeable > #nest');
`,
errors: [
{
messageId: Message.WRONG_SELECTOR,
},
{
messageId: Message.WRONG_SELECTOR,
},
],
output: `
By.css('ds-themeable');
By.css('#test > ds-themeable > #nest');
`,
},
{
name: 'disallow base selector in test queries',
filename: fixture('src/app/test/test.component.spec.ts'),
code: `
By.css('ds-base-themeable');
By.css('#test > ds-base-themeable > #nest');
`,
errors: [
{
messageId: Message.WRONG_SELECTOR,
},
{
messageId: Message.WRONG_SELECTOR,
},
],
output: `
By.css('ds-themeable');
By.css('#test > ds-themeable > #nest');
`,
},
{
name: 'disallow override selector in cypress queries',
filename: fixture('src/app/test/test.component.cy.ts'),
code: `
cy.get('ds-themed-themeable');
cy.get('#test > ds-themed-themeable > #nest');
`,
errors: [
{
messageId: Message.WRONG_SELECTOR,
},
{
messageId: Message.WRONG_SELECTOR,
},
],
output: `
cy.get('ds-themeable');
cy.get('#test > ds-themeable > #nest');
`,
},
{
name: 'disallow base selector in cypress queries',
filename: fixture('src/app/test/test.component.cy.ts'),
code: `
cy.get('ds-base-themeable');
cy.get('#test > ds-base-themeable > #nest');
`,
errors: [
{
messageId: Message.WRONG_SELECTOR,
},
{
messageId: Message.WRONG_SELECTOR,
},
],
output: `
cy.get('ds-themeable');
cy.get('#test > ds-themeable > #nest');
`,
},
{
name: 'edge case: unable to find usage node through usage token, but import is still flagged and fixed',
filename: fixture('src/themes/test/app/test/other-themeable.component.ts'),
code: `
import { Component } from '@angular/core';
import { Context } from './app/core/shared/context.model';
import { TestThemeableComponent } from '../../../../app/test/test-themeable.component';
@Component({
standalone: true,
imports: [TestThemeableComponent],
})
export class UsageComponent {
}
`,
errors: [
{
messageId: Message.WRONG_IMPORT,
},
{
messageId: Message.WRONG_CLASS,
},
],
output: `
import { Component } from '@angular/core';
import { Context } from './app/core/shared/context.model';
import { ThemedTestThemeableComponent } from '../../../../app/test/themed-test-themeable.component';
@Component({
standalone: true,
imports: [ThemedTestThemeableComponent],
})
export class UsageComponent {
}
`,
},
{
name: 'edge case edge case: both are imported, only wrapper is retained',
filename: fixture('src/themes/test/app/test/other-themeable.component.ts'),
code: `
import { Component } from '@angular/core';
import { Context } from './app/core/shared/context.model';
import { TestThemeableComponent } from '../../../../app/test/test-themeable.component';
import { ThemedTestThemeableComponent } from '../../../../app/test/themed-test-themeable.component';
@Component({
standalone: true,
imports: [TestThemeableComponent, ThemedTestThemeableComponent],
})
export class UsageComponent {
}
`,
errors: [
{
messageId: Message.WRONG_IMPORT,
},
{
messageId: Message.WRONG_CLASS,
},
],
output: `
import { Component } from '@angular/core';
import { Context } from './app/core/shared/context.model';
import { ThemedTestThemeableComponent } from '../../../../app/test/themed-test-themeable.component';
@Component({
standalone: true,
imports: [ThemedTestThemeableComponent],
})
export class UsageComponent {
}
`,
},
],
};
export default rule;

83
lint/src/util/angular.ts Normal file
View File

@@ -0,0 +1,83 @@
/**
* The contents of this file are subject to the license and copyright
* detailed in the LICENSE and NOTICE files at the root of the source
* tree and available online at
*
* http://www.dspace.org/license/
*/
import { TSESTree } from '@typescript-eslint/utils';
import { getObjectPropertyNodeByName } from './typescript';
export function getComponentSelectorNode(componentDecoratorNode: TSESTree.Decorator): TSESTree.StringLiteral | undefined {
const property = getComponentInitializerNodeByName(componentDecoratorNode, 'selector');
if (property !== undefined) {
// todo: support template literals as well
if (property.type === TSESTree.AST_NODE_TYPES.Literal && typeof property.value === 'string') {
return property as TSESTree.StringLiteral;
}
}
return undefined;
}
export function getComponentStandaloneNode(componentDecoratorNode: TSESTree.Decorator): TSESTree.BooleanLiteral | undefined {
const property = getComponentInitializerNodeByName(componentDecoratorNode, 'standalone');
if (property !== undefined) {
if (property.type === TSESTree.AST_NODE_TYPES.Literal && typeof property.value === 'boolean') {
return property as TSESTree.BooleanLiteral;
}
}
return undefined;
}
export function getComponentImportNode(componentDecoratorNode: TSESTree.Decorator): TSESTree.ArrayExpression | undefined {
const property = getComponentInitializerNodeByName(componentDecoratorNode, 'imports');
if (property !== undefined) {
if (property.type === TSESTree.AST_NODE_TYPES.ArrayExpression) {
return property as TSESTree.ArrayExpression;
}
}
return undefined;
}
export function getComponentClassName(decoratorNode: TSESTree.Decorator): string | undefined {
if (decoratorNode.parent.type !== TSESTree.AST_NODE_TYPES.ClassDeclaration) {
return undefined;
}
if (decoratorNode.parent.id?.type !== TSESTree.AST_NODE_TYPES.Identifier) {
return undefined;
}
return decoratorNode.parent.id.name;
}
export function getComponentSuperClassName(decoratorNode: TSESTree.Decorator): string | undefined {
if (decoratorNode.parent.type !== TSESTree.AST_NODE_TYPES.ClassDeclaration) {
return undefined;
}
if (decoratorNode.parent.superClass?.type !== TSESTree.AST_NODE_TYPES.Identifier) {
return undefined;
}
return decoratorNode.parent.superClass.name;
}
export function getComponentInitializer(componentDecoratorNode: TSESTree.Decorator): TSESTree.ObjectExpression {
return (componentDecoratorNode.expression as TSESTree.CallExpression).arguments[0] as TSESTree.ObjectExpression;
}
export function getComponentInitializerNodeByName(componentDecoratorNode: TSESTree.Decorator, name: string): TSESTree.Node | undefined {
const initializer = getComponentInitializer(componentDecoratorNode);
return getObjectPropertyNodeByName(initializer, name);
}
export function isPartOfViewChild(node: TSESTree.Identifier): boolean {
return (node.parent as any)?.callee?.name === 'ViewChild';
}

125
lint/src/util/fix.ts Normal file
View File

@@ -0,0 +1,125 @@
/**
* The contents of this file are subject to the license and copyright
* detailed in the LICENSE and NOTICE files at the root of the source
* tree and available online at
*
* http://www.dspace.org/license/
*/
import { TSESTree } from '@typescript-eslint/utils';
import {
RuleContext,
RuleFix,
RuleFixer,
} from '@typescript-eslint/utils/ts-eslint';
import { getSourceCode } from './typescript';
export function appendObjectProperties(context: RuleContext<any, any>, fixer: RuleFixer, objectNode: TSESTree.ObjectExpression, properties: string[]): RuleFix {
// todo: may not handle empty objects too well
const lastProperty = objectNode.properties[objectNode.properties.length - 1];
const source = getSourceCode(context);
const nextToken = source.getTokenAfter(lastProperty);
// todo: newline & indentation are hardcoded for @Component({})
// todo: we're assuming that we need trailing commas, what if we don't?
const newPart = '\n' + properties.map(p => ` ${p},`).join('\n');
if (nextToken !== null && nextToken.value === ',') {
return fixer.insertTextAfter(nextToken, newPart);
} else {
return fixer.insertTextAfter(lastProperty, ',' + newPart);
}
}
export function appendArrayElement(context: RuleContext<any, any>, fixer: RuleFixer, arrayNode: TSESTree.ArrayExpression, value: string): RuleFix {
const source = getSourceCode(context);
if (arrayNode.elements.length === 0) {
// This is the first element
const openArray = source.getTokenByRangeStart(arrayNode.range[0]);
if (openArray == null) {
throw new Error('Unexpected null token for opening square bracket');
}
// safe to assume the list is single-line
return fixer.insertTextAfter(openArray, `${value}`);
} else {
const lastElement = arrayNode.elements[arrayNode.elements.length - 1];
if (lastElement == null) {
throw new Error('Unexpected null node in array');
}
const nextToken = source.getTokenAfter(lastElement);
// todo: we don't know if the list is chopped or not, so we can't make any assumptions -- may produce output that will be flagged by other rules on the next run!
// todo: we're assuming that we need trailing commas, what if we don't?
if (nextToken !== null && nextToken.value === ',') {
return fixer.insertTextAfter(nextToken, ` ${value},`);
} else {
return fixer.insertTextAfter(lastElement, `, ${value},`);
}
}
}
export function isLast(elementNode: TSESTree.Node): boolean {
if (!elementNode.parent) {
return false;
}
let siblingNodes: (TSESTree.Node | null)[] = [null];
if (elementNode.parent.type === TSESTree.AST_NODE_TYPES.ArrayExpression) {
siblingNodes = elementNode.parent.elements;
} else if (elementNode.parent.type === TSESTree.AST_NODE_TYPES.ImportDeclaration) {
siblingNodes = elementNode.parent.specifiers;
}
return elementNode === siblingNodes[siblingNodes.length - 1];
}
export function removeWithCommas(context: RuleContext<any, any>, fixer: RuleFixer, elementNode: TSESTree.Node): RuleFix[] {
const ops = [];
const source = getSourceCode(context);
let nextToken = source.getTokenAfter(elementNode);
let prevToken = source.getTokenBefore(elementNode);
if (nextToken !== null && prevToken !== null) {
if (nextToken.value === ',') {
nextToken = source.getTokenAfter(nextToken);
if (nextToken !== null) {
ops.push(fixer.removeRange([elementNode.range[0], nextToken.range[0]]));
}
}
if (isLast(elementNode) && prevToken.value === ',') {
prevToken = source.getTokenBefore(prevToken);
if (prevToken !== null) {
ops.push(fixer.removeRange([prevToken.range[1], elementNode.range[1]]));
}
}
} else if (nextToken !== null) {
ops.push(fixer.removeRange([elementNode.range[0], nextToken.range[0]]));
}
return ops;
}
export function replaceOrRemoveArrayIdentifier(context: RuleContext<any, any>, fixer: RuleFixer, identifierNode: TSESTree.Identifier, newValue: string): RuleFix[] {
if (identifierNode.parent.type !== TSESTree.AST_NODE_TYPES.ArrayExpression) {
throw new Error('Parent node is not an array expression!');
}
const array = identifierNode.parent as TSESTree.ArrayExpression;
for (const element of array.elements) {
if (element !== null && element.type === TSESTree.AST_NODE_TYPES.Identifier && element.name === newValue) {
return removeWithCommas(context, fixer, identifierNode);
}
}
return [fixer.replaceText(identifierNode, newValue)];
}

28
lint/src/util/misc.ts Normal file
View File

@@ -0,0 +1,28 @@
/**
* 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/
*/
export function match(rangeA: number[], rangeB: number[]) {
return rangeA[0] === rangeB[0] && rangeA[1] === rangeB[1];
}
export function stringLiteral(value: string): string {
return `'${value}'`;
}
/**
* Transform Windows-style paths into Unix-style paths
*/
export function toUnixStylePath(path: string): string {
// note: we're assuming that none of the directory/file names contain '\' or '/' characters.
// using these characters in paths is very bad practice in general, so this should be a safe assumption.
if (path.includes('\\')) {
return path.replace(/^[A-Z]:\\/, '/').replaceAll('\\', '/');
}
return path;
}

View File

@@ -0,0 +1,57 @@
/**
* The contents of this file are subject to the license and copyright
* detailed in the LICENSE and NOTICE files at the root of the source
* tree and available online at
*
* http://www.dspace.org/license/
*/
import { TSESLint } from '@typescript-eslint/utils';
import { RuleTester } from 'eslint';
import { EnumType } from 'typescript';
export type Meta = TSESLint.RuleMetaData<string>;
export type Valid = TSESLint.ValidTestCase<unknown[]> | RuleTester.ValidTestCase;
export type Invalid = TSESLint.InvalidTestCase<string, unknown[]> | RuleTester.InvalidTestCase;
export interface DSpaceESLintRuleInfo {
name: string;
meta: Meta,
defaultOptions: unknown[],
}
export interface NamedTests {
plugin: string;
valid: Valid[];
invalid: Invalid[];
}
export interface RuleExports {
Message: EnumType,
info: DSpaceESLintRuleInfo,
rule: TSESLint.RuleModule<string>,
tests: NamedTests,
default: unknown,
}
export interface PluginExports {
name: string,
language: string,
rules: Record<string, unknown>,
index: RuleExports[],
}
export function bundle(
name: string,
language: string,
index: RuleExports[],
): PluginExports {
return index.reduce((o: PluginExports, i: RuleExports) => {
o.rules[i.info.name] = i.rule;
return o;
}, {
name,
language,
rules: {},
index,
});
}

View File

@@ -0,0 +1,5 @@
[DSpace ESLint plugins](../../../lint/README.md) > <%= plugin.language %> rules
_______
<% rules.forEach(rule => { %>
- [`<%= plugin.name %>/<%= rule.name %>`](./rules/<%= rule.name %>.md)<% if (rule.meta?.docs?.description) {%>: <%= rule.meta.docs.description.split('\n')[0].trim() -%><% }-%>
<% }) %>

View File

@@ -0,0 +1,48 @@
[DSpace ESLint plugins](../../../../lint/README.md) > [<%= plugin.language %> rules](../index.md) > `<%= plugin.name %>/<%= rule.name %>`
_______
<%- rule.meta.docs?.description %>
_______
[Source code](../../../../lint/src/rules/<%- plugin.name.replace('dspace-angular-', '') %>/<%- rule.name %>.ts)
### Examples
<% if (tests.valid) {%>
#### Valid code
<% tests.valid.forEach(test => { %>
##### <%= test.name !== undefined ? test.name : 'UNNAMED' %>
<% if (test.filename) { %>
Filename: `<%- test.filename %>`
<% } %>
```<%- plugin.language.toLowerCase() %>
<%- test.code.trim() %>
```
<% }) %>
<% } %>
<% if (tests.invalid) {%>
#### Invalid code <%= rule.meta.fixable ? ' & automatic fixes' : '' %>
<% tests.invalid.forEach(test => { %>
##### <%= test.name !== undefined ? test.name : 'UNNAMED' %>
<% if (test.filename) { %>
Filename: `<%- test.filename %>`
<% } %>
```<%- plugin.language.toLowerCase() %>
<%- test.code.trim() %>
```
Will produce the following error(s):
```
<% for (const error of test.errors) { -%>
<%- rule.meta.messages[error.messageId] %>
<% } -%>
```
<% if (test.output) { %>
Result of `yarn lint --fix`:
```<%- plugin.language.toLowerCase() %>
<%- test.output.trim() %>
```
<% } %>
<% }) %>
<% } %>

View File

@@ -0,0 +1,265 @@
/**
* The contents of this file are subject to the license and copyright
* detailed in the LICENSE and NOTICE files at the root of the source
* tree and available online at
*
* http://www.dspace.org/license/
*/
import { TSESTree } from '@typescript-eslint/utils';
import { readFileSync } from 'fs';
import { basename } from 'path';
import ts, { Identifier } from 'typescript';
import {
getComponentClassName,
isPartOfViewChild,
} from './angular';
import {
isPartOfClassDeclaration,
isPartOfTypeExpression,
} from './typescript';
/**
* Couples a themeable Component to its ThemedComponent wrapper
*/
export interface ThemeableComponentRegistryEntry {
basePath: string;
baseFileName: string,
baseClass: string;
wrapperPath: string;
wrapperFileName: string,
wrapperClass: string;
}
function isAngularComponentDecorator(node: ts.Node) {
if (node.kind === ts.SyntaxKind.Decorator && node.parent.kind === ts.SyntaxKind.ClassDeclaration) {
const decorator = node as ts.Decorator;
if (decorator.expression.kind === ts.SyntaxKind.CallExpression) {
const method = decorator.expression as ts.CallExpression;
if (method.expression.kind === ts.SyntaxKind.Identifier) {
return (method.expression as Identifier).text === 'Component';
}
}
}
return false;
}
function findImportDeclaration(source: ts.SourceFile, identifierName: string): ts.ImportDeclaration | undefined {
return ts.forEachChild(source, (topNode: ts.Node) => {
if (topNode.kind === ts.SyntaxKind.ImportDeclaration) {
const importDeclaration = topNode as ts.ImportDeclaration;
if (importDeclaration.importClause?.namedBindings?.kind === ts.SyntaxKind.NamedImports) {
const namedImports = importDeclaration.importClause?.namedBindings as ts.NamedImports;
for (const element of namedImports.elements) {
if (element.name.text === identifierName) {
return importDeclaration;
}
}
}
}
return undefined;
});
}
/**
* Listing of all themeable Components
*/
class ThemeableComponentRegistry {
public readonly entries: Set<ThemeableComponentRegistryEntry>;
public readonly byBaseClass: Map<string, ThemeableComponentRegistryEntry>;
public readonly byWrapperClass: Map<string, ThemeableComponentRegistryEntry>;
public readonly byBasePath: Map<string, ThemeableComponentRegistryEntry>;
public readonly byWrapperPath: Map<string, ThemeableComponentRegistryEntry>;
constructor() {
this.entries = new Set();
this.byBaseClass = new Map();
this.byWrapperClass = new Map();
this.byBasePath = new Map();
this.byWrapperPath = new Map();
}
public initialize(prefix = '') {
if (this.entries.size > 0) {
return;
}
function registerWrapper(path: string) {
const source = getSource(path);
function traverse(node: ts.Node) {
if (node.parent !== undefined && isAngularComponentDecorator(node)) {
const classNode = node.parent as ts.ClassDeclaration;
if (classNode.name === undefined || classNode.heritageClauses === undefined) {
return;
}
const wrapperClass = classNode.name?.escapedText as string;
for (const heritageClause of classNode.heritageClauses) {
for (const type of heritageClause.types) {
if ((type as any).expression.escapedText === 'ThemedComponent') {
if (type.kind !== ts.SyntaxKind.ExpressionWithTypeArguments || type.typeArguments === undefined) {
continue;
}
const firstTypeArg = type.typeArguments[0] as ts.TypeReferenceNode;
const baseClass = (firstTypeArg.typeName as ts.Identifier)?.escapedText;
if (baseClass === undefined) {
continue;
}
const importDeclaration = findImportDeclaration(source, baseClass);
if (importDeclaration === undefined) {
continue;
}
const basePath = resolveLocalPath((importDeclaration.moduleSpecifier as ts.StringLiteral).text, path);
themeableComponents.add({
baseClass,
basePath: basePath.replace(new RegExp(`^${prefix}`), ''),
baseFileName: basename(basePath).replace(/\.ts$/, ''),
wrapperClass,
wrapperPath: path.replace(new RegExp(`^${prefix}`), ''),
wrapperFileName: basename(path).replace(/\.ts$/, ''),
});
}
}
}
return;
} else {
ts.forEachChild(node, traverse);
}
}
traverse(source);
}
const glob = require('glob');
// note: this outputs Unix-style paths on Windows
const wrappers: string[] = glob.GlobSync(prefix + 'src/app/**/themed-*.component.ts', { ignore: 'node_modules/**' }).found;
for (const wrapper of wrappers) {
registerWrapper(wrapper);
}
}
private add(entry: ThemeableComponentRegistryEntry) {
this.entries.add(entry);
this.byBaseClass.set(entry.baseClass, entry);
this.byWrapperClass.set(entry.wrapperClass, entry);
this.byBasePath.set(entry.basePath, entry);
this.byWrapperPath.set(entry.wrapperPath, entry);
}
}
export const themeableComponents = new ThemeableComponentRegistry();
/**
* Construct the AST of a TypeScript source file
* @param file
*/
function getSource(file: string): ts.SourceFile {
return ts.createSourceFile(
file,
readFileSync(file).toString(),
ts.ScriptTarget.ES2020, // todo: actually use tsconfig.json?
/*setParentNodes */ true,
);
}
/**
* Resolve a possibly relative local path into an absolute path starting from the root directory of the project
*/
function resolveLocalPath(path: string, relativeTo: string) {
if (path.startsWith('src/')) {
return path;
} else if (path.startsWith('./')) {
const parts = relativeTo.split('/');
return [
...parts.slice(0, parts.length - 1),
path.replace(/^.\//, ''),
].join('/') + '.ts';
} else {
throw new Error(`Unsupported local path: ${path}`);
}
}
export function isThemedComponentWrapper(decoratorNode: TSESTree.Decorator): boolean {
if (decoratorNode.parent.type !== TSESTree.AST_NODE_TYPES.ClassDeclaration) {
return false;
}
if (decoratorNode.parent.superClass?.type !== TSESTree.AST_NODE_TYPES.Identifier) {
return false;
}
return (decoratorNode.parent.superClass as any)?.name === 'ThemedComponent';
}
export function getBaseComponentClassName(decoratorNode: TSESTree.Decorator): string | undefined {
const wrapperClass = getComponentClassName(decoratorNode);
if (wrapperClass === undefined) {
return;
}
themeableComponents.initialize();
const entry = themeableComponents.byWrapperClass.get(wrapperClass);
if (entry === undefined) {
return undefined;
}
return entry.baseClass;
}
export function isThemeableComponent(className: string): boolean {
themeableComponents.initialize();
return themeableComponents.byBaseClass.has(className);
}
export function inThemedComponentOverrideFile(filename: string): boolean {
const match = filename.match(/src\/themes\/[^\/]+\/(app\/.*)/);
if (!match) {
return false;
}
themeableComponents.initialize();
// todo: this is fragile!
return themeableComponents.byBasePath.has(`src/${match[1]}`);
}
export function allThemeableComponents(): ThemeableComponentRegistryEntry[] {
themeableComponents.initialize();
return [...themeableComponents.entries];
}
export function getThemeableComponentByBaseClass(baseClass: string): ThemeableComponentRegistryEntry | undefined {
themeableComponents.initialize();
return themeableComponents.byBaseClass.get(baseClass);
}
export function isAllowedUnthemedUsage(usageNode: TSESTree.Identifier) {
return isPartOfClassDeclaration(usageNode) || isPartOfTypeExpression(usageNode) || isPartOfViewChild(usageNode);
}
export const DISALLOWED_THEME_SELECTORS = 'ds-(base|themed)-';
export function fixSelectors(text: string): string {
return text.replaceAll(/ds-(base|themed)-/g, 'ds-');
}

154
lint/src/util/typescript.ts Normal file
View File

@@ -0,0 +1,154 @@
/**
* The contents of this file are subject to the license and copyright
* detailed in the LICENSE and NOTICE files at the root of the source
* tree and available online at
*
* http://www.dspace.org/license/
*/
import {
TSESLint,
TSESTree,
} from '@typescript-eslint/utils';
import {
match,
toUnixStylePath,
} from './misc';
export type AnyRuleContext = TSESLint.RuleContext<string, unknown[]>;
/**
* Return the current filename based on the ESLint rule context as a Unix-style path.
* This is easier for regex and comparisons to glob paths.
*/
export function getFilename(context: AnyRuleContext): string {
// TSESLint claims this is deprecated, but the suggested alternative is undefined (could be a version mismatch between ESLint and TSESlint?)
// eslint-disable-next-line deprecation/deprecation
return toUnixStylePath(context.getFilename());
}
export function getSourceCode(context: AnyRuleContext): TSESLint.SourceCode {
// TSESLint claims this is deprecated, but the suggested alternative is undefined (could be a version mismatch between ESLint and TSESlint?)
// eslint-disable-next-line deprecation/deprecation
return context.getSourceCode();
}
export function getObjectPropertyNodeByName(objectNode: TSESTree.ObjectExpression, propertyName: string): TSESTree.Node | undefined {
for (const propertyNode of objectNode.properties) {
if (
propertyNode.type === TSESTree.AST_NODE_TYPES.Property
&& (
(
propertyNode.key?.type === TSESTree.AST_NODE_TYPES.Identifier
&& propertyNode.key?.name === propertyName
) || (
propertyNode.key?.type === TSESTree.AST_NODE_TYPES.Literal
&& propertyNode.key?.value === propertyName
)
)
) {
return propertyNode.value;
}
}
return undefined;
}
export function findUsages(context: AnyRuleContext, localNode: TSESTree.Identifier): TSESTree.Identifier[] {
const source = getSourceCode(context);
const usages: TSESTree.Identifier[] = [];
for (const token of source.ast.tokens) {
if (token.type === TSESTree.AST_TOKEN_TYPES.Identifier && token.value === localNode.name && !match(token.range, localNode.range)) {
const node = source.getNodeByRangeIndex(token.range[0]);
// todo: in some cases, the resulting node can actually be the whole program (!)
if (node !== null) {
usages.push(node as TSESTree.Identifier);
}
}
}
return usages;
}
export function findUsagesByName(context: AnyRuleContext, identifier: string): TSESTree.Identifier[] {
const source = getSourceCode(context);
const usages: TSESTree.Identifier[] = [];
for (const token of source.ast.tokens) {
if (token.type === TSESTree.AST_TOKEN_TYPES.Identifier && token.value === identifier) {
const node = source.getNodeByRangeIndex(token.range[0]);
// todo: in some cases, the resulting node can actually be the whole program (!)
if (node !== null) {
usages.push(node as TSESTree.Identifier);
}
}
}
return usages;
}
export function isPartOfTypeExpression(node: TSESTree.Identifier): boolean {
return node.parent?.type?.valueOf().startsWith('TSType');
}
export function isPartOfClassDeclaration(node: TSESTree.Identifier): boolean {
return node.parent?.type === TSESTree.AST_NODE_TYPES.ClassDeclaration;
}
function fromSrc(path: string): string {
const m = path.match(/^.*(src\/.+)(\.(ts|json|js)?)$/);
if (m) {
return m[1];
} else {
throw new Error(`Can't infer project-absolute TS/resource path from: ${path}`);
}
}
export function relativePath(thisFile: string, importFile: string): string {
const fromParts = fromSrc(thisFile).split('/');
const toParts = fromSrc(importFile).split('/');
let lastCommon = 0;
for (let i = 0; i < fromParts.length - 1; i++) {
if (fromParts[i] === toParts[i]) {
lastCommon++;
} else {
break;
}
}
const path = toParts.slice(lastCommon, toParts.length).join('/');
const backtrack = fromParts.length - lastCommon - 1;
let prefix: string;
if (backtrack > 0) {
prefix = '../'.repeat(backtrack);
} else {
prefix = './';
}
return prefix + path;
}
export function findImportSpecifier(context: AnyRuleContext, identifier: string): TSESTree.ImportSpecifier | undefined {
const source = getSourceCode(context);
const usages: TSESTree.Identifier[] = [];
for (const token of source.ast.tokens) {
if (token.type === TSESTree.AST_TOKEN_TYPES.Identifier && token.value === identifier) {
const node = source.getNodeByRangeIndex(token.range[0]);
// todo: in some cases, the resulting node can actually be the whole program (!)
if (node && node.parent && node.parent.type === TSESTree.AST_NODE_TYPES.ImportSpecifier) {
return node.parent;
}
}
}
return undefined;
}

View File

@@ -0,0 +1,9 @@
# ESLint testing fixtures
The files in this directory are used for the ESLint testing environment
- Some rules rely on registries that must be built up _before_ the rule is run
- In order to test these registries, the fixture sources contain a few dummy components
- The TypeScript ESLint test runner requires at least one dummy file to exist to run any tests
- By default, [`test.ts`](./src/test.ts) is used. Note that this file is empty; it's only there for the TypeScript configuration, the actual content is injected from the `code` property in the tests.
- To test rules that make assertions based on the path of the file, you'll need to include the `filename` property in the test configuration. Note that it must point to an existing file too!
- The `filename` must be provided as `fixture('src/something.ts')`

View File

@@ -0,0 +1,13 @@
/**
* 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/
*/
export const FIXTURE = 'lint/test/fixture/';
export function fixture(path: string): string {
return FIXTURE + path;
}

View File

@@ -0,0 +1,14 @@
/**
* The contents of this file are subject to the license and copyright
* detailed in the LICENSE and NOTICE files at the root of the source
* tree and available online at
*
* http://www.dspace.org/license/
*/
import { ThemedTestThemeableComponent } from './themed-test-themeable.component';
export const ROUTES = [
{
component: ThemedTestThemeableComponent,
},
];

View File

@@ -0,0 +1,16 @@
/**
* The contents of this file are subject to the license and copyright
* detailed in the LICENSE and NOTICE files at the root of the source
* tree and available online at
*
* http://www.dspace.org/license/
*/
import { Component } from '@angular/core';
@Component({
selector: 'ds-base-test-themeable',
template: '',
standalone: true,
})
export class TestThemeableComponent {
}

View File

@@ -0,0 +1,8 @@
/**
* 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/
*/

View File

@@ -0,0 +1,8 @@
/**
* 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/
*/

View File

@@ -0,0 +1,15 @@
/**
* The contents of this file are subject to the license and copyright
* detailed in the LICENSE and NOTICE files at the root of the source
* tree and available online at
*
* http://www.dspace.org/license/
*/
import { Component } from '@angular/core';
@Component({
selector: 'ds-test',
template: '',
})
export class TestComponent {
}

View File

@@ -0,0 +1,24 @@
/**
* 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/
*/
// @ts-ignore
import { NgModule } from '@angular/core';
import { TestComponent } from './test.component';
import { TestThemeableComponent } from './test-themeable.component';
import { ThemedTestThemeableComponent } from './themed-test-themeable.component';
@NgModule({
declarations: [
TestComponent,
TestThemeableComponent,
ThemedTestThemeableComponent,
],
})
export class TestModule {
}

View File

@@ -0,0 +1,31 @@
/**
* The contents of this file are subject to the license and copyright
* detailed in the LICENSE and NOTICE files at the root of the source
* tree and available online at
*
* http://www.dspace.org/license/
*/
import { Component } from '@angular/core';
import { ThemedComponent } from '../../../../../../src/app/shared/theme-support/themed.component';
import { TestThemeableComponent } from './test-themeable.component';
@Component({
selector: 'ds-test-themeable',
template: '',
standalone: true,
imports: [TestThemeableComponent],
})
export class ThemedTestThemeableComponent extends ThemedComponent<TestThemeableComponent> {
protected getComponentName(): string {
return '';
}
protected importThemedComponent(themeName: string): Promise<any> {
return Promise.resolve(undefined);
}
protected importUnthemedComponent(): Promise<any> {
return Promise.resolve(undefined);
}
}

View File

@@ -0,0 +1,16 @@
/**
* The contents of this file are subject to the license and copyright
* detailed in the LICENSE and NOTICE files at the root of the source
* tree and available online at
*
* http://www.dspace.org/license/
*/
import { Component } from '@angular/core';
@Component({
selector: 'ds-themed-test-themeable',
template: '',
})
export class OtherThemeableComponent {
}

View File

@@ -0,0 +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/
*/
import { Component } from '@angular/core';
import { TestThemeableComponent as BaseComponent } from '../../../../app/test/test-themeable.component';
@Component({
selector: 'ds-themed-test-themeable',
template: '',
})
export class TestThemeableComponent extends BaseComponent {
}

View File

@@ -0,0 +1,22 @@
/**
* 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/
*/
// @ts-ignore
import { NgModule } from '@angular/core';
import { OtherThemeableComponent } from './app/test/other-themeable.component';
import { TestThemeableComponent } from './app/test/test-themeable.component';
@NgModule({
declarations: [
TestThemeableComponent,
OtherThemeableComponent,
],
})
export class TestModule {
}

View File

@@ -0,0 +1,7 @@
{
"extends": "../../tsconfig.json",
"include": [
"src/**/*.ts"
],
"exclude": []
}

13
lint/test/helpers.js Normal file
View File

@@ -0,0 +1,13 @@
const SpecReporter = require('jasmine-spec-reporter').SpecReporter;
const StacktraceOption = require('jasmine-spec-reporter').StacktraceOption;
jasmine.getEnv().clearReporters(); // Clear default console reporter for those instead
jasmine.getEnv().addReporter(new SpecReporter({
spec: {
displayErrorMessages: false,
},
summary: {
displayFailed: true,
displayStacktrace: StacktraceOption.PRETTY,
},
}));

26
lint/test/rules.spec.ts Normal file
View File

@@ -0,0 +1,26 @@
/**
* The contents of this file are subject to the license and copyright
* detailed in the LICENSE and NOTICE files at the root of the source
* tree and available online at
*
* http://www.dspace.org/license/
*/
import { default as htmlPlugin } from '../src/rules/html';
import { default as tsPlugin } from '../src/rules/ts';
import {
htmlRuleTester,
tsRuleTester,
} from './testing';
describe('TypeScript rules', () => {
for (const { info, rule, tests } of tsPlugin.index) {
tsRuleTester.run(info.name, rule, tests as any);
}
});
describe('HTML rules', () => {
for (const { info, rule, tests } of htmlPlugin.index) {
htmlRuleTester.run(info.name, rule, tests);
}
});

View File

@@ -0,0 +1,76 @@
/**
* The contents of this file are subject to the license and copyright
* detailed in the LICENSE and NOTICE files at the root of the source
* tree and available online at
*
* http://www.dspace.org/license/
*/
import { default as html } from '../src/rules/html';
import { default as ts } from '../src/rules/ts';
describe('plugin structure', () => {
for (const pluginExports of [ts, html]) {
const pluginName = pluginExports.name ?? 'UNNAMED PLUGIN';
describe(pluginName, () => {
it('should have a name', () => {
expect(pluginExports.name).toBeTruthy();
});
it('should have rules', () => {
expect(pluginExports.index).toBeTruthy();
expect(pluginExports.rules).toBeTruthy();
expect(pluginExports.index.length).toBeGreaterThan(0);
});
for (const ruleExports of pluginExports.index) {
const ruleName = ruleExports.info.name ?? 'UNNAMED RULE';
describe(ruleName, () => {
it('should have a name', () => {
expect(ruleExports.info.name).toBeTruthy();
});
it('should be included under the right name in the plugin', () => {
expect(pluginExports.rules[ruleExports.info.name]).toBe(ruleExports.rule);
});
it('should contain metadata', () => {
expect(ruleExports.info).toBeTruthy();
expect(ruleExports.info.name).toBeTruthy();
expect(ruleExports.info.meta).toBeTruthy();
expect(ruleExports.info.defaultOptions).toBeTruthy();
});
it('should contain messages', () => {
expect(ruleExports.Message).toBeTruthy();
expect(ruleExports.info.meta.messages).toBeTruthy();
});
describe('messages', () => {
for (const member of Object.keys(ruleExports.Message)) {
describe(member, () => {
const id = (ruleExports.Message as any)[member];
it('should have a valid ID', () => {
expect(id).toBeTruthy();
});
it('should have valid metadata', () => {
expect(ruleExports.info.meta.messages[id]).toBeTruthy();
});
});
}
});
it('should contain tests', () => {
expect(ruleExports.tests).toBeTruthy();
expect(ruleExports.tests.valid.length).toBeGreaterThan(0);
expect(ruleExports.tests.invalid.length).toBeGreaterThan(0);
});
});
}
});
}
});

53
lint/test/testing.ts Normal file
View File

@@ -0,0 +1,53 @@
/**
* The contents of this file are subject to the license and copyright
* detailed in the LICENSE and NOTICE files at the root of the source
* tree and available online at
*
* http://www.dspace.org/license/
*/
import { RuleTester as TypeScriptRuleTester } from '@typescript-eslint/rule-tester';
import { RuleTester } from 'eslint';
import { themeableComponents } from '../src/util/theme-support';
import {
FIXTURE,
fixture,
} from './fixture';
// Register themed components from test fixture
themeableComponents.initialize(FIXTURE);
TypeScriptRuleTester.itOnly = fit;
TypeScriptRuleTester.itSkip = xit;
export const tsRuleTester = new TypeScriptRuleTester({
parser: '@typescript-eslint/parser',
defaultFilenames: {
ts: fixture('src/test.ts'),
tsx: 'n/a',
},
parserOptions: {
project: fixture('tsconfig.json'),
},
});
class HtmlRuleTester extends RuleTester {
run(name: string, rule: any, tests: { valid: any[], invalid: any[] }) {
super.run(name, rule, {
valid: tests.valid.map((test) => ({
filename: fixture('test.html'),
...test,
})),
invalid: tests.invalid.map((test) => ({
filename: fixture('test.html'),
...test,
})),
});
}
}
export const htmlRuleTester = new HtmlRuleTester({
parser: require.resolve('@angular-eslint/template-parser'),
});

View File

@@ -0,0 +1,24 @@
/**
* The contents of this file are subject to the license and copyright
* detailed in the LICENSE and NOTICE files at the root of the source
* tree and available online at
*
* http://www.dspace.org/license/
*/
import { themeableComponents } from '../src/util/theme-support';
describe('theme-support', () => {
describe('themeable component registry', () => {
it('should contain all themeable components from the fixture', () => {
expect(themeableComponents.entries.size).toBe(1);
expect(themeableComponents.byBasePath.size).toBe(1);
expect(themeableComponents.byWrapperPath.size).toBe(1);
expect(themeableComponents.byBaseClass.size).toBe(1);
expect(themeableComponents.byBaseClass.get('TestThemeableComponent')).toBeTruthy();
expect(themeableComponents.byBasePath.get('src/app/test/test-themeable.component.ts')).toBeTruthy();
expect(themeableComponents.byWrapperPath.get('src/app/test/themed-test-themeable.component.ts')).toBeTruthy();
});
});
});

27
lint/tsconfig.json Normal file
View File

@@ -0,0 +1,27 @@
{
"compilerOptions": {
"target": "ES2021",
"lib": [
"es2021"
],
"module": "nodenext",
"moduleResolution": "nodenext",
"noImplicitReturns": true,
"skipLibCheck": true,
"strict": true,
"outDir": "./dist",
"sourceMap": true,
"allowSyntheticDefaultImports": true,
"types": [
"jasmine",
"node"
]
},
"include": [
"**/*.ts",
],
"exclude": [
"dist",
"test/fixture"
]
}

View File

@@ -1,6 +1,6 @@
{
"name": "dspace-angular",
"version": "8.0.0-rc1",
"version": "8.0.0",
"scripts": {
"ng": "ng",
"config:watch": "nodemon",
@@ -17,11 +17,16 @@
"build:stats": "ng build --stats-json",
"build:prod": "cross-env NODE_ENV=production yarn run build:ssr",
"build:ssr": "ng build --configuration production && ng run dspace-angular:server:production",
"build:lint": "rimraf 'lint/dist/**/*.js' 'lint/dist/**/*.js.map' && tsc -b lint/tsconfig.json",
"test": "ng test --source-map=true --watch=false --configuration test",
"test:watch": "nodemon --exec \"ng test --source-map=true --watch=true --configuration test\"",
"test:headless": "ng test --source-map=true --watch=false --configuration test --browsers=ChromeHeadless --code-coverage",
"lint": "ng lint",
"lint-fix": "ng lint --fix=true",
"test:lint": "yarn build:lint && yarn test:lint:nobuild",
"test:lint:nobuild": "jasmine --config=lint/jasmine.json",
"lint": "yarn build:lint && yarn lint:nobuild",
"lint:nobuild": "ng lint",
"lint-fix": "yarn build:lint && ng lint --fix=true",
"docs:lint": "ts-node --project ./lint/tsconfig.json ./lint/generate-docs.ts",
"e2e": "cross-env NODE_ENV=production ng e2e",
"clean:dev:config": "rimraf src/assets/config.json",
"clean:coverage": "rimraf coverage",
@@ -40,7 +45,8 @@
"cypress:run": "cypress run",
"env:yaml": "ts-node --project ./tsconfig.ts-node.json scripts/env-to-yaml.ts",
"base-href": "ts-node --project ./tsconfig.ts-node.json scripts/base-href.ts",
"check-circ-deps": "npx madge --exclude '(bitstream|bundle|collection|config-submission-form|eperson|item|version)\\.model\\.ts$' --circular --extensions ts ./"
"check-circ-deps": "npx madge --exclude '(bitstream|bundle|collection|config-submission-form|eperson|item|version)\\.model\\.ts$' --circular --extensions ts ./",
"postinstall": "yarn build:lint || echo 'Skipped DSpace ESLint plugins.'"
},
"browser": {
"fs": false,
@@ -55,17 +61,18 @@
"ts-node": "10.2.1"
},
"dependencies": {
"@angular/animations": "^16.2.12",
"@angular/cdk": "^16.2.12",
"@angular/common": "^16.2.12",
"@angular/compiler": "^16.2.12",
"@angular/core": "^16.2.12",
"@angular/forms": "^16.2.12",
"@angular/localize": "16.2.12",
"@angular/platform-browser": "^16.2.12",
"@angular/platform-browser-dynamic": "^16.2.12",
"@angular/platform-server": "^16.2.12",
"@angular/router": "^16.2.12",
"@angular/animations": "^17.3.11",
"@angular/cdk": "^17.3.10",
"@angular/common": "^17.3.11",
"@angular/compiler": "^17.3.11",
"@angular/core": "^17.3.11",
"@angular/forms": "^17.3.11",
"@angular/localize": "17.3.11",
"@angular/platform-browser": "^17.3.11",
"@angular/platform-browser-dynamic": "^17.3.11",
"@angular/platform-server": "^17.3.11",
"@angular/router": "^17.3.11",
"@angular/ssr": "^17.3.8",
"@babel/runtime": "7.21.0",
"@kolkov/ngx-gallery": "^2.0.1",
"@material-ui/core": "^4.11.0",
@@ -73,10 +80,9 @@
"@ng-bootstrap/ng-bootstrap": "^11.0.0",
"@ng-dynamic-forms/core": "^16.0.0",
"@ng-dynamic-forms/ui-ng-bootstrap": "^16.0.0",
"@ngrx/effects": "^16.3.0",
"@ngrx/router-store": "^16.3.0",
"@ngrx/store": "^16.3.0",
"@nguniversal/express-engine": "^16.2.0",
"@ngrx/effects": "^17.1.1",
"@ngrx/router-store": "^17.1.1",
"@ngrx/store": "^17.1.1",
"@ngx-translate/core": "^14.0.0",
"@nicky-lenaers/ngx-scroll-to": "^14.0.0",
"@types/grecaptcha": "^3.0.4",
@@ -93,7 +99,7 @@
"date-fns": "^2.29.3",
"date-fns-tz": "^1.3.7",
"deepmerge": "^4.3.1",
"ejs": "^3.1.9",
"ejs": "^3.1.10",
"express": "^4.19.2",
"express-rate-limit": "^5.1.3",
"fast-json-patch": "^3.1.1",
@@ -130,24 +136,24 @@
"sortablejs": "1.15.0",
"uuid": "^8.3.2",
"webfontloader": "1.6.28",
"zone.js": "~0.13.3"
"zone.js": "~0.14.4"
},
"devDependencies": {
"@angular-builders/custom-webpack": "~16.0.0",
"@angular-devkit/build-angular": "^16.2.12",
"@angular-eslint/builder": "16.3.1",
"@angular-eslint/eslint-plugin": "16.3.1",
"@angular-eslint/eslint-plugin-template": "16.3.1",
"@angular-eslint/schematics": "16.3.1",
"@angular-eslint/template-parser": "16.3.1",
"@angular/cli": "^16.2.12",
"@angular/compiler-cli": "^16.2.12",
"@angular/language-service": "^16.2.12",
"@angular-builders/custom-webpack": "~17.0.2",
"@angular-devkit/build-angular": "^17.3.8",
"@angular-eslint/builder": "17.2.1",
"@angular-eslint/bundled-angular-compiler": "17.2.1",
"@angular-eslint/eslint-plugin": "17.2.1",
"@angular-eslint/eslint-plugin-template": "17.2.1",
"@angular-eslint/schematics": "17.2.1",
"@angular-eslint/template-parser": "17.2.1",
"@angular/cli": "^17.3.8",
"@angular/compiler-cli": "^17.3.11",
"@angular/language-service": "^17.3.11",
"@cypress/schematic": "^1.5.0",
"@fortawesome/fontawesome-free": "^6.4.0",
"@ngrx/store-devtools": "^16.3.0",
"@ngrx/store-devtools": "^17.1.1",
"@ngtools/webpack": "^16.2.12",
"@nguniversal/builders": "^16.2.0",
"@types/deep-freeze": "0.1.2",
"@types/ejs": "^3.1.2",
"@types/express": "^4.17.17",
@@ -156,9 +162,12 @@
"@types/lodash": "^4.14.194",
"@types/node": "^14.14.9",
"@types/sanitize-html": "^2.9.0",
"@typescript-eslint/eslint-plugin": "^5.59.1",
"@typescript-eslint/parser": "^5.59.1",
"@typescript-eslint/eslint-plugin": "^7.2.0",
"@typescript-eslint/parser": "^7.2.0",
"@typescript-eslint/rule-tester": "^7.2.0",
"@typescript-eslint/utils": "^7.2.0",
"axe-core": "^4.7.2",
"browser-sync": "^3.0.0",
"compression-webpack-plugin": "^9.2.0",
"copy-webpack-plugin": "^6.4.1",
"cross-env": "^7.0.3",
@@ -167,6 +176,8 @@
"deep-freeze": "0.0.1",
"eslint": "^8.39.0",
"eslint-plugin-deprecation": "^1.4.1",
"eslint-plugin-dspace-angular-html": "link:./lint/dist/src/rules/html",
"eslint-plugin-dspace-angular-ts": "link:./lint/dist/src/rules/ts",
"eslint-plugin-import": "^2.27.5",
"eslint-plugin-import-newlines": "^1.3.1",
"eslint-plugin-jsdoc": "^45.0.0",
@@ -176,6 +187,7 @@
"eslint-plugin-simple-import-sort": "^10.0.0",
"eslint-plugin-unused-imports": "^2.0.0",
"express-static-gzip": "^2.1.7",
"jasmine": "^3.8.0",
"jasmine-core": "^3.8.0",
"jasmine-marbles": "0.9.2",
"karma": "^6.4.2",
@@ -200,10 +212,10 @@
"sass-loader": "^12.6.0",
"sass-resources-loader": "^2.2.5",
"ts-node": "^8.10.2",
"typescript": "~4.9.3",
"webpack": "5.76.1",
"typescript": "~5.3.3",
"webpack": "5.90.3",
"webpack-bundle-analyzer": "^4.8.0",
"webpack-cli": "^4.2.0",
"webpack-dev-server": "^4.13.3"
"webpack-cli": "^5.1.4",
"webpack-dev-server": "^4.15.1"
}
}

View File

@@ -275,7 +275,9 @@ function readFileIfExists(pathToFile) {
try {
return fs.readFileSync(pathToFile, 'utf8');
} catch (e) {
console.error('Error:', e.stack);
if (e instanceof Error) {
console.error('Error:', e.stack);
}
}
}
return null;

150
server.ts
View File

@@ -17,7 +17,6 @@
import 'zone.js/node';
import 'reflect-metadata';
import 'rxjs';
/* eslint-disable import/no-namespace */
import * as morgan from 'morgan';
@@ -39,23 +38,26 @@ import { join } from 'path';
import { enableProdMode } from '@angular/core';
import { ngExpressEngine } from '@nguniversal/express-engine';
import { REQUEST, RESPONSE } from '@nguniversal/express-engine/tokens';
import { environment } from './src/environments/environment';
import { createProxyMiddleware } from 'http-proxy-middleware';
import { hasNoValue, hasValue } from './src/app/shared/empty.util';
import { hasValue } from './src/app/shared/empty.util';
import { UIServerConfig } from './src/config/ui-server-config.interface';
import bootstrap from './src/main.server';
import { buildAppConfig } from './src/config/config.server';
import { APP_CONFIG, AppConfig } from './src/config/app-config.interface';
import {
APP_CONFIG,
AppConfig,
} from './src/config/app-config.interface';
import { extendEnvironmentWithAppConfig } from './src/config/config.util';
import { logStartupMessage } from './startup-message';
import { TOKENITEM } from './src/app/core/auth/models/auth-token-info.model';
import { CommonEngine } from '@angular/ssr';
import { APP_BASE_HREF } from '@angular/common';
import {
REQUEST,
RESPONSE,
} from './src/express.tokens';
/*
* Set path for the browser application's dist folder
@@ -127,28 +129,6 @@ export function app() {
*/
server.use(json());
// Our Universal express-engine (found @ https://github.com/angular/universal/tree/master/modules/express-engine)
server.engine('html', (_, options, callback) =>
ngExpressEngine({
bootstrap,
inlineCriticalCss: environment.universal.inlineCriticalCss,
providers: [
{
provide: REQUEST,
useValue: (options as any).req,
},
{
provide: RESPONSE,
useValue: (options as any).req.res,
},
{
provide: APP_CONFIG,
useValue: environment,
},
],
})(_, (options as any), callback),
);
server.engine('ejs', ejs.renderFile);
/*
@@ -237,10 +217,10 @@ export function app() {
/*
* The callback function to serve server side angular
*/
function ngApp(req, res) {
if (environment.universal.preboot) {
function ngApp(req, res, next) {
if (environment.ssr.enabled) {
// Render the page to user via SSR (server side rendering)
serverSideRender(req, res);
serverSideRender(req, res, next);
} else {
// If preboot is disabled, just serve the client
console.log('Universal off, serving for direct client-side rendering (CSR)');
@@ -253,45 +233,66 @@ function ngApp(req, res) {
* returned to the user.
* @param req current request
* @param res current response
* @param next the next function
* @param sendToUser if true (default), send the rendered content to the user.
* If false, then only save this rendered content to the in-memory cache (to refresh cache).
*/
function serverSideRender(req, res, sendToUser: boolean = true) {
function serverSideRender(req, res, next, sendToUser: boolean = true) {
const { protocol, originalUrl, baseUrl, headers } = req;
const commonEngine = new CommonEngine({ enablePerformanceProfiler: environment.ssr.enablePerformanceProfiler });
// Render the page via SSR (server side rendering)
res.render(indexHtml, {
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)) {
// save server side rendered page to cache (if any are enabled)
saveToCache(req, data);
if (sendToUser) {
res.locals.ssr = true; // mark response as SSR (enables text compression)
// send rendered page to user
res.send(data);
commonEngine
.render({
bootstrap,
documentFilePath: indexHtml,
inlineCriticalCss: environment.ssr.inlineCriticalCss,
url: `${protocol}://${headers.host}${originalUrl}`,
publicPath: DIST_FOLDER,
providers: [
{ provide: APP_BASE_HREF, useValue: baseUrl },
{
provide: REQUEST,
useValue: req,
},
{
provide: RESPONSE,
useValue: res,
},
{
provide: APP_CONFIG,
useValue: environment,
},
],
})
.then((html) => {
if (hasValue(html)) {
// save server side rendered page to cache (if any are enabled)
saveToCache(req, html);
if (sendToUser) {
res.locals.ssr = true; // mark response as SSR (enables text compression)
// send rendered page to user
res.send(html);
}
}
} else if (hasValue(err) && err.code === 'ERR_HTTP_HEADERS_SENT') {
// When this error occurs we can't fall back to CSR because the response has already been
// sent. These errors occur for various reasons in universal, not all of which are in our
// control to solve.
console.warn('Warning [ERR_HTTP_HEADERS_SENT]: Tried to set headers after they were sent to the client');
} else {
console.warn('Error in server-side rendering (SSR)');
if (hasValue(err)) {
console.warn('Error details : ', err);
})
.catch((err) => {
if (hasValue(err) && err.code === 'ERR_HTTP_HEADERS_SENT') {
// When this error occurs we can't fall back to CSR because the response has already been
// sent. These errors occur for various reasons in universal, not all of which are in our
// control to solve.
console.warn('Warning [ERR_HTTP_HEADERS_SENT]: Tried to set headers after they were sent to the client');
} else {
console.warn('Error in server-side rendering (SSR)');
if (hasValue(err)) {
console.warn('Error details : ', err);
}
if (sendToUser) {
console.warn('Falling back to serving direct client-side rendering (CSR).');
clientSideRender(req, res);
}
}
if (sendToUser) {
console.warn('Falling back to serving direct client-side rendering (CSR).');
clientSideRender(req, res);
}
}
});
next(err);
});
}
/**
@@ -349,7 +350,7 @@ function initCache() {
function botCacheEnabled(): boolean {
// Caching is only enabled if SSR is enabled AND
// "max" pages to cache is greater than zero
return environment.universal.preboot && environment.cache.serverSide.botCache.max && (environment.cache.serverSide.botCache.max > 0);
return environment.ssr.enabled && environment.cache.serverSide.botCache.max && (environment.cache.serverSide.botCache.max > 0);
}
/**
@@ -358,7 +359,7 @@ function botCacheEnabled(): boolean {
function anonymousCacheEnabled(): boolean {
// Caching is only enabled if SSR is enabled AND
// "max" pages to cache is greater than zero
return environment.universal.preboot && environment.cache.serverSide.anonymousCache.max && (environment.cache.serverSide.anonymousCache.max > 0);
return environment.ssr.enabled && environment.cache.serverSide.anonymousCache.max && (environment.cache.serverSide.anonymousCache.max > 0);
}
/**
@@ -371,9 +372,9 @@ function cacheCheck(req, res, next) {
// If the bot cache is enabled and this request looks like a bot, check the bot cache for a cached page.
if (botCacheEnabled() && isbot(req.get('user-agent'))) {
cachedCopy = checkCacheForRequest('bot', botCache, req, res);
cachedCopy = checkCacheForRequest('bot', botCache, req, res, next);
} else if (anonymousCacheEnabled() && !isUserAuthenticated(req)) {
cachedCopy = checkCacheForRequest('anonymous', anonymousCache, req, res);
cachedCopy = checkCacheForRequest('anonymous', anonymousCache, req, res, next);
}
// If cached copy exists, return it to the user.
@@ -409,9 +410,10 @@ function cacheCheck(req, res, next) {
* @param cache LRU cache to check
* @param req current request to look for in the cache
* @param res current response
* @param next the next function
* @returns cached copy (if found) or undefined (if not found)
*/
function checkCacheForRequest(cacheName: string, cache: LRU<string, any>, req, res): any {
function checkCacheForRequest(cacheName: string, cache: LRU<string, any>, req, res, next): any {
// Get the cache key for this request
const key = getCacheKey(req);
@@ -427,7 +429,7 @@ function checkCacheForRequest(cacheName: string, cache: LRU<string, any>, req, r
// Update cached copy by rerendering server-side
// NOTE: In this scenario the currently cached copy will be returned to the current user.
// This re-render is peformed behind the scenes to update cached copy for next user.
serverSideRender(req, res, false);
serverSideRender(req, res, next, false);
}
} else {
if (environment.cache.serverSide.debug) { console.log(`CACHE MISS FOR ${key} in ${cacheName} cache.`); }
@@ -531,7 +533,7 @@ function createHttpsServer(keys) {
const listener = createServer({
key: keys.serviceKey,
cert: keys.certificate,
}, app).listen(environment.ui.port, environment.ui.host, () => {
}, app()).listen(environment.ui.port, environment.ui.host, () => {
serverStarted();
});

View File

@@ -1,16 +1,13 @@
import { AbstractControl } from '@angular/forms';
import {
mapToCanActivate,
Route,
} from '@angular/router';
import { Route } from '@angular/router';
import {
DYNAMIC_ERROR_MESSAGES_MATCHER,
DynamicErrorMessagesMatcher,
} from '@ng-dynamic-forms/core';
import { i18nBreadcrumbResolver } from '../core/breadcrumbs/i18n-breadcrumb.resolver';
import { GroupAdministratorGuard } from '../core/data/feature-authorization/feature-authorization-guard/group-administrator.guard';
import { SiteAdministratorGuard } from '../core/data/feature-authorization/feature-authorization-guard/site-administrator.guard';
import { groupAdministratorGuard } from '../core/data/feature-authorization/feature-authorization-guard/group-administrator.guard';
import { siteAdministratorGuard } from '../core/data/feature-authorization/feature-authorization-guard/site-administrator.guard';
import {
EPERSON_PATH,
GROUP_PATH,
@@ -20,7 +17,7 @@ import { EPeopleRegistryComponent } from './epeople-registry/epeople-registry.co
import { EPersonFormComponent } from './epeople-registry/eperson-form/eperson-form.component';
import { EPersonResolver } from './epeople-registry/eperson-resolver.service';
import { GroupFormComponent } from './group-registry/group-form/group-form.component';
import { GroupPageGuard } from './group-registry/group-page.guard';
import { groupPageGuard } from './group-registry/group-page.guard';
import { GroupsRegistryComponent } from './group-registry/groups-registry.component';
/**
@@ -28,7 +25,7 @@ import { GroupsRegistryComponent } from './group-registry/groups-registry.compon
*/
export const ValidateEmailErrorStateMatcher: DynamicErrorMessagesMatcher =
(control: AbstractControl, model: any, hasFocus: boolean) => {
return (control.touched && !hasFocus) || (control.errors?.emailTaken && hasFocus);
return ( control.touched && !hasFocus ) || ( control.errors?.emailTaken && hasFocus );
};
const providers = [
@@ -46,7 +43,7 @@ export const ROUTES: Route[] = [
},
providers,
data: { title: 'admin.access-control.epeople.title', breadcrumbKey: 'admin.access-control.epeople' },
canActivate: mapToCanActivate([SiteAdministratorGuard]),
canActivate: [siteAdministratorGuard],
},
{
path: `${EPERSON_PATH}/create`,
@@ -56,7 +53,7 @@ export const ROUTES: Route[] = [
},
providers,
data: { title: 'admin.access-control.epeople.add.title', breadcrumbKey: 'admin.access-control.epeople.add' },
canActivate: mapToCanActivate([SiteAdministratorGuard]),
canActivate: [siteAdministratorGuard],
},
{
path: `${EPERSON_PATH}/:id/edit`,
@@ -67,7 +64,7 @@ export const ROUTES: Route[] = [
},
providers,
data: { title: 'admin.access-control.epeople.edit.title', breadcrumbKey: 'admin.access-control.epeople.edit' },
canActivate: mapToCanActivate([SiteAdministratorGuard]),
canActivate: [siteAdministratorGuard],
},
{
path: GROUP_PATH,
@@ -77,7 +74,7 @@ export const ROUTES: Route[] = [
},
providers,
data: { title: 'admin.access-control.groups.title', breadcrumbKey: 'admin.access-control.groups' },
canActivate: mapToCanActivate([GroupAdministratorGuard]),
canActivate: [groupAdministratorGuard],
},
{
path: `${GROUP_PATH}/create`,
@@ -90,7 +87,7 @@ export const ROUTES: Route[] = [
title: 'admin.access-control.groups.title.addGroup',
breadcrumbKey: 'admin.access-control.groups.addGroup',
},
canActivate: mapToCanActivate([GroupAdministratorGuard]),
canActivate: [groupAdministratorGuard],
},
{
path: `${GROUP_PATH}/:groupId/edit`,
@@ -103,7 +100,7 @@ export const ROUTES: Route[] = [
title: 'admin.access-control.groups.title.singleGroup',
breadcrumbKey: 'admin.access-control.groups.singleGroup',
},
canActivate: mapToCanActivate([GroupPageGuard]),
canActivate: [groupPageGuard],
},
{
path: 'bulk-access',
@@ -112,6 +109,6 @@ export const ROUTES: Route[] = [
breadcrumb: i18nBreadcrumbResolver,
},
data: { title: 'admin.access-control.bulk-access.title', breadcrumbKey: 'admin.access-control.bulk-access' },
canActivate: mapToCanActivate([SiteAdministratorGuard]),
canActivate: [siteAdministratorGuard],
},
];

View File

@@ -23,10 +23,10 @@
<a ngbNavLink>{{'admin.access-control.bulk-access-browse.search.header' | translate}}</a>
<ng-template ngbNavContent>
<div class="mx-n3">
<ds-themed-search [configuration]="'administrativeBulkAccess'"
<ds-search [configuration]="'administrativeBulkAccess'"
[selectable]="true"
[selectionConfig]="{ repeatable: true, listId: listId }"
[showThumbnails]="false"></ds-themed-search>
[showThumbnails]="false"></ds-search>
</div>
</ng-template>
</li>
@@ -37,7 +37,6 @@
<ng-template ngbNavContent>
<ds-pagination
[paginationOptions]="(paginationOptions$ | async)"
[pageInfoState]="(objectsSelected$|async)?.payload.pageInfo"
[collectionSize]="(objectsSelected$|async)?.payload?.totalElements"
[objects]="(objectsSelected$|async)"
[showPaginator]="false"

View File

@@ -41,11 +41,10 @@
</div>
</form>
<ds-themed-loading *ngIf="searching$ | async"></ds-themed-loading>
<ds-loading *ngIf="searching$ | async"></ds-loading>
<ds-pagination
*ngIf="(pageInfoState$ | async)?.totalElements > 0 && (searching$ | async) !== true"
[paginationOptions]="config"
[pageInfoState]="pageInfoState$"
[collectionSize]="(pageInfoState$ | async)?.totalElements"
[hideGear]="true"
[hidePagerWhenSinglePage]="true">

View File

@@ -42,17 +42,16 @@
</button>
</ds-form>
<ds-themed-loading [showMessage]="false" *ngIf="!formGroup"></ds-themed-loading>
<ds-loading [showMessage]="false" *ngIf="!formGroup"></ds-loading>
<div *ngIf="epersonService.getActiveEPerson() | async">
<h2>{{messagePrefix + '.groupsEPersonIsMemberOf' | translate}}</h2>
<ds-themed-loading [showMessage]="false" *ngIf="groups$ | async | dsHasNoValue"></ds-themed-loading>
<ds-loading [showMessage]="false" *ngIf="groups$ | async | dsHasNoValue"></ds-loading>
<ds-pagination
*ngIf="(groups$ | async)?.payload?.totalElements > 0"
[paginationOptions]="config"
[pageInfoState]="groupsPageInfoState$"
[collectionSize]="(groups$ | async)?.payload?.totalElements"
[hideGear]="true"
[hidePagerWhenSinglePage]="true"

View File

@@ -5,7 +5,6 @@
<ds-pagination *ngIf="(ePeopleMembersOfGroup | async)?.totalElements > 0"
[paginationOptions]="config"
[pageInfoState]="(ePeopleMembersOfGroup | async)"
[collectionSize]="(ePeopleMembersOfGroup | async)?.totalElements"
[hideGear]="true"
[hidePagerWhenSinglePage]="true">
@@ -21,25 +20,33 @@
</tr>
</thead>
<tbody>
<tr *ngFor="let eperson of (ePeopleMembersOfGroup | async)?.page">
<td class="align-middle">{{eperson.id}}</td>
<tr *ngFor="let epersonDTO of (ePeopleMembersOfGroup | async)?.page">
<td class="align-middle">{{epersonDTO.eperson.id}}</td>
<td class="align-middle">
<a [routerLink]="getEPersonEditRoute(eperson.id)">
{{ dsoNameService.getName(eperson) }}
<a [routerLink]="getEPersonEditRoute(epersonDTO.eperson.id)">
{{ dsoNameService.getName(epersonDTO.eperson) }}
</a>
</td>
<td class="align-middle">
{{messagePrefix + '.table.email' | translate}}: {{ eperson.email ? eperson.email : '-' }}<br/>
{{messagePrefix + '.table.netid' | translate}}: {{ eperson.netid ? eperson.netid : '-' }}
{{messagePrefix + '.table.email' | translate}}: {{ epersonDTO.eperson.email ? epersonDTO.eperson.email : '-' }}<br/>
{{messagePrefix + '.table.netid' | translate}}: {{ epersonDTO.eperson.netid ? epersonDTO.eperson.netid : '-' }}
</td>
<td class="align-middle">
<div class="btn-group edit-field">
<button (click)="deleteMemberFromGroup(eperson)"
<button (click)="deleteMemberFromGroup(epersonDTO.eperson)"
*ngIf="epersonDTO.ableToDelete"
[disabled]="actionConfig.remove.disabled"
[ngClass]="['btn btn-sm', actionConfig.remove.css]"
title="{{messagePrefix + '.table.edit.buttons.remove' | translate: { name: dsoNameService.getName(eperson) } }}">
title="{{messagePrefix + '.table.edit.buttons.remove' | translate: { name: dsoNameService.getName(epersonDTO.eperson) } }}">
<i [ngClass]="actionConfig.remove.icon"></i>
</button>
<button *ngIf="!epersonDTO.ableToDelete"
(click)="addMemberToGroup(epersonDTO.eperson)"
[disabled]="actionConfig.add.disabled"
[ngClass]="['btn btn-sm', actionConfig.add.css]"
title="{{messagePrefix + '.table.edit.buttons.add' | translate: { name: dsoNameService.getName(epersonDTO.eperson) } }}">
<i [ngClass]="actionConfig.add.icon"></i>
</button>
</div>
</td>
</tr>
@@ -86,7 +93,6 @@
<ds-pagination *ngIf="(ePeopleSearch | async)?.totalElements > 0"
[paginationOptions]="configSearch"
[pageInfoState]="(ePeopleSearch | async)"
[collectionSize]="(ePeopleSearch | async)?.totalElements"
[hideGear]="true"
[hidePagerWhenSinglePage]="true">

View File

@@ -222,13 +222,13 @@ describe('MembersListComponent', () => {
describe('if first delete button is pressed', () => {
beforeEach(() => {
spyOn(component, 'search').and.callThrough();
const deleteButton: DebugElement = fixture.debugElement.query(By.css('#ePeopleMembersOfGroup tbody .fa-trash-alt'));
deleteButton.nativeElement.click();
fixture.detectChanges();
});
it('then no ePerson remains as a member of the active group.', () => {
const epersonsFound = fixture.debugElement.queryAll(By.css('#ePeopleMembersOfGroup tbody tr'));
expect(epersonsFound.length).toEqual(0);
it('should trigger the search to add the user back to the search table', () => {
expect(component.search).toHaveBeenCalled();
});
});
});
@@ -264,13 +264,13 @@ describe('MembersListComponent', () => {
describe('if first add button is pressed', () => {
beforeEach(() => {
spyOn(component, 'search').and.callThrough();
const addButton: DebugElement = fixture.debugElement.query(By.css('#epersonsSearch tbody .fa-plus'));
addButton.nativeElement.click();
fixture.detectChanges();
});
it('then all (two) ePersons are member of the active group. No non-members left', () => {
epersonsFound = fixture.debugElement.queryAll(By.css('#epersonsSearch tbody tr'));
expect(epersonsFound.length).toEqual(0);
it('should trigger the search to remove the user from the search table', () => {
expect(component.search).toHaveBeenCalled();
});
});
});

View File

@@ -24,21 +24,29 @@ import {
} from '@ngx-translate/core';
import {
BehaviorSubject,
combineLatest as observableCombineLatest,
Observable,
ObservedValueOf,
of as observableOf,
Subscription,
} from 'rxjs';
import {
defaultIfEmpty,
map,
switchMap,
take,
} from 'rxjs/operators';
import { DSONameService } from '../../../../core/breadcrumbs/dso-name.service';
import { PaginatedList } from '../../../../core/data/paginated-list.model';
import {
buildPaginatedList,
PaginatedList,
} from '../../../../core/data/paginated-list.model';
import { RemoteData } from '../../../../core/data/remote-data';
import { EPersonDataService } from '../../../../core/eperson/eperson-data.service';
import { GroupDataService } from '../../../../core/eperson/group-data.service';
import { EPerson } from '../../../../core/eperson/models/eperson.model';
import { EpersonDtoModel } from '../../../../core/eperson/models/eperson-dto.model';
import { Group } from '../../../../core/eperson/models/group.model';
import { PaginationService } from '../../../../core/pagination/pagination.service';
import {
@@ -114,21 +122,21 @@ export interface EPersonListActionConfig {
export class MembersListComponent implements OnInit, OnDestroy {
@Input()
messagePrefix: string;
messagePrefix: string;
@Input()
actionConfig: EPersonListActionConfig = {
add: {
css: 'btn-outline-primary',
disabled: false,
icon: 'fas fa-plus fa-fw',
},
remove: {
css: 'btn-outline-danger',
disabled: false,
icon: 'fas fa-trash-alt fa-fw',
},
};
actionConfig: EPersonListActionConfig = {
add: {
css: 'btn-outline-primary',
disabled: false,
icon: 'fas fa-plus fa-fw',
},
remove: {
css: 'btn-outline-danger',
disabled: false,
icon: 'fas fa-trash-alt fa-fw',
},
};
/**
* EPeople being displayed in search result, initially all members, after search result of search
@@ -137,7 +145,7 @@ export class MembersListComponent implements OnInit, OnDestroy {
/**
* List of EPeople members of currently active group being edited
*/
ePeopleMembersOfGroup: BehaviorSubject<PaginatedList<EPerson>> = new BehaviorSubject<PaginatedList<EPerson>>(undefined);
ePeopleMembersOfGroup: BehaviorSubject<PaginatedList<EpersonDtoModel>> = new BehaviorSubject(undefined);
/**
* Pagination config used to display the list of EPeople that are result of EPeople search
@@ -226,10 +234,35 @@ export class MembersListComponent implements OnInit, OnDestroy {
return rd;
}
}),
getRemoteDataPayload())
.subscribe((paginatedListOfEPersons: PaginatedList<EPerson>) => {
this.ePeopleMembersOfGroup.next(paginatedListOfEPersons);
}));
switchMap((epersonListRD: RemoteData<PaginatedList<EPerson>>) => {
const dtos$ = observableCombineLatest([...epersonListRD.payload.page.map((member: EPerson) => {
const dto$: Observable<EpersonDtoModel> = observableCombineLatest(
this.isMemberOfGroup(member), (isMember: ObservedValueOf<Observable<boolean>>) => {
const epersonDtoModel: EpersonDtoModel = new EpersonDtoModel();
epersonDtoModel.eperson = member;
epersonDtoModel.ableToDelete = isMember;
return epersonDtoModel;
});
return dto$;
})]);
return dtos$.pipe(defaultIfEmpty([]), map((dtos: EpersonDtoModel[]) => {
return buildPaginatedList(epersonListRD.payload.pageInfo, dtos);
}));
}),
).subscribe((paginatedListOfDTOs: PaginatedList<EpersonDtoModel>) => {
this.ePeopleMembersOfGroup.next(paginatedListOfDTOs);
}),
);
}
/**
* We always return true since this is only used by the top section (which represents all the users part of the group
* in {@link MembersListComponent})
*
* @param possibleMember EPerson that is a possible member (being tested) of the group currently being edited
*/
isMemberOfGroup(possibleMember: EPerson): Observable<boolean> {
return observableOf(true);
}
/**

View File

@@ -5,7 +5,6 @@
<ds-pagination *ngIf="(subGroups$ | async)?.payload?.totalElements > 0"
[paginationOptions]="config"
[pageInfoState]="(subGroups$ | async)?.payload"
[collectionSize]="(subGroups$ | async)?.payload?.totalElements"
[hideGear]="true"
[hidePagerWhenSinglePage]="true">
@@ -84,7 +83,6 @@
<ds-pagination *ngIf="(searchResults$ | async)?.payload?.totalElements > 0"
[paginationOptions]="configSearch"
[pageInfoState]="(searchResults$ | async)?.payload"
[collectionSize]="(searchResults$ | async)?.payload?.totalElements"
[hideGear]="true"
[hidePagerWhenSinglePage]="true">

View File

@@ -80,7 +80,7 @@ enum SubKey {
export class SubgroupsListComponent implements OnInit, OnDestroy {
@Input()
messagePrefix: string;
messagePrefix: string;
/**
* Result of search groups, initially all groups

View File

@@ -1,14 +1,24 @@
import {
TestBed,
waitForAsync,
} from '@angular/core/testing';
import {
ActivatedRouteSnapshot,
Router,
UrlTree,
} from '@angular/router';
import { of as observableOf } from 'rxjs';
import {
Observable,
of as observableOf,
} from 'rxjs';
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 { HALEndpointService } from '../../core/shared/hal-endpoint.service';
import { GroupPageGuard } from './group-page.guard';
import { groupPageGuard } from './group-page.guard';
jasmine.DEFAULT_TIMEOUT_INTERVAL = 10000; // Increase timeout to 10 seconds
describe('GroupPageGuard', () => {
const groupsEndpointUrl = 'https://test.org/api/eperson/groups';
@@ -20,42 +30,54 @@ describe('GroupPageGuard', () => {
},
} as unknown as ActivatedRouteSnapshot;
let guard: GroupPageGuard;
let halEndpointService: HALEndpointService;
let authorizationService: AuthorizationDataService;
let router: Router;
let authService: AuthService;
beforeEach(() => {
function init() {
halEndpointService = jasmine.createSpyObj(['getEndpoint']);
(halEndpointService as any).getEndpoint.and.returnValue(observableOf(groupsEndpointUrl));
( halEndpointService as any ).getEndpoint.and.returnValue(observableOf(groupsEndpointUrl));
authorizationService = jasmine.createSpyObj(['isAuthorized']);
// NOTE: value is set in beforeEach
router = jasmine.createSpyObj(['parseUrl']);
(router as any).parseUrl.and.returnValue = {};
( router as any ).parseUrl.and.returnValue = {};
authService = jasmine.createSpyObj(['isAuthenticated']);
(authService as any).isAuthenticated.and.returnValue(observableOf(true));
( authService as any ).isAuthenticated.and.returnValue(observableOf(true));
guard = new GroupPageGuard(halEndpointService, authorizationService, router, authService);
});
TestBed.configureTestingModule({
providers: [
{ provide: AuthorizationDataService, useValue: authorizationService },
{ provide: Router, useValue: router },
{ provide: AuthService, useValue: authService },
{ provide: HALEndpointService, useValue: halEndpointService },
],
});
}
beforeEach(waitForAsync(() => {
init();
}));
it('should be created', () => {
expect(guard).toBeTruthy();
expect(groupPageGuard).toBeTruthy();
});
describe('canActivate', () => {
describe('when the current user can manage the group', () => {
beforeEach(() => {
(authorizationService as any).isAuthorized.and.returnValue(observableOf(true));
( authorizationService as any ).isAuthorized.and.returnValue(observableOf(true));
});
it('should return true', (done) => {
guard.canActivate(
routeSnapshotWithGroupId, { url: 'current-url' } as any,
).subscribe((result) => {
const result$ = TestBed.runInInjectionContext(() => {
return groupPageGuard()(routeSnapshotWithGroupId, { url: 'current-url' } as any);
}) as Observable<boolean | UrlTree>;
result$.subscribe((result) => {
expect(authorizationService.isAuthorized).toHaveBeenCalledWith(
FeatureID.CanManageGroup, groupEndpointUrl, undefined,
);
@@ -71,15 +93,18 @@ describe('GroupPageGuard', () => {
});
it('should not return true', (done) => {
guard.canActivate(
routeSnapshotWithGroupId, { url: 'current-url' } as any,
).subscribe((result) => {
const result$ = TestBed.runInInjectionContext(() => {
return groupPageGuard()(routeSnapshotWithGroupId, { url: 'current-url' } as any);
}) as Observable<boolean | UrlTree>;
result$.subscribe((result) => {
expect(authorizationService.isAuthorized).toHaveBeenCalledWith(
FeatureID.CanManageGroup, groupEndpointUrl, undefined,
);
expect(result).not.toBeTrue();
done();
});
});
});
});

View File

@@ -1,7 +1,7 @@
import { Injectable } from '@angular/core';
import { inject } from '@angular/core';
import {
ActivatedRouteSnapshot,
Router,
CanActivateFn,
RouterStateSnapshot,
} from '@angular/router';
import {
@@ -10,34 +10,29 @@ import {
} from 'rxjs';
import { map } from 'rxjs/operators';
import { AuthService } from '../../core/auth/auth.service';
import { AuthorizationDataService } from '../../core/data/feature-authorization/authorization-data.service';
import { SomeFeatureAuthorizationGuard } from '../../core/data/feature-authorization/feature-authorization-guard/some-feature-authorization.guard';
import {
someFeatureAuthorizationGuard,
StringGuardParamFn,
} from '../../core/data/feature-authorization/feature-authorization-guard/some-feature-authorization.guard';
import { FeatureID } from '../../core/data/feature-authorization/feature-id';
import { HALEndpointService } from '../../core/shared/hal-endpoint.service';
@Injectable({
providedIn: 'root',
})
export class GroupPageGuard extends SomeFeatureAuthorizationGuard {
const defaultGroupPageGetObjectUrl: StringGuardParamFn = (
route: ActivatedRouteSnapshot,
state: RouterStateSnapshot,
): Observable<string> => {
const halEndpointService = inject(HALEndpointService);
const groupsEndpoint = 'groups';
protected groupsEndpoint = 'groups';
return halEndpointService.getEndpoint(groupsEndpoint).pipe(
map(groupsUrl => `${groupsUrl}/${route?.params?.groupId}`),
);
};
constructor(protected halEndpointService: HALEndpointService,
protected authorizationService: AuthorizationDataService,
protected router: Router,
protected authService: AuthService) {
super(authorizationService, router, authService);
}
getFeatureIDs(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<FeatureID[]> {
return observableOf([FeatureID.CanManageGroup]);
}
getObjectUrl(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<string> {
return this.halEndpointService.getEndpoint(this.groupsEndpoint).pipe(
map(groupsUrl => `${groupsUrl}/${route?.params?.groupId}`),
);
}
}
export const groupPageGuard = (
getObjectUrl = defaultGroupPageGetObjectUrl,
getEPersonUuid?: StringGuardParamFn,
): CanActivateFn => someFeatureAuthorizationGuard(
() => observableOf([FeatureID.CanManageGroup]),
getObjectUrl,
getEPersonUuid);

View File

@@ -33,11 +33,10 @@
</div>
</form>
<ds-themed-loading *ngIf="loading$ | async"></ds-themed-loading>
<ds-loading *ngIf="loading$ | async"></ds-loading>
<ds-pagination
*ngIf="(pageInfoState$ | async)?.totalElements > 0 && (loading$ | async) !== true"
[paginationOptions]="config"
[pageInfoState]="pageInfoState$"
[collectionSize]="(pageInfoState$ | async)?.totalElements"
[hideGear]="true"
[hidePagerWhenSinglePage]="true">

View File

@@ -22,10 +22,7 @@ import {
} from '@angular/router';
import { NgbModule } from '@ng-bootstrap/ng-bootstrap';
import { provideMockStore } from '@ngrx/store/testing';
import {
TranslateLoader,
TranslateModule,
} from '@ngx-translate/core';
import { TranslateModule } from '@ngx-translate/core';
import {
Observable,
of as observableOf,
@@ -59,6 +56,7 @@ import {
} from '../../shared/mocks/dso-name.service.mock';
import { RouterMock } from '../../shared/mocks/router.mock';
import { NotificationsService } from '../../shared/notifications/notifications.service';
import { PaginationComponent } from '../../shared/pagination/pagination.component';
import { createSuccessfulRemoteDataObject$ } from '../../shared/remote-data.utils';
import { ActivatedRouteStub } from '../../shared/testing/active-router.stub';
import {
@@ -72,7 +70,6 @@ import {
import { NotificationsServiceStub } from '../../shared/testing/notifications-service.stub';
import { PaginationServiceStub } from '../../shared/testing/pagination-service.stub';
import { routeServiceStub } from '../../shared/testing/route-service.stub';
import { TranslateLoaderMock } from '../../shared/testing/translate-loader.mock';
import { GroupsRegistryComponent } from './groups-registry.component';
describe('GroupsRegistryComponent', () => {
@@ -209,12 +206,9 @@ describe('GroupsRegistryComponent', () => {
paginationService = new PaginationServiceStub();
return TestBed.configureTestingModule({
imports: [CommonModule, NgbModule, FormsModule, ReactiveFormsModule, BrowserModule,
TranslateModule.forRoot({
loader: {
provide: TranslateLoader,
useClass: TranslateLoaderMock,
},
}), GroupsRegistryComponent],
TranslateModule.forRoot(),
GroupsRegistryComponent,
],
providers: [GroupsRegistryComponent,
{ provide: DSONameService, useValue: new DSONameServiceMock() },
{ provide: EPersonDataService, useValue: ePersonDataServiceStub },
@@ -232,6 +226,12 @@ describe('GroupsRegistryComponent', () => {
provideMockStore(),
],
schemas: [NO_ERRORS_SCHEMA],
}).overrideComponent(GroupsRegistryComponent, {
remove: {
imports: [
PaginationComponent,
],
},
}).compileComponents();
}));

View File

@@ -14,10 +14,7 @@ import {
ReactiveFormsModule,
UntypedFormBuilder,
} from '@angular/forms';
import {
Router,
RouterLink,
} from '@angular/router';
import { RouterLink } from '@angular/router';
import { NgbTooltipModule } from '@ng-bootstrap/ng-bootstrap';
import {
TranslateModule,
@@ -149,7 +146,6 @@ export class GroupsRegistryComponent implements OnInit, OnDestroy {
private notificationsService: NotificationsService,
private formBuilder: UntypedFormBuilder,
protected routeService: RouteService,
private router: Router,
private authorizationService: AuthorizationDataService,
private paginationService: PaginationService,
public requestService: RequestService,

View File

@@ -21,12 +21,12 @@ import { NotificationsService } from '../../shared/notifications/notifications.s
import { FileDropzoneNoUploaderComponent } from '../../shared/upload/file-dropzone-no-uploader/file-dropzone-no-uploader.component';
@Component({
selector: 'ds-metadata-import-page',
selector: 'ds-base-metadata-import-page',
templateUrl: './metadata-import-page.component.html',
imports: [
TranslateModule,
FormsModule,
FileDropzoneNoUploaderComponent,
FormsModule,
TranslateModule,
],
standalone: true,
})

View File

@@ -0,0 +1,27 @@
import { Component } from '@angular/core';
import { ThemedComponent } from '../../shared/theme-support/themed.component';
import { MetadataImportPageComponent } from './metadata-import-page.component';
/**
* Themed wrapper for {@link MetadataImportPageComponent}.
*/
@Component({
selector: 'ds-metadata-import-page',
templateUrl: '../../shared/theme-support/themed.component.html',
standalone: true,
imports: [MetadataImportPageComponent],
})
export class ThemedMetadataImportPageComponent extends ThemedComponent<MetadataImportPageComponent> {
protected getComponentName(): string {
return 'MetadataImportPageComponent';
}
protected importThemedComponent(themeName: string): Promise<any> {
return import(`../../../themes/${themeName}/app/admin/admin-import-metadata-page/metadata-import-page.component`);
}
protected importUnthemedComponent(): Promise<any> {
return import('./metadata-import-page.component');
}
}

View File

@@ -212,7 +212,7 @@
<span> {{'ldn-service.control-constaint-select-none' | translate}} </span>
</button>
<button (click)="selectInboundItemFilter(constraint.id, i); $event.stopPropagation()"
*ngFor="let constraint of (itemfiltersRD$ | async)?.payload?.page; let internalIndex = index"
*ngFor="let constraint of (itemFiltersRD$ | async)?.payload?.page; let internalIndex = index"
class="dropdown-item collection-item text-truncate w-100"
ngbDropdownItem
type="button">
@@ -263,14 +263,18 @@
<span (click)="addInboundPattern()"
class="add-pattern-link mb-2">{{ 'ldn-new-service.form.label.addPattern' | translate }}</span>
<hr>
<div class="form-group row">
<div class="col text-right space-children-mr">
<ng-content select="[before]"></ng-content>
<button (click)="resetFormAndLeave()" class="btn btn-outline-secondary" type="button">
<span>&nbsp;{{ 'submission.general.back.submit' | translate }}</span>
</button>
<button class="btn btn-primary" type="submit">
<span><i class="fas fa-save"></i>&nbsp;{{ 'ldn-new-service.form.label.submit' | translate }}</span>
</button>
<div class="submission-form-footer my-1 position-sticky d-flex justify-content-between" role="group">
<button (click)="resetFormAndLeave()" class="btn btn-primary" type="button">
<span>&nbsp;{{ 'submission.general.back.submit' | translate }}</span>
</button>
<button class="btn btn-primary" type="submit">
<span><i class="fas fa-save"></i>&nbsp;{{ 'ldn-new-service.form.label.submit' | translate }}</span>
</button>
</div>
</div>
</form>
</div>
@@ -294,7 +298,7 @@
</div>
<div class="modal-footer">
<div *ngIf="!isNewService">
<button (click)="closeModal()" class="btn btn-danger mr-2"
<button (click)="closeModal()" class="btn btn-outline-secondary mr-2"
id="delete-confirm-edit">{{ 'service.detail.return' | translate }}
</button>
<button *ngIf="!isNewService" (click)="patchService()"
@@ -302,7 +306,7 @@
</button>
</div>
<div *ngIf="isNewService">
<button (click)="closeModal()" class="btn btn-danger mr-2 "
<button (click)="closeModal()" class="btn btn-outline-secondary mr-2 "
id="delete-confirm-new">{{ 'service.refuse.create' | translate }}
</button>
<button (click)="createService()"

View File

@@ -145,7 +145,7 @@ describe('LdnServiceFormEditComponent', () => {
it('should init properties correctly', fakeAsync(() => {
spyOn(component, 'fetchServiceData');
spyOn(component, 'setItemfilters');
spyOn(component, 'setItemFilters');
component.ngOnInit();
tick(100);
expect((component as any).serviceId).toEqual(testId);
@@ -153,7 +153,7 @@ describe('LdnServiceFormEditComponent', () => {
expect(component.areControlsInitialized).toBeTruthy();
expect(component.formModel.controls.notifyServiceInboundPatterns).toBeDefined();
expect(component.fetchServiceData).toHaveBeenCalledWith(testId);
expect(component.setItemfilters).toHaveBeenCalled();
expect(component.setItemFilters).toHaveBeenCalled();
}));
it('should unsubscribe on destroy', () => {

View File

@@ -92,7 +92,7 @@ export class LdnServiceFormComponent implements OnInit, OnDestroy {
public inboundPatterns: string[] = notifyPatterns;
public isNewService: boolean;
public areControlsInitialized: boolean;
public itemfiltersRD$: Observable<RemoteData<PaginatedList<Itemfilter>>>;
public itemFiltersRD$: Observable<RemoteData<PaginatedList<Itemfilter>>>;
public config: FindListOptions = Object.assign(new FindListOptions(), {
elementsPerPage: 20,
});
@@ -104,12 +104,12 @@ export class LdnServiceFormComponent implements OnInit, OnDestroy {
private deletedInboundPatterns: number[] = [];
private modalRef: any;
private ldnService: LdnService;
private selectPatternDefaultLabeli18Key = 'ldn-service.form.label.placeholder.default-select';
private selectPatternDefaultLabelI18Key = 'ldn-service.form.label.placeholder.default-select';
private routeSubscription: Subscription;
constructor(
protected ldnServicesService: LdnServicesService,
private ldnItemfiltersService: LdnItemfiltersService,
private ldnItemFiltersService: LdnItemfiltersService,
private formBuilder: FormBuilder,
private router: Router,
private route: ActivatedRoute,
@@ -147,7 +147,7 @@ export class LdnServiceFormComponent implements OnInit, OnDestroy {
this.fetchServiceData(this.serviceId);
}
});
this.setItemfilters();
this.setItemFilters();
}
ngOnDestroy(): void {
@@ -157,8 +157,8 @@ export class LdnServiceFormComponent implements OnInit, OnDestroy {
/**
* Sets item filters using LDN item filters service
*/
setItemfilters() {
this.itemfiltersRD$ = this.ldnItemfiltersService.findAll().pipe(
setItemFilters() {
this.itemFiltersRD$ = this.ldnItemFiltersService.findAll().pipe(
getFirstCompletedRemoteData());
}
@@ -168,21 +168,12 @@ export class LdnServiceFormComponent implements OnInit, OnDestroy {
*/
createService() {
this.formModel.markAllAsTouched();
const notifyServiceInboundPatterns = this.formModel.get('notifyServiceInboundPatterns') as FormArray;
const hasInboundPattern = notifyServiceInboundPatterns?.length > 0 ? this.checkPatterns(notifyServiceInboundPatterns) : false;
if (this.formModel.invalid) {
this.closeModal();
return;
}
if (!hasInboundPattern) {
this.notificationService.warning(this.translateService.get('ldn-service-notification.created.warning.title'));
this.closeModal();
return;
}
this.formModel.value.notifyServiceInboundPatterns = this.formModel.value.notifyServiceInboundPatterns.map((pattern: {
pattern: string;
patternLabel: string,
@@ -272,20 +263,24 @@ export class LdnServiceFormComponent implements OnInit, OnDestroy {
}
/**
* Filters pattern objects, initializes form groups, assigns labels, and adds them to the specified form array so the correct string is shown in the dropdown..
* Filters pattern objects, initializes form groups, assigns labels, and adds them to the specified form array so the correct string is shown in the dropdown.
* @param formArrayName - The name of the form array to be populated
*/
filterPatternObjectsAndAssignLabel(formArrayName: string) {
const PatternsArray = this.formModel.get(formArrayName) as FormArray;
PatternsArray.clear();
const servicesToUse = this.ldnService.notifyServiceInboundPatterns;
const servicesToUse = [...this.ldnService.notifyServiceInboundPatterns];
if (servicesToUse.length === 0) {
servicesToUse.push({ pattern: '', constraint: '', automatic: 'false' });
}
servicesToUse.forEach((patternObj: NotifyServicePattern) => {
const patternFormGroup = this.initializeInboundPatternFormGroup();
const patternLabel = patternObj?.pattern ? 'ldn-service.form.pattern.' + patternObj?.pattern + '.label' : 'ldn-service.form.label.placeholder.default-select';
const newPatternObjWithLabel = Object.assign(new NotifyServicePattern(), {
...patternObj,
patternLabel: this.translateService.instant('ldn-service.form.pattern.' + patternObj?.pattern + '.label'),
patternLabel: this.translateService.instant(patternLabel),
});
patternFormGroup.patchValue(newPatternObjWithLabel);
@@ -412,7 +407,7 @@ export class LdnServiceFormComponent implements OnInit, OnDestroy {
}
/**
* Patches the LDN service by retrieving and sending patch operations geenrated in generatePatchOperations()
* Patches the LDN service by retrieving and sending patch operations generated in generatePatchOperations()
*/
patchService() {
this.deleteMarkedInboundPatterns();
@@ -425,17 +420,6 @@ export class LdnServiceFormComponent implements OnInit, OnDestroy {
return;
}
const notifyServiceInboundPatterns = this.formModel.get('notifyServiceInboundPatterns') as FormArray;
const deletedInboundPatternsLength = this.deletedInboundPatterns.length;
// If no inbound patterns are specified, close the modal and return
// notify the user that no patterns are specified
if (notifyServiceInboundPatterns.length === deletedInboundPatternsLength) {
this.notificationService.warning(this.translateService.get('ldn-service-notification.created.warning.title'));
this.deletedInboundPatterns = [];
this.closeModal();
return;
}
this.ldnServicesService.patch(this.ldnService, patchOperations).pipe(
getFirstCompletedRemoteData(),
).subscribe(
@@ -571,7 +555,7 @@ export class LdnServiceFormComponent implements OnInit, OnDestroy {
private createInboundPatternFormGroup(): FormGroup {
const inBoundFormGroup = {
pattern: '',
patternLabel: this.translateService.instant(this.selectPatternDefaultLabeli18Key),
patternLabel: this.translateService.instant(this.selectPatternDefaultLabelI18Key),
constraint: '',
constraintFormatted: '',
automatic: false,

View File

@@ -10,7 +10,6 @@
[collectionSize]="(ldnServicesRD$ | async)?.payload?.totalElements"
[hideGear]="true"
[hidePagerWhenSinglePage]="true"
[pageInfoState]="(ldnServicesRD$ | async)?.payload"
[paginationOptions]="pageConfig">
<div class="table-responsive">
<table class="table table-striped table-hover">
@@ -83,10 +82,10 @@
<div>
{{ 'service.overview.delete.body' | translate }}
</div>
<div class="mt-4">
<div class="mt-4 text-right">
<button (click)="closeModal()"
[attr.aria-label]="'ldn-service-overview-close-modal' | translate"
class="btn btn-primary mr-2">{{ 'service.detail.delete.cancel' | translate }}</button>
class="btn btn-outline-secondary mr-2">{{ 'service.detail.delete.cancel' | translate }}</button>
<button (click)="deleteSelected(this.selectedServiceId.toString(), ldnServicesService)"
class="btn btn-danger"
[attr.aria-label]="'ldn-service-overview-select-delete' | translate"

View File

@@ -18,13 +18,13 @@ export class Itemfilter extends CacheableObject {
@excludeFromEquals
@autoserialize
type: ResourceType;
type: ResourceType;
@autoserialize
id: string;
id: string;
@deserialize
_links: {
_links: {
self: {
href: string;
};

View File

@@ -5,9 +5,9 @@ import { autoserialize } from 'cerialize';
*/
export class NotifyServicePattern {
@autoserialize
pattern: string;
pattern: string;
@autoserialize
constraint: string;
constraint: string;
@autoserialize
automatic: string;
automatic: string;
}

View File

@@ -29,43 +29,43 @@ export class LdnService extends CacheableObject {
@excludeFromEquals
@autoserialize
type: ResourceType;
type: ResourceType;
@autoserialize
id: number;
id: number;
@deserializeAs('id')
uuid: string;
uuid: string;
@autoserialize
name: string;
name: string;
@autoserialize
description: string;
description: string;
@autoserialize
url: string;
url: string;
@autoserialize
score: number;
score: number;
@autoserialize
enabled: boolean;
enabled: boolean;
@autoserialize
ldnUrl: string;
ldnUrl: string;
@autoserialize
lowerIp: string;
lowerIp: string;
@autoserialize
upperIp: string;
upperIp: string;
@autoserialize
notifyServiceInboundPatterns?: NotifyServicePattern[];
notifyServiceInboundPatterns?: NotifyServicePattern[];
@deserialize
_links: {
_links: {
self: {
href: string;
};

View File

@@ -11,6 +11,8 @@ export const notifyPatterns = [
'request-review',
'announce-relationship',
];

View File

@@ -1,18 +1,15 @@
import {
mapToCanActivate,
Route,
} from '@angular/router';
import { Route } from '@angular/router';
import { i18nBreadcrumbResolver } from '../../core/breadcrumbs/i18n-breadcrumb.resolver';
import { notifyInfoGuard } from '../../core/coar-notify/notify-info/notify-info.guard';
import { SiteAdministratorGuard } from '../../core/data/feature-authorization/feature-authorization-guard/site-administrator.guard';
import { siteAdministratorGuard } from '../../core/data/feature-authorization/feature-authorization-guard/site-administrator.guard';
import { AdminNotifyDashboardComponent } from './admin-notify-dashboard.component';
import { AdminNotifyIncomingComponent } from './admin-notify-logs/admin-notify-incoming/admin-notify-incoming.component';
import { AdminNotifyOutgoingComponent } from './admin-notify-logs/admin-notify-outgoing/admin-notify-outgoing.component';
export const ROUTES: Route[] = [
{
canActivate: [...mapToCanActivate([SiteAdministratorGuard]), notifyInfoGuard],
canActivate: [siteAdministratorGuard, notifyInfoGuard],
path: '',
resolve: {
breadcrumb: i18nBreadcrumbResolver,
@@ -30,7 +27,7 @@ export const ROUTES: Route[] = [
breadcrumb: i18nBreadcrumbResolver,
},
component: AdminNotifyIncomingComponent,
canActivate: [...mapToCanActivate([SiteAdministratorGuard]), notifyInfoGuard],
canActivate: [siteAdministratorGuard, notifyInfoGuard],
data: {
title: 'admin.notify.dashboard.page.title',
breadcrumbKey: 'admin.notify.dashboard',
@@ -42,7 +39,7 @@ export const ROUTES: Route[] = [
breadcrumb: i18nBreadcrumbResolver,
},
component: AdminNotifyOutgoingComponent,
canActivate: [...mapToCanActivate([SiteAdministratorGuard]), notifyInfoGuard],
canActivate: [siteAdministratorGuard, notifyInfoGuard],
data: {
title: 'admin.notify.dashboard.page.title',
breadcrumbKey: 'admin.notify.dashboard',

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