Skip to content

Commit 155fc91

Browse files
Merged in task/dspace-cris-2025_02_x/DSC-2748 (pull request DSpace#4120)
DSC-2748 Approved-by: Fapohunda, Adamo
2 parents f828134 + 4ddefe4 commit 155fc91

File tree

10 files changed

+76
-27
lines changed

10 files changed

+76
-27
lines changed

.github/workflows/build.yml

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,8 @@ name: Build
77
on: [push, pull_request]
88

99
permissions:
10-
contents: read # to fetch code (actions/checkout)
11-
packages: read # to fetch private images from GitHub Container Registry (GHCR)
10+
contents: read # to fetch code (actions/checkout)
11+
packages: read # to fetch private images from GitHub Container Registry (GHCR)
1212

1313
jobs:
1414
tests:
@@ -19,7 +19,7 @@ jobs:
1919
# NOTE: These settings should be kept in sync with those in [src]/docker/docker-compose-ci.yml
2020
DSPACE_REST_HOST: 127.0.0.1
2121
DSPACE_REST_PORT: 8080
22-
DSPACE_REST_NAMESPACE: '/server'
22+
DSPACE_REST_NAMESPACE: "/server"
2323
DSPACE_REST_SSL: false
2424
# Spin up UI on 127.0.0.1 to avoid host resolution issues in e2e tests with Node 20+
2525
DSPACE_UI_HOST: 127.0.0.1
@@ -35,9 +35,9 @@ jobs:
3535
# Comment this out to use the latest release
3636
#CHROME_VERSION: "116.0.5845.187-1"
3737
# Bump Node heap size (OOM in CI after upgrading to Angular 15)
38-
NODE_OPTIONS: '--max-old-space-size=4096'
38+
NODE_OPTIONS: "--max-old-space-size=4096"
3939
# Project name to use when running "docker compose" prior to e2e tests
40-
COMPOSE_PROJECT_NAME: 'ci'
40+
COMPOSE_PROJECT_NAME: "ci"
4141
# Docker Registry to use for Docker compose scripts below.
4242
# We use GitHub's Container Registry to avoid aggressive rate limits at DockerHub.
4343
DOCKER_REGISTRY: ghcr.io
@@ -117,7 +117,7 @@ jobs:
117117
if: matrix.node-version == '20.x'
118118
with:
119119
name: coverage-report-${{ matrix.node-version }}
120-
path: 'coverage/dspace-angular/lcov.info'
120+
path: "coverage/dspace-angular/lcov.info"
121121
retention-days: 14
122122

123123
# Login to our Docker registry, so that we can access private Docker images using "docker compose" below.
@@ -142,6 +142,7 @@ jobs:
142142
- name: Run e2e tests (integration tests)
143143
uses: cypress-io/github-action@v6
144144
with:
145+
install-command: npm ci
145146
# Run tests in Chrome, headless mode (default)
146147
browser: chrome
147148
# Start app before running tests (will be stopped automatically after tests finish)
@@ -234,9 +235,9 @@ jobs:
234235
# the name of the project. If it does, then SSR is working.
235236
- name: Verify SSR on a Project page
236237
run: |
237-
result=$(wget -O- -q http://127.0.0.1:4000/entities/project/1e3451e4-60d7-46a8-962e-5b94b62c63ff)
238+
result=$(wget -O- -q http://127.0.0.1:4000/entities/project/28f8f49a-1aaf-4acc-93a9-203f3cf7ba62)
238239
echo "$result"
239-
echo "$result" | grep -oE "<meta name=\"title\" [^>]*>" | grep "Test DSC-1819"
240+
echo "$result" | grep -oE "<meta name=\"title\" [^>]*>" | grep "TEST PROJECT"
240241
241242
# Get a specific orgunit in our test data and verify that the <meta name="title"> tag includes
242243
# the name of the orgunit. If it does, then SSR is working.
@@ -262,7 +263,6 @@ jobs:
262263
echo "$result"
263264
echo "$result" | grep -oE "<meta name=\"title\" [^>]*>" | grep "test funding"
264265
265-
266266
# Verify 301 Handle redirect behavior
267267
# Note: /handle/123456789/260 is the same test Publication used by our e2e tests
268268
- name: Verify 301 redirect from '/handle' URLs

cypress/e2e/my-dspace.cy.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -119,7 +119,7 @@ describe('My DSpace page', () => {
119119
// Open the New Import dropdown
120120
cy.get('button[data-test="import-dropdown"]').click();
121121
// Click on the "Item" type in that dropdown
122-
cy.get('#importControlsDropdownMenu button[title="Equipment"]').click();
122+
cy.get('#importControlsDropdownMenu button[title="Funding"]').click();
123123

124124
// New URL should include /import-external, as we've moved to the import page
125125
cy.url().should('include', '/import-external');

cypress/support/e2e.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,12 @@ import 'cypress-axe';
2121

2222
import { DSPACE_XSRF_COOKIE } from 'src/app/core/xsrf/xsrf.constants';
2323

24+
Cypress.Commands.overwrite('visit', (originalFn, url, options) => {
25+
return originalFn(url, options).then(() => {
26+
cy.get('[data-test="ds-hydrated"]');
27+
});
28+
});
29+
2430
// We might receive uncaught exceptions from external libraries (e.g. it happened before with a broken
2531
// version of the addToAny plugin). These should not cause our tests to fail, so we catch them here.
2632
Cypress.on('uncaught:exception', (err, runnable) => {

docker/db.entities.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
# # Therefore, it should be kept in sync with that file
1515
services:
1616
dspacedb:
17-
image: "${DOCKER_REGISTRY:-docker.io}/${DOCKER_OWNER:-4science}/dspace-cris-postgres-pgcrypto:${DSPACE_VER:-dspace-cris-2025_02_x}-loadsql"
17+
image: "${DOCKER_REGISTRY:-docker.io}/${DOCKER_OWNER:-4science}/dspace-cris-postgres-loadsql:${DSPACE_VER:-dspace-cris-2025_02_x}"
1818
environment:
1919
# This LOADSQL should be kept in sync with the URL in 4Science/DSpace
2020
# This SQL is available from https://github.com/4Science/DSpace-CRIS-Files/releases/download/cris-2025.02.00/db-entities.sql

src/app/my-dspace-page/my-dspace-new-submission/my-dspace-new-external-dropdown/my-dspace-new-external-dropdown.component.html

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
@if ((moreThanOne$ | async) !== true) {
1+
@let moreThanOne = moreThanOne$ | async;
2+
@if (moreThanOne !== true) {
23
<div class="add">
34
<button class="btn btn-lg btn-outline-primary mt-1 ms-2"
45
[attr.aria-label]="'mydspace.new-submission-external' | translate" [dsBtnDisabled]="(initialized$ | async) !== true"
@@ -8,7 +9,7 @@
89
</button>
910
</div>
1011
}
11-
@if ((moreThanOne$ | async)) {
12+
@if (moreThanOne === true) {
1213
<div class="add w-100" display="dynamic" placement="bottom-right"
1314
ngbDropdown
1415
>
@@ -24,7 +25,7 @@
2425
class="dropdown-menu p-0"
2526
id="importControlsDropdownMenu"
2627
aria-labelledby="dropdownImport">
27-
<ds-entity-dropdown [isSubmission]="false" (selectionChange)="openPage($event)"></ds-entity-dropdown>
28+
<ds-entity-dropdown [isSubmission]="false" [isImportFromExternalSource]="true" (selectionChange)="openPage($event)"></ds-entity-dropdown>
2829
</div>
2930
</div>
3031
}

src/app/root/root.component.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,11 @@
11
import {
22
AsyncPipe,
3+
isPlatformBrowser,
34
NgClass,
45
} from '@angular/common';
56
import {
67
Component,
8+
HostBinding,
79
Inject,
810
Input,
911
OnInit,
@@ -70,6 +72,8 @@ import { SystemWideAlertBannerComponent } from '../system-wide-alert/alert-banne
7072
],
7173
})
7274
export class RootComponent implements OnInit {
75+
@HostBinding('attr.data-test') dataTestAttribute: string | null = null;
76+
7377
theme: Observable<ThemeConfig> = of({} as any);
7478
isSidebarVisible$: Observable<boolean>;
7579
slideSidebarOver$: Observable<boolean>;
@@ -99,6 +103,7 @@ export class RootComponent implements OnInit {
99103
@Inject(NativeWindowService) private _window: NativeWindowRef,
100104
) {
101105
this.notificationOptions = environment.notifications;
106+
this.dataTestAttribute = isPlatformBrowser(platformId) ? 'ds-hydrated' : null;
102107
}
103108

104109
ngOnInit() {

src/app/shared/entity-dropdown/entity-dropdown.component.spec.ts

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -172,6 +172,24 @@ describe('EntityDropdownComponent', () => {
172172
expect((component as any).entityTypeService.getAllAuthorizedRelationshipType).toHaveBeenCalled();
173173
});
174174

175+
it('should init component with entities list when isImportFromExternalSource is true', () => {
176+
component.isSubmission = false;
177+
component.isImportFromExternalSource = true;
178+
spyOn(component.subs, 'push');
179+
spyOn(component, 'resetPagination');
180+
spyOn(component, 'populateEntityList').and.callThrough();
181+
182+
scheduler.schedule(() => fixture.detectChanges());
183+
scheduler.flush();
184+
const elements = fixture.debugElement.queryAll(By.css('.entity-item'));
185+
186+
expect(elements.length).toEqual(5);
187+
expect(component.subs.push).toHaveBeenCalled();
188+
expect(component.resetPagination).toHaveBeenCalled();
189+
expect(component.populateEntityList).toHaveBeenCalled();
190+
expect((component as any).entityTypeService.getAllAuthorizedRelationshipTypeImport).toHaveBeenCalled();
191+
});
192+
175193
it('should trigger onSelect method when select a new entity from list', () => {
176194
scheduler.schedule(() => fixture.detectChanges());
177195
scheduler.flush();

src/app/shared/entity-dropdown/entity-dropdown.component.ts

Lines changed: 23 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,12 @@ export class EntityDropdownComponent implements OnInit, OnDestroy {
9191
*/
9292
@Input() isSubmission: boolean;
9393

94+
/**
95+
* TRUE if the main operation is "Import metadata from an external source", FALSE otherwise.
96+
* Used to determine which list type to populate.
97+
*/
98+
@Input() isImportFromExternalSource: boolean;
99+
94100
/**
95101
* The entity to output to the parent component
96102
*/
@@ -193,23 +199,26 @@ export class EntityDropdownComponent implements OnInit, OnDestroy {
193199
*/
194200
public populateEntityList(page: number) {
195201
this.isLoadingList.next(true);
196-
let searchListEntity$;
197-
if (this.isSubmission) {
202+
let searchListEntity$: Observable<RemoteData<PaginatedList<ItemType>>>;
203+
if (this.isSubmission || this.isImportFromExternalSource) {
198204
// Set the pagination info
199205
const findOptions: FindListOptions = {
200206
elementsPerPage: 10,
201207
currentPage: page,
202208
};
203-
searchListEntity$ =
204-
this.entityTypeService.getAllAuthorizedRelationshipType(findOptions)
205-
.pipe(
206-
getFirstSucceededRemoteWithNotEmptyData(),
207-
tap(entityType => {
208-
if ((this.searchListEntity.length + findOptions.elementsPerPage) >= entityType.payload.totalElements) {
209-
this.hasNextPage = false;
210-
}
211-
}),
212-
);
209+
210+
searchListEntity$ = this.isSubmission ?
211+
this.entityTypeService.getAllAuthorizedRelationshipType(findOptions) :
212+
this.entityTypeService.getAllAuthorizedRelationshipTypeImport(findOptions);
213+
214+
searchListEntity$ = searchListEntity$.pipe(
215+
getFirstSucceededRemoteWithNotEmptyData(),
216+
tap(entityType => {
217+
if ((this.searchListEntity.length + findOptions.elementsPerPage) >= entityType.payload.totalElements) {
218+
this.hasNextPage = false;
219+
}
220+
}),
221+
);
213222
} else {
214223
searchListEntity$ =
215224
this.itemExportFormatService.byEntityTypeAndMolteplicity(null, ItemExportFormatMolteplicity.MULTIPLE)
@@ -227,6 +236,7 @@ export class EntityDropdownComponent implements OnInit, OnDestroy {
227236
tap(() => this.hasNextPage = false),
228237
);
229238
}
239+
230240
this.searchListEntity$ = searchListEntity$.pipe(
231241
switchMap((entityType: RemoteData<PaginatedList<ItemType>>) => entityType.payload.page),
232242
map((item: ItemType) => {
@@ -239,6 +249,7 @@ export class EntityDropdownComponent implements OnInit, OnDestroy {
239249
reduce((acc: any, value: any) => [...acc, value], []),
240250
startWith([]),
241251
);
252+
242253
this.subs.push(
243254
this.searchListEntity$.subscribe({
244255
next: (result: ItemType[]) => {

src/assets/i18n/en.json5

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5501,6 +5501,8 @@
55015501

55025502
"suggestion.type.orcidWorks": "Publication",
55035503

5504+
"suggestion.type.openalex": "OpenAlex",
5505+
55045506
"register-email.title": "New user registration",
55055507

55065508
"register-page.create-profile.header": "Create Profile",
@@ -9306,6 +9308,8 @@
93069308

93079309
"item.preview.organization.alternateName": "Alternative name",
93089310

9311+
"item.preview.dc.identifier.openalex": "OpenAlex ID",
9312+
93099313
"third-party-metrics-cookies.message": "{{ metricType }} badge is blocked by your ",
93109314

93119315
"third-party-metrics-cookies.consent-settings": "consent settings",

src/assets/i18n/it.json5

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8768,6 +8768,9 @@
87688768
// TODO New key - Add a translation
87698769
"suggestion.type.orcidWorks": "Publication",
87708770

8771+
// "suggestion.type.openalex" : "OpenAlex"
8772+
"suggestion.type.openalex": "OpenAlex",
8773+
87718774
// "register-email.title": "New user registration",
87728775
"register-email.title": "Registrazione nuovo utente",
87738776

@@ -15183,7 +15186,8 @@
1518315186
// TODO New key - Add a translation
1518415187
"item.preview.organization.alternateName": "Alternative name",
1518515188

15186-
15189+
// "item.preview.dc.identifier.openalex" : "OpenAlex ID"
15190+
"item.preview.dc.identifier.openalex": "OpenAlex ID",
1518715191

1518815192

1518915193

0 commit comments

Comments
 (0)