Skip to content

Commit 545a29e

Browse files
committed
Merge branch 'ux-plus-cris-2024_02_x' into main-glam
2 parents 6ba0735 + f18bb4a commit 545a29e

File tree

19 files changed

+357
-92
lines changed

19 files changed

+357
-92
lines changed

bitbucket-pipelines.yml

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,9 @@ options:
22
runs-on: self.hosted
33

44
definitions:
5+
caches:
6+
node-cris8: ./node_modules
7+
58
steps:
69
- step: &unittest-code-checks
710
name: test-code-checks
@@ -10,7 +13,7 @@ definitions:
1013
run-as-user: 1000
1114
size: 4x
1215
caches:
13-
- node
16+
- node-cris8
1417
script:
1518
- yarn install --frozen-lockfile
1619
- yarn run lint --quiet

config/config.example.yml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -135,6 +135,8 @@ auth:
135135
# If the rest token expires in less than this amount of time, it will be refreshed automatically.
136136
# This is independent from the idle warning.
137137
timeLeftBeforeTokenRefresh: 120000 # 2 minutes
138+
# Standard login enabled
139+
disableStandardLogin: false
138140

139141
# Form settings
140142
form:

src/app/app-routes.ts

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import {
44
RouterConfigOptions,
55
} from '@angular/router';
66

