Skip to content

Commit ab64890

Browse files
atarix83danieleninfo
authored andcommitted
Merged in task/prod/uon--repo/CST-24396 (pull request DSpace#4101)
Task/prod/uon repo/CST-24396 Approved-by: Daniele Ninfo
2 parents 4dcce4c + 67e6850 commit ab64890

File tree

111 files changed

+2354
-326
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

111 files changed

+2354
-326
lines changed

bitbucket-pipelines.yml

Lines changed: 47 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,7 @@ definitions:
8787
- yarn build:lint
8888
- npm run ng-high-memory -- lint --quiet
8989
- yarn run check-circ-deps
90-
- yarn run test:headless
90+
- yarn run test:headless:ci
9191
artifacts:
9292
- .next/**
9393
- .cache/**
@@ -105,6 +105,7 @@ definitions:
105105
- node-2024-02-x
106106
- cypress-2024-02-x
107107
script:
108+
- apt-get update && apt-get install -y curl
108109
- export HASH_COMMIT=${BITBUCKET_COMMIT:0:8}
109110
- echo "Running tests for commit $HASH_COMMIT"
110111
- export DSPACE_REST_HOST=${E2E_RUNNER_HOST}
@@ -120,6 +121,27 @@ definitions:
120121
- export CYPRESS_CACHE_FOLDER=~/.cache/Cypress
121122
- export CHROME_FLAGS="--no-sandbox --disable-dev-shm-usage --disable-gpu"
122123
- export NODE_OPTIONS="--max-old-space-size=4096"
124+
- |
125+
MAX_RETRIES=10
126+
RETRY_COUNT=0
127+
SUCCESS=false
128+
while [ $RETRY_COUNT -lt $MAX_RETRIES ]; do
129+
echo "Pinging REST endpoint... (Attempt $((RETRY_COUNT+1)))"
130+
STATUS_CODE=$(curl -s -o /dev/null -w "%{http_code}" "https://$DSPACE_REST_HOST$DSPACE_REST_NAMESPACE")
131+
if [ "$STATUS_CODE" -lt 400 ]; then
132+
echo "REST endpoint is up! Status code: $STATUS_CODE"
133+
SUCCESS=true
134+
break
135+
else
136+
echo "REST endpoint not ready (Status code: $STATUS_CODE). Retrying in 60 seconds..."
137+
RETRY_COUNT=$((RETRY_COUNT+1))
138+
sleep 60
139+
fi
140+
done
141+
if [ "$SUCCESS" = "false" ]; then
142+
echo "REST endpoint did not become available after $MAX_RETRIES attempts. Failing the build."
143+
exit 1
144+
fi
123145
- npx cypress install
124146
- yarn serve:ssr &
125147
- echo "Waiting for server to start..."
@@ -277,6 +299,18 @@ definitions:
277299
- export CLOUDFRONT_DISTRIBUTION_ID=$(aws cloudfront list-distributions --query "DistributionList.Items[?Comment=='test--${CLOUDFRONT_NAME}'].Id" --output text)
278300
- aws cloudfront create-invalidation --distribution-id $CLOUDFRONT_DISTRIBUTION_ID --paths "/*" || echo "CloudFront distribution $CLOUDFRONT_DISTRIBUTION_ID not found — skipping invalidation."
279301

302+
- step: &check-branch-name-allowed
303+
name: Check allowed branch name
304+
image: alpine:latest
305+
script:
306+
- |
307+
if [[ "$BITBUCKET_BRANCH" = "ux-plus-cris" ]] || [[ "$BITBUCKET_BRANCH" == ux-plus-cris-20*_02_x ]] || [[ "$BITBUCKET_BRANCH" == prod/* ]] || [[ "$BITBUCKET_BRANCH" == test/* ]]; then
308+
echo "Branch $BITBUCKET_BRANCH is allowed."
309+
else
310+
echo "This pipeline can only run on ux-plus-cris, ux-plus-cris-20*_02_x, prod/**, or test/**"
311+
exit 1
312+
fi
313+
280314
pipelines:
281315
custom:
282316
e2e-on-custom-backend:
@@ -290,23 +324,25 @@ pipelines:
290324
- step: *build-and-push
291325
- step: *deploy-on-dev
292326
- step: *find-and-invalidate-cloudfront-dev
327+
deploy-on-staging:
328+
- step: *check-branch-name-allowed
329+
- step: *angular-build
330+
- step: *build-and-push
331+
- step: *deploy-on-staging
332+
- step: *find-and-invalidate-cloudfront-staging
293333
turn-on-dev:
294334
- step: *turn-on-dev
295335
turn-on-staging:
296336
- step: *turn-on-staging
297337
turn-on-test:
298338
- step: *turn-on-test
299339
branches:
300-
'ux-plus-data-quality-cris-2024_02_x':
340+
"ux-plus-data-quality-cris-2024_02_x":
301341
- step: *preliminary-operation
302342
- step: *angular-build
303343
- parallel: *parallel-run-tests
304-
- step: *build-and-push
305-
- step: *deploy-on-dev
306-
- step: *find-and-invalidate-cloudfront-dev
307-
- step: *deploy-on-staging
308-
- step: *find-and-invalidate-cloudfront-staging
309-
'prod/**':
344+
"prod/**":
345+
- step: *check-branch-name-allowed
310346
- step: *preliminary-operation
311347
- step: *angular-build
312348
- parallel: *parallel-run-tests
@@ -315,7 +351,8 @@ pipelines:
315351
- step: *find-and-invalidate-cloudfront-dev
316352
- step: *deploy-on-staging
317353
- step: *find-and-invalidate-cloudfront-staging
318-
'test/**':
354+
"test/**":
355+
- step: *check-branch-name-allowed
319356
- step: *preliminary-operation
320357
- step: *angular-build
321358
- parallel: *parallel-run-tests
@@ -324,7 +361,7 @@ pipelines:
324361
- step: *find-and-invalidate-cloudfront-test
325362

326363
pull-requests:
327-
'**':
364+
"**":
328365
- step: *preliminary-operation
329366
- step: *angular-build
330367
- parallel: *parallel-run-tests

package.json

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "dspace-angular",
3-
"version": "2024.02.03",
3+
"version": "2024.02.04",
44
"scripts": {
55
"ng": "ng",
66
"config:watch": "nodemon",
@@ -25,6 +25,7 @@
2525
"test": "ng test --source-map=true --watch=false --configuration test",
2626
"test:watch": "nodemon --exec \"ng test --source-map=true --watch=true --configuration test\"",
2727
"test:headless": "ng test --source-map=true --watch=false --configuration test --browsers=ChromeHeadless --code-coverage",
28+
"test:headless:ci": "ng test --source-map=false --watch=false --configuration test --browsers=ChromeHeadless --code-coverage",
2829
"test:lint": "yarn build:lint && yarn test:lint:nobuild",
2930
"test:lint:nobuild": "jasmine --config=lint/jasmine.json",
3031
"lint": "yarn build:lint && yarn lint:nobuild",
@@ -91,8 +92,8 @@
9192
"@angular/platform-server": "^17.3.11",
9293
"@angular/router": "^17.3.11",
9394
"@angular/ssr": "^17.3.17",
94-
"@babel/runtime": "7.27.6",
9595
"@asymmetrik/ngx-leaflet": "^17.0.0",
96+
"@babel/runtime": "7.27.6",
9697
"@datadog/browser-rum": "^5.7.0",
9798
"@kolkov/ngx-gallery": "^2.0.1",
9899
"@ng-bootstrap/ng-bootstrap": "^11.0.0",
@@ -150,14 +151,16 @@
150151
"ng2-pdfjs-viewer": "^15.0.0",
151152
"ngx-infinite-scroll": "^17.0.0",
152153
"ngx-pagination": "6.0.3",
153-
"ngx-skeleton-loader": "^9.0.0",
154154
"ngx-quill": "25.3.3",
155+
"ngx-skeleton-loader": "^9.0.0",
155156
"nouislider": "^15.8.1",
156157
"pem": "1.14.8",
157158
"prop-types": "^15.8.1",
158159
"quill": "2.0.3",
159160
"quill-emoji": "^0.2.0",
161+
"react": "^17.0.0",
160162
"react-copy-to-clipboard": "^5.1.0",
163+
"react-dom": "^17.0.0",
161164
"redux-saga": "^1.3.0",
162165
"reflect-metadata": "^0.2.2",
163166
"rxjs": "^7.8.2",
@@ -194,9 +197,9 @@
194197
"@types/file-saver": "^2.0.1",
195198
"@types/googlemaps": "^3.43.3",
196199
"@types/grecaptcha": "^3.0.9",
197-
"@types/leaflet": "^1.9.12",
198200
"@types/jasmine": "~3.6.0",
199201
"@types/js-cookie": "2.2.6",
202+
"@types/leaflet": "^1.9.12",
200203
"@types/lodash": "^4.17.17",
201204
"@types/node": "^14.14.9",
202205
"@types/sanitize-html": "^2.13.0",
@@ -249,9 +252,9 @@
249252
"postcss-loader": "^4.0.3",
250253
"postcss-preset-env": "^7.4.2",
251254
"prop-types": "^15.8.1",
252-
"react": "^16.14.0",
255+
"react": "^17.0.0",
253256
"react-copy-to-clipboard": "^5.1.0",
254-
"react-dom": "^16.14.0",
257+
"react-dom": "^17.0.0",
255258
"rimraf": "^3.0.2",
256259
"sass": "~1.89.2",
257260
"sass-loader": "^12.6.0",

server.ts

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -255,6 +255,11 @@ export function app() {
255255
*/
256256
server.get('/app/client/health', clientHealthCheck);
257257

258+
/**
259+
* Redirecting old manifest
260+
*/
261+
server.get('/json/iiif/**/manifest', redirectManifest);
262+
258263
/**
259264
* Default sending all incoming requests to ngApp() function, after first checking for a cached
260265
* copy of the page (see cacheCheck())
@@ -721,6 +726,39 @@ function healthCheck(req, res) {
721726
});
722727
}
723728

729+
/*
730+
* The callback function to redirect old manifest
731+
*/
732+
function redirectManifest(req, res) {
733+
console.info('Redirecting old manifest');
734+
const url = req.url;
735+
const regex = /json\/iiif\/([^\/]+\/[^\/]+)(?:\/([^\/]+))?\/manifest/;
736+
const match = url.match(regex);
737+
let handle;
738+
let id;
739+
740+
if (match) {
741+
handle = match[1];
742+
const baseUrl = `${environment.rest.baseUrl}/api/pid/find?id=${handle}`;
743+
axios.get(baseUrl)
744+
.then((response) => {
745+
if (response.status === 200) {
746+
const newUrl = `${environment.rest.baseUrl}/iiif/${response.data.id}/manifest`;
747+
console.info('Manifest found, redirect to ', newUrl);
748+
res.redirect(newUrl);
749+
}
750+
})
751+
.catch((error) => {
752+
res.status(error.response.status).send({
753+
error: error.message
754+
});
755+
});
756+
} else {
757+
res.status(422).send({
758+
error: 'Wrong handle'
759+
});
760+
}
761+
}
724762

725763
// Webpack will replace 'require' with '__webpack_require__'
726764
// '__non_webpack_require__' is a proxy to Node 'require'

src/app/access-control/epeople-registry/eperson-form/eperson-form.component.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -307,7 +307,7 @@ export class EPersonFormComponent implements OnInit, OnDestroy {
307307
name: 'email',
308308
validators: {
309309
required: null,
310-
pattern: '^[a-z0-9._%+-]+@[a-z0-9.-]+\\.[a-z]{2,4}$',
310+
pattern: '^\\s*[a-z0-9._%+-]+@[a-z0-9.-]+\\.[a-z]{2,4}\\s*$',
311311
},
312312
required: true,
313313
errorMessages: {
@@ -426,7 +426,7 @@ export class EPersonFormComponent implements OnInit, OnDestroy {
426426
},
427427
],
428428
},
429-
email: this.email.value,
429+
email: (this.email.value as string)?.trim(),
430430
canLogIn: this.canLogIn.value,
431431
requireCertificate: this.requireCertificate.value,
432432
};

src/app/app-routes.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -194,12 +194,12 @@ export const APP_ROUTES: Route[] = [
194194
canActivate: [authenticatedGuard, endUserAgreementCurrentUserGuard],
195195
},
196196
{
197-
path: 'standard-login',
197+
path: 'admin-only-login',
198198
loadChildren: () => import('./login-page/login-page-routes').then((m) => m.ROUTES),
199199
data: {
200200
isBackDoor: true,
201201
},
202-
canMatch: [() => !environment.auth.disableStandardLogin],
202+
canMatch: [() => environment.auth.isPasswordLoginEnabledForAdminsOnly],
203203
},
204204
{
205205
path: 'login',
@@ -342,7 +342,7 @@ export const APP_ROUTES: Route[] = [
342342
.then((m) => m.ROUTES),
343343
},
344344
{
345-
path: 'luck-search',
345+
path: 'lucky-search',
346346
loadChildren: () => import('./lucky-search/lucky-search-routes')
347347
.then((m) => m.ROUTES),
348348
},

src/app/app.config.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,7 @@ import { AuthInterceptor } from './core/auth/auth.interceptor';
5757
import { DspaceRestInterceptor } from './core/dspace-rest/dspace-rest.interceptor';
5858
import { LocaleInterceptor } from './core/locale/locale.interceptor';
5959
import { LogInterceptor } from './core/log/log.interceptor';
60+
import { schemaModels } from './core/metadata/schema-json-ld/schema-types/provide-schema';
6061
import {
6162
models,
6263
provideCore,
@@ -169,3 +170,4 @@ const metadataRepresentations = METADATA_REPRESENTATION_COMPONENT_DECORATOR_MAP;
169170
const startsWithDecoratorMap = STARTS_WITH_DECORATOR_MAP;
170171
const browseByDecoratorMap = BROWSE_BY_DECORATOR_MAP;
171172
const authMethodForDecoratorMap = AUTH_METHOD_FOR_DECORATOR_MAP;
173+
const schemaModelList = schemaModels;

src/app/breadcrumbs/breadcrumbs.component.html

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,6 @@
1414
</ng-template>
1515

1616
<ng-template #activeBreadcrumb let-text="text">
17-
<li class="breadcrumb-item active" aria-current="page"><div class="breadcrumb-item-limiter"><span class="text-truncate" [innerHTML]="text | translate"></span></div></li>
17+
<li class="breadcrumb-item active" aria-current="page"><div class="breadcrumb-item-limiter"><span class="text-truncate" [innerHTML]="text | translate | dsEscapeHtml"></span></div></li>
1818
</ng-template>
1919
</ng-container>
20-

src/app/breadcrumbs/breadcrumbs.component.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import { NgbTooltipModule } from '@ng-bootstrap/ng-bootstrap';
1010
import { TranslateModule } from '@ngx-translate/core';
1111
import { Observable } from 'rxjs';
1212

13+
import { EscapeHtmlPipe } from '../shared/utils/escape-html.pipe';
1314
import { VarDirective } from '../shared/utils/var.directive';
1415
import { Breadcrumb } from './breadcrumb/breadcrumb.model';
1516
import { BreadcrumbsService } from './breadcrumbs.service';
@@ -22,7 +23,7 @@ import { BreadcrumbsService } from './breadcrumbs.service';
2223
templateUrl: './breadcrumbs.component.html',
2324
styleUrls: ['./breadcrumbs.component.scss'],
2425
standalone: true,
25-
imports: [VarDirective, NgIf, NgTemplateOutlet, NgFor, RouterLink, NgbTooltipModule, AsyncPipe, TranslateModule],
26+
imports: [VarDirective, NgIf, NgTemplateOutlet, NgFor, RouterLink, NgbTooltipModule, AsyncPipe, TranslateModule, EscapeHtmlPipe],
2627
})
2728
export class BreadcrumbsComponent {
2829

src/app/collection-page/collection-page.component.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
<div *ngIf="collectionRD?.hasSucceeded" @fadeInOut>
55
<div *ngIf="collectionRD?.payload as collection">
66
<div class="d-flex flex-row border-bottom mb-4 pb-4">
7-
<header class="comcol-header mr-auto">
7+
<header class="comcol-header w-100">
88
<!-- Collection Name -->
99
<ds-comcol-page-header
1010
[name]="dsoNameService.getName(collection)">

src/app/community-page/community-page.component.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
<div class="community-page" *ngIf="communityRD?.hasSucceeded" @fadeInOut>
33
<div *ngIf="communityRD?.payload; let communityPayload">
44
<div class="d-flex flex-row border-bottom mb-4 pb-4">
5-
<header class="comcol-header mr-auto">
5+
<header class="comcol-header w-100">
66
<!-- Community name -->
77
<ds-comcol-page-header [name]="dsoNameService.getName(communityPayload)"></ds-comcol-page-header>
88
<!-- Community logo -->

0 commit comments

Comments
 (0)