7+
import { environment } from '../environments/environment';
78
import { NOTIFICATIONS_MODULE_PATH } from './admin/admin-routing-paths';
89
import {
910
ACCESS_CONTROL_MODULE_PATH,
@@ -172,10 +173,21 @@ export const APP_ROUTES: Route[] = [
172173
providers: [provideSuggestionNotificationsState()],
173174
canActivate: [authenticatedGuard, endUserAgreementCurrentUserGuard],
174175
},
176+
{
177+
path: 'standard-login',
178+
loadChildren: () => import('./login-page/login-page-routes').then((m) => m.ROUTES),
179+
data: {
180+
isBackDoor: true,
181+
},
182+
canMatch: [() => environment.auth.disableStandardLogin],
183+
},
175184
{
176185
path: 'login',
177-
loadChildren: () => import('./login-page/login-page-routes')
178-
.then((m) => m.ROUTES),
186+
loadChildren: () => import('./login-page/login-page-routes').then((m) => m.ROUTES),
187+
data: {
188+
isBackDoor: false,
189+
},
190+
canMatch: [() => !environment.auth.disableStandardLogin],
179191
},
180192
{
181193
path: 'logout',

src/app/core/shared/image.utils.ts

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
import {
2+
Observable,
3+
of,
4+
} from 'rxjs';
5+
import { map } from 'rxjs/operators';
6+
7+
export const getDefaultImageUrlByEntityType = (entityType: string): Observable<string> => {
8+
const fallbackImage = 'assets/images/file-placeholder.svg';
9+
10+
if (!entityType) {
11+
return of(fallbackImage);
12+
}
13+
14+
const defaultImage = `assets/images/${entityType.toLowerCase()}-placeholder.svg`;
15+
return checkImageExists(defaultImage).pipe(map((exists) => exists ? defaultImage : fallbackImage));
16+
};
17+
18+
const checkImageExists = (url: string): Observable<boolean> => {
19+
return new Observable<boolean>((observer) => {
20+
const img = new Image();
21+
22+
img.onload = () => {
23+
observer.next(true);
24+
observer.complete();
25+
};
26+
27+
img.onerror = () => {
28+
observer.next(false);
29+
observer.complete();
30+
};
31+
32+
img.src = url;
33+
});
34+
};

src/app/core/submission/vocabularies/models/vocabulary.model.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,14 @@ export class Vocabulary implements CacheableObject {
7474
@autoserialize
7575
externalSource: VocabularyExternalSourceMap;
7676

77+
78+
/**
79+
* A boolean variable that indicates whether the functionality of
80+
* multiple value generation is enabled within a generator context.
81+
*/
82+
@autoserialize
83+
multiValueOnGenerator: boolean;
84+
7785
/**
7886
* A string representing the kind of Vocabulary model
7987
*/
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
11
<ds-thumbnail *ngIf="(initialized | async)" data-test="thumbnail"
22
[thumbnail]="thumbnail$ | async"
3-
[defaultImage]="default">
3+
[defaultImage]="default$ | async">
44
</ds-thumbnail>

src/app/cris-layout/cris-layout-matrix/cris-layout-box-container/boxes/metadata/rendering-types/thumbnail/thumbnail.component.spec.ts

Lines changed: 30 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -173,10 +173,12 @@ describe('', () => {
173173
expect(thumbnail).toBeTruthy();
174174
}));
175175

176-
it('should show default thumbnail', () => {
177-
expect(component.default).toBe('assets/images/file-placeholder.svg');
176+
it('should show default thumbnail', (done) => {
177+
component.default$.subscribe(image => {
178+
expect(image).toBe('assets/images/file-placeholder.svg');
179+
done();
180+
});
178181
});
179-
180182
});
181183

182184
describe('When bitstreams are only original', () => {
@@ -193,10 +195,12 @@ describe('', () => {
193195
expect(thumbnail).toBeTruthy();
194196
}));
195197

196-
it('should show default thumbnail', () => {
197-
expect(component.default).toBe('assets/images/file-placeholder.svg');
198+
it('should show default thumbnail', (done) => {
199+
component.default$.subscribe(image => {
200+
expect(image).toBe('assets/images/file-placeholder.svg');
201+
done();
202+
});
198203
});
199-
200204
});
201205

202206
describe('When bitstreams are only thumbnail', () => {
@@ -267,10 +271,12 @@ describe('', () => {
267271
expect(thumbnail).toBeTruthy();
268272
});
269273

270-
it('should show default thumbnail', () => {
271-
expect(component.default).toBe('assets/images/file-placeholder.svg');
274+
it('should show default thumbnail', (done) => {
275+
component.default$.subscribe(image => {
276+
expect(image).toBe('assets/images/file-placeholder.svg');
277+
done();
278+
});
272279
});
273-
274280
});
275281

276282
describe('When bitstreams are only original without the right metadata information', () => {
@@ -282,8 +288,11 @@ describe('', () => {
282288
fixture.detectChanges();
283289
});
284290

285-
it('should not show bitstream content image src but the default image', () => {
286-
expect(component.default).toBe('assets/images/file-placeholder.svg');
291+
it('should not show bitstream content image src but the default image', (done) => {
292+
component.default$.subscribe(image => {
293+
expect(image).toBe('assets/images/file-placeholder.svg');
294+
done();
295+
});
287296
});
288297

289298
});
@@ -297,10 +306,12 @@ describe('', () => {
297306
fixture.detectChanges();
298307
});
299308

300-
it('should not show thumbnail content image src but the default image', () => {
301-
expect(component.default).toBe('assets/images/file-placeholder.svg');
309+
it('should not show thumbnail content image src but the default image', (done) => {
310+
component.default$.subscribe(image => {
311+
expect(image).toBe('assets/images/file-placeholder.svg');
312+
done();
313+
});
302314
});
303-
304315
});
305316

306317
describe('When bitstreams are only original with the right metadata information', () => {
@@ -312,8 +323,11 @@ describe('', () => {
312323
fixture.detectChanges();
313324
});
314325

315-
it('should not show thumbnail content image src but the default image', () => {
316-
expect(component.default).toBe('assets/images/file-placeholder.svg');
326+
it('should not show thumbnail content image src but the default image', (done) => {
327+
component.default$.subscribe(image => {
328+
expect(image).toBe('assets/images/file-placeholder.svg');
329+
done();
330+
});
317331
});
318332

319333
});

src/app/cris-layout/cris-layout-matrix/cris-layout-box-container/boxes/metadata/rendering-types/thumbnail/thumbnail.component.ts

Lines changed: 12 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@ import {
1010
import { TranslateService } from '@ngx-translate/core';
1111
import {
1212
BehaviorSubject,
13+
combineLatest,
14+
Observable,
1315
of as observableOf,
1416
} from 'rxjs';
1517
import {
@@ -21,10 +23,10 @@ import { BitstreamDataService } from '../../../../../../../core/data/bitstream-d
2123
import { PaginatedList } from '../../../../../../../core/data/paginated-list.model';
2224
import { LayoutField } from '../../../../../../../core/layout/models/box.model';
2325
import { Bitstream } from '../../../../../../../core/shared/bitstream.model';
26+
import { getDefaultImageUrlByEntityType } from '../../../../../../../core/shared/image.utils';
2427
import { Item } from '../../../../../../../core/shared/item.model';
2528
import { getFirstCompletedRemoteData } from '../../../../../../../core/shared/operators';
2629
import {
27-
hasValue,
2830
isEmpty,
2931
isNotEmpty,
3032
} from '../../../../../../../shared/empty.util';
@@ -56,7 +58,7 @@ export class ThumbnailRenderingComponent extends BitstreamRenderingModelComponen
5658
/**
5759
* Default image to be shown in the thumbnail
5860
*/
59-
default: string;
61+
default$: Observable<string>;
6062

6163
/**
6264
* Item rendering initialization state
@@ -83,9 +85,14 @@ export class ThumbnailRenderingComponent extends BitstreamRenderingModelComponen
8385
* Get the thumbnail information from api for this item
8486
*/
8587
ngOnInit(): void {
86-
this.setDefaultImage();
87-
this.getBitstreamsByItem().pipe(
88-
map((bitstreamList: PaginatedList<Bitstream>) => bitstreamList.page),
88+
const eType = this.item.firstMetadataValue('dspace.entity.type');
89+
this.default$ = getDefaultImageUrlByEntityType(eType);
90+
91+
combineLatest([
92+
this.default$,
93+
this.getBitstreamsByItem(),
94+
]).pipe(
95+
map(([_, bitstreamList]: [string, PaginatedList<Bitstream>]) => bitstreamList.page),
8996
switchMap((filteredBitstreams: Bitstream[]) => {
9097
if (filteredBitstreams.length > 0) {
9198
if (isEmpty(filteredBitstreams[0].thumbnail)) {
@@ -113,19 +120,4 @@ export class ThumbnailRenderingComponent extends BitstreamRenderingModelComponen
113120
this.initialized.next(true);
114121
});
115122
}
116-
117-
/**
118-
* Set the default image src depending on item entity type
119-
*/
120-
setDefaultImage(): void {
121-
const eType = this.item.firstMetadataValue('dspace.entity.type');
122-
this.default = 'assets/images/file-placeholder.svg';
123-
if (hasValue(eType) && eType.toUpperCase() === 'PROJECT') {
124-
this.default = 'assets/images/project-placeholder.svg';
125-
} else if (hasValue(eType) && eType.toUpperCase() === 'ORGUNIT') {
126-
this.default = 'assets/images/orgunit-placeholder.svg';
127-
} else if (hasValue(eType) && eType.toUpperCase() === 'PERSON') {
128-
this.default = 'assets/images/person-placeholder.svg';
129-
}
130-
}
131123
}

0 commit comments

Comments
 (0)