From a157552a13033ad2bf6f721511e0bb8b26b4fe30 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?D=C3=A1niel=20P=C3=A9ter=20Sipos?= Date: Thu, 8 Oct 2020 14:15:16 +0200 Subject: [PATCH 001/132] #885 add media viewer --- package.json | 1 + src/app/+item-page/item-page.module.ts | 21 ++-- .../media-viewer-image.component.html | 1 + .../media-viewer-image.component.scss | 0 .../media-viewer-image.component.spec.ts | 41 +++++++ .../media-viewer-image.component.ts | 43 +++++++ .../media-viewer-video.component.html | 48 ++++++++ .../media-viewer-video.component.scss | 4 + .../media-viewer-video.component.spec.ts | 46 ++++++++ .../media-viewer-video.component.ts | 38 +++++++ .../media-viewer/media-viewer.component.html | 19 ++++ .../media-viewer/media-viewer.component.scss | 0 .../media-viewer.component.spec.ts | 106 ++++++++++++++++++ .../media-viewer/media-viewer.component.ts | 76 +++++++++++++ .../publication/publication.component.html | 5 +- .../core/shared/media-viewer-item.model.ts | 21 ++++ src/assets/i18n/en.json5 | 7 ++ src/assets/images/replacement_audio.svg | 9 ++ src/assets/images/replacement_document.svg | 9 ++ src/assets/images/replacement_image.svg | 9 ++ src/assets/images/replacement_video.svg | 9 ++ src/environments/environment.common.ts | 6 +- yarn.lock | 5 + 23 files changed, 511 insertions(+), 13 deletions(-) create mode 100644 src/app/+item-page/media-viewer/media-viewer-image/media-viewer-image.component.html create mode 100644 src/app/+item-page/media-viewer/media-viewer-image/media-viewer-image.component.scss create mode 100644 src/app/+item-page/media-viewer/media-viewer-image/media-viewer-image.component.spec.ts create mode 100644 src/app/+item-page/media-viewer/media-viewer-image/media-viewer-image.component.ts create mode 100644 src/app/+item-page/media-viewer/media-viewer-video/media-viewer-video.component.html create mode 100644 src/app/+item-page/media-viewer/media-viewer-video/media-viewer-video.component.scss create mode 100644 src/app/+item-page/media-viewer/media-viewer-video/media-viewer-video.component.spec.ts create mode 100644 src/app/+item-page/media-viewer/media-viewer-video/media-viewer-video.component.ts create mode 100644 src/app/+item-page/media-viewer/media-viewer.component.html create mode 100644 src/app/+item-page/media-viewer/media-viewer.component.scss create mode 100644 src/app/+item-page/media-viewer/media-viewer.component.spec.ts create mode 100644 src/app/+item-page/media-viewer/media-viewer.component.ts create mode 100644 src/app/core/shared/media-viewer-item.model.ts create mode 100644 src/assets/images/replacement_audio.svg create mode 100644 src/assets/images/replacement_document.svg create mode 100644 src/assets/images/replacement_image.svg create mode 100644 src/assets/images/replacement_video.svg diff --git a/package.json b/package.json index ae4abd2e41..ddbcf5d719 100644 --- a/package.json +++ b/package.json @@ -104,6 +104,7 @@ "ng2-file-upload": "1.4.0", "ng2-nouislider": "^1.8.2", "ngx-bootstrap": "^5.3.2", + "ngx-gallery": "^5.10.0", "ngx-infinite-scroll": "6.0.1", "ngx-moment": "^3.4.0", "ngx-pagination": "3.0.3", diff --git a/src/app/+item-page/item-page.module.ts b/src/app/+item-page/item-page.module.ts index 4c3a64e117..06dd6a4262 100644 --- a/src/app/+item-page/item-page.module.ts +++ b/src/app/+item-page/item-page.module.ts @@ -31,6 +31,11 @@ import { TabbedRelatedEntitiesSearchComponent } from './simple/related-entities/ import { StatisticsModule } from '../statistics/statistics.module'; import { AbstractIncrementalListComponent } from './simple/abstract-incremental-list/abstract-incremental-list.component'; +import { MediaViewerComponent } from './media-viewer/media-viewer.component'; +import { MediaViewerVideoComponent } from './media-viewer/media-viewer-video/media-viewer-video.component'; +import { MediaViewerImageComponent } from './media-viewer/media-viewer-image/media-viewer-image.component'; +import { NgxGalleryModule } from 'ngx-gallery'; + @NgModule({ imports: [ CommonModule, @@ -38,7 +43,8 @@ import { AbstractIncrementalListComponent } from './simple/abstract-incremental- ItemPageRoutingModule, EditItemPageModule, SearchPageModule, - StatisticsModule.forRoot() + StatisticsModule.forRoot(), + NgxGalleryModule, ], declarations: [ ItemPageComponent, @@ -62,6 +68,9 @@ import { AbstractIncrementalListComponent } from './simple/abstract-incremental- UploadBitstreamComponent, TabbedRelatedEntitiesSearchComponent, AbstractIncrementalListComponent, + MediaViewerComponent, + MediaViewerVideoComponent, + MediaViewerImageComponent, ], exports: [ ItemComponent, @@ -72,12 +81,8 @@ import { AbstractIncrementalListComponent } from './simple/abstract-incremental- RelatedItemsComponent, MetadataRepresentationListComponent, ItemPageTitleFieldComponent, - TabbedRelatedEntitiesSearchComponent + TabbedRelatedEntitiesSearchComponent, ], - entryComponents: [ - PublicationComponent - ] + entryComponents: [PublicationComponent], }) -export class ItemPageModule { - -} +export class ItemPageModule {} diff --git a/src/app/+item-page/media-viewer/media-viewer-image/media-viewer-image.component.html b/src/app/+item-page/media-viewer/media-viewer-image/media-viewer-image.component.html new file mode 100644 index 0000000000..b0398830a8 --- /dev/null +++ b/src/app/+item-page/media-viewer/media-viewer-image/media-viewer-image.component.html @@ -0,0 +1 @@ + diff --git a/src/app/+item-page/media-viewer/media-viewer-image/media-viewer-image.component.scss b/src/app/+item-page/media-viewer/media-viewer-image/media-viewer-image.component.scss new file mode 100644 index 0000000000..e69de29bb2 diff --git a/src/app/+item-page/media-viewer/media-viewer-image/media-viewer-image.component.spec.ts b/src/app/+item-page/media-viewer/media-viewer-image/media-viewer-image.component.spec.ts new file mode 100644 index 0000000000..2cc02bd2ac --- /dev/null +++ b/src/app/+item-page/media-viewer/media-viewer-image/media-viewer-image.component.spec.ts @@ -0,0 +1,41 @@ +import { DebugElement } from '@angular/core'; +import { async, ComponentFixture, TestBed } from '@angular/core/testing'; +import { By } from '@angular/platform-browser'; + +import { MediaViewerImageComponent } from './media-viewer-image.component'; + +describe('MediaViewerImageComponent', () => { + let component: MediaViewerImageComponent; + let fixture: ComponentFixture; + let debugElement: DebugElement; + let htmlElement: HTMLElement; + + beforeEach(async(() => { + TestBed.configureTestingModule({ + declarations: [MediaViewerImageComponent], + }).compileComponents(); + })); + + beforeEach(() => { + fixture = TestBed.createComponent(MediaViewerImageComponent); + component = fixture.componentInstance; + component.galleryOptions = [ + { + image: true, + imageSize: 'contain', + thumbnails: false, + imageArrows: false, + width: '340px', + height: '279px', + }, + ]; + debugElement = fixture.debugElement.query(By.css('ngx-gallery')); + htmlElement = debugElement.nativeElement; + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); + + describe; +}); diff --git a/src/app/+item-page/media-viewer/media-viewer-image/media-viewer-image.component.ts b/src/app/+item-page/media-viewer/media-viewer-image/media-viewer-image.component.ts new file mode 100644 index 0000000000..78fef69765 --- /dev/null +++ b/src/app/+item-page/media-viewer/media-viewer-image/media-viewer-image.component.ts @@ -0,0 +1,43 @@ +import { Component, Input, OnInit } from '@angular/core'; + +import { NgxGalleryOptions, NgxGalleryImage } from 'ngx-gallery'; +import { MediaViewerItem } from '../../../core/shared/media-viewer-item.model'; + +@Component({ + selector: 'ds-media-viewer-image', + templateUrl: './media-viewer-image.component.html', + styleUrls: ['./media-viewer-image.component.scss'], +}) +export class MediaViewerImageComponent implements OnInit { + @Input() images: MediaViewerItem[]; + constructor() {} + + galleryOptions: NgxGalleryOptions[]; + galleryImages: NgxGalleryImage[]; + + ngOnInit(): void { + this.galleryImages = new Array(); + this.galleryOptions = [ + { + image: true, + imageSize: 'contain', + thumbnails: false, + imageArrows: false, + width: '340px', + height: '279px', + }, + ]; + for (const image of this.images) { + this.galleryImages = [ + ...this.galleryImages, + { + small: image.thumbnail + ? image.thumbnail + : './assets/images/replacements_image.svg', + medium: image.bitstream._links.content.href, + big: image.bitstream._links.content.href, + }, + ]; + } + } +} diff --git a/src/app/+item-page/media-viewer/media-viewer-video/media-viewer-video.component.html b/src/app/+item-page/media-viewer/media-viewer-video/media-viewer-video.component.html new file mode 100644 index 0000000000..ec813a3116 --- /dev/null +++ b/src/app/+item-page/media-viewer/media-viewer-video/media-viewer-video.component.html @@ -0,0 +1,48 @@ + + +
+ + + +
+ +
+ +
+
+
+
diff --git a/src/app/+item-page/media-viewer/media-viewer-video/media-viewer-video.component.scss b/src/app/+item-page/media-viewer/media-viewer-video/media-viewer-video.component.scss new file mode 100644 index 0000000000..7702da7361 --- /dev/null +++ b/src/app/+item-page/media-viewer/media-viewer-video/media-viewer-video.component.scss @@ -0,0 +1,4 @@ +video { + width: 340px; + height: 279px; +} diff --git a/src/app/+item-page/media-viewer/media-viewer-video/media-viewer-video.component.spec.ts b/src/app/+item-page/media-viewer/media-viewer-video/media-viewer-video.component.spec.ts new file mode 100644 index 0000000000..48935880de --- /dev/null +++ b/src/app/+item-page/media-viewer/media-viewer-video/media-viewer-video.component.spec.ts @@ -0,0 +1,46 @@ +import { NO_ERRORS_SCHEMA } from '@angular/core'; +import { async, ComponentFixture, TestBed } from '@angular/core/testing'; +import { BrowserAnimationsModule } from '@angular/platform-browser/animations'; +import { TranslateLoader, TranslateModule } from '@ngx-translate/core'; +import { TranslateLoaderMock } from '../../../shared/mocks/translate-loader.mock'; +import { FileSizePipe } from '../../../shared/utils/file-size-pipe'; +import { VarDirective } from '../../../shared/utils/var.directive'; +import { MetadataFieldWrapperComponent } from '../../field-components/metadata-field-wrapper/metadata-field-wrapper.component'; + +import { MediaViewerVideoComponent } from './media-viewer-video.component'; + +describe('MediaViewerVideoComponent', () => { + let component: MediaViewerVideoComponent; + let fixture: ComponentFixture; + + beforeEach(async(() => { + TestBed.configureTestingModule({ + imports: [ + TranslateModule.forRoot({ + loader: { + provide: TranslateLoader, + useClass: TranslateLoaderMock, + }, + }), + BrowserAnimationsModule, + ], + declarations: [ + MediaViewerVideoComponent, + VarDirective, + FileSizePipe, + MetadataFieldWrapperComponent, + ], + schemas: [NO_ERRORS_SCHEMA], + }).compileComponents(); + })); + + beforeEach(() => { + fixture = TestBed.createComponent(MediaViewerVideoComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/+item-page/media-viewer/media-viewer-video/media-viewer-video.component.ts b/src/app/+item-page/media-viewer/media-viewer-video/media-viewer-video.component.ts new file mode 100644 index 0000000000..12a55979bf --- /dev/null +++ b/src/app/+item-page/media-viewer/media-viewer-video/media-viewer-video.component.ts @@ -0,0 +1,38 @@ +import { Component, Input, OnInit } from '@angular/core'; +import { MediaViewerItem } from '../../../core/shared/media-viewer-item.model'; + +@Component({ + selector: 'ds-media-viewer-video', + templateUrl: './media-viewer-video.component.html', + styleUrls: ['./media-viewer-video.component.scss'], +}) +export class MediaViewerVideoComponent implements OnInit { + @Input() medias: MediaViewerItem[]; + + isCollapsed: boolean; + currentIndex = 0; + + replacements = { + video: './assets/images/replacement_video.svg', + audio: './assets/images/replacement_audio.svg', + document: './assets/images/replacement_document.svg', + }; + + replacementThumbnail: string; + constructor() {} + + ngOnInit() { + this.isCollapsed = false; + } + + selectedMedia(index: number) { + console.log(index); + this.currentIndex = index; + } + nextMedia() { + this.currentIndex++; + } + prevMedia() { + this.currentIndex--; + } +} diff --git a/src/app/+item-page/media-viewer/media-viewer.component.html b/src/app/+item-page/media-viewer/media-viewer.component.html new file mode 100644 index 0000000000..dd901e2230 --- /dev/null +++ b/src/app/+item-page/media-viewer/media-viewer.component.html @@ -0,0 +1,19 @@ + + +
+ + + + + + +
+
diff --git a/src/app/+item-page/media-viewer/media-viewer.component.scss b/src/app/+item-page/media-viewer/media-viewer.component.scss new file mode 100644 index 0000000000..e69de29bb2 diff --git a/src/app/+item-page/media-viewer/media-viewer.component.spec.ts b/src/app/+item-page/media-viewer/media-viewer.component.spec.ts new file mode 100644 index 0000000000..c487facafd --- /dev/null +++ b/src/app/+item-page/media-viewer/media-viewer.component.spec.ts @@ -0,0 +1,106 @@ +import { async, ComponentFixture, TestBed } from '@angular/core/testing'; +import { Bitstream } from '../../core/shared/bitstream.model'; +import { createSuccessfulRemoteDataObject$ } from '../../shared/remote-data.utils'; +import { createPaginatedList } from '../../shared/testing/utils.test'; +import { of as observableOf } from 'rxjs'; +import { By } from '@angular/platform-browser'; +import { MediaViewerComponent } from './media-viewer.component'; +import { MockBitstreamFormat1 } from '../../shared/mocks/item.mock'; +import { TranslateLoader, TranslateModule } from '@ngx-translate/core'; +import { TranslateLoaderMock } from '../../shared/mocks/translate-loader.mock'; +import { BrowserAnimationsModule } from '@angular/platform-browser/animations'; +import { BitstreamDataService } from '../../core/data/bitstream-data.service'; +import { NO_ERRORS_SCHEMA } from '@angular/core'; +import { MediaViewerItem } from '../../core/shared/media-viewer-item.model'; +import { VarDirective } from '../../shared/utils/var.directive'; +import { MetadataFieldWrapperComponent } from '../field-components/metadata-field-wrapper/metadata-field-wrapper.component'; +import { FileSizePipe } from '../../shared/utils/file-size-pipe'; + +describe('MediaViewerComponent', () => { + let comp: MediaViewerComponent; + let fixture: ComponentFixture; + + const bitstreamDataService = jasmine.createSpyObj('bitstreamDataService', { + findAllByItemAndBundleName: createSuccessfulRemoteDataObject$( + createPaginatedList([]) + ), + }); + + const mockBitstream: Bitstream = Object.assign(new Bitstream(), { + sizeBytes: 10201, + content: + 'https://dspace7.4science.it/dspace-spring-rest/api/core/bitstreams/cf9b0c8e-a1eb-4b65-afd0-567366448713/content', + format: observableOf(MockBitstreamFormat1), + bundleName: 'ORIGINAL', + _links: { + self: { + href: + 'https://dspace7.4science.it/dspace-spring-rest/api/core/bitstreams/cf9b0c8e-a1eb-4b65-afd0-567366448713', + }, + content: { + href: + 'https://dspace7.4science.it/dspace-spring-rest/api/core/bitstreams/cf9b0c8e-a1eb-4b65-afd0-567366448713/content', + }, + }, + id: 'cf9b0c8e-a1eb-4b65-afd0-567366448713', + uuid: 'cf9b0c8e-a1eb-4b65-afd0-567366448713', + type: 'bitstream', + metadata: { + 'dc.title': [ + { + language: null, + value: 'test_word.docx', + }, + ], + }, + }); + + const mockMediaViewerItem: MediaViewerItem = Object.assign( + new MediaViewerItem(), + { bitstream: mockBitstream, format: 'image', thumbnail: null } + ); + + beforeEach(async(() => { + TestBed.configureTestingModule({ + imports: [ + TranslateModule.forRoot({ + loader: { + provide: TranslateLoader, + useClass: TranslateLoaderMock, + }, + }), + BrowserAnimationsModule, + ], + declarations: [ + MediaViewerComponent, + VarDirective, + FileSizePipe, + MetadataFieldWrapperComponent, + ], + providers: [ + { provide: BitstreamDataService, useValue: bitstreamDataService }, + ], + + schemas: [NO_ERRORS_SCHEMA], + }).compileComponents(); + })); + + beforeEach(() => { + fixture = TestBed.createComponent(MediaViewerComponent); + comp = fixture.componentInstance; + fixture.detectChanges(); + }); + + describe('when the bitstreams are loading', () => { + beforeEach(() => { + comp.mediaList$.next([mockMediaViewerItem]); + comp.isLoading = true; + fixture.detectChanges(); + }); + + it('should display a loading component', () => { + const loading = fixture.debugElement.query(By.css('ds-loading')); + expect(loading.nativeElement).toBeDefined(); + }); + }); +}); diff --git a/src/app/+item-page/media-viewer/media-viewer.component.ts b/src/app/+item-page/media-viewer/media-viewer.component.ts new file mode 100644 index 0000000000..c6c336826a --- /dev/null +++ b/src/app/+item-page/media-viewer/media-viewer.component.ts @@ -0,0 +1,76 @@ +import { Component, Input, OnInit } from '@angular/core'; +import { BehaviorSubject, Observable } from 'rxjs'; +import { filter, takeWhile } from 'rxjs/operators'; +import { BitstreamDataService } from '../../core/data/bitstream-data.service'; +import { BitstreamFormatDataService } from '../../core/data/bitstream-format-data.service'; +import { PaginatedList } from '../../core/data/paginated-list'; +import { RemoteData } from '../../core/data/remote-data'; +import { Bitstream } from '../../core/shared/bitstream.model'; +import { Item } from '../../core/shared/item.model'; +import { MediaViewerItem } from '../../core/shared/media-viewer-item.model'; +import { getFirstSucceededRemoteDataPayload } from '../../core/shared/operators'; +import { hasNoValue, hasValue } from '../../shared/empty.util'; + +@Component({ + selector: 'ds-media-viewer', + templateUrl: './media-viewer.component.html', + styleUrls: ['./media-viewer.component.scss'], +}) +export class MediaViewerComponent implements OnInit { + @Input() item: Item; + + mediaList$: BehaviorSubject; + + isLoading: boolean; + + constructor( + protected bitstreamDataService: BitstreamDataService, + protected bitstreamFormatDataService: BitstreamFormatDataService + ) {} + + ngOnInit(): void { + this.mediaList$ = new BehaviorSubject([]); + this.isLoading = true; + + this.loadRemoteData('ORIGINAL').subscribe((bitstreamsRD) => { + console.log(bitstreamsRD); + this.loadRemoteData('THUMBNAIL').subscribe((thumbnailsRD) => { + for (let index = 0; index < bitstreamsRD.payload.page.length; index++) { + this.bitstreamFormatDataService + .findByBitstream(bitstreamsRD.payload.page[index]) + .pipe(getFirstSucceededRemoteDataPayload()) + .subscribe((format) => { + const current = this.mediaList$.getValue(); + const mediaItem = new MediaViewerItem(); + mediaItem.bitstream = bitstreamsRD.payload.page[index]; + mediaItem.format = format.mimetype.split('/')[0]; + mediaItem.thumbnail = + thumbnailsRD.payload && thumbnailsRD.payload.page[index] + ? thumbnailsRD.payload.page[index]._links.content.href + : null; + this.mediaList$.next([...current, mediaItem]); + }); + } + this.isLoading = false; + }); + }); + } + + loadRemoteData( + bundleName: string + ): Observable>> { + return this.bitstreamDataService + .findAllByItemAndBundleName(this.item, bundleName) + .pipe( + filter((bitstreamsRD: RemoteData>) => + hasValue(bitstreamsRD) + ), + takeWhile( + (bitstreamsRD_1: RemoteData>) => + hasNoValue(bitstreamsRD_1.payload) && + hasNoValue(bitstreamsRD_1.error), + true + ) + ); + } +} diff --git a/src/app/+item-page/simple/item-types/publication/publication.component.html b/src/app/+item-page/simple/item-types/publication/publication.component.html index 9eb704b9e9..4b802ac583 100644 --- a/src/app/+item-page/simple/item-types/publication/publication.component.html +++ b/src/app/+item-page/simple/item-types/publication/publication.component.html @@ -3,9 +3,10 @@
- + + diff --git a/src/app/core/shared/media-viewer-item.model.ts b/src/app/core/shared/media-viewer-item.model.ts new file mode 100644 index 0000000000..cd3a31bd0b --- /dev/null +++ b/src/app/core/shared/media-viewer-item.model.ts @@ -0,0 +1,21 @@ +import { Bitstream } from './bitstream.model'; + +/** + * Model representing a media viewer item + */ +export class MediaViewerItem { + /** + * Incoming Bitsream + */ + bitstream: Bitstream; + + /** + * Incoming Bitsream format type + */ + format: string; + + /** + * Incoming Bitsream thumbnail + */ + thumbnail: string; +} diff --git a/src/assets/i18n/en.json5 b/src/assets/i18n/en.json5 index 369d3e0e63..b9ef252fe3 100644 --- a/src/assets/i18n/en.json5 +++ b/src/assets/i18n/en.json5 @@ -2449,6 +2449,13 @@ "publication.search.results.head": "Publication Search Results", "publication.search.title": "DSpace Angular :: Publication Search", + + + "media-viewer.next": "Next", + + "media-viewer.previus": "Previus", + + "media-viewer.playlist": "Playlist", "register-email.title": "New user registration", diff --git a/src/assets/images/replacement_audio.svg b/src/assets/images/replacement_audio.svg new file mode 100644 index 0000000000..03899914c9 --- /dev/null +++ b/src/assets/images/replacement_audio.svg @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/src/assets/images/replacement_document.svg b/src/assets/images/replacement_document.svg new file mode 100644 index 0000000000..f684ca9597 --- /dev/null +++ b/src/assets/images/replacement_document.svg @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/src/assets/images/replacement_image.svg b/src/assets/images/replacement_image.svg new file mode 100644 index 0000000000..b6817cf7fc --- /dev/null +++ b/src/assets/images/replacement_image.svg @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/src/assets/images/replacement_video.svg b/src/assets/images/replacement_video.svg new file mode 100644 index 0000000000..1972b25eca --- /dev/null +++ b/src/assets/images/replacement_video.svg @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/src/environments/environment.common.ts b/src/environments/environment.common.ts index 4f73339690..58a8443b6c 100644 --- a/src/environments/environment.common.ts +++ b/src/environments/environment.common.ts @@ -17,9 +17,9 @@ export const environment: GlobalConfig = { // The REST API server settings. // NOTE: these must be "synced" with the 'dspace.server.url' setting in your backend's local.cfg. rest: { - ssl: true, - host: 'dspace7.4science.cloud', - port: 443, + ssl: false, + host: 'localhost', + port: 8080, // NOTE: Space is capitalized because 'namespace' is a reserved string in TypeScript nameSpace: '/server', }, diff --git a/yarn.lock b/yarn.lock index d44182cc51..261651bb18 100644 --- a/yarn.lock +++ b/yarn.lock @@ -6928,6 +6928,11 @@ ngx-bootstrap@^5.3.2: resolved "https://registry.yarnpkg.com/ngx-bootstrap/-/ngx-bootstrap-5.3.2.tgz#0668b01202610657e998b3ca87669645e0b31dc9" integrity sha512-gSMf8EXYl99Q3gqkq4RVhoTNSTYHz2Or6Cig2BJRbLJyqk15ZQE5qcq/ldHS8zzx/wgCA3HQeI63t2j2mEU9PA== +ngx-gallery@^5.10.0: + version "5.10.0" + resolved "https://registry.yarnpkg.com/ngx-gallery/-/ngx-gallery-5.10.0.tgz#21f623cb788578dbb5a3625c869712de2b95258c" + integrity sha512-+2DnsBfkIzNQoReOHf6+OMf06+qyQQMyVVN4iQAtL0+KykjVqDZiBwLQtmwajDWMGph6O1HNKLrqTcmgqw+d2A== + ngx-infinite-scroll@6.0.1: version "6.0.1" resolved "https://registry.yarnpkg.com/ngx-infinite-scroll/-/ngx-infinite-scroll-6.0.1.tgz#571e54860ce32839451569bcf6e7a63cfae327bd" From a740453e887f2a54f0dbfbb8fc1c2c116beea2fa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?D=C3=A1niel=20P=C3=A9ter=20Sipos?= Date: Thu, 8 Oct 2020 14:45:37 +0200 Subject: [PATCH 002/132] #885 fix gallery --- src/app/app.component.scss | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/app/app.component.scss b/src/app/app.component.scss index b18e7e1402..327998923f 100644 --- a/src/app/app.component.scss +++ b/src/app/app.component.scss @@ -39,10 +39,6 @@ body { margin: 0; } -ds-header-navbar-wrapper { - z-index: $nav-z-index; -} - ds-admin-sidebar { position: fixed; z-index: $sidebar-z-index; @@ -51,3 +47,8 @@ ds-admin-sidebar { .ds-full-screen-loader { height: 100vh; } + +.sticky-top{ + z-index: 0; +} + From 55cca0538a494adf6df852148266138fab84c24c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?D=C3=A1niel=20P=C3=A9ter=20Sipos?= Date: Thu, 8 Oct 2020 15:43:31 +0200 Subject: [PATCH 003/132] #885 fix for linter --- .../media-viewer-image.component.spec.ts | 1 - .../media-viewer-image.component.ts | 1 - .../media-viewer-video.component.ts | 1 - .../media-viewer/media-viewer.component.ts | 18 ++++++++---------- 4 files changed, 8 insertions(+), 13 deletions(-) diff --git a/src/app/+item-page/media-viewer/media-viewer-image/media-viewer-image.component.spec.ts b/src/app/+item-page/media-viewer/media-viewer-image/media-viewer-image.component.spec.ts index 2cc02bd2ac..35a7835cd1 100644 --- a/src/app/+item-page/media-viewer/media-viewer-image/media-viewer-image.component.spec.ts +++ b/src/app/+item-page/media-viewer/media-viewer-image/media-viewer-image.component.spec.ts @@ -37,5 +37,4 @@ describe('MediaViewerImageComponent', () => { expect(component).toBeTruthy(); }); - describe; }); diff --git a/src/app/+item-page/media-viewer/media-viewer-image/media-viewer-image.component.ts b/src/app/+item-page/media-viewer/media-viewer-image/media-viewer-image.component.ts index 78fef69765..06952fa4cd 100644 --- a/src/app/+item-page/media-viewer/media-viewer-image/media-viewer-image.component.ts +++ b/src/app/+item-page/media-viewer/media-viewer-image/media-viewer-image.component.ts @@ -10,7 +10,6 @@ import { MediaViewerItem } from '../../../core/shared/media-viewer-item.model'; }) export class MediaViewerImageComponent implements OnInit { @Input() images: MediaViewerItem[]; - constructor() {} galleryOptions: NgxGalleryOptions[]; galleryImages: NgxGalleryImage[]; diff --git a/src/app/+item-page/media-viewer/media-viewer-video/media-viewer-video.component.ts b/src/app/+item-page/media-viewer/media-viewer-video/media-viewer-video.component.ts index 12a55979bf..0cf2decc67 100644 --- a/src/app/+item-page/media-viewer/media-viewer-video/media-viewer-video.component.ts +++ b/src/app/+item-page/media-viewer/media-viewer-video/media-viewer-video.component.ts @@ -19,7 +19,6 @@ export class MediaViewerVideoComponent implements OnInit { }; replacementThumbnail: string; - constructor() {} ngOnInit() { this.isCollapsed = false; diff --git a/src/app/+item-page/media-viewer/media-viewer.component.ts b/src/app/+item-page/media-viewer/media-viewer.component.ts index c6c336826a..ee17f01110 100644 --- a/src/app/+item-page/media-viewer/media-viewer.component.ts +++ b/src/app/+item-page/media-viewer/media-viewer.component.ts @@ -1,6 +1,6 @@ import { Component, Input, OnInit } from '@angular/core'; import { BehaviorSubject, Observable } from 'rxjs'; -import { filter, takeWhile } from 'rxjs/operators'; +import { filter, take } from 'rxjs/operators'; import { BitstreamDataService } from '../../core/data/bitstream-data.service'; import { BitstreamFormatDataService } from '../../core/data/bitstream-format-data.service'; import { PaginatedList } from '../../core/data/paginated-list'; @@ -9,7 +9,7 @@ import { Bitstream } from '../../core/shared/bitstream.model'; import { Item } from '../../core/shared/item.model'; import { MediaViewerItem } from '../../core/shared/media-viewer-item.model'; import { getFirstSucceededRemoteDataPayload } from '../../core/shared/operators'; -import { hasNoValue, hasValue } from '../../shared/empty.util'; +import { hasValue } from '../../shared/empty.util'; @Component({ selector: 'ds-media-viewer', @@ -35,6 +35,7 @@ export class MediaViewerComponent implements OnInit { this.loadRemoteData('ORIGINAL').subscribe((bitstreamsRD) => { console.log(bitstreamsRD); this.loadRemoteData('THUMBNAIL').subscribe((thumbnailsRD) => { + console.log(bitstreamsRD,thumbnailsRD) for (let index = 0; index < bitstreamsRD.payload.page.length; index++) { this.bitstreamFormatDataService .findByBitstream(bitstreamsRD.payload.page[index]) @@ -62,15 +63,12 @@ export class MediaViewerComponent implements OnInit { return this.bitstreamDataService .findAllByItemAndBundleName(this.item, bundleName) .pipe( - filter((bitstreamsRD: RemoteData>) => - hasValue(bitstreamsRD) + filter( + (bitstreamsRD: RemoteData>) => + hasValue(bitstreamsRD) && + (hasValue(bitstreamsRD.error) || hasValue(bitstreamsRD.payload)) ), - takeWhile( - (bitstreamsRD_1: RemoteData>) => - hasNoValue(bitstreamsRD_1.payload) && - hasNoValue(bitstreamsRD_1.error), - true - ) + take(1) ); } } From cfe6eb6e61094d32514b4e66023f3aeb3121d6d7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?D=C3=A1niel=20P=C3=A9ter=20Sipos?= Date: Thu, 8 Oct 2020 15:46:59 +0200 Subject: [PATCH 004/132] #885 fix enviroment --- src/environments/environment.common.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/environments/environment.common.ts b/src/environments/environment.common.ts index 58a8443b6c..4f73339690 100644 --- a/src/environments/environment.common.ts +++ b/src/environments/environment.common.ts @@ -17,9 +17,9 @@ export const environment: GlobalConfig = { // The REST API server settings. // NOTE: these must be "synced" with the 'dspace.server.url' setting in your backend's local.cfg. rest: { - ssl: false, - host: 'localhost', - port: 8080, + ssl: true, + host: 'dspace7.4science.cloud', + port: 443, // NOTE: Space is capitalized because 'namespace' is a reserved string in TypeScript nameSpace: '/server', }, From 88a64b1bd70fbf21c65d85ca94b897a42f3c8528 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?D=C3=A1niel=20P=C3=A9ter=20Sipos?= Date: Fri, 9 Oct 2020 14:25:44 +0200 Subject: [PATCH 005/132] #855 fix tests and add angular 8 compatible gallery --- package.json | 2 +- src/app/+item-page/item-page.module.ts | 2 +- .../media-viewer-image.component.html | 8 +++- .../media-viewer-image.component.scss | 1 + .../media-viewer-image.component.spec.ts | 32 +++++++------- .../media-viewer-image.component.ts | 6 ++- .../media-viewer-video.component.spec.ts | 43 ++++++++++++++++++- .../media-viewer.component.spec.ts | 9 ++++ .../media-viewer/media-viewer.component.ts | 2 - yarn.lock | 10 ++--- 10 files changed, 86 insertions(+), 29 deletions(-) diff --git a/package.json b/package.json index ddbcf5d719..bff7c22daa 100644 --- a/package.json +++ b/package.json @@ -66,6 +66,7 @@ "@angular/platform-server": "~8.2.14", "@angular/router": "~8.2.14", "@angularclass/bootloader": "1.0.1", + "@kolkov/ngx-gallery": "^1.2.3", "@ng-bootstrap/ng-bootstrap": "5.2.1", "@ng-dynamic-forms/core": "8.1.1", "@ng-dynamic-forms/ui-ng-bootstrap": "8.1.1", @@ -104,7 +105,6 @@ "ng2-file-upload": "1.4.0", "ng2-nouislider": "^1.8.2", "ngx-bootstrap": "^5.3.2", - "ngx-gallery": "^5.10.0", "ngx-infinite-scroll": "6.0.1", "ngx-moment": "^3.4.0", "ngx-pagination": "3.0.3", diff --git a/src/app/+item-page/item-page.module.ts b/src/app/+item-page/item-page.module.ts index 06dd6a4262..e9744857d6 100644 --- a/src/app/+item-page/item-page.module.ts +++ b/src/app/+item-page/item-page.module.ts @@ -34,7 +34,7 @@ import { AbstractIncrementalListComponent } from './simple/abstract-incremental- import { MediaViewerComponent } from './media-viewer/media-viewer.component'; import { MediaViewerVideoComponent } from './media-viewer/media-viewer-video/media-viewer-video.component'; import { MediaViewerImageComponent } from './media-viewer/media-viewer-image/media-viewer-image.component'; -import { NgxGalleryModule } from 'ngx-gallery'; +import { NgxGalleryModule } from '@kolkov/ngx-gallery'; @NgModule({ imports: [ diff --git a/src/app/+item-page/media-viewer/media-viewer-image/media-viewer-image.component.html b/src/app/+item-page/media-viewer/media-viewer-image/media-viewer-image.component.html index b0398830a8..63c7abe42e 100644 --- a/src/app/+item-page/media-viewer/media-viewer-image/media-viewer-image.component.html +++ b/src/app/+item-page/media-viewer/media-viewer-image/media-viewer-image.component.html @@ -1 +1,7 @@ - + + + diff --git a/src/app/+item-page/media-viewer/media-viewer-image/media-viewer-image.component.scss b/src/app/+item-page/media-viewer/media-viewer-image/media-viewer-image.component.scss index e69de29bb2..a0c6fe3fd7 100644 --- a/src/app/+item-page/media-viewer/media-viewer-image/media-viewer-image.component.scss +++ b/src/app/+item-page/media-viewer/media-viewer-image/media-viewer-image.component.scss @@ -0,0 +1 @@ +.ngx-gallery { display: inline-block; margin-bottom: 20px; } diff --git a/src/app/+item-page/media-viewer/media-viewer-image/media-viewer-image.component.spec.ts b/src/app/+item-page/media-viewer/media-viewer-image/media-viewer-image.component.spec.ts index 35a7835cd1..ea8bf3d874 100644 --- a/src/app/+item-page/media-viewer/media-viewer-image/media-viewer-image.component.spec.ts +++ b/src/app/+item-page/media-viewer/media-viewer-image/media-viewer-image.component.spec.ts @@ -1,40 +1,40 @@ -import { DebugElement } from '@angular/core'; +import { DebugElement, NO_ERRORS_SCHEMA } from '@angular/core'; import { async, ComponentFixture, TestBed } from '@angular/core/testing'; import { By } from '@angular/platform-browser'; +import { NgxGalleryImage, NgxGalleryOptions } from '@kolkov/ngx-gallery'; import { MediaViewerImageComponent } from './media-viewer-image.component'; describe('MediaViewerImageComponent', () => { let component: MediaViewerImageComponent; let fixture: ComponentFixture; - let debugElement: DebugElement; - let htmlElement: HTMLElement; beforeEach(async(() => { TestBed.configureTestingModule({ declarations: [MediaViewerImageComponent], - }).compileComponents(); + schemas: [NO_ERRORS_SCHEMA] + }).compileComponents(); })); beforeEach(() => { fixture = TestBed.createComponent(MediaViewerImageComponent); component = fixture.componentInstance; - component.galleryOptions = [ - { - image: true, - imageSize: 'contain', - thumbnails: false, - imageArrows: false, - width: '340px', - height: '279px', - }, + component.galleryOptions = [new NgxGalleryOptions({})]; + component.galleryImages = [ + new NgxGalleryImage({ + small: './assets/images/banner.jpg', + medium: './assets/images/banner.jpg', + big: './assets/images/banner.jpg', + }), + new NgxGalleryImage({ + small: './assets/images/dspace-logo.png', + medium: './assets/images/2-medium.jpg', + big: './assets/images/2-big.jpg', + }), ]; - debugElement = fixture.debugElement.query(By.css('ngx-gallery')); - htmlElement = debugElement.nativeElement; }); it('should create', () => { expect(component).toBeTruthy(); }); - }); diff --git a/src/app/+item-page/media-viewer/media-viewer-image/media-viewer-image.component.ts b/src/app/+item-page/media-viewer/media-viewer-image/media-viewer-image.component.ts index 06952fa4cd..05d7e824dd 100644 --- a/src/app/+item-page/media-viewer/media-viewer-image/media-viewer-image.component.ts +++ b/src/app/+item-page/media-viewer/media-viewer-image/media-viewer-image.component.ts @@ -1,7 +1,7 @@ import { Component, Input, OnInit } from '@angular/core'; - -import { NgxGalleryOptions, NgxGalleryImage } from 'ngx-gallery'; +import { NgxGalleryImage, NgxGalleryOptions } from '@kolkov/ngx-gallery'; import { MediaViewerItem } from '../../../core/shared/media-viewer-item.model'; +import { NgxGalleryAnimation } from '@kolkov/ngx-gallery'; @Component({ selector: 'ds-media-viewer-image', @@ -24,6 +24,8 @@ export class MediaViewerImageComponent implements OnInit { imageArrows: false, width: '340px', height: '279px', + startIndex: 0, + imageAnimation: NgxGalleryAnimation.Slide, }, ]; for (const image of this.images) { diff --git a/src/app/+item-page/media-viewer/media-viewer-video/media-viewer-video.component.spec.ts b/src/app/+item-page/media-viewer/media-viewer-video/media-viewer-video.component.spec.ts index 48935880de..45ce472db2 100644 --- a/src/app/+item-page/media-viewer/media-viewer-video/media-viewer-video.component.spec.ts +++ b/src/app/+item-page/media-viewer/media-viewer-video/media-viewer-video.component.spec.ts @@ -2,11 +2,14 @@ import { NO_ERRORS_SCHEMA } from '@angular/core'; import { async, ComponentFixture, TestBed } from '@angular/core/testing'; import { BrowserAnimationsModule } from '@angular/platform-browser/animations'; import { TranslateLoader, TranslateModule } from '@ngx-translate/core'; +import { of as observableOf } from 'rxjs'; +import { Bitstream } from '../../../core/shared/bitstream.model'; +import { MediaViewerItem } from '../../../core/shared/media-viewer-item.model'; import { TranslateLoaderMock } from '../../../shared/mocks/translate-loader.mock'; import { FileSizePipe } from '../../../shared/utils/file-size-pipe'; import { VarDirective } from '../../../shared/utils/var.directive'; import { MetadataFieldWrapperComponent } from '../../field-components/metadata-field-wrapper/metadata-field-wrapper.component'; - +import { MockBitstreamFormat1 } from '../../../shared/mocks/item.mock'; import { MediaViewerVideoComponent } from './media-viewer-video.component'; describe('MediaViewerVideoComponent', () => { @@ -34,9 +37,47 @@ describe('MediaViewerVideoComponent', () => { }).compileComponents(); })); + const mockBitstream: Bitstream = Object.assign(new Bitstream(), { + sizeBytes: 10201, + content: + 'https://dspace7.4science.it/dspace-spring-rest/api/core/bitstreams/cf9b0c8e-a1eb-4b65-afd0-567366448713/content', + format: observableOf(MockBitstreamFormat1), + bundleName: 'ORIGINAL', + _links: { + self: { + href: + 'https://dspace7.4science.it/dspace-spring-rest/api/core/bitstreams/cf9b0c8e-a1eb-4b65-afd0-567366448713', + }, + content: { + href: + 'https://dspace7.4science.it/dspace-spring-rest/api/core/bitstreams/cf9b0c8e-a1eb-4b65-afd0-567366448713/content', + }, + }, + id: 'cf9b0c8e-a1eb-4b65-afd0-567366448713', + uuid: 'cf9b0c8e-a1eb-4b65-afd0-567366448713', + type: 'bitstream', + metadata: { + 'dc.title': [ + { + language: null, + value: 'test_word.docx', + }, + ], + }, + }); + + const mockMediaViewerItems: MediaViewerItem[] = Object.assign( + new Array(), + [ + { bitstream: mockBitstream, format: 'video', thumbnail: null }, + { bitstream: mockBitstream, format: 'video', thumbnail: null }, + ] + ); + beforeEach(() => { fixture = TestBed.createComponent(MediaViewerVideoComponent); component = fixture.componentInstance; + component.medias = mockMediaViewerItems; fixture.detectChanges(); }); diff --git a/src/app/+item-page/media-viewer/media-viewer.component.spec.ts b/src/app/+item-page/media-viewer/media-viewer.component.spec.ts index c487facafd..8ab006f4fc 100644 --- a/src/app/+item-page/media-viewer/media-viewer.component.spec.ts +++ b/src/app/+item-page/media-viewer/media-viewer.component.spec.ts @@ -15,6 +15,8 @@ import { MediaViewerItem } from '../../core/shared/media-viewer-item.model'; import { VarDirective } from '../../shared/utils/var.directive'; import { MetadataFieldWrapperComponent } from '../field-components/metadata-field-wrapper/metadata-field-wrapper.component'; import { FileSizePipe } from '../../shared/utils/file-size-pipe'; +import { BitstreamFormat } from '../../core/shared/bitstream-format.model'; +import { BitstreamFormatDataService } from '../../core/data/bitstream-format-data.service'; describe('MediaViewerComponent', () => { let comp: MediaViewerComponent; @@ -26,6 +28,12 @@ describe('MediaViewerComponent', () => { ), }); + const bitstreamFormatDataService = jasmine.createSpyObj('bitstreamFormatDataService', { + findByBitstream: createSuccessfulRemoteDataObject$( + new BitstreamFormat() + ), + }); + const mockBitstream: Bitstream = Object.assign(new Bitstream(), { sizeBytes: 10201, content: @@ -79,6 +87,7 @@ describe('MediaViewerComponent', () => { ], providers: [ { provide: BitstreamDataService, useValue: bitstreamDataService }, + { provide: BitstreamFormatDataService, useValue: bitstreamFormatDataService }, ], schemas: [NO_ERRORS_SCHEMA], diff --git a/src/app/+item-page/media-viewer/media-viewer.component.ts b/src/app/+item-page/media-viewer/media-viewer.component.ts index ee17f01110..3f12f73d6a 100644 --- a/src/app/+item-page/media-viewer/media-viewer.component.ts +++ b/src/app/+item-page/media-viewer/media-viewer.component.ts @@ -33,9 +33,7 @@ export class MediaViewerComponent implements OnInit { this.isLoading = true; this.loadRemoteData('ORIGINAL').subscribe((bitstreamsRD) => { - console.log(bitstreamsRD); this.loadRemoteData('THUMBNAIL').subscribe((thumbnailsRD) => { - console.log(bitstreamsRD,thumbnailsRD) for (let index = 0; index < bitstreamsRD.payload.page.length; index++) { this.bitstreamFormatDataService .findByBitstream(bitstreamsRD.payload.page[index]) diff --git a/yarn.lock b/yarn.lock index 261651bb18..fa0109f53c 100644 --- a/yarn.lock +++ b/yarn.lock @@ -985,6 +985,11 @@ resolved "https://registry.yarnpkg.com/@istanbuljs/schema/-/schema-0.1.2.tgz#26520bf09abe4a5644cd5414e37125a8954241dd" integrity sha512-tsAQNx32a8CoFhjhijUIhI4kccIAgmGhy8LZMZgGfmXcpMbPRUqn5LWmgRttILi6yeGmBJd2xsPkFMs0PzgPCw== +"@kolkov/ngx-gallery@^1.2.3": + version "1.2.3" + resolved "https://registry.yarnpkg.com/@kolkov/ngx-gallery/-/ngx-gallery-1.2.3.tgz#bb15d4b64a5c03905677aa4ca741835aabe41f43" + integrity sha512-Dpnhwq3DGPSXrNt65gexo+/Smb2L0bne14A0WONN04+racETtcY33fqFvNWfRw5Nvk2Eza+sq95eEA0NbgF/6g== + "@mrmlnc/readdir-enhanced@^2.2.1": version "2.2.1" resolved "https://registry.yarnpkg.com/@mrmlnc/readdir-enhanced/-/readdir-enhanced-2.2.1.tgz#524af240d1a360527b730475ecfa1344aa540dde" @@ -6928,11 +6933,6 @@ ngx-bootstrap@^5.3.2: resolved "https://registry.yarnpkg.com/ngx-bootstrap/-/ngx-bootstrap-5.3.2.tgz#0668b01202610657e998b3ca87669645e0b31dc9" integrity sha512-gSMf8EXYl99Q3gqkq4RVhoTNSTYHz2Or6Cig2BJRbLJyqk15ZQE5qcq/ldHS8zzx/wgCA3HQeI63t2j2mEU9PA== -ngx-gallery@^5.10.0: - version "5.10.0" - resolved "https://registry.yarnpkg.com/ngx-gallery/-/ngx-gallery-5.10.0.tgz#21f623cb788578dbb5a3625c869712de2b95258c" - integrity sha512-+2DnsBfkIzNQoReOHf6+OMf06+qyQQMyVVN4iQAtL0+KykjVqDZiBwLQtmwajDWMGph6O1HNKLrqTcmgqw+d2A== - ngx-infinite-scroll@6.0.1: version "6.0.1" resolved "https://registry.yarnpkg.com/ngx-infinite-scroll/-/ngx-infinite-scroll-6.0.1.tgz#571e54860ce32839451569bcf6e7a63cfae327bd" From c044f458e1dc35ca5348a19bd5171f0cd4efb3c2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?D=C3=A1niel=20P=C3=A9ter=20Sipos?= Date: Fri, 9 Oct 2020 14:28:24 +0200 Subject: [PATCH 006/132] #885 fix lint --- .../media-viewer-image.component.spec.ts | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/app/+item-page/media-viewer/media-viewer-image/media-viewer-image.component.spec.ts b/src/app/+item-page/media-viewer/media-viewer-image/media-viewer-image.component.spec.ts index ea8bf3d874..623d98b6c3 100644 --- a/src/app/+item-page/media-viewer/media-viewer-image/media-viewer-image.component.spec.ts +++ b/src/app/+item-page/media-viewer/media-viewer-image/media-viewer-image.component.spec.ts @@ -1,6 +1,5 @@ -import { DebugElement, NO_ERRORS_SCHEMA } from '@angular/core'; +import { NO_ERRORS_SCHEMA } from '@angular/core'; import { async, ComponentFixture, TestBed } from '@angular/core/testing'; -import { By } from '@angular/platform-browser'; import { NgxGalleryImage, NgxGalleryOptions } from '@kolkov/ngx-gallery'; import { MediaViewerImageComponent } from './media-viewer-image.component'; @@ -12,8 +11,8 @@ describe('MediaViewerImageComponent', () => { beforeEach(async(() => { TestBed.configureTestingModule({ declarations: [MediaViewerImageComponent], - schemas: [NO_ERRORS_SCHEMA] - }).compileComponents(); + schemas: [NO_ERRORS_SCHEMA], + }).compileComponents(); })); beforeEach(() => { From f46c8ef7b3b2ecc2ea72b984278e5a703f96913e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?D=C3=A1niel=20P=C3=A9ter=20Sipos?= Date: Mon, 12 Oct 2020 11:02:21 +0200 Subject: [PATCH 007/132] QREPO-110 add commnets --- .../media-viewer-image.component.ts | 7 ++- .../media-viewer-video.component.html | 6 +-- .../media-viewer-video.component.spec.ts | 45 ++++++++++++++++++- .../media-viewer-video.component.ts | 15 +++++++ .../media-viewer/media-viewer.component.ts | 14 ++++++ 5 files changed, 82 insertions(+), 5 deletions(-) diff --git a/src/app/+item-page/media-viewer/media-viewer-image/media-viewer-image.component.ts b/src/app/+item-page/media-viewer/media-viewer-image/media-viewer-image.component.ts index 05d7e824dd..455c452cc6 100644 --- a/src/app/+item-page/media-viewer/media-viewer-image/media-viewer-image.component.ts +++ b/src/app/+item-page/media-viewer/media-viewer-image/media-viewer-image.component.ts @@ -2,7 +2,9 @@ import { Component, Input, OnInit } from '@angular/core'; import { NgxGalleryImage, NgxGalleryOptions } from '@kolkov/ngx-gallery'; import { MediaViewerItem } from '../../../core/shared/media-viewer-item.model'; import { NgxGalleryAnimation } from '@kolkov/ngx-gallery'; - +/** + * This componenet render an image gallery for the image viewer + */ @Component({ selector: 'ds-media-viewer-image', templateUrl: './media-viewer-image.component.html', @@ -14,6 +16,9 @@ export class MediaViewerImageComponent implements OnInit { galleryOptions: NgxGalleryOptions[]; galleryImages: NgxGalleryImage[]; + /** + * Thi method sets up the gallery settings and data + */ ngOnInit(): void { this.galleryImages = new Array(); this.galleryOptions = [ diff --git a/src/app/+item-page/media-viewer/media-viewer-video/media-viewer-video.component.html b/src/app/+item-page/media-viewer/media-viewer-video/media-viewer-video.component.html index ec813a3116..3fd09a5d5b 100644 --- a/src/app/+item-page/media-viewer/media-viewer-video/media-viewer-video.component.html +++ b/src/app/+item-page/media-viewer/media-viewer-video/media-viewer-video.component.html @@ -12,7 +12,7 @@ >
diff --git a/src/app/+item-page/media-viewer/media-viewer.component.ts b/src/app/+item-page/media-viewer/media-viewer.component.ts index 811445b864..866b0cb1cf 100644 --- a/src/app/+item-page/media-viewer/media-viewer.component.ts +++ b/src/app/+item-page/media-viewer/media-viewer.component.ts @@ -28,6 +28,8 @@ export class MediaViewerComponent implements OnInit { isLoading: boolean; + thumbnailPlaceholder = './assets/images/replacement_document.svg'; + constructor( protected bitstreamDataService: BitstreamDataService, protected bitstreamFormatDataService: BitstreamFormatDataService @@ -84,7 +86,6 @@ export class MediaViewerComponent implements OnInit { format: BitstreamFormat, thumbnail: Bitstream ): MediaViewerItem { - console.log(original, format, thumbnail); const mediaItem = new MediaViewerItem(); mediaItem.bitstream = original; mediaItem.format = format.mimetype.split('/')[0]; From 401bbf3a8ea0ca75c587bcd50a797b7ccd589800 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?D=C3=A1niel=20P=C3=A9ter=20Sipos?= Date: Tue, 13 Oct 2020 13:38:30 +0200 Subject: [PATCH 012/132] #885 fix default tumbnail --- src/app/+item-page/media-viewer/media-viewer.component.html | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/app/+item-page/media-viewer/media-viewer.component.html b/src/app/+item-page/media-viewer/media-viewer.component.html index 8f6d5ffa8c..60af6887ae 100644 --- a/src/app/+item-page/media-viewer/media-viewer.component.html +++ b/src/app/+item-page/media-viewer/media-viewer.component.html @@ -17,8 +17,8 @@ From 4312776b2d0b8fdff67e6b48673ce18ca62662fd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?D=C3=A1niel=20P=C3=A9ter=20Sipos?= Date: Tue, 3 Nov 2020 10:59:31 +0100 Subject: [PATCH 013/132] #885 fix loading bitstream format --- .../media-viewer-image.component.ts | 4 +++- .../media-viewer/media-viewer.component.scss | 4 ++++ .../media-viewer/media-viewer.component.spec.ts | 13 ------------- .../media-viewer/media-viewer.component.ts | 10 ++++------ 4 files changed, 11 insertions(+), 20 deletions(-) diff --git a/src/app/+item-page/media-viewer/media-viewer-image/media-viewer-image.component.ts b/src/app/+item-page/media-viewer/media-viewer-image/media-viewer-image.component.ts index b66ab791c8..7dbef894cd 100644 --- a/src/app/+item-page/media-viewer/media-viewer-image/media-viewer-image.component.ts +++ b/src/app/+item-page/media-viewer/media-viewer-image/media-viewer-image.component.ts @@ -46,7 +46,9 @@ export class MediaViewerImageComponent implements OnInit { small: image.thumbnail ? image.thumbnail : './assets/images/replacement_image.svg', - medium: image.bitstream._links.content.href, + medium: image.thumbnail + ? image.thumbnail + : './assets/images/replacement_image.svg', big: image.bitstream._links.content.href, }); } diff --git a/src/app/+item-page/media-viewer/media-viewer.component.scss b/src/app/+item-page/media-viewer/media-viewer.component.scss index e69de29bb2..84259b424d 100644 --- a/src/app/+item-page/media-viewer/media-viewer.component.scss +++ b/src/app/+item-page/media-viewer/media-viewer.component.scss @@ -0,0 +1,4 @@ +.media-viewer{ + width: 340px; + height: 279px; +} diff --git a/src/app/+item-page/media-viewer/media-viewer.component.spec.ts b/src/app/+item-page/media-viewer/media-viewer.component.spec.ts index 7bf31db965..1f3d410f3e 100644 --- a/src/app/+item-page/media-viewer/media-viewer.component.spec.ts +++ b/src/app/+item-page/media-viewer/media-viewer.component.spec.ts @@ -15,8 +15,6 @@ import { MediaViewerItem } from '../../core/shared/media-viewer-item.model'; import { VarDirective } from '../../shared/utils/var.directive'; import { MetadataFieldWrapperComponent } from '../field-components/metadata-field-wrapper/metadata-field-wrapper.component'; import { FileSizePipe } from '../../shared/utils/file-size-pipe'; -import { BitstreamFormat } from '../../core/shared/bitstream-format.model'; -import { BitstreamFormatDataService } from '../../core/data/bitstream-format-data.service'; describe('MediaViewerComponent', () => { let comp: MediaViewerComponent; @@ -57,13 +55,6 @@ describe('MediaViewerComponent', () => { ), }); - const bitstreamFormatDataService = jasmine.createSpyObj( - 'bitstreamFormatDataService', - { - findByBitstream: createSuccessfulRemoteDataObject$(new BitstreamFormat()), - } - ); - const mockMediaViewerItem: MediaViewerItem = Object.assign( new MediaViewerItem(), { bitstream: mockBitstream, format: 'image', thumbnail: null } @@ -88,10 +79,6 @@ describe('MediaViewerComponent', () => { ], providers: [ { provide: BitstreamDataService, useValue: bitstreamDataService }, - { - provide: BitstreamFormatDataService, - useValue: bitstreamFormatDataService, - }, ], schemas: [NO_ERRORS_SCHEMA], diff --git a/src/app/+item-page/media-viewer/media-viewer.component.ts b/src/app/+item-page/media-viewer/media-viewer.component.ts index 866b0cb1cf..938ad6c2d6 100644 --- a/src/app/+item-page/media-viewer/media-viewer.component.ts +++ b/src/app/+item-page/media-viewer/media-viewer.component.ts @@ -2,7 +2,6 @@ import { Component, Input, OnInit } from '@angular/core'; import { BehaviorSubject, Observable } from 'rxjs'; import { filter, take } from 'rxjs/operators'; import { BitstreamDataService } from '../../core/data/bitstream-data.service'; -import { BitstreamFormatDataService } from '../../core/data/bitstream-format-data.service'; import { PaginatedList } from '../../core/data/paginated-list'; import { RemoteData } from '../../core/data/remote-data'; import { BitstreamFormat } from '../../core/shared/bitstream-format.model'; @@ -11,6 +10,7 @@ import { Item } from '../../core/shared/item.model'; import { MediaViewerItem } from '../../core/shared/media-viewer-item.model'; import { getFirstSucceededRemoteDataPayload } from '../../core/shared/operators'; import { hasValue } from '../../shared/empty.util'; +import { followLink } from '../../shared/utils/follow-link-config.model'; /** * This componenet renders the media viewers @@ -32,7 +32,6 @@ export class MediaViewerComponent implements OnInit { constructor( protected bitstreamDataService: BitstreamDataService, - protected bitstreamFormatDataService: BitstreamFormatDataService ) {} /** @@ -44,9 +43,8 @@ export class MediaViewerComponent implements OnInit { this.loadRemoteData('ORIGINAL').subscribe((bitstreamsRD) => { this.loadRemoteData('THUMBNAIL').subscribe((thumbnailsRD) => { for (let index = 0; index < bitstreamsRD.payload.page.length; index++) { - this.bitstreamFormatDataService - .findByBitstream(bitstreamsRD.payload.page[index]) - .pipe(getFirstSucceededRemoteDataPayload()) + bitstreamsRD.payload.page[index].format + .pipe(getFirstSucceededRemoteDataPayload()) .subscribe((format) => { const current = this.mediaList$.getValue(); const mediaItem = this.createMediaViewerItem( @@ -70,7 +68,7 @@ export class MediaViewerComponent implements OnInit { bundleName: string ): Observable>> { return this.bitstreamDataService - .findAllByItemAndBundleName(this.item, bundleName) + .findAllByItemAndBundleName(this.item, bundleName, {}, followLink('format')) .pipe( filter( (bitstreamsRD: RemoteData>) => From 66f0b5f77d9ec4556618b0f36c8453e14667dfd7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?D=C3=A1niel=20P=C3=A9ter=20Sipos?= Date: Tue, 3 Nov 2020 11:15:16 +0100 Subject: [PATCH 014/132] #885 fix thumbnail size --- src/app/+item-page/media-viewer/media-viewer.component.scss | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/app/+item-page/media-viewer/media-viewer.component.scss b/src/app/+item-page/media-viewer/media-viewer.component.scss index 84259b424d..c2b7823e6c 100644 --- a/src/app/+item-page/media-viewer/media-viewer.component.scss +++ b/src/app/+item-page/media-viewer/media-viewer.component.scss @@ -1,4 +1,8 @@ .media-viewer{ width: 340px; height: 279px; + img{ + width: 100%; + height: 100%; + } } From 263c12e8f23fb9aa68a8260f7febddcfda41bfd6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?D=C3=A1niel=20P=C3=A9ter=20Sipos?= Date: Tue, 3 Nov 2020 13:27:17 +0100 Subject: [PATCH 015/132] #885 fix other thumbnail --- .../media-viewer-image.component.ts | 14 +++++++++++++- .../media-viewer/media-viewer.component.html | 2 +- .../media-viewer/media-viewer.component.scss | 9 +-------- 3 files changed, 15 insertions(+), 10 deletions(-) diff --git a/src/app/+item-page/media-viewer/media-viewer-image/media-viewer-image.component.ts b/src/app/+item-page/media-viewer/media-viewer-image/media-viewer-image.component.ts index 7dbef894cd..ae9dc7b927 100644 --- a/src/app/+item-page/media-viewer/media-viewer-image/media-viewer-image.component.ts +++ b/src/app/+item-page/media-viewer/media-viewer-image/media-viewer-image.component.ts @@ -12,6 +12,7 @@ import { NgxGalleryAnimation } from '@kolkov/ngx-gallery'; }) export class MediaViewerImageComponent implements OnInit { @Input() images: MediaViewerItem[]; + @Input() image: string; galleryOptions: NgxGalleryOptions[]; galleryImages: NgxGalleryImage[]; @@ -32,7 +33,18 @@ export class MediaViewerImageComponent implements OnInit { imageAnimation: NgxGalleryAnimation.Slide, }, ]; - this.galleryImages = this.convertToGalleryImage(this.images); + + if (this.image) { + this.galleryImages = [ + { + small: this.image, + medium: this.image, + big: this.image, + }, + ]; + } else { + this.galleryImages = this.convertToGalleryImage(this.images); + } } /** diff --git a/src/app/+item-page/media-viewer/media-viewer.component.html b/src/app/+item-page/media-viewer/media-viewer.component.html index 60af6887ae..c6f0468e85 100644 --- a/src/app/+item-page/media-viewer/media-viewer.component.html +++ b/src/app/+item-page/media-viewer/media-viewer.component.html @@ -22,7 +22,7 @@ mediaList[0]?.format !== 'audio' " > - +
diff --git a/src/app/+item-page/media-viewer/media-viewer.component.scss b/src/app/+item-page/media-viewer/media-viewer.component.scss index c2b7823e6c..8b13789179 100644 --- a/src/app/+item-page/media-viewer/media-viewer.component.scss +++ b/src/app/+item-page/media-viewer/media-viewer.component.scss @@ -1,8 +1 @@ -.media-viewer{ - width: 340px; - height: 279px; - img{ - width: 100%; - height: 100%; - } -} + From ae079f06ed3753452b75a092ca80baadf2d341b2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?D=C3=A1niel=20P=C3=A9ter=20Sipos?= Date: Tue, 3 Nov 2020 16:09:34 +0100 Subject: [PATCH 016/132] #885 quick fix --- .../media-viewer-image/media-viewer-image.component.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/app/+item-page/media-viewer/media-viewer-image/media-viewer-image.component.ts b/src/app/+item-page/media-viewer/media-viewer-image/media-viewer-image.component.ts index ae9dc7b927..b3993d2805 100644 --- a/src/app/+item-page/media-viewer/media-viewer-image/media-viewer-image.component.ts +++ b/src/app/+item-page/media-viewer/media-viewer-image/media-viewer-image.component.ts @@ -12,7 +12,7 @@ import { NgxGalleryAnimation } from '@kolkov/ngx-gallery'; }) export class MediaViewerImageComponent implements OnInit { @Input() images: MediaViewerItem[]; - @Input() image: string; + @Input() image?: string; galleryOptions: NgxGalleryOptions[]; galleryImages: NgxGalleryImage[]; From af79945fd865be08e027f065942e412da6770563 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?D=C3=A1niel=20P=C3=A9ter=20Sipos?= Date: Fri, 6 Nov 2020 11:05:20 +0100 Subject: [PATCH 017/132] #885 add enviroment variable for media viewer --- .editorconfig | 3 ++ .../media-viewer-image.component.ts | 7 +++++ .../media-viewer-video.component.html | 6 ++-- .../media-viewer/media-viewer.component.html | 31 ++++++++++++------- .../media-viewer/media-viewer.component.ts | 15 ++++++--- .../publication/publication.component.html | 13 +++++--- .../item-types/shared/item.component.ts | 3 ++ src/app/app.component.scss | 5 +++ src/assets/i18n/en.json5 | 2 +- src/config/global-config.interface.ts | 6 ++-- src/config/media-viewer-config.interface.ts | 7 +++++ src/environments/environment.common.ts | 5 +++ 12 files changed, 76 insertions(+), 27 deletions(-) create mode 100644 src/config/media-viewer-config.interface.ts diff --git a/.editorconfig b/.editorconfig index 70ce43b68e..15d4c87b14 100644 --- a/.editorconfig +++ b/.editorconfig @@ -12,3 +12,6 @@ trim_trailing_whitespace = true [*.md] insert_final_newline = false trim_trailing_whitespace = false + +[*.ts] +quote_type = single diff --git a/src/app/+item-page/media-viewer/media-viewer-image/media-viewer-image.component.ts b/src/app/+item-page/media-viewer/media-viewer-image/media-viewer-image.component.ts index b3993d2805..9069658d86 100644 --- a/src/app/+item-page/media-viewer/media-viewer-image/media-viewer-image.component.ts +++ b/src/app/+item-page/media-viewer/media-viewer-image/media-viewer-image.component.ts @@ -12,6 +12,7 @@ import { NgxGalleryAnimation } from '@kolkov/ngx-gallery'; }) export class MediaViewerImageComponent implements OnInit { @Input() images: MediaViewerItem[]; + @Input() preview?: boolean; @Input() image?: string; galleryOptions: NgxGalleryOptions[]; @@ -21,8 +22,10 @@ export class MediaViewerImageComponent implements OnInit { * Thi method sets up the gallery settings and data */ ngOnInit(): void { + console.log(this.preview); this.galleryOptions = [ { + preview: this.preview !== undefined ? this.preview : true, image: true, imageSize: 'contain', thumbnails: false, @@ -31,6 +34,10 @@ export class MediaViewerImageComponent implements OnInit { height: '279px', startIndex: 0, imageAnimation: NgxGalleryAnimation.Slide, + previewCloseOnEsc: true, + previewZoom: true, + previewRotate: true, + previewFullscreen: true, }, ]; diff --git a/src/app/+item-page/media-viewer/media-viewer-video/media-viewer-video.component.html b/src/app/+item-page/media-viewer/media-viewer-video/media-viewer-video.component.html index e190475e84..9fb02c445a 100644 --- a/src/app/+item-page/media-viewer/media-viewer-video/media-viewer-video.component.html +++ b/src/app/+item-page/media-viewer/media-viewer-video/media-viewer-video.component.html @@ -12,15 +12,15 @@ >
+ +
+ + +
-
+
-
- -
- +
diff --git a/src/app/app.component.scss b/src/app/app.component.scss index 337a358c3e..397f9d66e4 100644 --- a/src/app/app.component.scss +++ b/src/app/app.component.scss @@ -1,6 +1,6 @@ -@import '../styles/helpers/font_awesome_imports.scss'; -@import '../../node_modules/bootstrap/scss/bootstrap.scss'; -@import '../../node_modules/nouislider/distribute/nouislider.min'; +@import "../styles/helpers/font_awesome_imports.scss"; +@import "../../node_modules/bootstrap/scss/bootstrap.scss"; +@import "../../node_modules/nouislider/distribute/nouislider.min"; html { position: relative; @@ -48,12 +48,19 @@ ds-admin-sidebar { z-index: $sidebar-z-index; } - .ds-full-screen-loader { height: 100vh; } -.sticky-top{ +.sticky-top { z-index: 0; } +.media-viewer + .change-gallery + .ngx-gallery + ngx-gallery-preview.ngx-gallery-active { + right: 0; + left: auto; + width: 96%; +} From d17b8741562056ee28a949d6d23c904f732ef829 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?D=C3=A1niel=20P=C3=A9ter=20Sipos?= Date: Fri, 6 Nov 2020 13:40:28 +0100 Subject: [PATCH 019/132] #885 remove auto play and filter unsupported media types --- .../media-viewer-image.component.ts | 20 ++++++++++--------- .../media-viewer-video.component.html | 14 ++++++------- .../media-viewer-video.component.ts | 5 +++++ 3 files changed, 23 insertions(+), 16 deletions(-) diff --git a/src/app/+item-page/media-viewer/media-viewer-image/media-viewer-image.component.ts b/src/app/+item-page/media-viewer/media-viewer-image/media-viewer-image.component.ts index f0a5962e1f..9d7b3da45a 100644 --- a/src/app/+item-page/media-viewer/media-viewer-image/media-viewer-image.component.ts +++ b/src/app/+item-page/media-viewer/media-viewer-image/media-viewer-image.component.ts @@ -73,15 +73,17 @@ export class MediaViewerImageComponent implements OnInit { convertToGalleryImage(medias: MediaViewerItem[]): NgxGalleryImage[] { const mappadImages = []; for (const image of medias) { - mappadImages.push({ - small: image.thumbnail - ? image.thumbnail - : './assets/images/replacement_image.svg', - medium: image.thumbnail - ? image.thumbnail - : './assets/images/replacement_image.svg', - big: image.bitstream._links.content.href, - }); + if (image.format === 'image') { + mappadImages.push({ + small: image.thumbnail + ? image.thumbnail + : './assets/images/replacement_image.svg', + medium: image.thumbnail + ? image.thumbnail + : './assets/images/replacement_image.svg', + big: image.bitstream._links.content.href, + }); + } } return mappadImages; } diff --git a/src/app/+item-page/media-viewer/media-viewer-video/media-viewer-video.component.html b/src/app/+item-page/media-viewer/media-viewer-video/media-viewer-video.component.html index 1288af99b1..27d36c8a1b 100644 --- a/src/app/+item-page/media-viewer/media-viewer-video/media-viewer-video.component.html +++ b/src/app/+item-page/media-viewer/media-viewer-video/media-viewer-video.component.html @@ -1,15 +1,15 @@ -
+
diff --git a/src/app/+item-page/media-viewer/media-viewer.component.ts b/src/app/+item-page/media-viewer/media-viewer.component.ts index 3681846aaa..3f9de8ed3e 100644 --- a/src/app/+item-page/media-viewer/media-viewer.component.ts +++ b/src/app/+item-page/media-viewer/media-viewer.component.ts @@ -97,7 +97,7 @@ export class MediaViewerComponent implements OnInit { /** * This method create MediaViewerItem from incoming bitstreams * @param original original remote data bitstream - * @param format original bitstream format + * @param format original bitstream format * @param thumbnail trunbnail remote data bitstream */ createMediaViewerItem( From 151b02aeec81107731f5eadcdf4d4f25e7d34590 Mon Sep 17 00:00:00 2001 From: Giuseppe Digilio Date: Wed, 17 Feb 2021 16:10:22 +0100 Subject: [PATCH 035/132] [CST-3782] Make changes in order to remove template row in form's repeatable fields --- ...amic-form-control-container.component.html | 7 +- ...ynamic-form-control-container.component.ts | 4 + .../dynamic-form-array.component.html | 61 ++++------ .../dynamic-form-array.component.ts | 7 +- .../form/builder/form-builder.service.ts | 8 +- .../builder/parsers/concat-field-parser.ts | 16 ++- .../form/builder/parsers/field-parser.ts | 37 +++--- .../builder/parsers/onebox-field-parser.ts | 4 +- src/app/shared/form/form.component.html | 107 +++++++++--------- src/app/shared/form/form.component.ts | 47 +------- .../form/section-form-operations.service.ts | 33 +++--- src/assets/i18n/en.json5 | 2 + 12 files changed, 154 insertions(+), 179 deletions(-) diff --git a/src/app/shared/form/builder/ds-dynamic-form-ui/ds-dynamic-form-control-container.component.html b/src/app/shared/form/builder/ds-dynamic-form-ui/ds-dynamic-form-control-container.component.html index 7473f894fa..0ab69851a5 100644 --- a/src/app/shared/form/builder/ds-dynamic-form-ui/ds-dynamic-form-control-container.component.html +++ b/src/app/shared/form/builder/ds-dynamic-form-ui/ds-dynamic-form-control-container.component.html @@ -13,6 +13,11 @@ + +  
{{ message | translate: model.validators }} @@ -32,7 +37,7 @@
-
+
-
-
- - -
-
- -
-
- - - - - - -
-
-
-
- - -
-
+ + + +
+
+ + +
- + +
+
+ +
+
+
+ +
+ + + +
+
+
+
+ + +
+
+
+ +
diff --git a/src/app/shared/form/form.component.ts b/src/app/shared/form/form.component.ts index a4af407a55..f749f4391b 100644 --- a/src/app/shared/form/form.component.ts +++ b/src/app/shared/form/form.component.ts @@ -187,7 +187,6 @@ export class FormComponent implements OnDestroy, OnInit { if (field) { const model: DynamicFormControlModel = this.formBuilderService.findById(fieldId, formModel); this.formService.addErrorToField(field, model, error.message); - // this.formService.validateAllFormFields(formGroup); this.changeDetectorRef.detectChanges(); } @@ -300,55 +299,15 @@ export class FormComponent implements OnDestroy, OnInit { removeItem($event, arrayContext: DynamicFormArrayModel, index: number): void { const formArrayControl = this.formGroup.get(this.formBuilderService.getPath(arrayContext)) as FormArray; - this.removeArrayItem.emit(this.getEvent($event, arrayContext, index - 1, 'remove')); + this.removeArrayItem.emit(this.getEvent($event, arrayContext, index, 'remove')); this.formBuilderService.removeFormArrayGroup(index, formArrayControl, arrayContext); this.formService.changeForm(this.formId, this.formModel); } insertItem($event, arrayContext: DynamicFormArrayModel, index: number): void { const formArrayControl = this.formGroup.get(this.formBuilderService.getPath(arrayContext)) as FormArray; - - // First emit the new value so it can be sent to the server - const value = formArrayControl.controls[0].value; - const event = this.getEvent($event, arrayContext, 0, 'add'); - this.addArrayItem.emit(event); - this.change.emit(event); - - // Next: update the UI so the user sees the changes - // without having to wait for the server's reply - - // add an empty new field at the bottom - this.formBuilderService.addFormArrayGroup(formArrayControl, arrayContext); - - // set that field to the new value - const model = arrayContext.groups[arrayContext.groups.length - 1].group[0] as any; - if (model.hasAuthority) { - model.value = Object.values(value)[0]; - const ctrl = formArrayControl.controls[formArrayControl.length - 1]; - const ctrlValue = ctrl.value; - const ctrlValueKey = Object.keys(ctrlValue)[0]; - ctrl.setValue({ - [ctrlValueKey]: model.value - }); - } else if (this.formBuilderService.isQualdropGroup(model)) { - const ctrl = formArrayControl.controls[formArrayControl.length - 1]; - const ctrlKey = Object.keys(ctrl.value).find((key: string) => isNotEmpty(key.match(QUALDROP_GROUP_REGEX))); - const valueKey = Object.keys(value).find((key: string) => isNotEmpty(key.match(QUALDROP_GROUP_REGEX))); - if (ctrlKey !== valueKey) { - Object.defineProperty(value, ctrlKey, Object.getOwnPropertyDescriptor(value, valueKey)); - delete value[valueKey]; - } - ctrl.setValue(value); - } else { - formArrayControl.controls[formArrayControl.length - 1].setValue(value); - } - - // Clear the topmost field by removing the filled out version and inserting a new, empty version. - // Doing it this way ensures an empty value of the correct type is added without a bunch of ifs here - this.formBuilderService.removeFormArrayGroup(0, formArrayControl, arrayContext); - this.formBuilderService.insertFormArrayGroup(0, formArrayControl, arrayContext); - - // Tell the formService that it should rerender. + this.formBuilderService.insertFormArrayGroup(index, formArrayControl, arrayContext); + this.addArrayItem.emit(this.getEvent($event, arrayContext, index, 'add')); this.formService.changeForm(this.formId, this.formModel); } diff --git a/src/app/submission/sections/form/section-form-operations.service.ts b/src/app/submission/sections/form/section-form-operations.service.ts index d019663d6c..1c372fb06f 100644 --- a/src/app/submission/sections/form/section-form-operations.service.ts +++ b/src/app/submission/sections/form/section-form-operations.service.ts @@ -9,15 +9,7 @@ import { DynamicFormControlModel } from '@ng-dynamic-forms/core'; -import { - hasNoValue, - hasValue, - isNotEmpty, - isNotNull, - isNotUndefined, - isNull, - isUndefined -} from '../../../shared/empty.util'; +import { hasValue, isNotEmpty, isNotNull, isNotUndefined, isNull, isUndefined } from '../../../shared/empty.util'; import { JsonPatchOperationPathCombiner } from '../../../core/json-patch/builder/json-patch-operation-path-combiner'; import { FormFieldPreviousValueObject } from '../../../shared/form/builder/models/form-field-previous-value-object'; import { JsonPatchOperationsBuilder } from '../../../core/json-patch/builder/json-patch-operations-builder'; @@ -30,6 +22,7 @@ import { DynamicQualdropModel } from '../../../shared/form/builder/ds-dynamic-fo import { DynamicRelationGroupModel } from '../../../shared/form/builder/ds-dynamic-form-ui/models/relation-group/dynamic-relation-group.model'; import { VocabularyEntryDetail } from '../../../core/submission/vocabularies/models/vocabulary-entry-detail.model'; import { deepClone } from 'fast-json-patch'; +import { dateToString, isNgbDateStruct } from '../../../shared/date.util'; /** * The service handling all form section operations @@ -71,9 +64,6 @@ export class SectionFormOperationsService { case 'change': this.dispatchOperationsFromChangeEvent(pathCombiner, event, previousValue, hasStoredValue); break; - case 'add': - this.dispatchOperationsFromAddEvent(pathCombiner, event); - break; default: break; } @@ -245,6 +235,8 @@ export class SectionFormOperationsService { // Language without Authority (input, textArea) fieldValue = new FormFieldMetadataValueObject(value, language); } + } else if (isNgbDateStruct(value)) { + fieldValue = new FormFieldMetadataValueObject(dateToString(value)); } else if (value instanceof FormFieldLanguageValueObject || value instanceof VocabularyEntry || value instanceof VocabularyEntryDetail || isObject(value)) { fieldValue = value; @@ -295,7 +287,7 @@ export class SectionFormOperationsService { const value = this.getFieldValueFromChangeEvent(event); if (this.formBuilder.isQualdropGroup(event.model as DynamicFormControlModel)) { this.dispatchOperationsFromMap(this.getQualdropValueMap(event), pathCombiner, event, previousValue); - } else if (isNotEmpty(value)) { + } else if (isNotEmpty(value) && (value instanceof FormFieldMetadataValueObject && value.hasValue())) { this.operationsBuilder.remove(pathCombiner.getPath(path)); } } @@ -362,7 +354,7 @@ export class SectionFormOperationsService { } else if (this.formBuilder.isRelationGroup(event.model)) { // It's a relation model this.dispatchOperationsFromMap(this.getValueMap(value), pathCombiner, event, previousValue); - } else if (this.formBuilder.hasArrayGroupValue(event.model) && hasNoValue((event.model as any).relationshipConfig)) { + } else if (this.formBuilder.hasArrayGroupValue(event.model)) { // Model has as value an array, so dispatch an add operation with entire block of values this.operationsBuilder.add( pathCombiner.getPath(segmentedPath), @@ -398,13 +390,22 @@ export class SectionFormOperationsService { value); } previousValue.delete(); - } else if (value.hasValue() && (isUndefined(this.getArrayIndexFromEvent(event)) - || this.getArrayIndexFromEvent(event) === 0)) { + } else if (value.hasValue()) { + // Here model has no previous value but a new one + if (isUndefined(this.getArrayIndexFromEvent(event)) + || this.getArrayIndexFromEvent(event) === 0) { // Model is single field or is part of an array model but is the first item, // so dispatch an add operation that initialize the values of a specific metadata this.operationsBuilder.add( pathCombiner.getPath(segmentedPath), value, true); + } else { + // Model is part of an array model but is not the first item, + // so dispatch an add operation that add a value to an existent metadata + this.operationsBuilder.add( + pathCombiner.getPath(path), + value); + } } } diff --git a/src/assets/i18n/en.json5 b/src/assets/i18n/en.json5 index 51a2c0bd35..05d3aa4e49 100644 --- a/src/assets/i18n/en.json5 +++ b/src/assets/i18n/en.json5 @@ -1267,6 +1267,8 @@ "form.clear-help": "Click here to remove the selected value", + "form.discard": "Discard", + "form.edit": "Edit", "form.edit-help": "Click here to edit the selected value", From d208cf16fa56bd27b17f1f70b3e1cabcfb8607a8 Mon Sep 17 00:00:00 2001 From: Alessandro Martelli Date: Wed, 17 Feb 2021 17:57:29 +0100 Subject: [PATCH 036/132] [CST-3782] Drag drop restored --- .../dynamic-form-array.component.html | 50 +++++++++++-------- .../dynamic-form-array.component.ts | 12 +++-- src/app/shared/form/form.component.spec.ts | 4 +- .../sections/form/section-form.component.ts | 21 ++++---- 4 files changed, 49 insertions(+), 38 deletions(-) diff --git a/src/app/shared/form/builder/ds-dynamic-form-ui/models/array-group/dynamic-form-array.component.html b/src/app/shared/form/builder/ds-dynamic-form-ui/models/array-group/dynamic-form-array.component.html index d6cfc57b90..ec007d6ff4 100644 --- a/src/app/shared/form/builder/ds-dynamic-form-ui/models/array-group/dynamic-form-array.component.html +++ b/src/app/shared/form/builder/ds-dynamic-form-ui/models/array-group/dynamic-form-array.component.html @@ -3,29 +3,37 @@ [formArrayName]="model.id" [ngClass]="getClass('element', 'control')"> -
- - - - - - + +
+ +
+ + + + +
+
+ +
diff --git a/src/app/shared/form/builder/ds-dynamic-form-ui/models/array-group/dynamic-form-array.component.ts b/src/app/shared/form/builder/ds-dynamic-form-ui/models/array-group/dynamic-form-array.component.ts index 3c275ddf19..b6c1a6c308 100644 --- a/src/app/shared/form/builder/ds-dynamic-form-ui/models/array-group/dynamic-form-array.component.ts +++ b/src/app/shared/form/builder/ds-dynamic-form-ui/models/array-group/dynamic-form-array.component.ts @@ -44,9 +44,15 @@ export class DsDynamicFormArrayComponent extends DynamicFormArrayComponent { } moveSelection(event: CdkDragDrop) { + + // prevent propagating events generated releasing on the same position + if (event.previousIndex === event.currentIndex) { + return; + } + this.model.moveGroup(event.previousIndex, event.currentIndex - event.previousIndex); - const prevIndex = event.previousIndex - 1; - const index = event.currentIndex - 1; + const prevIndex = event.previousIndex; + const index = event.currentIndex; if (hasValue(this.model.groups[index]) && hasValue((this.control as any).controls[index])) { const $event = { @@ -59,7 +65,7 @@ export class DsDynamicFormArrayComponent extends DynamicFormArrayComponent { }; this.onChange($event); - } + } } update(event: any, index: number) { diff --git a/src/app/shared/form/form.component.spec.ts b/src/app/shared/form/form.component.spec.ts index aa004b3f87..4dd733a554 100644 --- a/src/app/shared/form/form.component.spec.ts +++ b/src/app/shared/form/form.component.spec.ts @@ -418,7 +418,7 @@ describe('FormComponent test suite', () => { })); it('should dispatch FormChangeAction when an item has been removed from an array', inject([FormBuilderService], (service: FormBuilderService) => { - formComp.removeItem(new Event('click'), formComp.formModel[0] as DynamicFormArrayModel, 1); + formComp.removeItem(new Event('click'), formComp.formModel[0] as DynamicFormArrayModel, 0); expect(store.dispatch).toHaveBeenCalledWith(new FormChangeAction('testFormArray', service.getValueFromModel(formComp.formModel))); })); @@ -426,7 +426,7 @@ describe('FormComponent test suite', () => { it('should emit removeArrayItem Event when an item has been removed from an array', inject([FormBuilderService], (service: FormBuilderService) => { spyOn(formComp.removeArrayItem, 'emit'); - formComp.removeItem(new Event('click'), formComp.formModel[0] as DynamicFormArrayModel, 1); + formComp.removeItem(new Event('click'), formComp.formModel[0] as DynamicFormArrayModel, 0); expect(formComp.removeArrayItem.emit).toHaveBeenCalled(); })); diff --git a/src/app/submission/sections/form/section-form.component.ts b/src/app/submission/sections/form/section-form.component.ts index c3d4575148..bc88323a8c 100644 --- a/src/app/submission/sections/form/section-form.component.ts +++ b/src/app/submission/sections/form/section-form.component.ts @@ -359,19 +359,16 @@ export class SubmissionSectionformComponent extends SectionModelComponent { * the [[DynamicFormControlEvent]] emitted */ onChange(event: DynamicFormControlEvent): void { - // don't handle change events for things with an index < 0, those are template rows. - if (hasNoValue(event.context) || hasNoValue(event.context.index) || event.context.index >= 0) { - this.formOperationsService.dispatchOperationsFromEvent( - this.pathCombiner, - event, - this.previousValue, - this.hasStoredValue(this.formBuilderService.getId(event.model), this.formOperationsService.getArrayIndexFromEvent(event))); - const metadata = this.formOperationsService.getFieldPathSegmentedFromChangeEvent(event); - const value = this.formOperationsService.getFieldValueFromChangeEvent(event); + this.formOperationsService.dispatchOperationsFromEvent( + this.pathCombiner, + event, + this.previousValue, + this.hasStoredValue(this.formBuilderService.getId(event.model), this.formOperationsService.getArrayIndexFromEvent(event))); + const metadata = this.formOperationsService.getFieldPathSegmentedFromChangeEvent(event); + const value = this.formOperationsService.getFieldValueFromChangeEvent(event); - if (environment.submission.autosave.metadata.indexOf(metadata) !== -1 && isNotEmpty(value)) { - this.submissionService.dispatchSave(this.submissionId); - } + if (environment.submission.autosave.metadata.indexOf(metadata) !== -1 && isNotEmpty(value)) { + this.submissionService.dispatchSave(this.submissionId); } } From 1901ace5a6416d12b00bbe70ce2d43aded99ad1d Mon Sep 17 00:00:00 2001 From: Giuseppe Digilio Date: Wed, 17 Feb 2021 20:25:46 +0100 Subject: [PATCH 037/132] [CST-3782] Changes in order to display add more and lookup button at the end of the repeatable fields array --- ...amic-form-control-container.component.html | 18 ++---- ...ynamic-form-control-container.component.ts | 51 +--------------- ...sting-metadata-list-element.component.html | 1 + ...ng-metadata-list-element.component.spec.ts | 10 ++++ .../dynamic-form-array.component.html | 2 +- .../dynamic-form-array.component.scss | 3 +- ...namic-lookup-relation-modal.component.html | 3 +- ...ic-lookup-relation-modal.component.spec.ts | 20 +++++++ ...dynamic-lookup-relation-modal.component.ts | 37 +++++++++++- src/app/shared/form/form.component.html | 33 +++++++---- src/app/shared/form/form.component.scss | 5 ++ src/app/shared/form/form.component.ts | 59 ++++++++++++++++--- src/assets/i18n/en.json5 | 2 +- 13 files changed, 160 insertions(+), 84 deletions(-) diff --git a/src/app/shared/form/builder/ds-dynamic-form-ui/ds-dynamic-form-control-container.component.html b/src/app/shared/form/builder/ds-dynamic-form-ui/ds-dynamic-form-control-container.component.html index 0ab69851a5..cb00993324 100644 --- a/src/app/shared/form/builder/ds-dynamic-form-ui/ds-dynamic-form-control-container.component.html +++ b/src/app/shared/form/builder/ds-dynamic-form-ui/ds-dynamic-form-control-container.component.html @@ -11,13 +11,12 @@ 'd-none': value?.isVirtual && (model.hasSelectableMetadata || context?.index > 0)}">
+ - -   + +
{{ message | translate: model.validators }} @@ -37,14 +36,6 @@
-
- -
@@ -70,6 +61,7 @@ [relationshipOptions]="model.relationship" > +
diff --git a/src/app/shared/form/builder/ds-dynamic-form-ui/ds-dynamic-form-control-container.component.ts b/src/app/shared/form/builder/ds-dynamic-form-ui/ds-dynamic-form-control-container.component.ts index 72dd374231..6c080a7f53 100644 --- a/src/app/shared/form/builder/ds-dynamic-form-ui/ds-dynamic-form-control-container.component.ts +++ b/src/app/shared/form/builder/ds-dynamic-form-ui/ds-dynamic-form-control-container.component.ts @@ -37,7 +37,6 @@ import { DynamicFormControl, DynamicFormControlContainerComponent, DynamicFormControlEvent, - DynamicFormControlEventType, DynamicFormControlModel, DynamicFormLayout, DynamicFormLayoutService, @@ -83,18 +82,16 @@ import { find, map, startWith, switchMap, take } from 'rxjs/operators'; import { combineLatest as observableCombineLatest, Observable, Subscription } from 'rxjs'; import { SearchResult } from '../../../search/search-result.model'; import { DSpaceObject } from '../../../../core/shared/dspace-object.model'; -import { NgbModal, NgbModalRef } from '@ng-bootstrap/ng-bootstrap'; import { RelationshipService } from '../../../../core/data/relationship.service'; import { SelectableListService } from '../../../object-list/selectable-list/selectable-list.service'; import { DsDynamicDisabledComponent } from './models/disabled/dynamic-disabled.component'; import { DYNAMIC_FORM_CONTROL_TYPE_DISABLED } from './models/disabled/dynamic-disabled.model'; -import { DsDynamicLookupRelationModalComponent } from './relation-lookup-modal/dynamic-lookup-relation-modal.component'; import { getAllSucceededRemoteData, + getFirstSucceededRemoteData, getFirstSucceededRemoteDataPayload, getPaginatedListPayload, - getRemoteDataPayload, - getFirstSucceededRemoteData + getRemoteDataPayload } from '../../../../core/shared/operators'; import { RemoteData } from '../../../../core/data/remote-data'; import { Item } from '../../../../core/shared/item.model'; @@ -110,7 +107,6 @@ import { Collection } from '../../../../core/shared/collection.model'; import { MetadataValue, VIRTUAL_METADATA_PREFIX } from '../../../../core/shared/metadata.models'; import { FormService } from '../../form.service'; import { SelectableListState } from '../../../object-list/selectable-list/selectable-list.reducer'; -import { SubmissionService } from '../../../../submission/submission.service'; import { followLink } from '../../../utils/follow-link-config.model'; import { paginatedRelationsToItems } from '../../../../+item-page/simple/item-types/shared/item-relationships-utils'; import { RelationshipOptions } from '../models/relationship-options.model'; @@ -206,7 +202,6 @@ export class DsDynamicFormControlContainerComponent extends DynamicFormControlCo @Input() model: any; relationshipValue$: Observable; isRelationship: boolean; - modalRef: NgbModalRef; item: Item; item$: Observable; collection: Collection; @@ -239,7 +234,6 @@ export class DsDynamicFormControlContainerComponent extends DynamicFormControlCo protected validationService: DynamicFormValidationService, protected translateService: TranslateService, protected relationService: DynamicFormRelationService, - private modalService: NgbModal, private relationshipService: RelationshipService, private selectableListService: SelectableListService, private itemService: ItemDataService, @@ -249,7 +243,6 @@ export class DsDynamicFormControlContainerComponent extends DynamicFormControlCo private ref: ChangeDetectorRef, private formService: FormService, private formBuilderService: FormBuilderService, - private submissionService: SubmissionService ) { super(ref, componentFactoryResolver, layoutService, validationService, dynamicFormComponentService, relationService); } @@ -264,7 +257,6 @@ export class DsDynamicFormControlContainerComponent extends DynamicFormControlCo if (this.isRelationship || isWrapperAroundRelationshipList) { const config = this.model.relationshipConfig || this.model.relationship; const relationshipOptions = Object.assign(new RelationshipOptions(), config); - this.listId = `list-${this.model.submissionId}-${relationshipOptions.relationshipType}`; this.setItem(); if (isWrapperAroundRelationshipList || !this.model.repeatable) { @@ -378,45 +370,6 @@ export class DsDynamicFormControlContainerComponent extends DynamicFormControlCo return this.model.value.pipe(map((list: SearchResult[]) => isNotEmpty(list))); } - /** - * Open a modal where the user can select relationships to be added to item being submitted - */ - openLookup() { - this.modalRef = this.modalService.open(DsDynamicLookupRelationModalComponent, { - size: 'lg' - }); - const modalComp = this.modalRef.componentInstance; - - if (hasValue(this.model.value) && !this.model.readOnly) { - if (typeof this.model.value === 'string') { - modalComp.query = this.model.value; - } else if (typeof this.model.value.value === 'string') { - modalComp.query = this.model.value.value; - } - } - - if (hasValue(this.model.value)) { - this.model.value = ''; - this.onChange({ - $event: { previousIndex: 0 }, - context: { index: 0 }, - control: this.control, - model: this.model, - type: DynamicFormControlEventType.Change - }); - } - this.submissionService.dispatchSave(this.model.submissionId); - - modalComp.repeatable = this.model.repeatable; - modalComp.listId = this.listId; - modalComp.relationshipOptions = this.model.relationship; - modalComp.label = this.model.relationship.relationshipType; - modalComp.metadataFields = this.model.metadataFields; - modalComp.item = this.item; - modalComp.collection = this.collection; - modalComp.submissionId = this.model.submissionId; - } - /** * Callback for the remove event, * remove the current control from its array diff --git a/src/app/shared/form/builder/ds-dynamic-form-ui/existing-metadata-list-element/existing-metadata-list-element.component.html b/src/app/shared/form/builder/ds-dynamic-form-ui/existing-metadata-list-element/existing-metadata-list-element.component.html index 57ab7d66d8..07ea131a00 100644 --- a/src/app/shared/form/builder/ds-dynamic-form-ui/existing-metadata-list-element/existing-metadata-list-element.component.html +++ b/src/app/shared/form/builder/ds-dynamic-form-ui/existing-metadata-list-element/existing-metadata-list-element.component.html @@ -8,6 +8,7 @@ diff --git a/src/app/shared/form/builder/ds-dynamic-form-ui/existing-metadata-list-element/existing-metadata-list-element.component.spec.ts b/src/app/shared/form/builder/ds-dynamic-form-ui/existing-metadata-list-element/existing-metadata-list-element.component.spec.ts index c606145c03..3a5623cfdd 100644 --- a/src/app/shared/form/builder/ds-dynamic-form-ui/existing-metadata-list-element/existing-metadata-list-element.component.spec.ts +++ b/src/app/shared/form/builder/ds-dynamic-form-ui/existing-metadata-list-element/existing-metadata-list-element.component.spec.ts @@ -14,6 +14,8 @@ import { createSuccessfulRemoteDataObject$ } from '../../../../remote-data.utils import { RemoveRelationshipAction } from '../relation-lookup-modal/relationship.actions'; import { ItemSearchResult } from '../../../../object-collection/shared/item-search-result.model'; import { of as observableOf } from 'rxjs'; +import { TranslateLoader, TranslateModule } from '@ngx-translate/core'; +import { TranslateLoaderMock } from '../../../../testing/translate-loader.mock'; describe('ExistingMetadataListElementComponent', () => { let component: ExistingMetadataListElementComponent; @@ -65,6 +67,14 @@ describe('ExistingMetadataListElementComponent', () => { beforeEach(waitForAsync(() => { init(); TestBed.configureTestingModule({ + imports: [ + TranslateModule.forRoot({ + loader: { + provide: TranslateLoader, + useClass: TranslateLoaderMock + } + }) + ], declarations: [ExistingMetadataListElementComponent], providers: [ { provide: SelectableListService, useValue: selectionService }, diff --git a/src/app/shared/form/builder/ds-dynamic-form-ui/models/array-group/dynamic-form-array.component.html b/src/app/shared/form/builder/ds-dynamic-form-ui/models/array-group/dynamic-form-array.component.html index ec007d6ff4..d036627345 100644 --- a/src/app/shared/form/builder/ds-dynamic-form-ui/models/array-group/dynamic-form-array.component.html +++ b/src/app/shared/form/builder/ds-dynamic-form-ui/models/array-group/dynamic-form-array.component.html @@ -12,7 +12,7 @@ [ngClass]="[getClass('element', 'group'), getClass('grid', 'group')]" cdkDrag cdkDragHandle> - +
From 975ef7ebd2d8c037813757ebbc96413676b5dcb3 Mon Sep 17 00:00:00 2001 From: Alessandro Martelli Date: Wed, 24 Feb 2021 15:34:21 +0100 Subject: [PATCH 041/132] [CST-3782] Style refinements and qualdrop moves fixed --- ...-dynamic-form-control-container.component.html | 15 +++++++-------- .../array-group/dynamic-form-array.component.html | 6 ++++++ .../array-group/dynamic-form-array.component.scss | 14 ++++---------- .../form/section-form-operations.service.ts | 3 ++- src/assets/i18n/en.json5 | 1 + 5 files changed, 20 insertions(+), 19 deletions(-) diff --git a/src/app/shared/form/builder/ds-dynamic-form-ui/ds-dynamic-form-control-container.component.html b/src/app/shared/form/builder/ds-dynamic-form-ui/ds-dynamic-form-control-container.component.html index cb00993324..029ba0b1f8 100644 --- a/src/app/shared/form/builder/ds-dynamic-form-ui/ds-dynamic-form-control-container.component.html +++ b/src/app/shared/form/builder/ds-dynamic-form-ui/ds-dynamic-form-control-container.component.html @@ -11,16 +11,15 @@ 'd-none': value?.isVirtual && (model.hasSelectableMetadata || context?.index > 0)}">
- - - -
+ +
-
- {{ message | translate: model.validators }} -
+
+ {{ message | translate: model.validators }} +
diff --git a/src/app/shared/form/builder/ds-dynamic-form-ui/models/array-group/dynamic-form-array.component.html b/src/app/shared/form/builder/ds-dynamic-form-ui/models/array-group/dynamic-form-array.component.html index d036627345..732b5978ac 100644 --- a/src/app/shared/form/builder/ds-dynamic-form-ui/models/array-group/dynamic-form-array.component.html +++ b/src/app/shared/form/builder/ds-dynamic-form-ui/models/array-group/dynamic-form-array.component.html @@ -12,6 +12,12 @@ [ngClass]="[getClass('element', 'group'), getClass('grid', 'group')]" cdkDrag cdkDragHandle> +
+
+ {{ 'form.repeatable.sort.tip' | translate }} +
+
+ Date: Thu, 25 Feb 2021 13:17:47 +0100 Subject: [PATCH 042/132] [CST-3620] fix typo --- src/app/shared/form/builder/parsers/field-parser.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/app/shared/form/builder/parsers/field-parser.ts b/src/app/shared/form/builder/parsers/field-parser.ts index b8411ca22c..93f941e344 100644 --- a/src/app/shared/form/builder/parsers/field-parser.ts +++ b/src/app/shared/form/builder/parsers/field-parser.ts @@ -67,11 +67,11 @@ export abstract class FieldParser { model = this.modelFactory(); arrayCounter++; } else { - const fieldArrayOfValueLenght = this.getInitValueCount(arrayCounter - 1); + const fieldArrayOfValueLength = this.getInitValueCount(arrayCounter - 1); let fieldValue = null; - if (fieldArrayOfValueLenght > 0) { + if (fieldArrayOfValueLength > 0) { fieldValue = this.getInitFieldValue(arrayCounter - 1, fieldArrayCounter++); - if (fieldArrayCounter === fieldArrayOfValueLenght) { + if (fieldArrayCounter === fieldArrayOfValueLength) { fieldArrayCounter = 0; arrayCounter++; } From 5eec2efa9c0dbb58eaf331ba48fa07eab3ba29bf Mon Sep 17 00:00:00 2001 From: Yura Bondarenko Date: Thu, 25 Feb 2021 13:37:24 +0100 Subject: [PATCH 043/132] 77205: Move admin-access-control out of +admin --- src/app/+admin/admin-routing.module.ts | 2 +- src/app/+admin/admin.module.ts | 2 +- .../admin-access-control-routing-paths.ts | 4 +- .../admin-access-control-routing.module.ts | 0 .../admin-access-control.module.ts | 2 +- .../epeople-registry.actions.ts | 4 +- .../epeople-registry.component.html | 0 .../epeople-registry.component.spec.ts | 34 +++++++------- .../epeople-registry.component.ts | 30 ++++++------ .../epeople-registry.reducers.spec.ts | 2 +- .../epeople-registry.reducers.ts | 2 +- .../eperson-form/eperson-form.component.html | 0 .../eperson-form.component.spec.ts | 38 +++++++-------- .../eperson-form/eperson-form.component.ts | 34 +++++++------- .../group-form/group-form.component.html | 0 .../group-form/group-form.component.spec.ts | 46 +++++++++---------- .../group-form/group-form.component.ts | 44 +++++++++--------- .../members-list/members-list.component.html | 0 .../members-list.component.spec.ts | 36 +++++++-------- .../members-list/members-list.component.ts | 20 ++++---- .../subgroups-list.component.html | 0 .../subgroups-list.component.spec.ts | 30 ++++++------ .../subgroup-list/subgroups-list.component.ts | 16 +++---- .../group-registry/group-registry.actions.ts | 4 +- .../group-registry.reducers.spec.ts | 2 +- .../group-registry/group-registry.reducers.ts | 2 +- .../groups-registry.component.html | 0 .../groups-registry.component.spec.ts | 40 ++++++++-------- .../groups-registry.component.ts | 38 +++++++-------- src/app/app.reducer.ts | 4 +- .../core/eperson/eperson-data.service.spec.ts | 2 +- src/app/core/eperson/eperson-data.service.ts | 4 +- .../core/eperson/group-data.service.spec.ts | 2 +- src/app/core/eperson/group-data.service.ts | 4 +- .../comcol-role/comcol-role.component.ts | 2 +- .../resource-policies.component.ts | 2 +- 36 files changed, 226 insertions(+), 226 deletions(-) rename src/app/{+admin => }/admin-access-control/admin-access-control-routing-paths.ts (56%) rename src/app/{+admin => }/admin-access-control/admin-access-control-routing.module.ts (100%) rename src/app/{+admin => }/admin-access-control/admin-access-control.module.ts (95%) rename src/app/{+admin => }/admin-access-control/epeople-registry/epeople-registry.actions.ts (91%) rename src/app/{+admin => }/admin-access-control/epeople-registry/epeople-registry.component.html (100%) rename src/app/{+admin => }/admin-access-control/epeople-registry/epeople-registry.component.spec.ts (87%) rename src/app/{+admin => }/admin-access-control/epeople-registry/epeople-registry.component.ts (88%) rename src/app/{+admin => }/admin-access-control/epeople-registry/epeople-registry.reducers.spec.ts (96%) rename src/app/{+admin => }/admin-access-control/epeople-registry/epeople-registry.reducers.ts (93%) rename src/app/{+admin => }/admin-access-control/epeople-registry/eperson-form/eperson-form.component.html (100%) rename src/app/{+admin => }/admin-access-control/epeople-registry/eperson-form/eperson-form.component.spec.ts (87%) rename src/app/{+admin => }/admin-access-control/epeople-registry/eperson-form/eperson-form.component.ts (91%) rename src/app/{+admin => }/admin-access-control/group-registry/group-form/group-form.component.html (100%) rename src/app/{+admin => }/admin-access-control/group-registry/group-form/group-form.component.spec.ts (77%) rename src/app/{+admin => }/admin-access-control/group-registry/group-form/group-form.component.ts (89%) rename src/app/{+admin => }/admin-access-control/group-registry/group-form/members-list/members-list.component.html (100%) rename src/app/{+admin => }/admin-access-control/group-registry/group-form/members-list/members-list.component.spec.ts (85%) rename src/app/{+admin => }/admin-access-control/group-registry/group-form/members-list/members-list.component.ts (93%) rename src/app/{+admin => }/admin-access-control/group-registry/group-form/subgroup-list/subgroups-list.component.html (100%) rename src/app/{+admin => }/admin-access-control/group-registry/group-form/subgroup-list/subgroups-list.component.spec.ts (86%) rename src/app/{+admin => }/admin-access-control/group-registry/group-form/subgroup-list/subgroups-list.component.ts (93%) rename src/app/{+admin => }/admin-access-control/group-registry/group-registry.actions.ts (91%) rename src/app/{+admin => }/admin-access-control/group-registry/group-registry.reducers.spec.ts (96%) rename src/app/{+admin => }/admin-access-control/group-registry/group-registry.reducers.ts (93%) rename src/app/{+admin => }/admin-access-control/group-registry/groups-registry.component.html (100%) rename src/app/{+admin => }/admin-access-control/group-registry/groups-registry.component.spec.ts (81%) rename src/app/{+admin => }/admin-access-control/group-registry/groups-registry.component.ts (84%) diff --git a/src/app/+admin/admin-routing.module.ts b/src/app/+admin/admin-routing.module.ts index 6c44af8190..5094201841 100644 --- a/src/app/+admin/admin-routing.module.ts +++ b/src/app/+admin/admin-routing.module.ts @@ -18,7 +18,7 @@ import { ACCESS_CONTROL_MODULE_PATH, REGISTRIES_MODULE_PATH } from './admin-rout }, { path: ACCESS_CONTROL_MODULE_PATH, - loadChildren: () => import('./admin-access-control/admin-access-control.module') + loadChildren: () => import('../admin-access-control/admin-access-control.module') .then((m) => m.AdminAccessControlModule), }, { diff --git a/src/app/+admin/admin.module.ts b/src/app/+admin/admin.module.ts index 494edd71eb..a1a5caaf99 100644 --- a/src/app/+admin/admin.module.ts +++ b/src/app/+admin/admin.module.ts @@ -1,6 +1,6 @@ import { NgModule } from '@angular/core'; import { SharedModule } from '../shared/shared.module'; -import { AdminAccessControlModule } from './admin-access-control/admin-access-control.module'; +import { AdminAccessControlModule } from '../admin-access-control/admin-access-control.module'; import { MetadataImportPageComponent } from './admin-import-metadata-page/metadata-import-page.component'; import { AdminRegistriesModule } from './admin-registries/admin-registries.module'; import { AdminRoutingModule } from './admin-routing.module'; diff --git a/src/app/+admin/admin-access-control/admin-access-control-routing-paths.ts b/src/app/admin-access-control/admin-access-control-routing-paths.ts similarity index 56% rename from src/app/+admin/admin-access-control/admin-access-control-routing-paths.ts rename to src/app/admin-access-control/admin-access-control-routing-paths.ts index 2080cb14a7..2a38a78015 100644 --- a/src/app/+admin/admin-access-control/admin-access-control-routing-paths.ts +++ b/src/app/admin-access-control/admin-access-control-routing-paths.ts @@ -1,5 +1,5 @@ -import { URLCombiner } from '../../core/url-combiner/url-combiner'; -import { getAccessControlModuleRoute } from '../admin-routing-paths'; +import { URLCombiner } from '../core/url-combiner/url-combiner'; +import { getAccessControlModuleRoute } from '../+admin/admin-routing-paths'; export const GROUP_EDIT_PATH = 'groups'; diff --git a/src/app/+admin/admin-access-control/admin-access-control-routing.module.ts b/src/app/admin-access-control/admin-access-control-routing.module.ts similarity index 100% rename from src/app/+admin/admin-access-control/admin-access-control-routing.module.ts rename to src/app/admin-access-control/admin-access-control-routing.module.ts diff --git a/src/app/+admin/admin-access-control/admin-access-control.module.ts b/src/app/admin-access-control/admin-access-control.module.ts similarity index 95% rename from src/app/+admin/admin-access-control/admin-access-control.module.ts rename to src/app/admin-access-control/admin-access-control.module.ts index 04051ff46c..c26191c376 100644 --- a/src/app/+admin/admin-access-control/admin-access-control.module.ts +++ b/src/app/admin-access-control/admin-access-control.module.ts @@ -1,7 +1,7 @@ import { CommonModule } from '@angular/common'; import { NgModule } from '@angular/core'; import { RouterModule } from '@angular/router'; -import { SharedModule } from '../../shared/shared.module'; +import { SharedModule } from '../shared/shared.module'; import { AdminAccessControlRoutingModule } from './admin-access-control-routing.module'; import { EPeopleRegistryComponent } from './epeople-registry/epeople-registry.component'; import { EPersonFormComponent } from './epeople-registry/eperson-form/eperson-form.component'; diff --git a/src/app/+admin/admin-access-control/epeople-registry/epeople-registry.actions.ts b/src/app/admin-access-control/epeople-registry/epeople-registry.actions.ts similarity index 91% rename from src/app/+admin/admin-access-control/epeople-registry/epeople-registry.actions.ts rename to src/app/admin-access-control/epeople-registry/epeople-registry.actions.ts index 000dc48263..b8b1044362 100644 --- a/src/app/+admin/admin-access-control/epeople-registry/epeople-registry.actions.ts +++ b/src/app/admin-access-control/epeople-registry/epeople-registry.actions.ts @@ -1,6 +1,6 @@ import { Action } from '@ngrx/store'; -import { EPerson } from '../../../core/eperson/models/eperson.model'; -import { type } from '../../../shared/ngrx/type'; +import { EPerson } from '../../core/eperson/models/eperson.model'; +import { type } from '../../shared/ngrx/type'; /** * For each action type in an action group, make a simple diff --git a/src/app/+admin/admin-access-control/epeople-registry/epeople-registry.component.html b/src/app/admin-access-control/epeople-registry/epeople-registry.component.html similarity index 100% rename from src/app/+admin/admin-access-control/epeople-registry/epeople-registry.component.html rename to src/app/admin-access-control/epeople-registry/epeople-registry.component.html diff --git a/src/app/+admin/admin-access-control/epeople-registry/epeople-registry.component.spec.ts b/src/app/admin-access-control/epeople-registry/epeople-registry.component.spec.ts similarity index 87% rename from src/app/+admin/admin-access-control/epeople-registry/epeople-registry.component.spec.ts rename to src/app/admin-access-control/epeople-registry/epeople-registry.component.spec.ts index c104de0b17..425a61ddb3 100644 --- a/src/app/+admin/admin-access-control/epeople-registry/epeople-registry.component.spec.ts +++ b/src/app/admin-access-control/epeople-registry/epeople-registry.component.spec.ts @@ -7,24 +7,24 @@ import { FormsModule, ReactiveFormsModule } from '@angular/forms'; import { BrowserModule, By } from '@angular/platform-browser'; import { NgbModule } from '@ng-bootstrap/ng-bootstrap'; import { TranslateLoader, TranslateModule, TranslateService } from '@ngx-translate/core'; -import { buildPaginatedList, PaginatedList } from '../../../core/data/paginated-list.model'; -import { RemoteData } from '../../../core/data/remote-data'; -import { FindListOptions } from '../../../core/data/request.models'; -import { EPersonDataService } from '../../../core/eperson/eperson-data.service'; -import { EPerson } from '../../../core/eperson/models/eperson.model'; -import { PageInfo } from '../../../core/shared/page-info.model'; -import { FormBuilderService } from '../../../shared/form/builder/form-builder.service'; -import { NotificationsService } from '../../../shared/notifications/notifications.service'; +import { buildPaginatedList, PaginatedList } from '../../core/data/paginated-list.model'; +import { RemoteData } from '../../core/data/remote-data'; +import { FindListOptions } from '../../core/data/request.models'; +import { EPersonDataService } from '../../core/eperson/eperson-data.service'; +import { EPerson } from '../../core/eperson/models/eperson.model'; +import { PageInfo } from '../../core/shared/page-info.model'; +import { FormBuilderService } from '../../shared/form/builder/form-builder.service'; +import { NotificationsService } from '../../shared/notifications/notifications.service'; import { EPeopleRegistryComponent } from './epeople-registry.component'; -import { EPersonMock, EPersonMock2 } from '../../../shared/testing/eperson.mock'; -import { createSuccessfulRemoteDataObject$ } from '../../../shared/remote-data.utils'; -import { getMockFormBuilderService } from '../../../shared/mocks/form-builder-service.mock'; -import { getMockTranslateService } from '../../../shared/mocks/translate.service.mock'; -import { TranslateLoaderMock } from '../../../shared/mocks/translate-loader.mock'; -import { NotificationsServiceStub } from '../../../shared/testing/notifications-service.stub'; -import { RouterStub } from '../../../shared/testing/router.stub'; -import { AuthorizationDataService } from '../../../core/data/feature-authorization/authorization-data.service'; -import { RequestService } from '../../../core/data/request.service'; +import { EPersonMock, EPersonMock2 } from '../../shared/testing/eperson.mock'; +import { createSuccessfulRemoteDataObject$ } from '../../shared/remote-data.utils'; +import { getMockFormBuilderService } from '../../shared/mocks/form-builder-service.mock'; +import { getMockTranslateService } from '../../shared/mocks/translate.service.mock'; +import { TranslateLoaderMock } from '../../shared/mocks/translate-loader.mock'; +import { NotificationsServiceStub } from '../../shared/testing/notifications-service.stub'; +import { RouterStub } from '../../shared/testing/router.stub'; +import { AuthorizationDataService } from '../../core/data/feature-authorization/authorization-data.service'; +import { RequestService } from '../../core/data/request.service'; describe('EPeopleRegistryComponent', () => { let component: EPeopleRegistryComponent; diff --git a/src/app/+admin/admin-access-control/epeople-registry/epeople-registry.component.ts b/src/app/admin-access-control/epeople-registry/epeople-registry.component.ts similarity index 88% rename from src/app/+admin/admin-access-control/epeople-registry/epeople-registry.component.ts rename to src/app/admin-access-control/epeople-registry/epeople-registry.component.ts index 11b146b294..3e9b137965 100644 --- a/src/app/+admin/admin-access-control/epeople-registry/epeople-registry.component.ts +++ b/src/app/admin-access-control/epeople-registry/epeople-registry.component.ts @@ -4,25 +4,25 @@ import { Router } from '@angular/router'; import { TranslateService } from '@ngx-translate/core'; import { BehaviorSubject, combineLatest, Observable, Subscription } from 'rxjs'; import { map, switchMap, take } from 'rxjs/operators'; -import { PaginatedList, buildPaginatedList } from '../../../core/data/paginated-list.model'; -import { RemoteData } from '../../../core/data/remote-data'; -import { EPersonDataService } from '../../../core/eperson/eperson-data.service'; -import { EPerson } from '../../../core/eperson/models/eperson.model'; -import { hasValue } from '../../../shared/empty.util'; -import { NotificationsService } from '../../../shared/notifications/notifications.service'; -import { PaginationComponentOptions } from '../../../shared/pagination/pagination-component-options.model'; -import { EpersonDtoModel } from '../../../core/eperson/models/eperson-dto.model'; -import { FeatureID } from '../../../core/data/feature-authorization/feature-id'; -import { AuthorizationDataService } from '../../../core/data/feature-authorization/authorization-data.service'; +import { PaginatedList, buildPaginatedList } from '../../core/data/paginated-list.model'; +import { RemoteData } from '../../core/data/remote-data'; +import { EPersonDataService } from '../../core/eperson/eperson-data.service'; +import { EPerson } from '../../core/eperson/models/eperson.model'; +import { hasValue } from '../../shared/empty.util'; +import { NotificationsService } from '../../shared/notifications/notifications.service'; +import { PaginationComponentOptions } from '../../shared/pagination/pagination-component-options.model'; +import { EpersonDtoModel } from '../../core/eperson/models/eperson-dto.model'; +import { FeatureID } from '../../core/data/feature-authorization/feature-id'; +import { AuthorizationDataService } from '../../core/data/feature-authorization/authorization-data.service'; import { getFirstCompletedRemoteData, getAllSucceededRemoteData -} from '../../../core/shared/operators'; -import { ConfirmationModalComponent } from '../../../shared/confirmation-modal/confirmation-modal.component'; +} from '../../core/shared/operators'; +import { ConfirmationModalComponent } from '../../shared/confirmation-modal/confirmation-modal.component'; import { NgbModal } from '@ng-bootstrap/ng-bootstrap'; -import { RequestService } from '../../../core/data/request.service'; -import { PageInfo } from '../../../core/shared/page-info.model'; -import { NoContent } from '../../../core/shared/NoContent.model'; +import { RequestService } from '../../core/data/request.service'; +import { PageInfo } from '../../core/shared/page-info.model'; +import { NoContent } from '../../core/shared/NoContent.model'; @Component({ selector: 'ds-epeople-registry', diff --git a/src/app/+admin/admin-access-control/epeople-registry/epeople-registry.reducers.spec.ts b/src/app/admin-access-control/epeople-registry/epeople-registry.reducers.spec.ts similarity index 96% rename from src/app/+admin/admin-access-control/epeople-registry/epeople-registry.reducers.spec.ts rename to src/app/admin-access-control/epeople-registry/epeople-registry.reducers.spec.ts index 87ab70a942..7158acc79b 100644 --- a/src/app/+admin/admin-access-control/epeople-registry/epeople-registry.reducers.spec.ts +++ b/src/app/admin-access-control/epeople-registry/epeople-registry.reducers.spec.ts @@ -1,6 +1,6 @@ import { EPeopleRegistryCancelEPersonAction, EPeopleRegistryEditEPersonAction } from './epeople-registry.actions'; import { ePeopleRegistryReducer, EPeopleRegistryState } from './epeople-registry.reducers'; -import { EPersonMock } from '../../../shared/testing/eperson.mock'; +import { EPersonMock } from '../../shared/testing/eperson.mock'; const initialState: EPeopleRegistryState = { editEPerson: null, diff --git a/src/app/+admin/admin-access-control/epeople-registry/epeople-registry.reducers.ts b/src/app/admin-access-control/epeople-registry/epeople-registry.reducers.ts similarity index 93% rename from src/app/+admin/admin-access-control/epeople-registry/epeople-registry.reducers.ts rename to src/app/admin-access-control/epeople-registry/epeople-registry.reducers.ts index 42b31d61e9..1e0319f3ba 100644 --- a/src/app/+admin/admin-access-control/epeople-registry/epeople-registry.reducers.ts +++ b/src/app/admin-access-control/epeople-registry/epeople-registry.reducers.ts @@ -1,4 +1,4 @@ -import { EPerson } from '../../../core/eperson/models/eperson.model'; +import { EPerson } from '../../core/eperson/models/eperson.model'; import { EPeopleRegistryAction, EPeopleRegistryActionTypes, diff --git a/src/app/+admin/admin-access-control/epeople-registry/eperson-form/eperson-form.component.html b/src/app/admin-access-control/epeople-registry/eperson-form/eperson-form.component.html similarity index 100% rename from src/app/+admin/admin-access-control/epeople-registry/eperson-form/eperson-form.component.html rename to src/app/admin-access-control/epeople-registry/eperson-form/eperson-form.component.html diff --git a/src/app/+admin/admin-access-control/epeople-registry/eperson-form/eperson-form.component.spec.ts b/src/app/admin-access-control/epeople-registry/eperson-form/eperson-form.component.spec.ts similarity index 87% rename from src/app/+admin/admin-access-control/epeople-registry/eperson-form/eperson-form.component.spec.ts rename to src/app/admin-access-control/epeople-registry/eperson-form/eperson-form.component.spec.ts index 1163490e12..454dad0018 100644 --- a/src/app/+admin/admin-access-control/epeople-registry/eperson-form/eperson-form.component.spec.ts +++ b/src/app/admin-access-control/epeople-registry/eperson-form/eperson-form.component.spec.ts @@ -6,26 +6,26 @@ import { FormsModule, ReactiveFormsModule } from '@angular/forms'; import { BrowserModule, By } from '@angular/platform-browser'; import { NgbModule } from '@ng-bootstrap/ng-bootstrap'; import { TranslateLoader, TranslateModule } from '@ngx-translate/core'; -import { buildPaginatedList, PaginatedList } from '../../../../core/data/paginated-list.model'; -import { RemoteData } from '../../../../core/data/remote-data'; -import { FindListOptions } from '../../../../core/data/request.models'; -import { EPersonDataService } from '../../../../core/eperson/eperson-data.service'; -import { EPerson } from '../../../../core/eperson/models/eperson.model'; -import { PageInfo } from '../../../../core/shared/page-info.model'; -import { FormBuilderService } from '../../../../shared/form/builder/form-builder.service'; -import { NotificationsService } from '../../../../shared/notifications/notifications.service'; +import { buildPaginatedList, PaginatedList } from '../../../core/data/paginated-list.model'; +import { RemoteData } from '../../../core/data/remote-data'; +import { FindListOptions } from '../../../core/data/request.models'; +import { EPersonDataService } from '../../../core/eperson/eperson-data.service'; +import { EPerson } from '../../../core/eperson/models/eperson.model'; +import { PageInfo } from '../../../core/shared/page-info.model'; +import { FormBuilderService } from '../../../shared/form/builder/form-builder.service'; +import { NotificationsService } from '../../../shared/notifications/notifications.service'; import { EPersonFormComponent } from './eperson-form.component'; -import { EPersonMock, EPersonMock2 } from '../../../../shared/testing/eperson.mock'; -import { createSuccessfulRemoteDataObject$ } from '../../../../shared/remote-data.utils'; -import { getMockFormBuilderService } from '../../../../shared/mocks/form-builder-service.mock'; -import { NotificationsServiceStub } from '../../../../shared/testing/notifications-service.stub'; -import { TranslateLoaderMock } from '../../../../shared/mocks/translate-loader.mock'; -import { AuthService } from '../../../../core/auth/auth.service'; -import { AuthServiceStub } from '../../../../shared/testing/auth-service.stub'; -import { AuthorizationDataService } from '../../../../core/data/feature-authorization/authorization-data.service'; -import { GroupDataService } from '../../../../core/eperson/group-data.service'; -import { createPaginatedList } from '../../../../shared/testing/utils.test'; -import { RequestService } from '../../../../core/data/request.service'; +import { EPersonMock, EPersonMock2 } from '../../../shared/testing/eperson.mock'; +import { createSuccessfulRemoteDataObject$ } from '../../../shared/remote-data.utils'; +import { getMockFormBuilderService } from '../../../shared/mocks/form-builder-service.mock'; +import { NotificationsServiceStub } from '../../../shared/testing/notifications-service.stub'; +import { TranslateLoaderMock } from '../../../shared/mocks/translate-loader.mock'; +import { AuthService } from '../../../core/auth/auth.service'; +import { AuthServiceStub } from '../../../shared/testing/auth-service.stub'; +import { AuthorizationDataService } from '../../../core/data/feature-authorization/authorization-data.service'; +import { GroupDataService } from '../../../core/eperson/group-data.service'; +import { createPaginatedList } from '../../../shared/testing/utils.test'; +import { RequestService } from '../../../core/data/request.service'; describe('EPersonFormComponent', () => { let component: EPersonFormComponent; diff --git a/src/app/+admin/admin-access-control/epeople-registry/eperson-form/eperson-form.component.ts b/src/app/admin-access-control/epeople-registry/eperson-form/eperson-form.component.ts similarity index 91% rename from src/app/+admin/admin-access-control/epeople-registry/eperson-form/eperson-form.component.ts rename to src/app/admin-access-control/epeople-registry/eperson-form/eperson-form.component.ts index 3c284735a9..ecb4606ae4 100644 --- a/src/app/+admin/admin-access-control/epeople-registry/eperson-form/eperson-form.component.ts +++ b/src/app/admin-access-control/epeople-registry/eperson-form/eperson-form.component.ts @@ -9,28 +9,28 @@ import { import { TranslateService } from '@ngx-translate/core'; import { combineLatest, Observable, of, Subscription } from 'rxjs'; import { switchMap, take } from 'rxjs/operators'; -import { 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 { Group } from '../../../../core/eperson/models/group.model'; +import { 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 { Group } from '../../../core/eperson/models/group.model'; import { getRemoteDataPayload, getFirstSucceededRemoteData, getFirstCompletedRemoteData -} from '../../../../core/shared/operators'; -import { hasValue } from '../../../../shared/empty.util'; -import { FormBuilderService } from '../../../../shared/form/builder/form-builder.service'; -import { NotificationsService } from '../../../../shared/notifications/notifications.service'; -import { PaginationComponentOptions } from '../../../../shared/pagination/pagination-component-options.model'; -import { AuthService } from '../../../../core/auth/auth.service'; -import { AuthorizationDataService } from '../../../../core/data/feature-authorization/authorization-data.service'; -import { FeatureID } from '../../../../core/data/feature-authorization/feature-id'; -import { ConfirmationModalComponent } from '../../../../shared/confirmation-modal/confirmation-modal.component'; +} from '../../../core/shared/operators'; +import { hasValue } from '../../../shared/empty.util'; +import { FormBuilderService } from '../../../shared/form/builder/form-builder.service'; +import { NotificationsService } from '../../../shared/notifications/notifications.service'; +import { PaginationComponentOptions } from '../../../shared/pagination/pagination-component-options.model'; +import { AuthService } from '../../../core/auth/auth.service'; +import { AuthorizationDataService } from '../../../core/data/feature-authorization/authorization-data.service'; +import { FeatureID } from '../../../core/data/feature-authorization/feature-id'; +import { ConfirmationModalComponent } from '../../../shared/confirmation-modal/confirmation-modal.component'; import { NgbModal } from '@ng-bootstrap/ng-bootstrap'; -import { RequestService } from '../../../../core/data/request.service'; -import { NoContent } from '../../../../core/shared/NoContent.model'; +import { RequestService } from '../../../core/data/request.service'; +import { NoContent } from '../../../core/shared/NoContent.model'; @Component({ selector: 'ds-eperson-form', diff --git a/src/app/+admin/admin-access-control/group-registry/group-form/group-form.component.html b/src/app/admin-access-control/group-registry/group-form/group-form.component.html similarity index 100% rename from src/app/+admin/admin-access-control/group-registry/group-form/group-form.component.html rename to src/app/admin-access-control/group-registry/group-form/group-form.component.html diff --git a/src/app/+admin/admin-access-control/group-registry/group-form/group-form.component.spec.ts b/src/app/admin-access-control/group-registry/group-form/group-form.component.spec.ts similarity index 77% rename from src/app/+admin/admin-access-control/group-registry/group-form/group-form.component.spec.ts rename to src/app/admin-access-control/group-registry/group-form/group-form.component.spec.ts index fd5edf0354..00fe2aa6e6 100644 --- a/src/app/+admin/admin-access-control/group-registry/group-form/group-form.component.spec.ts +++ b/src/app/admin-access-control/group-registry/group-form/group-form.component.spec.ts @@ -9,30 +9,30 @@ import { NgbModule } from '@ng-bootstrap/ng-bootstrap'; import { Store } from '@ngrx/store'; import { TranslateLoader, TranslateModule, TranslateService } from '@ngx-translate/core'; import { Observable, of as observableOf } from 'rxjs'; -import { RemoteDataBuildService } from '../../../../core/cache/builders/remote-data-build.service'; -import { ObjectCacheService } from '../../../../core/cache/object-cache.service'; -import { DSOChangeAnalyzer } from '../../../../core/data/dso-change-analyzer.service'; -import { DSpaceObjectDataService } from '../../../../core/data/dspace-object-data.service'; -import { AuthorizationDataService } from '../../../../core/data/feature-authorization/authorization-data.service'; -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 { Group } from '../../../../core/eperson/models/group.model'; -import { DSpaceObject } from '../../../../core/shared/dspace-object.model'; -import { HALEndpointService } from '../../../../core/shared/hal-endpoint.service'; -import { PageInfo } from '../../../../core/shared/page-info.model'; -import { UUIDService } from '../../../../core/shared/uuid.service'; -import { FormBuilderService } from '../../../../shared/form/builder/form-builder.service'; -import { NotificationsService } from '../../../../shared/notifications/notifications.service'; -import { GroupMock, GroupMock2 } from '../../../../shared/testing/group-mock'; +import { RemoteDataBuildService } from '../../../core/cache/builders/remote-data-build.service'; +import { ObjectCacheService } from '../../../core/cache/object-cache.service'; +import { DSOChangeAnalyzer } from '../../../core/data/dso-change-analyzer.service'; +import { DSpaceObjectDataService } from '../../../core/data/dspace-object-data.service'; +import { AuthorizationDataService } from '../../../core/data/feature-authorization/authorization-data.service'; +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 { Group } from '../../../core/eperson/models/group.model'; +import { DSpaceObject } from '../../../core/shared/dspace-object.model'; +import { HALEndpointService } from '../../../core/shared/hal-endpoint.service'; +import { PageInfo } from '../../../core/shared/page-info.model'; +import { UUIDService } from '../../../core/shared/uuid.service'; +import { FormBuilderService } from '../../../shared/form/builder/form-builder.service'; +import { NotificationsService } from '../../../shared/notifications/notifications.service'; +import { GroupMock, GroupMock2 } from '../../../shared/testing/group-mock'; import { GroupFormComponent } from './group-form.component'; -import { createSuccessfulRemoteDataObject$ } from '../../../../shared/remote-data.utils'; -import { getMockFormBuilderService } from '../../../../shared/mocks/form-builder-service.mock'; -import { getMockTranslateService } from '../../../../shared/mocks/translate.service.mock'; -import { TranslateLoaderMock } from '../../../../shared/testing/translate-loader.mock'; -import { RouterMock } from '../../../../shared/mocks/router.mock'; -import { NotificationsServiceStub } from '../../../../shared/testing/notifications-service.stub'; +import { createSuccessfulRemoteDataObject$ } from '../../../shared/remote-data.utils'; +import { getMockFormBuilderService } from '../../../shared/mocks/form-builder-service.mock'; +import { getMockTranslateService } from '../../../shared/mocks/translate.service.mock'; +import { TranslateLoaderMock } from '../../../shared/testing/translate-loader.mock'; +import { RouterMock } from '../../../shared/mocks/router.mock'; +import { NotificationsServiceStub } from '../../../shared/testing/notifications-service.stub'; import { Operation } from 'fast-json-patch'; describe('GroupFormComponent', () => { diff --git a/src/app/+admin/admin-access-control/group-registry/group-form/group-form.component.ts b/src/app/admin-access-control/group-registry/group-form/group-form.component.ts similarity index 89% rename from src/app/+admin/admin-access-control/group-registry/group-form/group-form.component.ts rename to src/app/admin-access-control/group-registry/group-form/group-form.component.ts index 7984fc50d1..2b834bde1d 100644 --- a/src/app/+admin/admin-access-control/group-registry/group-form/group-form.component.ts +++ b/src/app/admin-access-control/group-registry/group-form/group-form.component.ts @@ -17,32 +17,32 @@ import { Subscription } from 'rxjs'; import { catchError, map, switchMap, take } from 'rxjs/operators'; -import { getCollectionEditRolesRoute } from '../../../../+collection-page/collection-page-routing-paths'; -import { getCommunityEditRolesRoute } from '../../../../+community-page/community-page-routing-paths'; -import { DSpaceObjectDataService } from '../../../../core/data/dspace-object-data.service'; -import { AuthorizationDataService } from '../../../../core/data/feature-authorization/authorization-data.service'; -import { FeatureID } from '../../../../core/data/feature-authorization/feature-id'; -import { PaginatedList } from '../../../../core/data/paginated-list.model'; -import { RemoteData } from '../../../../core/data/remote-data'; -import { RequestService } from '../../../../core/data/request.service'; -import { EPersonDataService } from '../../../../core/eperson/eperson-data.service'; -import { GroupDataService } from '../../../../core/eperson/group-data.service'; -import { Group } from '../../../../core/eperson/models/group.model'; -import { Collection } from '../../../../core/shared/collection.model'; -import { Community } from '../../../../core/shared/community.model'; -import { DSpaceObject } from '../../../../core/shared/dspace-object.model'; +import { getCollectionEditRolesRoute } from '../../../+collection-page/collection-page-routing-paths'; +import { getCommunityEditRolesRoute } from '../../../+community-page/community-page-routing-paths'; +import { DSpaceObjectDataService } from '../../../core/data/dspace-object-data.service'; +import { AuthorizationDataService } from '../../../core/data/feature-authorization/authorization-data.service'; +import { FeatureID } from '../../../core/data/feature-authorization/feature-id'; +import { PaginatedList } from '../../../core/data/paginated-list.model'; +import { RemoteData } from '../../../core/data/remote-data'; +import { RequestService } from '../../../core/data/request.service'; +import { EPersonDataService } from '../../../core/eperson/eperson-data.service'; +import { GroupDataService } from '../../../core/eperson/group-data.service'; +import { Group } from '../../../core/eperson/models/group.model'; +import { Collection } from '../../../core/shared/collection.model'; +import { Community } from '../../../core/shared/community.model'; +import { DSpaceObject } from '../../../core/shared/dspace-object.model'; import { getRemoteDataPayload, getFirstSucceededRemoteData, getFirstCompletedRemoteData -} from '../../../../core/shared/operators'; -import { AlertType } from '../../../../shared/alert/aletr-type'; -import { ConfirmationModalComponent } from '../../../../shared/confirmation-modal/confirmation-modal.component'; -import { hasValue, isNotEmpty, hasValueOperator } from '../../../../shared/empty.util'; -import { FormBuilderService } from '../../../../shared/form/builder/form-builder.service'; -import { NotificationsService } from '../../../../shared/notifications/notifications.service'; -import { followLink } from '../../../../shared/utils/follow-link-config.model'; -import { NoContent } from '../../../../core/shared/NoContent.model'; +} from '../../../core/shared/operators'; +import { AlertType } from '../../../shared/alert/aletr-type'; +import { ConfirmationModalComponent } from '../../../shared/confirmation-modal/confirmation-modal.component'; +import { hasValue, isNotEmpty, hasValueOperator } from '../../../shared/empty.util'; +import { FormBuilderService } from '../../../shared/form/builder/form-builder.service'; +import { NotificationsService } from '../../../shared/notifications/notifications.service'; +import { followLink } from '../../../shared/utils/follow-link-config.model'; +import { NoContent } from '../../../core/shared/NoContent.model'; import { Operation } from 'fast-json-patch'; @Component({ diff --git a/src/app/+admin/admin-access-control/group-registry/group-form/members-list/members-list.component.html b/src/app/admin-access-control/group-registry/group-form/members-list/members-list.component.html similarity index 100% rename from src/app/+admin/admin-access-control/group-registry/group-form/members-list/members-list.component.html rename to src/app/admin-access-control/group-registry/group-form/members-list/members-list.component.html diff --git a/src/app/+admin/admin-access-control/group-registry/group-form/members-list/members-list.component.spec.ts b/src/app/admin-access-control/group-registry/group-form/members-list/members-list.component.spec.ts similarity index 85% rename from src/app/+admin/admin-access-control/group-registry/group-form/members-list/members-list.component.spec.ts rename to src/app/admin-access-control/group-registry/group-form/members-list/members-list.component.spec.ts index 10735cbde5..bb7fd48ec6 100644 --- a/src/app/+admin/admin-access-control/group-registry/group-form/members-list/members-list.component.spec.ts +++ b/src/app/admin-access-control/group-registry/group-form/members-list/members-list.component.spec.ts @@ -7,25 +7,25 @@ import { Router } from '@angular/router'; import { NgbModule } from '@ng-bootstrap/ng-bootstrap'; import { TranslateLoader, TranslateModule, TranslateService } from '@ngx-translate/core'; import { Observable, of as observableOf } from 'rxjs'; -import { RestResponse } from '../../../../../core/cache/response.models'; -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 { Group } from '../../../../../core/eperson/models/group.model'; -import { PageInfo } from '../../../../../core/shared/page-info.model'; -import { FormBuilderService } from '../../../../../shared/form/builder/form-builder.service'; -import { NotificationsService } from '../../../../../shared/notifications/notifications.service'; -import { GroupMock, GroupMock2 } from '../../../../../shared/testing/group-mock'; +import { RestResponse } from '../../../../core/cache/response.models'; +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 { Group } from '../../../../core/eperson/models/group.model'; +import { PageInfo } from '../../../../core/shared/page-info.model'; +import { FormBuilderService } from '../../../../shared/form/builder/form-builder.service'; +import { NotificationsService } from '../../../../shared/notifications/notifications.service'; +import { GroupMock, GroupMock2 } from '../../../../shared/testing/group-mock'; import { MembersListComponent } from './members-list.component'; -import { EPersonMock, EPersonMock2 } from '../../../../../shared/testing/eperson.mock'; -import { createSuccessfulRemoteDataObject$ } from '../../../../../shared/remote-data.utils'; -import { getMockTranslateService } from '../../../../../shared/mocks/translate.service.mock'; -import { getMockFormBuilderService } from '../../../../../shared/mocks/form-builder-service.mock'; -import { TranslateLoaderMock } from '../../../../../shared/testing/translate-loader.mock'; -import { NotificationsServiceStub } from '../../../../../shared/testing/notifications-service.stub'; -import { RouterMock } from '../../../../../shared/mocks/router.mock'; +import { EPersonMock, EPersonMock2 } from '../../../../shared/testing/eperson.mock'; +import { createSuccessfulRemoteDataObject$ } from '../../../../shared/remote-data.utils'; +import { getMockTranslateService } from '../../../../shared/mocks/translate.service.mock'; +import { getMockFormBuilderService } from '../../../../shared/mocks/form-builder-service.mock'; +import { TranslateLoaderMock } from '../../../../shared/testing/translate-loader.mock'; +import { NotificationsServiceStub } from '../../../../shared/testing/notifications-service.stub'; +import { RouterMock } from '../../../../shared/mocks/router.mock'; describe('MembersListComponent', () => { let component: MembersListComponent; diff --git a/src/app/+admin/admin-access-control/group-registry/group-form/members-list/members-list.component.ts b/src/app/admin-access-control/group-registry/group-form/members-list/members-list.component.ts similarity index 93% rename from src/app/+admin/admin-access-control/group-registry/group-form/members-list/members-list.component.ts rename to src/app/admin-access-control/group-registry/group-form/members-list/members-list.component.ts index f1d25725d6..475ee0de7f 100644 --- a/src/app/+admin/admin-access-control/group-registry/group-form/members-list/members-list.component.ts +++ b/src/app/admin-access-control/group-registry/group-form/members-list/members-list.component.ts @@ -10,20 +10,20 @@ import { combineLatest as observableCombineLatest, ObservedValueOf, } from 'rxjs'; import { map, mergeMap, switchMap, take } from 'rxjs/operators'; -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 { Group } from '../../../../../core/eperson/models/group.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 { Group } from '../../../../core/eperson/models/group.model'; import { getRemoteDataPayload, getFirstSucceededRemoteData, getFirstCompletedRemoteData, getAllCompletedRemoteData -} from '../../../../../core/shared/operators'; -import { NotificationsService } from '../../../../../shared/notifications/notifications.service'; -import { PaginationComponentOptions } from '../../../../../shared/pagination/pagination-component-options.model'; -import {EpersonDtoModel} from '../../../../../core/eperson/models/eperson-dto.model'; +} from '../../../../core/shared/operators'; +import { NotificationsService } from '../../../../shared/notifications/notifications.service'; +import { PaginationComponentOptions } from '../../../../shared/pagination/pagination-component-options.model'; +import {EpersonDtoModel} from '../../../../core/eperson/models/eperson-dto.model'; /** * Keys to keep track of specific subscriptions diff --git a/src/app/+admin/admin-access-control/group-registry/group-form/subgroup-list/subgroups-list.component.html b/src/app/admin-access-control/group-registry/group-form/subgroup-list/subgroups-list.component.html similarity index 100% rename from src/app/+admin/admin-access-control/group-registry/group-form/subgroup-list/subgroups-list.component.html rename to src/app/admin-access-control/group-registry/group-form/subgroup-list/subgroups-list.component.html diff --git a/src/app/+admin/admin-access-control/group-registry/group-form/subgroup-list/subgroups-list.component.spec.ts b/src/app/admin-access-control/group-registry/group-form/subgroup-list/subgroups-list.component.spec.ts similarity index 86% rename from src/app/+admin/admin-access-control/group-registry/group-form/subgroup-list/subgroups-list.component.spec.ts rename to src/app/admin-access-control/group-registry/group-form/subgroup-list/subgroups-list.component.spec.ts index 9841d2b02e..b8ba1e4f13 100644 --- a/src/app/+admin/admin-access-control/group-registry/group-form/subgroup-list/subgroups-list.component.spec.ts +++ b/src/app/admin-access-control/group-registry/group-form/subgroup-list/subgroups-list.component.spec.ts @@ -15,25 +15,25 @@ import { Router } from '@angular/router'; import { NgbModule } from '@ng-bootstrap/ng-bootstrap'; import { TranslateLoader, TranslateModule, TranslateService } from '@ngx-translate/core'; import { Observable, of as observableOf, BehaviorSubject } from 'rxjs'; -import { RestResponse } from '../../../../../core/cache/response.models'; -import { buildPaginatedList, PaginatedList } from '../../../../../core/data/paginated-list.model'; -import { RemoteData } from '../../../../../core/data/remote-data'; -import { GroupDataService } from '../../../../../core/eperson/group-data.service'; -import { Group } from '../../../../../core/eperson/models/group.model'; -import { PageInfo } from '../../../../../core/shared/page-info.model'; -import { FormBuilderService } from '../../../../../shared/form/builder/form-builder.service'; -import { NotificationsService } from '../../../../../shared/notifications/notifications.service'; -import { GroupMock, GroupMock2 } from '../../../../../shared/testing/group-mock'; +import { RestResponse } from '../../../../core/cache/response.models'; +import { buildPaginatedList, PaginatedList } from '../../../../core/data/paginated-list.model'; +import { RemoteData } from '../../../../core/data/remote-data'; +import { GroupDataService } from '../../../../core/eperson/group-data.service'; +import { Group } from '../../../../core/eperson/models/group.model'; +import { PageInfo } from '../../../../core/shared/page-info.model'; +import { FormBuilderService } from '../../../../shared/form/builder/form-builder.service'; +import { NotificationsService } from '../../../../shared/notifications/notifications.service'; +import { GroupMock, GroupMock2 } from '../../../../shared/testing/group-mock'; import { SubgroupsListComponent } from './subgroups-list.component'; import { createSuccessfulRemoteDataObject$, createSuccessfulRemoteDataObject -} from '../../../../../shared/remote-data.utils'; -import { RouterMock } from '../../../../../shared/mocks/router.mock'; -import { getMockFormBuilderService } from '../../../../../shared/mocks/form-builder-service.mock'; -import { getMockTranslateService } from '../../../../../shared/mocks/translate.service.mock'; -import { TranslateLoaderMock } from '../../../../../shared/testing/translate-loader.mock'; -import { NotificationsServiceStub } from '../../../../../shared/testing/notifications-service.stub'; +} from '../../../../shared/remote-data.utils'; +import { RouterMock } from '../../../../shared/mocks/router.mock'; +import { getMockFormBuilderService } from '../../../../shared/mocks/form-builder-service.mock'; +import { getMockTranslateService } from '../../../../shared/mocks/translate.service.mock'; +import { TranslateLoaderMock } from '../../../../shared/testing/translate-loader.mock'; +import { NotificationsServiceStub } from '../../../../shared/testing/notifications-service.stub'; import { map } from 'rxjs/operators'; describe('SubgroupsListComponent', () => { diff --git a/src/app/+admin/admin-access-control/group-registry/group-form/subgroup-list/subgroups-list.component.ts b/src/app/admin-access-control/group-registry/group-form/subgroup-list/subgroups-list.component.ts similarity index 93% rename from src/app/+admin/admin-access-control/group-registry/group-form/subgroup-list/subgroups-list.component.ts rename to src/app/admin-access-control/group-registry/group-form/subgroup-list/subgroups-list.component.ts index d754e71e4f..d9f03963d6 100644 --- a/src/app/+admin/admin-access-control/group-registry/group-form/subgroup-list/subgroups-list.component.ts +++ b/src/app/admin-access-control/group-registry/group-form/subgroup-list/subgroups-list.component.ts @@ -4,18 +4,18 @@ import { Router } from '@angular/router'; import { TranslateService } from '@ngx-translate/core'; import { Observable, of as observableOf, Subscription, BehaviorSubject } from 'rxjs'; import { map, mergeMap, take } from 'rxjs/operators'; -import { PaginatedList } from '../../../../../core/data/paginated-list.model'; -import { RemoteData } from '../../../../../core/data/remote-data'; -import { GroupDataService } from '../../../../../core/eperson/group-data.service'; -import { Group } from '../../../../../core/eperson/models/group.model'; +import { PaginatedList } from '../../../../core/data/paginated-list.model'; +import { RemoteData } from '../../../../core/data/remote-data'; +import { GroupDataService } from '../../../../core/eperson/group-data.service'; +import { Group } from '../../../../core/eperson/models/group.model'; import { getRemoteDataPayload, getFirstSucceededRemoteData, getFirstCompletedRemoteData -} from '../../../../../core/shared/operators'; -import { NotificationsService } from '../../../../../shared/notifications/notifications.service'; -import { PaginationComponentOptions } from '../../../../../shared/pagination/pagination-component-options.model'; -import { NoContent } from '../../../../../core/shared/NoContent.model'; +} from '../../../../core/shared/operators'; +import { NotificationsService } from '../../../../shared/notifications/notifications.service'; +import { PaginationComponentOptions } from '../../../../shared/pagination/pagination-component-options.model'; +import { NoContent } from '../../../../core/shared/NoContent.model'; /** * Keys to keep track of specific subscriptions diff --git a/src/app/+admin/admin-access-control/group-registry/group-registry.actions.ts b/src/app/admin-access-control/group-registry/group-registry.actions.ts similarity index 91% rename from src/app/+admin/admin-access-control/group-registry/group-registry.actions.ts rename to src/app/admin-access-control/group-registry/group-registry.actions.ts index b5ba3bc4b5..bc1c0b97a6 100644 --- a/src/app/+admin/admin-access-control/group-registry/group-registry.actions.ts +++ b/src/app/admin-access-control/group-registry/group-registry.actions.ts @@ -1,6 +1,6 @@ import { Action } from '@ngrx/store'; -import { Group } from '../../../core/eperson/models/group.model'; -import { type } from '../../../shared/ngrx/type'; +import { Group } from '../../core/eperson/models/group.model'; +import { type } from '../../shared/ngrx/type'; /** * For each action type in an action group, make a simple diff --git a/src/app/+admin/admin-access-control/group-registry/group-registry.reducers.spec.ts b/src/app/admin-access-control/group-registry/group-registry.reducers.spec.ts similarity index 96% rename from src/app/+admin/admin-access-control/group-registry/group-registry.reducers.spec.ts rename to src/app/admin-access-control/group-registry/group-registry.reducers.spec.ts index 6c9f9d327a..de5b65f5ba 100644 --- a/src/app/+admin/admin-access-control/group-registry/group-registry.reducers.spec.ts +++ b/src/app/admin-access-control/group-registry/group-registry.reducers.spec.ts @@ -1,4 +1,4 @@ -import { GroupMock } from '../../../shared/testing/group-mock'; +import { GroupMock } from '../../shared/testing/group-mock'; import { GroupRegistryCancelGroupAction, GroupRegistryEditGroupAction } from './group-registry.actions'; import { groupRegistryReducer, GroupRegistryState } from './group-registry.reducers'; diff --git a/src/app/+admin/admin-access-control/group-registry/group-registry.reducers.ts b/src/app/admin-access-control/group-registry/group-registry.reducers.ts similarity index 93% rename from src/app/+admin/admin-access-control/group-registry/group-registry.reducers.ts rename to src/app/admin-access-control/group-registry/group-registry.reducers.ts index eca6c282a7..8e288b7f3a 100644 --- a/src/app/+admin/admin-access-control/group-registry/group-registry.reducers.ts +++ b/src/app/admin-access-control/group-registry/group-registry.reducers.ts @@ -1,4 +1,4 @@ -import { Group } from '../../../core/eperson/models/group.model'; +import { Group } from '../../core/eperson/models/group.model'; import { GroupRegistryAction, GroupRegistryActionTypes, GroupRegistryEditGroupAction } from './group-registry.actions'; /** diff --git a/src/app/+admin/admin-access-control/group-registry/groups-registry.component.html b/src/app/admin-access-control/group-registry/groups-registry.component.html similarity index 100% rename from src/app/+admin/admin-access-control/group-registry/groups-registry.component.html rename to src/app/admin-access-control/group-registry/groups-registry.component.html diff --git a/src/app/+admin/admin-access-control/group-registry/groups-registry.component.spec.ts b/src/app/admin-access-control/group-registry/groups-registry.component.spec.ts similarity index 81% rename from src/app/+admin/admin-access-control/group-registry/groups-registry.component.spec.ts rename to src/app/admin-access-control/group-registry/groups-registry.component.spec.ts index dd08ea6772..c7d502eff6 100644 --- a/src/app/+admin/admin-access-control/group-registry/groups-registry.component.spec.ts +++ b/src/app/admin-access-control/group-registry/groups-registry.component.spec.ts @@ -7,27 +7,27 @@ import { Router } from '@angular/router'; import { NgbModule } from '@ng-bootstrap/ng-bootstrap'; import { TranslateLoader, TranslateModule } from '@ngx-translate/core'; import { Observable, of as observableOf } from 'rxjs'; -import { DSpaceObjectDataService } from '../../../core/data/dspace-object-data.service'; -import { AuthorizationDataService } from '../../../core/data/feature-authorization/authorization-data.service'; -import { buildPaginatedList, PaginatedList } from '../../../core/data/paginated-list.model'; -import { RemoteData } from '../../../core/data/remote-data'; -import { RequestService } from '../../../core/data/request.service'; -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 { Group } from '../../../core/eperson/models/group.model'; -import { RouteService } from '../../../core/services/route.service'; -import { DSpaceObject } from '../../../core/shared/dspace-object.model'; -import { PageInfo } from '../../../core/shared/page-info.model'; -import { NotificationsService } from '../../../shared/notifications/notifications.service'; -import { GroupMock, GroupMock2 } from '../../../shared/testing/group-mock'; +import { DSpaceObjectDataService } from '../../core/data/dspace-object-data.service'; +import { AuthorizationDataService } from '../../core/data/feature-authorization/authorization-data.service'; +import { buildPaginatedList, PaginatedList } from '../../core/data/paginated-list.model'; +import { RemoteData } from '../../core/data/remote-data'; +import { RequestService } from '../../core/data/request.service'; +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 { Group } from '../../core/eperson/models/group.model'; +import { RouteService } from '../../core/services/route.service'; +import { DSpaceObject } from '../../core/shared/dspace-object.model'; +import { PageInfo } from '../../core/shared/page-info.model'; +import { NotificationsService } from '../../shared/notifications/notifications.service'; +import { GroupMock, GroupMock2 } from '../../shared/testing/group-mock'; import { GroupsRegistryComponent } from './groups-registry.component'; -import { EPersonMock, EPersonMock2 } from '../../../shared/testing/eperson.mock'; -import { createSuccessfulRemoteDataObject$ } from '../../../shared/remote-data.utils'; -import { TranslateLoaderMock } from '../../../shared/testing/translate-loader.mock'; -import { NotificationsServiceStub } from '../../../shared/testing/notifications-service.stub'; -import { routeServiceStub } from '../../../shared/testing/route-service.stub'; -import { RouterMock } from '../../../shared/mocks/router.mock'; +import { EPersonMock, EPersonMock2 } from '../../shared/testing/eperson.mock'; +import { createSuccessfulRemoteDataObject$ } from '../../shared/remote-data.utils'; +import { TranslateLoaderMock } from '../../shared/testing/translate-loader.mock'; +import { NotificationsServiceStub } from '../../shared/testing/notifications-service.stub'; +import { routeServiceStub } from '../../shared/testing/route-service.stub'; +import { RouterMock } from '../../shared/mocks/router.mock'; describe('GroupRegistryComponent', () => { let component: GroupsRegistryComponent; diff --git a/src/app/+admin/admin-access-control/group-registry/groups-registry.component.ts b/src/app/admin-access-control/group-registry/groups-registry.component.ts similarity index 84% rename from src/app/+admin/admin-access-control/group-registry/groups-registry.component.ts rename to src/app/admin-access-control/group-registry/groups-registry.component.ts index 305da75eeb..bfe6d50c43 100644 --- a/src/app/+admin/admin-access-control/group-registry/groups-registry.component.ts +++ b/src/app/admin-access-control/group-registry/groups-registry.component.ts @@ -10,29 +10,29 @@ import { of as observableOf } from 'rxjs'; import { catchError, map, switchMap, take } from 'rxjs/operators'; -import { DSpaceObjectDataService } from '../../../core/data/dspace-object-data.service'; -import { AuthorizationDataService } from '../../../core/data/feature-authorization/authorization-data.service'; -import { FeatureID } from '../../../core/data/feature-authorization/feature-id'; -import { PaginatedList, buildPaginatedList } from '../../../core/data/paginated-list.model'; -import { RemoteData } from '../../../core/data/remote-data'; -import { RequestService } from '../../../core/data/request.service'; -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 { GroupDtoModel } from '../../../core/eperson/models/group-dto.model'; -import { Group } from '../../../core/eperson/models/group.model'; -import { RouteService } from '../../../core/services/route.service'; -import { DSpaceObject } from '../../../core/shared/dspace-object.model'; +import { DSpaceObjectDataService } from '../../core/data/dspace-object-data.service'; +import { AuthorizationDataService } from '../../core/data/feature-authorization/authorization-data.service'; +import { FeatureID } from '../../core/data/feature-authorization/feature-id'; +import { PaginatedList, buildPaginatedList } from '../../core/data/paginated-list.model'; +import { RemoteData } from '../../core/data/remote-data'; +import { RequestService } from '../../core/data/request.service'; +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 { GroupDtoModel } from '../../core/eperson/models/group-dto.model'; +import { Group } from '../../core/eperson/models/group.model'; +import { RouteService } from '../../core/services/route.service'; +import { DSpaceObject } from '../../core/shared/dspace-object.model'; import { getAllSucceededRemoteDataPayload, getFirstCompletedRemoteData, getFirstSucceededRemoteData -} from '../../../core/shared/operators'; -import { PageInfo } from '../../../core/shared/page-info.model'; -import { hasValue } from '../../../shared/empty.util'; -import { NotificationsService } from '../../../shared/notifications/notifications.service'; -import { PaginationComponentOptions } from '../../../shared/pagination/pagination-component-options.model'; -import { NoContent } from '../../../core/shared/NoContent.model'; +} from '../../core/shared/operators'; +import { PageInfo } from '../../core/shared/page-info.model'; +import { hasValue } from '../../shared/empty.util'; +import { NotificationsService } from '../../shared/notifications/notifications.service'; +import { PaginationComponentOptions } from '../../shared/pagination/pagination-component-options.model'; +import { NoContent } from '../../core/shared/NoContent.model'; @Component({ selector: 'ds-groups-registry', diff --git a/src/app/app.reducer.ts b/src/app/app.reducer.ts index 813b8d0f4f..dceb779fad 100644 --- a/src/app/app.reducer.ts +++ b/src/app/app.reducer.ts @@ -3,11 +3,11 @@ import { ActionReducerMap, createSelector, MemoizedSelector } from '@ngrx/store' import { ePeopleRegistryReducer, EPeopleRegistryState -} from './+admin/admin-access-control/epeople-registry/epeople-registry.reducers'; +} from './admin-access-control/epeople-registry/epeople-registry.reducers'; import { groupRegistryReducer, GroupRegistryState -} from './+admin/admin-access-control/group-registry/group-registry.reducers'; +} from './admin-access-control/group-registry/group-registry.reducers'; import { metadataRegistryReducer, MetadataRegistryState diff --git a/src/app/core/eperson/eperson-data.service.spec.ts b/src/app/core/eperson/eperson-data.service.spec.ts index 3af02b267b..f403dd4cc0 100644 --- a/src/app/core/eperson/eperson-data.service.spec.ts +++ b/src/app/core/eperson/eperson-data.service.spec.ts @@ -10,7 +10,7 @@ import { TestScheduler } from 'rxjs/testing'; import { EPeopleRegistryCancelEPersonAction, EPeopleRegistryEditEPersonAction -} from '../../+admin/admin-access-control/epeople-registry/epeople-registry.actions'; +} from '../../admin-access-control/epeople-registry/epeople-registry.actions'; import { RequestParam } from '../cache/models/request-param.model'; import { CoreState } from '../core.reducers'; import { ChangeAnalyzer } from '../data/change-analyzer'; diff --git a/src/app/core/eperson/eperson-data.service.ts b/src/app/core/eperson/eperson-data.service.ts index 79df246833..152b3c3c11 100644 --- a/src/app/core/eperson/eperson-data.service.ts +++ b/src/app/core/eperson/eperson-data.service.ts @@ -7,8 +7,8 @@ import { find, map, take } from 'rxjs/operators'; import { EPeopleRegistryCancelEPersonAction, EPeopleRegistryEditEPersonAction -} from '../../+admin/admin-access-control/epeople-registry/epeople-registry.actions'; -import { EPeopleRegistryState } from '../../+admin/admin-access-control/epeople-registry/epeople-registry.reducers'; +} from '../../admin-access-control/epeople-registry/epeople-registry.actions'; +import { EPeopleRegistryState } from '../../admin-access-control/epeople-registry/epeople-registry.reducers'; import { AppState } from '../../app.reducer'; import { hasValue, hasNoValue } from '../../shared/empty.util'; import { NotificationsService } from '../../shared/notifications/notifications.service'; diff --git a/src/app/core/eperson/group-data.service.spec.ts b/src/app/core/eperson/group-data.service.spec.ts index f77c831b55..b39a58c83d 100644 --- a/src/app/core/eperson/group-data.service.spec.ts +++ b/src/app/core/eperson/group-data.service.spec.ts @@ -8,7 +8,7 @@ import { compare, Operation } from 'fast-json-patch'; import { GroupRegistryCancelGroupAction, GroupRegistryEditGroupAction -} from '../../+admin/admin-access-control/group-registry/group-registry.actions'; +} from '../../admin-access-control/group-registry/group-registry.actions'; import { GroupMock, GroupMock2 } from '../../shared/testing/group-mock'; import { RequestParam } from '../cache/models/request-param.model'; import { CoreState } from '../core.reducers'; diff --git a/src/app/core/eperson/group-data.service.ts b/src/app/core/eperson/group-data.service.ts index dc5fd97d9a..3e5424b376 100644 --- a/src/app/core/eperson/group-data.service.ts +++ b/src/app/core/eperson/group-data.service.ts @@ -7,8 +7,8 @@ import { filter, map, take } from 'rxjs/operators'; import { GroupRegistryCancelGroupAction, GroupRegistryEditGroupAction -} from '../../+admin/admin-access-control/group-registry/group-registry.actions'; -import { GroupRegistryState } from '../../+admin/admin-access-control/group-registry/group-registry.reducers'; +} from '../../admin-access-control/group-registry/group-registry.actions'; +import { GroupRegistryState } from '../../admin-access-control/group-registry/group-registry.reducers'; import { AppState } from '../../app.reducer'; import { NotificationsService } from '../../shared/notifications/notifications.service'; import { FollowLinkConfig } from '../../shared/utils/follow-link-config.model'; diff --git a/src/app/shared/comcol-forms/edit-comcol-page/comcol-role/comcol-role.component.ts b/src/app/shared/comcol-forms/edit-comcol-page/comcol-role/comcol-role.component.ts index 7ec422e69d..65a0881fc7 100644 --- a/src/app/shared/comcol-forms/edit-comcol-page/comcol-role/comcol-role.component.ts +++ b/src/app/shared/comcol-forms/edit-comcol-page/comcol-role/comcol-role.component.ts @@ -9,7 +9,7 @@ import { getAllCompletedRemoteData, getFirstCompletedRemoteData } from '../../.. import { RequestService } from '../../../../core/data/request.service'; import { RemoteData } from '../../../../core/data/remote-data'; import { HALLink } from '../../../../core/shared/hal-link.model'; -import { getGroupEditRoute } from '../../../../+admin/admin-access-control/admin-access-control-routing-paths'; +import { getGroupEditRoute } from '../../../../admin-access-control/admin-access-control-routing-paths'; import { hasNoValue, hasValue } from '../../../empty.util'; import { NoContent } from '../../../../core/shared/NoContent.model'; diff --git a/src/app/shared/resource-policies/resource-policies.component.ts b/src/app/shared/resource-policies/resource-policies.component.ts index d52d7a0799..38981b4f05 100644 --- a/src/app/shared/resource-policies/resource-policies.component.ts +++ b/src/app/shared/resource-policies/resource-policies.component.ts @@ -32,7 +32,7 @@ import { NotificationsService } from '../notifications/notifications.service'; import { dateToString, stringToNgbDateStruct } from '../date.util'; import { followLink } from '../utils/follow-link-config.model'; import { ADMIN_MODULE_PATH } from '../../app-routing-paths'; -import { GROUP_EDIT_PATH } from '../../+admin/admin-access-control/admin-access-control-routing-paths'; +import { GROUP_EDIT_PATH } from '../../admin-access-control/admin-access-control-routing-paths'; import { ACCESS_CONTROL_MODULE_PATH } from '../../+admin/admin-routing-paths'; interface ResourcePolicyCheckboxEntry { From d9eb05d40efdc3b7d734d716a5af425e3fbc36b3 Mon Sep 17 00:00:00 2001 From: Yura Bondarenko Date: Thu, 25 Feb 2021 13:39:07 +0100 Subject: [PATCH 044/132] 77205: Refactor admin-access-control to access-control --- src/app/+admin/admin-routing.module.ts | 4 ++-- src/app/+admin/admin.module.ts | 4 ++-- .../access-control-routing-paths.ts} | 0 .../access-control-routing.module.ts} | 4 ++-- .../access-control.module.ts} | 6 +++--- .../epeople-registry/epeople-registry.actions.ts | 0 .../epeople-registry/epeople-registry.component.html | 0 .../epeople-registry/epeople-registry.component.spec.ts | 0 .../epeople-registry/epeople-registry.component.ts | 0 .../epeople-registry/epeople-registry.reducers.spec.ts | 0 .../epeople-registry/epeople-registry.reducers.ts | 0 .../eperson-form/eperson-form.component.html | 0 .../eperson-form/eperson-form.component.spec.ts | 0 .../epeople-registry/eperson-form/eperson-form.component.ts | 0 .../group-registry/group-form/group-form.component.html | 0 .../group-registry/group-form/group-form.component.spec.ts | 0 .../group-registry/group-form/group-form.component.ts | 0 .../group-form/members-list/members-list.component.html | 0 .../group-form/members-list/members-list.component.spec.ts | 0 .../group-form/members-list/members-list.component.ts | 0 .../group-form/subgroup-list/subgroups-list.component.html | 0 .../subgroup-list/subgroups-list.component.spec.ts | 0 .../group-form/subgroup-list/subgroups-list.component.ts | 0 .../group-registry/group-registry.actions.ts | 0 .../group-registry/group-registry.reducers.spec.ts | 0 .../group-registry/group-registry.reducers.ts | 0 .../group-registry/groups-registry.component.html | 0 .../group-registry/groups-registry.component.spec.ts | 0 .../group-registry/groups-registry.component.ts | 0 src/app/app.reducer.ts | 4 ++-- src/app/core/eperson/eperson-data.service.spec.ts | 2 +- src/app/core/eperson/eperson-data.service.ts | 4 ++-- src/app/core/eperson/group-data.service.spec.ts | 2 +- src/app/core/eperson/group-data.service.ts | 4 ++-- .../edit-comcol-page/comcol-role/comcol-role.component.ts | 2 +- .../shared/resource-policies/resource-policies.component.ts | 2 +- 36 files changed, 19 insertions(+), 19 deletions(-) rename src/app/{admin-access-control/admin-access-control-routing-paths.ts => access-control/access-control-routing-paths.ts} (100%) rename src/app/{admin-access-control/admin-access-control-routing.module.ts => access-control/access-control-routing.module.ts} (90%) rename src/app/{admin-access-control/admin-access-control.module.ts => access-control/access-control.module.ts} (87%) rename src/app/{admin-access-control => access-control}/epeople-registry/epeople-registry.actions.ts (100%) rename src/app/{admin-access-control => access-control}/epeople-registry/epeople-registry.component.html (100%) rename src/app/{admin-access-control => access-control}/epeople-registry/epeople-registry.component.spec.ts (100%) rename src/app/{admin-access-control => access-control}/epeople-registry/epeople-registry.component.ts (100%) rename src/app/{admin-access-control => access-control}/epeople-registry/epeople-registry.reducers.spec.ts (100%) rename src/app/{admin-access-control => access-control}/epeople-registry/epeople-registry.reducers.ts (100%) rename src/app/{admin-access-control => access-control}/epeople-registry/eperson-form/eperson-form.component.html (100%) rename src/app/{admin-access-control => access-control}/epeople-registry/eperson-form/eperson-form.component.spec.ts (100%) rename src/app/{admin-access-control => access-control}/epeople-registry/eperson-form/eperson-form.component.ts (100%) rename src/app/{admin-access-control => access-control}/group-registry/group-form/group-form.component.html (100%) rename src/app/{admin-access-control => access-control}/group-registry/group-form/group-form.component.spec.ts (100%) rename src/app/{admin-access-control => access-control}/group-registry/group-form/group-form.component.ts (100%) rename src/app/{admin-access-control => access-control}/group-registry/group-form/members-list/members-list.component.html (100%) rename src/app/{admin-access-control => access-control}/group-registry/group-form/members-list/members-list.component.spec.ts (100%) rename src/app/{admin-access-control => access-control}/group-registry/group-form/members-list/members-list.component.ts (100%) rename src/app/{admin-access-control => access-control}/group-registry/group-form/subgroup-list/subgroups-list.component.html (100%) rename src/app/{admin-access-control => access-control}/group-registry/group-form/subgroup-list/subgroups-list.component.spec.ts (100%) rename src/app/{admin-access-control => access-control}/group-registry/group-form/subgroup-list/subgroups-list.component.ts (100%) rename src/app/{admin-access-control => access-control}/group-registry/group-registry.actions.ts (100%) rename src/app/{admin-access-control => access-control}/group-registry/group-registry.reducers.spec.ts (100%) rename src/app/{admin-access-control => access-control}/group-registry/group-registry.reducers.ts (100%) rename src/app/{admin-access-control => access-control}/group-registry/groups-registry.component.html (100%) rename src/app/{admin-access-control => access-control}/group-registry/groups-registry.component.spec.ts (100%) rename src/app/{admin-access-control => access-control}/group-registry/groups-registry.component.ts (100%) diff --git a/src/app/+admin/admin-routing.module.ts b/src/app/+admin/admin-routing.module.ts index 5094201841..a5c844a118 100644 --- a/src/app/+admin/admin-routing.module.ts +++ b/src/app/+admin/admin-routing.module.ts @@ -18,8 +18,8 @@ import { ACCESS_CONTROL_MODULE_PATH, REGISTRIES_MODULE_PATH } from './admin-rout }, { path: ACCESS_CONTROL_MODULE_PATH, - loadChildren: () => import('../admin-access-control/admin-access-control.module') - .then((m) => m.AdminAccessControlModule), + loadChildren: () => import('../access-control/access-control.module') + .then((m) => m.AccessControlModule), }, { path: 'search', diff --git a/src/app/+admin/admin.module.ts b/src/app/+admin/admin.module.ts index a1a5caaf99..25cdd67dcf 100644 --- a/src/app/+admin/admin.module.ts +++ b/src/app/+admin/admin.module.ts @@ -1,6 +1,6 @@ import { NgModule } from '@angular/core'; import { SharedModule } from '../shared/shared.module'; -import { AdminAccessControlModule } from '../admin-access-control/admin-access-control.module'; +import { AccessControlModule } from '../access-control/access-control.module'; import { MetadataImportPageComponent } from './admin-import-metadata-page/metadata-import-page.component'; import { AdminRegistriesModule } from './admin-registries/admin-registries.module'; import { AdminRoutingModule } from './admin-routing.module'; @@ -21,7 +21,7 @@ const ENTRY_COMPONENTS = [ imports: [ AdminRoutingModule, AdminRegistriesModule, - AdminAccessControlModule, + AccessControlModule, AdminSearchModule.withEntryComponents(), AdminWorkflowModuleModule.withEntryComponents(), SharedModule, diff --git a/src/app/admin-access-control/admin-access-control-routing-paths.ts b/src/app/access-control/access-control-routing-paths.ts similarity index 100% rename from src/app/admin-access-control/admin-access-control-routing-paths.ts rename to src/app/access-control/access-control-routing-paths.ts diff --git a/src/app/admin-access-control/admin-access-control-routing.module.ts b/src/app/access-control/access-control-routing.module.ts similarity index 90% rename from src/app/admin-access-control/admin-access-control-routing.module.ts rename to src/app/access-control/access-control-routing.module.ts index 10ac117b0f..2dbba19f70 100644 --- a/src/app/admin-access-control/admin-access-control-routing.module.ts +++ b/src/app/access-control/access-control-routing.module.ts @@ -3,7 +3,7 @@ import { RouterModule } from '@angular/router'; import { EPeopleRegistryComponent } from './epeople-registry/epeople-registry.component'; import { GroupFormComponent } from './group-registry/group-form/group-form.component'; import { GroupsRegistryComponent } from './group-registry/groups-registry.component'; -import { GROUP_EDIT_PATH } from './admin-access-control-routing-paths'; +import { GROUP_EDIT_PATH } from './access-control-routing-paths'; @NgModule({ imports: [ @@ -26,6 +26,6 @@ import { GROUP_EDIT_PATH } from './admin-access-control-routing-paths'; /** * Routing module for the AccessControl section of the admin sidebar */ -export class AdminAccessControlRoutingModule { +export class AccessControlRoutingModule { } diff --git a/src/app/admin-access-control/admin-access-control.module.ts b/src/app/access-control/access-control.module.ts similarity index 87% rename from src/app/admin-access-control/admin-access-control.module.ts rename to src/app/access-control/access-control.module.ts index c26191c376..0e872458bd 100644 --- a/src/app/admin-access-control/admin-access-control.module.ts +++ b/src/app/access-control/access-control.module.ts @@ -2,7 +2,7 @@ import { CommonModule } from '@angular/common'; import { NgModule } from '@angular/core'; import { RouterModule } from '@angular/router'; import { SharedModule } from '../shared/shared.module'; -import { AdminAccessControlRoutingModule } from './admin-access-control-routing.module'; +import { AccessControlRoutingModule } from './access-control-routing.module'; import { EPeopleRegistryComponent } from './epeople-registry/epeople-registry.component'; import { EPersonFormComponent } from './epeople-registry/eperson-form/eperson-form.component'; import { GroupFormComponent } from './group-registry/group-form/group-form.component'; @@ -15,7 +15,7 @@ import { GroupsRegistryComponent } from './group-registry/groups-registry.compon CommonModule, SharedModule, RouterModule, - AdminAccessControlRoutingModule + AccessControlRoutingModule ], declarations: [ EPeopleRegistryComponent, @@ -29,6 +29,6 @@ import { GroupsRegistryComponent } from './group-registry/groups-registry.compon /** * This module handles all components related to the access control pages */ -export class AdminAccessControlModule { +export class AccessControlModule { } diff --git a/src/app/admin-access-control/epeople-registry/epeople-registry.actions.ts b/src/app/access-control/epeople-registry/epeople-registry.actions.ts similarity index 100% rename from src/app/admin-access-control/epeople-registry/epeople-registry.actions.ts rename to src/app/access-control/epeople-registry/epeople-registry.actions.ts diff --git a/src/app/admin-access-control/epeople-registry/epeople-registry.component.html b/src/app/access-control/epeople-registry/epeople-registry.component.html similarity index 100% rename from src/app/admin-access-control/epeople-registry/epeople-registry.component.html rename to src/app/access-control/epeople-registry/epeople-registry.component.html diff --git a/src/app/admin-access-control/epeople-registry/epeople-registry.component.spec.ts b/src/app/access-control/epeople-registry/epeople-registry.component.spec.ts similarity index 100% rename from src/app/admin-access-control/epeople-registry/epeople-registry.component.spec.ts rename to src/app/access-control/epeople-registry/epeople-registry.component.spec.ts diff --git a/src/app/admin-access-control/epeople-registry/epeople-registry.component.ts b/src/app/access-control/epeople-registry/epeople-registry.component.ts similarity index 100% rename from src/app/admin-access-control/epeople-registry/epeople-registry.component.ts rename to src/app/access-control/epeople-registry/epeople-registry.component.ts diff --git a/src/app/admin-access-control/epeople-registry/epeople-registry.reducers.spec.ts b/src/app/access-control/epeople-registry/epeople-registry.reducers.spec.ts similarity index 100% rename from src/app/admin-access-control/epeople-registry/epeople-registry.reducers.spec.ts rename to src/app/access-control/epeople-registry/epeople-registry.reducers.spec.ts diff --git a/src/app/admin-access-control/epeople-registry/epeople-registry.reducers.ts b/src/app/access-control/epeople-registry/epeople-registry.reducers.ts similarity index 100% rename from src/app/admin-access-control/epeople-registry/epeople-registry.reducers.ts rename to src/app/access-control/epeople-registry/epeople-registry.reducers.ts diff --git a/src/app/admin-access-control/epeople-registry/eperson-form/eperson-form.component.html b/src/app/access-control/epeople-registry/eperson-form/eperson-form.component.html similarity index 100% rename from src/app/admin-access-control/epeople-registry/eperson-form/eperson-form.component.html rename to src/app/access-control/epeople-registry/eperson-form/eperson-form.component.html diff --git a/src/app/admin-access-control/epeople-registry/eperson-form/eperson-form.component.spec.ts b/src/app/access-control/epeople-registry/eperson-form/eperson-form.component.spec.ts similarity index 100% rename from src/app/admin-access-control/epeople-registry/eperson-form/eperson-form.component.spec.ts rename to src/app/access-control/epeople-registry/eperson-form/eperson-form.component.spec.ts diff --git a/src/app/admin-access-control/epeople-registry/eperson-form/eperson-form.component.ts b/src/app/access-control/epeople-registry/eperson-form/eperson-form.component.ts similarity index 100% rename from src/app/admin-access-control/epeople-registry/eperson-form/eperson-form.component.ts rename to src/app/access-control/epeople-registry/eperson-form/eperson-form.component.ts diff --git a/src/app/admin-access-control/group-registry/group-form/group-form.component.html b/src/app/access-control/group-registry/group-form/group-form.component.html similarity index 100% rename from src/app/admin-access-control/group-registry/group-form/group-form.component.html rename to src/app/access-control/group-registry/group-form/group-form.component.html diff --git a/src/app/admin-access-control/group-registry/group-form/group-form.component.spec.ts b/src/app/access-control/group-registry/group-form/group-form.component.spec.ts similarity index 100% rename from src/app/admin-access-control/group-registry/group-form/group-form.component.spec.ts rename to src/app/access-control/group-registry/group-form/group-form.component.spec.ts diff --git a/src/app/admin-access-control/group-registry/group-form/group-form.component.ts b/src/app/access-control/group-registry/group-form/group-form.component.ts similarity index 100% rename from src/app/admin-access-control/group-registry/group-form/group-form.component.ts rename to src/app/access-control/group-registry/group-form/group-form.component.ts diff --git a/src/app/admin-access-control/group-registry/group-form/members-list/members-list.component.html b/src/app/access-control/group-registry/group-form/members-list/members-list.component.html similarity index 100% rename from src/app/admin-access-control/group-registry/group-form/members-list/members-list.component.html rename to src/app/access-control/group-registry/group-form/members-list/members-list.component.html diff --git a/src/app/admin-access-control/group-registry/group-form/members-list/members-list.component.spec.ts b/src/app/access-control/group-registry/group-form/members-list/members-list.component.spec.ts similarity index 100% rename from src/app/admin-access-control/group-registry/group-form/members-list/members-list.component.spec.ts rename to src/app/access-control/group-registry/group-form/members-list/members-list.component.spec.ts diff --git a/src/app/admin-access-control/group-registry/group-form/members-list/members-list.component.ts b/src/app/access-control/group-registry/group-form/members-list/members-list.component.ts similarity index 100% rename from src/app/admin-access-control/group-registry/group-form/members-list/members-list.component.ts rename to src/app/access-control/group-registry/group-form/members-list/members-list.component.ts diff --git a/src/app/admin-access-control/group-registry/group-form/subgroup-list/subgroups-list.component.html b/src/app/access-control/group-registry/group-form/subgroup-list/subgroups-list.component.html similarity index 100% rename from src/app/admin-access-control/group-registry/group-form/subgroup-list/subgroups-list.component.html rename to src/app/access-control/group-registry/group-form/subgroup-list/subgroups-list.component.html diff --git a/src/app/admin-access-control/group-registry/group-form/subgroup-list/subgroups-list.component.spec.ts b/src/app/access-control/group-registry/group-form/subgroup-list/subgroups-list.component.spec.ts similarity index 100% rename from src/app/admin-access-control/group-registry/group-form/subgroup-list/subgroups-list.component.spec.ts rename to src/app/access-control/group-registry/group-form/subgroup-list/subgroups-list.component.spec.ts diff --git a/src/app/admin-access-control/group-registry/group-form/subgroup-list/subgroups-list.component.ts b/src/app/access-control/group-registry/group-form/subgroup-list/subgroups-list.component.ts similarity index 100% rename from src/app/admin-access-control/group-registry/group-form/subgroup-list/subgroups-list.component.ts rename to src/app/access-control/group-registry/group-form/subgroup-list/subgroups-list.component.ts diff --git a/src/app/admin-access-control/group-registry/group-registry.actions.ts b/src/app/access-control/group-registry/group-registry.actions.ts similarity index 100% rename from src/app/admin-access-control/group-registry/group-registry.actions.ts rename to src/app/access-control/group-registry/group-registry.actions.ts diff --git a/src/app/admin-access-control/group-registry/group-registry.reducers.spec.ts b/src/app/access-control/group-registry/group-registry.reducers.spec.ts similarity index 100% rename from src/app/admin-access-control/group-registry/group-registry.reducers.spec.ts rename to src/app/access-control/group-registry/group-registry.reducers.spec.ts diff --git a/src/app/admin-access-control/group-registry/group-registry.reducers.ts b/src/app/access-control/group-registry/group-registry.reducers.ts similarity index 100% rename from src/app/admin-access-control/group-registry/group-registry.reducers.ts rename to src/app/access-control/group-registry/group-registry.reducers.ts diff --git a/src/app/admin-access-control/group-registry/groups-registry.component.html b/src/app/access-control/group-registry/groups-registry.component.html similarity index 100% rename from src/app/admin-access-control/group-registry/groups-registry.component.html rename to src/app/access-control/group-registry/groups-registry.component.html diff --git a/src/app/admin-access-control/group-registry/groups-registry.component.spec.ts b/src/app/access-control/group-registry/groups-registry.component.spec.ts similarity index 100% rename from src/app/admin-access-control/group-registry/groups-registry.component.spec.ts rename to src/app/access-control/group-registry/groups-registry.component.spec.ts diff --git a/src/app/admin-access-control/group-registry/groups-registry.component.ts b/src/app/access-control/group-registry/groups-registry.component.ts similarity index 100% rename from src/app/admin-access-control/group-registry/groups-registry.component.ts rename to src/app/access-control/group-registry/groups-registry.component.ts diff --git a/src/app/app.reducer.ts b/src/app/app.reducer.ts index dceb779fad..ab0c31b41c 100644 --- a/src/app/app.reducer.ts +++ b/src/app/app.reducer.ts @@ -3,11 +3,11 @@ import { ActionReducerMap, createSelector, MemoizedSelector } from '@ngrx/store' import { ePeopleRegistryReducer, EPeopleRegistryState -} from './admin-access-control/epeople-registry/epeople-registry.reducers'; +} from './access-control/epeople-registry/epeople-registry.reducers'; import { groupRegistryReducer, GroupRegistryState -} from './admin-access-control/group-registry/group-registry.reducers'; +} from './access-control/group-registry/group-registry.reducers'; import { metadataRegistryReducer, MetadataRegistryState diff --git a/src/app/core/eperson/eperson-data.service.spec.ts b/src/app/core/eperson/eperson-data.service.spec.ts index f403dd4cc0..cd7b664379 100644 --- a/src/app/core/eperson/eperson-data.service.spec.ts +++ b/src/app/core/eperson/eperson-data.service.spec.ts @@ -10,7 +10,7 @@ import { TestScheduler } from 'rxjs/testing'; import { EPeopleRegistryCancelEPersonAction, EPeopleRegistryEditEPersonAction -} from '../../admin-access-control/epeople-registry/epeople-registry.actions'; +} from '../../access-control/epeople-registry/epeople-registry.actions'; import { RequestParam } from '../cache/models/request-param.model'; import { CoreState } from '../core.reducers'; import { ChangeAnalyzer } from '../data/change-analyzer'; diff --git a/src/app/core/eperson/eperson-data.service.ts b/src/app/core/eperson/eperson-data.service.ts index 152b3c3c11..5b52510ddd 100644 --- a/src/app/core/eperson/eperson-data.service.ts +++ b/src/app/core/eperson/eperson-data.service.ts @@ -7,8 +7,8 @@ import { find, map, take } from 'rxjs/operators'; import { EPeopleRegistryCancelEPersonAction, EPeopleRegistryEditEPersonAction -} from '../../admin-access-control/epeople-registry/epeople-registry.actions'; -import { EPeopleRegistryState } from '../../admin-access-control/epeople-registry/epeople-registry.reducers'; +} from '../../access-control/epeople-registry/epeople-registry.actions'; +import { EPeopleRegistryState } from '../../access-control/epeople-registry/epeople-registry.reducers'; import { AppState } from '../../app.reducer'; import { hasValue, hasNoValue } from '../../shared/empty.util'; import { NotificationsService } from '../../shared/notifications/notifications.service'; diff --git a/src/app/core/eperson/group-data.service.spec.ts b/src/app/core/eperson/group-data.service.spec.ts index b39a58c83d..378c3c9667 100644 --- a/src/app/core/eperson/group-data.service.spec.ts +++ b/src/app/core/eperson/group-data.service.spec.ts @@ -8,7 +8,7 @@ import { compare, Operation } from 'fast-json-patch'; import { GroupRegistryCancelGroupAction, GroupRegistryEditGroupAction -} from '../../admin-access-control/group-registry/group-registry.actions'; +} from '../../access-control/group-registry/group-registry.actions'; import { GroupMock, GroupMock2 } from '../../shared/testing/group-mock'; import { RequestParam } from '../cache/models/request-param.model'; import { CoreState } from '../core.reducers'; diff --git a/src/app/core/eperson/group-data.service.ts b/src/app/core/eperson/group-data.service.ts index 3e5424b376..cff1c37f09 100644 --- a/src/app/core/eperson/group-data.service.ts +++ b/src/app/core/eperson/group-data.service.ts @@ -7,8 +7,8 @@ import { filter, map, take } from 'rxjs/operators'; import { GroupRegistryCancelGroupAction, GroupRegistryEditGroupAction -} from '../../admin-access-control/group-registry/group-registry.actions'; -import { GroupRegistryState } from '../../admin-access-control/group-registry/group-registry.reducers'; +} from '../../access-control/group-registry/group-registry.actions'; +import { GroupRegistryState } from '../../access-control/group-registry/group-registry.reducers'; import { AppState } from '../../app.reducer'; import { NotificationsService } from '../../shared/notifications/notifications.service'; import { FollowLinkConfig } from '../../shared/utils/follow-link-config.model'; diff --git a/src/app/shared/comcol-forms/edit-comcol-page/comcol-role/comcol-role.component.ts b/src/app/shared/comcol-forms/edit-comcol-page/comcol-role/comcol-role.component.ts index 65a0881fc7..d155d66a0a 100644 --- a/src/app/shared/comcol-forms/edit-comcol-page/comcol-role/comcol-role.component.ts +++ b/src/app/shared/comcol-forms/edit-comcol-page/comcol-role/comcol-role.component.ts @@ -9,7 +9,7 @@ import { getAllCompletedRemoteData, getFirstCompletedRemoteData } from '../../.. import { RequestService } from '../../../../core/data/request.service'; import { RemoteData } from '../../../../core/data/remote-data'; import { HALLink } from '../../../../core/shared/hal-link.model'; -import { getGroupEditRoute } from '../../../../admin-access-control/admin-access-control-routing-paths'; +import { getGroupEditRoute } from '../../../../access-control/access-control-routing-paths'; import { hasNoValue, hasValue } from '../../../empty.util'; import { NoContent } from '../../../../core/shared/NoContent.model'; diff --git a/src/app/shared/resource-policies/resource-policies.component.ts b/src/app/shared/resource-policies/resource-policies.component.ts index 38981b4f05..2b21d69d34 100644 --- a/src/app/shared/resource-policies/resource-policies.component.ts +++ b/src/app/shared/resource-policies/resource-policies.component.ts @@ -32,7 +32,7 @@ import { NotificationsService } from '../notifications/notifications.service'; import { dateToString, stringToNgbDateStruct } from '../date.util'; import { followLink } from '../utils/follow-link-config.model'; import { ADMIN_MODULE_PATH } from '../../app-routing-paths'; -import { GROUP_EDIT_PATH } from '../../admin-access-control/admin-access-control-routing-paths'; +import { GROUP_EDIT_PATH } from '../../access-control/access-control-routing-paths'; import { ACCESS_CONTROL_MODULE_PATH } from '../../+admin/admin-routing-paths'; interface ResourcePolicyCheckboxEntry { From a8544a7f32e31f6a0d38291d1a7cda94288f4277 Mon Sep 17 00:00:00 2001 From: Yura Bondarenko Date: Thu, 25 Feb 2021 13:40:11 +0100 Subject: [PATCH 045/132] 77205: Remove access-control from admin routes --- src/app/+admin/admin-routing-paths.ts | 5 ----- src/app/+admin/admin-routing.module.ts | 7 +------ src/app/access-control/access-control-routing-paths.ts | 6 +++++- .../resource-policies/resource-policies.component.ts | 3 +-- 4 files changed, 7 insertions(+), 14 deletions(-) diff --git a/src/app/+admin/admin-routing-paths.ts b/src/app/+admin/admin-routing-paths.ts index 11eac49fe2..3168ea93c9 100644 --- a/src/app/+admin/admin-routing-paths.ts +++ b/src/app/+admin/admin-routing-paths.ts @@ -2,12 +2,7 @@ import { URLCombiner } from '../core/url-combiner/url-combiner'; import { getAdminModuleRoute } from '../app-routing-paths'; export const REGISTRIES_MODULE_PATH = 'registries'; -export const ACCESS_CONTROL_MODULE_PATH = 'access-control'; export function getRegistriesModuleRoute() { return new URLCombiner(getAdminModuleRoute(), REGISTRIES_MODULE_PATH).toString(); } - -export function getAccessControlModuleRoute() { - return new URLCombiner(getAdminModuleRoute(), ACCESS_CONTROL_MODULE_PATH).toString(); -} diff --git a/src/app/+admin/admin-routing.module.ts b/src/app/+admin/admin-routing.module.ts index a5c844a118..ee5cb8737b 100644 --- a/src/app/+admin/admin-routing.module.ts +++ b/src/app/+admin/admin-routing.module.ts @@ -6,7 +6,7 @@ import { I18nBreadcrumbResolver } from '../core/breadcrumbs/i18n-breadcrumb.reso import { AdminWorkflowPageComponent } from './admin-workflow-page/admin-workflow-page.component'; import { I18nBreadcrumbsService } from '../core/breadcrumbs/i18n-breadcrumbs.service'; import { AdminCurationTasksComponent } from './admin-curation-tasks/admin-curation-tasks.component'; -import { ACCESS_CONTROL_MODULE_PATH, REGISTRIES_MODULE_PATH } from './admin-routing-paths'; +import { REGISTRIES_MODULE_PATH } from './admin-routing-paths'; @NgModule({ imports: [ @@ -16,11 +16,6 @@ import { ACCESS_CONTROL_MODULE_PATH, REGISTRIES_MODULE_PATH } from './admin-rout loadChildren: () => import('./admin-registries/admin-registries.module') .then((m) => m.AdminRegistriesModule), }, - { - path: ACCESS_CONTROL_MODULE_PATH, - loadChildren: () => import('../access-control/access-control.module') - .then((m) => m.AccessControlModule), - }, { path: 'search', resolve: { breadcrumb: I18nBreadcrumbResolver }, diff --git a/src/app/access-control/access-control-routing-paths.ts b/src/app/access-control/access-control-routing-paths.ts index 2a38a78015..10ef09066d 100644 --- a/src/app/access-control/access-control-routing-paths.ts +++ b/src/app/access-control/access-control-routing-paths.ts @@ -1,7 +1,11 @@ import { URLCombiner } from '../core/url-combiner/url-combiner'; -import { getAccessControlModuleRoute } from '../+admin/admin-routing-paths'; export const GROUP_EDIT_PATH = 'groups'; +export const ACCESS_CONTROL_MODULE_PATH = 'access-control'; + +export function getAccessControlModuleRoute() { + return `/${ACCESS_CONTROL_MODULE_PATH}`; +} export function getGroupEditRoute(id: string) { return new URLCombiner(getAccessControlModuleRoute(), GROUP_EDIT_PATH, id).toString(); diff --git a/src/app/shared/resource-policies/resource-policies.component.ts b/src/app/shared/resource-policies/resource-policies.component.ts index 2b21d69d34..a83492d79f 100644 --- a/src/app/shared/resource-policies/resource-policies.component.ts +++ b/src/app/shared/resource-policies/resource-policies.component.ts @@ -32,8 +32,7 @@ import { NotificationsService } from '../notifications/notifications.service'; import { dateToString, stringToNgbDateStruct } from '../date.util'; import { followLink } from '../utils/follow-link-config.model'; import { ADMIN_MODULE_PATH } from '../../app-routing-paths'; -import { GROUP_EDIT_PATH } from '../../access-control/access-control-routing-paths'; -import { ACCESS_CONTROL_MODULE_PATH } from '../../+admin/admin-routing-paths'; +import { ACCESS_CONTROL_MODULE_PATH, GROUP_EDIT_PATH } from '../../access-control/access-control-routing-paths'; interface ResourcePolicyCheckboxEntry { id: string; From 801cea4062d49a07860ac7006062f5be454cea59 Mon Sep 17 00:00:00 2001 From: Yura Bondarenko Date: Thu, 25 Feb 2021 13:54:33 +0100 Subject: [PATCH 046/132] 77205: Separate access control section in admin sidebar --- .../admin-sidebar/admin-sidebar.component.ts | 105 ++++++++++-------- .../access-control-routing-paths.ts | 6 +- src/app/app-routing-paths.ts | 6 + .../data/feature-authorization/feature-id.ts | 1 + .../resource-policies.component.ts | 4 +- 5 files changed, 70 insertions(+), 52 deletions(-) diff --git a/src/app/+admin/admin-sidebar/admin-sidebar.component.ts b/src/app/+admin/admin-sidebar/admin-sidebar.component.ts index bfc36cea24..9d7b35eb68 100644 --- a/src/app/+admin/admin-sidebar/admin-sidebar.component.ts +++ b/src/app/+admin/admin-sidebar/admin-sidebar.component.ts @@ -79,6 +79,7 @@ export class AdminSidebarComponent extends MenuComponent implements OnInit { this.createSiteAdministratorMenuSections(); this.createExportMenuSections(); this.createImportMenuSections(); + this.createAccessControlMenuSections(); super.ngOnInit(); this.sidebarWidth = this.variableService.getVariable('sidebarItemsWidth'); this.authService.isAuthenticated() @@ -436,51 +437,6 @@ export class AdminSidebarComponent extends MenuComponent implements OnInit { createSiteAdministratorMenuSections() { this.authorizationService.isAuthorized(FeatureID.AdministratorOf).subscribe((authorized) => { const menuList = [ - /* Access Control */ - { - id: 'access_control', - active: false, - visible: authorized, - model: { - type: MenuItemType.TEXT, - text: 'menu.section.access_control' - } as TextMenuItemModel, - icon: 'key', - index: 4 - }, - { - id: 'access_control_people', - parentID: 'access_control', - active: false, - visible: authorized, - model: { - type: MenuItemType.LINK, - text: 'menu.section.access_control_people', - link: '/admin/access-control/epeople' - } as LinkMenuItemModel, - }, - { - id: 'access_control_groups', - parentID: 'access_control', - active: false, - visible: authorized, - model: { - type: MenuItemType.LINK, - text: 'menu.section.access_control_groups', - link: '/admin/access-control/groups' - } as LinkMenuItemModel, - }, - { - id: 'access_control_authorizations', - parentID: 'access_control', - active: false, - visible: authorized, - model: { - type: MenuItemType.LINK, - text: 'menu.section.access_control_authorizations', - link: '' - } as LinkMenuItemModel, - }, /* Admin Search */ { id: 'admin_search', @@ -564,6 +520,65 @@ export class AdminSidebarComponent extends MenuComponent implements OnInit { }); } + /** + * Create menu sections dependent on whether or not the current user can manage access control groups + */ + createAccessControlMenuSections() { + this.authorizationService.isAuthorized(FeatureID.CanManageGroups).subscribe((authorized) => { + const menuList = [ + /* Access Control */ + { + id: 'access_control', + active: false, + visible: authorized, + model: { + type: MenuItemType.TEXT, + text: 'menu.section.access_control' + } as TextMenuItemModel, + icon: 'key', + index: 4 + }, + { + id: 'access_control_people', + parentID: 'access_control', + active: false, + visible: authorized, + model: { + type: MenuItemType.LINK, + text: 'menu.section.access_control_people', + link: '/access-control/epeople' + } as LinkMenuItemModel, + }, + { + id: 'access_control_groups', + parentID: 'access_control', + active: false, + visible: authorized, + model: { + type: MenuItemType.LINK, + text: 'menu.section.access_control_groups', + link: '/access-control/groups' + } as LinkMenuItemModel, + }, + { + id: 'access_control_authorizations', + parentID: 'access_control', + active: false, + visible: authorized, + model: { + type: MenuItemType.LINK, + text: 'menu.section.access_control_authorizations', + link: '' + } as LinkMenuItemModel, + }, + ]; + + menuList.forEach((menuSection) => this.menuService.addSection(this.menuID, Object.assign(menuSection, { + shouldPersistOnRouteChange: true, + }))); + }) + } + /** * Method to change this.collapsed to false when the slide animation ends and is sliding open * @param event The animation event diff --git a/src/app/access-control/access-control-routing-paths.ts b/src/app/access-control/access-control-routing-paths.ts index 10ef09066d..d229d12bd2 100644 --- a/src/app/access-control/access-control-routing-paths.ts +++ b/src/app/access-control/access-control-routing-paths.ts @@ -1,11 +1,7 @@ import { URLCombiner } from '../core/url-combiner/url-combiner'; +import { getAccessControlModuleRoute } from '../app-routing-paths'; export const GROUP_EDIT_PATH = 'groups'; -export const ACCESS_CONTROL_MODULE_PATH = 'access-control'; - -export function getAccessControlModuleRoute() { - return `/${ACCESS_CONTROL_MODULE_PATH}`; -} export function getGroupEditRoute(id: string) { return new URLCombiner(getAccessControlModuleRoute(), GROUP_EDIT_PATH, id).toString(); diff --git a/src/app/app-routing-paths.ts b/src/app/app-routing-paths.ts index 8db4ba5aa7..453b03dcfb 100644 --- a/src/app/app-routing-paths.ts +++ b/src/app/app-routing-paths.ts @@ -71,3 +71,9 @@ export const INFO_MODULE_PATH = 'info'; export function getInfoModulePath() { return `/${INFO_MODULE_PATH}`; } + +export const ACCESS_CONTROL_MODULE_PATH = 'access-control'; + +export function getAccessControlModuleRoute() { + return `/${ACCESS_CONTROL_MODULE_PATH}`; +} diff --git a/src/app/core/data/feature-authorization/feature-id.ts b/src/app/core/data/feature-authorization/feature-id.ts index 3c17f43cb1..0af2399b7c 100644 --- a/src/app/core/data/feature-authorization/feature-id.ts +++ b/src/app/core/data/feature-authorization/feature-id.ts @@ -9,4 +9,5 @@ export enum FeatureID { WithdrawItem = 'withdrawItem', ReinstateItem = 'reinstateItem', EPersonRegistration = 'epersonRegistration', + CanManageGroups = 'canManageGroups', } diff --git a/src/app/shared/resource-policies/resource-policies.component.ts b/src/app/shared/resource-policies/resource-policies.component.ts index a83492d79f..bc83314ee4 100644 --- a/src/app/shared/resource-policies/resource-policies.component.ts +++ b/src/app/shared/resource-policies/resource-policies.component.ts @@ -31,8 +31,8 @@ import { RequestService } from '../../core/data/request.service'; import { NotificationsService } from '../notifications/notifications.service'; import { dateToString, stringToNgbDateStruct } from '../date.util'; import { followLink } from '../utils/follow-link-config.model'; -import { ADMIN_MODULE_PATH } from '../../app-routing-paths'; -import { ACCESS_CONTROL_MODULE_PATH, GROUP_EDIT_PATH } from '../../access-control/access-control-routing-paths'; +import { ACCESS_CONTROL_MODULE_PATH, ADMIN_MODULE_PATH } from '../../app-routing-paths'; +import { GROUP_EDIT_PATH } from '../../access-control/access-control-routing-paths'; interface ResourcePolicyCheckboxEntry { id: string; From d401a92a17d27d33ff8cc8f2d226cd98eaad28ad Mon Sep 17 00:00:00 2001 From: Yura Bondarenko Date: Thu, 25 Feb 2021 14:06:59 +0100 Subject: [PATCH 047/132] 77205: Add CanManageGroupGuard & configure routing --- .../guards/can-manage-group.guard.spec.ts | 16 +++++++++++++++ .../guards/can-manage-group.guard.ts | 20 +++++++++++++++++++ src/app/app-routing.module.ts | 9 ++++++++- 3 files changed, 44 insertions(+), 1 deletion(-) create mode 100644 src/app/access-control/guards/can-manage-group.guard.spec.ts create mode 100644 src/app/access-control/guards/can-manage-group.guard.ts diff --git a/src/app/access-control/guards/can-manage-group.guard.spec.ts b/src/app/access-control/guards/can-manage-group.guard.spec.ts new file mode 100644 index 0000000000..aa3fd9be5d --- /dev/null +++ b/src/app/access-control/guards/can-manage-group.guard.spec.ts @@ -0,0 +1,16 @@ +import { TestBed } from '@angular/core/testing'; + +import { CanManageGroupGuard } from './can-manage-group.guard'; + +describe('CanManageGroupGuard', () => { + let guard: CanManageGroupGuard; + + beforeEach(() => { + TestBed.configureTestingModule({}); + guard = TestBed.inject(CanManageGroupGuard); + }); + + it('should be created', () => { + expect(guard).toBeTruthy(); + }); +}); diff --git a/src/app/access-control/guards/can-manage-group.guard.ts b/src/app/access-control/guards/can-manage-group.guard.ts new file mode 100644 index 0000000000..7b62fecf2c --- /dev/null +++ b/src/app/access-control/guards/can-manage-group.guard.ts @@ -0,0 +1,20 @@ +import { Injectable } from '@angular/core'; +import { CanActivate, ActivatedRouteSnapshot, RouterStateSnapshot } from '@angular/router'; +import { Observable } from 'rxjs'; +import { FeatureID } from '../../core/data/feature-authorization/feature-id'; +import { AuthorizationDataService } from '../../core/data/feature-authorization/authorization-data.service'; + +/** + * Guard for preventing unauthorized access to /access-control/groups/* + */ +@Injectable({ + providedIn: 'root' +}) +export class CanManageGroupGuard implements CanActivate { + constructor(private authorizationService: AuthorizationDataService) { + } + + canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable { + return this.authorizationService.isAuthorized(FeatureID.CanManageGroups); + } +} diff --git a/src/app/app-routing.module.ts b/src/app/app-routing.module.ts index e14672f1f5..a7e736a630 100644 --- a/src/app/app-routing.module.ts +++ b/src/app/app-routing.module.ts @@ -6,6 +6,7 @@ import { PageNotFoundComponent } from './pagenotfound/pagenotfound.component'; import { AuthenticatedGuard } from './core/auth/authenticated.guard'; import { SiteAdministratorGuard } from './core/data/feature-authorization/feature-authorization-guard/site-administrator.guard'; import { + ACCESS_CONTROL_MODULE_PATH, ADMIN_MODULE_PATH, BITSTREAM_MODULE_PATH, FORBIDDEN_PATH, @@ -13,7 +14,7 @@ import { INFO_MODULE_PATH, PROFILE_MODULE_PATH, REGISTER_PATH, - WORKFLOW_ITEM_MODULE_PATH + WORKFLOW_ITEM_MODULE_PATH, } from './app-routing-paths'; import { COLLECTION_MODULE_PATH } from './+collection-page/collection-page-routing-paths'; import { COMMUNITY_MODULE_PATH } from './+community-page/community-page-routing-paths'; @@ -23,6 +24,7 @@ import { ReloadGuard } from './core/reload/reload.guard'; import { EndUserAgreementCurrentUserGuard } from './core/end-user-agreement/end-user-agreement-current-user.guard'; import { SiteRegisterGuard } from './core/data/feature-authorization/feature-authorization-guard/site-register.guard'; import { ForbiddenComponent } from './forbidden/forbidden.component'; +import { CanManageGroupGuard } from './access-control/guards/can-manage-group.guard'; @NgModule({ imports: [ @@ -175,6 +177,11 @@ import { ForbiddenComponent } from './forbidden/forbidden.component'; loadChildren: () => import('./statistics-page/statistics-page-routing.module') .then((m) => m.StatisticsPageRoutingModule), }, + { + path: ACCESS_CONTROL_MODULE_PATH, + loadChildren: () => import('./access-control/access-control.module').then((m) => m.AccessControlModule), + canActivate: [CanManageGroupGuard], + }, { path: '**', pathMatch: 'full', component: PageNotFoundComponent }, ]} ],{ From 3f4e032bb56864f312b14f01aa7398ec7941dc6a Mon Sep 17 00:00:00 2001 From: Yura Bondarenko Date: Thu, 25 Feb 2021 14:55:41 +0100 Subject: [PATCH 048/132] 77205: Add Comm/Coll admin guards & authorization checks --- .../admin-sidebar/admin-sidebar.component.ts | 369 +++++++++--------- .../collection-page.component.html | 2 +- .../collection-page.component.ts | 9 + .../edit-collection-page.routing.module.ts | 2 + .../community-page.component.html | 2 +- .../community-page.component.ts | 13 +- .../edit-community-page.routing.module.ts | 2 + .../guards/is-collection-admin.guard.spec.ts | 16 + .../guards/is-collection-admin.guard.ts | 20 + .../guards/is-community-admin.guard.spec.ts | 16 + .../guards/is-community-admin.guard.ts | 20 + .../data/feature-authorization/feature-id.ts | 2 + 12 files changed, 287 insertions(+), 186 deletions(-) create mode 100644 src/app/access-control/guards/is-collection-admin.guard.spec.ts create mode 100644 src/app/access-control/guards/is-collection-admin.guard.ts create mode 100644 src/app/access-control/guards/is-community-admin.guard.spec.ts create mode 100644 src/app/access-control/guards/is-community-admin.guard.ts diff --git a/src/app/+admin/admin-sidebar/admin-sidebar.component.ts b/src/app/+admin/admin-sidebar/admin-sidebar.component.ts index 9d7b35eb68..2748254dbb 100644 --- a/src/app/+admin/admin-sidebar/admin-sidebar.component.ts +++ b/src/app/+admin/admin-sidebar/admin-sidebar.component.ts @@ -1,6 +1,6 @@ import { Component, Injector, OnInit } from '@angular/core'; import { NgbModal } from '@ng-bootstrap/ng-bootstrap'; -import { combineLatest as observableCombineLatest, Observable } from 'rxjs'; +import { combineLatest, combineLatest as observableCombineLatest, Observable } from 'rxjs'; import { first, map, take } from 'rxjs/operators'; import { AuthService } from '../../core/auth/auth.service'; import { ScriptDataService } from '../../core/data/processes/script-data.service'; @@ -103,192 +103,197 @@ export class AdminSidebarComponent extends MenuComponent implements OnInit { * Initialize all menu sections and items for this menu */ createMenu() { - const menuList = [ - /* News */ - { - id: 'new', - active: false, - visible: true, - model: { - type: MenuItemType.TEXT, - text: 'menu.section.new' - } as TextMenuItemModel, - icon: 'plus-circle', - index: 0 - }, - { - id: 'new_community', - parentID: 'new', - active: false, - visible: true, - model: { - type: MenuItemType.ONCLICK, - text: 'menu.section.new_community', - function: () => { - this.modalService.open(CreateCommunityParentSelectorComponent); - } - } as OnClickMenuItemModel, - }, - { - id: 'new_collection', - parentID: 'new', - active: false, - visible: true, - model: { - type: MenuItemType.ONCLICK, - text: 'menu.section.new_collection', - function: () => { - this.modalService.open(CreateCollectionParentSelectorComponent); - } - } as OnClickMenuItemModel, - }, - { - id: 'new_item', - parentID: 'new', - active: false, - visible: true, - model: { - type: MenuItemType.ONCLICK, - text: 'menu.section.new_item', - function: () => { - this.modalService.open(CreateItemParentSelectorComponent); - } - } as OnClickMenuItemModel, - }, - { - id: 'new_process', - parentID: 'new', - active: false, - visible: true, - model: { - type: MenuItemType.LINK, - text: 'menu.section.new_process', - link: '/processes/new' - } as LinkMenuItemModel, - }, - { - id: 'new_item_version', - parentID: 'new', - active: false, - visible: true, - model: { - type: MenuItemType.LINK, - text: 'menu.section.new_item_version', - link: '' - } as LinkMenuItemModel, - }, + combineLatest([ + this.authorizationService.isAuthorized(FeatureID.IsCollectionAdmin), + this.authorizationService.isAuthorized(FeatureID.IsCommunityAdmin), + ]).subscribe(([isCollectionAdmin, isCommunityAdmin]) => { + const menuList = [ + /* News */ + { + id: 'new', + active: false, + visible: true, + model: { + type: MenuItemType.TEXT, + text: 'menu.section.new' + } as TextMenuItemModel, + icon: 'plus-circle', + index: 0 + }, + { + id: 'new_community', + parentID: 'new', + active: false, + visible: true, + model: { + type: MenuItemType.ONCLICK, + text: 'menu.section.new_community', + function: () => { + this.modalService.open(CreateCommunityParentSelectorComponent); + } + } as OnClickMenuItemModel, + }, + { + id: 'new_collection', + parentID: 'new', + active: false, + visible: true, + model: { + type: MenuItemType.ONCLICK, + text: 'menu.section.new_collection', + function: () => { + this.modalService.open(CreateCollectionParentSelectorComponent); + } + } as OnClickMenuItemModel, + }, + { + id: 'new_item', + parentID: 'new', + active: false, + visible: true, + model: { + type: MenuItemType.ONCLICK, + text: 'menu.section.new_item', + function: () => { + this.modalService.open(CreateItemParentSelectorComponent); + } + } as OnClickMenuItemModel, + }, + { + id: 'new_process', + parentID: 'new', + active: false, + visible: true, + model: { + type: MenuItemType.LINK, + text: 'menu.section.new_process', + link: '/processes/new' + } as LinkMenuItemModel, + }, + { + id: 'new_item_version', + parentID: 'new', + active: false, + visible: true, + model: { + type: MenuItemType.LINK, + text: 'menu.section.new_item_version', + link: '' + } as LinkMenuItemModel, + }, - /* Edit */ - { - id: 'edit', - active: false, - visible: true, - model: { - type: MenuItemType.TEXT, - text: 'menu.section.edit' - } as TextMenuItemModel, - icon: 'pencil-alt', - index: 1 - }, - { - id: 'edit_community', - parentID: 'edit', - active: false, - visible: true, - model: { - type: MenuItemType.ONCLICK, - text: 'menu.section.edit_community', - function: () => { - this.modalService.open(EditCommunitySelectorComponent); - } - } as OnClickMenuItemModel, - }, - { - id: 'edit_collection', - parentID: 'edit', - active: false, - visible: true, - model: { - type: MenuItemType.ONCLICK, - text: 'menu.section.edit_collection', - function: () => { - this.modalService.open(EditCollectionSelectorComponent); - } - } as OnClickMenuItemModel, - }, - { - id: 'edit_item', - parentID: 'edit', - active: false, - visible: true, - model: { - type: MenuItemType.ONCLICK, - text: 'menu.section.edit_item', - function: () => { - this.modalService.open(EditItemSelectorComponent); - } - } as OnClickMenuItemModel, - }, + /* Edit */ + { + id: 'edit', + active: false, + visible: true, + model: { + type: MenuItemType.TEXT, + text: 'menu.section.edit' + } as TextMenuItemModel, + icon: 'pencil-alt', + index: 1 + }, + { + id: 'edit_community', + parentID: 'edit', + active: false, + visible: isCommunityAdmin, + model: { + type: MenuItemType.ONCLICK, + text: 'menu.section.edit_community', + function: () => { + this.modalService.open(EditCommunitySelectorComponent); + } + } as OnClickMenuItemModel, + }, + { + id: 'edit_collection', + parentID: 'edit', + active: false, + visible: isCollectionAdmin, + model: { + type: MenuItemType.ONCLICK, + text: 'menu.section.edit_collection', + function: () => { + this.modalService.open(EditCollectionSelectorComponent); + } + } as OnClickMenuItemModel, + }, + { + id: 'edit_item', + parentID: 'edit', + active: false, + visible: true, + model: { + type: MenuItemType.ONCLICK, + text: 'menu.section.edit_item', + function: () => { + this.modalService.open(EditItemSelectorComponent); + } + } as OnClickMenuItemModel, + }, - /* Curation tasks */ - { - id: 'curation_tasks', - active: false, - visible: true, - model: { - type: MenuItemType.LINK, - text: 'menu.section.curation_task', - link: '' - } as LinkMenuItemModel, - icon: 'filter', - index: 7 - }, + /* Curation tasks */ + { + id: 'curation_tasks', + active: false, + visible: true, + model: { + type: MenuItemType.LINK, + text: 'menu.section.curation_task', + link: '' + } as LinkMenuItemModel, + icon: 'filter', + index: 7 + }, - /* Statistics */ - { - id: 'statistics_task', - active: false, - visible: true, - model: { - type: MenuItemType.LINK, - text: 'menu.section.statistics_task', - link: '' - } as LinkMenuItemModel, - icon: 'chart-bar', - index: 8 - }, + /* Statistics */ + { + id: 'statistics_task', + active: false, + visible: true, + model: { + type: MenuItemType.LINK, + text: 'menu.section.statistics_task', + link: '' + } as LinkMenuItemModel, + icon: 'chart-bar', + index: 8 + }, - /* Control Panel */ - { - id: 'control_panel', - active: false, - visible: true, - model: { - type: MenuItemType.LINK, - text: 'menu.section.control_panel', - link: '' - } as LinkMenuItemModel, - icon: 'cogs', - index: 9 - }, + /* Control Panel */ + { + id: 'control_panel', + active: false, + visible: true, + model: { + type: MenuItemType.LINK, + text: 'menu.section.control_panel', + link: '' + } as LinkMenuItemModel, + icon: 'cogs', + index: 9 + }, - /* Processes */ - { - id: 'processes', - active: false, - visible: true, - model: { - type: MenuItemType.LINK, - text: 'menu.section.processes', - link: '/processes' - } as LinkMenuItemModel, - icon: 'terminal', - index: 10 - }, - ]; - menuList.forEach((menuSection) => this.menuService.addSection(this.menuID, Object.assign(menuSection, { - shouldPersistOnRouteChange: true - }))); + /* Processes */ + { + id: 'processes', + active: false, + visible: true, + model: { + type: MenuItemType.LINK, + text: 'menu.section.processes', + link: '/processes' + } as LinkMenuItemModel, + icon: 'terminal', + index: 10 + }, + ]; + menuList.forEach((menuSection) => this.menuService.addSection(this.menuID, Object.assign(menuSection, { + shouldPersistOnRouteChange: true + }))); + }) } /** diff --git a/src/app/+collection-page/collection-page.component.html b/src/app/+collection-page/collection-page.component.html index beb7413415..a9dd99068e 100644 --- a/src/app/+collection-page/collection-page.component.html +++ b/src/app/+collection-page/collection-page.component.html @@ -35,7 +35,7 @@
- +
diff --git a/src/app/+collection-page/collection-page.component.ts b/src/app/+collection-page/collection-page.component.ts index 8065480604..72e217a7ec 100644 --- a/src/app/+collection-page/collection-page.component.ts +++ b/src/app/+collection-page/collection-page.component.ts @@ -22,6 +22,8 @@ import { hasValue, isNotEmpty } from '../shared/empty.util'; import { PaginationComponentOptions } from '../shared/pagination/pagination-component-options.model'; import { AuthService } from '../core/auth/auth.service'; import {PaginationChangeEvent} from '../shared/pagination/paginationChangeEvent.interface'; +import { AuthorizationDataService } from '../core/data/feature-authorization/authorization-data.service'; +import { FeatureID } from '../core/data/feature-authorization/feature-id'; @Component({ selector: 'ds-collection-page', @@ -44,6 +46,11 @@ export class CollectionPageComponent implements OnInit { sortConfig: SortOptions }>; + /** + * Whether the current user is a Community admin + */ + isCollectionAdmin$: Observable; + constructor( private collectionDataService: CollectionDataService, private searchService: SearchService, @@ -51,6 +58,7 @@ export class CollectionPageComponent implements OnInit { private route: ActivatedRoute, private router: Router, private authService: AuthService, + private authorizationDataService: AuthorizationDataService, ) { this.paginationConfig = new PaginationComponentOptions(); this.paginationConfig.id = 'collection-page-pagination'; @@ -70,6 +78,7 @@ export class CollectionPageComponent implements OnInit { filter((collection: Collection) => hasValue(collection)), mergeMap((collection: Collection) => collection.logo) ); + this.isCollectionAdmin$ = this.authorizationDataService.isAuthorized(FeatureID.IsCollectionAdmin); this.paginationChanges$ = new BehaviorSubject({ paginationConfig: this.paginationConfig, diff --git a/src/app/+collection-page/edit-collection-page/edit-collection-page.routing.module.ts b/src/app/+collection-page/edit-collection-page/edit-collection-page.routing.module.ts index e41f0ebda4..e4dea5e63c 100644 --- a/src/app/+collection-page/edit-collection-page/edit-collection-page.routing.module.ts +++ b/src/app/+collection-page/edit-collection-page/edit-collection-page.routing.module.ts @@ -12,6 +12,7 @@ import { ResourcePolicyTargetResolver } from '../../shared/resource-policies/res import { ResourcePolicyCreateComponent } from '../../shared/resource-policies/create/resource-policy-create.component'; import { ResourcePolicyResolver } from '../../shared/resource-policies/resolvers/resource-policy.resolver'; import { ResourcePolicyEditComponent } from '../../shared/resource-policies/edit/resource-policy-edit.component'; +import { IsCollectionAdminGuard } from '../../access-control/guards/is-collection-admin.guard'; /** * Routing module that handles the routing for the Edit Collection page administrator functionality @@ -26,6 +27,7 @@ import { ResourcePolicyEditComponent } from '../../shared/resource-policies/edit }, data: { breadcrumbKey: 'collection.edit' }, component: EditCollectionPageComponent, + canActivate: [IsCollectionAdminGuard], children: [ { path: '', diff --git a/src/app/+community-page/community-page.component.html b/src/app/+community-page/community-page.component.html index 418e69ed10..c1d88c9ab8 100644 --- a/src/app/+community-page/community-page.component.html +++ b/src/app/+community-page/community-page.component.html @@ -21,7 +21,7 @@
- +
diff --git a/src/app/+community-page/community-page.component.ts b/src/app/+community-page/community-page.component.ts index e4812e6514..32886b3f01 100644 --- a/src/app/+community-page/community-page.component.ts +++ b/src/app/+community-page/community-page.component.ts @@ -15,6 +15,8 @@ import { fadeInOut } from '../shared/animations/fade'; import { hasValue } from '../shared/empty.util'; import { redirectOn4xx } from '../core/shared/operators'; 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'; @Component({ selector: 'ds-community-page', @@ -32,6 +34,11 @@ export class CommunityPageComponent implements OnInit { */ communityRD$: Observable>; + /** + * Whether the current user is a Community admin + */ + isCommunityAdmin$: Observable; + /** * The logo of this community */ @@ -42,6 +49,7 @@ export class CommunityPageComponent implements OnInit { private route: ActivatedRoute, private router: Router, private authService: AuthService, + private authorizationDataService: AuthorizationDataService ) { } @@ -54,7 +62,8 @@ export class CommunityPageComponent implements OnInit { this.logoRD$ = this.communityRD$.pipe( map((rd: RemoteData) => rd.payload), filter((community: Community) => hasValue(community)), - mergeMap((community: Community) => community.logo)); + mergeMap((community: Community) => community.logo) + ); + this.isCommunityAdmin$ = this.authorizationDataService.isAuthorized(FeatureID.IsCommunityAdmin); } - } diff --git a/src/app/+community-page/edit-community-page/edit-community-page.routing.module.ts b/src/app/+community-page/edit-community-page/edit-community-page.routing.module.ts index 440fa01a30..b5aa20f252 100644 --- a/src/app/+community-page/edit-community-page/edit-community-page.routing.module.ts +++ b/src/app/+community-page/edit-community-page/edit-community-page.routing.module.ts @@ -10,6 +10,7 @@ import { ResourcePolicyTargetResolver } from '../../shared/resource-policies/res import { ResourcePolicyCreateComponent } from '../../shared/resource-policies/create/resource-policy-create.component'; import { ResourcePolicyResolver } from '../../shared/resource-policies/resolvers/resource-policy.resolver'; import { ResourcePolicyEditComponent } from '../../shared/resource-policies/edit/resource-policy-edit.component'; +import { IsCommunityAdminGuard } from '../../access-control/guards/is-community-admin.guard'; /** * Routing module that handles the routing for the Edit Community page administrator functionality @@ -24,6 +25,7 @@ import { ResourcePolicyEditComponent } from '../../shared/resource-policies/edit }, data: { breadcrumbKey: 'community.edit' }, component: EditCommunityPageComponent, + canActivate: [IsCommunityAdminGuard], children: [ { path: '', diff --git a/src/app/access-control/guards/is-collection-admin.guard.spec.ts b/src/app/access-control/guards/is-collection-admin.guard.spec.ts new file mode 100644 index 0000000000..9a60980c01 --- /dev/null +++ b/src/app/access-control/guards/is-collection-admin.guard.spec.ts @@ -0,0 +1,16 @@ +import { TestBed } from '@angular/core/testing'; + +import { IsCollectionAdminGuard } from './is-collection-admin.guard'; + +describe('IsCollectionAdminGuard', () => { + let guard: IsCollectionAdminGuard; + + beforeEach(() => { + TestBed.configureTestingModule({}); + guard = TestBed.inject(IsCollectionAdminGuard); + }); + + it('should be created', () => { + expect(guard).toBeTruthy(); + }); +}); diff --git a/src/app/access-control/guards/is-collection-admin.guard.ts b/src/app/access-control/guards/is-collection-admin.guard.ts new file mode 100644 index 0000000000..140ea46e68 --- /dev/null +++ b/src/app/access-control/guards/is-collection-admin.guard.ts @@ -0,0 +1,20 @@ +import { Injectable } from '@angular/core'; +import { CanActivate, ActivatedRouteSnapshot, RouterStateSnapshot } from '@angular/router'; +import { Observable } from 'rxjs'; +import { FeatureID } from '../../core/data/feature-authorization/feature-id'; +import { AuthorizationDataService } from '../../core/data/feature-authorization/authorization-data.service'; + +/** + * Guard for preventing unauthorized editing of Communities + */ +@Injectable({ + providedIn: 'root' +}) +export class IsCollectionAdminGuard implements CanActivate { + constructor(private authorizationService: AuthorizationDataService) { + } + + canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable { + return this.authorizationService.isAuthorized(FeatureID.IsCollectionAdmin); + } +} diff --git a/src/app/access-control/guards/is-community-admin.guard.spec.ts b/src/app/access-control/guards/is-community-admin.guard.spec.ts new file mode 100644 index 0000000000..52dc7ec33c --- /dev/null +++ b/src/app/access-control/guards/is-community-admin.guard.spec.ts @@ -0,0 +1,16 @@ +import { TestBed } from '@angular/core/testing'; + +import { IsCommunityAdminGuard } from './is-community-admin.guard'; + +describe('IsCommunityAdminGuard', () => { + let guard: IsCommunityAdminGuard; + + beforeEach(() => { + TestBed.configureTestingModule({}); + guard = TestBed.inject(IsCommunityAdminGuard); + }); + + it('should be created', () => { + expect(guard).toBeTruthy(); + }); +}); diff --git a/src/app/access-control/guards/is-community-admin.guard.ts b/src/app/access-control/guards/is-community-admin.guard.ts new file mode 100644 index 0000000000..fcc4f6520a --- /dev/null +++ b/src/app/access-control/guards/is-community-admin.guard.ts @@ -0,0 +1,20 @@ +import { Injectable } from '@angular/core'; +import { CanActivate, ActivatedRouteSnapshot, RouterStateSnapshot } from '@angular/router'; +import { Observable } from 'rxjs'; +import { FeatureID } from '../../core/data/feature-authorization/feature-id'; +import { AuthorizationDataService } from '../../core/data/feature-authorization/authorization-data.service'; + +/** + * Guard for preventing unauthorized editing of Communities + */ +@Injectable({ + providedIn: 'root' +}) +export class IsCommunityAdminGuard implements CanActivate { + constructor(private authorizationService: AuthorizationDataService) { + } + + canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable { + return this.authorizationService.isAuthorized(FeatureID.IsCommunityAdmin); + } +} diff --git a/src/app/core/data/feature-authorization/feature-id.ts b/src/app/core/data/feature-authorization/feature-id.ts index 0af2399b7c..e3473a895e 100644 --- a/src/app/core/data/feature-authorization/feature-id.ts +++ b/src/app/core/data/feature-authorization/feature-id.ts @@ -10,4 +10,6 @@ export enum FeatureID { ReinstateItem = 'reinstateItem', EPersonRegistration = 'epersonRegistration', CanManageGroups = 'canManageGroups', + IsCollectionAdmin = 'isCollectionAdmin', + IsCommunityAdmin = 'isCommunityAdmin', } From 70e9bb118070242838042d62b9e2933a1463ee40 Mon Sep 17 00:00:00 2001 From: Yura Bondarenko Date: Thu, 25 Feb 2021 16:37:32 +0100 Subject: [PATCH 049/132] 77205: Use existing admin authorization guards for comm/coll --- .../edit-collection-page.routing.module.ts | 4 +-- .../edit-community-page.routing.module.ts | 4 +-- .../guards/can-manage-group.guard.spec.ts | 16 ----------- .../guards/can-manage-group.guard.ts | 20 -------------- .../guards/is-collection-admin.guard.spec.ts | 16 ----------- .../guards/is-collection-admin.guard.ts | 20 -------------- .../guards/is-community-admin.guard.spec.ts | 16 ----------- .../guards/is-community-admin.guard.ts | 20 -------------- src/app/app-routing.module.ts | 4 +-- .../group-administrator.guard.ts | 27 +++++++++++++++++++ 10 files changed, 33 insertions(+), 114 deletions(-) delete mode 100644 src/app/access-control/guards/can-manage-group.guard.spec.ts delete mode 100644 src/app/access-control/guards/can-manage-group.guard.ts delete mode 100644 src/app/access-control/guards/is-collection-admin.guard.spec.ts delete mode 100644 src/app/access-control/guards/is-collection-admin.guard.ts delete mode 100644 src/app/access-control/guards/is-community-admin.guard.spec.ts delete mode 100644 src/app/access-control/guards/is-community-admin.guard.ts create mode 100644 src/app/core/data/feature-authorization/feature-authorization-guard/group-administrator.guard.ts diff --git a/src/app/+collection-page/edit-collection-page/edit-collection-page.routing.module.ts b/src/app/+collection-page/edit-collection-page/edit-collection-page.routing.module.ts index e4dea5e63c..0e6e202230 100644 --- a/src/app/+collection-page/edit-collection-page/edit-collection-page.routing.module.ts +++ b/src/app/+collection-page/edit-collection-page/edit-collection-page.routing.module.ts @@ -12,7 +12,7 @@ import { ResourcePolicyTargetResolver } from '../../shared/resource-policies/res import { ResourcePolicyCreateComponent } from '../../shared/resource-policies/create/resource-policy-create.component'; import { ResourcePolicyResolver } from '../../shared/resource-policies/resolvers/resource-policy.resolver'; import { ResourcePolicyEditComponent } from '../../shared/resource-policies/edit/resource-policy-edit.component'; -import { IsCollectionAdminGuard } from '../../access-control/guards/is-collection-admin.guard'; +import { CollectionPageAdministratorGuard } from '../collection-page-administrator.guard'; /** * Routing module that handles the routing for the Edit Collection page administrator functionality @@ -27,7 +27,7 @@ import { IsCollectionAdminGuard } from '../../access-control/guards/is-collectio }, data: { breadcrumbKey: 'collection.edit' }, component: EditCollectionPageComponent, - canActivate: [IsCollectionAdminGuard], + canActivate: [CollectionPageAdministratorGuard], children: [ { path: '', diff --git a/src/app/+community-page/edit-community-page/edit-community-page.routing.module.ts b/src/app/+community-page/edit-community-page/edit-community-page.routing.module.ts index b5aa20f252..deb14fced0 100644 --- a/src/app/+community-page/edit-community-page/edit-community-page.routing.module.ts +++ b/src/app/+community-page/edit-community-page/edit-community-page.routing.module.ts @@ -10,7 +10,7 @@ import { ResourcePolicyTargetResolver } from '../../shared/resource-policies/res import { ResourcePolicyCreateComponent } from '../../shared/resource-policies/create/resource-policy-create.component'; import { ResourcePolicyResolver } from '../../shared/resource-policies/resolvers/resource-policy.resolver'; import { ResourcePolicyEditComponent } from '../../shared/resource-policies/edit/resource-policy-edit.component'; -import { IsCommunityAdminGuard } from '../../access-control/guards/is-community-admin.guard'; +import { CommunityPageAdministratorGuard } from '../community-page-administrator.guard'; /** * Routing module that handles the routing for the Edit Community page administrator functionality @@ -25,7 +25,7 @@ import { IsCommunityAdminGuard } from '../../access-control/guards/is-community- }, data: { breadcrumbKey: 'community.edit' }, component: EditCommunityPageComponent, - canActivate: [IsCommunityAdminGuard], + canActivate: [CommunityPageAdministratorGuard], children: [ { path: '', diff --git a/src/app/access-control/guards/can-manage-group.guard.spec.ts b/src/app/access-control/guards/can-manage-group.guard.spec.ts deleted file mode 100644 index aa3fd9be5d..0000000000 --- a/src/app/access-control/guards/can-manage-group.guard.spec.ts +++ /dev/null @@ -1,16 +0,0 @@ -import { TestBed } from '@angular/core/testing'; - -import { CanManageGroupGuard } from './can-manage-group.guard'; - -describe('CanManageGroupGuard', () => { - let guard: CanManageGroupGuard; - - beforeEach(() => { - TestBed.configureTestingModule({}); - guard = TestBed.inject(CanManageGroupGuard); - }); - - it('should be created', () => { - expect(guard).toBeTruthy(); - }); -}); diff --git a/src/app/access-control/guards/can-manage-group.guard.ts b/src/app/access-control/guards/can-manage-group.guard.ts deleted file mode 100644 index 7b62fecf2c..0000000000 --- a/src/app/access-control/guards/can-manage-group.guard.ts +++ /dev/null @@ -1,20 +0,0 @@ -import { Injectable } from '@angular/core'; -import { CanActivate, ActivatedRouteSnapshot, RouterStateSnapshot } from '@angular/router'; -import { Observable } from 'rxjs'; -import { FeatureID } from '../../core/data/feature-authorization/feature-id'; -import { AuthorizationDataService } from '../../core/data/feature-authorization/authorization-data.service'; - -/** - * Guard for preventing unauthorized access to /access-control/groups/* - */ -@Injectable({ - providedIn: 'root' -}) -export class CanManageGroupGuard implements CanActivate { - constructor(private authorizationService: AuthorizationDataService) { - } - - canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable { - return this.authorizationService.isAuthorized(FeatureID.CanManageGroups); - } -} diff --git a/src/app/access-control/guards/is-collection-admin.guard.spec.ts b/src/app/access-control/guards/is-collection-admin.guard.spec.ts deleted file mode 100644 index 9a60980c01..0000000000 --- a/src/app/access-control/guards/is-collection-admin.guard.spec.ts +++ /dev/null @@ -1,16 +0,0 @@ -import { TestBed } from '@angular/core/testing'; - -import { IsCollectionAdminGuard } from './is-collection-admin.guard'; - -describe('IsCollectionAdminGuard', () => { - let guard: IsCollectionAdminGuard; - - beforeEach(() => { - TestBed.configureTestingModule({}); - guard = TestBed.inject(IsCollectionAdminGuard); - }); - - it('should be created', () => { - expect(guard).toBeTruthy(); - }); -}); diff --git a/src/app/access-control/guards/is-collection-admin.guard.ts b/src/app/access-control/guards/is-collection-admin.guard.ts deleted file mode 100644 index 140ea46e68..0000000000 --- a/src/app/access-control/guards/is-collection-admin.guard.ts +++ /dev/null @@ -1,20 +0,0 @@ -import { Injectable } from '@angular/core'; -import { CanActivate, ActivatedRouteSnapshot, RouterStateSnapshot } from '@angular/router'; -import { Observable } from 'rxjs'; -import { FeatureID } from '../../core/data/feature-authorization/feature-id'; -import { AuthorizationDataService } from '../../core/data/feature-authorization/authorization-data.service'; - -/** - * Guard for preventing unauthorized editing of Communities - */ -@Injectable({ - providedIn: 'root' -}) -export class IsCollectionAdminGuard implements CanActivate { - constructor(private authorizationService: AuthorizationDataService) { - } - - canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable { - return this.authorizationService.isAuthorized(FeatureID.IsCollectionAdmin); - } -} diff --git a/src/app/access-control/guards/is-community-admin.guard.spec.ts b/src/app/access-control/guards/is-community-admin.guard.spec.ts deleted file mode 100644 index 52dc7ec33c..0000000000 --- a/src/app/access-control/guards/is-community-admin.guard.spec.ts +++ /dev/null @@ -1,16 +0,0 @@ -import { TestBed } from '@angular/core/testing'; - -import { IsCommunityAdminGuard } from './is-community-admin.guard'; - -describe('IsCommunityAdminGuard', () => { - let guard: IsCommunityAdminGuard; - - beforeEach(() => { - TestBed.configureTestingModule({}); - guard = TestBed.inject(IsCommunityAdminGuard); - }); - - it('should be created', () => { - expect(guard).toBeTruthy(); - }); -}); diff --git a/src/app/access-control/guards/is-community-admin.guard.ts b/src/app/access-control/guards/is-community-admin.guard.ts deleted file mode 100644 index fcc4f6520a..0000000000 --- a/src/app/access-control/guards/is-community-admin.guard.ts +++ /dev/null @@ -1,20 +0,0 @@ -import { Injectable } from '@angular/core'; -import { CanActivate, ActivatedRouteSnapshot, RouterStateSnapshot } from '@angular/router'; -import { Observable } from 'rxjs'; -import { FeatureID } from '../../core/data/feature-authorization/feature-id'; -import { AuthorizationDataService } from '../../core/data/feature-authorization/authorization-data.service'; - -/** - * Guard for preventing unauthorized editing of Communities - */ -@Injectable({ - providedIn: 'root' -}) -export class IsCommunityAdminGuard implements CanActivate { - constructor(private authorizationService: AuthorizationDataService) { - } - - canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable { - return this.authorizationService.isAuthorized(FeatureID.IsCommunityAdmin); - } -} diff --git a/src/app/app-routing.module.ts b/src/app/app-routing.module.ts index a7e736a630..8713b1dc94 100644 --- a/src/app/app-routing.module.ts +++ b/src/app/app-routing.module.ts @@ -24,7 +24,7 @@ import { ReloadGuard } from './core/reload/reload.guard'; import { EndUserAgreementCurrentUserGuard } from './core/end-user-agreement/end-user-agreement-current-user.guard'; import { SiteRegisterGuard } from './core/data/feature-authorization/feature-authorization-guard/site-register.guard'; import { ForbiddenComponent } from './forbidden/forbidden.component'; -import { CanManageGroupGuard } from './access-control/guards/can-manage-group.guard'; +import { GroupAdministratorGuard } from './core/data/feature-authorization/feature-authorization-guard/group-administrator.guard'; @NgModule({ imports: [ @@ -180,7 +180,7 @@ import { CanManageGroupGuard } from './access-control/guards/can-manage-group.gu { path: ACCESS_CONTROL_MODULE_PATH, loadChildren: () => import('./access-control/access-control.module').then((m) => m.AccessControlModule), - canActivate: [CanManageGroupGuard], + canActivate: [GroupAdministratorGuard], }, { path: '**', pathMatch: 'full', component: PageNotFoundComponent }, ]} diff --git a/src/app/core/data/feature-authorization/feature-authorization-guard/group-administrator.guard.ts b/src/app/core/data/feature-authorization/feature-authorization-guard/group-administrator.guard.ts new file mode 100644 index 0000000000..3fee767fdc --- /dev/null +++ b/src/app/core/data/feature-authorization/feature-authorization-guard/group-administrator.guard.ts @@ -0,0 +1,27 @@ +import { Injectable } from '@angular/core'; +import { FeatureAuthorizationGuard } from './feature-authorization.guard'; +import { AuthorizationDataService } from '../authorization-data.service'; +import { ActivatedRouteSnapshot, Router, RouterStateSnapshot } from '@angular/router'; +import { AuthService } from '../../../auth/auth.service'; +import { Observable, of as observableOf } from 'rxjs'; +import { FeatureID } from '../feature-id'; + +/** + * Prevent unauthorized activating and loading of routes when the current authenticated user doesn't have group + * management rights + */ +@Injectable({ + providedIn: 'root' +}) +export class GroupAdministratorGuard extends FeatureAuthorizationGuard { + constructor(protected authorizationService: AuthorizationDataService, protected router: Router, protected authService: AuthService) { + super(authorizationService, router, authService); + } + + /** + * Check group management rights + */ + getFeatureID(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable { + return observableOf(FeatureID.CanManageGroups); + } +} From a6effcad34051b058ee63fc33167342eec5a1b1a Mon Sep 17 00:00:00 2001 From: Giuseppe Digilio Date: Thu, 25 Feb 2021 17:09:33 +0100 Subject: [PATCH 050/132] [CST-3620] Changes to show lookup button next to the field --- ...amic-form-control-container.component.html | 8 +++ ...ynamic-form-control-container.component.ts | 66 +++++++++++++++++++ ...dynamic-lookup-relation-modal.component.ts | 1 - src/app/shared/form/form.component.html | 10 +-- src/app/shared/form/form.component.ts | 44 +------------ 5 files changed, 77 insertions(+), 52 deletions(-) diff --git a/src/app/shared/form/builder/ds-dynamic-form-ui/ds-dynamic-form-control-container.component.html b/src/app/shared/form/builder/ds-dynamic-form-ui/ds-dynamic-form-control-container.component.html index 029ba0b1f8..8ba6489068 100644 --- a/src/app/shared/form/builder/ds-dynamic-form-ui/ds-dynamic-form-control-container.component.html +++ b/src/app/shared/form/builder/ds-dynamic-form-ui/ds-dynamic-form-control-container.component.html @@ -35,6 +35,14 @@
+
+ +
diff --git a/src/app/shared/form/builder/ds-dynamic-form-ui/ds-dynamic-form-control-container.component.ts b/src/app/shared/form/builder/ds-dynamic-form-ui/ds-dynamic-form-control-container.component.ts index 6c080a7f53..5ab4a7b247 100644 --- a/src/app/shared/form/builder/ds-dynamic-form-ui/ds-dynamic-form-control-container.component.ts +++ b/src/app/shared/form/builder/ds-dynamic-form-ui/ds-dynamic-form-control-container.component.ts @@ -37,6 +37,7 @@ import { DynamicFormControl, DynamicFormControlContainerComponent, DynamicFormControlEvent, + DynamicFormControlEventType, DynamicFormControlModel, DynamicFormLayout, DynamicFormLayoutService, @@ -82,10 +83,12 @@ import { find, map, startWith, switchMap, take } from 'rxjs/operators'; import { combineLatest as observableCombineLatest, Observable, Subscription } from 'rxjs'; import { SearchResult } from '../../../search/search-result.model'; import { DSpaceObject } from '../../../../core/shared/dspace-object.model'; +import { NgbModal, NgbModalRef } from '@ng-bootstrap/ng-bootstrap'; import { RelationshipService } from '../../../../core/data/relationship.service'; import { SelectableListService } from '../../../object-list/selectable-list/selectable-list.service'; import { DsDynamicDisabledComponent } from './models/disabled/dynamic-disabled.component'; import { DYNAMIC_FORM_CONTROL_TYPE_DISABLED } from './models/disabled/dynamic-disabled.model'; +import { DsDynamicLookupRelationModalComponent } from './relation-lookup-modal/dynamic-lookup-relation-modal.component'; import { getAllSucceededRemoteData, getFirstSucceededRemoteData, @@ -107,6 +110,7 @@ import { Collection } from '../../../../core/shared/collection.model'; import { MetadataValue, VIRTUAL_METADATA_PREFIX } from '../../../../core/shared/metadata.models'; import { FormService } from '../../form.service'; import { SelectableListState } from '../../../object-list/selectable-list/selectable-list.reducer'; +import { SubmissionService } from '../../../../submission/submission.service'; import { followLink } from '../../../utils/follow-link-config.model'; import { paginatedRelationsToItems } from '../../../../+item-page/simple/item-types/shared/item-relationships-utils'; import { RelationshipOptions } from '../models/relationship-options.model'; @@ -202,6 +206,7 @@ export class DsDynamicFormControlContainerComponent extends DynamicFormControlCo @Input() model: any; relationshipValue$: Observable; isRelationship: boolean; + modalRef: NgbModalRef; item: Item; item$: Observable; collection: Collection; @@ -234,6 +239,7 @@ export class DsDynamicFormControlContainerComponent extends DynamicFormControlCo protected validationService: DynamicFormValidationService, protected translateService: TranslateService, protected relationService: DynamicFormRelationService, + private modalService: NgbModal, private relationshipService: RelationshipService, private selectableListService: SelectableListService, private itemService: ItemDataService, @@ -243,6 +249,7 @@ export class DsDynamicFormControlContainerComponent extends DynamicFormControlCo private ref: ChangeDetectorRef, private formService: FormService, private formBuilderService: FormBuilderService, + private submissionService: SubmissionService ) { super(ref, componentFactoryResolver, layoutService, validationService, dynamicFormComponentService, relationService); } @@ -257,6 +264,7 @@ export class DsDynamicFormControlContainerComponent extends DynamicFormControlCo if (this.isRelationship || isWrapperAroundRelationshipList) { const config = this.model.relationshipConfig || this.model.relationship; const relationshipOptions = Object.assign(new RelationshipOptions(), config); + this.listId = `list-${this.model.submissionId}-${relationshipOptions.relationshipType}`; this.setItem(); if (isWrapperAroundRelationshipList || !this.model.repeatable) { @@ -366,10 +374,68 @@ export class DsDynamicFormControlContainerComponent extends DynamicFormControlCo } } + hasRelationship() { + return isNotEmpty(this.model) && this.model.hasOwnProperty('relationship') && isNotEmpty(this.model.relationship); + } + + isVirtual() { + const value: FormFieldMetadataValueObject = this.model.metadataValue; + return isNotEmpty(value) && value.isVirtual; + } + public hasResultsSelected(): Observable { return this.model.value.pipe(map((list: SearchResult[]) => isNotEmpty(list))); } + /** + * Open a modal where the user can select relationships to be added to item being submitted + */ + openLookup() { + this.modalRef = this.modalService.open(DsDynamicLookupRelationModalComponent, { + size: 'lg' + }); + + if (hasValue(this.model.value)) { + this.focus.emit({ + $event: new Event('focus'), + context: this.context, + control: this.control, + model: this.model, + type: DynamicFormControlEventType.Focus + } as DynamicFormControlEvent); + + this.model.value = null; + this.change.emit({ + $event: new Event('change'), + context: this.context, + control: this.control, + model: this.model, + type: DynamicFormControlEventType.Change + } as DynamicFormControlEvent); + + this.submissionService.dispatchSave(this.model.submissionId); + } + + const modalComp = this.modalRef.componentInstance; + + if (hasValue(this.model.value) && !this.model.readOnly) { + if (typeof this.model.value === 'string') { + modalComp.query = this.model.value; + } else if (typeof this.model.value.value === 'string') { + modalComp.query = this.model.value.value; + } + } + + modalComp.repeatable = this.model.repeatable; + modalComp.listId = this.listId; + modalComp.relationshipOptions = this.model.relationship; + modalComp.label = this.model.relationship.relationshipType; + modalComp.metadataFields = this.model.metadataFields; + modalComp.item = this.item; + modalComp.collection = this.collection; + modalComp.submissionId = this.model.submissionId; + } + /** * Callback for the remove event, * remove the current control from its array diff --git a/src/app/shared/form/builder/ds-dynamic-form-ui/relation-lookup-modal/dynamic-lookup-relation-modal.component.ts b/src/app/shared/form/builder/ds-dynamic-form-ui/relation-lookup-modal/dynamic-lookup-relation-modal.component.ts index c7474cb769..4ed972b2fa 100644 --- a/src/app/shared/form/builder/ds-dynamic-form-ui/relation-lookup-modal/dynamic-lookup-relation-modal.component.ts +++ b/src/app/shared/form/builder/ds-dynamic-form-ui/relation-lookup-modal/dynamic-lookup-relation-modal.component.ts @@ -147,7 +147,6 @@ export class DsDynamicLookupRelationModalComponent implements OnInit, OnDestroy ngOnInit(): void { this.setItem(); - this.submissionService.dispatchSave(this.submissionId); this.selection$ = this.selectableListService .getSelectableList(this.listId) .pipe(map((listState: SelectableListState) => hasValue(listState) && hasValue(listState.selection) ? listState.selection : [])); diff --git a/src/app/shared/form/form.component.html b/src/app/shared/form/form.component.html index 8f5c18a6cf..7f6efc5b9f 100644 --- a/src/app/shared/form/form.component.html +++ b/src/app/shared/form/form.component.html @@ -14,14 +14,12 @@
-
-
@@ -31,13 +29,6 @@ (click)="insertItem($event, group.context, group.context.groups.length)"> {{'form.add' | translate}} -
@@ -54,6 +45,7 @@
+ diff --git a/src/app/shared/form/form.component.ts b/src/app/shared/form/form.component.ts index bd742dc9c6..c2b690504a 100644 --- a/src/app/shared/form/form.component.ts +++ b/src/app/shared/form/form.component.ts @@ -10,15 +10,13 @@ import { DynamicFormGroupModel, DynamicFormLayout, } from '@ng-dynamic-forms/core'; -import { NgbModal, NgbModalRef } from '@ng-bootstrap/ng-bootstrap'; +import { NgbModalRef } from '@ng-bootstrap/ng-bootstrap'; import { findIndex } from 'lodash'; import { FormBuilderService } from './builder/form-builder.service'; import { hasValue, isNotEmpty, isNotNull, isNull } from '../empty.util'; import { FormService } from './form.service'; import { FormEntry, FormError } from './form.reducer'; -import { DsDynamicLookupRelationModalComponent } from './builder/ds-dynamic-form-ui/relation-lookup-modal/dynamic-lookup-relation-modal.component'; -import { RelationshipOptions } from './builder/models/relationship-options.model'; import { FormFieldMetadataValueObject } from './builder/models/form-field-metadata-value.model'; /** @@ -101,8 +99,7 @@ export class FormComponent implements OnDestroy, OnInit { constructor(private formService: FormService, protected changeDetectorRef: ChangeDetectorRef, - private formBuilderService: FormBuilderService, - private modalService: NgbModal) { + private formBuilderService: FormBuilderService) { } /** @@ -169,7 +166,6 @@ export class FormComponent implements OnDestroy, OnInit { filter((formState: FormEntry) => !!formState && (isNotEmpty(formState.errors) || isNotEmpty(this.formErrors))), map((formState) => formState.errors), distinctUntilChanged()) - // .delay(100) // this terrible delay is here to prevent the detection change error .subscribe((errors: FormError[]) => { const { formGroup, formModel } = this; errors @@ -320,42 +316,6 @@ export class FormComponent implements OnDestroy, OnInit { return isNotEmpty(value) && value.isVirtual; } - hasRelationship(arrayContext: DynamicFormArrayModel, index: number) { - const context = arrayContext.groups[index]; - const model = context.group[0] as any; - return isNotEmpty(model) && model.hasOwnProperty('relationship') && isNotEmpty(model.relationship); - } - - /** - * Open a modal where the user can select relationships to be added to item being submitted - */ - openLookup(arrayContext: DynamicFormArrayModel, index: number) { - const context = arrayContext.groups[index]; - const model = context.group[0] as any; - this.modalRef = this.modalService.open(DsDynamicLookupRelationModalComponent, { - size: 'lg' - }); - const modalComp = this.modalRef.componentInstance; - - if (hasValue(model.value) && !model.readOnly) { - if (typeof model.value === 'string') { - modalComp.query = model.value; - } else if (typeof model.value.value === 'string') { - modalComp.query = model.value.value; - } - } - - const config = model.relationshipConfig || model.relationship; - const relationshipOptions = Object.assign(new RelationshipOptions(), config); - - modalComp.repeatable = model.repeatable; - modalComp.listId = `list-${model.submissionId}-${relationshipOptions.relationshipType}`; - modalComp.relationshipOptions = model.relationship; - modalComp.label = model.relationship.relationshipType; - modalComp.metadataFields = model.metadataFields; - modalComp.submissionId = model.submissionId; - } - protected getEvent($event: any, arrayContext: DynamicFormArrayModel, index: number, type: string): DynamicFormControlEvent { const context = arrayContext.groups[index]; const itemGroupModel = context.context; From a66ec43cccaa63bd8f5b21e244f5c56923828a59 Mon Sep 17 00:00:00 2001 From: Alessandro Martelli Date: Thu, 25 Feb 2021 19:07:51 +0100 Subject: [PATCH 051/132] [CST-3782] Disabled drag when only one value is present --- .../models/array-group/dynamic-form-array.component.html | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/app/shared/form/builder/ds-dynamic-form-ui/models/array-group/dynamic-form-array.component.html b/src/app/shared/form/builder/ds-dynamic-form-ui/models/array-group/dynamic-form-array.component.html index 732b5978ac..1c14c0b994 100644 --- a/src/app/shared/form/builder/ds-dynamic-form-ui/models/array-group/dynamic-form-array.component.html +++ b/src/app/shared/form/builder/ds-dynamic-form-ui/models/array-group/dynamic-form-array.component.html @@ -10,7 +10,9 @@ role="group" [formGroupName]="idx" [ngClass]="[getClass('element', 'group'), getClass('grid', 'group')]" - cdkDrag cdkDragHandle> + cdkDrag + cdkDragHandle + [cdkDragDisabled]="model.groups.length === 1">
From 3d4f8c5222531fd98ef20b3d47021f781fe25daa Mon Sep 17 00:00:00 2001 From: Yura Bondarenko Date: Fri, 26 Feb 2021 08:33:28 +0100 Subject: [PATCH 052/132] 77205: Wrap all section-specific methods in createMenu --- .../admin-sidebar/admin-sidebar.component.ts | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/src/app/+admin/admin-sidebar/admin-sidebar.component.ts b/src/app/+admin/admin-sidebar/admin-sidebar.component.ts index 2748254dbb..1dd8e020f9 100644 --- a/src/app/+admin/admin-sidebar/admin-sidebar.component.ts +++ b/src/app/+admin/admin-sidebar/admin-sidebar.component.ts @@ -76,10 +76,6 @@ export class AdminSidebarComponent extends MenuComponent implements OnInit { */ ngOnInit(): void { this.createMenu(); - this.createSiteAdministratorMenuSections(); - this.createExportMenuSections(); - this.createImportMenuSections(); - this.createAccessControlMenuSections(); super.ngOnInit(); this.sidebarWidth = this.variableService.getVariable('sidebarItemsWidth'); this.authService.isAuthenticated() @@ -103,6 +99,18 @@ export class AdminSidebarComponent extends MenuComponent implements OnInit { * Initialize all menu sections and items for this menu */ createMenu() { + this.createMainMenuSections(); + this.createSiteAdministratorMenuSections(); + this.createExportMenuSections(); + this.createImportMenuSections(); + this.createAccessControlMenuSections(); + } + + /** + * Initialize the main menu sections. + * edit_community / edit_collection is only included if the current user is a Community or Collection admin + */ + createMainMenuSections() { combineLatest([ this.authorizationService.isAuthorized(FeatureID.IsCollectionAdmin), this.authorizationService.isAuthorized(FeatureID.IsCommunityAdmin), From 1c030e6bad59a9a2436efba3889710c11d9ad82b Mon Sep 17 00:00:00 2001 From: Yura Bondarenko Date: Fri, 26 Feb 2021 10:00:42 +0100 Subject: [PATCH 053/132] 77205: Add unit tests for authorization-dependent admin menu content --- .../admin-sidebar.component.spec.ts | 148 ++++++++++++++++++ src/app/shared/testing/menu-service.stub.ts | 2 +- 2 files changed, 149 insertions(+), 1 deletion(-) diff --git a/src/app/+admin/admin-sidebar/admin-sidebar.component.spec.ts b/src/app/+admin/admin-sidebar/admin-sidebar.component.spec.ts index ec571ff3d5..18e2988f48 100644 --- a/src/app/+admin/admin-sidebar/admin-sidebar.component.spec.ts +++ b/src/app/+admin/admin-sidebar/admin-sidebar.component.spec.ts @@ -16,6 +16,8 @@ import { NgbModal } from '@ng-bootstrap/ng-bootstrap'; import { RouterTestingModule } from '@angular/router/testing'; import { ActivatedRoute } from '@angular/router'; import { AuthorizationDataService } from '../../core/data/feature-authorization/authorization-data.service'; +import { FeatureID } from '../../core/data/feature-authorization/feature-id'; +import createSpy = jasmine.createSpy; describe('AdminSidebarComponent', () => { let comp: AdminSidebarComponent; @@ -170,4 +172,150 @@ describe('AdminSidebarComponent', () => { expect(menuService.collapseMenuPreview).toHaveBeenCalled(); })); }); + + describe('menu', () => { + beforeEach(() => { + spyOn(menuService, 'addSection'); + }); + + describe('for regular user', () => { + beforeEach(() => { + authorizationService.isAuthorized = createSpy('isAuthorized').and.callFake(() => { + return observableOf(false); + }); + }); + + beforeEach(() => { + comp.createMenu(); + }); + + it('should not show site admin section', () => { + expect(menuService.addSection).toHaveBeenCalledWith(comp.menuID, jasmine.objectContaining({ + id: 'admin_search', visible: false, + })); + expect(menuService.addSection).toHaveBeenCalledWith(comp.menuID, jasmine.objectContaining({ + id: 'registries', visible: false, + })); + expect(menuService.addSection).toHaveBeenCalledWith(comp.menuID, jasmine.objectContaining({ + parentID: 'registries', visible: false, + })); + expect(menuService.addSection).toHaveBeenCalledWith(comp.menuID, jasmine.objectContaining({ + id: 'curation_tasks', visible: false, + })); + expect(menuService.addSection).toHaveBeenCalledWith(comp.menuID, jasmine.objectContaining({ + id: 'workflow', visible: false, + })); + }); + + it('should not show edit_community', () => { + expect(menuService.addSection).toHaveBeenCalledWith(comp.menuID, jasmine.objectContaining({ + id: 'edit_community', visible: false, + })); + + }); + + it('should not show edit_collection', () => { + expect(menuService.addSection).toHaveBeenCalledWith(comp.menuID, jasmine.objectContaining({ + id: 'edit_collection', visible: false, + })); + }); + + it('should not show access control section', () => { + expect(menuService.addSection).toHaveBeenCalledWith(comp.menuID, jasmine.objectContaining({ + id: 'access_control', visible: false, + })); + expect(menuService.addSection).toHaveBeenCalledWith(comp.menuID, jasmine.objectContaining({ + parentID: 'access_control', visible: false, + })); + + }); + }) + + describe('for site admin', () => { + beforeEach(() => { + authorizationService.isAuthorized = createSpy('isAuthorized').and.callFake((featureID: FeatureID) => { + return observableOf(featureID === FeatureID.AdministratorOf); + }); + }); + + beforeEach(() => { + comp.createMenu(); + }); + + it('should contain site admin section', () => { + expect(menuService.addSection).toHaveBeenCalledWith(comp.menuID, jasmine.objectContaining({ + id: 'admin_search', visible: true, + })); + expect(menuService.addSection).toHaveBeenCalledWith(comp.menuID, jasmine.objectContaining({ + id: 'registries', visible: true, + })); + expect(menuService.addSection).toHaveBeenCalledWith(comp.menuID, jasmine.objectContaining({ + parentID: 'registries', visible: true, + })); + expect(menuService.addSection).toHaveBeenCalledWith(comp.menuID, jasmine.objectContaining({ + id: 'curation_tasks', visible: true, + })); + expect(menuService.addSection).toHaveBeenCalledWith(comp.menuID, jasmine.objectContaining({ + id: 'workflow', visible: true, + })); + }); + }); + + describe('for community admin', () => { + beforeEach(() => { + authorizationService.isAuthorized = createSpy('isAuthorized').and.callFake((featureID: FeatureID) => { + return observableOf(featureID === FeatureID.IsCommunityAdmin); + }); + }); + + beforeEach(() => { + comp.createMenu(); + }); + + it('should show edit_community', () => { + expect(menuService.addSection).toHaveBeenCalledWith(comp.menuID, jasmine.objectContaining({ + id: 'edit_community', visible: true, + })); + }); + }); + + describe('for collection admin', () => { + beforeEach(() => { + authorizationService.isAuthorized = createSpy('isAuthorized').and.callFake((featureID: FeatureID) => { + return observableOf(featureID === FeatureID.IsCollectionAdmin); + }); + }); + + beforeEach(() => { + comp.createMenu(); + }); + + it('should show edit_collection', () => { + expect(menuService.addSection).toHaveBeenCalledWith(comp.menuID, jasmine.objectContaining({ + id: 'edit_collection', visible: true, + })); + }); + }); + + describe('for group admin', () => { + beforeEach(() => { + authorizationService.isAuthorized = createSpy('isAuthorized').and.callFake((featureID: FeatureID) => { + return observableOf(featureID === FeatureID.CanManageGroups); + }); + }); + + beforeEach(() => { + comp.createMenu(); + }); + + it('should show access control section', () => { + expect(menuService.addSection).toHaveBeenCalledWith(comp.menuID, jasmine.objectContaining({ + id: 'access_control', visible: true, + })); + expect(menuService.addSection).toHaveBeenCalledWith(comp.menuID, jasmine.objectContaining({ + parentID: 'access_control', visible: true, + })); + }); + }); + }); }); diff --git a/src/app/shared/testing/menu-service.stub.ts b/src/app/shared/testing/menu-service.stub.ts index 1b6824c8ee..4f2828a7e1 100644 --- a/src/app/shared/testing/menu-service.stub.ts +++ b/src/app/shared/testing/menu-service.stub.ts @@ -52,7 +52,7 @@ export class MenuServiceStub { deactivateSection(): void { /***/ } - addSection(): void { /***/ + addSection(menuID: MenuID, section: MenuSection): void { /***/ } removeSection(): void { /***/ From 47adba98b5bbea3d7f91c7c0d27bff7a1997888b Mon Sep 17 00:00:00 2001 From: Yura Bondarenko Date: Fri, 26 Feb 2021 10:14:55 +0100 Subject: [PATCH 054/132] 77205: Extend FeatureAuthorizationGuard for isCommunityAdmin/isCollectionAdmin --- .../edit-collection-page.routing.module.ts | 4 +-- .../edit-community-page.routing.module.ts | 4 +-- .../collection-administrator.guard.ts | 27 +++++++++++++++++++ .../community-administrator.guard.ts | 27 +++++++++++++++++++ 4 files changed, 58 insertions(+), 4 deletions(-) create mode 100644 src/app/core/data/feature-authorization/feature-authorization-guard/collection-administrator.guard.ts create mode 100644 src/app/core/data/feature-authorization/feature-authorization-guard/community-administrator.guard.ts diff --git a/src/app/+collection-page/edit-collection-page/edit-collection-page.routing.module.ts b/src/app/+collection-page/edit-collection-page/edit-collection-page.routing.module.ts index 0e6e202230..e523cee991 100644 --- a/src/app/+collection-page/edit-collection-page/edit-collection-page.routing.module.ts +++ b/src/app/+collection-page/edit-collection-page/edit-collection-page.routing.module.ts @@ -12,7 +12,7 @@ import { ResourcePolicyTargetResolver } from '../../shared/resource-policies/res import { ResourcePolicyCreateComponent } from '../../shared/resource-policies/create/resource-policy-create.component'; import { ResourcePolicyResolver } from '../../shared/resource-policies/resolvers/resource-policy.resolver'; import { ResourcePolicyEditComponent } from '../../shared/resource-policies/edit/resource-policy-edit.component'; -import { CollectionPageAdministratorGuard } from '../collection-page-administrator.guard'; +import { CollectionAdministratorGuard } from '../../core/data/feature-authorization/feature-authorization-guard/collection-administrator.guard'; /** * Routing module that handles the routing for the Edit Collection page administrator functionality @@ -27,7 +27,7 @@ import { CollectionPageAdministratorGuard } from '../collection-page-administrat }, data: { breadcrumbKey: 'collection.edit' }, component: EditCollectionPageComponent, - canActivate: [CollectionPageAdministratorGuard], + canActivate: [CollectionAdministratorGuard], children: [ { path: '', diff --git a/src/app/+community-page/edit-community-page/edit-community-page.routing.module.ts b/src/app/+community-page/edit-community-page/edit-community-page.routing.module.ts index deb14fced0..faebb1ef2e 100644 --- a/src/app/+community-page/edit-community-page/edit-community-page.routing.module.ts +++ b/src/app/+community-page/edit-community-page/edit-community-page.routing.module.ts @@ -10,7 +10,7 @@ import { ResourcePolicyTargetResolver } from '../../shared/resource-policies/res import { ResourcePolicyCreateComponent } from '../../shared/resource-policies/create/resource-policy-create.component'; import { ResourcePolicyResolver } from '../../shared/resource-policies/resolvers/resource-policy.resolver'; import { ResourcePolicyEditComponent } from '../../shared/resource-policies/edit/resource-policy-edit.component'; -import { CommunityPageAdministratorGuard } from '../community-page-administrator.guard'; +import { CommunityAdministratorGuard } from '../../core/data/feature-authorization/feature-authorization-guard/community-administrator.guard'; /** * Routing module that handles the routing for the Edit Community page administrator functionality @@ -25,7 +25,7 @@ import { CommunityPageAdministratorGuard } from '../community-page-administrator }, data: { breadcrumbKey: 'community.edit' }, component: EditCommunityPageComponent, - canActivate: [CommunityPageAdministratorGuard], + canActivate: [CommunityAdministratorGuard], children: [ { path: '', diff --git a/src/app/core/data/feature-authorization/feature-authorization-guard/collection-administrator.guard.ts b/src/app/core/data/feature-authorization/feature-authorization-guard/collection-administrator.guard.ts new file mode 100644 index 0000000000..bc39397ed9 --- /dev/null +++ b/src/app/core/data/feature-authorization/feature-authorization-guard/collection-administrator.guard.ts @@ -0,0 +1,27 @@ +import { Injectable } from '@angular/core'; +import { FeatureAuthorizationGuard } from './feature-authorization.guard'; +import { AuthorizationDataService } from '../authorization-data.service'; +import { ActivatedRouteSnapshot, Router, RouterStateSnapshot } from '@angular/router'; +import { AuthService } from '../../../auth/auth.service'; +import { Observable, of as observableOf } from 'rxjs'; +import { FeatureID } from '../feature-id'; + +/** + * Prevent unauthorized activating and loading of routes when the current authenticated user + * isn't a Collection administrator + */ +@Injectable({ + providedIn: 'root' +}) +export class CollectionAdministratorGuard extends FeatureAuthorizationGuard { + constructor(protected authorizationService: AuthorizationDataService, protected router: Router, protected authService: AuthService) { + super(authorizationService, router, authService); + } + + /** + * Check group management rights + */ + getFeatureID(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable { + return observableOf(FeatureID.IsCollectionAdmin); + } +} diff --git a/src/app/core/data/feature-authorization/feature-authorization-guard/community-administrator.guard.ts b/src/app/core/data/feature-authorization/feature-authorization-guard/community-administrator.guard.ts new file mode 100644 index 0000000000..afb1fea63d --- /dev/null +++ b/src/app/core/data/feature-authorization/feature-authorization-guard/community-administrator.guard.ts @@ -0,0 +1,27 @@ +import { Injectable } from '@angular/core'; +import { FeatureAuthorizationGuard } from './feature-authorization.guard'; +import { AuthorizationDataService } from '../authorization-data.service'; +import { ActivatedRouteSnapshot, Router, RouterStateSnapshot } from '@angular/router'; +import { AuthService } from '../../../auth/auth.service'; +import { Observable, of as observableOf } from 'rxjs'; +import { FeatureID } from '../feature-id'; + +/** + * Prevent unauthorized activating and loading of routes when the current authenticated user + * isn't a Community administrator + */ +@Injectable({ + providedIn: 'root' +}) +export class CommunityAdministratorGuard extends FeatureAuthorizationGuard { + constructor(protected authorizationService: AuthorizationDataService, protected router: Router, protected authService: AuthService) { + super(authorizationService, router, authService); + } + + /** + * Check group management rights + */ + getFeatureID(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable { + return observableOf(FeatureID.IsCommunityAdmin); + } +} From 7e0866afe7a41570a18d6a13f8979fc477e17d23 Mon Sep 17 00:00:00 2001 From: Yura Bondarenko Date: Fri, 26 Feb 2021 11:08:57 +0100 Subject: [PATCH 055/132] 77205: Fix leftover links to /admin/access-control/ --- .../epeople-registry/epeople-registry.component.spec.ts | 2 +- .../group-registry/group-form/group-form.component.spec.ts | 2 +- .../group-form/members-list/members-list.component.spec.ts | 4 ++-- .../group-form/subgroup-list/subgroups-list.component.spec.ts | 2 +- .../group-registry/groups-registry.component.spec.ts | 4 ++-- src/app/core/eperson/eperson-data.service.ts | 4 ++-- src/app/core/eperson/group-data.service.ts | 4 ++-- .../shared/resource-policies/resource-policies.component.ts | 2 +- 8 files changed, 12 insertions(+), 12 deletions(-) diff --git a/src/app/access-control/epeople-registry/epeople-registry.component.spec.ts b/src/app/access-control/epeople-registry/epeople-registry.component.spec.ts index 425a61ddb3..2fb955bb02 100644 --- a/src/app/access-control/epeople-registry/epeople-registry.component.spec.ts +++ b/src/app/access-control/epeople-registry/epeople-registry.component.spec.ts @@ -107,7 +107,7 @@ describe('EPeopleRegistryComponent', () => { // empty }, getEPeoplePageRouterLink(): string { - return '/admin/access-control/epeople'; + return '/access-control/epeople'; } }; authorizationService = jasmine.createSpyObj('authorizationService', { diff --git a/src/app/access-control/group-registry/group-form/group-form.component.spec.ts b/src/app/access-control/group-registry/group-form/group-form.component.spec.ts index 00fe2aa6e6..d213a071d7 100644 --- a/src/app/access-control/group-registry/group-form/group-form.component.spec.ts +++ b/src/app/access-control/group-registry/group-form/group-form.component.spec.ts @@ -75,7 +75,7 @@ describe('GroupFormComponent', () => { return observableOf(this.activeGroup); }, getGroupRegistryRouterLink(): string { - return '/admin/access-control/groups'; + return '/access-control/groups'; }, editGroup(group: Group) { this.activeGroup = group; diff --git a/src/app/access-control/group-registry/group-form/members-list/members-list.component.spec.ts b/src/app/access-control/group-registry/group-form/members-list/members-list.component.spec.ts index bb7fd48ec6..20419fb49d 100644 --- a/src/app/access-control/group-registry/group-form/members-list/members-list.component.spec.ts +++ b/src/app/access-control/group-registry/group-form/members-list/members-list.component.spec.ts @@ -66,7 +66,7 @@ describe('MembersListComponent', () => { // empty }, getEPeoplePageRouterLink(): string { - return '/admin/access-control/epeople'; + return '/access-control/epeople'; } }; groupsDataServiceStub = { @@ -97,7 +97,7 @@ describe('MembersListComponent', () => { // empty }, getGroupEditPageRouterLink(group: Group): string { - return '/admin/access-control/groups/' + group.id; + return '/access-control/groups/' + group.id; }, deleteMemberFromGroup(parentGroup, epersonToDelete: EPerson): Observable { this.epersonMembers = this.epersonMembers.find((eperson: EPerson) => { diff --git a/src/app/access-control/group-registry/group-form/subgroup-list/subgroups-list.component.spec.ts b/src/app/access-control/group-registry/group-form/subgroup-list/subgroups-list.component.spec.ts index b8ba1e4f13..e839d77a6a 100644 --- a/src/app/access-control/group-registry/group-form/subgroup-list/subgroups-list.component.spec.ts +++ b/src/app/access-control/group-registry/group-form/subgroup-list/subgroups-list.component.spec.ts @@ -70,7 +70,7 @@ describe('SubgroupsListComponent', () => { ); }, getGroupEditPageRouterLink(group: Group): string { - return '/admin/access-control/groups/' + group.id; + return '/access-control/groups/' + group.id; }, searchGroups(query: string): Observable>> { if (query === '') { diff --git a/src/app/access-control/group-registry/groups-registry.component.spec.ts b/src/app/access-control/group-registry/groups-registry.component.spec.ts index c7d502eff6..b5b5a1b209 100644 --- a/src/app/access-control/group-registry/groups-registry.component.spec.ts +++ b/src/app/access-control/group-registry/groups-registry.component.spec.ts @@ -98,10 +98,10 @@ describe('GroupRegistryComponent', () => { } }, getGroupEditPageRouterLink(group: Group): string { - return '/admin/access-control/groups/' + group.id; + return '/access-control/groups/' + group.id; }, getGroupRegistryRouterLink(): string { - return '/admin/access-control/groups'; + return '/access-control/groups'; }, searchGroups(query: string): Observable>> { if (query === '') { diff --git a/src/app/core/eperson/eperson-data.service.ts b/src/app/core/eperson/eperson-data.service.ts index 5b52510ddd..bceb38f163 100644 --- a/src/app/core/eperson/eperson-data.service.ts +++ b/src/app/core/eperson/eperson-data.service.ts @@ -269,7 +269,7 @@ export class EPersonDataService extends DataService { this.editEPerson(ePerson); } }); - return '/admin/access-control/epeople'; + return '/access-control/epeople'; } /** @@ -277,7 +277,7 @@ export class EPersonDataService extends DataService { * @param ePerson New EPerson to edit */ public getEPeoplePageRouterLink(): string { - return '/admin/access-control/epeople'; + return '/access-control/epeople'; } /** diff --git a/src/app/core/eperson/group-data.service.ts b/src/app/core/eperson/group-data.service.ts index cff1c37f09..5b8f474d1a 100644 --- a/src/app/core/eperson/group-data.service.ts +++ b/src/app/core/eperson/group-data.service.ts @@ -209,7 +209,7 @@ export class GroupDataService extends DataService { } public getGroupRegistryRouterLink(): string { - return '/admin/access-control/groups'; + return '/access-control/groups'; } /** @@ -240,7 +240,7 @@ export class GroupDataService extends DataService { * @param groupID Group ID we want edit page for */ public getGroupEditPageRouterLinkWithID(groupId: string): string { - return '/admin/access-control/groups/' + groupId; + return '/access-control/groups/' + groupId; } /** diff --git a/src/app/shared/resource-policies/resource-policies.component.ts b/src/app/shared/resource-policies/resource-policies.component.ts index bc83314ee4..8380c78db1 100644 --- a/src/app/shared/resource-policies/resource-policies.component.ts +++ b/src/app/shared/resource-policies/resource-policies.component.ts @@ -316,7 +316,7 @@ export class ResourcePoliciesComponent implements OnInit, OnDestroy { getFirstSucceededRemoteDataPayload(), map((group: Group) => group.id) ).subscribe((groupUUID) => { - this.router.navigate([ADMIN_MODULE_PATH, ACCESS_CONTROL_MODULE_PATH, GROUP_EDIT_PATH, groupUUID]); + this.router.navigate([ACCESS_CONTROL_MODULE_PATH, GROUP_EDIT_PATH, groupUUID]); }) ); } From bfbe598bddd3226e1adfc9da50f2a4bc307f15f2 Mon Sep 17 00:00:00 2001 From: Yura Bondarenko Date: Fri, 26 Feb 2021 15:25:00 +0100 Subject: [PATCH 056/132] TESTING: sectionID argument to debug getComponentForMenu --- src/app/shared/menu/menu-section.decorator.ts | 2 +- src/app/shared/menu/menu.component.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/app/shared/menu/menu-section.decorator.ts b/src/app/shared/menu/menu-section.decorator.ts index c27e870e13..241e9cdf6b 100644 --- a/src/app/shared/menu/menu-section.decorator.ts +++ b/src/app/shared/menu/menu-section.decorator.ts @@ -26,6 +26,6 @@ export function rendersSectionForMenu(menuID: MenuID, expandable: boolean) { * @param {boolean} expandable True when the section should be expandable, false when if should not * @returns {GenericConstructor} The constructor of the matching Component */ -export function getComponentForMenu(menuID: MenuID, expandable: boolean) { +export function getComponentForMenu(menuID: MenuID, expandable: boolean, sectionID: string) { return menuComponentMap.get(menuID).get(expandable); } diff --git a/src/app/shared/menu/menu.component.ts b/src/app/shared/menu/menu.component.ts index bc22b254b8..e02753006a 100644 --- a/src/app/shared/menu/menu.component.ts +++ b/src/app/shared/menu/menu.component.ts @@ -164,7 +164,7 @@ export class MenuComponent implements OnInit, OnDestroy { private getSectionComponent(section: MenuSection): Observable> { return this.menuService.hasSubSections(this.menuID, section.id).pipe( map((expandable: boolean) => { - return getComponentForMenu(this.menuID, expandable); + return getComponentForMenu(this.menuID, expandable, section.id); } ), ); From e23e46b212fe1ab8d4eebc6408e0f6924df0bbb9 Mon Sep 17 00:00:00 2001 From: Yura Bondarenko Date: Fri, 26 Feb 2021 16:12:54 +0100 Subject: [PATCH 057/132] Revert "TESTING: sectionID argument to debug getComponentForMenu" This reverts commit bfbe598bddd3226e1adfc9da50f2a4bc307f15f2. --- src/app/shared/menu/menu-section.decorator.ts | 2 +- src/app/shared/menu/menu.component.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/app/shared/menu/menu-section.decorator.ts b/src/app/shared/menu/menu-section.decorator.ts index 241e9cdf6b..c27e870e13 100644 --- a/src/app/shared/menu/menu-section.decorator.ts +++ b/src/app/shared/menu/menu-section.decorator.ts @@ -26,6 +26,6 @@ export function rendersSectionForMenu(menuID: MenuID, expandable: boolean) { * @param {boolean} expandable True when the section should be expandable, false when if should not * @returns {GenericConstructor} The constructor of the matching Component */ -export function getComponentForMenu(menuID: MenuID, expandable: boolean, sectionID: string) { +export function getComponentForMenu(menuID: MenuID, expandable: boolean) { return menuComponentMap.get(menuID).get(expandable); } diff --git a/src/app/shared/menu/menu.component.ts b/src/app/shared/menu/menu.component.ts index e02753006a..bc22b254b8 100644 --- a/src/app/shared/menu/menu.component.ts +++ b/src/app/shared/menu/menu.component.ts @@ -164,7 +164,7 @@ export class MenuComponent implements OnInit, OnDestroy { private getSectionComponent(section: MenuSection): Observable> { return this.menuService.hasSubSections(this.menuID, section.id).pipe( map((expandable: boolean) => { - return getComponentForMenu(this.menuID, expandable, section.id); + return getComponentForMenu(this.menuID, expandable); } ), ); From 8b2db8626858cddc00489744f1aa4873da8be40e Mon Sep 17 00:00:00 2001 From: Yura Bondarenko Date: Fri, 26 Feb 2021 16:12:36 +0100 Subject: [PATCH 058/132] 77205: Workaround: add access_control parent section after child sections --- .../admin-sidebar/admin-sidebar.component.ts | 22 +++++++++---------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/src/app/+admin/admin-sidebar/admin-sidebar.component.ts b/src/app/+admin/admin-sidebar/admin-sidebar.component.ts index 1dd8e020f9..51a4a4ae8d 100644 --- a/src/app/+admin/admin-sidebar/admin-sidebar.component.ts +++ b/src/app/+admin/admin-sidebar/admin-sidebar.component.ts @@ -540,17 +540,6 @@ export class AdminSidebarComponent extends MenuComponent implements OnInit { this.authorizationService.isAuthorized(FeatureID.CanManageGroups).subscribe((authorized) => { const menuList = [ /* Access Control */ - { - id: 'access_control', - active: false, - visible: authorized, - model: { - type: MenuItemType.TEXT, - text: 'menu.section.access_control' - } as TextMenuItemModel, - icon: 'key', - index: 4 - }, { id: 'access_control_people', parentID: 'access_control', @@ -584,6 +573,17 @@ export class AdminSidebarComponent extends MenuComponent implements OnInit { link: '' } as LinkMenuItemModel, }, + { + id: 'access_control', + active: false, + visible: authorized, + model: { + type: MenuItemType.TEXT, + text: 'menu.section.access_control' + } as TextMenuItemModel, + icon: 'key', + index: 4 + }, ]; menuList.forEach((menuSection) => this.menuService.addSection(this.menuID, Object.assign(menuSection, { From 913ead60199dd2e26f3ee7873221a040d6e416f4 Mon Sep 17 00:00:00 2001 From: lotte Date: Fri, 26 Feb 2021 17:27:02 +0100 Subject: [PATCH 059/132] 77237: overwriteMerge environment files merge --- scripts/set-env.ts | 8 ++++---- src/app/core/shared/metadata.utils.ts | 2 ++ 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/scripts/set-env.ts b/scripts/set-env.ts index 5eee22a4be..b3516ae68f 100644 --- a/scripts/set-env.ts +++ b/scripts/set-env.ts @@ -10,7 +10,7 @@ const targetPath = './src/environments/environment.ts'; const colors = require('colors'); require('dotenv').config(); const merge = require('deepmerge'); - +const mergeOptions = { arrayMerge: (destinationArray, sourceArray, options) => sourceArray }; const environment = process.argv[2]; let environmentFilePath; let production = false; @@ -45,10 +45,10 @@ const processEnv = { } as GlobalConfig; import(environmentFilePath) - .then((file) => generateEnvironmentFile(merge.all([commonEnv, file.environment, processEnv]))) + .then((file) => generateEnvironmentFile(merge.all([commonEnv, file.environment, processEnv], mergeOptions))) .catch(() => { console.log(colors.yellow.bold(`No specific environment file found for ` + environment)); - generateEnvironmentFile(merge(commonEnv, processEnv)) + generateEnvironmentFile(merge(commonEnv, processEnv, mergeOptions)) }); function generateEnvironmentFile(file: GlobalConfig): void { @@ -65,7 +65,7 @@ function generateEnvironmentFile(file: GlobalConfig): void { } // allow to override a few important options by environment variables -function createServerConfig(host?: string, port?: string, nameSpace?: string, ssl?: string): ServerConfig { +function createServerConfig(host?: string, port?: string, nameSpace?: string, ssl?: string): ServerConfig { const result = {} as any; if (hasValue(host)) { result.host = host; diff --git a/src/app/core/shared/metadata.utils.ts b/src/app/core/shared/metadata.utils.ts index 612fba1d4a..41e6afd7f2 100644 --- a/src/app/core/shared/metadata.utils.ts +++ b/src/app/core/shared/metadata.utils.ts @@ -156,7 +156,9 @@ export class Metadata { const outputKeys: string[] = []; for (const inputKey of inputKeys) { if (inputKey.includes('*')) { + const inputKeyRegex = new RegExp('^' + inputKey.replace('.', '\.').replace('*', '.*') + '$'); + for (const mapKey of Object.keys(mdMap)) { if (!outputKeys.includes(mapKey) && inputKeyRegex.test(mapKey)) { outputKeys.push(mapKey); From 4f08ad453f8b1589100ad67a033ab2dcd903a684 Mon Sep 17 00:00:00 2001 From: Raf Ponsaerts Date: Thu, 4 Mar 2021 09:48:27 +0100 Subject: [PATCH 060/132] removed whitelines --- src/app/core/shared/metadata.utils.ts | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/app/core/shared/metadata.utils.ts b/src/app/core/shared/metadata.utils.ts index 41e6afd7f2..612fba1d4a 100644 --- a/src/app/core/shared/metadata.utils.ts +++ b/src/app/core/shared/metadata.utils.ts @@ -156,9 +156,7 @@ export class Metadata { const outputKeys: string[] = []; for (const inputKey of inputKeys) { if (inputKey.includes('*')) { - const inputKeyRegex = new RegExp('^' + inputKey.replace('.', '\.').replace('*', '.*') + '$'); - for (const mapKey of Object.keys(mdMap)) { if (!outputKeys.includes(mapKey) && inputKeyRegex.test(mapKey)) { outputKeys.push(mapKey); From 5eb0a8744f4f85a1040ebdac9232cda498f2a2ff Mon Sep 17 00:00:00 2001 From: Alessandro Martelli Date: Thu, 4 Mar 2021 11:49:28 +0100 Subject: [PATCH 061/132] [CSTPER-3782] custom move events handled correctly --- .../dynamic-form-array.component.ts | 15 ++---- src/app/shared/form/form.component.html | 3 +- src/app/shared/form/form.component.ts | 5 ++ .../form/section-form-operations.service.ts | 46 +++++++++++++++---- .../sections/form/section-form.component.html | 1 + .../sections/form/section-form.component.ts | 13 ++++++ 6 files changed, 62 insertions(+), 21 deletions(-) diff --git a/src/app/shared/form/builder/ds-dynamic-form-ui/models/array-group/dynamic-form-array.component.ts b/src/app/shared/form/builder/ds-dynamic-form-ui/models/array-group/dynamic-form-array.component.ts index b6c1a6c308..42a02fee45 100644 --- a/src/app/shared/form/builder/ds-dynamic-form-ui/models/array-group/dynamic-form-array.component.ts +++ b/src/app/shared/form/builder/ds-dynamic-form-ui/models/array-group/dynamic-form-array.component.ts @@ -6,7 +6,6 @@ import { DynamicFormArrayModel, DynamicFormControlCustomEvent, DynamicFormControlEvent, - DynamicFormControlEventType, DynamicFormControlLayout, DynamicFormLayout, DynamicFormLayoutService, @@ -55,16 +54,12 @@ export class DsDynamicFormArrayComponent extends DynamicFormArrayComponent { const index = event.currentIndex; if (hasValue(this.model.groups[index]) && hasValue((this.control as any).controls[index])) { - const $event = { - $event: { previousIndex: prevIndex }, - context: { index }, - control: (this.control as any).controls[index], - group: this.group, + this.onCustomEvent({ + previousIndex: prevIndex, + index, model: this.model.groups[index].group[0], - type: DynamicFormControlEventType.Change - }; - - this.onChange($event); + control: (this.control as any).controls[index] + }, 'move'); } } diff --git a/src/app/shared/form/form.component.html b/src/app/shared/form/form.component.html index 7f6efc5b9f..10ec8da3b9 100644 --- a/src/app/shared/form/form.component.html +++ b/src/app/shared/form/form.component.html @@ -9,7 +9,8 @@ (change)="$event.stopPropagation();" (dfBlur)="onBlur($event)" (dfChange)="onChange($event)" - (dfFocus)="onFocus($event)"> + (dfFocus)="onFocus($event)" + (ngbEvent)="onCustomEvent($event)">
= new EventEmitter(); @Output('dfChange') change: EventEmitter = new EventEmitter(); @Output('dfFocus') focus: EventEmitter = new EventEmitter(); + @Output('ngbEvent') customEvent: EventEmitter = new EventEmitter(); /* tslint:enable:no-output-rename */ @Output() addArrayItem: EventEmitter = new EventEmitter(); @Output() removeArrayItem: EventEmitter = new EventEmitter(); @@ -250,6 +251,10 @@ export class FormComponent implements OnDestroy, OnInit { this.blur.emit(event); } + onCustomEvent(event: any) { + this.customEvent.emit(event); + } + onFocus(event: DynamicFormControlEvent): void { this.formService.setTouched(this.formId, this.formModel, event); this.focus.emit(event); diff --git a/src/app/submission/sections/form/section-form-operations.service.ts b/src/app/submission/sections/form/section-form-operations.service.ts index 27e4f73876..136203329f 100644 --- a/src/app/submission/sections/form/section-form-operations.service.ts +++ b/src/app/submission/sections/form/section-form-operations.service.ts @@ -6,7 +6,7 @@ import { DYNAMIC_FORM_CONTROL_TYPE_GROUP, DynamicFormArrayGroupModel, DynamicFormControlEvent, - DynamicFormControlModel + DynamicFormControlModel, isDynamicFormControlEvent } from '@ng-dynamic-forms/core'; import { hasValue, isNotEmpty, isNotNull, isNotUndefined, isNull, isUndefined } from '../../../shared/empty.util'; @@ -64,6 +64,9 @@ export class SectionFormOperationsService { case 'change': this.dispatchOperationsFromChangeEvent(pathCombiner, event, previousValue, hasStoredValue); break; + case 'move': + this.dispatchOperationsFromMoveEvent(pathCombiner, event); + break; default: break; } @@ -73,20 +76,29 @@ export class SectionFormOperationsService { * Return index if specified field is part of fields array * * @param event - * the [[DynamicFormControlEvent]] for the specified operation + * the [[DynamicFormControlEvent]] | CustomEvent for the specified operation * @return number * the array index is part of array, zero otherwise */ - public getArrayIndexFromEvent(event: DynamicFormControlEvent): number { + public getArrayIndexFromEvent(event: DynamicFormControlEvent | any): number { let fieldIndex: number; + if (isNotEmpty(event)) { - if (isNull(event.context)) { - // Check whether model is part of an Array of group - if (this.isPartOfArrayOfGroup(event.model)) { - fieldIndex = (event.model.parent as any).parent.index; + if (isDynamicFormControlEvent(event)) { + // This is the case of a default insertItem/removeItem event + + if (isNull(event.context)) { + // Check whether model is part of an Array of group + if (this.isPartOfArrayOfGroup(event.model)) { + fieldIndex = (event.model.parent as any).parent.index; + } + } else { + fieldIndex = event.context.index; } + } else { - fieldIndex = event.context.index; + // This is the case of a custom event which contains indexes information + fieldIndex = event.index as any; } } @@ -394,8 +406,7 @@ export class SectionFormOperationsService { previousValue.delete(); } else if (value.hasValue()) { // Here model has no previous value but a new one - if (isUndefined(this.getArrayIndexFromEvent(event)) - || this.getArrayIndexFromEvent(event) === 0) { + if (isUndefined(this.getArrayIndexFromEvent(event)) || this.getArrayIndexFromEvent(event) === 0) { // Model is single field or is part of an array model but is the first item, // so dispatch an add operation that initialize the values of a specific metadata this.operationsBuilder.add( @@ -457,4 +468,19 @@ export class SectionFormOperationsService { previousValue.delete(); } + + private dispatchOperationsFromMoveEvent(pathCombiner: JsonPatchOperationPathCombiner, + event: DynamicFormControlEvent) { + const customEvent = event.$event; + const path = this.getFieldPathFromEvent(customEvent); + const segmentedPath = this.getFieldPathSegmentedFromChangeEvent(customEvent); + const moveTo = pathCombiner.getPath(path); + const moveFrom = pathCombiner.getPath(segmentedPath + '/' + customEvent.previousIndex); + if (isNotEmpty(moveFrom.path) && isNotEmpty(moveTo.path) && moveFrom.path !== moveTo.path) { + this.operationsBuilder.move( + moveTo, + moveFrom.path + ); + } + } } diff --git a/src/app/submission/sections/form/section-form.component.html b/src/app/submission/sections/form/section-form.component.html index 166e52675b..64e8a05d80 100644 --- a/src/app/submission/sections/form/section-form.component.html +++ b/src/app/submission/sections/form/section-form.component.html @@ -6,4 +6,5 @@ (dfChange)="onChange($event)" (dfFocus)="onFocus($event)" (remove)="onRemove($event)" + (ngbEvent)="onCustomEvent($event)" (removeArrayItem)="onRemove($event)"> diff --git a/src/app/submission/sections/form/section-form.component.ts b/src/app/submission/sections/form/section-form.component.ts index bc88323a8c..2d1b0ed764 100644 --- a/src/app/submission/sections/form/section-form.component.ts +++ b/src/app/submission/sections/form/section-form.component.ts @@ -448,4 +448,17 @@ export class SubmissionSectionformComponent extends SectionModelComponent { isFieldToRemove(fieldId, index) { return this.fieldsOnTheirWayToBeRemoved.has(fieldId) && this.fieldsOnTheirWayToBeRemoved.get(fieldId).includes(index); } + + /** + * Handle the customEvent (ex. drag-drop move event). + * The customEvent is stored inside event.$event + * @param $event + */ + onCustomEvent(event: any) { + this.formOperationsService.dispatchOperationsFromEvent( + this.pathCombiner, + event, + null, + null); + } } From 7a1b98ce838279e9e911316f7adbd433aa10091c Mon Sep 17 00:00:00 2001 From: Raf Ponsaerts Date: Thu, 4 Mar 2021 13:30:07 +0100 Subject: [PATCH 062/132] remove unused import --- src/app/shared/resource-policies/resource-policies.component.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/app/shared/resource-policies/resource-policies.component.ts b/src/app/shared/resource-policies/resource-policies.component.ts index 8380c78db1..30bd7ce45b 100644 --- a/src/app/shared/resource-policies/resource-policies.component.ts +++ b/src/app/shared/resource-policies/resource-policies.component.ts @@ -31,7 +31,7 @@ import { RequestService } from '../../core/data/request.service'; import { NotificationsService } from '../notifications/notifications.service'; import { dateToString, stringToNgbDateStruct } from '../date.util'; import { followLink } from '../utils/follow-link-config.model'; -import { ACCESS_CONTROL_MODULE_PATH, ADMIN_MODULE_PATH } from '../../app-routing-paths'; +import { ACCESS_CONTROL_MODULE_PATH } from '../../app-routing-paths'; import { GROUP_EDIT_PATH } from '../../access-control/access-control-routing-paths'; interface ResourcePolicyCheckboxEntry { From 83819c5b1899da6ddee8799e865e4a377b65e3b1 Mon Sep 17 00:00:00 2001 From: Raf Ponsaerts Date: Thu, 4 Mar 2021 14:32:14 +0100 Subject: [PATCH 063/132] fixed lint issues --- .../admin-sidebar.component.spec.ts | 38 +++++++++---------- .../admin-sidebar/admin-sidebar.component.ts | 4 +- 2 files changed, 21 insertions(+), 21 deletions(-) diff --git a/src/app/+admin/admin-sidebar/admin-sidebar.component.spec.ts b/src/app/+admin/admin-sidebar/admin-sidebar.component.spec.ts index 18e2988f48..0a9ef512d7 100644 --- a/src/app/+admin/admin-sidebar/admin-sidebar.component.spec.ts +++ b/src/app/+admin/admin-sidebar/admin-sidebar.component.spec.ts @@ -229,7 +229,7 @@ describe('AdminSidebarComponent', () => { })); }); - }) + }); describe('for site admin', () => { beforeEach(() => { @@ -244,20 +244,20 @@ describe('AdminSidebarComponent', () => { it('should contain site admin section', () => { expect(menuService.addSection).toHaveBeenCalledWith(comp.menuID, jasmine.objectContaining({ - id: 'admin_search', visible: true, - })); + id: 'admin_search', visible: true, + })); expect(menuService.addSection).toHaveBeenCalledWith(comp.menuID, jasmine.objectContaining({ - id: 'registries', visible: true, - })); + id: 'registries', visible: true, + })); expect(menuService.addSection).toHaveBeenCalledWith(comp.menuID, jasmine.objectContaining({ - parentID: 'registries', visible: true, - })); + parentID: 'registries', visible: true, + })); expect(menuService.addSection).toHaveBeenCalledWith(comp.menuID, jasmine.objectContaining({ - id: 'curation_tasks', visible: true, - })); + id: 'curation_tasks', visible: true, + })); expect(menuService.addSection).toHaveBeenCalledWith(comp.menuID, jasmine.objectContaining({ - id: 'workflow', visible: true, - })); + id: 'workflow', visible: true, + })); }); }); @@ -274,8 +274,8 @@ describe('AdminSidebarComponent', () => { it('should show edit_community', () => { expect(menuService.addSection).toHaveBeenCalledWith(comp.menuID, jasmine.objectContaining({ - id: 'edit_community', visible: true, - })); + id: 'edit_community', visible: true, + })); }); }); @@ -292,8 +292,8 @@ describe('AdminSidebarComponent', () => { it('should show edit_collection', () => { expect(menuService.addSection).toHaveBeenCalledWith(comp.menuID, jasmine.objectContaining({ - id: 'edit_collection', visible: true, - })); + id: 'edit_collection', visible: true, + })); }); }); @@ -310,11 +310,11 @@ describe('AdminSidebarComponent', () => { it('should show access control section', () => { expect(menuService.addSection).toHaveBeenCalledWith(comp.menuID, jasmine.objectContaining({ - id: 'access_control', visible: true, - })); + id: 'access_control', visible: true, + })); expect(menuService.addSection).toHaveBeenCalledWith(comp.menuID, jasmine.objectContaining({ - parentID: 'access_control', visible: true, - })); + parentID: 'access_control', visible: true, + })); }); }); }); diff --git a/src/app/+admin/admin-sidebar/admin-sidebar.component.ts b/src/app/+admin/admin-sidebar/admin-sidebar.component.ts index 51a4a4ae8d..36959a7ffd 100644 --- a/src/app/+admin/admin-sidebar/admin-sidebar.component.ts +++ b/src/app/+admin/admin-sidebar/admin-sidebar.component.ts @@ -301,7 +301,7 @@ export class AdminSidebarComponent extends MenuComponent implements OnInit { menuList.forEach((menuSection) => this.menuService.addSection(this.menuID, Object.assign(menuSection, { shouldPersistOnRouteChange: true }))); - }) + }); } /** @@ -589,7 +589,7 @@ export class AdminSidebarComponent extends MenuComponent implements OnInit { menuList.forEach((menuSection) => this.menuService.addSection(this.menuID, Object.assign(menuSection, { shouldPersistOnRouteChange: true, }))); - }) + }); } /** From 5201b4a31d09b9ff2e1f0d449afe021551e06564 Mon Sep 17 00:00:00 2001 From: Alessandro Martelli Date: Thu, 4 Mar 2021 18:25:01 +0100 Subject: [PATCH 064/132] [CST-3782] qualdrop move restored --- .../form/section-form-operations.service.ts | 23 +++++++++++++++++-- .../sections/form/section-form.component.ts | 6 ++--- 2 files changed, 24 insertions(+), 5 deletions(-) diff --git a/src/app/submission/sections/form/section-form-operations.service.ts b/src/app/submission/sections/form/section-form-operations.service.ts index 136203329f..be0e397ddb 100644 --- a/src/app/submission/sections/form/section-form-operations.service.ts +++ b/src/app/submission/sections/form/section-form-operations.service.ts @@ -65,7 +65,7 @@ export class SectionFormOperationsService { this.dispatchOperationsFromChangeEvent(pathCombiner, event, previousValue, hasStoredValue); break; case 'move': - this.dispatchOperationsFromMoveEvent(pathCombiner, event); + this.dispatchOperationsFromMoveEvent(pathCombiner, event, previousValue); break; default: break; @@ -469,9 +469,28 @@ export class SectionFormOperationsService { previousValue.delete(); } + /** + * Handle form move operations + * + * @param pathCombiner + * the [[JsonPatchOperationPathCombiner]] object for the specified operation + * @param event + * the [[DynamicFormControlEvent]] for the specified operation + * @param previousValue + * the [[FormFieldPreviousValueObject]] for the specified operation + */ private dispatchOperationsFromMoveEvent(pathCombiner: JsonPatchOperationPathCombiner, - event: DynamicFormControlEvent) { + event: DynamicFormControlEvent, + previousValue: FormFieldPreviousValueObject) { + const customEvent = event.$event; + + if (this.formBuilder.isQualdropGroup(customEvent.model.parent as DynamicFormControlModel) + || this.formBuilder.isQualdropGroup(customEvent.model as DynamicFormControlModel)) { + // It's a qualdrup model + this.dispatchOperationsFromMap(this.getQualdropValueMap(customEvent), pathCombiner, customEvent, previousValue); + return; + } const path = this.getFieldPathFromEvent(customEvent); const segmentedPath = this.getFieldPathSegmentedFromChangeEvent(customEvent); const moveTo = pathCombiner.getPath(path); diff --git a/src/app/submission/sections/form/section-form.component.ts b/src/app/submission/sections/form/section-form.component.ts index 2d1b0ed764..99a2e12b47 100644 --- a/src/app/submission/sections/form/section-form.component.ts +++ b/src/app/submission/sections/form/section-form.component.ts @@ -19,7 +19,7 @@ import { FormComponent } from '../../../shared/form/form.component'; import { FormService } from '../../../shared/form/form.service'; import { SectionModelComponent } from '../models/section.model'; import { SubmissionFormsConfigService } from '../../../core/config/submission-forms-config.service'; -import { hasNoValue, hasValue, isNotEmpty, isUndefined } from '../../../shared/empty.util'; +import { hasValue, isNotEmpty, isUndefined } from '../../../shared/empty.util'; import { JsonPatchOperationPathCombiner } from '../../../core/json-patch/builder/json-patch-operation-path-combiner'; import { SubmissionFormsModel } from '../../../core/config/models/config-submission-forms.model'; import { SubmissionSectionError, SubmissionSectionObject } from '../../objects/submission-objects.reducer'; @@ -454,11 +454,11 @@ export class SubmissionSectionformComponent extends SectionModelComponent { * The customEvent is stored inside event.$event * @param $event */ - onCustomEvent(event: any) { + onCustomEvent(event: DynamicFormControlEvent) { this.formOperationsService.dispatchOperationsFromEvent( this.pathCombiner, event, - null, + this.previousValue, null); } } From 28894f67647bf803ce613bd638c1c3f11168f257 Mon Sep 17 00:00:00 2001 From: Alessandro Martelli Date: Wed, 10 Mar 2021 11:24:42 +0100 Subject: [PATCH 065/132] [CST-3782] lookup search icon --- .../ds-dynamic-form-control-container.component.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/app/shared/form/builder/ds-dynamic-form-ui/ds-dynamic-form-control-container.component.html b/src/app/shared/form/builder/ds-dynamic-form-ui/ds-dynamic-form-control-container.component.html index 8ba6489068..eb7b5b720f 100644 --- a/src/app/shared/form/builder/ds-dynamic-form-ui/ds-dynamic-form-control-container.component.html +++ b/src/app/shared/form/builder/ds-dynamic-form-ui/ds-dynamic-form-control-container.component.html @@ -40,7 +40,7 @@ type="button" ngbTooltip="{{'form.lookup-help' | translate}}" placement="top" - (click)="openLookup(); $event.stopPropagation();">{{'form.lookup' | translate}} + (click)="openLookup(); $event.stopPropagation();">
From 996d54f37e858d01ca06fffb66f271bf9145d399 Mon Sep 17 00:00:00 2001 From: Alessandro Martelli Date: Wed, 10 Mar 2021 17:11:53 +0100 Subject: [PATCH 066/132] [CST-3782] item deletion on lookup disabled --- ...ynamic-form-control-container.component.ts | 21 ------------------- 1 file changed, 21 deletions(-) diff --git a/src/app/shared/form/builder/ds-dynamic-form-ui/ds-dynamic-form-control-container.component.ts b/src/app/shared/form/builder/ds-dynamic-form-ui/ds-dynamic-form-control-container.component.ts index 5ab4a7b247..4fbc29f79d 100644 --- a/src/app/shared/form/builder/ds-dynamic-form-ui/ds-dynamic-form-control-container.component.ts +++ b/src/app/shared/form/builder/ds-dynamic-form-ui/ds-dynamic-form-control-container.component.ts @@ -395,27 +395,6 @@ export class DsDynamicFormControlContainerComponent extends DynamicFormControlCo size: 'lg' }); - if (hasValue(this.model.value)) { - this.focus.emit({ - $event: new Event('focus'), - context: this.context, - control: this.control, - model: this.model, - type: DynamicFormControlEventType.Focus - } as DynamicFormControlEvent); - - this.model.value = null; - this.change.emit({ - $event: new Event('change'), - context: this.context, - control: this.control, - model: this.model, - type: DynamicFormControlEventType.Change - } as DynamicFormControlEvent); - - this.submissionService.dispatchSave(this.model.submissionId); - } - const modalComp = this.modalRef.componentInstance; if (hasValue(this.model.value) && !this.model.readOnly) { From 7b455c47c8168d0ceb8dd262d7d192272d212855 Mon Sep 17 00:00:00 2001 From: Bruno Roemers Date: Fri, 12 Mar 2021 11:06:42 +0100 Subject: [PATCH 067/132] 77643: Rename BreadcrumbsService to BreadcrumbsProviderService --- src/app/breadcrumbs/breadcrumb/breadcrumb-config.model.ts | 4 ++-- src/app/breadcrumbs/breadcrumbs.component.spec.ts | 4 ++-- .../{breadcrumbs.service.ts => breadcrumbsProviderService.ts} | 2 +- src/app/core/breadcrumbs/dso-breadcrumbs.service.ts | 4 ++-- src/app/core/breadcrumbs/i18n-breadcrumbs.service.ts | 4 ++-- src/app/process-page/process-breadcrumbs.service.ts | 4 ++-- 6 files changed, 11 insertions(+), 11 deletions(-) rename src/app/core/breadcrumbs/{breadcrumbs.service.ts => breadcrumbsProviderService.ts} (90%) diff --git a/src/app/breadcrumbs/breadcrumb/breadcrumb-config.model.ts b/src/app/breadcrumbs/breadcrumb/breadcrumb-config.model.ts index 0ff8fc5033..cc9277ee50 100644 --- a/src/app/breadcrumbs/breadcrumb/breadcrumb-config.model.ts +++ b/src/app/breadcrumbs/breadcrumb/breadcrumb-config.model.ts @@ -1,4 +1,4 @@ -import { BreadcrumbsService } from '../../core/breadcrumbs/breadcrumbs.service'; +import { BreadcrumbsProviderService } from '../../core/breadcrumbs/breadcrumbsProviderService'; /** * Interface for breadcrumb configuration objects @@ -7,7 +7,7 @@ export interface BreadcrumbConfig { /** * The service used to calculate the breadcrumb object */ - provider: BreadcrumbsService; + provider: BreadcrumbsProviderService; /** * The key that is used to calculate the breadcrumb display value diff --git a/src/app/breadcrumbs/breadcrumbs.component.spec.ts b/src/app/breadcrumbs/breadcrumbs.component.spec.ts index f7f8789144..f56e94bf44 100644 --- a/src/app/breadcrumbs/breadcrumbs.component.spec.ts +++ b/src/app/breadcrumbs/breadcrumbs.component.spec.ts @@ -7,14 +7,14 @@ import { RouterTestingModule } from '@angular/router/testing'; import { TranslateLoader, TranslateModule } from '@ngx-translate/core'; import { TranslateLoaderMock } from '../shared/testing/translate-loader.mock'; import { BreadcrumbConfig } from './breadcrumb/breadcrumb-config.model'; -import { BreadcrumbsService } from '../core/breadcrumbs/breadcrumbs.service'; +import { BreadcrumbsProviderService } from '../core/breadcrumbs/breadcrumbsProviderService'; import { Breadcrumb } from './breadcrumb/breadcrumb.model'; import { NO_ERRORS_SCHEMA } from '@angular/core'; import { NgbModule } from '@ng-bootstrap/ng-bootstrap'; import { VarDirective } from '../shared/utils/var.directive'; import { getTestScheduler } from 'jasmine-marbles'; -class TestBreadcrumbsService implements BreadcrumbsService { +class TestBreadcrumbsService implements BreadcrumbsProviderService { getBreadcrumbs(key: string, url: string): Observable { return observableOf([new Breadcrumb(key, url)]); } diff --git a/src/app/core/breadcrumbs/breadcrumbs.service.ts b/src/app/core/breadcrumbs/breadcrumbsProviderService.ts similarity index 90% rename from src/app/core/breadcrumbs/breadcrumbs.service.ts rename to src/app/core/breadcrumbs/breadcrumbsProviderService.ts index f274485d5d..4f5dd0a583 100644 --- a/src/app/core/breadcrumbs/breadcrumbs.service.ts +++ b/src/app/core/breadcrumbs/breadcrumbsProviderService.ts @@ -4,7 +4,7 @@ import { Observable } from 'rxjs'; /** * Service to calculate breadcrumbs for a single part of the route */ -export interface BreadcrumbsService { +export interface BreadcrumbsProviderService { /** * Method to calculate the breadcrumbs for a part of the route diff --git a/src/app/core/breadcrumbs/dso-breadcrumbs.service.ts b/src/app/core/breadcrumbs/dso-breadcrumbs.service.ts index f822a953a8..23fff18537 100644 --- a/src/app/core/breadcrumbs/dso-breadcrumbs.service.ts +++ b/src/app/core/breadcrumbs/dso-breadcrumbs.service.ts @@ -1,5 +1,5 @@ import { Breadcrumb } from '../../breadcrumbs/breadcrumb/breadcrumb.model'; -import { BreadcrumbsService } from './breadcrumbs.service'; +import { BreadcrumbsProviderService } from './breadcrumbsProviderService'; import { DSONameService } from './dso-name.service'; import { Observable, of as observableOf } from 'rxjs'; import { ChildHALResource } from '../shared/child-hal-resource.model'; @@ -18,7 +18,7 @@ import { getDSORoute } from '../../app-routing-paths'; @Injectable({ providedIn: 'root' }) -export class DSOBreadcrumbsService implements BreadcrumbsService { +export class DSOBreadcrumbsService implements BreadcrumbsProviderService { constructor( private linkService: LinkService, private dsoNameService: DSONameService diff --git a/src/app/core/breadcrumbs/i18n-breadcrumbs.service.ts b/src/app/core/breadcrumbs/i18n-breadcrumbs.service.ts index b774b58126..15563bdde8 100644 --- a/src/app/core/breadcrumbs/i18n-breadcrumbs.service.ts +++ b/src/app/core/breadcrumbs/i18n-breadcrumbs.service.ts @@ -1,5 +1,5 @@ import { Breadcrumb } from '../../breadcrumbs/breadcrumb/breadcrumb.model'; -import { BreadcrumbsService } from './breadcrumbs.service'; +import { BreadcrumbsProviderService } from './breadcrumbsProviderService'; import { Observable, of as observableOf } from 'rxjs'; import { Injectable } from '@angular/core'; @@ -14,7 +14,7 @@ export const BREADCRUMB_MESSAGE_POSTFIX = '.breadcrumbs'; @Injectable({ providedIn: 'root' }) -export class I18nBreadcrumbsService implements BreadcrumbsService { +export class I18nBreadcrumbsService implements BreadcrumbsProviderService { /** * Method to calculate the breadcrumbs diff --git a/src/app/process-page/process-breadcrumbs.service.ts b/src/app/process-page/process-breadcrumbs.service.ts index ffd289e04e..26b0787a53 100644 --- a/src/app/process-page/process-breadcrumbs.service.ts +++ b/src/app/process-page/process-breadcrumbs.service.ts @@ -1,6 +1,6 @@ import { Observable, of as observableOf } from 'rxjs'; import { Injectable } from '@angular/core'; -import { BreadcrumbsService } from '../core/breadcrumbs/breadcrumbs.service'; +import { BreadcrumbsProviderService } from '../core/breadcrumbs/breadcrumbsProviderService'; import { Breadcrumb } from '../breadcrumbs/breadcrumb/breadcrumb.model'; import { Process } from './processes/process.model'; @@ -8,7 +8,7 @@ import { Process } from './processes/process.model'; * Service to calculate process breadcrumbs for a single part of the route */ @Injectable() -export class ProcessBreadcrumbsService implements BreadcrumbsService { +export class ProcessBreadcrumbsService implements BreadcrumbsProviderService { /** * Method to calculate the breadcrumbs From c2ca35c522751294fd6bc41b165dbc0525dfdabd Mon Sep 17 00:00:00 2001 From: Bruno Roemers Date: Fri, 12 Mar 2021 15:36:00 +0100 Subject: [PATCH 068/132] 77643: WIP: Refactor BreadcrumbsComponent into service --- .../breadcrumbs/breadcrumbs.component.html | 2 +- .../breadcrumbs/breadcrumbs.component.spec.ts | 41 +++---- src/app/breadcrumbs/breadcrumbs.component.ts | 68 ++-------- .../breadcrumbs/breadcrumbs.service.spec.ts | 116 ++++++++++++++++++ src/app/breadcrumbs/breadcrumbs.service.ts | 74 +++++++++++ 5 files changed, 222 insertions(+), 79 deletions(-) create mode 100644 src/app/breadcrumbs/breadcrumbs.service.spec.ts create mode 100644 src/app/breadcrumbs/breadcrumbs.service.ts diff --git a/src/app/breadcrumbs/breadcrumbs.component.html b/src/app/breadcrumbs/breadcrumbs.component.html index 1f142526e2..a6072ed58a 100644 --- a/src/app/breadcrumbs/breadcrumbs.component.html +++ b/src/app/breadcrumbs/breadcrumbs.component.html @@ -1,5 +1,5 @@ -
diff --git a/src/app/+collection-page/edit-item-template-page/edit-item-template-page.component.ts b/src/app/+collection-page/edit-item-template-page/edit-item-template-page.component.ts index 19e24eff59..5d29eb7f73 100644 --- a/src/app/+collection-page/edit-item-template-page/edit-item-template-page.component.ts +++ b/src/app/+collection-page/edit-item-template-page/edit-item-template-page.component.ts @@ -8,6 +8,7 @@ import { ItemTemplateDataService } from '../../core/data/item-template-data.serv import { getCollectionEditRoute } from '../collection-page-routing-paths'; import { Item } from '../../core/shared/item.model'; import { getFirstSucceededRemoteDataPayload } from '../../core/shared/operators'; +import { AlertType } from '../../shared/alert/aletr-type'; @Component({ selector: 'ds-edit-item-template-page', @@ -28,6 +29,12 @@ export class EditItemTemplatePageComponent implements OnInit { */ itemRD$: Observable>; + /** + * The AlertType enumeration + * @type {AlertType} + */ + AlertTypeEnum = AlertType; + constructor(protected route: ActivatedRoute, public itemTemplateService: ItemTemplateDataService) { } diff --git a/src/assets/i18n/en.json5 b/src/assets/i18n/en.json5 index a16d41a9e3..0ba07cdaf1 100644 --- a/src/assets/i18n/en.json5 +++ b/src/assets/i18n/en.json5 @@ -777,10 +777,14 @@ "collection.edit.template.edit-button": "Edit", + "collection.edit.template.error": "An error occurred retrieving the template item", + "collection.edit.template.head": "Edit Template Item for Collection \"{{ collection }}\"", "collection.edit.template.label": "Template item", + "collection.edit.template.loading": "Loading template item...", + "collection.edit.template.notifications.delete.error": "Failed to delete the item template", "collection.edit.template.notifications.delete.success": "Successfully deleted the item template", From 6fabf436e32df04ee57ff5517533a3ef84e9f1bd Mon Sep 17 00:00:00 2001 From: Yura Bondarenko Date: Tue, 16 Mar 2021 14:30:59 +0100 Subject: [PATCH 074/132] 77583: Specify id type ~ /api/pid/find?id=hdl:... --- src/app/+lookup-by-id/lookup-guard.spec.ts | 4 ++-- src/app/+lookup-by-id/lookup-guard.ts | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/app/+lookup-by-id/lookup-guard.spec.ts b/src/app/+lookup-by-id/lookup-guard.spec.ts index 9c98e13bd3..63bb68884e 100644 --- a/src/app/+lookup-by-id/lookup-guard.spec.ts +++ b/src/app/+lookup-by-id/lookup-guard.spec.ts @@ -22,7 +22,7 @@ describe('LookupGuard', () => { } }; guard.canActivate(scopedRoute as any, undefined); - expect(dsoService.findByIdAndIDType).toHaveBeenCalledWith('123456789/1234', IdentifierType.HANDLE); + expect(dsoService.findByIdAndIDType).toHaveBeenCalledWith('hdl:123456789/1234', IdentifierType.HANDLE); }); it('should call findByIdAndIDType with handle params', () => { @@ -33,7 +33,7 @@ describe('LookupGuard', () => { } }; guard.canActivate(scopedRoute as any, undefined); - expect(dsoService.findByIdAndIDType).toHaveBeenCalledWith('123456789%2F1234', IdentifierType.HANDLE); + expect(dsoService.findByIdAndIDType).toHaveBeenCalledWith('hdl:123456789%2F1234', IdentifierType.HANDLE); }); it('should call findByIdAndIDType with UUID params', () => { diff --git a/src/app/+lookup-by-id/lookup-guard.ts b/src/app/+lookup-by-id/lookup-guard.ts index 0df10d2b31..2146e56245 100644 --- a/src/app/+lookup-by-id/lookup-guard.ts +++ b/src/app/+lookup-by-id/lookup-guard.ts @@ -35,11 +35,11 @@ export class LookupGuard implements CanActivate { type = IdentifierType.HANDLE; const prefix = route.params.idType; const handleId = route.params.id; - id = `${prefix}/${handleId}`; + id = `hdl:${prefix}/${handleId}`; } else if (route.params.idType === IdentifierType.HANDLE) { type = IdentifierType.HANDLE; - id = route.params.id; + id = 'hdl:' + route.params.id; } else { type = IdentifierType.UUID; From 34990c6f13fa2b49a3fea433c1b5cc73c5e756a8 Mon Sep 17 00:00:00 2001 From: Alessandro Martelli Date: Wed, 17 Mar 2021 17:11:04 +0100 Subject: [PATCH 075/132] [CSTPER-321] Delete an item is not working --- .../item-delete/item-delete.component.spec.ts | 13 +++++++++++++ .../item-delete/item-delete.component.ts | 13 ++++++++----- 2 files changed, 21 insertions(+), 5 deletions(-) diff --git a/src/app/+item-page/edit-item-page/item-delete/item-delete.component.spec.ts b/src/app/+item-page/edit-item-page/item-delete/item-delete.component.spec.ts index 116a0feb21..ea78767df5 100644 --- a/src/app/+item-page/edit-item-page/item-delete/item-delete.component.spec.ts +++ b/src/app/+item-page/edit-item-page/item-delete/item-delete.component.spec.ts @@ -173,6 +173,19 @@ describe('ItemDeleteComponent', () => { .toHaveBeenCalledWith(mockItem.id, types.filter((type) => typesSelection[type]).map((type) => type.id)); expect(comp.notify).toHaveBeenCalled(); }); + + it('should call delete function from the ItemDataService with empty types', () => { + + spyOn(comp, 'notify'); + jasmine.getEnv().allowRespy(true); + spyOn(entityTypeService, 'getEntityTypeRelationships').and.returnValue([]); + comp.ngOnInit(); + + comp.performAction(); + + expect(mockItemDataService.delete).toHaveBeenCalledWith(mockItem.id, []); + expect(comp.notify).toHaveBeenCalled(); + }); }); describe('notify', () => { it('should navigate to the homepage on successful deletion of the item', () => { diff --git a/src/app/+item-page/edit-item-page/item-delete/item-delete.component.ts b/src/app/+item-page/edit-item-page/item-delete/item-delete.component.ts index 366b22bec7..a05ffec4f5 100644 --- a/src/app/+item-page/edit-item-page/item-delete/item-delete.component.ts +++ b/src/app/+item-page/edit-item-page/item-delete/item-delete.component.ts @@ -1,5 +1,5 @@ import { Component, Input, OnInit } from '@angular/core'; -import { defaultIfEmpty, filter, map, switchMap, take } from 'rxjs/operators'; +import {defaultIfEmpty, filter, map, switchMap, take} from 'rxjs/operators'; import { AbstractSimpleItemActionComponent } from '../simple-item-action/abstract-simple-item-action.component'; import { NgbModal, NgbModalRef } from '@ng-bootstrap/ng-bootstrap'; import { @@ -121,8 +121,11 @@ export class ItemDeleteComponent getFirstSucceededRemoteData(), getRemoteDataPayload(), map((relationshipTypes) => relationshipTypes.page), - switchMap((types) => - combineLatest(types.map((type) => this.getRelationships(type))).pipe( + switchMap((types) => { + if (types.length === 0) { + return observableOf(types); + } + return combineLatest(types.map((type) => this.getRelationships(type))).pipe( map((relationships) => types.reduce((includedTypes, type, index) => { if (!includedTypes.some((includedType) => includedType.id === type.id) @@ -133,8 +136,8 @@ export class ItemDeleteComponent } }, []) ), - ) - ), + ); + }) ); } else { this.types$ = observableOf([]); From 12f8e82aa23b6236ce447377a64d1732c00d20cb Mon Sep 17 00:00:00 2001 From: Tim Donohue Date: Wed, 17 Mar 2021 13:01:15 -0500 Subject: [PATCH 076/132] Add step to verify REST API is up/available for e2e tests --- .github/workflows/build.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index fb17a43575..be958e7369 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -80,6 +80,9 @@ jobs: docker-compose -f ./docker/cli.yml -f ./docker/cli.assetstore.yml run --rm dspace-cli docker container ls + - name: Check DSpace REST Backend available (for e2e tests) + run: curl http://localhost:8080/server/api + - name: Run e2e tests (integration tests) run: yarn run e2e:ci From ba4c7a8e88cf78fd2fa5748dda90a5adac7b4d65 Mon Sep 17 00:00:00 2001 From: Tim Donohue Date: Wed, 17 Mar 2021 15:31:00 -0500 Subject: [PATCH 077/132] Add a step to wait until REST API is ready (returns 200) --- .github/workflows/build.yml | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index be958e7369..8c6d921237 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -80,7 +80,16 @@ jobs: docker-compose -f ./docker/cli.yml -f ./docker/cli.assetstore.yml run --rm dspace-cli docker container ls - - name: Check DSpace REST Backend available (for e2e tests) + # Wait until the REST API returns a 200 response (or for a max of 30 seconds) + # https://github.com/nev7n/wait_for_response + - name: Wait for DSpace REST Backend to be ready (for e2e tests) + uses: nev7n/wait_for_response@v1 + with: + url: 'http://localhost:8080/server/api' + responseCode: 200 + timeout: 30000 + + - name: Check DSpace REST Backend response (for e2e tests) run: curl http://localhost:8080/server/api - name: Run e2e tests (integration tests) From 43d2351adacb55d26955f42146b8b68be60fb5da Mon Sep 17 00:00:00 2001 From: Tim Donohue Date: Thu, 18 Mar 2021 09:01:44 -0500 Subject: [PATCH 078/132] Wait on /api/core/sites to also ensure database is up --- .github/workflows/build.yml | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 8c6d921237..0b5b3f9d8c 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -85,11 +85,12 @@ jobs: - name: Wait for DSpace REST Backend to be ready (for e2e tests) uses: nev7n/wait_for_response@v1 with: - url: 'http://localhost:8080/server/api' + # We use the 'sites' endpoint to also ensure the database is ready + url: 'http://localhost:8080/server/api/core/sites' responseCode: 200 timeout: 30000 - - name: Check DSpace REST Backend response (for e2e tests) + - name: Get DSpace REST Backend info/properties run: curl http://localhost:8080/server/api - name: Run e2e tests (integration tests) From 8b7a33bff2152a032a53d77c771a7c3429e8624a Mon Sep 17 00:00:00 2001 From: Yana De Pauw Date: Wed, 3 Mar 2021 11:05:52 +0100 Subject: [PATCH 079/132] 77349: Add themeable components - pt. 1 --- .../themed-browse-by-switcher.component.ts | 28 +++++++ .../+browse-by/browse-by-routing.module.ts | 4 +- src/app/+browse-by/browse-by.module.ts | 2 + .../collection-page-routing.module.ts | 4 +- .../collection-page.module.ts | 2 + .../themed-collection-page.component.ts | 27 +++++++ .../community-page-routing.module.ts | 4 +- .../+community-page/community-page.module.ts | 17 +++-- .../themed-community-page.component.ts | 27 +++++++ .../lookup-by-id-routing.module.ts | 4 +- src/app/+lookup-by-id/lookup-by-id.module.ts | 4 +- .../themed-objectnotfound.component.ts | 27 +++++++ .../search-page-routing.module.ts | 8 +- src/app/+search-page/search-page.module.ts | 4 +- ...med-configuration-search-page.component.ts | 73 +++++++++++++++++++ .../themed-search-page.component.ts | 27 +++++++ src/app/app-routing.module.ts | 9 ++- src/app/app.module.ts | 4 + .../community-list-page.module.ts | 15 +++- .../community-list-page.routing.module.ts | 4 +- .../themed-community-list-page.component.ts | 27 +++++++ .../forbidden/themed-forbidden.component.ts | 27 +++++++ .../themed-end-user-agreement.component.ts | 28 +++++++ src/app/info/info-routing.module.ts | 8 +- src/app/info/info.module.ts | 19 ++++- .../info/privacy/themed-privacy.component.ts | 27 +++++++ .../themed-pagenotfound.component.ts | 27 +++++++ src/app/shared/shared.module.ts | 4 +- ...ed-collection-statistics-page.component.ts | 27 +++++++ ...med-community-statistics-page.component.ts | 27 +++++++ .../themed-item-statistics-page.component.ts | 27 +++++++ .../themed-site-statistics-page.component.ts | 27 +++++++ .../statistics-page-routing.module.ts | 17 +++-- .../statistics-page/statistics-page.module.ts | 10 ++- src/environments/environment.common.ts | 8 +- .../browse-by-switcher.component.html | 0 .../browse-by-switcher.component.scss | 0 .../browse-by-switcher.component.ts | 15 ++++ .../collection-page.component.html | 0 .../collection-page.component.scss | 0 .../collection-page.component.ts | 17 +++++ .../community-page.component.html | 0 .../community-page.component.scss | 0 .../community-page.component.ts | 17 +++++ .../objectnotfound.component.html | 0 .../objectnotfound.component.scss | 0 .../objectnotfound.component.ts | 16 ++++ .../configuration-search-page.component.html | 0 .../configuration-search-page.component.scss | 0 .../configuration-search-page.component.ts | 15 ++++ .../+search-page/search-page.component.html | 0 .../+search-page/search-page.component.scss | 0 .../app/+search-page/search-page.component.ts | 15 ++++ .../community-list-page.component.html | 0 .../community-list-page.component.scss | 0 .../community-list-page.component.ts | 15 ++++ .../app/forbidden/forbidden.component.html | 0 .../app/forbidden/forbidden.component.scss | 0 .../app/forbidden/forbidden.component.ts | 17 +++++ .../end-user-agreement.component.html | 0 .../end-user-agreement.component.scss | 0 .../end-user-agreement.component.ts | 16 ++++ .../app/info/privacy/privacy.component.html | 0 .../app/info/privacy/privacy.component.scss | 0 .../app/info/privacy/privacy.component.ts | 15 ++++ .../pagenotfound/pagenotfound.component.html | 0 .../pagenotfound/pagenotfound.component.scss | 0 .../pagenotfound/pagenotfound.component.ts | 16 ++++ .../collection-statistics-page.component.html | 0 .../collection-statistics-page.component.scss | 0 .../collection-statistics-page.component.ts | 16 ++++ .../community-statistics-page.component.html | 0 .../community-statistics-page.component.scss | 0 .../community-statistics-page.component.ts | 16 ++++ .../item-statistics-page.component.html | 0 .../item-statistics-page.component.scss | 0 .../item-statistics-page.component.ts | 16 ++++ .../site-statistics-page.component.html | 0 .../site-statistics-page.component.scss | 0 .../site-statistics-page.component.ts | 16 ++++ src/themes/custom/theme.module.ts | 42 ++++++++++- 81 files changed, 833 insertions(+), 51 deletions(-) create mode 100644 src/app/+browse-by/+browse-by-switcher/themed-browse-by-switcher.component.ts create mode 100644 src/app/+collection-page/themed-collection-page.component.ts create mode 100644 src/app/+community-page/themed-community-page.component.ts create mode 100644 src/app/+lookup-by-id/objectnotfound/themed-objectnotfound.component.ts create mode 100644 src/app/+search-page/themed-configuration-search-page.component.ts create mode 100644 src/app/+search-page/themed-search-page.component.ts create mode 100644 src/app/community-list-page/themed-community-list-page.component.ts create mode 100644 src/app/forbidden/themed-forbidden.component.ts create mode 100644 src/app/info/end-user-agreement/themed-end-user-agreement.component.ts create mode 100644 src/app/info/privacy/themed-privacy.component.ts create mode 100644 src/app/pagenotfound/themed-pagenotfound.component.ts create mode 100644 src/app/statistics-page/collection-statistics-page/themed-collection-statistics-page.component.ts create mode 100644 src/app/statistics-page/community-statistics-page/themed-community-statistics-page.component.ts create mode 100644 src/app/statistics-page/item-statistics-page/themed-item-statistics-page.component.ts create mode 100644 src/app/statistics-page/site-statistics-page/themed-site-statistics-page.component.ts create mode 100644 src/themes/custom/app/+browse-by/+browse-by-switcher/browse-by-switcher.component.html create mode 100644 src/themes/custom/app/+browse-by/+browse-by-switcher/browse-by-switcher.component.scss create mode 100644 src/themes/custom/app/+browse-by/+browse-by-switcher/browse-by-switcher.component.ts create mode 100644 src/themes/custom/app/+collection-page/collection-page.component.html create mode 100644 src/themes/custom/app/+collection-page/collection-page.component.scss create mode 100644 src/themes/custom/app/+collection-page/collection-page.component.ts create mode 100644 src/themes/custom/app/+community-page/community-page.component.html create mode 100644 src/themes/custom/app/+community-page/community-page.component.scss create mode 100644 src/themes/custom/app/+community-page/community-page.component.ts create mode 100644 src/themes/custom/app/+lookup-by-id/objectnotfound/objectnotfound.component.html create mode 100644 src/themes/custom/app/+lookup-by-id/objectnotfound/objectnotfound.component.scss create mode 100644 src/themes/custom/app/+lookup-by-id/objectnotfound/objectnotfound.component.ts create mode 100644 src/themes/custom/app/+search-page/configuration-search-page.component.html create mode 100644 src/themes/custom/app/+search-page/configuration-search-page.component.scss create mode 100644 src/themes/custom/app/+search-page/configuration-search-page.component.ts create mode 100644 src/themes/custom/app/+search-page/search-page.component.html create mode 100644 src/themes/custom/app/+search-page/search-page.component.scss create mode 100644 src/themes/custom/app/+search-page/search-page.component.ts create mode 100644 src/themes/custom/app/community-list-page/community-list-page.component.html create mode 100644 src/themes/custom/app/community-list-page/community-list-page.component.scss create mode 100644 src/themes/custom/app/community-list-page/community-list-page.component.ts create mode 100644 src/themes/custom/app/forbidden/forbidden.component.html create mode 100644 src/themes/custom/app/forbidden/forbidden.component.scss create mode 100644 src/themes/custom/app/forbidden/forbidden.component.ts create mode 100644 src/themes/custom/app/info/end-user-agreement/end-user-agreement.component.html create mode 100644 src/themes/custom/app/info/end-user-agreement/end-user-agreement.component.scss create mode 100644 src/themes/custom/app/info/end-user-agreement/end-user-agreement.component.ts create mode 100644 src/themes/custom/app/info/privacy/privacy.component.html create mode 100644 src/themes/custom/app/info/privacy/privacy.component.scss create mode 100644 src/themes/custom/app/info/privacy/privacy.component.ts create mode 100644 src/themes/custom/app/pagenotfound/pagenotfound.component.html create mode 100644 src/themes/custom/app/pagenotfound/pagenotfound.component.scss create mode 100644 src/themes/custom/app/pagenotfound/pagenotfound.component.ts create mode 100644 src/themes/custom/app/statistics-page/collection-statistics-page/collection-statistics-page.component.html create mode 100644 src/themes/custom/app/statistics-page/collection-statistics-page/collection-statistics-page.component.scss create mode 100644 src/themes/custom/app/statistics-page/collection-statistics-page/collection-statistics-page.component.ts create mode 100644 src/themes/custom/app/statistics-page/community-statistics-page/community-statistics-page.component.html create mode 100644 src/themes/custom/app/statistics-page/community-statistics-page/community-statistics-page.component.scss create mode 100644 src/themes/custom/app/statistics-page/community-statistics-page/community-statistics-page.component.ts create mode 100644 src/themes/custom/app/statistics-page/item-statistics-page/item-statistics-page.component.html create mode 100644 src/themes/custom/app/statistics-page/item-statistics-page/item-statistics-page.component.scss create mode 100644 src/themes/custom/app/statistics-page/item-statistics-page/item-statistics-page.component.ts create mode 100644 src/themes/custom/app/statistics-page/site-statistics-page/site-statistics-page.component.html create mode 100644 src/themes/custom/app/statistics-page/site-statistics-page/site-statistics-page.component.scss create mode 100644 src/themes/custom/app/statistics-page/site-statistics-page/site-statistics-page.component.ts diff --git a/src/app/+browse-by/+browse-by-switcher/themed-browse-by-switcher.component.ts b/src/app/+browse-by/+browse-by-switcher/themed-browse-by-switcher.component.ts new file mode 100644 index 0000000000..20d27012fe --- /dev/null +++ b/src/app/+browse-by/+browse-by-switcher/themed-browse-by-switcher.component.ts @@ -0,0 +1,28 @@ +import { Component, OnInit } from '@angular/core'; + +import { ThemedComponent } from '../../shared/theme-support/themed.component'; +import { BrowseBySwitcherComponent } from './browse-by-switcher.component'; + +@Component({ + selector: 'ds-themed-browse-by-switcher', + styleUrls: [], + templateUrl: '../../shared/theme-support/themed.component.html' +}) +/** + * Component for determining what Browse-By component to use depending on the metadata (browse ID) provided + */ +export class ThemedBrowseBySwitcherComponent extends ThemedComponent { + protected getComponentName(): string { + return 'BrowseBySwitcherComponent'; + } + + protected importThemedComponent(themeName: string): Promise { + return import(`../../../themes/${themeName}/app/+browse-by/+browse-by-switcher/browse-by-switcher.component`); + } + + protected importUnthemedComponent(): Promise { + return import(`./browse-by-switcher.component`); + } + + +} diff --git a/src/app/+browse-by/browse-by-routing.module.ts b/src/app/+browse-by/browse-by-routing.module.ts index a686e7007e..8cf989695a 100644 --- a/src/app/+browse-by/browse-by-routing.module.ts +++ b/src/app/+browse-by/browse-by-routing.module.ts @@ -1,9 +1,9 @@ import { RouterModule } from '@angular/router'; import { NgModule } from '@angular/core'; import { BrowseByGuard } from './browse-by-guard'; -import { BrowseBySwitcherComponent } from './+browse-by-switcher/browse-by-switcher.component'; import { BrowseByDSOBreadcrumbResolver } from './browse-by-dso-breadcrumb.resolver'; import { BrowseByI18nBreadcrumbResolver } from './browse-by-i18n-breadcrumb.resolver'; +import { ThemedBrowseBySwitcherComponent } from './+browse-by-switcher/themed-browse-by-switcher.component'; @NgModule({ imports: [ @@ -14,7 +14,7 @@ import { BrowseByI18nBreadcrumbResolver } from './browse-by-i18n-breadcrumb.reso children: [ { path: ':id', - component: BrowseBySwitcherComponent, + component: ThemedBrowseBySwitcherComponent, canActivate: [BrowseByGuard], resolve: { breadcrumb: BrowseByI18nBreadcrumbResolver }, data: { title: 'browse.title', breadcrumbKey: 'browse.metadata' } diff --git a/src/app/+browse-by/browse-by.module.ts b/src/app/+browse-by/browse-by.module.ts index 60574f4074..08b6c5739b 100644 --- a/src/app/+browse-by/browse-by.module.ts +++ b/src/app/+browse-by/browse-by.module.ts @@ -5,6 +5,7 @@ import { SharedModule } from '../shared/shared.module'; import { BrowseByMetadataPageComponent } from './+browse-by-metadata-page/browse-by-metadata-page.component'; import { BrowseByDatePageComponent } from './+browse-by-date-page/browse-by-date-page.component'; import { BrowseBySwitcherComponent } from './+browse-by-switcher/browse-by-switcher.component'; +import { ThemedBrowseBySwitcherComponent } from './+browse-by-switcher/themed-browse-by-switcher.component'; const ENTRY_COMPONENTS = [ // put only entry components that use custom decorator @@ -20,6 +21,7 @@ const ENTRY_COMPONENTS = [ ], declarations: [ BrowseBySwitcherComponent, + ThemedBrowseBySwitcherComponent, ...ENTRY_COMPONENTS ], exports: [ diff --git a/src/app/+collection-page/collection-page-routing.module.ts b/src/app/+collection-page/collection-page-routing.module.ts index 7e44883a53..5879e523af 100644 --- a/src/app/+collection-page/collection-page-routing.module.ts +++ b/src/app/+collection-page/collection-page-routing.module.ts @@ -1,7 +1,6 @@ import { NgModule } from '@angular/core'; import { RouterModule } from '@angular/router'; -import { CollectionPageComponent } from './collection-page.component'; import { CollectionPageResolver } from './collection-page.resolver'; import { CreateCollectionPageComponent } from './create-collection-page/create-collection-page.component'; import { AuthenticatedGuard } from '../core/auth/authenticated.guard'; @@ -21,6 +20,7 @@ import { import { CollectionPageAdministratorGuard } from './collection-page-administrator.guard'; import { MenuItemType } from '../shared/menu/initial-menus-state'; import { LinkMenuItemModel } from '../shared/menu/menu-item/models/link.model'; +import { ThemedCollectionPageComponent } from './themed-collection-page.component'; @NgModule({ imports: [ @@ -62,7 +62,7 @@ import { LinkMenuItemModel } from '../shared/menu/menu-item/models/link.model'; }, { path: '', - component: CollectionPageComponent, + component: ThemedCollectionPageComponent, pathMatch: 'full', } ], diff --git a/src/app/+collection-page/collection-page.module.ts b/src/app/+collection-page/collection-page.module.ts index 83ba12f037..7946e7a1a4 100644 --- a/src/app/+collection-page/collection-page.module.ts +++ b/src/app/+collection-page/collection-page.module.ts @@ -13,6 +13,7 @@ import { CollectionItemMapperComponent } from './collection-item-mapper/collecti import { SearchService } from '../core/shared/search/search.service'; import { StatisticsModule } from '../statistics/statistics.module'; import { CollectionFormModule } from './collection-form/collection-form.module'; +import { ThemedCollectionPageComponent } from './themed-collection-page.component'; @NgModule({ imports: [ @@ -25,6 +26,7 @@ import { CollectionFormModule } from './collection-form/collection-form.module'; ], declarations: [ CollectionPageComponent, + ThemedCollectionPageComponent, CreateCollectionPageComponent, DeleteCollectionPageComponent, EditItemTemplatePageComponent, diff --git a/src/app/+collection-page/themed-collection-page.component.ts b/src/app/+collection-page/themed-collection-page.component.ts new file mode 100644 index 0000000000..7bbc720e30 --- /dev/null +++ b/src/app/+collection-page/themed-collection-page.component.ts @@ -0,0 +1,27 @@ +import { Component } from '@angular/core'; +import { ThemedComponent } from '../shared/theme-support/themed.component'; +import { CollectionPageComponent } from './collection-page.component'; + +@Component({ + selector: 'ds-themed-community-page', + styleUrls: [], + templateUrl: '../shared/theme-support/themed.component.html', +}) + +/** + * Component to render the news section on the home page + */ +export class ThemedCollectionPageComponent extends ThemedComponent { + protected getComponentName(): string { + return 'CollectionPageComponent'; + } + + protected importThemedComponent(themeName: string): Promise { + return import(`../../themes/${themeName}/app/+collection-page/collection-page.component`); + } + + protected importUnthemedComponent(): Promise { + return import(`./collection-page.component`); + } + +} diff --git a/src/app/+community-page/community-page-routing.module.ts b/src/app/+community-page/community-page-routing.module.ts index 571bff7413..ad1b1fd2f2 100644 --- a/src/app/+community-page/community-page-routing.module.ts +++ b/src/app/+community-page/community-page-routing.module.ts @@ -1,7 +1,6 @@ import { NgModule } from '@angular/core'; import { RouterModule } from '@angular/router'; -import { CommunityPageComponent } from './community-page.component'; import { CommunityPageResolver } from './community-page.resolver'; import { CreateCommunityPageComponent } from './create-community-page/create-community-page.component'; import { AuthenticatedGuard } from '../core/auth/authenticated.guard'; @@ -14,6 +13,7 @@ import { COMMUNITY_EDIT_PATH, COMMUNITY_CREATE_PATH } from './community-page-rou import { CommunityPageAdministratorGuard } from './community-page-administrator.guard'; import { MenuItemType } from '../shared/menu/initial-menus-state'; import { LinkMenuItemModel } from '../shared/menu/menu-item/models/link.model'; +import { ThemedCommunityPageComponent } from './themed-community-page.component'; @NgModule({ imports: [ @@ -45,7 +45,7 @@ import { LinkMenuItemModel } from '../shared/menu/menu-item/models/link.model'; }, { path: '', - component: CommunityPageComponent, + component: ThemedCommunityPageComponent, pathMatch: 'full', } ], diff --git a/src/app/+community-page/community-page.module.ts b/src/app/+community-page/community-page.module.ts index a9eaef033d..3ae75f166c 100644 --- a/src/app/+community-page/community-page.module.ts +++ b/src/app/+community-page/community-page.module.ts @@ -11,6 +11,14 @@ import { CreateCommunityPageComponent } from './create-community-page/create-com import { DeleteCommunityPageComponent } from './delete-community-page/delete-community-page.component'; import { StatisticsModule } from '../statistics/statistics.module'; import { CommunityFormModule } from './community-form/community-form.module'; +import { ThemedCommunityPageComponent } from './themed-community-page.component'; + +const DECLARATIONS = [CommunityPageComponent, + ThemedCommunityPageComponent, + CommunityPageSubCollectionListComponent, + CommunityPageSubCommunityListComponent, + CreateCommunityPageComponent, + DeleteCommunityPageComponent]; @NgModule({ imports: [ @@ -21,11 +29,10 @@ import { CommunityFormModule } from './community-form/community-form.module'; CommunityFormModule ], declarations: [ - CommunityPageComponent, - CommunityPageSubCollectionListComponent, - CommunityPageSubCommunityListComponent, - CreateCommunityPageComponent, - DeleteCommunityPageComponent + ...DECLARATIONS + ], + exports: [ + ...DECLARATIONS ] }) diff --git a/src/app/+community-page/themed-community-page.component.ts b/src/app/+community-page/themed-community-page.component.ts new file mode 100644 index 0000000000..b420789c5f --- /dev/null +++ b/src/app/+community-page/themed-community-page.component.ts @@ -0,0 +1,27 @@ +import { Component } from '@angular/core'; +import { ThemedComponent } from '../shared/theme-support/themed.component'; +import { CommunityPageComponent } from './community-page.component'; + +@Component({ + selector: 'ds-themed-community-page', + styleUrls: [], + templateUrl: '../shared/theme-support/themed.component.html', +}) + +/** + * Component to render the news section on the home page + */ +export class ThemedCommunityPageComponent extends ThemedComponent { + protected getComponentName(): string { + return 'CommunityPageComponent'; + } + + protected importThemedComponent(themeName: string): Promise { + return import(`../../themes/${themeName}/app/+community-page/community-page.component`); + } + + protected importUnthemedComponent(): Promise { + return import(`./community-page.component`); + } + +} diff --git a/src/app/+lookup-by-id/lookup-by-id-routing.module.ts b/src/app/+lookup-by-id/lookup-by-id-routing.module.ts index 76c90ed6d4..52a7c8a358 100644 --- a/src/app/+lookup-by-id/lookup-by-id-routing.module.ts +++ b/src/app/+lookup-by-id/lookup-by-id-routing.module.ts @@ -1,8 +1,8 @@ import { LookupGuard } from './lookup-guard'; import { NgModule } from '@angular/core'; import { RouterModule, UrlSegment } from '@angular/router'; -import { ObjectNotFoundComponent } from './objectnotfound/objectnotfound.component'; import { isNotEmpty } from '../shared/empty.util'; +import { ThemedObjectNotFoundComponent } from './objectnotfound/themed-objectnotfound.component'; @NgModule({ imports: [ @@ -10,7 +10,7 @@ import { isNotEmpty } from '../shared/empty.util'; { matcher: urlMatcher, canActivate: [LookupGuard], - component: ObjectNotFoundComponent } + component: ThemedObjectNotFoundComponent } ]) ], providers: [ diff --git a/src/app/+lookup-by-id/lookup-by-id.module.ts b/src/app/+lookup-by-id/lookup-by-id.module.ts index 1b070c1279..0202a43033 100644 --- a/src/app/+lookup-by-id/lookup-by-id.module.ts +++ b/src/app/+lookup-by-id/lookup-by-id.module.ts @@ -4,6 +4,7 @@ import { SharedModule } from '../shared/shared.module'; import { LookupRoutingModule } from './lookup-by-id-routing.module'; import { ObjectNotFoundComponent } from './objectnotfound/objectnotfound.component'; import { DsoRedirectDataService } from '../core/data/dso-redirect-data.service'; +import { ThemedObjectNotFoundComponent } from './objectnotfound/themed-objectnotfound.component'; @NgModule({ imports: [ @@ -12,7 +13,8 @@ import { DsoRedirectDataService } from '../core/data/dso-redirect-data.service'; SharedModule, ], declarations: [ - ObjectNotFoundComponent + ObjectNotFoundComponent, + ThemedObjectNotFoundComponent ], providers: [ DsoRedirectDataService diff --git a/src/app/+lookup-by-id/objectnotfound/themed-objectnotfound.component.ts b/src/app/+lookup-by-id/objectnotfound/themed-objectnotfound.component.ts new file mode 100644 index 0000000000..947a9f4eaa --- /dev/null +++ b/src/app/+lookup-by-id/objectnotfound/themed-objectnotfound.component.ts @@ -0,0 +1,27 @@ +import { Component } from '@angular/core'; +import { ThemedComponent } from '../../shared/theme-support/themed.component'; +import { ObjectNotFoundComponent } from './objectnotfound.component'; + +@Component({ + selector: 'ds-themed-objnotfound', + styleUrls: [], + templateUrl: '../../shared/theme-support/themed.component.html', +}) + +/** + * Component to render the news section on the home page + */ +export class ThemedObjectNotFoundComponent extends ThemedComponent { + protected getComponentName(): string { + return 'ObjectNotFoundComponent'; + } + + protected importThemedComponent(themeName: string): Promise { + return import(`../../../themes/${themeName}/app/+lookup-by-id/objectnotfound/objectnotfound.component`); + } + + protected importUnthemedComponent(): Promise { + return import(`./objectnotfound.component`); + } + +} diff --git a/src/app/+search-page/search-page-routing.module.ts b/src/app/+search-page/search-page-routing.module.ts index f71c7b45ee..9e39ad1bc9 100644 --- a/src/app/+search-page/search-page-routing.module.ts +++ b/src/app/+search-page/search-page-routing.module.ts @@ -2,11 +2,11 @@ import { NgModule } from '@angular/core'; import { RouterModule } from '@angular/router'; import { ConfigurationSearchPageGuard } from './configuration-search-page.guard'; -import { ConfigurationSearchPageComponent } from './configuration-search-page.component'; -import { SearchPageComponent } from './search-page.component'; import { I18nBreadcrumbResolver } from '../core/breadcrumbs/i18n-breadcrumb.resolver'; import { I18nBreadcrumbsService } from '../core/breadcrumbs/i18n-breadcrumbs.service'; import { SearchPageModule } from './search-page.module'; +import { ThemedSearchPageComponent } from './themed-search-page.component'; +import { ThemedConfigurationSearchPageComponent } from './themed-configuration-search-page.component'; @NgModule({ imports: [ @@ -15,8 +15,8 @@ import { SearchPageModule } from './search-page.module'; path: '', resolve: { breadcrumb: I18nBreadcrumbResolver }, data: { title: 'search.title', breadcrumbKey: 'search' }, children: [ - { path: '', component: SearchPageComponent }, - { path: ':configuration', component: ConfigurationSearchPageComponent, canActivate: [ConfigurationSearchPageGuard] } + { path: '', component: ThemedSearchPageComponent }, + { path: ':configuration', component: ThemedConfigurationSearchPageComponent, canActivate: [ConfigurationSearchPageGuard] } ] }] ) diff --git a/src/app/+search-page/search-page.module.ts b/src/app/+search-page/search-page.module.ts index 286f1d12be..0cf6164f8a 100644 --- a/src/app/+search-page/search-page.module.ts +++ b/src/app/+search-page/search-page.module.ts @@ -13,11 +13,13 @@ import { SearchFilterService } from '../core/shared/search/search-filter.service import { SearchConfigurationService } from '../core/shared/search/search-configuration.service'; import { JournalEntitiesModule } from '../entity-groups/journal-entities/journal-entities.module'; import { ResearchEntitiesModule } from '../entity-groups/research-entities/research-entities.module'; +import { ThemedSearchPageComponent } from './themed-search-page.component'; const components = [ SearchPageComponent, SearchComponent, - SearchTrackerComponent + SearchTrackerComponent, + ThemedSearchPageComponent ]; @NgModule({ diff --git a/src/app/+search-page/themed-configuration-search-page.component.ts b/src/app/+search-page/themed-configuration-search-page.component.ts new file mode 100644 index 0000000000..3528d3a326 --- /dev/null +++ b/src/app/+search-page/themed-configuration-search-page.component.ts @@ -0,0 +1,73 @@ +import { Component, Input } from '@angular/core'; +import { ThemedComponent } from '../shared/theme-support/themed.component'; +import { ConfigurationSearchPageComponent } from './configuration-search-page.component'; +import { Observable } from 'rxjs'; +import { Context } from '../core/shared/context.model'; + +@Component({ + selector: 'ds-themed-configuration-search-page', + styleUrls: [], + templateUrl: '../shared/theme-support/themed.component.html', +}) + +/** + * Component to render the news section on the home page + */ +export class ThemedConfigurationSearchPageComponent extends ThemedComponent { + /** + * The configuration to use for the search options + * If empty, the configuration will be determined by the route parameter called 'configuration' + */ + @Input() configuration: string; + + /** + * The actual query for the fixed filter. + * If empty, the query will be determined by the route parameter called 'filter' + */ + @Input() fixedFilterQuery: string; + + /** + * True when the search component should show results on the current page + */ + @Input() inPlaceSearch = true; + + /** + * Whether or not the search bar should be visible + */ + @Input() + searchEnabled = true; + + /** + * The width of the sidebar (bootstrap columns) + */ + @Input() + sideBarWidth = 3; + + /** + * The currently applied configuration (determines title of search) + */ + @Input() + configuration$: Observable; + + /** + * The current context + */ + @Input() + context: Context; + + protected inAndOutputNames: (keyof ConfigurationSearchPageComponent & keyof this)[] = + ['configuration', 'fixedFilterQuery', 'inPlaceSearch', 'searchEnabled', 'sideBarWidth', 'configuration$', 'context']; + + protected getComponentName(): string { + return 'ConfigurationSearchPageComponent'; + } + + protected importThemedComponent(themeName: string): Promise { + return import(`../../themes/${themeName}/app/+search-page/configuration-search-page.component`); + } + + protected importUnthemedComponent(): Promise { + return import(`./configuration-search-page.component`); + } + +} diff --git a/src/app/+search-page/themed-search-page.component.ts b/src/app/+search-page/themed-search-page.component.ts new file mode 100644 index 0000000000..b23fff6289 --- /dev/null +++ b/src/app/+search-page/themed-search-page.component.ts @@ -0,0 +1,27 @@ +import { Component } from '@angular/core'; +import { ThemedComponent } from '../shared/theme-support/themed.component'; +import { SearchPageComponent } from './search-page.component'; + +@Component({ + selector: 'ds-themed-search-page', + styleUrls: [], + templateUrl: '../shared/theme-support/themed.component.html', +}) +/** + * This component represents the whole search page + * It renders search results depending on the current search options + */ +export class ThemedSearchPageComponent extends ThemedComponent { + + protected getComponentName(): string { + return 'SearchPageComponent'; + } + + protected importThemedComponent(themeName: string): Promise { + return import(`../../themes/${themeName}/app/+search-page/search-page.component`); + } + + protected importUnthemedComponent(): Promise { + return import(`./search-page.component`); + } +} diff --git a/src/app/app-routing.module.ts b/src/app/app-routing.module.ts index 5e5c5f5413..18ce77df07 100644 --- a/src/app/app-routing.module.ts +++ b/src/app/app-routing.module.ts @@ -2,7 +2,6 @@ import { NgModule } from '@angular/core'; import { RouterModule } from '@angular/router'; import { AuthBlockingGuard } from './core/auth/auth-blocking.guard'; -import { PageNotFoundComponent } from './pagenotfound/pagenotfound.component'; import { AuthenticatedGuard } from './core/auth/authenticated.guard'; import { SiteAdministratorGuard } from './core/data/feature-authorization/feature-authorization-guard/site-administrator.guard'; import { @@ -23,6 +22,8 @@ import { ReloadGuard } from './core/reload/reload.guard'; import { EndUserAgreementCurrentUserGuard } from './core/end-user-agreement/end-user-agreement-current-user.guard'; import { SiteRegisterGuard } from './core/data/feature-authorization/feature-authorization-guard/site-register.guard'; import { ForbiddenComponent } from './forbidden/forbidden.component'; +import { ThemedPageNotFoundComponent } from './pagenotfound/themed-pagenotfound.component'; +import { ThemedForbiddenComponent } from './forbidden/themed-forbidden.component'; @NgModule({ imports: [ @@ -30,7 +31,7 @@ import { ForbiddenComponent } from './forbidden/forbidden.component'; path: '', canActivate: [AuthBlockingGuard], children: [ { path: '', redirectTo: '/home', pathMatch: 'full' }, - { path: 'reload/:rnd', component: PageNotFoundComponent, pathMatch: 'full', canActivate: [ReloadGuard] }, + { path: 'reload/:rnd', component: ThemedPageNotFoundComponent, pathMatch: 'full', canActivate: [ReloadGuard] }, { path: 'home', loadChildren: () => import('./+home-page/home-page.module') @@ -173,14 +174,14 @@ import { ForbiddenComponent } from './forbidden/forbidden.component'; }, { path: FORBIDDEN_PATH, - component: ForbiddenComponent + component: ThemedForbiddenComponent }, { path: 'statistics', loadChildren: () => import('./statistics-page/statistics-page-routing.module') .then((m) => m.StatisticsPageRoutingModule), }, - { path: '**', pathMatch: 'full', component: PageNotFoundComponent }, + { path: '**', pathMatch: 'full', component: ThemedPageNotFoundComponent }, ]} ],{ onSameUrlNavigation: 'reload', diff --git a/src/app/app.module.ts b/src/app/app.module.ts index cc428483c9..20aaa4ba02 100755 --- a/src/app/app.module.ts +++ b/src/app/app.module.ts @@ -46,6 +46,8 @@ import { XsrfInterceptor } from './core/xsrf/xsrf.interceptor'; import { RootComponent } from './root/root.component'; import { ThemedRootComponent } from './root/themed-root.component'; import { ThemedEntryComponentModule } from '../themes/themed-entry-component.module'; +import { ThemedPageNotFoundComponent } from './pagenotfound/themed-pagenotfound.component'; +import { ThemedForbiddenComponent } from './forbidden/themed-forbidden.component'; export function getBase() { return environment.ui.nameSpace; @@ -133,11 +135,13 @@ const DECLARATIONS = [ ExpandableAdminSidebarSectionComponent, FooterComponent, PageNotFoundComponent, + ThemedPageNotFoundComponent, NotificationComponent, NotificationsBoardComponent, SearchNavbarComponent, BreadcrumbsComponent, ForbiddenComponent, + ThemedForbiddenComponent, ]; const EXPORTS = [ diff --git a/src/app/community-list-page/community-list-page.module.ts b/src/app/community-list-page/community-list-page.module.ts index 57b016bc6e..3b009e227c 100644 --- a/src/app/community-list-page/community-list-page.module.ts +++ b/src/app/community-list-page/community-list-page.module.ts @@ -4,7 +4,14 @@ import { SharedModule } from '../shared/shared.module'; import { CommunityListPageComponent } from './community-list-page.component'; import { CommunityListPageRoutingModule } from './community-list-page.routing.module'; import { CommunityListComponent } from './community-list/community-list.component'; +import { ThemedCommunityListPageComponent } from './themed-community-list-page.component'; + +const DECLARATIONS = [ + CommunityListPageComponent, + CommunityListComponent, + ThemedCommunityListPageComponent +]; /** * The page which houses a title and the community list, as described in community-list.component */ @@ -15,9 +22,11 @@ import { CommunityListComponent } from './community-list/community-list.componen CommunityListPageRoutingModule ], declarations: [ - CommunityListPageComponent, - CommunityListComponent - ] + ...DECLARATIONS + ], + exports: [ + ...DECLARATIONS, + ], }) export class CommunityListPageModule { diff --git a/src/app/community-list-page/community-list-page.routing.module.ts b/src/app/community-list-page/community-list-page.routing.module.ts index fe250cb96d..d618e33269 100644 --- a/src/app/community-list-page/community-list-page.routing.module.ts +++ b/src/app/community-list-page/community-list-page.routing.module.ts @@ -2,8 +2,8 @@ import { NgModule } from '@angular/core'; import { RouterModule } from '@angular/router'; import { CdkTreeModule } from '@angular/cdk/tree'; -import { CommunityListPageComponent } from './community-list-page.component'; import { CommunityListService } from './community-list-service'; +import { ThemedCommunityListPageComponent } from './themed-community-list-page.component'; /** * RouterModule to help navigate to the page with the community list tree @@ -13,7 +13,7 @@ import { CommunityListService } from './community-list-service'; RouterModule.forChild([ { path: '', - component: CommunityListPageComponent, + component: ThemedCommunityListPageComponent, pathMatch: 'full', data: { title: 'communityList.tabTitle' } } diff --git a/src/app/community-list-page/themed-community-list-page.component.ts b/src/app/community-list-page/themed-community-list-page.component.ts new file mode 100644 index 0000000000..6b374fca90 --- /dev/null +++ b/src/app/community-list-page/themed-community-list-page.component.ts @@ -0,0 +1,27 @@ +import { Component } from '@angular/core'; +import { ThemedComponent } from '../shared/theme-support/themed.component'; +import { CommunityListPageComponent } from './community-list-page.component'; + +/** + * Page with title and the community list tree, as described in community-list.component; + * navigated to with community-list.page.routing.module + */ +@Component({ + selector: 'ds-themed-community-list-page', + styleUrls: [], + templateUrl: '../shared/theme-support/themed.component.html', +}) +export class ThemedCommunityListPageComponent extends ThemedComponent { + protected getComponentName(): string { + return 'CommunityListPageComponent'; + } + + protected importThemedComponent(themeName: string): Promise { + return import(`../../themes/${themeName}/app/community-list-page/community-list-page.component`); + } + + protected importUnthemedComponent(): Promise { + return import(`./community-list-page.component`); + } + +} diff --git a/src/app/forbidden/themed-forbidden.component.ts b/src/app/forbidden/themed-forbidden.component.ts new file mode 100644 index 0000000000..bb3694cae2 --- /dev/null +++ b/src/app/forbidden/themed-forbidden.component.ts @@ -0,0 +1,27 @@ +import { Component } from '@angular/core'; +import { ThemedComponent } from '../shared/theme-support/themed.component'; +import { ForbiddenComponent } from './forbidden.component'; + +@Component({ + selector: 'ds-themed-forbidden', + styleUrls: [], + templateUrl: '../shared/theme-support/themed.component.html', +}) + +/** + * Component to render the news section on the home page + */ +export class ThemedForbiddenComponent extends ThemedComponent { + protected getComponentName(): string { + return 'ForbiddenComponent'; + } + + protected importThemedComponent(themeName: string): Promise { + return import(`../../themes/${themeName}/app/forbidden/forbidden.component`); + } + + protected importUnthemedComponent(): Promise { + return import(`./forbidden.component`); + } + +} diff --git a/src/app/info/end-user-agreement/themed-end-user-agreement.component.ts b/src/app/info/end-user-agreement/themed-end-user-agreement.component.ts new file mode 100644 index 0000000000..6c76314e06 --- /dev/null +++ b/src/app/info/end-user-agreement/themed-end-user-agreement.component.ts @@ -0,0 +1,28 @@ +import { Component } from '@angular/core'; +import { ThemedComponent } from '../../shared/theme-support/themed.component'; +import { EndUserAgreementComponent } from './end-user-agreement.component'; + +@Component({ + selector: 'ds-themed-end-user-agreement', + styleUrls: [], + templateUrl: '../../shared/theme-support/themed.component.html', +}) + +/** + * Component to render the news section on the home page + */ +export class ThemedEndUserAgreementComponent extends ThemedComponent { + + protected getComponentName(): string { + return 'EndUserAgreementComponent'; + } + + protected importThemedComponent(themeName: string): Promise { + return import(`../../../themes/${themeName}/app/info/end-user-agreement/end-user-agreement.component`); + } + + protected importUnthemedComponent(): Promise { + return import(`./end-user-agreement.component`); + } + +} diff --git a/src/app/info/info-routing.module.ts b/src/app/info/info-routing.module.ts index 799572f9b9..f76fb47ff0 100644 --- a/src/app/info/info-routing.module.ts +++ b/src/app/info/info-routing.module.ts @@ -1,16 +1,16 @@ import { NgModule } from '@angular/core'; import { RouterModule } from '@angular/router'; -import { EndUserAgreementComponent } from './end-user-agreement/end-user-agreement.component'; import { I18nBreadcrumbResolver } from '../core/breadcrumbs/i18n-breadcrumb.resolver'; -import { PrivacyComponent } from './privacy/privacy.component'; import { PRIVACY_PATH, END_USER_AGREEMENT_PATH } from './info-routing-paths'; +import { ThemedEndUserAgreementComponent } from './end-user-agreement/themed-end-user-agreement.component'; +import { ThemedPrivacyComponent } from './privacy/themed-privacy.component'; @NgModule({ imports: [ RouterModule.forChild([ { path: END_USER_AGREEMENT_PATH, - component: EndUserAgreementComponent, + component: ThemedEndUserAgreementComponent, resolve: { breadcrumb: I18nBreadcrumbResolver }, data: { title: 'info.end-user-agreement.title', breadcrumbKey: 'info.end-user-agreement' } } @@ -18,7 +18,7 @@ import { PRIVACY_PATH, END_USER_AGREEMENT_PATH } from './info-routing-paths'; RouterModule.forChild([ { path: PRIVACY_PATH, - component: PrivacyComponent, + component: ThemedPrivacyComponent, resolve: { breadcrumb: I18nBreadcrumbResolver }, data: { title: 'info.privacy.title', breadcrumbKey: 'info.privacy' } } diff --git a/src/app/info/info.module.ts b/src/app/info/info.module.ts index ae8ef89b27..84ba5a62db 100644 --- a/src/app/info/info.module.ts +++ b/src/app/info/info.module.ts @@ -6,6 +6,17 @@ import { InfoRoutingModule } from './info-routing.module'; import { EndUserAgreementContentComponent } from './end-user-agreement/end-user-agreement-content/end-user-agreement-content.component'; import { PrivacyComponent } from './privacy/privacy.component'; import { PrivacyContentComponent } from './privacy/privacy-content/privacy-content.component'; +import { ThemedEndUserAgreementComponent } from './end-user-agreement/themed-end-user-agreement.component'; +import { ThemedPrivacyComponent } from './privacy/themed-privacy.component'; + +const DECLARATIONS = [ + EndUserAgreementComponent, + ThemedEndUserAgreementComponent, + EndUserAgreementContentComponent, + PrivacyComponent, + PrivacyContentComponent, + ThemedPrivacyComponent +]; @NgModule({ imports: [ @@ -14,10 +25,10 @@ import { PrivacyContentComponent } from './privacy/privacy-content/privacy-conte InfoRoutingModule ], declarations: [ - EndUserAgreementComponent, - EndUserAgreementContentComponent, - PrivacyComponent, - PrivacyContentComponent + ...DECLARATIONS + ], + exports: [ + ...DECLARATIONS ] }) export class InfoModule { diff --git a/src/app/info/privacy/themed-privacy.component.ts b/src/app/info/privacy/themed-privacy.component.ts new file mode 100644 index 0000000000..5aed8d38af --- /dev/null +++ b/src/app/info/privacy/themed-privacy.component.ts @@ -0,0 +1,27 @@ +import { Component } from '@angular/core'; +import { ThemedComponent } from '../../shared/theme-support/themed.component'; +import { PrivacyComponent } from './privacy.component'; + +@Component({ + selector: 'ds-themed-privacy', + styleUrls: [], + templateUrl: '../../shared/theme-support/themed.component.html', +}) + +/** + * Component to render the news section on the home page + */ +export class ThemedPrivacyComponent extends ThemedComponent { + protected getComponentName(): string { + return 'PrivacyComponent'; + } + + protected importThemedComponent(themeName: string): Promise { + return import(`../../../themes/${themeName}/app/info/privacy/privacy.component`); + } + + protected importUnthemedComponent(): Promise { + return import(`./privacy.component`); + } + +} diff --git a/src/app/pagenotfound/themed-pagenotfound.component.ts b/src/app/pagenotfound/themed-pagenotfound.component.ts new file mode 100644 index 0000000000..68b06e2ac0 --- /dev/null +++ b/src/app/pagenotfound/themed-pagenotfound.component.ts @@ -0,0 +1,27 @@ +import { Component } from '@angular/core'; +import { ThemedComponent } from '../shared/theme-support/themed.component'; +import { PageNotFoundComponent } from './pagenotfound.component'; + +@Component({ + selector: 'ds-themed-search-page', + styleUrls: [], + templateUrl: '../shared/theme-support/themed.component.html', +}) +/** + * This component represents the whole search page + * It renders search results depending on the current search options + */ +export class ThemedPageNotFoundComponent extends ThemedComponent { + + protected getComponentName(): string { + return 'PageNotFoundComponent'; + } + + protected importThemedComponent(themeName: string): Promise { + return import(`../../themes/${themeName}/app/pagenotfound/pagenotfound.component`); + } + + protected importUnthemedComponent(): Promise { + return import(`./pagenotfound.component`); + } +} diff --git a/src/app/shared/shared.module.ts b/src/app/shared/shared.module.ts index 1065d82833..406c7f92fc 100644 --- a/src/app/shared/shared.module.ts +++ b/src/app/shared/shared.module.ts @@ -232,6 +232,7 @@ import { ConfigurationSearchPageComponent } from '../+search-page/configuration- import { LinkMenuItemComponent } from './menu/menu-item/link-menu-item.component'; import { OnClickMenuItemComponent } from './menu/menu-item/onclick-menu-item.component'; import { TextMenuItemComponent } from './menu/menu-item/text-menu-item.component'; +import { ThemedConfigurationSearchPageComponent } from '../+search-page/themed-configuration-search-page.component'; /** * Declaration needed to make sure all decorator functions are called in time @@ -516,7 +517,8 @@ const ENTRY_COMPONENTS = [ ]; const SHARED_SEARCH_PAGE_COMPONENTS = [ - ConfigurationSearchPageComponent + ConfigurationSearchPageComponent, + ThemedConfigurationSearchPageComponent ]; const SHARED_ITEM_PAGE_COMPONENTS = [ diff --git a/src/app/statistics-page/collection-statistics-page/themed-collection-statistics-page.component.ts b/src/app/statistics-page/collection-statistics-page/themed-collection-statistics-page.component.ts new file mode 100644 index 0000000000..75cf60437f --- /dev/null +++ b/src/app/statistics-page/collection-statistics-page/themed-collection-statistics-page.component.ts @@ -0,0 +1,27 @@ +import { Component } from '@angular/core'; +import { ThemedComponent } from '../../shared/theme-support/themed.component'; +import { CollectionStatisticsPageComponent } from './collection-statistics-page.component'; + +@Component({ + selector: 'ds-themed-collection-statistics-page', + styleUrls: [], + templateUrl: '../../shared/theme-support/themed.component.html', +}) + +/** + * Component to render the news section on the home page + */ +export class ThemedCollectionStatisticsPageComponent extends ThemedComponent { + protected getComponentName(): string { + return 'CollectionStatisticsPageComponent'; + } + + protected importThemedComponent(themeName: string): Promise { + return import(`../../../themes/${themeName}/app/statistics-page/collection-statistics-page/collection-statistics-page.component`); + } + + protected importUnthemedComponent(): Promise { + return import(`./collection-statistics-page.component`); + } + +} diff --git a/src/app/statistics-page/community-statistics-page/themed-community-statistics-page.component.ts b/src/app/statistics-page/community-statistics-page/themed-community-statistics-page.component.ts new file mode 100644 index 0000000000..34dc17e1b3 --- /dev/null +++ b/src/app/statistics-page/community-statistics-page/themed-community-statistics-page.component.ts @@ -0,0 +1,27 @@ +import { Component } from '@angular/core'; +import { ThemedComponent } from '../../shared/theme-support/themed.component'; +import { CommunityStatisticsPageComponent } from './community-statistics-page.component'; + +@Component({ + selector: 'ds-themed-collection-statistics-page', + styleUrls: [], + templateUrl: '../../shared/theme-support/themed.component.html', +}) + +/** + * Component to render the news section on the home page + */ +export class ThemedCommunityStatisticsPageComponent extends ThemedComponent { + protected getComponentName(): string { + return 'CommunityStatisticsPageComponent'; + } + + protected importThemedComponent(themeName: string): Promise { + return import(`../../../themes/${themeName}/app/statistics-page/community-statistics-page/community-statistics-page.component`); + } + + protected importUnthemedComponent(): Promise { + return import(`./community-statistics-page.component`); + } + +} diff --git a/src/app/statistics-page/item-statistics-page/themed-item-statistics-page.component.ts b/src/app/statistics-page/item-statistics-page/themed-item-statistics-page.component.ts new file mode 100644 index 0000000000..4651269c54 --- /dev/null +++ b/src/app/statistics-page/item-statistics-page/themed-item-statistics-page.component.ts @@ -0,0 +1,27 @@ +import { Component } from '@angular/core'; +import { ThemedComponent } from '../../shared/theme-support/themed.component'; +import { ItemStatisticsPageComponent } from './item-statistics-page.component'; + +@Component({ + selector: 'ds-themed-item-statistics-page', + styleUrls: [], + templateUrl: '../../shared/theme-support/themed.component.html', +}) + +/** + * Component to render the news section on the home page + */ +export class ThemedItemStatisticsPageComponent extends ThemedComponent { + protected getComponentName(): string { + return 'ItemStatisticsPageComponent'; + } + + protected importThemedComponent(themeName: string): Promise { + return import(`../../../themes/${themeName}/app/statistics-page/item-statistics-page/item-statistics-page.component`); + } + + protected importUnthemedComponent(): Promise { + return import(`./item-statistics-page.component`); + } + +} diff --git a/src/app/statistics-page/site-statistics-page/themed-site-statistics-page.component.ts b/src/app/statistics-page/site-statistics-page/themed-site-statistics-page.component.ts new file mode 100644 index 0000000000..4238cc788a --- /dev/null +++ b/src/app/statistics-page/site-statistics-page/themed-site-statistics-page.component.ts @@ -0,0 +1,27 @@ +import { Component } from '@angular/core'; +import { ThemedComponent } from '../../shared/theme-support/themed.component'; +import { SiteStatisticsPageComponent } from './site-statistics-page.component'; + +@Component({ + selector: 'ds-themed-site-statistics-page', + styleUrls: [], + templateUrl: '../../shared/theme-support/themed.component.html', +}) + +/** + * Component to render the news section on the home page + */ +export class ThemedSiteStatisticsPageComponent extends ThemedComponent { + protected getComponentName(): string { + return 'SiteStatisticsPageComponent'; + } + + protected importThemedComponent(themeName: string): Promise { + return import(`../../../themes/${themeName}/app/statistics-page/site-statistics-page/site-statistics-page.component`); + } + + protected importUnthemedComponent(): Promise { + return import(`./site-statistics-page.component`); + } + +} diff --git a/src/app/statistics-page/statistics-page-routing.module.ts b/src/app/statistics-page/statistics-page-routing.module.ts index 44943b94d2..6a133fc9ac 100644 --- a/src/app/statistics-page/statistics-page-routing.module.ts +++ b/src/app/statistics-page/statistics-page-routing.module.ts @@ -3,13 +3,13 @@ import { RouterModule } from '@angular/router'; import { I18nBreadcrumbResolver } from '../core/breadcrumbs/i18n-breadcrumb.resolver'; import { I18nBreadcrumbsService } from '../core/breadcrumbs/i18n-breadcrumbs.service'; import { StatisticsPageModule } from './statistics-page.module'; -import { SiteStatisticsPageComponent } from './site-statistics-page/site-statistics-page.component'; import { ItemPageResolver } from '../+item-page/item-page.resolver'; -import { ItemStatisticsPageComponent } from './item-statistics-page/item-statistics-page.component'; import { CollectionPageResolver } from '../+collection-page/collection-page.resolver'; -import { CollectionStatisticsPageComponent } from './collection-statistics-page/collection-statistics-page.component'; import { CommunityPageResolver } from '../+community-page/community-page.resolver'; -import { CommunityStatisticsPageComponent } from './community-statistics-page/community-statistics-page.component'; +import { ThemedCollectionStatisticsPageComponent } from './collection-statistics-page/themed-collection-statistics-page.component'; +import { ThemedCommunityStatisticsPageComponent } from './community-statistics-page/themed-community-statistics-page.component'; +import { ThemedItemStatisticsPageComponent } from './item-statistics-page/themed-item-statistics-page.component'; +import { ThemedSiteStatisticsPageComponent } from './site-statistics-page/themed-site-statistics-page.component'; @NgModule({ imports: [ @@ -27,7 +27,7 @@ import { CommunityStatisticsPageComponent } from './community-statistics-page/co children: [ { path: '', - component: SiteStatisticsPageComponent, + component: ThemedSiteStatisticsPageComponent, }, ] }, @@ -41,7 +41,7 @@ import { CommunityStatisticsPageComponent } from './community-statistics-page/co title: 'statistics.title', breadcrumbKey: 'statistics' }, - component: ItemStatisticsPageComponent, + component: ThemedItemStatisticsPageComponent, }, { path: `collections/:id`, @@ -53,7 +53,7 @@ import { CommunityStatisticsPageComponent } from './community-statistics-page/co title: 'statistics.title', breadcrumbKey: 'statistics' }, - component: CollectionStatisticsPageComponent, + component: ThemedCollectionStatisticsPageComponent, }, { path: `communities/:id`, @@ -65,7 +65,7 @@ import { CommunityStatisticsPageComponent } from './community-statistics-page/co title: 'statistics.title', breadcrumbKey: 'statistics' }, - component: CommunityStatisticsPageComponent, + component: ThemedCommunityStatisticsPageComponent, }, ] ) @@ -75,6 +75,7 @@ import { CommunityStatisticsPageComponent } from './community-statistics-page/co I18nBreadcrumbsService, CollectionPageResolver, CommunityPageResolver, + ItemPageResolver ] }) export class StatisticsPageRoutingModule { diff --git a/src/app/statistics-page/statistics-page.module.ts b/src/app/statistics-page/statistics-page.module.ts index 9957d4b0d7..863e17fcb5 100644 --- a/src/app/statistics-page/statistics-page.module.ts +++ b/src/app/statistics-page/statistics-page.module.ts @@ -10,13 +10,21 @@ import { StatisticsTableComponent } from './statistics-table/statistics-table.co import { ItemStatisticsPageComponent } from './item-statistics-page/item-statistics-page.component'; import { CollectionStatisticsPageComponent } from './collection-statistics-page/collection-statistics-page.component'; import { CommunityStatisticsPageComponent } from './community-statistics-page/community-statistics-page.component'; +import { ThemedCollectionStatisticsPageComponent } from './collection-statistics-page/themed-collection-statistics-page.component'; +import { ThemedCommunityStatisticsPageComponent } from './community-statistics-page/themed-community-statistics-page.component'; +import { ThemedItemStatisticsPageComponent } from './item-statistics-page/themed-item-statistics-page.component'; +import { ThemedSiteStatisticsPageComponent } from './site-statistics-page/themed-site-statistics-page.component'; const components = [ StatisticsTableComponent, SiteStatisticsPageComponent, ItemStatisticsPageComponent, CollectionStatisticsPageComponent, - CommunityStatisticsPageComponent + CommunityStatisticsPageComponent, + ThemedCollectionStatisticsPageComponent, + ThemedCommunityStatisticsPageComponent, + ThemedItemStatisticsPageComponent, + ThemedSiteStatisticsPageComponent ]; @NgModule({ diff --git a/src/environments/environment.common.ts b/src/environments/environment.common.ts index c6ae9858e5..bc1f634e19 100644 --- a/src/environments/environment.common.ts +++ b/src/environments/environment.common.ts @@ -251,10 +251,10 @@ export const environment: GlobalConfig = { // name: 'custom', // uuid: '0958c910-2037-42a9-81c7-dca80e3892b4' // }, - // { - // // A theme with only a name will match every route - // name: 'custom' - // }, + { + // A theme with only a name will match every route + name: 'custom' + }, { // This theme will use the default bootstrap styling for DSpace components diff --git a/src/themes/custom/app/+browse-by/+browse-by-switcher/browse-by-switcher.component.html b/src/themes/custom/app/+browse-by/+browse-by-switcher/browse-by-switcher.component.html new file mode 100644 index 0000000000..e69de29bb2 diff --git a/src/themes/custom/app/+browse-by/+browse-by-switcher/browse-by-switcher.component.scss b/src/themes/custom/app/+browse-by/+browse-by-switcher/browse-by-switcher.component.scss new file mode 100644 index 0000000000..e69de29bb2 diff --git a/src/themes/custom/app/+browse-by/+browse-by-switcher/browse-by-switcher.component.ts b/src/themes/custom/app/+browse-by/+browse-by-switcher/browse-by-switcher.component.ts new file mode 100644 index 0000000000..b772701ad0 --- /dev/null +++ b/src/themes/custom/app/+browse-by/+browse-by-switcher/browse-by-switcher.component.ts @@ -0,0 +1,15 @@ +import { Component } from '@angular/core'; +import { BrowseBySwitcherComponent as BaseComponent } from '../../../../../app/+browse-by/+browse-by-switcher/browse-by-switcher.component'; + +@Component({ + selector: 'ds-browse-by-switcher', + // styleUrls: ['./browse-by-switcher.component.scss'], + // templateUrl: './browse-by-switcher.component.html' + templateUrl: '../../../../../app/+browse-by/+browse-by-switcher/browse-by-switcher.component.html' +}) + +/** + * Component to render the news section on the home page + */ +export class BrowseBySwitcherComponent extends BaseComponent {} + diff --git a/src/themes/custom/app/+collection-page/collection-page.component.html b/src/themes/custom/app/+collection-page/collection-page.component.html new file mode 100644 index 0000000000..e69de29bb2 diff --git a/src/themes/custom/app/+collection-page/collection-page.component.scss b/src/themes/custom/app/+collection-page/collection-page.component.scss new file mode 100644 index 0000000000..e69de29bb2 diff --git a/src/themes/custom/app/+collection-page/collection-page.component.ts b/src/themes/custom/app/+collection-page/collection-page.component.ts new file mode 100644 index 0000000000..f38a90631f --- /dev/null +++ b/src/themes/custom/app/+collection-page/collection-page.component.ts @@ -0,0 +1,17 @@ +import { Component } from '@angular/core'; +import { CollectionPageComponent as BaseComponent} from '../../../../app/+collection-page/collection-page.component'; + +/** + * This component representing the `Forbidden` DSpace page. + */ +@Component({ + selector: 'ds-collection-page', + // templateUrl: './collection-page.component.html', + templateUrl: '../../../../app/+collection-page/collection-page.component.html', + // styleUrls: ['./collection-page.component.scss'] + styleUrls: ['../../../../app/+collection-page/collection-page.component.scss'] +}) +/** + * Component to render the news section on the home page + */ +export class CollectionPageComponent extends BaseComponent {} diff --git a/src/themes/custom/app/+community-page/community-page.component.html b/src/themes/custom/app/+community-page/community-page.component.html new file mode 100644 index 0000000000..e69de29bb2 diff --git a/src/themes/custom/app/+community-page/community-page.component.scss b/src/themes/custom/app/+community-page/community-page.component.scss new file mode 100644 index 0000000000..e69de29bb2 diff --git a/src/themes/custom/app/+community-page/community-page.component.ts b/src/themes/custom/app/+community-page/community-page.component.ts new file mode 100644 index 0000000000..2df33a0b9e --- /dev/null +++ b/src/themes/custom/app/+community-page/community-page.component.ts @@ -0,0 +1,17 @@ +import { Component } from '@angular/core'; +import { CommunityPageComponent as BaseComponent} from '../../../../app/+community-page/community-page.component'; + +/** + * This component representing the `Forbidden` DSpace page. + */ +@Component({ + selector: 'ds-community-page', + // templateUrl: './community-page.component.html', + templateUrl: '../../../../app/+community-page/community-page.component.html', + // styleUrls: ['./community-page.component.scss'] + styleUrls: ['../../../../app/+community-page/community-page.component.scss'] +}) +/** + * Component to render the news section on the home page + */ +export class CommunityPageComponent extends BaseComponent {} diff --git a/src/themes/custom/app/+lookup-by-id/objectnotfound/objectnotfound.component.html b/src/themes/custom/app/+lookup-by-id/objectnotfound/objectnotfound.component.html new file mode 100644 index 0000000000..e69de29bb2 diff --git a/src/themes/custom/app/+lookup-by-id/objectnotfound/objectnotfound.component.scss b/src/themes/custom/app/+lookup-by-id/objectnotfound/objectnotfound.component.scss new file mode 100644 index 0000000000..e69de29bb2 diff --git a/src/themes/custom/app/+lookup-by-id/objectnotfound/objectnotfound.component.ts b/src/themes/custom/app/+lookup-by-id/objectnotfound/objectnotfound.component.ts new file mode 100644 index 0000000000..f41553ff00 --- /dev/null +++ b/src/themes/custom/app/+lookup-by-id/objectnotfound/objectnotfound.component.ts @@ -0,0 +1,16 @@ +import { Component } from '@angular/core'; +import { ObjectNotFoundComponent as BaseComponent } from '../../../../../app/+lookup-by-id/objectnotfound/objectnotfound.component'; + +@Component({ + selector: 'ds-objnotfound', + // styleUrls: ['./objectnotfound.component.scss'], + styleUrls: ['../../../../../app/+lookup-by-id/objectnotfound/objectnotfound.component.scss'], + // templateUrl: './objectnotfound.component.html', + templateUrl: '../../../../../app/+lookup-by-id/objectnotfound/objectnotfound.component.html' +}) + +/** + * Component to render the news section on the home page + */ +export class ObjectNotFoundComponent extends BaseComponent {} + diff --git a/src/themes/custom/app/+search-page/configuration-search-page.component.html b/src/themes/custom/app/+search-page/configuration-search-page.component.html new file mode 100644 index 0000000000..e69de29bb2 diff --git a/src/themes/custom/app/+search-page/configuration-search-page.component.scss b/src/themes/custom/app/+search-page/configuration-search-page.component.scss new file mode 100644 index 0000000000..e69de29bb2 diff --git a/src/themes/custom/app/+search-page/configuration-search-page.component.ts b/src/themes/custom/app/+search-page/configuration-search-page.component.ts new file mode 100644 index 0000000000..96c3915d39 --- /dev/null +++ b/src/themes/custom/app/+search-page/configuration-search-page.component.ts @@ -0,0 +1,15 @@ +import { Component } from '@angular/core'; +import { SearchPageComponent as BaseComponent } from '../../../../app/+search-page/search-page.component'; + +@Component({ + selector: 'ds-configuration-search-page', + // styleUrls: ['./configuration-search-page.component.html'], + // templateUrl: './configuration-search-page.component.html' + templateUrl: '../../../../app/+search-page/search.component.html' +}) + +/** + * Component to render the news section on the home page + */ +export class ConfigurationSearchPageComponent extends BaseComponent {} + diff --git a/src/themes/custom/app/+search-page/search-page.component.html b/src/themes/custom/app/+search-page/search-page.component.html new file mode 100644 index 0000000000..e69de29bb2 diff --git a/src/themes/custom/app/+search-page/search-page.component.scss b/src/themes/custom/app/+search-page/search-page.component.scss new file mode 100644 index 0000000000..e69de29bb2 diff --git a/src/themes/custom/app/+search-page/search-page.component.ts b/src/themes/custom/app/+search-page/search-page.component.ts new file mode 100644 index 0000000000..1b7c912260 --- /dev/null +++ b/src/themes/custom/app/+search-page/search-page.component.ts @@ -0,0 +1,15 @@ +import { Component } from '@angular/core'; +import { SearchPageComponent as BaseComponent } from '../../../../app/+search-page/search-page.component'; + +@Component({ + selector: 'ds-search-page', + // styleUrls: ['./search-page.component.scss'], + // templateUrl: './search-page.component.html' + templateUrl: '../../../../app/+search-page/search-page.component.html' +}) + +/** + * Component to render the news section on the home page + */ +export class SearchPageComponent extends BaseComponent {} + diff --git a/src/themes/custom/app/community-list-page/community-list-page.component.html b/src/themes/custom/app/community-list-page/community-list-page.component.html new file mode 100644 index 0000000000..e69de29bb2 diff --git a/src/themes/custom/app/community-list-page/community-list-page.component.scss b/src/themes/custom/app/community-list-page/community-list-page.component.scss new file mode 100644 index 0000000000..e69de29bb2 diff --git a/src/themes/custom/app/community-list-page/community-list-page.component.ts b/src/themes/custom/app/community-list-page/community-list-page.component.ts new file mode 100644 index 0000000000..87e8be0a96 --- /dev/null +++ b/src/themes/custom/app/community-list-page/community-list-page.component.ts @@ -0,0 +1,15 @@ +import { Component } from '@angular/core'; +import { CommunityListPageComponent as BaseComponent } from '../../../../app/community-list-page/community-list-page.component'; + +@Component({ + selector: 'ds-community-list-page', + // styleUrls: ['./community-list-page.component.scss'], + // templateUrl: './community-list-page.component.html' + templateUrl: '../../../../app/community-list-page/community-list-page.component.html' +}) + +/** + * Component to render the news section on the home page + */ +export class CommunityListPageComponent extends BaseComponent {} + diff --git a/src/themes/custom/app/forbidden/forbidden.component.html b/src/themes/custom/app/forbidden/forbidden.component.html new file mode 100644 index 0000000000..e69de29bb2 diff --git a/src/themes/custom/app/forbidden/forbidden.component.scss b/src/themes/custom/app/forbidden/forbidden.component.scss new file mode 100644 index 0000000000..e69de29bb2 diff --git a/src/themes/custom/app/forbidden/forbidden.component.ts b/src/themes/custom/app/forbidden/forbidden.component.ts new file mode 100644 index 0000000000..e374d67508 --- /dev/null +++ b/src/themes/custom/app/forbidden/forbidden.component.ts @@ -0,0 +1,17 @@ +import { Component } from '@angular/core'; +import { ForbiddenComponent as BaseComponent } from '../../../../app/forbidden/forbidden.component'; + +/** + * This component representing the `Forbidden` DSpace page. + */ +@Component({ + selector: 'ds-forbidden', + // templateUrl: './forbidden.component.html', + templateUrl: '../../../../app/forbidden/forbidden.component.html', + // styleUrls: ['./forbidden.component.scss'] + styleUrls: ['../../../../app/forbidden/forbidden.component.scss'] +}) +/** + * Component to render the news section on the home page + */ +export class ForbiddenComponent extends BaseComponent {} diff --git a/src/themes/custom/app/info/end-user-agreement/end-user-agreement.component.html b/src/themes/custom/app/info/end-user-agreement/end-user-agreement.component.html new file mode 100644 index 0000000000..e69de29bb2 diff --git a/src/themes/custom/app/info/end-user-agreement/end-user-agreement.component.scss b/src/themes/custom/app/info/end-user-agreement/end-user-agreement.component.scss new file mode 100644 index 0000000000..e69de29bb2 diff --git a/src/themes/custom/app/info/end-user-agreement/end-user-agreement.component.ts b/src/themes/custom/app/info/end-user-agreement/end-user-agreement.component.ts new file mode 100644 index 0000000000..7e4f490023 --- /dev/null +++ b/src/themes/custom/app/info/end-user-agreement/end-user-agreement.component.ts @@ -0,0 +1,16 @@ +import { Component } from '@angular/core'; +import { EndUserAgreementComponent as BaseComponent } from '../../../../../app/info/end-user-agreement/end-user-agreement.component'; + +@Component({ + selector: 'ds-home-news', + // styleUrls: ['./end-user-agreement.component.scss'], + styleUrls: ['../../../../../app/info/end-user-agreement/end-user-agreement.component.scss'], + // templateUrl: './end-user-agreement.component.html' + templateUrl: '../../../../../app/info/end-user-agreement/end-user-agreement.component.html' +}) + +/** + * Component to render the news section on the home page + */ +export class EndUserAgreementComponent extends BaseComponent {} + diff --git a/src/themes/custom/app/info/privacy/privacy.component.html b/src/themes/custom/app/info/privacy/privacy.component.html new file mode 100644 index 0000000000..e69de29bb2 diff --git a/src/themes/custom/app/info/privacy/privacy.component.scss b/src/themes/custom/app/info/privacy/privacy.component.scss new file mode 100644 index 0000000000..e69de29bb2 diff --git a/src/themes/custom/app/info/privacy/privacy.component.ts b/src/themes/custom/app/info/privacy/privacy.component.ts new file mode 100644 index 0000000000..fb7f193f4e --- /dev/null +++ b/src/themes/custom/app/info/privacy/privacy.component.ts @@ -0,0 +1,15 @@ +import { Component } from '@angular/core'; +import { PrivacyComponent as BaseComponent } from '../../../../../app/info/privacy/privacy.component'; + +@Component({ + selector: 'ds-privacy', + // styleUrls: ['./privacy.component.scss'], + styleUrls: ['../../../../../app/info/privacy/privacy.component.scss'], + // templateUrl: './privacy.component.html' + templateUrl: '../../../../../app/info/privacy/privacy.component.html' +}) + +/** + * Component to render the news section on the home page + */ +export class PrivacyComponent extends BaseComponent {} diff --git a/src/themes/custom/app/pagenotfound/pagenotfound.component.html b/src/themes/custom/app/pagenotfound/pagenotfound.component.html new file mode 100644 index 0000000000..e69de29bb2 diff --git a/src/themes/custom/app/pagenotfound/pagenotfound.component.scss b/src/themes/custom/app/pagenotfound/pagenotfound.component.scss new file mode 100644 index 0000000000..e69de29bb2 diff --git a/src/themes/custom/app/pagenotfound/pagenotfound.component.ts b/src/themes/custom/app/pagenotfound/pagenotfound.component.ts new file mode 100644 index 0000000000..565b648172 --- /dev/null +++ b/src/themes/custom/app/pagenotfound/pagenotfound.component.ts @@ -0,0 +1,16 @@ +import { Component } from '@angular/core'; +import { PageNotFoundComponent as BaseComponent } from '../../../../app/pagenotfound/pagenotfound.component'; + +@Component({ + selector: 'ds-pagenotfound', + // styleUrls: ['./pagenotfound.component.scss'], + styleUrls: ['../../../../app/pagenotfound/pagenotfound.component.scss'], + // templateUrl: './pagenotfound.component.html' + templateUrl: '../../../../app/pagenotfound/pagenotfound.component.html' +}) + +/** + * Component to render the news section on the home page + */ +export class PageNotFoundComponent extends BaseComponent {} + diff --git a/src/themes/custom/app/statistics-page/collection-statistics-page/collection-statistics-page.component.html b/src/themes/custom/app/statistics-page/collection-statistics-page/collection-statistics-page.component.html new file mode 100644 index 0000000000..e69de29bb2 diff --git a/src/themes/custom/app/statistics-page/collection-statistics-page/collection-statistics-page.component.scss b/src/themes/custom/app/statistics-page/collection-statistics-page/collection-statistics-page.component.scss new file mode 100644 index 0000000000..e69de29bb2 diff --git a/src/themes/custom/app/statistics-page/collection-statistics-page/collection-statistics-page.component.ts b/src/themes/custom/app/statistics-page/collection-statistics-page/collection-statistics-page.component.ts new file mode 100644 index 0000000000..0d637fa44d --- /dev/null +++ b/src/themes/custom/app/statistics-page/collection-statistics-page/collection-statistics-page.component.ts @@ -0,0 +1,16 @@ +import { Component } from '@angular/core'; +import { CollectionStatisticsPageComponent as BaseComponent } from '../../../../../app/statistics-page/collection-statistics-page/collection-statistics-page.component'; + +@Component({ + selector: 'ds-collection-statistics-page', + // styleUrls: ['./collection-statistics-page.component.scss'], + styleUrls: ['../../../../../app/statistics-page/collection-statistics-page/collection-statistics-page.component.scss'], + // templateUrl: './collection-statistics-page.component.html', + templateUrl: '../../../../../app/statistics-page/statistics-page/statistics-page.component.html' +}) + +/** + * Component to render the news section on the home page + */ +export class CollectionStatisticsPageComponent extends BaseComponent {} + diff --git a/src/themes/custom/app/statistics-page/community-statistics-page/community-statistics-page.component.html b/src/themes/custom/app/statistics-page/community-statistics-page/community-statistics-page.component.html new file mode 100644 index 0000000000..e69de29bb2 diff --git a/src/themes/custom/app/statistics-page/community-statistics-page/community-statistics-page.component.scss b/src/themes/custom/app/statistics-page/community-statistics-page/community-statistics-page.component.scss new file mode 100644 index 0000000000..e69de29bb2 diff --git a/src/themes/custom/app/statistics-page/community-statistics-page/community-statistics-page.component.ts b/src/themes/custom/app/statistics-page/community-statistics-page/community-statistics-page.component.ts new file mode 100644 index 0000000000..7094d944c9 --- /dev/null +++ b/src/themes/custom/app/statistics-page/community-statistics-page/community-statistics-page.component.ts @@ -0,0 +1,16 @@ +import { Component } from '@angular/core'; +import { CommunityStatisticsPageComponent as BaseComponent } from '../../../../../app/statistics-page/community-statistics-page/community-statistics-page.component'; + +@Component({ + selector: 'ds-collection-statistics-page', + // styleUrls: ['./community-statistics-page.component.scss'], + styleUrls: ['../../../../../app/statistics-page/community-statistics-page/community-statistics-page.component.scss'], + // templateUrl: './community-statistics-page.component.html', + templateUrl: '../../../../../app/statistics-page/statistics-page/statistics-page.component.html' +}) + +/** + * Component to render the news section on the home page + */ +export class CommunityStatisticsPageComponent extends BaseComponent {} + diff --git a/src/themes/custom/app/statistics-page/item-statistics-page/item-statistics-page.component.html b/src/themes/custom/app/statistics-page/item-statistics-page/item-statistics-page.component.html new file mode 100644 index 0000000000..e69de29bb2 diff --git a/src/themes/custom/app/statistics-page/item-statistics-page/item-statistics-page.component.scss b/src/themes/custom/app/statistics-page/item-statistics-page/item-statistics-page.component.scss new file mode 100644 index 0000000000..e69de29bb2 diff --git a/src/themes/custom/app/statistics-page/item-statistics-page/item-statistics-page.component.ts b/src/themes/custom/app/statistics-page/item-statistics-page/item-statistics-page.component.ts new file mode 100644 index 0000000000..f436d7ea9f --- /dev/null +++ b/src/themes/custom/app/statistics-page/item-statistics-page/item-statistics-page.component.ts @@ -0,0 +1,16 @@ +import { Component } from '@angular/core'; +import { ItemStatisticsPageComponent as BaseComponent } from '../../../../../app/statistics-page/item-statistics-page/item-statistics-page.component'; + +@Component({ + selector: 'ds-item-statistics-page', + // styleUrls: ['./item-statistics-page.component.scss'], + styleUrls: ['../../../../../app/statistics-page/item-statistics-page/item-statistics-page.component.scss'], + // templateUrl: './item-statistics-page.component.html', + templateUrl: '../../../../../app/statistics-page/statistics-page/statistics-page.component.html' +}) + +/** + * Component to render the news section on the home page + */ +export class ItemStatisticsPageComponent extends BaseComponent {} + diff --git a/src/themes/custom/app/statistics-page/site-statistics-page/site-statistics-page.component.html b/src/themes/custom/app/statistics-page/site-statistics-page/site-statistics-page.component.html new file mode 100644 index 0000000000..e69de29bb2 diff --git a/src/themes/custom/app/statistics-page/site-statistics-page/site-statistics-page.component.scss b/src/themes/custom/app/statistics-page/site-statistics-page/site-statistics-page.component.scss new file mode 100644 index 0000000000..e69de29bb2 diff --git a/src/themes/custom/app/statistics-page/site-statistics-page/site-statistics-page.component.ts b/src/themes/custom/app/statistics-page/site-statistics-page/site-statistics-page.component.ts new file mode 100644 index 0000000000..3634a55ada --- /dev/null +++ b/src/themes/custom/app/statistics-page/site-statistics-page/site-statistics-page.component.ts @@ -0,0 +1,16 @@ +import { Component } from '@angular/core'; +import { SiteStatisticsPageComponent as BaseComponent } from '../../../../../app/statistics-page/site-statistics-page/site-statistics-page.component'; + +@Component({ + selector: 'ds-site-statistics-page', + // styleUrls: ['./site-statistics-page.component.scss'], + styleUrls: ['../../../../../app/statistics-page/site-statistics-page/site-statistics-page.component.scss'], + // templateUrl: './site-statistics-page.component.html', + templateUrl: '../../../../../app/statistics-page/statistics-page/statistics-page.component.html' +}) + +/** + * Component to render the news section on the home page + */ +export class SiteStatisticsPageComponent extends BaseComponent {} + diff --git a/src/themes/custom/theme.module.ts b/src/themes/custom/theme.module.ts index 1f451df1bc..18a048275a 100644 --- a/src/themes/custom/theme.module.ts +++ b/src/themes/custom/theme.module.ts @@ -37,12 +37,47 @@ import { AppModule } from '../../app/app.module'; import { PublicationComponent } from './app/+item-page/simple/item-types/publication/publication.component'; import { ItemPageModule } from '../../app/+item-page/item-page.module'; import { RouterModule } from '@angular/router'; +import { BrowseBySwitcherComponent } from './app/+browse-by/+browse-by-switcher/browse-by-switcher.component'; +import { CommunityListPageComponent } from './app/community-list-page/community-list-page.component'; +import { CommunityListPageModule } from '../../app/community-list-page/community-list-page.module'; +import { SearchPageComponent } from './app/+search-page/search-page.component'; +import { InfoModule } from '../../app/info/info.module'; +import { EndUserAgreementComponent } from './app/info/end-user-agreement/end-user-agreement.component'; +import { PageNotFoundComponent } from './app/pagenotfound/pagenotfound.component'; +import { ObjectNotFoundComponent } from './app/+lookup-by-id/objectnotfound/objectnotfound.component'; +import { ForbiddenComponent } from './app/forbidden/forbidden.component'; +import { PrivacyComponent } from './app/info/privacy/privacy.component'; +import { CollectionStatisticsPageComponent } from './app/statistics-page/collection-statistics-page/collection-statistics-page.component'; +import { CommunityStatisticsPageComponent } from './app/statistics-page/community-statistics-page/community-statistics-page.component'; +import { StatisticsPageModule } from '../../app/statistics-page/statistics-page.module'; +import { ItemStatisticsPageComponent } from './app/statistics-page/item-statistics-page/item-statistics-page.component'; +import { SiteStatisticsPageComponent } from './app/statistics-page/site-statistics-page/site-statistics-page.component'; +import { CommunityPageComponent } from './app/+community-page/community-page.component'; +import { CollectionPageComponent } from './app/+collection-page/collection-page.component'; +import { CommunityPageModule } from '../../app/+community-page/community-page.module'; +import { CollectionPageModule } from '../../app/+collection-page/collection-page.module'; +import { ConfigurationSearchPageComponent } from './app/+search-page/configuration-search-page.component'; const DECLARATIONS = [ HomePageComponent, HomeNewsComponent, RootComponent, - PublicationComponent + PublicationComponent, + BrowseBySwitcherComponent, + CommunityListPageComponent, + SearchPageComponent, + ConfigurationSearchPageComponent, + EndUserAgreementComponent, + PageNotFoundComponent, + ObjectNotFoundComponent, + ForbiddenComponent, + PrivacyComponent, + CollectionStatisticsPageComponent, + CommunityStatisticsPageComponent, + ItemStatisticsPageComponent, + SiteStatisticsPageComponent, + CommunityPageComponent, + CollectionPageComponent ]; @NgModule({ @@ -55,8 +90,11 @@ const DECLARATIONS = [ BitstreamFormatsModule, BrowseByModule, CollectionFormModule, + CollectionPageModule, CommonModule, CommunityFormModule, + CommunityListPageModule, + CommunityPageModule, CoreModule, DragDropModule, ItemPageModule, @@ -65,6 +103,7 @@ const DECLARATIONS = [ HomePageModule, HttpClientModule, IdlePreloadModule, + InfoModule, JournalEntitiesModule, MenuModule, MyDspaceSearchModule, @@ -78,6 +117,7 @@ const DECLARATIONS = [ SearchPageModule, SharedModule, StatisticsModule, + StatisticsPageModule, StoreModule, StoreRouterConnectingModule, TranslateModule, From 2a354c87e14194d23c2e04a915be4a51f9d2176c Mon Sep 17 00:00:00 2001 From: Art Lowel Date: Wed, 3 Mar 2021 15:19:55 +0100 Subject: [PATCH 080/132] fix issue with themed ConfigurationSearchPageComponent --- .../configuration-search-page.component.ts | 20 +++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/src/themes/custom/app/+search-page/configuration-search-page.component.ts b/src/themes/custom/app/+search-page/configuration-search-page.component.ts index 96c3915d39..88e9746b71 100644 --- a/src/themes/custom/app/+search-page/configuration-search-page.component.ts +++ b/src/themes/custom/app/+search-page/configuration-search-page.component.ts @@ -1,11 +1,23 @@ -import { Component } from '@angular/core'; -import { SearchPageComponent as BaseComponent } from '../../../../app/+search-page/search-page.component'; +import { Component, ChangeDetectionStrategy } from '@angular/core'; +import { pushInOut } from '../../../../app/shared/animations/push'; +import { SEARCH_CONFIG_SERVICE } from '../../../../app/+my-dspace-page/my-dspace-page.component'; +import { SearchConfigurationService } from '../../../../app/core/shared/search/search-configuration.service'; +import { ConfigurationSearchPageComponent as BaseComponent } from '../../../../app/+search-page/configuration-search-page.component'; @Component({ selector: 'ds-configuration-search-page', - // styleUrls: ['./configuration-search-page.component.html'], + // styleUrls: ['./configuration-search-page.component.scss'], + styleUrls: ['../../../../app/+search-page/search.component.scss'], // templateUrl: './configuration-search-page.component.html' - templateUrl: '../../../../app/+search-page/search.component.html' + templateUrl: '../../../../app/+search-page/search.component.html', + changeDetection: ChangeDetectionStrategy.OnPush, + animations: [pushInOut], + providers: [ + { + provide: SEARCH_CONFIG_SERVICE, + useClass: SearchConfigurationService + } + ] }) /** From 1c4763b409843e17ff10fbab23778d4a64a712f8 Mon Sep 17 00:00:00 2001 From: Yana De Pauw Date: Thu, 4 Mar 2021 09:07:58 +0100 Subject: [PATCH 081/132] 77349: Add additional properties and update comment --- .../browse-by-switcher.component.ts | 2 +- .../collection-page.component.ts | 16 ++++++++++------ .../+community-page/community-page.component.ts | 13 +++++++------ .../objectnotfound/objectnotfound.component.ts | 7 ++++--- .../configuration-search-page.component.ts | 2 +- .../app/+search-page/search-page.component.ts | 3 ++- .../community-list-page.component.ts | 3 ++- .../custom/app/forbidden/forbidden.component.ts | 6 ++---- .../end-user-agreement.component.ts | 2 +- .../custom/app/info/privacy/privacy.component.ts | 2 +- .../app/pagenotfound/pagenotfound.component.ts | 7 ++++--- .../collection-statistics-page.component.ts | 2 +- .../community-statistics-page.component.ts | 2 +- .../item-statistics-page.component.ts | 2 +- .../site-statistics-page.component.ts | 2 +- 15 files changed, 39 insertions(+), 32 deletions(-) diff --git a/src/themes/custom/app/+browse-by/+browse-by-switcher/browse-by-switcher.component.ts b/src/themes/custom/app/+browse-by/+browse-by-switcher/browse-by-switcher.component.ts index b772701ad0..58fee73779 100644 --- a/src/themes/custom/app/+browse-by/+browse-by-switcher/browse-by-switcher.component.ts +++ b/src/themes/custom/app/+browse-by/+browse-by-switcher/browse-by-switcher.component.ts @@ -9,7 +9,7 @@ import { BrowseBySwitcherComponent as BaseComponent } from '../../../../../app/+ }) /** - * Component to render the news section on the home page + * Component for determining what Browse-By component to use depending on the metadata (browse ID) provided */ export class BrowseBySwitcherComponent extends BaseComponent {} diff --git a/src/themes/custom/app/+collection-page/collection-page.component.ts b/src/themes/custom/app/+collection-page/collection-page.component.ts index f38a90631f..9d1d5f03f9 100644 --- a/src/themes/custom/app/+collection-page/collection-page.component.ts +++ b/src/themes/custom/app/+collection-page/collection-page.component.ts @@ -1,17 +1,21 @@ -import { Component } from '@angular/core'; +import { ChangeDetectionStrategy, Component } from '@angular/core'; import { CollectionPageComponent as BaseComponent} from '../../../../app/+collection-page/collection-page.component'; +import { fadeIn, fadeInOut } from '../../../../app/shared/animations/fade'; + -/** - * This component representing the `Forbidden` DSpace page. - */ @Component({ selector: 'ds-collection-page', // templateUrl: './collection-page.component.html', templateUrl: '../../../../app/+collection-page/collection-page.component.html', // styleUrls: ['./collection-page.component.scss'] - styleUrls: ['../../../../app/+collection-page/collection-page.component.scss'] + styleUrls: ['../../../../app/+collection-page/collection-page.component.scss'], + changeDetection: ChangeDetectionStrategy.OnPush, + animations: [ + fadeIn, + fadeInOut + ] }) /** - * Component to render the news section on the home page + * This component represents a detail page for a single collection */ export class CollectionPageComponent extends BaseComponent {} diff --git a/src/themes/custom/app/+community-page/community-page.component.ts b/src/themes/custom/app/+community-page/community-page.component.ts index 2df33a0b9e..54e9352eb8 100644 --- a/src/themes/custom/app/+community-page/community-page.component.ts +++ b/src/themes/custom/app/+community-page/community-page.component.ts @@ -1,17 +1,18 @@ -import { Component } from '@angular/core'; +import { ChangeDetectionStrategy, Component } from '@angular/core'; import { CommunityPageComponent as BaseComponent} from '../../../../app/+community-page/community-page.component'; +import { fadeInOut } from '../../../../app/shared/animations/fade'; + -/** - * This component representing the `Forbidden` DSpace page. - */ @Component({ selector: 'ds-community-page', // templateUrl: './community-page.component.html', templateUrl: '../../../../app/+community-page/community-page.component.html', // styleUrls: ['./community-page.component.scss'] - styleUrls: ['../../../../app/+community-page/community-page.component.scss'] + styleUrls: ['../../../../app/+community-page/community-page.component.scss'], + changeDetection: ChangeDetectionStrategy.OnPush, + animations: [fadeInOut] }) /** - * Component to render the news section on the home page + * This component represents a detail page for a single community */ export class CommunityPageComponent extends BaseComponent {} diff --git a/src/themes/custom/app/+lookup-by-id/objectnotfound/objectnotfound.component.ts b/src/themes/custom/app/+lookup-by-id/objectnotfound/objectnotfound.component.ts index f41553ff00..2c10ddde53 100644 --- a/src/themes/custom/app/+lookup-by-id/objectnotfound/objectnotfound.component.ts +++ b/src/themes/custom/app/+lookup-by-id/objectnotfound/objectnotfound.component.ts @@ -1,4 +1,4 @@ -import { Component } from '@angular/core'; +import { ChangeDetectionStrategy, Component } from '@angular/core'; import { ObjectNotFoundComponent as BaseComponent } from '../../../../../app/+lookup-by-id/objectnotfound/objectnotfound.component'; @Component({ @@ -6,11 +6,12 @@ import { ObjectNotFoundComponent as BaseComponent } from '../../../../../app/+lo // styleUrls: ['./objectnotfound.component.scss'], styleUrls: ['../../../../../app/+lookup-by-id/objectnotfound/objectnotfound.component.scss'], // templateUrl: './objectnotfound.component.html', - templateUrl: '../../../../../app/+lookup-by-id/objectnotfound/objectnotfound.component.html' + templateUrl: '../../../../../app/+lookup-by-id/objectnotfound/objectnotfound.component.html', + changeDetection: ChangeDetectionStrategy.Default }) /** - * Component to render the news section on the home page + * This component representing the `PageNotFound` DSpace page. */ export class ObjectNotFoundComponent extends BaseComponent {} diff --git a/src/themes/custom/app/+search-page/configuration-search-page.component.ts b/src/themes/custom/app/+search-page/configuration-search-page.component.ts index 88e9746b71..42e8dbf2d0 100644 --- a/src/themes/custom/app/+search-page/configuration-search-page.component.ts +++ b/src/themes/custom/app/+search-page/configuration-search-page.component.ts @@ -21,7 +21,7 @@ import { ConfigurationSearchPageComponent as BaseComponent } from '../../../../a }) /** - * Component to render the news section on the home page + * This component renders a search page using a configuration as input. */ export class ConfigurationSearchPageComponent extends BaseComponent {} diff --git a/src/themes/custom/app/+search-page/search-page.component.ts b/src/themes/custom/app/+search-page/search-page.component.ts index 1b7c912260..c9bcd65349 100644 --- a/src/themes/custom/app/+search-page/search-page.component.ts +++ b/src/themes/custom/app/+search-page/search-page.component.ts @@ -9,7 +9,8 @@ import { SearchPageComponent as BaseComponent } from '../../../../app/+search-pa }) /** - * Component to render the news section on the home page + * This component represents the whole search page + * It renders search results depending on the current search options */ export class SearchPageComponent extends BaseComponent {} diff --git a/src/themes/custom/app/community-list-page/community-list-page.component.ts b/src/themes/custom/app/community-list-page/community-list-page.component.ts index 87e8be0a96..1dbfa15b40 100644 --- a/src/themes/custom/app/community-list-page/community-list-page.component.ts +++ b/src/themes/custom/app/community-list-page/community-list-page.component.ts @@ -9,7 +9,8 @@ import { CommunityListPageComponent as BaseComponent } from '../../../../app/com }) /** - * Component to render the news section on the home page + * Page with title and the community list tree, as described in community-list.component; + * navigated to with community-list.page.routing.module */ export class CommunityListPageComponent extends BaseComponent {} diff --git a/src/themes/custom/app/forbidden/forbidden.component.ts b/src/themes/custom/app/forbidden/forbidden.component.ts index e374d67508..915cf651cb 100644 --- a/src/themes/custom/app/forbidden/forbidden.component.ts +++ b/src/themes/custom/app/forbidden/forbidden.component.ts @@ -1,9 +1,7 @@ import { Component } from '@angular/core'; import { ForbiddenComponent as BaseComponent } from '../../../../app/forbidden/forbidden.component'; -/** - * This component representing the `Forbidden` DSpace page. - */ + @Component({ selector: 'ds-forbidden', // templateUrl: './forbidden.component.html', @@ -12,6 +10,6 @@ import { ForbiddenComponent as BaseComponent } from '../../../../app/forbidden/f styleUrls: ['../../../../app/forbidden/forbidden.component.scss'] }) /** - * Component to render the news section on the home page + * This component representing the `Forbidden` DSpace page. */ export class ForbiddenComponent extends BaseComponent {} diff --git a/src/themes/custom/app/info/end-user-agreement/end-user-agreement.component.ts b/src/themes/custom/app/info/end-user-agreement/end-user-agreement.component.ts index 7e4f490023..e3e5ac8d19 100644 --- a/src/themes/custom/app/info/end-user-agreement/end-user-agreement.component.ts +++ b/src/themes/custom/app/info/end-user-agreement/end-user-agreement.component.ts @@ -10,7 +10,7 @@ import { EndUserAgreementComponent as BaseComponent } from '../../../../../app/i }) /** - * Component to render the news section on the home page + * Component displaying the End User Agreement and an option to accept it */ export class EndUserAgreementComponent extends BaseComponent {} diff --git a/src/themes/custom/app/info/privacy/privacy.component.ts b/src/themes/custom/app/info/privacy/privacy.component.ts index fb7f193f4e..f261c64c14 100644 --- a/src/themes/custom/app/info/privacy/privacy.component.ts +++ b/src/themes/custom/app/info/privacy/privacy.component.ts @@ -10,6 +10,6 @@ import { PrivacyComponent as BaseComponent } from '../../../../../app/info/priva }) /** - * Component to render the news section on the home page + * Component displaying the Privacy Statement */ export class PrivacyComponent extends BaseComponent {} diff --git a/src/themes/custom/app/pagenotfound/pagenotfound.component.ts b/src/themes/custom/app/pagenotfound/pagenotfound.component.ts index 565b648172..71dc7332d4 100644 --- a/src/themes/custom/app/pagenotfound/pagenotfound.component.ts +++ b/src/themes/custom/app/pagenotfound/pagenotfound.component.ts @@ -1,4 +1,4 @@ -import { Component } from '@angular/core'; +import { ChangeDetectionStrategy, Component } from '@angular/core'; import { PageNotFoundComponent as BaseComponent } from '../../../../app/pagenotfound/pagenotfound.component'; @Component({ @@ -6,11 +6,12 @@ import { PageNotFoundComponent as BaseComponent } from '../../../../app/pagenotf // styleUrls: ['./pagenotfound.component.scss'], styleUrls: ['../../../../app/pagenotfound/pagenotfound.component.scss'], // templateUrl: './pagenotfound.component.html' - templateUrl: '../../../../app/pagenotfound/pagenotfound.component.html' + templateUrl: '../../../../app/pagenotfound/pagenotfound.component.html', + changeDetection: ChangeDetectionStrategy.Default }) /** - * Component to render the news section on the home page + * This component representing the `PageNotFound` DSpace page. */ export class PageNotFoundComponent extends BaseComponent {} diff --git a/src/themes/custom/app/statistics-page/collection-statistics-page/collection-statistics-page.component.ts b/src/themes/custom/app/statistics-page/collection-statistics-page/collection-statistics-page.component.ts index 0d637fa44d..f3fa9d3e42 100644 --- a/src/themes/custom/app/statistics-page/collection-statistics-page/collection-statistics-page.component.ts +++ b/src/themes/custom/app/statistics-page/collection-statistics-page/collection-statistics-page.component.ts @@ -10,7 +10,7 @@ import { CollectionStatisticsPageComponent as BaseComponent } from '../../../../ }) /** - * Component to render the news section on the home page + * Component representing the statistics page for a collection. */ export class CollectionStatisticsPageComponent extends BaseComponent {} diff --git a/src/themes/custom/app/statistics-page/community-statistics-page/community-statistics-page.component.ts b/src/themes/custom/app/statistics-page/community-statistics-page/community-statistics-page.component.ts index 7094d944c9..76aac6aa15 100644 --- a/src/themes/custom/app/statistics-page/community-statistics-page/community-statistics-page.component.ts +++ b/src/themes/custom/app/statistics-page/community-statistics-page/community-statistics-page.component.ts @@ -10,7 +10,7 @@ import { CommunityStatisticsPageComponent as BaseComponent } from '../../../../. }) /** - * Component to render the news section on the home page + * Component representing the statistics page for a community. */ export class CommunityStatisticsPageComponent extends BaseComponent {} diff --git a/src/themes/custom/app/statistics-page/item-statistics-page/item-statistics-page.component.ts b/src/themes/custom/app/statistics-page/item-statistics-page/item-statistics-page.component.ts index f436d7ea9f..f2adbc9c21 100644 --- a/src/themes/custom/app/statistics-page/item-statistics-page/item-statistics-page.component.ts +++ b/src/themes/custom/app/statistics-page/item-statistics-page/item-statistics-page.component.ts @@ -10,7 +10,7 @@ import { ItemStatisticsPageComponent as BaseComponent } from '../../../../../app }) /** - * Component to render the news section on the home page + * Component representing the statistics page for an item. */ export class ItemStatisticsPageComponent extends BaseComponent {} diff --git a/src/themes/custom/app/statistics-page/site-statistics-page/site-statistics-page.component.ts b/src/themes/custom/app/statistics-page/site-statistics-page/site-statistics-page.component.ts index 3634a55ada..30dc6502ea 100644 --- a/src/themes/custom/app/statistics-page/site-statistics-page/site-statistics-page.component.ts +++ b/src/themes/custom/app/statistics-page/site-statistics-page/site-statistics-page.component.ts @@ -10,7 +10,7 @@ import { SiteStatisticsPageComponent as BaseComponent } from '../../../../../app }) /** - * Component to render the news section on the home page + * Component representing the site-wide statistics page. */ export class SiteStatisticsPageComponent extends BaseComponent {} From cddbdbfed7a4b875201bc29b97e60af90c78a207 Mon Sep 17 00:00:00 2001 From: lotte Date: Tue, 2 Mar 2021 18:22:02 +0100 Subject: [PATCH 082/132] 77350: wip --- .../full/full-item-page.component.ts | 3 +-- .../full/themed-full-item-page.component.ts | 25 +++++++++++++++++ .../+item-page/item-page-routing.module.ts | 10 +++---- src/app/+item-page/item-page.module.ts | 4 +++ .../simple/themed-item-page.component.ts | 27 +++++++++++++++++++ .../+login-page/login-page-routing.module.ts | 5 ++-- src/app/+login-page/login-page.module.ts | 4 ++- .../themed-login-page.component.ts | 25 +++++++++++++++++ .../logout-page-routing.module.ts | 5 ++-- src/app/+logout-page/logout-page.module.ts | 4 ++- .../themed-logout-page.component.ts | 25 +++++++++++++++++ .../themed-forgot-email.component.ts | 26 ++++++++++++++++++ .../themed-forgot-password-form.component.ts | 25 +++++++++++++++++ .../forgot-password-routing.module.ts | 10 +++---- .../forgot-password/forgot-password.module.ts | 6 ++++- .../profile-page-routing.module.ts | 4 +-- src/app/profile-page/profile-page.module.ts | 2 ++ .../themed-profile-page.component.ts | 25 +++++++++++++++++ .../themed-create-profile.component.ts | 25 +++++++++++++++++ .../register-page-routing.module.ts | 3 ++- src/app/register-page/register-page.module.ts | 4 ++- 21 files changed, 242 insertions(+), 25 deletions(-) create mode 100644 src/app/+item-page/full/themed-full-item-page.component.ts create mode 100644 src/app/+item-page/simple/themed-item-page.component.ts create mode 100644 src/app/+login-page/themed-login-page.component.ts create mode 100644 src/app/+logout-page/themed-logout-page.component.ts create mode 100644 src/app/forgot-password/forgot-password-email/themed-forgot-email.component.ts create mode 100644 src/app/forgot-password/forgot-password-form/themed-forgot-password-form.component.ts create mode 100644 src/app/profile-page/themed-profile-page.component.ts create mode 100644 src/app/register-page/create-profile/themed-create-profile.component.ts diff --git a/src/app/+item-page/full/full-item-page.component.ts b/src/app/+item-page/full/full-item-page.component.ts index 741f1e76a7..aea350e58e 100644 --- a/src/app/+item-page/full/full-item-page.component.ts +++ b/src/app/+item-page/full/full-item-page.component.ts @@ -18,9 +18,8 @@ import { hasValue } from '../../shared/empty.util'; import { AuthService } from '../../core/auth/auth.service'; /** - * This component renders a simple item page. + * This component renders a full item page. * The route parameter 'id' is used to request the item it represents. - * All fields of the item that should be displayed, are defined in its template. */ @Component({ diff --git a/src/app/+item-page/full/themed-full-item-page.component.ts b/src/app/+item-page/full/themed-full-item-page.component.ts new file mode 100644 index 0000000000..3d89f489ff --- /dev/null +++ b/src/app/+item-page/full/themed-full-item-page.component.ts @@ -0,0 +1,25 @@ +import { Component } from '@angular/core'; +import { ThemedComponent } from '../../shared/theme-support/themed.component'; +import { FullItemPageComponent } from './full-item-page.component'; + +/** + * Themed wrapper for FullItemPageComponent + */ +@Component({ + selector: 'ds-themed-full-item-page', + styleUrls: [], + templateUrl: './../../shared/theme-support/themed.component.html', +}) +export class ThemedFullItemPageComponent extends ThemedComponent { + protected getComponentName(): string { + return 'FullItemPageComponent'; + } + + protected importThemedComponent(themeName: string): Promise { + return import(`../../themes/${themeName}/app/+item-page/full/full-item-page.component`); + } + + protected importUnthemedComponent(): Promise { + return import(`./full-item-page.component`); + } +} diff --git a/src/app/+item-page/item-page-routing.module.ts b/src/app/+item-page/item-page-routing.module.ts index b04a783b2f..b259f57dcb 100644 --- a/src/app/+item-page/item-page-routing.module.ts +++ b/src/app/+item-page/item-page-routing.module.ts @@ -1,7 +1,5 @@ import { NgModule } from '@angular/core'; import { RouterModule } from '@angular/router'; - -import { ItemPageComponent } from './simple/item-page.component'; import { FullItemPageComponent } from './full/full-item-page.component'; import { ItemPageResolver } from './item-page.resolver'; import { AuthenticatedGuard } from '../core/auth/authenticated.guard'; @@ -9,10 +7,12 @@ import { ItemBreadcrumbResolver } from '../core/breadcrumbs/item-breadcrumb.reso import { DSOBreadcrumbsService } from '../core/breadcrumbs/dso-breadcrumbs.service'; import { LinkService } from '../core/cache/builders/link.service'; import { UploadBitstreamComponent } from './bitstreams/upload/upload-bitstream.component'; -import { UPLOAD_BITSTREAM_PATH, ITEM_EDIT_PATH } from './item-page-routing-paths'; +import { ITEM_EDIT_PATH, UPLOAD_BITSTREAM_PATH } from './item-page-routing-paths'; import { ItemPageAdministratorGuard } from './item-page-administrator.guard'; import { MenuItemType } from '../shared/menu/initial-menus-state'; import { LinkMenuItemModel } from '../shared/menu/menu-item/models/link.model'; +import { ThemedItemPageComponent } from './simple/themed-item-page.component'; +import { ThemedFullItemPageComponent } from './full/themed-full-item-page.component'; @NgModule({ imports: [ @@ -27,12 +27,12 @@ import { LinkMenuItemModel } from '../shared/menu/menu-item/models/link.model'; children: [ { path: '', - component: ItemPageComponent, + component: ThemedItemPageComponent, pathMatch: 'full', }, { path: 'full', - component: FullItemPageComponent, + component: ThemedFullItemPageComponent, }, { path: ITEM_EDIT_PATH, diff --git a/src/app/+item-page/item-page.module.ts b/src/app/+item-page/item-page.module.ts index ed8d872b36..af95411cef 100644 --- a/src/app/+item-page/item-page.module.ts +++ b/src/app/+item-page/item-page.module.ts @@ -25,6 +25,8 @@ import { AbstractIncrementalListComponent } from './simple/abstract-incremental- import { UntypedItemComponent } from './simple/item-types/untyped-item/untyped-item.component'; import { JournalEntitiesModule } from '../entity-groups/journal-entities/journal-entities.module'; import { ResearchEntitiesModule } from '../entity-groups/research-entities/research-entities.module'; +import { ThemedItemPageComponent } from './simple/themed-item-page.component'; +import { ThemedFullItemPageComponent } from './full/themed-full-item-page.component'; const ENTRY_COMPONENTS = [ // put only entry components that use custom decorator @@ -34,7 +36,9 @@ const ENTRY_COMPONENTS = [ const DECLARATIONS = [ ItemPageComponent, + ThemedItemPageComponent, FullItemPageComponent, + ThemedFullItemPageComponent, MetadataUriValuesComponent, ItemPageAuthorFieldComponent, ItemPageDateFieldComponent, diff --git a/src/app/+item-page/simple/themed-item-page.component.ts b/src/app/+item-page/simple/themed-item-page.component.ts new file mode 100644 index 0000000000..3d04f04acd --- /dev/null +++ b/src/app/+item-page/simple/themed-item-page.component.ts @@ -0,0 +1,27 @@ +import { Component } from '@angular/core'; +import { ThemedComponent } from '../../shared/theme-support/themed.component'; +import { ItemPageComponent } from './item-page.component'; + +/** + * Themed wrapper for ItemPageComponent + */ +@Component({ + selector: 'ds-themed-item-page', + styleUrls: [], + templateUrl: './../../shared/theme-support/themed.component.html', +}) + +export class ThemedItemPageComponent extends ThemedComponent { + protected getComponentName(): string { + return 'ItemPageComponent'; + } + + protected importThemedComponent(themeName: string): Promise { + return import(`../../../themes/${themeName}/app/+item-page/simple/item-page.component`); + } + + protected importUnthemedComponent(): Promise { + return import(`./item-page.component`); + } + +} diff --git a/src/app/+login-page/login-page-routing.module.ts b/src/app/+login-page/login-page-routing.module.ts index 9fa4a9e5ad..3a48852625 100644 --- a/src/app/+login-page/login-page-routing.module.ts +++ b/src/app/+login-page/login-page-routing.module.ts @@ -1,14 +1,13 @@ import { NgModule } from '@angular/core'; import { RouterModule } from '@angular/router'; - -import { LoginPageComponent } from './login-page.component'; import { I18nBreadcrumbResolver } from '../core/breadcrumbs/i18n-breadcrumb.resolver'; import { I18nBreadcrumbsService } from '../core/breadcrumbs/i18n-breadcrumbs.service'; +import { ThemedLoginPageComponent } from './themed-login-page.component'; @NgModule({ imports: [ RouterModule.forChild([ - { path: '', pathMatch: 'full', component: LoginPageComponent, resolve: { breadcrumb: I18nBreadcrumbResolver }, data: { breadcrumbKey: 'login', title: 'login.title' } } + { path: '', pathMatch: 'full', component: ThemedLoginPageComponent, resolve: { breadcrumb: I18nBreadcrumbResolver }, data: { breadcrumbKey: 'login', title: 'login.title' } } ]) ], providers: [ diff --git a/src/app/+login-page/login-page.module.ts b/src/app/+login-page/login-page.module.ts index 4d3f726c40..4facc82df1 100644 --- a/src/app/+login-page/login-page.module.ts +++ b/src/app/+login-page/login-page.module.ts @@ -3,6 +3,7 @@ import { NgModule } from '@angular/core'; import { SharedModule } from '../shared/shared.module'; import { LoginPageComponent } from './login-page.component'; import { LoginPageRoutingModule } from './login-page-routing.module'; +import { ThemedLoginPageComponent } from './themed-login-page.component'; @NgModule({ imports: [ @@ -11,7 +12,8 @@ import { LoginPageRoutingModule } from './login-page-routing.module'; SharedModule, ], declarations: [ - LoginPageComponent + LoginPageComponent, + ThemedLoginPageComponent ] }) export class LoginPageModule { diff --git a/src/app/+login-page/themed-login-page.component.ts b/src/app/+login-page/themed-login-page.component.ts new file mode 100644 index 0000000000..cdf5932802 --- /dev/null +++ b/src/app/+login-page/themed-login-page.component.ts @@ -0,0 +1,25 @@ +import { Component } from '@angular/core'; +import { ThemedComponent } from '../shared/theme-support/themed.component'; +import { LoginPageComponent } from './login-page.component'; + +/** + * Themed wrapper for LoginPageComponent + */ +@Component({ + selector: 'ds-themed-login-page', + styleUrls: [], + templateUrl: './../shared/theme-support/themed.component.html' +}) +export class ThemedLoginPageComponent extends ThemedComponent { + protected getComponentName(): string { + return 'LoginPageComponent'; + } + + protected importThemedComponent(themeName: string): Promise { + return import(`../../themes/${themeName}/app/+login-page/login-page.component`); + } + + protected importUnthemedComponent(): Promise { + return import(`./login-page.component`); + } +} diff --git a/src/app/+logout-page/logout-page-routing.module.ts b/src/app/+logout-page/logout-page-routing.module.ts index 64894c1f87..a5df0fe580 100644 --- a/src/app/+logout-page/logout-page-routing.module.ts +++ b/src/app/+logout-page/logout-page-routing.module.ts @@ -1,8 +1,7 @@ import { NgModule } from '@angular/core'; import { RouterModule } from '@angular/router'; - -import { LogoutPageComponent } from './logout-page.component'; import { AuthenticatedGuard } from '../core/auth/authenticated.guard'; +import { ThemedLogoutPageComponent } from './themed-logout-page.component'; @NgModule({ imports: [ @@ -10,7 +9,7 @@ import { AuthenticatedGuard } from '../core/auth/authenticated.guard'; { canActivate: [AuthenticatedGuard], path: '', - component: LogoutPageComponent, + component: ThemedLogoutPageComponent, data: { title: 'logout.title' } } ]) diff --git a/src/app/+logout-page/logout-page.module.ts b/src/app/+logout-page/logout-page.module.ts index b085a5117b..59a5459e7f 100644 --- a/src/app/+logout-page/logout-page.module.ts +++ b/src/app/+logout-page/logout-page.module.ts @@ -3,6 +3,7 @@ import { NgModule } from '@angular/core'; import { SharedModule } from '../shared/shared.module'; import { LogoutPageComponent } from './logout-page.component'; import { LogoutPageRoutingModule } from './logout-page-routing.module'; +import { ThemedLogoutPageComponent } from './themed-logout-page.component'; @NgModule({ imports: [ @@ -11,7 +12,8 @@ import { LogoutPageRoutingModule } from './logout-page-routing.module'; SharedModule, ], declarations: [ - LogoutPageComponent + LogoutPageComponent, + ThemedLogoutPageComponent ] }) export class LogoutPageModule { diff --git a/src/app/+logout-page/themed-logout-page.component.ts b/src/app/+logout-page/themed-logout-page.component.ts new file mode 100644 index 0000000000..19e1e2d1d1 --- /dev/null +++ b/src/app/+logout-page/themed-logout-page.component.ts @@ -0,0 +1,25 @@ +import { Component } from '@angular/core'; +import { ThemedComponent } from '../shared/theme-support/themed.component'; +import { LogoutPageComponent } from './logout-page.component'; + +/** + * Themed wrapper for LogoutPageComponent + */ +@Component({ + selector: 'ds-themed-logout-page', + styleUrls: [], + templateUrl: './../shared/theme-support/themed.component.html' +}) +export class ThemedLogoutPageComponent extends ThemedComponent { + protected getComponentName(): string { + return 'LogoutPageComponent'; + } + + protected importThemedComponent(themeName: string): Promise { + return import(`../../themes/${themeName}/app/+logout-page/logout-page.component`); + } + + protected importUnthemedComponent(): Promise { + return import(`./logout-page.component`); + } +} diff --git a/src/app/forgot-password/forgot-password-email/themed-forgot-email.component.ts b/src/app/forgot-password/forgot-password-email/themed-forgot-email.component.ts new file mode 100644 index 0000000000..68fcf9302f --- /dev/null +++ b/src/app/forgot-password/forgot-password-email/themed-forgot-email.component.ts @@ -0,0 +1,26 @@ +import { Component } from '@angular/core'; +import { ThemedComponent } from '../../shared/theme-support/themed.component'; +import { ForgotEmailComponent } from './forgot-email.component'; + +/** + * Themed wrapper for ForgotEmailComponent + */ +@Component({ + selector: 'ds-themed-forgot-email', + styleUrls: [], + templateUrl: './../../shared/theme-support/themed.component.html' +}) +export class ThemedForgotEmailComponent extends ThemedComponent { + protected getComponentName(): string { + return 'ForgotEmailComponent'; + } + + protected importThemedComponent(themeName: string): Promise { + return import(`../../themes/${themeName}/app/forgot-password/forgot-password-email/forgot-email.component`); + } + + protected importUnthemedComponent(): Promise { + return import(`./forgot-email.component`); + } + +} diff --git a/src/app/forgot-password/forgot-password-form/themed-forgot-password-form.component.ts b/src/app/forgot-password/forgot-password-form/themed-forgot-password-form.component.ts new file mode 100644 index 0000000000..523f81312a --- /dev/null +++ b/src/app/forgot-password/forgot-password-form/themed-forgot-password-form.component.ts @@ -0,0 +1,25 @@ +import { Component } from '@angular/core'; +import { ThemedComponent } from '../../shared/theme-support/themed.component'; +import { ForgotPasswordFormComponent } from './forgot-password-form.component'; + +/** + * Themed wrapper for ForgotPasswordFormComponent + */ +@Component({ + selector: 'ds-themed-forgot-password-form', + styleUrls: [], + templateUrl: './../../shared/theme-support/themed.component.html' +}) +export class ThemedForgotPasswordFormComponent extends ThemedComponent { + protected getComponentName(): string { + return 'ForgotPasswordFormComponent'; + } + + protected importThemedComponent(themeName: string): Promise { + return import(`../../themes/${themeName}/app/forgot-password/forgot-password-form/forgot-password-form.component`); + } + + protected importUnthemedComponent(): Promise { + return import(`./forgot-password-form.component`); + } +} diff --git a/src/app/forgot-password/forgot-password-routing.module.ts b/src/app/forgot-password/forgot-password-routing.module.ts index 702de03a9d..2496c4eec6 100644 --- a/src/app/forgot-password/forgot-password-routing.module.ts +++ b/src/app/forgot-password/forgot-password-routing.module.ts @@ -2,27 +2,27 @@ import { NgModule } from '@angular/core'; import { RouterModule } from '@angular/router'; import { ItemPageResolver } from '../+item-page/item-page.resolver'; import { RegistrationResolver } from '../register-email-form/registration.resolver'; -import { ForgotPasswordFormComponent } from './forgot-password-form/forgot-password-form.component'; -import { ForgotEmailComponent } from './forgot-password-email/forgot-email.component'; +import { ThemedForgotPasswordFormComponent } from './forgot-password-form/themed-forgot-password-form.component'; +import { ThemedForgotEmailComponent } from './forgot-password-email/themed-forgot-email.component'; @NgModule({ imports: [ RouterModule.forChild([ { path: '', - component: ForgotEmailComponent, + component: ThemedForgotEmailComponent, data: {title: 'forgot-password.title'}, }, { path: ':token', - component: ForgotPasswordFormComponent, + component: ThemedForgotPasswordFormComponent, resolve: {registration: RegistrationResolver} } ]) ], providers: [ RegistrationResolver, - ItemPageResolver + ItemPageResolver, ] }) /** diff --git a/src/app/forgot-password/forgot-password.module.ts b/src/app/forgot-password/forgot-password.module.ts index 94fb482db9..593149d2a5 100644 --- a/src/app/forgot-password/forgot-password.module.ts +++ b/src/app/forgot-password/forgot-password.module.ts @@ -6,6 +6,8 @@ import { ForgotPasswordRoutingModule } from './forgot-password-routing.module'; import { RegisterEmailFormModule } from '../register-email-form/register-email-form.module'; import { ForgotPasswordFormComponent } from './forgot-password-form/forgot-password-form.component'; import { ProfilePageModule } from '../profile-page/profile-page.module'; +import { ThemedForgotPasswordFormComponent } from './forgot-password-form/themed-forgot-password-form.component'; +import { ThemedForgotEmailComponent } from './forgot-password-email/themed-forgot-email.component'; @NgModule({ imports: [ @@ -17,7 +19,9 @@ import { ProfilePageModule } from '../profile-page/profile-page.module'; ], declarations: [ ForgotEmailComponent, - ForgotPasswordFormComponent + ThemedForgotEmailComponent, + ForgotPasswordFormComponent, + ThemedForgotPasswordFormComponent, ], providers: [] }) diff --git a/src/app/profile-page/profile-page-routing.module.ts b/src/app/profile-page/profile-page-routing.module.ts index 4b9f2b7fff..695a78837f 100644 --- a/src/app/profile-page/profile-page-routing.module.ts +++ b/src/app/profile-page/profile-page-routing.module.ts @@ -1,12 +1,12 @@ import { NgModule } from '@angular/core'; import { RouterModule } from '@angular/router'; import { I18nBreadcrumbResolver } from '../core/breadcrumbs/i18n-breadcrumb.resolver'; -import { ProfilePageComponent } from './profile-page.component'; +import { ThemedProfilePageComponent } from './themed-profile-page.component'; @NgModule({ imports: [ RouterModule.forChild([ - { path: '', pathMatch: 'full', component: ProfilePageComponent, resolve: { breadcrumb: I18nBreadcrumbResolver }, data: { breadcrumbKey: 'profile', title: 'profile.title' } } + { path: '', pathMatch: 'full', component: ThemedProfilePageComponent, resolve: { breadcrumb: I18nBreadcrumbResolver }, data: { breadcrumbKey: 'profile', title: 'profile.title' } } ]) ] }) diff --git a/src/app/profile-page/profile-page.module.ts b/src/app/profile-page/profile-page.module.ts index 54b59c97ce..6fd0c8e4aa 100644 --- a/src/app/profile-page/profile-page.module.ts +++ b/src/app/profile-page/profile-page.module.ts @@ -5,6 +5,7 @@ import { ProfilePageRoutingModule } from './profile-page-routing.module'; import { ProfilePageComponent } from './profile-page.component'; import { ProfilePageMetadataFormComponent } from './profile-page-metadata-form/profile-page-metadata-form.component'; import { ProfilePageSecurityFormComponent } from './profile-page-security-form/profile-page-security-form.component'; +import { ThemedProfilePageComponent } from './themed-profile-page.component'; @NgModule({ imports: [ @@ -17,6 +18,7 @@ import { ProfilePageSecurityFormComponent } from './profile-page-security-form/p ], declarations: [ ProfilePageComponent, + ThemedProfilePageComponent, ProfilePageMetadataFormComponent, ProfilePageSecurityFormComponent ] diff --git a/src/app/profile-page/themed-profile-page.component.ts b/src/app/profile-page/themed-profile-page.component.ts new file mode 100644 index 0000000000..2348d416cf --- /dev/null +++ b/src/app/profile-page/themed-profile-page.component.ts @@ -0,0 +1,25 @@ +import { Component } from '@angular/core'; +import { ThemedComponent } from '../shared/theme-support/themed.component'; +import { ProfilePageComponent } from './profile-page.component'; + +/** + * Themed wrapper for ProfilePageComponent + */ +@Component({ + selector: 'ds-themed-profile-page', + styleUrls: [], + templateUrl: './../shared/theme-support/themed.component.html' +}) +export class ThemedProfilePageComponent extends ThemedComponent { + protected getComponentName(): string { + return 'ProfilePageComponent'; + } + + protected importThemedComponent(themeName: string): Promise { + return import(`../../themes/${themeName}/app/profile-page/profile-page.component`); + } + + protected importUnthemedComponent(): Promise { + return import(`./profile-page.component`); + } +} diff --git a/src/app/register-page/create-profile/themed-create-profile.component.ts b/src/app/register-page/create-profile/themed-create-profile.component.ts new file mode 100644 index 0000000000..3cbc4ad553 --- /dev/null +++ b/src/app/register-page/create-profile/themed-create-profile.component.ts @@ -0,0 +1,25 @@ +import { Component } from '@angular/core'; +import { CreateProfileComponent } from './create-profile.component'; +import { ThemedComponent } from '../../shared/theme-support/themed.component'; + +/** + * Themed wrapper for CreateProfileComponent + */ +@Component({ + selector: 'ds-themed-create-profile', + styleUrls: [], + templateUrl: './../../shared/theme-support/themed.component.html' +}) +export class ThemedCreateProfileComponent extends ThemedComponent { + protected getComponentName(): string { + return 'CreateProfileComponent'; + } + + protected importThemedComponent(themeName: string): Promise { + return import(`../../themes/${themeName}/app/register-page/create-profile/create-profile.component`); + } + + protected importUnthemedComponent(): Promise { + return import(`./create-profile.component`); + } +} diff --git a/src/app/register-page/register-page-routing.module.ts b/src/app/register-page/register-page-routing.module.ts index 7954d7963a..0fdb92b4ec 100644 --- a/src/app/register-page/register-page-routing.module.ts +++ b/src/app/register-page/register-page-routing.module.ts @@ -5,6 +5,7 @@ import { CreateProfileComponent } from './create-profile/create-profile.componen import { ItemPageResolver } from '../+item-page/item-page.resolver'; import { RegistrationResolver } from '../register-email-form/registration.resolver'; import { EndUserAgreementCookieGuard } from '../core/end-user-agreement/end-user-agreement-cookie.guard'; +import { ThemedCreateProfileComponent } from './create-profile/themed-create-profile.component'; @NgModule({ imports: [ @@ -16,7 +17,7 @@ import { EndUserAgreementCookieGuard } from '../core/end-user-agreement/end-user }, { path: ':token', - component: CreateProfileComponent, + component: ThemedCreateProfileComponent, resolve: {registration: RegistrationResolver}, canActivate: [EndUserAgreementCookieGuard] } diff --git a/src/app/register-page/register-page.module.ts b/src/app/register-page/register-page.module.ts index 34f890afe8..b13dbb6afb 100644 --- a/src/app/register-page/register-page.module.ts +++ b/src/app/register-page/register-page.module.ts @@ -6,6 +6,7 @@ import { RegisterEmailComponent } from './register-email/register-email.componen import { CreateProfileComponent } from './create-profile/create-profile.component'; import { RegisterEmailFormModule } from '../register-email-form/register-email-form.module'; import { ProfilePageModule } from '../profile-page/profile-page.module'; +import { ThemedCreateProfileComponent } from './create-profile/themed-create-profile.component'; @NgModule({ imports: [ @@ -17,7 +18,8 @@ import { ProfilePageModule } from '../profile-page/profile-page.module'; ], declarations: [ RegisterEmailComponent, - CreateProfileComponent + CreateProfileComponent, + ThemedCreateProfileComponent ], providers: [] }) From d3dd8fb5654a1597d23553fa5b8fd1052e38ef30 Mon Sep 17 00:00:00 2001 From: lotte Date: Thu, 4 Mar 2021 14:00:37 +0100 Subject: [PATCH 083/132] Finished themeable components --- .../import-external-routing.module.ts | 4 +- .../full/themed-full-item-page.component.ts | 2 +- .../my-dspace-page-routing.module.ts | 5 +- .../+my-dspace-page/my-dspace-page.module.ts | 19 +++--- .../themed-my-dspace-page.component.ts | 27 ++++++++ .../submit-page-routing.module.ts | 4 +- .../themed-workflow-item-delete.component.ts | 26 ++++++++ ...hemed-workflow-item-send-back.component.ts | 26 ++++++++ .../workflowitems-edit-page-routing.module.ts | 18 +++--- .../workflowitems-edit-page.module.ts | 4 +- ...workspaceitems-edit-page-routing.module.ts | 4 +- .../forgot-email.component.scss | 0 .../forgot-email.component.ts | 1 + .../themed-forgot-email.component.ts | 2 +- .../forgot-password-form.component.scss | 0 .../forgot-password-form.component.ts | 1 + .../themed-forgot-password-form.component.ts | 2 +- .../profile-page/profile-page.component.scss | 0 .../profile-page/profile-page.component.ts | 1 + .../create-profile.component.scss | 0 .../create-profile.component.ts | 1 + .../themed-create-profile.component.ts | 2 +- .../register-email.component.scss | 0 .../register-email.component.ts | 1 + .../edit/themed-submission-edit.component.ts | 25 ++++++++ ...ed-submission-import-external.component.ts | 25 ++++++++ src/app/submission/submission.module.ts | 61 ++++++++++--------- .../themed-submission-submit.component.ts | 25 ++++++++ src/environments/environment.common.ts | 8 +-- .../full/full-item-page.component.html | 0 .../full/full-item-page.component.scss | 0 .../full/full-item-page.component.ts | 20 ++++++ .../simple/item-page.component.html | 0 .../simple/item-page.component.scss | 0 .../+item-page/simple/item-page.component.ts | 21 +++++++ .../app/+login-page/login-page.component.html | 10 +++ .../app/+login-page/login-page.component.scss | 4 ++ .../app/+login-page/login-page.component.ts | 15 +++++ .../+logout-page/logout-page.component.html | 9 +++ .../+logout-page/logout-page.component.scss | 1 + .../app/+logout-page/logout-page.component.ts | 12 ++++ .../my-dspace-page.component.html | 0 .../my-dspace-page.component.scss | 0 .../my-dspace-page.component.ts | 25 ++++++++ .../workflow-item-delete.component.html | 0 .../workflow-item-delete.component.scss | 0 .../workflow-item-delete.component.ts | 14 +++++ .../workflow-item-send-back.component.html | 0 .../workflow-item-send-back.component.scss | 0 .../workflow-item-send-back.component.ts | 14 +++++ .../forgot-email.component.html | 0 .../forgot-email.component.scss | 0 .../forgot-email.component.ts | 15 +++++ .../forgot-password-form.component.html | 0 .../forgot-password-form.component.scss | 0 .../forgot-password-form.component.ts | 15 +++++ .../profile-page/profile-page.component.html | 0 .../profile-page/profile-page.component.scss | 0 .../profile-page/profile-page.component.ts | 14 +++++ .../create-profile.component.html | 0 .../create-profile.component.scss | 0 .../create-profile.component.ts | 15 +++++ .../register-email.component.html | 0 .../register-email.component.scss | 0 .../register-email.component.ts | 15 +++++ .../edit/submission-edit.component.html | 0 .../edit/submission-edit.component.scss | 0 .../edit/submission-edit.component.ts | 15 +++++ .../submission-import-external.component.html | 0 .../submission-import-external.component.scss | 0 .../submission-import-external.component.ts | 18 ++++++ .../submit/submission-submit.component.html | 0 .../submit/submission-submit.component.scss | 0 .../submit/submission-submit.component.ts | 15 +++++ src/themes/custom/theme.module.ts | 52 +++++++++++++--- 75 files changed, 540 insertions(+), 73 deletions(-) create mode 100644 src/app/+my-dspace-page/themed-my-dspace-page.component.ts create mode 100644 src/app/+workflowitems-edit-page/workflow-item-delete/themed-workflow-item-delete.component.ts create mode 100644 src/app/+workflowitems-edit-page/workflow-item-send-back/themed-workflow-item-send-back.component.ts create mode 100644 src/app/forgot-password/forgot-password-email/forgot-email.component.scss create mode 100644 src/app/forgot-password/forgot-password-form/forgot-password-form.component.scss create mode 100644 src/app/profile-page/profile-page.component.scss create mode 100644 src/app/register-page/create-profile/create-profile.component.scss create mode 100644 src/app/register-page/register-email/register-email.component.scss create mode 100644 src/app/submission/edit/themed-submission-edit.component.ts create mode 100644 src/app/submission/import-external/themed-submission-import-external.component.ts create mode 100644 src/app/submission/submit/themed-submission-submit.component.ts create mode 100644 src/themes/custom/app/+item-page/full/full-item-page.component.html create mode 100644 src/themes/custom/app/+item-page/full/full-item-page.component.scss create mode 100644 src/themes/custom/app/+item-page/full/full-item-page.component.ts create mode 100644 src/themes/custom/app/+item-page/simple/item-page.component.html create mode 100644 src/themes/custom/app/+item-page/simple/item-page.component.scss create mode 100644 src/themes/custom/app/+item-page/simple/item-page.component.ts create mode 100644 src/themes/custom/app/+login-page/login-page.component.html create mode 100644 src/themes/custom/app/+login-page/login-page.component.scss create mode 100644 src/themes/custom/app/+login-page/login-page.component.ts create mode 100644 src/themes/custom/app/+logout-page/logout-page.component.html create mode 100644 src/themes/custom/app/+logout-page/logout-page.component.scss create mode 100644 src/themes/custom/app/+logout-page/logout-page.component.ts create mode 100644 src/themes/custom/app/+my-dspace-page/my-dspace-page.component.html create mode 100644 src/themes/custom/app/+my-dspace-page/my-dspace-page.component.scss create mode 100644 src/themes/custom/app/+my-dspace-page/my-dspace-page.component.ts create mode 100644 src/themes/custom/app/+workflowitems-edit-page/workflow-item-delete/workflow-item-delete.component.html create mode 100644 src/themes/custom/app/+workflowitems-edit-page/workflow-item-delete/workflow-item-delete.component.scss create mode 100644 src/themes/custom/app/+workflowitems-edit-page/workflow-item-delete/workflow-item-delete.component.ts create mode 100644 src/themes/custom/app/+workflowitems-edit-page/workflow-item-send-back/workflow-item-send-back.component.html create mode 100644 src/themes/custom/app/+workflowitems-edit-page/workflow-item-send-back/workflow-item-send-back.component.scss create mode 100644 src/themes/custom/app/+workflowitems-edit-page/workflow-item-send-back/workflow-item-send-back.component.ts create mode 100644 src/themes/custom/app/forgot-password/forgot-password-email/forgot-email.component.html create mode 100644 src/themes/custom/app/forgot-password/forgot-password-email/forgot-email.component.scss create mode 100644 src/themes/custom/app/forgot-password/forgot-password-email/forgot-email.component.ts create mode 100644 src/themes/custom/app/forgot-password/forgot-password-form/forgot-password-form.component.html create mode 100644 src/themes/custom/app/forgot-password/forgot-password-form/forgot-password-form.component.scss create mode 100644 src/themes/custom/app/forgot-password/forgot-password-form/forgot-password-form.component.ts create mode 100644 src/themes/custom/app/profile-page/profile-page.component.html create mode 100644 src/themes/custom/app/profile-page/profile-page.component.scss create mode 100644 src/themes/custom/app/profile-page/profile-page.component.ts create mode 100644 src/themes/custom/app/register-page/create-profile/create-profile.component.html create mode 100644 src/themes/custom/app/register-page/create-profile/create-profile.component.scss create mode 100644 src/themes/custom/app/register-page/create-profile/create-profile.component.ts create mode 100644 src/themes/custom/app/register-page/register-email/register-email.component.html create mode 100644 src/themes/custom/app/register-page/register-email/register-email.component.scss create mode 100644 src/themes/custom/app/register-page/register-email/register-email.component.ts create mode 100644 src/themes/custom/app/submission/edit/submission-edit.component.html create mode 100644 src/themes/custom/app/submission/edit/submission-edit.component.scss create mode 100644 src/themes/custom/app/submission/edit/submission-edit.component.ts create mode 100644 src/themes/custom/app/submission/import-external/submission-import-external.component.html create mode 100644 src/themes/custom/app/submission/import-external/submission-import-external.component.scss create mode 100644 src/themes/custom/app/submission/import-external/submission-import-external.component.ts create mode 100644 src/themes/custom/app/submission/submit/submission-submit.component.html create mode 100644 src/themes/custom/app/submission/submit/submission-submit.component.scss create mode 100644 src/themes/custom/app/submission/submit/submission-submit.component.ts diff --git a/src/app/+import-external-page/import-external-routing.module.ts b/src/app/+import-external-page/import-external-routing.module.ts index 91cdbf9877..e5c6da5b21 100644 --- a/src/app/+import-external-page/import-external-routing.module.ts +++ b/src/app/+import-external-page/import-external-routing.module.ts @@ -1,7 +1,7 @@ import { NgModule } from '@angular/core'; import { RouterModule } from '@angular/router'; import { AuthenticatedGuard } from '../core/auth/authenticated.guard'; -import { SubmissionImportExternalComponent } from '../submission/import-external/submission-import-external.component'; +import { ThemedSubmissionImportExternalComponent } from '../submission/import-external/themed-submission-import-external.component'; @NgModule({ imports: [ @@ -9,7 +9,7 @@ import { SubmissionImportExternalComponent } from '../submission/import-external { canActivate: [ AuthenticatedGuard ], path: '', - component: SubmissionImportExternalComponent, + component: ThemedSubmissionImportExternalComponent, pathMatch: 'full', data: { title: 'submission.import-external.page.title' diff --git a/src/app/+item-page/full/themed-full-item-page.component.ts b/src/app/+item-page/full/themed-full-item-page.component.ts index 3d89f489ff..c184d0a4e4 100644 --- a/src/app/+item-page/full/themed-full-item-page.component.ts +++ b/src/app/+item-page/full/themed-full-item-page.component.ts @@ -16,7 +16,7 @@ export class ThemedFullItemPageComponent extends ThemedComponent { - return import(`../../themes/${themeName}/app/+item-page/full/full-item-page.component`); + return import(`../../../themes/${themeName}/app/+item-page/full/full-item-page.component`); } protected importUnthemedComponent(): Promise { diff --git a/src/app/+my-dspace-page/my-dspace-page-routing.module.ts b/src/app/+my-dspace-page/my-dspace-page-routing.module.ts index d70a007e3a..46deb36e20 100644 --- a/src/app/+my-dspace-page/my-dspace-page-routing.module.ts +++ b/src/app/+my-dspace-page/my-dspace-page-routing.module.ts @@ -1,15 +1,14 @@ import { NgModule } from '@angular/core'; import { RouterModule } from '@angular/router'; - -import { MyDSpacePageComponent } from './my-dspace-page.component'; import { MyDSpaceGuard } from './my-dspace.guard'; +import { ThemedMyDSpacePageComponent } from './themed-my-dspace-page.component'; @NgModule({ imports: [ RouterModule.forChild([ { path: '', - component: MyDSpacePageComponent, + component: ThemedMyDSpacePageComponent, data: { title: 'mydspace.title' }, canActivate: [ MyDSpaceGuard diff --git a/src/app/+my-dspace-page/my-dspace-page.module.ts b/src/app/+my-dspace-page/my-dspace-page.module.ts index 40bbcc903c..52c80c90b0 100644 --- a/src/app/+my-dspace-page/my-dspace-page.module.ts +++ b/src/app/+my-dspace-page/my-dspace-page.module.ts @@ -11,6 +11,15 @@ import { MyDSpaceGuard } from './my-dspace.guard'; import { MyDSpaceConfigurationService } from './my-dspace-configuration.service'; import { CollectionSelectorComponent } from './collection-selector/collection-selector.component'; import { MyDspaceSearchModule } from './my-dspace-search.module'; +import { ThemedMyDSpacePageComponent } from './themed-my-dspace-page.component'; + +const DECLARATIONS = [ + MyDSpacePageComponent, + ThemedMyDSpacePageComponent, + MyDSpaceResultsComponent, + MyDSpaceNewSubmissionComponent, + CollectionSelectorComponent +]; @NgModule({ imports: [ @@ -19,16 +28,12 @@ import { MyDspaceSearchModule } from './my-dspace-search.module'; MyDspacePageRoutingModule, MyDspaceSearchModule.withEntryComponents() ], - declarations: [ - MyDSpacePageComponent, - MyDSpaceResultsComponent, - MyDSpaceNewSubmissionComponent, - CollectionSelectorComponent - ], + declarations: DECLARATIONS, providers: [ MyDSpaceGuard, MyDSpaceConfigurationService - ] + ], + exports: DECLARATIONS, }) /** diff --git a/src/app/+my-dspace-page/themed-my-dspace-page.component.ts b/src/app/+my-dspace-page/themed-my-dspace-page.component.ts new file mode 100644 index 0000000000..47275496ca --- /dev/null +++ b/src/app/+my-dspace-page/themed-my-dspace-page.component.ts @@ -0,0 +1,27 @@ +import { Component } from '@angular/core'; +import { ThemedComponent } from '../shared/theme-support/themed.component'; +import { MyDSpacePageComponent } from './my-dspace-page.component'; + +/** + * Themed wrapper for MyDSpacePageComponent + */ +@Component({ + selector: 'ds-themed-my-dspace-page', + styleUrls: [], + templateUrl: './../shared/theme-support/themed.component.html' +}) +export class ThemedMyDSpacePageComponent extends ThemedComponent { + protected inAndOutputNames: (keyof MyDSpacePageComponent & keyof this)[]; + + protected getComponentName(): string { + return 'MyDSpacePageComponent'; + } + + protected importThemedComponent(themeName: string): Promise { + return import(`../../themes/${themeName}/app/+my-dspace-page/my-dspace-page.component`); + } + + protected importUnthemedComponent(): Promise { + return import(`./my-dspace-page.component`); + } +} diff --git a/src/app/+submit-page/submit-page-routing.module.ts b/src/app/+submit-page/submit-page-routing.module.ts index 7a123bfc31..92c9bd8cdf 100644 --- a/src/app/+submit-page/submit-page-routing.module.ts +++ b/src/app/+submit-page/submit-page-routing.module.ts @@ -2,7 +2,7 @@ import { NgModule } from '@angular/core'; import { RouterModule } from '@angular/router'; import { AuthenticatedGuard } from '../core/auth/authenticated.guard'; -import { SubmissionSubmitComponent } from '../submission/submit/submission-submit.component'; +import { ThemedSubmissionSubmitComponent } from '../submission/submit/themed-submission-submit.component'; @NgModule({ imports: [ @@ -11,7 +11,7 @@ import { SubmissionSubmitComponent } from '../submission/submit/submission-submi canActivate: [AuthenticatedGuard], path: '', pathMatch: 'full', - component: SubmissionSubmitComponent, + component: ThemedSubmissionSubmitComponent, data: { title: 'submission.submit.title' } } ]) diff --git a/src/app/+workflowitems-edit-page/workflow-item-delete/themed-workflow-item-delete.component.ts b/src/app/+workflowitems-edit-page/workflow-item-delete/themed-workflow-item-delete.component.ts new file mode 100644 index 0000000000..498975075f --- /dev/null +++ b/src/app/+workflowitems-edit-page/workflow-item-delete/themed-workflow-item-delete.component.ts @@ -0,0 +1,26 @@ +import { WorkflowItemDeleteComponent } from './workflow-item-delete.component'; +import { ThemedComponent } from '../../shared/theme-support/themed.component'; +import { Component } from '@angular/core'; + +/** + * Themed wrapper for WorkflowItemDeleteComponent + */ + +@Component({ + selector: 'ds-themed-workflow-item-delete', + styleUrls: [], + templateUrl: './../../shared/theme-support/themed.component.html' +}) +export class ThemedWorkflowItemDeleteComponent extends ThemedComponent { + protected getComponentName(): string { + return 'WorkflowItemDeleteComponent'; + } + + protected importThemedComponent(themeName: string): Promise { + return import(`../../../themes/${themeName}/app/+workflowitems-edit-page/workflow-item-delete/workflow-item-delete.component`); + } + + protected importUnthemedComponent(): Promise { + return import(`./workflow-item-delete.component`); + } +} diff --git a/src/app/+workflowitems-edit-page/workflow-item-send-back/themed-workflow-item-send-back.component.ts b/src/app/+workflowitems-edit-page/workflow-item-send-back/themed-workflow-item-send-back.component.ts new file mode 100644 index 0000000000..a2cc68ac74 --- /dev/null +++ b/src/app/+workflowitems-edit-page/workflow-item-send-back/themed-workflow-item-send-back.component.ts @@ -0,0 +1,26 @@ +import { ThemedComponent } from '../../shared/theme-support/themed.component'; +import { Component } from '@angular/core'; +import { WorkflowItemSendBackComponent } from './workflow-item-send-back.component'; + +/** + * Themed wrapper for WorkflowItemActionPageComponent + */ + +@Component({ + selector: 'ds-themed-workflow-item-send-back', + styleUrls: [], + templateUrl: './../../shared/theme-support/themed.component.html' +}) +export class ThemedWorkflowItemSendBackComponent extends ThemedComponent { + protected getComponentName(): string { + return 'WorkflowItemSendBackComponent'; + } + + protected importThemedComponent(themeName: string): Promise { + return import(`../../../themes/${themeName}/app/+workflowitems-edit-page/workflow-item-send-back/workflow-item-send-back.component`); + } + + protected importUnthemedComponent(): Promise { + return import(`./workflow-item-send-back.component`); + } +} diff --git a/src/app/+workflowitems-edit-page/workflowitems-edit-page-routing.module.ts b/src/app/+workflowitems-edit-page/workflowitems-edit-page-routing.module.ts index 27b7fe1199..2d104cf376 100644 --- a/src/app/+workflowitems-edit-page/workflowitems-edit-page-routing.module.ts +++ b/src/app/+workflowitems-edit-page/workflowitems-edit-page-routing.module.ts @@ -2,15 +2,11 @@ import { NgModule } from '@angular/core'; import { RouterModule } from '@angular/router'; import { AuthenticatedGuard } from '../core/auth/authenticated.guard'; -import { SubmissionEditComponent } from '../submission/edit/submission-edit.component'; -import { WorkflowItemDeleteComponent } from './workflow-item-delete/workflow-item-delete.component'; import { WorkflowItemPageResolver } from './workflow-item-page.resolver'; -import { WorkflowItemSendBackComponent } from './workflow-item-send-back/workflow-item-send-back.component'; -import { - WORKFLOW_ITEM_SEND_BACK_PATH, - WORKFLOW_ITEM_DELETE_PATH, - WORKFLOW_ITEM_EDIT_PATH -} from './workflowitems-edit-page-routing-paths'; +import { WORKFLOW_ITEM_DELETE_PATH, WORKFLOW_ITEM_EDIT_PATH, WORKFLOW_ITEM_SEND_BACK_PATH } from './workflowitems-edit-page-routing-paths'; +import { ThemedSubmissionEditComponent } from '../submission/edit/themed-submission-edit.component'; +import { ThemedWorkflowItemDeleteComponent } from './workflow-item-delete/themed-workflow-item-delete.component'; +import { ThemedWorkflowItemSendBackComponent } from './workflow-item-send-back/themed-workflow-item-send-back.component'; @NgModule({ imports: [ @@ -22,19 +18,19 @@ import { { canActivate: [AuthenticatedGuard], path: WORKFLOW_ITEM_EDIT_PATH, - component: SubmissionEditComponent, + component: ThemedSubmissionEditComponent, data: { title: 'submission.edit.title' } }, { canActivate: [AuthenticatedGuard], path: WORKFLOW_ITEM_DELETE_PATH, - component: WorkflowItemDeleteComponent, + component: ThemedWorkflowItemDeleteComponent, data: { title: 'workflow-item.delete.title' } }, { canActivate: [AuthenticatedGuard], path: WORKFLOW_ITEM_SEND_BACK_PATH, - component: WorkflowItemSendBackComponent, + component: ThemedWorkflowItemSendBackComponent, data: { title: 'workflow-item.send-back.title' } } ] diff --git a/src/app/+workflowitems-edit-page/workflowitems-edit-page.module.ts b/src/app/+workflowitems-edit-page/workflowitems-edit-page.module.ts index ef1e49abf5..6e4b3212e8 100644 --- a/src/app/+workflowitems-edit-page/workflowitems-edit-page.module.ts +++ b/src/app/+workflowitems-edit-page/workflowitems-edit-page.module.ts @@ -5,6 +5,8 @@ import { WorkflowItemsEditPageRoutingModule } from './workflowitems-edit-page-ro import { SubmissionModule } from '../submission/submission.module'; import { WorkflowItemDeleteComponent } from './workflow-item-delete/workflow-item-delete.component'; import { WorkflowItemSendBackComponent } from './workflow-item-send-back/workflow-item-send-back.component'; +import { ThemedWorkflowItemDeleteComponent } from './workflow-item-delete/themed-workflow-item-delete.component'; +import { ThemedWorkflowItemSendBackComponent } from './workflow-item-send-back/themed-workflow-item-send-back.component'; @NgModule({ imports: [ @@ -13,7 +15,7 @@ import { WorkflowItemSendBackComponent } from './workflow-item-send-back/workflo SharedModule, SubmissionModule, ], - declarations: [WorkflowItemDeleteComponent, WorkflowItemSendBackComponent] + declarations: [WorkflowItemDeleteComponent, ThemedWorkflowItemDeleteComponent, WorkflowItemSendBackComponent, ThemedWorkflowItemSendBackComponent] }) /** * This module handles all modules that need to access the workflowitems edit page. diff --git a/src/app/+workspaceitems-edit-page/workspaceitems-edit-page-routing.module.ts b/src/app/+workspaceitems-edit-page/workspaceitems-edit-page-routing.module.ts index d10c53e138..791bb4f9aa 100644 --- a/src/app/+workspaceitems-edit-page/workspaceitems-edit-page-routing.module.ts +++ b/src/app/+workspaceitems-edit-page/workspaceitems-edit-page-routing.module.ts @@ -2,7 +2,7 @@ import { NgModule } from '@angular/core'; import { RouterModule } from '@angular/router'; import { AuthenticatedGuard } from '../core/auth/authenticated.guard'; -import { SubmissionEditComponent } from '../submission/edit/submission-edit.component'; +import { ThemedSubmissionEditComponent } from '../submission/edit/themed-submission-edit.component'; @NgModule({ imports: [ @@ -11,7 +11,7 @@ import { SubmissionEditComponent } from '../submission/edit/submission-edit.comp { canActivate: [AuthenticatedGuard], path: ':id/edit', - component: SubmissionEditComponent, + component: ThemedSubmissionEditComponent, data: { title: 'submission.edit.title' } } ]) diff --git a/src/app/forgot-password/forgot-password-email/forgot-email.component.scss b/src/app/forgot-password/forgot-password-email/forgot-email.component.scss new file mode 100644 index 0000000000..e69de29bb2 diff --git a/src/app/forgot-password/forgot-password-email/forgot-email.component.ts b/src/app/forgot-password/forgot-password-email/forgot-email.component.ts index 5e18aff113..af482bdb67 100644 --- a/src/app/forgot-password/forgot-password-email/forgot-email.component.ts +++ b/src/app/forgot-password/forgot-password-email/forgot-email.component.ts @@ -2,6 +2,7 @@ import { Component } from '@angular/core'; @Component({ selector: 'ds-forgot-email', + styleUrls: ['./forgot-email.component.scss'], templateUrl: './forgot-email.component.html' }) /** diff --git a/src/app/forgot-password/forgot-password-email/themed-forgot-email.component.ts b/src/app/forgot-password/forgot-password-email/themed-forgot-email.component.ts index 68fcf9302f..da3848db1d 100644 --- a/src/app/forgot-password/forgot-password-email/themed-forgot-email.component.ts +++ b/src/app/forgot-password/forgot-password-email/themed-forgot-email.component.ts @@ -16,7 +16,7 @@ export class ThemedForgotEmailComponent extends ThemedComponent { - return import(`../../themes/${themeName}/app/forgot-password/forgot-password-email/forgot-email.component`); + return import(`../../../themes/${themeName}/app/forgot-password/forgot-password-email/forgot-email.component`); } protected importUnthemedComponent(): Promise { diff --git a/src/app/forgot-password/forgot-password-form/forgot-password-form.component.scss b/src/app/forgot-password/forgot-password-form/forgot-password-form.component.scss new file mode 100644 index 0000000000..e69de29bb2 diff --git a/src/app/forgot-password/forgot-password-form/forgot-password-form.component.ts b/src/app/forgot-password/forgot-password-form/forgot-password-form.component.ts index 8bfed0b2eb..98188a07e8 100644 --- a/src/app/forgot-password/forgot-password-form/forgot-password-form.component.ts +++ b/src/app/forgot-password/forgot-password-form/forgot-password-form.component.ts @@ -14,6 +14,7 @@ import { EPerson } from '../../core/eperson/models/eperson.model'; @Component({ selector: 'ds-forgot-password-form', + styleUrls: ['./forgot-password-form.component.scss'], templateUrl: './forgot-password-form.component.html' }) /** diff --git a/src/app/forgot-password/forgot-password-form/themed-forgot-password-form.component.ts b/src/app/forgot-password/forgot-password-form/themed-forgot-password-form.component.ts index 523f81312a..3fb1b67e01 100644 --- a/src/app/forgot-password/forgot-password-form/themed-forgot-password-form.component.ts +++ b/src/app/forgot-password/forgot-password-form/themed-forgot-password-form.component.ts @@ -16,7 +16,7 @@ export class ThemedForgotPasswordFormComponent extends ThemedComponent { - return import(`../../themes/${themeName}/app/forgot-password/forgot-password-form/forgot-password-form.component`); + return import(`../../../themes/${themeName}/app/forgot-password/forgot-password-form/forgot-password-form.component`); } protected importUnthemedComponent(): Promise { diff --git a/src/app/profile-page/profile-page.component.scss b/src/app/profile-page/profile-page.component.scss new file mode 100644 index 0000000000..e69de29bb2 diff --git a/src/app/profile-page/profile-page.component.ts b/src/app/profile-page/profile-page.component.ts index 5b7697ed48..e9c4dec832 100644 --- a/src/app/profile-page/profile-page.component.ts +++ b/src/app/profile-page/profile-page.component.ts @@ -21,6 +21,7 @@ import { Operation } from 'fast-json-patch'; @Component({ selector: 'ds-profile-page', + styleUrls: ['./profile-page.component.scss'], templateUrl: './profile-page.component.html' }) /** diff --git a/src/app/register-page/create-profile/create-profile.component.scss b/src/app/register-page/create-profile/create-profile.component.scss new file mode 100644 index 0000000000..e69de29bb2 diff --git a/src/app/register-page/create-profile/create-profile.component.ts b/src/app/register-page/create-profile/create-profile.component.ts index 5f02556248..790e1d6fc5 100644 --- a/src/app/register-page/create-profile/create-profile.component.ts +++ b/src/app/register-page/create-profile/create-profile.component.ts @@ -26,6 +26,7 @@ import { getFirstCompletedRemoteData } from '../../core/shared/operators'; */ @Component({ selector: 'ds-create-profile', + styleUrls: ['./create-profile.component.scss'], templateUrl: './create-profile.component.html' }) export class CreateProfileComponent implements OnInit { diff --git a/src/app/register-page/create-profile/themed-create-profile.component.ts b/src/app/register-page/create-profile/themed-create-profile.component.ts index 3cbc4ad553..cc968bfbe2 100644 --- a/src/app/register-page/create-profile/themed-create-profile.component.ts +++ b/src/app/register-page/create-profile/themed-create-profile.component.ts @@ -16,7 +16,7 @@ export class ThemedCreateProfileComponent extends ThemedComponent { - return import(`../../themes/${themeName}/app/register-page/create-profile/create-profile.component`); + return import(`../../../themes/${themeName}/app/register-page/create-profile/create-profile.component`); } protected importUnthemedComponent(): Promise { diff --git a/src/app/register-page/register-email/register-email.component.scss b/src/app/register-page/register-email/register-email.component.scss new file mode 100644 index 0000000000..e69de29bb2 diff --git a/src/app/register-page/register-email/register-email.component.ts b/src/app/register-page/register-email/register-email.component.ts index ac221c109a..7b7b0f631b 100644 --- a/src/app/register-page/register-email/register-email.component.ts +++ b/src/app/register-page/register-email/register-email.component.ts @@ -2,6 +2,7 @@ import { Component } from '@angular/core'; @Component({ selector: 'ds-register-email', + styleUrls: ['./register-email.component.scss'], templateUrl: './register-email.component.html' }) /** diff --git a/src/app/submission/edit/themed-submission-edit.component.ts b/src/app/submission/edit/themed-submission-edit.component.ts new file mode 100644 index 0000000000..bbaf432c13 --- /dev/null +++ b/src/app/submission/edit/themed-submission-edit.component.ts @@ -0,0 +1,25 @@ +/** + * Themed wrapper for SubmissionEditComponent + */ +import { Component } from '@angular/core'; +import { ThemedComponent } from '../../shared/theme-support/themed.component'; +import { SubmissionEditComponent } from './submission-edit.component'; + +@Component({ + selector: 'ds-themed-submission-edit', + styleUrls: [], + templateUrl: './../../shared/theme-support/themed.component.html' +}) +export class ThemedSubmissionEditComponent extends ThemedComponent { + protected getComponentName(): string { + return 'SubmissionEditComponent'; + } + + protected importThemedComponent(themeName: string): Promise { + return import(`../../../themes/${themeName}/app/submission/edit/submission-edit.component`); + } + + protected importUnthemedComponent(): Promise { + return import(`./submission-edit.component`); + } +} diff --git a/src/app/submission/import-external/themed-submission-import-external.component.ts b/src/app/submission/import-external/themed-submission-import-external.component.ts new file mode 100644 index 0000000000..698a64842d --- /dev/null +++ b/src/app/submission/import-external/themed-submission-import-external.component.ts @@ -0,0 +1,25 @@ +import { Component } from '@angular/core'; +import { ThemedComponent } from '../../shared/theme-support/themed.component'; +import { SubmissionImportExternalComponent } from './submission-import-external.component'; + +/** + * Themed wrapper for SubmissionImportExternalComponent + */ +@Component({ + selector: 'ds-themed-submission-import-external', + styleUrls: [], + templateUrl: './../../shared/theme-support/themed.component.html' +}) +export class ThemedSubmissionImportExternalComponent extends ThemedComponent { + protected getComponentName(): string { + return 'SubmissionImportExternalComponent'; + } + + protected importThemedComponent(themeName: string): Promise { + return import(`../../../themes/${themeName}/app/submission/import-external/submission-import-external.component`); + } + + protected importUnthemedComponent(): Promise { + return import(`./submission-import-external.component`); + } +} diff --git a/src/app/submission/submission.module.ts b/src/app/submission/submission.module.ts index 32c11d6673..13cf2016dd 100644 --- a/src/app/submission/submission.module.ts +++ b/src/app/submission/submission.module.ts @@ -34,6 +34,36 @@ import { SubmissionImportExternalCollectionComponent } from './import-external/i import { SubmissionSectionCcLicensesComponent } from './sections/cc-license/submission-section-cc-licenses.component'; import { JournalEntitiesModule } from '../entity-groups/journal-entities/journal-entities.module'; import { ResearchEntitiesModule } from '../entity-groups/research-entities/research-entities.module'; +import { ThemedSubmissionEditComponent } from './edit/themed-submission-edit.component'; +import { ThemedSubmissionSubmitComponent } from './submit/themed-submission-submit.component'; +import { ThemedSubmissionImportExternalComponent } from './import-external/themed-submission-import-external.component'; + +const DECLARATIONS = [ + SubmissionSectionUploadAccessConditionsComponent, + SubmissionSectionUploadComponent, + SubmissionSectionformComponent, + SubmissionSectionLicenseComponent, + SubmissionSectionCcLicensesComponent, + SectionsDirective, + SubmissionEditComponent, + ThemedSubmissionEditComponent, + SubmissionFormSectionAddComponent, + SubmissionFormCollectionComponent, + SubmissionFormComponent, + SubmissionFormFooterComponent, + SubmissionSubmitComponent, + ThemedSubmissionSubmitComponent, + SubmissionUploadFilesComponent, + SubmissionSectionContainerComponent, + SubmissionSectionUploadFileComponent, + SubmissionSectionUploadFileEditComponent, + SubmissionSectionUploadFileViewComponent, + SubmissionImportExternalComponent, + ThemedSubmissionImportExternalComponent, + SubmissionImportExternalSearchbarComponent, + SubmissionImportExternalPreviewComponent, + SubmissionImportExternalCollectionComponent +]; @NgModule({ imports: [ @@ -45,35 +75,8 @@ import { ResearchEntitiesModule } from '../entity-groups/research-entities/resea JournalEntitiesModule.withEntryComponents(), ResearchEntitiesModule.withEntryComponents(), ], - declarations: [ - SubmissionSectionUploadAccessConditionsComponent, - SubmissionSectionUploadComponent, - SubmissionSectionformComponent, - SubmissionSectionLicenseComponent, - SubmissionSectionCcLicensesComponent, - SectionsDirective, - SubmissionEditComponent, - SubmissionFormSectionAddComponent, - SubmissionFormCollectionComponent, - SubmissionFormComponent, - SubmissionFormFooterComponent, - SubmissionSubmitComponent, - SubmissionUploadFilesComponent, - SubmissionSectionContainerComponent, - SubmissionSectionUploadFileComponent, - SubmissionSectionUploadFileEditComponent, - SubmissionSectionUploadFileViewComponent, - SubmissionImportExternalComponent, - SubmissionImportExternalSearchbarComponent, - SubmissionImportExternalPreviewComponent, - SubmissionImportExternalCollectionComponent - ], - exports: [ - SubmissionEditComponent, - SubmissionFormComponent, - SubmissionSubmitComponent, - SubmissionImportExternalComponent - ], + declarations: DECLARATIONS, + exports: DECLARATIONS, providers: [ SectionUploadService, SectionsService, diff --git a/src/app/submission/submit/themed-submission-submit.component.ts b/src/app/submission/submit/themed-submission-submit.component.ts new file mode 100644 index 0000000000..ad313bf7bb --- /dev/null +++ b/src/app/submission/submit/themed-submission-submit.component.ts @@ -0,0 +1,25 @@ +import { Component } from '@angular/core'; +import { ThemedComponent } from '../../shared/theme-support/themed.component'; +import { SubmissionSubmitComponent } from './submission-submit.component'; + +/** + * Themed wrapper for SubmissionSubmitComponent + */ +@Component({ + selector: 'ds-themed-submission-submit', + styleUrls: [], + templateUrl: './../../shared/theme-support/themed.component.html' +}) +export class ThemedSubmissionSubmitComponent extends ThemedComponent { + protected getComponentName(): string { + return 'SubmissionImportExternalComponent'; + } + + protected importThemedComponent(themeName: string): Promise { + return import(`../../../themes/${themeName}/app/submission/submit/submission-submit.component`); + } + + protected importUnthemedComponent(): Promise { + return import(`./submission-submit.component`); + } +} diff --git a/src/environments/environment.common.ts b/src/environments/environment.common.ts index bc1f634e19..c6ae9858e5 100644 --- a/src/environments/environment.common.ts +++ b/src/environments/environment.common.ts @@ -251,10 +251,10 @@ export const environment: GlobalConfig = { // name: 'custom', // uuid: '0958c910-2037-42a9-81c7-dca80e3892b4' // }, - { - // A theme with only a name will match every route - name: 'custom' - }, + // { + // // A theme with only a name will match every route + // name: 'custom' + // }, { // This theme will use the default bootstrap styling for DSpace components diff --git a/src/themes/custom/app/+item-page/full/full-item-page.component.html b/src/themes/custom/app/+item-page/full/full-item-page.component.html new file mode 100644 index 0000000000..e69de29bb2 diff --git a/src/themes/custom/app/+item-page/full/full-item-page.component.scss b/src/themes/custom/app/+item-page/full/full-item-page.component.scss new file mode 100644 index 0000000000..e69de29bb2 diff --git a/src/themes/custom/app/+item-page/full/full-item-page.component.ts b/src/themes/custom/app/+item-page/full/full-item-page.component.ts new file mode 100644 index 0000000000..1e6230132b --- /dev/null +++ b/src/themes/custom/app/+item-page/full/full-item-page.component.ts @@ -0,0 +1,20 @@ +import { ChangeDetectionStrategy, Component } from '@angular/core'; +import { fadeInOut } from '../../../../../app/shared/animations/fade'; +import { FullItemPageComponent as BaseComponent } from '../../../../../app/+item-page/full/full-item-page.component'; + +/** + * This component renders a full item page. + * The route parameter 'id' is used to request the item it represents. + */ + +@Component({ + selector: 'ds-full-item-page', + // styleUrls: ['./full-item-page.component.scss'], + styleUrls: ['../../../../../app/+item-page/full/full-item-page.component.scss'], + // templateUrl: './full-item-page.component.html', + templateUrl: '../../../../../app/+item-page/full/full-item-page.component.html', + changeDetection: ChangeDetectionStrategy.OnPush, + animations: [fadeInOut] +}) +export class FullItemPageComponent extends BaseComponent { +} diff --git a/src/themes/custom/app/+item-page/simple/item-page.component.html b/src/themes/custom/app/+item-page/simple/item-page.component.html new file mode 100644 index 0000000000..e69de29bb2 diff --git a/src/themes/custom/app/+item-page/simple/item-page.component.scss b/src/themes/custom/app/+item-page/simple/item-page.component.scss new file mode 100644 index 0000000000..e69de29bb2 diff --git a/src/themes/custom/app/+item-page/simple/item-page.component.ts b/src/themes/custom/app/+item-page/simple/item-page.component.ts new file mode 100644 index 0000000000..1ba534972e --- /dev/null +++ b/src/themes/custom/app/+item-page/simple/item-page.component.ts @@ -0,0 +1,21 @@ +import { ChangeDetectionStrategy, Component } from '@angular/core'; +import { ItemPageComponent as BaseComponent } from '../../../../../app/+item-page/simple/item-page.component'; +import { fadeInOut } from '../../../../../app/shared/animations/fade'; + +/** + * This component renders a simple item page. + * The route parameter 'id' is used to request the item it represents. + * All fields of the item that should be displayed, are defined in its template. + */ +@Component({ + selector: 'ds-item-page', + // styleUrls: ['../item-page.component.scss'], + styleUrls: ['../../../../../app/+item-page/simple/item-page.component.scss'], + // templateUrl: './item-page.component.html', + templateUrl: '../../../../../app/+item-page/simple/item-page.component.html', + changeDetection: ChangeDetectionStrategy.OnPush, + animations: [fadeInOut] +}) +export class ItemPageComponent extends BaseComponent { + +} diff --git a/src/themes/custom/app/+login-page/login-page.component.html b/src/themes/custom/app/+login-page/login-page.component.html new file mode 100644 index 0000000000..84059877f4 --- /dev/null +++ b/src/themes/custom/app/+login-page/login-page.component.html @@ -0,0 +1,10 @@ +
+
+
+ +

{{"login.form.header" | translate}}

+ +
+
+
diff --git a/src/themes/custom/app/+login-page/login-page.component.scss b/src/themes/custom/app/+login-page/login-page.component.scss new file mode 100644 index 0000000000..d628a5089f --- /dev/null +++ b/src/themes/custom/app/+login-page/login-page.component.scss @@ -0,0 +1,4 @@ +.login-logo { + height: var(--ds-login-logo-height); + width: var(--ds-login-logo-width); +} diff --git a/src/themes/custom/app/+login-page/login-page.component.ts b/src/themes/custom/app/+login-page/login-page.component.ts new file mode 100644 index 0000000000..4c5922c8fd --- /dev/null +++ b/src/themes/custom/app/+login-page/login-page.component.ts @@ -0,0 +1,15 @@ +import { Component } from '@angular/core'; +import { LoginPageComponent as BaseComponent } from '../../../../app/+login-page/login-page.component'; + +/** + * This component represents the login page + */ +@Component({ + selector: 'ds-login-page', + // styleUrls: ['./login-page.component.scss'], + styleUrls: ['../../../../app/+login-page/login-page.component.scss'], + // templateUrl: './login-page.component.html' + templateUrl: '../../../../app/+login-page/login-page.component.html' +}) +export class LoginPageComponent extends BaseComponent { +} diff --git a/src/themes/custom/app/+logout-page/logout-page.component.html b/src/themes/custom/app/+logout-page/logout-page.component.html new file mode 100644 index 0000000000..b5012ed53b --- /dev/null +++ b/src/themes/custom/app/+logout-page/logout-page.component.html @@ -0,0 +1,9 @@ +
+
+
+ +

{{"logout.form.header" | translate}}

+ +
+
+
diff --git a/src/themes/custom/app/+logout-page/logout-page.component.scss b/src/themes/custom/app/+logout-page/logout-page.component.scss new file mode 100644 index 0000000000..7e594c0d9b --- /dev/null +++ b/src/themes/custom/app/+logout-page/logout-page.component.scss @@ -0,0 +1 @@ +@import '../+login-page/login-page.component.scss'; diff --git a/src/themes/custom/app/+logout-page/logout-page.component.ts b/src/themes/custom/app/+logout-page/logout-page.component.ts new file mode 100644 index 0000000000..5b94d906c0 --- /dev/null +++ b/src/themes/custom/app/+logout-page/logout-page.component.ts @@ -0,0 +1,12 @@ +import { Component } from '@angular/core'; +import { LogoutPageComponent as BaseComponent} from '../../../../app/+logout-page/logout-page.component'; + +@Component({ + selector: 'ds-logout-page', + // styleUrls: ['./logout-page.component.scss'], + styleUrls: ['../../../../app/+logout-page/logout-page.component.scss'], + // templateUrl: './logout-page.component.html' + templateUrl: '../../../../app/+logout-page/logout-page.component.html' +}) +export class LogoutPageComponent extends BaseComponent { +} diff --git a/src/themes/custom/app/+my-dspace-page/my-dspace-page.component.html b/src/themes/custom/app/+my-dspace-page/my-dspace-page.component.html new file mode 100644 index 0000000000..e69de29bb2 diff --git a/src/themes/custom/app/+my-dspace-page/my-dspace-page.component.scss b/src/themes/custom/app/+my-dspace-page/my-dspace-page.component.scss new file mode 100644 index 0000000000..e69de29bb2 diff --git a/src/themes/custom/app/+my-dspace-page/my-dspace-page.component.ts b/src/themes/custom/app/+my-dspace-page/my-dspace-page.component.ts new file mode 100644 index 0000000000..8ea24a041d --- /dev/null +++ b/src/themes/custom/app/+my-dspace-page/my-dspace-page.component.ts @@ -0,0 +1,25 @@ +import { ChangeDetectionStrategy, Component } from '@angular/core'; +import { pushInOut } from '../../../../app/shared/animations/push'; +import { MyDSpacePageComponent as BaseComponent, SEARCH_CONFIG_SERVICE } from '../../../../app/+my-dspace-page/my-dspace-page.component'; +import { MyDSpaceConfigurationService } from '../../../../app/+my-dspace-page/my-dspace-configuration.service'; + +/** + * This component represents the whole mydspace page + */ +@Component({ + selector: 'ds-my-dspace-page', + // styleUrls: ['./my-dspace-page.component.scss'], + styleUrls: ['../../../../app/+my-dspace-page/my-dspace-page.component.scss'], + // templateUrl: './my-dspace-page.component.html', + templateUrl: '../../../../app/+my-dspace-page/my-dspace-page.component.html', + changeDetection: ChangeDetectionStrategy.OnPush, + animations: [pushInOut], + providers: [ + { + provide: SEARCH_CONFIG_SERVICE, + useClass: MyDSpaceConfigurationService + } + ] +}) +export class MyDSpacePageComponent extends BaseComponent { +} diff --git a/src/themes/custom/app/+workflowitems-edit-page/workflow-item-delete/workflow-item-delete.component.html b/src/themes/custom/app/+workflowitems-edit-page/workflow-item-delete/workflow-item-delete.component.html new file mode 100644 index 0000000000..e69de29bb2 diff --git a/src/themes/custom/app/+workflowitems-edit-page/workflow-item-delete/workflow-item-delete.component.scss b/src/themes/custom/app/+workflowitems-edit-page/workflow-item-delete/workflow-item-delete.component.scss new file mode 100644 index 0000000000..e69de29bb2 diff --git a/src/themes/custom/app/+workflowitems-edit-page/workflow-item-delete/workflow-item-delete.component.ts b/src/themes/custom/app/+workflowitems-edit-page/workflow-item-delete/workflow-item-delete.component.ts new file mode 100644 index 0000000000..c9c140835a --- /dev/null +++ b/src/themes/custom/app/+workflowitems-edit-page/workflow-item-delete/workflow-item-delete.component.ts @@ -0,0 +1,14 @@ +import { Component } from '@angular/core'; +import { WorkflowItemDeleteComponent as BaseComponent } from '../../../../../app/+workflowitems-edit-page/workflow-item-delete/workflow-item-delete.component'; + +@Component({ + selector: 'ds-workflow-item-delete', + // styleUrls: ['workflow-item-delete.component.scss'], + // templateUrl: './workflow-item-delete.component.html' + templateUrl: '../../../../../app/+workflowitems-edit-page/workflow-item-action-page.component.html' +}) +/** + * Component representing a page to delete a workflow item + */ +export class WorkflowItemDeleteComponent extends BaseComponent { +} diff --git a/src/themes/custom/app/+workflowitems-edit-page/workflow-item-send-back/workflow-item-send-back.component.html b/src/themes/custom/app/+workflowitems-edit-page/workflow-item-send-back/workflow-item-send-back.component.html new file mode 100644 index 0000000000..e69de29bb2 diff --git a/src/themes/custom/app/+workflowitems-edit-page/workflow-item-send-back/workflow-item-send-back.component.scss b/src/themes/custom/app/+workflowitems-edit-page/workflow-item-send-back/workflow-item-send-back.component.scss new file mode 100644 index 0000000000..e69de29bb2 diff --git a/src/themes/custom/app/+workflowitems-edit-page/workflow-item-send-back/workflow-item-send-back.component.ts b/src/themes/custom/app/+workflowitems-edit-page/workflow-item-send-back/workflow-item-send-back.component.ts new file mode 100644 index 0000000000..343faf765c --- /dev/null +++ b/src/themes/custom/app/+workflowitems-edit-page/workflow-item-send-back/workflow-item-send-back.component.ts @@ -0,0 +1,14 @@ +import { Component } from '@angular/core'; +import { WorkflowItemSendBackComponent as BaseComponent } from '../../../../../app/+workflowitems-edit-page/workflow-item-send-back/workflow-item-send-back.component'; + +@Component({ + selector: 'ds-workflow-item-send-back', + // styleUrls: ['workflow-item-send-back.component.scss'], + // templateUrl: './workflow-item-send-back.component.html' + templateUrl: '../../../../../app/+workflowitems-edit-page/workflow-item-action-page.component.html' +}) +/** + * Component representing a page to send back a workflow item to the submitter + */ +export class WorkflowItemSendBackComponent extends BaseComponent { +} diff --git a/src/themes/custom/app/forgot-password/forgot-password-email/forgot-email.component.html b/src/themes/custom/app/forgot-password/forgot-password-email/forgot-email.component.html new file mode 100644 index 0000000000..e69de29bb2 diff --git a/src/themes/custom/app/forgot-password/forgot-password-email/forgot-email.component.scss b/src/themes/custom/app/forgot-password/forgot-password-email/forgot-email.component.scss new file mode 100644 index 0000000000..e69de29bb2 diff --git a/src/themes/custom/app/forgot-password/forgot-password-email/forgot-email.component.ts b/src/themes/custom/app/forgot-password/forgot-password-email/forgot-email.component.ts new file mode 100644 index 0000000000..8eaa2bb0fa --- /dev/null +++ b/src/themes/custom/app/forgot-password/forgot-password-email/forgot-email.component.ts @@ -0,0 +1,15 @@ +import { Component } from '@angular/core'; +import { ForgotEmailComponent as BaseComponent } from '../../../../../app/forgot-password/forgot-password-email/forgot-email.component'; + +@Component({ + selector: 'ds-forgot-email', + // styleUrls: ['./forgot-email.component.scss'], + styleUrls: ['../../../../../app/forgot-password/forgot-password-email/forgot-email.component.scss'], + // templateUrl: './forgot-email.component.html' + templateUrl: '../../../../../app/forgot-password/forgot-password-email/forgot-email.component.html' +}) +/** + * Component responsible the forgot password email step + */ +export class ForgotEmailComponent extends BaseComponent { +} diff --git a/src/themes/custom/app/forgot-password/forgot-password-form/forgot-password-form.component.html b/src/themes/custom/app/forgot-password/forgot-password-form/forgot-password-form.component.html new file mode 100644 index 0000000000..e69de29bb2 diff --git a/src/themes/custom/app/forgot-password/forgot-password-form/forgot-password-form.component.scss b/src/themes/custom/app/forgot-password/forgot-password-form/forgot-password-form.component.scss new file mode 100644 index 0000000000..e69de29bb2 diff --git a/src/themes/custom/app/forgot-password/forgot-password-form/forgot-password-form.component.ts b/src/themes/custom/app/forgot-password/forgot-password-form/forgot-password-form.component.ts new file mode 100644 index 0000000000..d64d925f71 --- /dev/null +++ b/src/themes/custom/app/forgot-password/forgot-password-form/forgot-password-form.component.ts @@ -0,0 +1,15 @@ +import { Component } from '@angular/core'; +import { ForgotPasswordFormComponent as BaseComponent } from '../../../../../app/forgot-password/forgot-password-form/forgot-password-form.component'; + +@Component({ + selector: 'ds-forgot-password-form', + // styleUrls: ['./forgot-password-form.component.scss'], + styleUrls: ['../../../../../app/forgot-password/forgot-password-form/forgot-password-form.component.scss'], + // templateUrl: './forgot-password-form.component.html' + templateUrl: '../../../../../app/forgot-password/forgot-password-form/forgot-password-form.component.html' +}) +/** + * Component for a user to enter a new password for a forgot token. + */ +export class ForgotPasswordFormComponent extends BaseComponent { +} diff --git a/src/themes/custom/app/profile-page/profile-page.component.html b/src/themes/custom/app/profile-page/profile-page.component.html new file mode 100644 index 0000000000..e69de29bb2 diff --git a/src/themes/custom/app/profile-page/profile-page.component.scss b/src/themes/custom/app/profile-page/profile-page.component.scss new file mode 100644 index 0000000000..e69de29bb2 diff --git a/src/themes/custom/app/profile-page/profile-page.component.ts b/src/themes/custom/app/profile-page/profile-page.component.ts new file mode 100644 index 0000000000..fe25f0685b --- /dev/null +++ b/src/themes/custom/app/profile-page/profile-page.component.ts @@ -0,0 +1,14 @@ +import { Component } from '@angular/core'; +import { ProfilePageComponent as BaseComponent } from '../../../../app/profile-page/profile-page.component'; + +@Component({ + selector: 'ds-profile-page', + styleUrls: ['./profile-page.component.scss'], + templateUrl: './profile-page.component.html' +}) +/** + * Component for a user to edit their profile information + */ +export class ProfilePageComponent extends BaseComponent { + +} diff --git a/src/themes/custom/app/register-page/create-profile/create-profile.component.html b/src/themes/custom/app/register-page/create-profile/create-profile.component.html new file mode 100644 index 0000000000..e69de29bb2 diff --git a/src/themes/custom/app/register-page/create-profile/create-profile.component.scss b/src/themes/custom/app/register-page/create-profile/create-profile.component.scss new file mode 100644 index 0000000000..e69de29bb2 diff --git a/src/themes/custom/app/register-page/create-profile/create-profile.component.ts b/src/themes/custom/app/register-page/create-profile/create-profile.component.ts new file mode 100644 index 0000000000..0cffa3288d --- /dev/null +++ b/src/themes/custom/app/register-page/create-profile/create-profile.component.ts @@ -0,0 +1,15 @@ +import { Component } from '@angular/core'; +import { CreateProfileComponent as BaseComponent } from '../../../../../app/register-page/create-profile/create-profile.component'; + +/** + * Component that renders the create profile page to be used by a user registering through a token + */ +@Component({ + selector: 'ds-create-profile', + // styleUrls: ['./create-profile.component.scss'], + styleUrls: ['../../../../../app/register-page/create-profile/create-profile.component.scss'], + // templateUrl: './create-profile.component.html' + templateUrl: '../../../../../app/register-page/create-profile/create-profile.component.html' +}) +export class CreateProfileComponent extends BaseComponent { +} diff --git a/src/themes/custom/app/register-page/register-email/register-email.component.html b/src/themes/custom/app/register-page/register-email/register-email.component.html new file mode 100644 index 0000000000..e69de29bb2 diff --git a/src/themes/custom/app/register-page/register-email/register-email.component.scss b/src/themes/custom/app/register-page/register-email/register-email.component.scss new file mode 100644 index 0000000000..e69de29bb2 diff --git a/src/themes/custom/app/register-page/register-email/register-email.component.ts b/src/themes/custom/app/register-page/register-email/register-email.component.ts new file mode 100644 index 0000000000..6e85a61732 --- /dev/null +++ b/src/themes/custom/app/register-page/register-email/register-email.component.ts @@ -0,0 +1,15 @@ +import { Component } from '@angular/core'; +import { RegisterEmailComponent as BaseComponent } from '../../../../../app/register-page/register-email/register-email.component'; + +@Component({ + selector: 'ds-register-email', + // styleUrls: ['./register-email.component.scss'], + styleUrls: ['../../../../../app/register-page/register-email/register-email.component.scss'], + // templateUrl: './register-email.component.html' + templateUrl: '../../../../../app/register-page/register-email/register-email.component.html' +}) +/** + * Component responsible the email registration step when registering as a new user + */ +export class RegisterEmailComponent extends BaseComponent{ +} diff --git a/src/themes/custom/app/submission/edit/submission-edit.component.html b/src/themes/custom/app/submission/edit/submission-edit.component.html new file mode 100644 index 0000000000..e69de29bb2 diff --git a/src/themes/custom/app/submission/edit/submission-edit.component.scss b/src/themes/custom/app/submission/edit/submission-edit.component.scss new file mode 100644 index 0000000000..e69de29bb2 diff --git a/src/themes/custom/app/submission/edit/submission-edit.component.ts b/src/themes/custom/app/submission/edit/submission-edit.component.ts new file mode 100644 index 0000000000..88559d30b4 --- /dev/null +++ b/src/themes/custom/app/submission/edit/submission-edit.component.ts @@ -0,0 +1,15 @@ +import { Component } from '@angular/core'; +import { SubmissionEditComponent as BaseComponent } from '../../../../../app/submission/edit/submission-edit.component'; + +/** + * This component allows to edit an existing workspaceitem/workflowitem. + */ +@Component({ + selector: 'ds-submission-edit', + // styleUrls: ['./submission-edit.component.scss'], + styleUrls: ['../../../../../app/submission/edit/submission-edit.component.scss'], + // templateUrl: './submission-edit.component.html' + templateUrl: '../../../../../app/submission/edit/submission-edit.component.html' +}) +export class SubmissionEditComponent extends BaseComponent { +} diff --git a/src/themes/custom/app/submission/import-external/submission-import-external.component.html b/src/themes/custom/app/submission/import-external/submission-import-external.component.html new file mode 100644 index 0000000000..e69de29bb2 diff --git a/src/themes/custom/app/submission/import-external/submission-import-external.component.scss b/src/themes/custom/app/submission/import-external/submission-import-external.component.scss new file mode 100644 index 0000000000..e69de29bb2 diff --git a/src/themes/custom/app/submission/import-external/submission-import-external.component.ts b/src/themes/custom/app/submission/import-external/submission-import-external.component.ts new file mode 100644 index 0000000000..cf541b85c9 --- /dev/null +++ b/src/themes/custom/app/submission/import-external/submission-import-external.component.ts @@ -0,0 +1,18 @@ +import { Component } from '@angular/core'; +import { fadeIn } from '../../../../../app/shared/animations/fade'; +import { SubmissionImportExternalComponent as BaseComponent } from '../../../../../app/submission/import-external/submission-import-external.component'; + +/** + * This component allows to submit a new workspaceitem importing the data from an external source. + */ +@Component({ + selector: 'ds-submission-import-external', + // styleUrls: ['./submission-import-external.component.scss'], + styleUrls: ['../../../../../app/submission/import-external/submission-import-external.component.scss'], + // templateUrl: './submission-import-external.component.html', + templateUrl: '../../../../../app/submission/import-external/submission-import-external.component.html', + animations: [fadeIn] +}) +export class SubmissionImportExternalComponent extends BaseComponent { + +} diff --git a/src/themes/custom/app/submission/submit/submission-submit.component.html b/src/themes/custom/app/submission/submit/submission-submit.component.html new file mode 100644 index 0000000000..e69de29bb2 diff --git a/src/themes/custom/app/submission/submit/submission-submit.component.scss b/src/themes/custom/app/submission/submit/submission-submit.component.scss new file mode 100644 index 0000000000..e69de29bb2 diff --git a/src/themes/custom/app/submission/submit/submission-submit.component.ts b/src/themes/custom/app/submission/submit/submission-submit.component.ts new file mode 100644 index 0000000000..1273e26069 --- /dev/null +++ b/src/themes/custom/app/submission/submit/submission-submit.component.ts @@ -0,0 +1,15 @@ +import { Component } from '@angular/core'; +import { SubmissionSubmitComponent as BaseComponent } from '../../../../../app/submission/submit/submission-submit.component'; + +/** + * This component allows to submit a new workspaceitem. + */ +@Component({ + selector: 'ds-submission-submit', + // styleUrls: ['./submission-submit.component.scss'], + styleUrls: ['../../../../../app/submission/submit/submission-submit.component.scss'], + // templateUrl: './submission-submit.component.html' + templateUrl: '../../../../../app/submission/submit/submission-submit.component.html' +}) +export class SubmissionSubmitComponent extends BaseComponent{ +} diff --git a/src/themes/custom/theme.module.ts b/src/themes/custom/theme.module.ts index 18a048275a..6192451692 100644 --- a/src/themes/custom/theme.module.ts +++ b/src/themes/custom/theme.module.ts @@ -57,6 +57,23 @@ import { CollectionPageComponent } from './app/+collection-page/collection-page. import { CommunityPageModule } from '../../app/+community-page/community-page.module'; import { CollectionPageModule } from '../../app/+collection-page/collection-page.module'; import { ConfigurationSearchPageComponent } from './app/+search-page/configuration-search-page.component'; +import { ItemPageComponent } from './app/+item-page/simple/item-page.component'; +import { FullItemPageComponent } from './app/+item-page/full/full-item-page.component'; +import { LoginPageComponent } from './app/+login-page/login-page.component'; +import { LogoutPageComponent } from './app/+logout-page/logout-page.component'; +import { CreateProfileComponent } from './app/register-page/create-profile/create-profile.component'; +import { ForgotEmailComponent } from './app/forgot-password/forgot-password-email/forgot-email.component'; +import { ForgotPasswordFormComponent } from './app/forgot-password/forgot-password-form/forgot-password-form.component'; +import { ProfilePageComponent } from './app/profile-page/profile-page.component'; +import { RegisterEmailComponent } from './app/register-page/register-email/register-email.component'; +import { SubmissionEditComponent } from './app/submission/edit/submission-edit.component'; +import { SubmissionImportExternalComponent } from './app/submission/import-external/submission-import-external.component'; +import { SubmissionSubmitComponent } from './app/submission/submit/submission-submit.component'; +import { MyDSpacePageComponent } from './app/+my-dspace-page/my-dspace-page.component'; +import { WorkflowItemSendBackComponent } from './app/+workflowitems-edit-page/workflow-item-send-back/workflow-item-send-back.component'; +import { WorkflowItemDeleteComponent } from './app/+workflowitems-edit-page/workflow-item-delete/workflow-item-delete.component'; +import { SubmissionModule } from '../../app/submission/submission.module'; +import { MyDSpacePageModule } from '../../app/+my-dspace-page/my-dspace-page.module'; const DECLARATIONS = [ HomePageComponent, @@ -77,7 +94,23 @@ const DECLARATIONS = [ ItemStatisticsPageComponent, SiteStatisticsPageComponent, CommunityPageComponent, - CollectionPageComponent + CollectionPageComponent, + ItemPageComponent, + FullItemPageComponent, + LoginPageComponent, + LogoutPageComponent, + CreateProfileComponent, + ForgotEmailComponent, + ForgotPasswordFormComponent, + ProfilePageComponent, + RegisterEmailComponent, + MyDSpacePageComponent, + SubmissionEditComponent, + SubmissionImportExternalComponent, + SubmissionSubmitComponent, + WorkflowItemDeleteComponent, + WorkflowItemSendBackComponent + ]; @NgModule({ @@ -121,16 +154,19 @@ const DECLARATIONS = [ StoreModule, StoreRouterConnectingModule, TranslateModule, + SubmissionModule, + MyDSpacePageModule, + MyDspaceSearchModule, ], declarations: DECLARATIONS }) -/** - * This module serves as an index for all the components in this theme. - * It should import all other modules, so the compiler knows where to find any components referenced - * from a component in this theme - * It is purposefully not exported, it should never be imported anywhere else, its only purpose is - * to give lazily loaded components a context in which they can be compiled successfully - */ + /** + * This module serves as an index for all the components in this theme. + * It should import all other modules, so the compiler knows where to find any components referenced + * from a component in this theme + * It is purposefully not exported, it should never be imported anywhere else, its only purpose is + * to give lazily loaded components a context in which they can be compiled successfully + */ class ThemeModule { } From 05aaa5400df71eb0f0bf7640c64a78e4ee243390 Mon Sep 17 00:00:00 2001 From: Art Lowel Date: Thu, 4 Mar 2021 14:21:55 +0100 Subject: [PATCH 084/132] fix lint issues --- .../register-page/register-email/register-email.component.ts | 2 +- .../custom/app/submission/submit/submission-submit.component.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/themes/custom/app/register-page/register-email/register-email.component.ts b/src/themes/custom/app/register-page/register-email/register-email.component.ts index 6e85a61732..66becd1b6b 100644 --- a/src/themes/custom/app/register-page/register-email/register-email.component.ts +++ b/src/themes/custom/app/register-page/register-email/register-email.component.ts @@ -11,5 +11,5 @@ import { RegisterEmailComponent as BaseComponent } from '../../../../../app/regi /** * Component responsible the email registration step when registering as a new user */ -export class RegisterEmailComponent extends BaseComponent{ +export class RegisterEmailComponent extends BaseComponent { } diff --git a/src/themes/custom/app/submission/submit/submission-submit.component.ts b/src/themes/custom/app/submission/submit/submission-submit.component.ts index 1273e26069..05c3389cb7 100644 --- a/src/themes/custom/app/submission/submit/submission-submit.component.ts +++ b/src/themes/custom/app/submission/submit/submission-submit.component.ts @@ -11,5 +11,5 @@ import { SubmissionSubmitComponent as BaseComponent } from '../../../../../app/s // templateUrl: './submission-submit.component.html' templateUrl: '../../../../../app/submission/submit/submission-submit.component.html' }) -export class SubmissionSubmitComponent extends BaseComponent{ +export class SubmissionSubmitComponent extends BaseComponent { } From f5a34bb14eaaa4c9d5e17da3acbd12d3aea2ccb2 Mon Sep 17 00:00:00 2001 From: lotte Date: Thu, 4 Mar 2021 14:48:52 +0100 Subject: [PATCH 085/132] fixed lgtm issues --- .../themed-browse-by-switcher.component.ts | 2 +- src/app/+item-page/item-page-routing.module.ts | 1 - src/app/app-routing.module.ts | 12 +----------- .../register-page/register-page-routing.module.ts | 1 - 4 files changed, 2 insertions(+), 14 deletions(-) diff --git a/src/app/+browse-by/+browse-by-switcher/themed-browse-by-switcher.component.ts b/src/app/+browse-by/+browse-by-switcher/themed-browse-by-switcher.component.ts index 20d27012fe..9fbf1979b5 100644 --- a/src/app/+browse-by/+browse-by-switcher/themed-browse-by-switcher.component.ts +++ b/src/app/+browse-by/+browse-by-switcher/themed-browse-by-switcher.component.ts @@ -1,4 +1,4 @@ -import { Component, OnInit } from '@angular/core'; +import { Component } from '@angular/core'; import { ThemedComponent } from '../../shared/theme-support/themed.component'; import { BrowseBySwitcherComponent } from './browse-by-switcher.component'; diff --git a/src/app/+item-page/item-page-routing.module.ts b/src/app/+item-page/item-page-routing.module.ts index b259f57dcb..c9f2c402bb 100644 --- a/src/app/+item-page/item-page-routing.module.ts +++ b/src/app/+item-page/item-page-routing.module.ts @@ -1,6 +1,5 @@ import { NgModule } from '@angular/core'; import { RouterModule } from '@angular/router'; -import { FullItemPageComponent } from './full/full-item-page.component'; import { ItemPageResolver } from './item-page.resolver'; import { AuthenticatedGuard } from '../core/auth/authenticated.guard'; import { ItemBreadcrumbResolver } from '../core/breadcrumbs/item-breadcrumb.resolver'; diff --git a/src/app/app-routing.module.ts b/src/app/app-routing.module.ts index 18ce77df07..13e1133d82 100644 --- a/src/app/app-routing.module.ts +++ b/src/app/app-routing.module.ts @@ -4,16 +4,7 @@ import { AuthBlockingGuard } from './core/auth/auth-blocking.guard'; import { AuthenticatedGuard } from './core/auth/authenticated.guard'; import { SiteAdministratorGuard } from './core/data/feature-authorization/feature-authorization-guard/site-administrator.guard'; -import { - ADMIN_MODULE_PATH, - BITSTREAM_MODULE_PATH, - FORBIDDEN_PATH, - FORGOT_PASSWORD_PATH, - INFO_MODULE_PATH, - PROFILE_MODULE_PATH, - REGISTER_PATH, - WORKFLOW_ITEM_MODULE_PATH -} from './app-routing-paths'; +import { ADMIN_MODULE_PATH, BITSTREAM_MODULE_PATH, FORBIDDEN_PATH, FORGOT_PASSWORD_PATH, INFO_MODULE_PATH, PROFILE_MODULE_PATH, REGISTER_PATH, WORKFLOW_ITEM_MODULE_PATH } from './app-routing-paths'; import { COLLECTION_MODULE_PATH } from './+collection-page/collection-page-routing-paths'; import { COMMUNITY_MODULE_PATH } from './+community-page/community-page-routing-paths'; import { ITEM_MODULE_PATH } from './+item-page/item-page-routing-paths'; @@ -21,7 +12,6 @@ import { PROCESS_MODULE_PATH } from './process-page/process-page-routing.paths'; import { ReloadGuard } from './core/reload/reload.guard'; import { EndUserAgreementCurrentUserGuard } from './core/end-user-agreement/end-user-agreement-current-user.guard'; import { SiteRegisterGuard } from './core/data/feature-authorization/feature-authorization-guard/site-register.guard'; -import { ForbiddenComponent } from './forbidden/forbidden.component'; import { ThemedPageNotFoundComponent } from './pagenotfound/themed-pagenotfound.component'; import { ThemedForbiddenComponent } from './forbidden/themed-forbidden.component'; diff --git a/src/app/register-page/register-page-routing.module.ts b/src/app/register-page/register-page-routing.module.ts index 0fdb92b4ec..f623643a8d 100644 --- a/src/app/register-page/register-page-routing.module.ts +++ b/src/app/register-page/register-page-routing.module.ts @@ -1,7 +1,6 @@ import { NgModule } from '@angular/core'; import { RouterModule } from '@angular/router'; import { RegisterEmailComponent } from './register-email/register-email.component'; -import { CreateProfileComponent } from './create-profile/create-profile.component'; import { ItemPageResolver } from '../+item-page/item-page.resolver'; import { RegistrationResolver } from '../register-email-form/registration.resolver'; import { EndUserAgreementCookieGuard } from '../core/end-user-agreement/end-user-agreement-cookie.guard'; From 1d4c77e48557eead566dda2f2f65ba04df2df851 Mon Sep 17 00:00:00 2001 From: lotte Date: Wed, 17 Mar 2021 11:32:59 +0100 Subject: [PATCH 086/132] Added themable header, footer and navbar --- src/app/app.module.ts | 4 +++ src/app/footer/themed-footer.component.ts | 25 ++++++++++++++++ .../header-navbar-wrapper.component.html | 6 ++-- src/app/header/themed-header.component.ts | 29 +++++++++++++++++++ src/app/navbar/navbar.module.ts | 4 ++- src/app/navbar/themed-navbar.component.ts | 25 ++++++++++++++++ src/app/root/root.component.html | 2 +- .../custom/app/footer/footer.component.html | 0 .../custom/app/footer/footer.component.scss | 0 .../custom/app/footer/footer.component.ts | 12 ++++++++ .../custom/app/header/header.component.html | 0 .../custom/app/header/header.component.scss | 0 .../custom/app/header/header.component.ts | 15 ++++++++++ .../custom/app/navbar/navbar.component.html | 0 .../custom/app/navbar/navbar.component.scss | 0 .../custom/app/navbar/navbar.component.ts | 17 +++++++++++ src/themes/custom/theme.module.ts | 8 ++++- 17 files changed, 141 insertions(+), 6 deletions(-) create mode 100644 src/app/footer/themed-footer.component.ts create mode 100644 src/app/header/themed-header.component.ts create mode 100644 src/app/navbar/themed-navbar.component.ts create mode 100644 src/themes/custom/app/footer/footer.component.html create mode 100644 src/themes/custom/app/footer/footer.component.scss create mode 100644 src/themes/custom/app/footer/footer.component.ts create mode 100644 src/themes/custom/app/header/header.component.html create mode 100644 src/themes/custom/app/header/header.component.scss create mode 100644 src/themes/custom/app/header/header.component.ts create mode 100644 src/themes/custom/app/navbar/navbar.component.html create mode 100644 src/themes/custom/app/navbar/navbar.component.scss create mode 100644 src/themes/custom/app/navbar/navbar.component.ts diff --git a/src/app/app.module.ts b/src/app/app.module.ts index 20aaa4ba02..827c837ce7 100755 --- a/src/app/app.module.ts +++ b/src/app/app.module.ts @@ -48,6 +48,8 @@ import { ThemedRootComponent } from './root/themed-root.component'; import { ThemedEntryComponentModule } from '../themes/themed-entry-component.module'; import { ThemedPageNotFoundComponent } from './pagenotfound/themed-pagenotfound.component'; import { ThemedForbiddenComponent } from './forbidden/themed-forbidden.component'; +import { ThemedHeaderComponent } from './header/themed-header.component'; +import { ThemedFooterComponent } from './footer/themed-footer.component'; export function getBase() { return environment.ui.nameSpace; @@ -129,11 +131,13 @@ const DECLARATIONS = [ RootComponent, ThemedRootComponent, HeaderComponent, + ThemedHeaderComponent, HeaderNavbarWrapperComponent, AdminSidebarComponent, AdminSidebarSectionComponent, ExpandableAdminSidebarSectionComponent, FooterComponent, + ThemedFooterComponent, PageNotFoundComponent, ThemedPageNotFoundComponent, NotificationComponent, diff --git a/src/app/footer/themed-footer.component.ts b/src/app/footer/themed-footer.component.ts new file mode 100644 index 0000000000..c52a0af29f --- /dev/null +++ b/src/app/footer/themed-footer.component.ts @@ -0,0 +1,25 @@ +import { Component } from '@angular/core'; +import { ThemedComponent } from '../shared/theme-support/themed.component'; +import { FooterComponent } from './footer.component'; + +/** + * Themed wrapper for FooterComponent + */ +@Component({ + selector: 'ds-themed-footer', + styleUrls: ['footer.component.scss'], + templateUrl: '../shared/theme-support/themed.component.html', +}) +export class ThemedFooterComponent extends ThemedComponent { + protected getComponentName(): string { + return 'FooterComponent'; + } + + protected importThemedComponent(themeName: string): Promise { + return import(`../../themes/${themeName}/app/footer/footer.component`); + } + + protected importUnthemedComponent(): Promise { + return import(`./footer.component`); + } +} diff --git a/src/app/header-nav-wrapper/header-navbar-wrapper.component.html b/src/app/header-nav-wrapper/header-navbar-wrapper.component.html index 931ab36749..f99070b738 100644 --- a/src/app/header-nav-wrapper/header-navbar-wrapper.component.html +++ b/src/app/header-nav-wrapper/header-navbar-wrapper.component.html @@ -1,4 +1,4 @@
- - -
\ No newline at end of file + + + diff --git a/src/app/header/themed-header.component.ts b/src/app/header/themed-header.component.ts new file mode 100644 index 0000000000..8bf43e8ea1 --- /dev/null +++ b/src/app/header/themed-header.component.ts @@ -0,0 +1,29 @@ +import { Component } from '@angular/core'; +import { Observable } from 'rxjs'; +import { MenuService } from '../shared/menu/menu.service'; +import { MenuID } from '../shared/menu/initial-menus-state'; +import { ThemedComponent } from '../shared/theme-support/themed.component'; +import { CommunityListPageComponent } from '../community-list-page/community-list-page.component'; +import { HeaderComponent } from './header.component'; + +/** + * Themed wrapper for HeaderComponent + */ +@Component({ + selector: 'ds-themed-header', + styleUrls: [], + templateUrl: '../shared/theme-support/themed.component.html', +}) +export class ThemedHeaderComponent extends ThemedComponent { + protected getComponentName(): string { + return 'HeaderComponent'; + } + + protected importThemedComponent(themeName: string): Promise { + return import(`../../themes/${themeName}/app/header/header.component`); + } + + protected importUnthemedComponent(): Promise { + return import(`./header.component`); + } +} diff --git a/src/app/navbar/navbar.module.ts b/src/app/navbar/navbar.module.ts index 5e1e11d10f..5299c6cfc3 100644 --- a/src/app/navbar/navbar.module.ts +++ b/src/app/navbar/navbar.module.ts @@ -10,6 +10,7 @@ import { ExpandableNavbarSectionComponent } from './expandable-navbar-section/ex import { NavbarComponent } from './navbar.component'; import { MenuModule } from '../shared/menu/menu.module'; import { FormsModule } from '@angular/forms'; +import { ThemedNavbarComponent } from './themed-navbar.component'; const effects = [ NavbarEffects @@ -31,6 +32,7 @@ const ENTRY_COMPONENTS = [ ], declarations: [ NavbarComponent, + ThemedNavbarComponent, NavbarSectionComponent, ExpandableNavbarSectionComponent ], @@ -42,7 +44,7 @@ const ENTRY_COMPONENTS = [ ExpandableNavbarSectionComponent ], exports: [ - NavbarComponent, + ThemedNavbarComponent, NavbarSectionComponent, ExpandableNavbarSectionComponent ] diff --git a/src/app/navbar/themed-navbar.component.ts b/src/app/navbar/themed-navbar.component.ts new file mode 100644 index 0000000000..43efdc181e --- /dev/null +++ b/src/app/navbar/themed-navbar.component.ts @@ -0,0 +1,25 @@ +import { Component } from '@angular/core'; +import { ThemedComponent } from '../shared/theme-support/themed.component'; +import { NavbarComponent } from './navbar.component'; + +/** + * Themed wrapper for NavbarComponent + */ +@Component({ + selector: 'ds-themed-navbar', + styleUrls: [], + templateUrl: '../shared/theme-support/themed.component.html', +}) +export class ThemedNavbarComponent extends ThemedComponent { + protected getComponentName(): string { + return 'NavbarComponent'; + } + + protected importThemedComponent(themeName: string): Promise { + return import(`../../themes/${themeName}/app/navbar/navbar.component`); + } + + protected importUnthemedComponent(): Promise { + return import(`./navbar.component`); + } +} diff --git a/src/app/root/root.component.html b/src/app/root/root.component.html index 96439cd999..a0aa4dc1a3 100644 --- a/src/app/root/root.component.html +++ b/src/app/root/root.component.html @@ -20,7 +20,7 @@ - + diff --git a/src/themes/custom/app/footer/footer.component.html b/src/themes/custom/app/footer/footer.component.html new file mode 100644 index 0000000000..e69de29bb2 diff --git a/src/themes/custom/app/footer/footer.component.scss b/src/themes/custom/app/footer/footer.component.scss new file mode 100644 index 0000000000..e69de29bb2 diff --git a/src/themes/custom/app/footer/footer.component.ts b/src/themes/custom/app/footer/footer.component.ts new file mode 100644 index 0000000000..de80ceb311 --- /dev/null +++ b/src/themes/custom/app/footer/footer.component.ts @@ -0,0 +1,12 @@ +import { Component } from '@angular/core'; +import { FooterComponent as BaseComponent } from '../../../../app/footer/footer.component'; + +@Component({ + selector: 'ds-footer', + // styleUrls: ['footer.component.scss'], + styleUrls: ['../../../../app/footer/footer.component.scss'], + // templateUrl: 'footer.component.html' + templateUrl: '../../../../app/footer/footer.component.html' +}) +export class FooterComponent extends BaseComponent { +} diff --git a/src/themes/custom/app/header/header.component.html b/src/themes/custom/app/header/header.component.html new file mode 100644 index 0000000000..e69de29bb2 diff --git a/src/themes/custom/app/header/header.component.scss b/src/themes/custom/app/header/header.component.scss new file mode 100644 index 0000000000..e69de29bb2 diff --git a/src/themes/custom/app/header/header.component.ts b/src/themes/custom/app/header/header.component.ts new file mode 100644 index 0000000000..866072f3b6 --- /dev/null +++ b/src/themes/custom/app/header/header.component.ts @@ -0,0 +1,15 @@ +import { Component } from '@angular/core'; +import { HeaderComponent as BaseComponent } from '../../../../app/header/header.component'; + +/** + * Represents the header with the logo and simple navigation + */ +@Component({ + selector: 'ds-header', + // styleUrls: ['header.component.scss'], + styleUrls: ['../../../../app/header/header.component.scss'], + // templateUrl: 'header.component.html', + templateUrl: '../../../../app/header/header.component.html', +}) +export class HeaderComponent extends BaseComponent { +} diff --git a/src/themes/custom/app/navbar/navbar.component.html b/src/themes/custom/app/navbar/navbar.component.html new file mode 100644 index 0000000000..e69de29bb2 diff --git a/src/themes/custom/app/navbar/navbar.component.scss b/src/themes/custom/app/navbar/navbar.component.scss new file mode 100644 index 0000000000..e69de29bb2 diff --git a/src/themes/custom/app/navbar/navbar.component.ts b/src/themes/custom/app/navbar/navbar.component.ts new file mode 100644 index 0000000000..e163f096e9 --- /dev/null +++ b/src/themes/custom/app/navbar/navbar.component.ts @@ -0,0 +1,17 @@ +import { Component } from '@angular/core'; +import { NavbarComponent as BaseComponent } from '../../../../app/navbar/navbar.component'; +import { slideMobileNav } from '../../../../app/shared/animations/slide'; + +/** + * Component representing the public navbar + */ +@Component({ + selector: 'ds-navbar', + // styleUrls: ['./navbar.component.scss'], + styleUrls: ['../../../../app/navbar/navbar.component.scss'], + // templateUrl: './navbar.component.html', + templateUrl: '../../../../app/navbar/navbar.component.html', + animations: [slideMobileNav] +}) +export class NavbarComponent extends BaseComponent { +} diff --git a/src/themes/custom/theme.module.ts b/src/themes/custom/theme.module.ts index 6192451692..0e1096f957 100644 --- a/src/themes/custom/theme.module.ts +++ b/src/themes/custom/theme.module.ts @@ -74,6 +74,9 @@ import { WorkflowItemSendBackComponent } from './app/+workflowitems-edit-page/wo import { WorkflowItemDeleteComponent } from './app/+workflowitems-edit-page/workflow-item-delete/workflow-item-delete.component'; import { SubmissionModule } from '../../app/submission/submission.module'; import { MyDSpacePageModule } from '../../app/+my-dspace-page/my-dspace-page.module'; +import { NavbarComponent } from './app/navbar/navbar.component'; +import { HeaderComponent } from './app/header/header.component'; +import { FooterComponent } from './app/footer/footer.component'; const DECLARATIONS = [ HomePageComponent, @@ -109,7 +112,10 @@ const DECLARATIONS = [ SubmissionImportExternalComponent, SubmissionSubmitComponent, WorkflowItemDeleteComponent, - WorkflowItemSendBackComponent + WorkflowItemSendBackComponent, + FooterComponent, + HeaderComponent, + NavbarComponent ]; From d50bef9c8a3a1bb018fd561b035ca48daf35bcd8 Mon Sep 17 00:00:00 2001 From: lotte Date: Wed, 17 Mar 2021 11:51:08 +0100 Subject: [PATCH 087/132] Fixed LGTM import issues --- src/app/header/themed-header.component.ts | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/app/header/themed-header.component.ts b/src/app/header/themed-header.component.ts index 8bf43e8ea1..51c817b63d 100644 --- a/src/app/header/themed-header.component.ts +++ b/src/app/header/themed-header.component.ts @@ -1,9 +1,5 @@ import { Component } from '@angular/core'; -import { Observable } from 'rxjs'; -import { MenuService } from '../shared/menu/menu.service'; -import { MenuID } from '../shared/menu/initial-menus-state'; import { ThemedComponent } from '../shared/theme-support/themed.component'; -import { CommunityListPageComponent } from '../community-list-page/community-list-page.component'; import { HeaderComponent } from './header.component'; /** From b12e616ff61651bc08ecff992da9bb08cdb511da Mon Sep 17 00:00:00 2001 From: lotte Date: Wed, 17 Mar 2021 11:51:35 +0100 Subject: [PATCH 088/132] Added themable breadcrumbs --- src/app/app.module.ts | 2 ++ .../themed-breadcrumbs.component.ts | 25 +++++++++++++++++++ src/app/root/root.component.html | 2 +- .../breadcrumbs/breadcrumbs.component.html | 0 .../breadcrumbs/breadcrumbs.component.scss | 0 .../app/breadcrumbs/breadcrumbs.component.ts | 15 +++++++++++ src/themes/custom/theme.module.ts | 5 ++-- 7 files changed, 46 insertions(+), 3 deletions(-) create mode 100644 src/app/breadcrumbs/themed-breadcrumbs.component.ts create mode 100644 src/themes/custom/app/breadcrumbs/breadcrumbs.component.html create mode 100644 src/themes/custom/app/breadcrumbs/breadcrumbs.component.scss create mode 100644 src/themes/custom/app/breadcrumbs/breadcrumbs.component.ts diff --git a/src/app/app.module.ts b/src/app/app.module.ts index 827c837ce7..5bfa593ef1 100755 --- a/src/app/app.module.ts +++ b/src/app/app.module.ts @@ -50,6 +50,7 @@ import { ThemedPageNotFoundComponent } from './pagenotfound/themed-pagenotfound. import { ThemedForbiddenComponent } from './forbidden/themed-forbidden.component'; import { ThemedHeaderComponent } from './header/themed-header.component'; import { ThemedFooterComponent } from './footer/themed-footer.component'; +import { ThemedBreadcrumbsComponent } from './breadcrumbs/themed-breadcrumbs.component'; export function getBase() { return environment.ui.nameSpace; @@ -144,6 +145,7 @@ const DECLARATIONS = [ NotificationsBoardComponent, SearchNavbarComponent, BreadcrumbsComponent, + ThemedBreadcrumbsComponent, ForbiddenComponent, ThemedForbiddenComponent, ]; diff --git a/src/app/breadcrumbs/themed-breadcrumbs.component.ts b/src/app/breadcrumbs/themed-breadcrumbs.component.ts new file mode 100644 index 0000000000..1869a440b9 --- /dev/null +++ b/src/app/breadcrumbs/themed-breadcrumbs.component.ts @@ -0,0 +1,25 @@ +import { Component } from '@angular/core'; +import { ThemedComponent } from '../shared/theme-support/themed.component'; +import { BreadcrumbsComponent } from './breadcrumbs.component'; + +/** + * Themed wrapper for BreadcrumbsComponent + */ +@Component({ + selector: 'ds-themed-breadcrumbs', + styleUrls: [], + templateUrl: '../shared/theme-support/themed.component.html', +}) +export class ThemedBreadcrumbsComponent extends ThemedComponent { + protected getComponentName(): string { + return 'BreadcrumbsComponent'; + } + + protected importThemedComponent(themeName: string): Promise { + return import(`../../themes/${themeName}/app/breadcrumbs/breadcrumbs.component`); + } + + protected importUnthemedComponent(): Promise { + return import(`./breadcrumbs.component`); + } +} diff --git a/src/app/root/root.component.html b/src/app/root/root.component.html index a0aa4dc1a3..af59e0d2ad 100644 --- a/src/app/root/root.component.html +++ b/src/app/root/root.component.html @@ -11,7 +11,7 @@
- +
diff --git a/src/themes/custom/app/breadcrumbs/breadcrumbs.component.html b/src/themes/custom/app/breadcrumbs/breadcrumbs.component.html new file mode 100644 index 0000000000..e69de29bb2 diff --git a/src/themes/custom/app/breadcrumbs/breadcrumbs.component.scss b/src/themes/custom/app/breadcrumbs/breadcrumbs.component.scss new file mode 100644 index 0000000000..e69de29bb2 diff --git a/src/themes/custom/app/breadcrumbs/breadcrumbs.component.ts b/src/themes/custom/app/breadcrumbs/breadcrumbs.component.ts new file mode 100644 index 0000000000..32d00fc8b6 --- /dev/null +++ b/src/themes/custom/app/breadcrumbs/breadcrumbs.component.ts @@ -0,0 +1,15 @@ +import { Component } from '@angular/core'; +import { BreadcrumbsComponent as BaseComponent } from '../../../../app/breadcrumbs/breadcrumbs.component'; + +/** + * Component representing the breadcrumbs of a page + */ +@Component({ + selector: 'ds-breadcrumbs', + // templateUrl: './breadcrumbs.component.html', + templateUrl: '../../../../app/breadcrumbs/breadcrumbs.component.html', + // styleUrls: ['./breadcrumbs.component.scss'] + styleUrls: ['../../../../app/breadcrumbs/breadcrumbs.component.scss'] +}) +export class BreadcrumbsComponent extends BaseComponent { +} diff --git a/src/themes/custom/theme.module.ts b/src/themes/custom/theme.module.ts index 0e1096f957..b9bba225a7 100644 --- a/src/themes/custom/theme.module.ts +++ b/src/themes/custom/theme.module.ts @@ -77,6 +77,7 @@ import { MyDSpacePageModule } from '../../app/+my-dspace-page/my-dspace-page.mod import { NavbarComponent } from './app/navbar/navbar.component'; import { HeaderComponent } from './app/header/header.component'; import { FooterComponent } from './app/footer/footer.component'; +import { BreadcrumbsComponent } from './app/breadcrumbs/breadcrumbs.component'; const DECLARATIONS = [ HomePageComponent, @@ -115,8 +116,8 @@ const DECLARATIONS = [ WorkflowItemSendBackComponent, FooterComponent, HeaderComponent, - NavbarComponent - + NavbarComponent, + BreadcrumbsComponent ]; @NgModule({ From c19ee0d49ebf752a5ea58e7960c659a85bdf7878 Mon Sep 17 00:00:00 2001 From: lotte Date: Wed, 17 Mar 2021 12:09:50 +0100 Subject: [PATCH 089/132] Updated TypeDoc for themed components --- .../themed-browse-by-switcher.component.ts | 6 +++--- .../+collection-page/themed-collection-page.component.ts | 7 +++---- src/app/+community-page/themed-community-page.component.ts | 7 +++---- .../objectnotfound/themed-objectnotfound.component.ts | 7 +++---- .../themed-configuration-search-page.component.ts | 7 +++---- src/app/+search-page/themed-search-page.component.ts | 7 +++---- .../themed-community-list-page.component.ts | 3 +-- src/app/forbidden/themed-forbidden.component.ts | 7 +++---- .../themed-end-user-agreement.component.ts | 7 +++---- src/app/info/privacy/themed-privacy.component.ts | 7 +++---- src/app/pagenotfound/themed-pagenotfound.component.ts | 7 +++---- .../themed-collection-statistics-page.component.ts | 7 +++---- .../themed-community-statistics-page.component.ts | 7 +++---- .../themed-item-statistics-page.component.ts | 7 +++---- .../themed-site-statistics-page.component.ts | 7 +++---- 15 files changed, 43 insertions(+), 57 deletions(-) diff --git a/src/app/+browse-by/+browse-by-switcher/themed-browse-by-switcher.component.ts b/src/app/+browse-by/+browse-by-switcher/themed-browse-by-switcher.component.ts index 9fbf1979b5..e92fe30ba9 100644 --- a/src/app/+browse-by/+browse-by-switcher/themed-browse-by-switcher.component.ts +++ b/src/app/+browse-by/+browse-by-switcher/themed-browse-by-switcher.component.ts @@ -3,14 +3,14 @@ import { Component } from '@angular/core'; import { ThemedComponent } from '../../shared/theme-support/themed.component'; import { BrowseBySwitcherComponent } from './browse-by-switcher.component'; +/** + * Themed wrapper for BrowseBySwitcherComponent + */ @Component({ selector: 'ds-themed-browse-by-switcher', styleUrls: [], templateUrl: '../../shared/theme-support/themed.component.html' }) -/** - * Component for determining what Browse-By component to use depending on the metadata (browse ID) provided - */ export class ThemedBrowseBySwitcherComponent extends ThemedComponent { protected getComponentName(): string { return 'BrowseBySwitcherComponent'; diff --git a/src/app/+collection-page/themed-collection-page.component.ts b/src/app/+collection-page/themed-collection-page.component.ts index 7bbc720e30..4ad9ed87e3 100644 --- a/src/app/+collection-page/themed-collection-page.component.ts +++ b/src/app/+collection-page/themed-collection-page.component.ts @@ -2,15 +2,14 @@ import { Component } from '@angular/core'; import { ThemedComponent } from '../shared/theme-support/themed.component'; import { CollectionPageComponent } from './collection-page.component'; +/** + * Themed wrapper for CollectionPageComponent + */ @Component({ selector: 'ds-themed-community-page', styleUrls: [], templateUrl: '../shared/theme-support/themed.component.html', }) - -/** - * Component to render the news section on the home page - */ export class ThemedCollectionPageComponent extends ThemedComponent { protected getComponentName(): string { return 'CollectionPageComponent'; diff --git a/src/app/+community-page/themed-community-page.component.ts b/src/app/+community-page/themed-community-page.component.ts index b420789c5f..97dd59821c 100644 --- a/src/app/+community-page/themed-community-page.component.ts +++ b/src/app/+community-page/themed-community-page.component.ts @@ -2,15 +2,14 @@ import { Component } from '@angular/core'; import { ThemedComponent } from '../shared/theme-support/themed.component'; import { CommunityPageComponent } from './community-page.component'; +/** + * Themed wrapper for CommunityPageComponent + */ @Component({ selector: 'ds-themed-community-page', styleUrls: [], templateUrl: '../shared/theme-support/themed.component.html', }) - -/** - * Component to render the news section on the home page - */ export class ThemedCommunityPageComponent extends ThemedComponent { protected getComponentName(): string { return 'CommunityPageComponent'; diff --git a/src/app/+lookup-by-id/objectnotfound/themed-objectnotfound.component.ts b/src/app/+lookup-by-id/objectnotfound/themed-objectnotfound.component.ts index 947a9f4eaa..e1bec33dfd 100644 --- a/src/app/+lookup-by-id/objectnotfound/themed-objectnotfound.component.ts +++ b/src/app/+lookup-by-id/objectnotfound/themed-objectnotfound.component.ts @@ -2,15 +2,14 @@ import { Component } from '@angular/core'; import { ThemedComponent } from '../../shared/theme-support/themed.component'; import { ObjectNotFoundComponent } from './objectnotfound.component'; +/** + * Themed wrapper for ObjectNotFoundComponent + */ @Component({ selector: 'ds-themed-objnotfound', styleUrls: [], templateUrl: '../../shared/theme-support/themed.component.html', }) - -/** - * Component to render the news section on the home page - */ export class ThemedObjectNotFoundComponent extends ThemedComponent { protected getComponentName(): string { return 'ObjectNotFoundComponent'; diff --git a/src/app/+search-page/themed-configuration-search-page.component.ts b/src/app/+search-page/themed-configuration-search-page.component.ts index 3528d3a326..9f7277be0e 100644 --- a/src/app/+search-page/themed-configuration-search-page.component.ts +++ b/src/app/+search-page/themed-configuration-search-page.component.ts @@ -4,15 +4,14 @@ import { ConfigurationSearchPageComponent } from './configuration-search-page.co import { Observable } from 'rxjs'; import { Context } from '../core/shared/context.model'; +/** + * Themed wrapper for ConfigurationSearchPageComponent + */ @Component({ selector: 'ds-themed-configuration-search-page', styleUrls: [], templateUrl: '../shared/theme-support/themed.component.html', }) - -/** - * Component to render the news section on the home page - */ export class ThemedConfigurationSearchPageComponent extends ThemedComponent { /** * The configuration to use for the search options diff --git a/src/app/+search-page/themed-search-page.component.ts b/src/app/+search-page/themed-search-page.component.ts index b23fff6289..0b2f673373 100644 --- a/src/app/+search-page/themed-search-page.component.ts +++ b/src/app/+search-page/themed-search-page.component.ts @@ -2,15 +2,14 @@ import { Component } from '@angular/core'; import { ThemedComponent } from '../shared/theme-support/themed.component'; import { SearchPageComponent } from './search-page.component'; +/** + * Themed wrapper for SearchPageComponent + */ @Component({ selector: 'ds-themed-search-page', styleUrls: [], templateUrl: '../shared/theme-support/themed.component.html', }) -/** - * This component represents the whole search page - * It renders search results depending on the current search options - */ export class ThemedSearchPageComponent extends ThemedComponent { protected getComponentName(): string { diff --git a/src/app/community-list-page/themed-community-list-page.component.ts b/src/app/community-list-page/themed-community-list-page.component.ts index 6b374fca90..20fa97bedd 100644 --- a/src/app/community-list-page/themed-community-list-page.component.ts +++ b/src/app/community-list-page/themed-community-list-page.component.ts @@ -3,8 +3,7 @@ import { ThemedComponent } from '../shared/theme-support/themed.component'; import { CommunityListPageComponent } from './community-list-page.component'; /** - * Page with title and the community list tree, as described in community-list.component; - * navigated to with community-list.page.routing.module + * Themed wrapper for CommunityListPageComponent */ @Component({ selector: 'ds-themed-community-list-page', diff --git a/src/app/forbidden/themed-forbidden.component.ts b/src/app/forbidden/themed-forbidden.component.ts index bb3694cae2..830529c8fa 100644 --- a/src/app/forbidden/themed-forbidden.component.ts +++ b/src/app/forbidden/themed-forbidden.component.ts @@ -2,15 +2,14 @@ import { Component } from '@angular/core'; import { ThemedComponent } from '../shared/theme-support/themed.component'; import { ForbiddenComponent } from './forbidden.component'; +/** + * Themed wrapper for ForbiddenComponent + */ @Component({ selector: 'ds-themed-forbidden', styleUrls: [], templateUrl: '../shared/theme-support/themed.component.html', }) - -/** - * Component to render the news section on the home page - */ export class ThemedForbiddenComponent extends ThemedComponent { protected getComponentName(): string { return 'ForbiddenComponent'; diff --git a/src/app/info/end-user-agreement/themed-end-user-agreement.component.ts b/src/app/info/end-user-agreement/themed-end-user-agreement.component.ts index 6c76314e06..74eb545b8a 100644 --- a/src/app/info/end-user-agreement/themed-end-user-agreement.component.ts +++ b/src/app/info/end-user-agreement/themed-end-user-agreement.component.ts @@ -2,15 +2,14 @@ import { Component } from '@angular/core'; import { ThemedComponent } from '../../shared/theme-support/themed.component'; import { EndUserAgreementComponent } from './end-user-agreement.component'; +/** + * Themed wrapper for EndUserAgreementComponent + */ @Component({ selector: 'ds-themed-end-user-agreement', styleUrls: [], templateUrl: '../../shared/theme-support/themed.component.html', }) - -/** - * Component to render the news section on the home page - */ export class ThemedEndUserAgreementComponent extends ThemedComponent { protected getComponentName(): string { diff --git a/src/app/info/privacy/themed-privacy.component.ts b/src/app/info/privacy/themed-privacy.component.ts index 5aed8d38af..7f2ee80ffc 100644 --- a/src/app/info/privacy/themed-privacy.component.ts +++ b/src/app/info/privacy/themed-privacy.component.ts @@ -2,15 +2,14 @@ import { Component } from '@angular/core'; import { ThemedComponent } from '../../shared/theme-support/themed.component'; import { PrivacyComponent } from './privacy.component'; +/** + * Themed wrapper for PrivacyComponent + */ @Component({ selector: 'ds-themed-privacy', styleUrls: [], templateUrl: '../../shared/theme-support/themed.component.html', }) - -/** - * Component to render the news section on the home page - */ export class ThemedPrivacyComponent extends ThemedComponent { protected getComponentName(): string { return 'PrivacyComponent'; diff --git a/src/app/pagenotfound/themed-pagenotfound.component.ts b/src/app/pagenotfound/themed-pagenotfound.component.ts index 68b06e2ac0..e6ef9eb700 100644 --- a/src/app/pagenotfound/themed-pagenotfound.component.ts +++ b/src/app/pagenotfound/themed-pagenotfound.component.ts @@ -2,15 +2,14 @@ import { Component } from '@angular/core'; import { ThemedComponent } from '../shared/theme-support/themed.component'; import { PageNotFoundComponent } from './pagenotfound.component'; +/** + * Themed wrapper for PageNotFoundComponent + */ @Component({ selector: 'ds-themed-search-page', styleUrls: [], templateUrl: '../shared/theme-support/themed.component.html', }) -/** - * This component represents the whole search page - * It renders search results depending on the current search options - */ export class ThemedPageNotFoundComponent extends ThemedComponent { protected getComponentName(): string { diff --git a/src/app/statistics-page/collection-statistics-page/themed-collection-statistics-page.component.ts b/src/app/statistics-page/collection-statistics-page/themed-collection-statistics-page.component.ts index 75cf60437f..dab96aef04 100644 --- a/src/app/statistics-page/collection-statistics-page/themed-collection-statistics-page.component.ts +++ b/src/app/statistics-page/collection-statistics-page/themed-collection-statistics-page.component.ts @@ -2,15 +2,14 @@ import { Component } from '@angular/core'; import { ThemedComponent } from '../../shared/theme-support/themed.component'; import { CollectionStatisticsPageComponent } from './collection-statistics-page.component'; +/** + * Themed wrapper for CollectionStatisticsPageComponent + */ @Component({ selector: 'ds-themed-collection-statistics-page', styleUrls: [], templateUrl: '../../shared/theme-support/themed.component.html', }) - -/** - * Component to render the news section on the home page - */ export class ThemedCollectionStatisticsPageComponent extends ThemedComponent { protected getComponentName(): string { return 'CollectionStatisticsPageComponent'; diff --git a/src/app/statistics-page/community-statistics-page/themed-community-statistics-page.component.ts b/src/app/statistics-page/community-statistics-page/themed-community-statistics-page.component.ts index 34dc17e1b3..17f185f786 100644 --- a/src/app/statistics-page/community-statistics-page/themed-community-statistics-page.component.ts +++ b/src/app/statistics-page/community-statistics-page/themed-community-statistics-page.component.ts @@ -2,15 +2,14 @@ import { Component } from '@angular/core'; import { ThemedComponent } from '../../shared/theme-support/themed.component'; import { CommunityStatisticsPageComponent } from './community-statistics-page.component'; +/** + * Themed wrapper for CommunityStatisticsPageComponent + */ @Component({ selector: 'ds-themed-collection-statistics-page', styleUrls: [], templateUrl: '../../shared/theme-support/themed.component.html', }) - -/** - * Component to render the news section on the home page - */ export class ThemedCommunityStatisticsPageComponent extends ThemedComponent { protected getComponentName(): string { return 'CommunityStatisticsPageComponent'; diff --git a/src/app/statistics-page/item-statistics-page/themed-item-statistics-page.component.ts b/src/app/statistics-page/item-statistics-page/themed-item-statistics-page.component.ts index 4651269c54..50e26329a9 100644 --- a/src/app/statistics-page/item-statistics-page/themed-item-statistics-page.component.ts +++ b/src/app/statistics-page/item-statistics-page/themed-item-statistics-page.component.ts @@ -2,15 +2,14 @@ import { Component } from '@angular/core'; import { ThemedComponent } from '../../shared/theme-support/themed.component'; import { ItemStatisticsPageComponent } from './item-statistics-page.component'; +/** + * Themed wrapper for ItemStatisticsPageComponent + */ @Component({ selector: 'ds-themed-item-statistics-page', styleUrls: [], templateUrl: '../../shared/theme-support/themed.component.html', }) - -/** - * Component to render the news section on the home page - */ export class ThemedItemStatisticsPageComponent extends ThemedComponent { protected getComponentName(): string { return 'ItemStatisticsPageComponent'; diff --git a/src/app/statistics-page/site-statistics-page/themed-site-statistics-page.component.ts b/src/app/statistics-page/site-statistics-page/themed-site-statistics-page.component.ts index 4238cc788a..3f841163ed 100644 --- a/src/app/statistics-page/site-statistics-page/themed-site-statistics-page.component.ts +++ b/src/app/statistics-page/site-statistics-page/themed-site-statistics-page.component.ts @@ -2,15 +2,14 @@ import { Component } from '@angular/core'; import { ThemedComponent } from '../../shared/theme-support/themed.component'; import { SiteStatisticsPageComponent } from './site-statistics-page.component'; +/** + * Themed wrapper for SiteStatisticsPageComponent + */ @Component({ selector: 'ds-themed-site-statistics-page', styleUrls: [], templateUrl: '../../shared/theme-support/themed.component.html', }) - -/** - * Component to render the news section on the home page - */ export class ThemedSiteStatisticsPageComponent extends ThemedComponent { protected getComponentName(): string { return 'SiteStatisticsPageComponent'; From 06cac3203c8dc7bc0af9e04230c988ce7c52fb3c Mon Sep 17 00:00:00 2001 From: Raf Ponsaerts Date: Thu, 18 Mar 2021 16:08:43 +0100 Subject: [PATCH 090/132] fixed compiling issue --- src/themes/custom/theme.module.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/themes/custom/theme.module.ts b/src/themes/custom/theme.module.ts index 1f451df1bc..095d4dde95 100644 --- a/src/themes/custom/theme.module.ts +++ b/src/themes/custom/theme.module.ts @@ -1,6 +1,5 @@ import { NgModule } from '@angular/core'; import { CommonModule } from '@angular/common'; -import { AdminAccessControlModule } from '../../app/+admin/admin-access-control/admin-access-control.module'; import { AdminRegistriesModule } from '../../app/+admin/admin-registries/admin-registries.module'; import { AdminSearchModule } from '../../app/+admin/admin-search-page/admin-search.module'; import { AdminWorkflowModuleModule } from '../../app/+admin/admin-workflow-page/admin-workflow.module'; @@ -37,6 +36,7 @@ import { AppModule } from '../../app/app.module'; import { PublicationComponent } from './app/+item-page/simple/item-types/publication/publication.component'; import { ItemPageModule } from '../../app/+item-page/item-page.module'; import { RouterModule } from '@angular/router'; +import { AccessControlModule } from "../../app/access-control/access-control.module"; const DECLARATIONS = [ HomePageComponent, @@ -47,7 +47,7 @@ const DECLARATIONS = [ @NgModule({ imports: [ - AdminAccessControlModule, + AccessControlModule, AdminRegistriesModule, AdminSearchModule, AdminWorkflowModuleModule, From 0488cd6b45b8796b738d98689b73f07554e5bdf6 Mon Sep 17 00:00:00 2001 From: lotte Date: Tue, 16 Mar 2021 18:01:47 +0100 Subject: [PATCH 091/132] Solved lgtm and regex sanitization issues --- src/app/core/auth/auth.interceptor.ts | 2 +- src/app/core/shared/metadata.utils.spec.ts | 8 ++++++++ src/app/core/shared/metadata.utils.ts | 2 +- 3 files changed, 10 insertions(+), 2 deletions(-) diff --git a/src/app/core/auth/auth.interceptor.ts b/src/app/core/auth/auth.interceptor.ts index 31de304665..7b9a08de92 100644 --- a/src/app/core/auth/auth.interceptor.ts +++ b/src/app/core/auth/auth.interceptor.ts @@ -102,7 +102,7 @@ export class AuthInterceptor implements HttpInterceptor { private parseLocation(header: string): string { let location = header.trim(); location = location.replace('location="', ''); - location = location.replace('"', ''); + location = location.replace('"', ''); /* lgtm [js/incomplete-sanitization] */ let re = /%3A%2F%2F/g; location = location.replace(re, '://'); re = /%3A/g; diff --git a/src/app/core/shared/metadata.utils.spec.ts b/src/app/core/shared/metadata.utils.spec.ts index ec0b3dd3ba..d9068dd900 100644 --- a/src/app/core/shared/metadata.utils.spec.ts +++ b/src/app/core/shared/metadata.utils.spec.ts @@ -20,6 +20,7 @@ const dcTitle0 = mdValue('Title 0'); const dcTitle1 = mdValue('Title 1'); const dcTitle2 = mdValue('Title 2', 'en_US'); const bar = mdValue('Bar'); +const test = mdValue('Test'); const singleMap = { 'dc.title': [dcTitle0] }; @@ -30,6 +31,10 @@ const multiMap = { 'foo': [bar] }; +const regexTestMap = { + 'foolbar.baz': [test] +}; + const multiViewModelList = [ { key: 'dc.description', ...dcDescription, order: 0 }, { key: 'dc.description.abstract', ...dcAbstract, order: 0 }, @@ -98,6 +103,9 @@ describe('Metadata', () => { testAll([multiMap, singleMap], 'dc.*', [dcDescription, dcAbstract, dcTitle1, dcTitle2]); testAll([multiMap, singleMap], ['dc.title', 'dc.*'], [dcTitle1, dcTitle2, dcDescription, dcAbstract]); }); + describe('with regexTestMap', () => { + testAll(regexTestMap, 'foo.bar.*', []); + }); }); describe('allValues method', () => { diff --git a/src/app/core/shared/metadata.utils.ts b/src/app/core/shared/metadata.utils.ts index 612fba1d4a..6e69109dd7 100644 --- a/src/app/core/shared/metadata.utils.ts +++ b/src/app/core/shared/metadata.utils.ts @@ -156,7 +156,7 @@ export class Metadata { const outputKeys: string[] = []; for (const inputKey of inputKeys) { if (inputKey.includes('*')) { - const inputKeyRegex = new RegExp('^' + inputKey.replace('.', '\.').replace('*', '.*') + '$'); + const inputKeyRegex = new RegExp('^' + inputKey.replace('.', '\\.').replace('*', '.*') + '$'); for (const mapKey of Object.keys(mdMap)) { if (!outputKeys.includes(mapKey) && inputKeyRegex.test(mapKey)) { outputKeys.push(mapKey); From b833407dd1050e919edc33322d4ce5f53f9d9ea2 Mon Sep 17 00:00:00 2001 From: lotte Date: Tue, 16 Mar 2021 16:46:58 +0100 Subject: [PATCH 092/132] 77472: Fix unclickable titles in search lists --- ...arch-result-list-element.component.spec.ts | 5 +++- ...arch-result-list-element.component.spec.ts | 5 +++- ...arch-result-list-element.component.spec.ts | 5 +++- ...in-workflow-list-element.component.spec.ts | 3 +++ ...t-admin-workflow-list-element.component.ts | 8 ++++-- .../core/breadcrumbs/dso-name.service.spec.ts | 2 +- src/app/core/breadcrumbs/dso-name.service.ts | 7 ++++- ...arch-result-list-element.component.spec.ts | 5 +++- ...arch-result-list-element.component.spec.ts | 5 +++- ...arch-result-list-element.component.spec.ts | 5 +++- ...arch-result-list-element.component.spec.ts | 5 +++- ...arch-result-list-element.component.spec.ts | 5 +++- ...arch-result-list-element.component.spec.ts | 5 +++- ...n-sidebar-search-list-element.component.ts | 7 +++-- ...-list-submission-element.component.spec.ts | 3 +++ ...esult-list-submission-element.component.ts | 8 ++++-- ...esult-list-submission-element.component.ts | 8 ++++-- src/app/shared/mocks/dso-name.service.mock.ts | 9 +++++++ ...ch-result-detail-element.component.spec.ts | 5 +++- ...ch-result-detail-element.component.spec.ts | 5 +++- ...ch-result-detail-element.component.spec.ts | 5 +++- ...arch-result-list-element.component.spec.ts | 5 +++- ...ed-search-result-list-element.component.ts | 6 +++-- ...arch-result-list-element.component.spec.ts | 5 +++- ...ed-search-result-list-element.component.ts | 6 +++-- ...arch-result-list-element.component.spec.ts | 5 +++- ...ed-search-result-list-element.component.ts | 6 +++-- ...-list-element-submission.component.spec.ts | 3 +++ ...arch-result-list-element.component.spec.ts | 5 +++- ...ol-search-result-list-element.component.ts | 6 +++-- ...arch-result-list-element.component.spec.ts | 3 +++ ...em-search-result-list-element.component.ts | 6 +++-- ...arch-result-list-element.component.spec.ts | 3 +++ ...em-search-result-list-element.component.ts | 6 +++-- ...-search-result-list-element.component.html | 4 +-- ...arch-result-list-element.component.spec.ts | 3 +++ ...-search-result-list-element.component.html | 4 +-- ...arch-result-list-element.component.spec.ts | 3 +++ ...-search-result-list-element.component.html | 8 +++--- ...arch-result-list-element.component.spec.ts | 27 ++++++++++++------- .../search-result-list-element.component.ts | 5 +++- ...ebar-search-list-element.component.spec.ts | 3 +++ .../sidebar-search-list-element.component.ts | 7 +++-- src/assets/i18n/en.json5 | 4 +++ 44 files changed, 190 insertions(+), 58 deletions(-) create mode 100644 src/app/shared/mocks/dso-name.service.mock.ts diff --git a/src/app/+admin/admin-search-page/admin-search-results/admin-search-result-list-element/collection-search-result/collection-admin-search-result-list-element.component.spec.ts b/src/app/+admin/admin-search-page/admin-search-results/admin-search-result-list-element/collection-search-result/collection-admin-search-result-list-element.component.spec.ts index 218cbc0ca2..56e25264cf 100644 --- a/src/app/+admin/admin-search-page/admin-search-results/admin-search-result-list-element/collection-search-result/collection-admin-search-result-list-element.component.spec.ts +++ b/src/app/+admin/admin-search-page/admin-search-results/admin-search-result-list-element/collection-search-result/collection-admin-search-result-list-element.component.spec.ts @@ -11,6 +11,8 @@ import { Collection } from '../../../../../core/shared/collection.model'; import { By } from '@angular/platform-browser'; import { RouterTestingModule } from '@angular/router/testing'; import { getCollectionEditRoute } from '../../../../../+collection-page/collection-page-routing-paths'; +import { DSONameService } from '../../../../../core/breadcrumbs/dso-name.service'; +import { DSONameServiceMock } from '../../../../../shared/mocks/dso-name.service.mock'; describe('CollectionAdminSearchResultListElementComponent', () => { let component: CollectionAdminSearchResultListElementComponent; @@ -33,7 +35,8 @@ describe('CollectionAdminSearchResultListElementComponent', () => { RouterTestingModule.withRoutes([]) ], declarations: [CollectionAdminSearchResultListElementComponent], - providers: [{ provide: TruncatableService, useValue: {} }], + providers: [{ provide: TruncatableService, useValue: {} }, + { provide: DSONameService, useClass: DSONameServiceMock }], schemas: [NO_ERRORS_SCHEMA] }) .compileComponents(); diff --git a/src/app/+admin/admin-search-page/admin-search-results/admin-search-result-list-element/community-search-result/community-admin-search-result-list-element.component.spec.ts b/src/app/+admin/admin-search-page/admin-search-results/admin-search-result-list-element/community-search-result/community-admin-search-result-list-element.component.spec.ts index 69fe8856dd..29d9925326 100644 --- a/src/app/+admin/admin-search-page/admin-search-results/admin-search-result-list-element/community-search-result/community-admin-search-result-list-element.component.spec.ts +++ b/src/app/+admin/admin-search-page/admin-search-results/admin-search-result-list-element/community-search-result/community-admin-search-result-list-element.component.spec.ts @@ -11,6 +11,8 @@ import { CommunityAdminSearchResultListElementComponent } from './community-admi import { CommunitySearchResult } from '../../../../../shared/object-collection/shared/community-search-result.model'; import { Community } from '../../../../../core/shared/community.model'; import { getCommunityEditRoute } from '../../../../../+community-page/community-page-routing-paths'; +import { DSONameService } from '../../../../../core/breadcrumbs/dso-name.service'; +import { DSONameServiceMock } from '../../../../../shared/mocks/dso-name.service.mock'; describe('CommunityAdminSearchResultListElementComponent', () => { let component: CommunityAdminSearchResultListElementComponent; @@ -33,7 +35,8 @@ describe('CommunityAdminSearchResultListElementComponent', () => { RouterTestingModule.withRoutes([]) ], declarations: [CommunityAdminSearchResultListElementComponent], - providers: [{ provide: TruncatableService, useValue: {} }], + providers: [{ provide: TruncatableService, useValue: {} }, + { provide: DSONameService, useClass: DSONameServiceMock }], schemas: [NO_ERRORS_SCHEMA] }) .compileComponents(); diff --git a/src/app/+admin/admin-search-page/admin-search-results/admin-search-result-list-element/item-search-result/item-admin-search-result-list-element.component.spec.ts b/src/app/+admin/admin-search-page/admin-search-results/admin-search-result-list-element/item-search-result/item-admin-search-result-list-element.component.spec.ts index 1d2f25c2eb..3774a07757 100644 --- a/src/app/+admin/admin-search-page/admin-search-results/admin-search-result-list-element/item-search-result/item-admin-search-result-list-element.component.spec.ts +++ b/src/app/+admin/admin-search-page/admin-search-results/admin-search-result-list-element/item-search-result/item-admin-search-result-list-element.component.spec.ts @@ -8,6 +8,8 @@ import { RouterTestingModule } from '@angular/router/testing'; import { ItemSearchResult } from '../../../../../shared/object-collection/shared/item-search-result.model'; import { ItemAdminSearchResultListElementComponent } from './item-admin-search-result-list-element.component'; import { Item } from '../../../../../core/shared/item.model'; +import { DSONameService } from '../../../../../core/breadcrumbs/dso-name.service'; +import { DSONameServiceMock } from '../../../../../shared/mocks/dso-name.service.mock'; describe('ItemAdminSearchResultListElementComponent', () => { let component: ItemAdminSearchResultListElementComponent; @@ -30,7 +32,8 @@ describe('ItemAdminSearchResultListElementComponent', () => { RouterTestingModule.withRoutes([]) ], declarations: [ItemAdminSearchResultListElementComponent], - providers: [{ provide: TruncatableService, useValue: {} }], + providers: [{ provide: TruncatableService, useValue: {} }, + { provide: DSONameService, useClass: DSONameServiceMock }], schemas: [NO_ERRORS_SCHEMA] }) .compileComponents(); diff --git a/src/app/+admin/admin-workflow-page/admin-workflow-search-results/admin-workflow-search-result-list-element/workflow-item/workflow-item-search-result-admin-workflow-list-element.component.spec.ts b/src/app/+admin/admin-workflow-page/admin-workflow-search-results/admin-workflow-search-result-list-element/workflow-item/workflow-item-search-result-admin-workflow-list-element.component.spec.ts index 47907999a2..a792a606e9 100644 --- a/src/app/+admin/admin-workflow-page/admin-workflow-search-results/admin-workflow-search-result-list-element/workflow-item/workflow-item-search-result-admin-workflow-list-element.component.spec.ts +++ b/src/app/+admin/admin-workflow-page/admin-workflow-search-results/admin-workflow-search-result-list-element/workflow-item/workflow-item-search-result-admin-workflow-list-element.component.spec.ts @@ -16,6 +16,8 @@ import { Item } from '../../../../../core/shared/item.model'; import { WorkflowItemSearchResult } from '../../../../../shared/object-collection/shared/workflow-item-search-result.model'; import { createSuccessfulRemoteDataObject$ } from '../../../../../shared/remote-data.utils'; import { getMockLinkService } from '../../../../../shared/mocks/link-service.mock'; +import { DSONameService } from '../../../../../core/breadcrumbs/dso-name.service'; +import { DSONameServiceMock } from '../../../../../shared/mocks/dso-name.service.mock'; describe('WorkflowItemAdminWorkflowListElementComponent', () => { let component: WorkflowItemSearchResultAdminWorkflowListElementComponent; @@ -49,6 +51,7 @@ describe('WorkflowItemAdminWorkflowListElementComponent', () => { providers: [ { provide: TruncatableService, useValue: mockTruncatableService }, { provide: LinkService, useValue: linkService }, + { provide: DSONameService, useClass: DSONameServiceMock } ], schemas: [NO_ERRORS_SCHEMA] }) diff --git a/src/app/+admin/admin-workflow-page/admin-workflow-search-results/admin-workflow-search-result-list-element/workflow-item/workflow-item-search-result-admin-workflow-list-element.component.ts b/src/app/+admin/admin-workflow-page/admin-workflow-search-results/admin-workflow-search-result-list-element/workflow-item/workflow-item-search-result-admin-workflow-list-element.component.ts index 80225db09f..3dd17faf25 100644 --- a/src/app/+admin/admin-workflow-page/admin-workflow-search-results/admin-workflow-search-result-list-element/workflow-item/workflow-item-search-result-admin-workflow-list-element.component.ts +++ b/src/app/+admin/admin-workflow-page/admin-workflow-search-results/admin-workflow-search-result-list-element/workflow-item/workflow-item-search-result-admin-workflow-list-element.component.ts @@ -12,6 +12,7 @@ import { Item } from '../../../../../core/shared/item.model'; import { SearchResultListElementComponent } from '../../../../../shared/object-list/search-result-list-element/search-result-list-element.component'; import { TruncatableService } from '../../../../../shared/truncatable/truncatable.service'; import { WorkflowItemSearchResult } from '../../../../../shared/object-collection/shared/workflow-item-search-result.model'; +import { DSONameService } from '../../../../../core/breadcrumbs/dso-name.service'; @listableObjectComponent(WorkflowItemSearchResult, ViewMode.ListElement, Context.AdminWorkflowSearch) @Component({ @@ -29,8 +30,11 @@ export class WorkflowItemSearchResultAdminWorkflowListElementComponent extends S */ public item$: Observable; - constructor(private linkService: LinkService, protected truncatableService: TruncatableService) { - super(truncatableService); + constructor(private linkService: LinkService, + protected truncatableService: TruncatableService, + protected dsoNameService: DSONameService + ) { + super(truncatableService, dsoNameService); } /** diff --git a/src/app/core/breadcrumbs/dso-name.service.spec.ts b/src/app/core/breadcrumbs/dso-name.service.spec.ts index 5dd02032b9..7a399ce748 100644 --- a/src/app/core/breadcrumbs/dso-name.service.spec.ts +++ b/src/app/core/breadcrumbs/dso-name.service.spec.ts @@ -45,7 +45,7 @@ describe(`DSONameService`, () => { } }); - service = new DSONameService(); + service = new DSONameService({ instant: (a) => a } as any); }); describe(`getName`, () => { diff --git a/src/app/core/breadcrumbs/dso-name.service.ts b/src/app/core/breadcrumbs/dso-name.service.ts index 7f8af2352b..38363d1989 100644 --- a/src/app/core/breadcrumbs/dso-name.service.ts +++ b/src/app/core/breadcrumbs/dso-name.service.ts @@ -1,6 +1,7 @@ import { Injectable } from '@angular/core'; import { hasValue } from '../../shared/empty.util'; import { DSpaceObject } from '../shared/dspace-object.model'; +import { TranslateService } from '@ngx-translate/core'; /** * Returns a name for a {@link DSpaceObject} based @@ -11,6 +12,10 @@ import { DSpaceObject } from '../shared/dspace-object.model'; }) export class DSONameService { + constructor(private translateService: TranslateService) { + + } + /** * Functions to generate the specific names. * @@ -29,7 +34,7 @@ export class DSONameService { }, Default: (dso: DSpaceObject): string => { // If object doesn't have dc.title metadata use name property - return dso.firstMetadataValue('dc.title') || dso.name; + return dso.firstMetadataValue('dc.title') || dso.name || this.translateService.instant('dso.name.untitled'); } }; diff --git a/src/app/entity-groups/journal-entities/item-list-elements/search-result-list-elements/journal-issue/journal-issue-search-result-list-element.component.spec.ts b/src/app/entity-groups/journal-entities/item-list-elements/search-result-list-elements/journal-issue/journal-issue-search-result-list-element.component.spec.ts index 9f15cc9816..b47a767be2 100644 --- a/src/app/entity-groups/journal-entities/item-list-elements/search-result-list-elements/journal-issue/journal-issue-search-result-list-element.component.spec.ts +++ b/src/app/entity-groups/journal-entities/item-list-elements/search-result-list-elements/journal-issue/journal-issue-search-result-list-element.component.spec.ts @@ -7,6 +7,8 @@ import { JournalIssueSearchResultListElementComponent } from './journal-issue-se import { Item } from '../../../../../core/shared/item.model'; import { TruncatePipe } from '../../../../../shared/utils/truncate.pipe'; import { TruncatableService } from '../../../../../shared/truncatable/truncatable.service'; +import { DSONameService } from '../../../../../core/breadcrumbs/dso-name.service'; +import { DSONameServiceMock } from '../../../../../shared/mocks/dso-name.service.mock'; let journalIssueListElementComponent: JournalIssueSearchResultListElementComponent; let fixture: ComponentFixture; @@ -60,7 +62,8 @@ describe('JournalIssueSearchResultListElementComponent', () => { TestBed.configureTestingModule({ declarations: [JournalIssueSearchResultListElementComponent, TruncatePipe], providers: [ - { provide: TruncatableService, useValue: {} } + { provide: TruncatableService, useValue: {} }, + { provide: DSONameService, useClass: DSONameServiceMock } ], schemas: [NO_ERRORS_SCHEMA] diff --git a/src/app/entity-groups/journal-entities/item-list-elements/search-result-list-elements/journal-volume/journal-volume-search-result-list-element.component.spec.ts b/src/app/entity-groups/journal-entities/item-list-elements/search-result-list-elements/journal-volume/journal-volume-search-result-list-element.component.spec.ts index b39129fbd2..d03bc29d6b 100644 --- a/src/app/entity-groups/journal-entities/item-list-elements/search-result-list-elements/journal-volume/journal-volume-search-result-list-element.component.spec.ts +++ b/src/app/entity-groups/journal-entities/item-list-elements/search-result-list-elements/journal-volume/journal-volume-search-result-list-element.component.spec.ts @@ -7,6 +7,8 @@ import { Item } from '../../../../../core/shared/item.model'; import { JournalVolumeSearchResultListElementComponent } from './journal-volume-search-result-list-element.component'; import { TruncatePipe } from '../../../../../shared/utils/truncate.pipe'; import { TruncatableService } from '../../../../../shared/truncatable/truncatable.service'; +import { DSONameService } from '../../../../../core/breadcrumbs/dso-name.service'; +import { DSONameServiceMock } from '../../../../../shared/mocks/dso-name.service.mock'; let journalVolumeListElementComponent: JournalVolumeSearchResultListElementComponent; let fixture: ComponentFixture; @@ -59,7 +61,8 @@ describe('JournalVolumeSearchResultListElementComponent', () => { TestBed.configureTestingModule({ declarations: [JournalVolumeSearchResultListElementComponent, TruncatePipe], providers: [ - { provide: TruncatableService, useValue: {} } + { provide: TruncatableService, useValue: {} }, + { provide: DSONameService, useClass: DSONameServiceMock }, ], schemas: [NO_ERRORS_SCHEMA] diff --git a/src/app/entity-groups/journal-entities/item-list-elements/search-result-list-elements/journal/journal-search-result-list-element.component.spec.ts b/src/app/entity-groups/journal-entities/item-list-elements/search-result-list-elements/journal/journal-search-result-list-element.component.spec.ts index 5ab60e97b7..9aca414ec6 100644 --- a/src/app/entity-groups/journal-entities/item-list-elements/search-result-list-elements/journal/journal-search-result-list-element.component.spec.ts +++ b/src/app/entity-groups/journal-entities/item-list-elements/search-result-list-elements/journal/journal-search-result-list-element.component.spec.ts @@ -7,6 +7,8 @@ import { Item } from '../../../../../core/shared/item.model'; import { TruncatePipe } from '../../../../../shared/utils/truncate.pipe'; import { TruncatableService } from '../../../../../shared/truncatable/truncatable.service'; import { ItemSearchResult } from '../../../../../shared/object-collection/shared/item-search-result.model'; +import { DSONameService } from '../../../../../core/breadcrumbs/dso-name.service'; +import { DSONameServiceMock } from '../../../../../shared/mocks/dso-name.service.mock'; let journalListElementComponent: JournalSearchResultListElementComponent; let fixture: ComponentFixture; @@ -55,7 +57,8 @@ describe('JournalSearchResultListElementComponent', () => { TestBed.configureTestingModule({ declarations: [JournalSearchResultListElementComponent, TruncatePipe], providers: [ - { provide: TruncatableService, useValue: {} } + { provide: TruncatableService, useValue: {} }, + { provide: DSONameService, useClass: DSONameServiceMock }, ], schemas: [NO_ERRORS_SCHEMA] diff --git a/src/app/entity-groups/research-entities/item-list-elements/search-result-list-elements/org-unit/org-unit-search-result-list-element.component.spec.ts b/src/app/entity-groups/research-entities/item-list-elements/search-result-list-elements/org-unit/org-unit-search-result-list-element.component.spec.ts index 29bb069121..d116b2ade7 100644 --- a/src/app/entity-groups/research-entities/item-list-elements/search-result-list-elements/org-unit/org-unit-search-result-list-element.component.spec.ts +++ b/src/app/entity-groups/research-entities/item-list-elements/search-result-list-elements/org-unit/org-unit-search-result-list-element.component.spec.ts @@ -7,6 +7,8 @@ import { Item } from '../../../../../core/shared/item.model'; import { TruncatePipe } from '../../../../../shared/utils/truncate.pipe'; import { TruncatableService } from '../../../../../shared/truncatable/truncatable.service'; import { ItemSearchResult } from '../../../../../shared/object-collection/shared/item-search-result.model'; +import { DSONameService } from '../../../../../core/breadcrumbs/dso-name.service'; +import { DSONameServiceMock } from '../../../../../shared/mocks/dso-name.service.mock'; let orgUnitListElementComponent: OrgUnitSearchResultListElementComponent; let fixture: ComponentFixture; @@ -53,7 +55,8 @@ describe('OrgUnitSearchResultListElementComponent', () => { TestBed.configureTestingModule({ declarations: [ OrgUnitSearchResultListElementComponent , TruncatePipe], providers: [ - { provide: TruncatableService, useValue: {} } + { provide: TruncatableService, useValue: {} }, + { provide: DSONameService, useClass: DSONameServiceMock } ], schemas: [ NO_ERRORS_SCHEMA ] diff --git a/src/app/entity-groups/research-entities/item-list-elements/search-result-list-elements/person/person-search-result-list-element.component.spec.ts b/src/app/entity-groups/research-entities/item-list-elements/search-result-list-elements/person/person-search-result-list-element.component.spec.ts index 08fdf821d3..2acb02da7d 100644 --- a/src/app/entity-groups/research-entities/item-list-elements/search-result-list-elements/person/person-search-result-list-element.component.spec.ts +++ b/src/app/entity-groups/research-entities/item-list-elements/search-result-list-elements/person/person-search-result-list-element.component.spec.ts @@ -7,6 +7,8 @@ import { PersonSearchResultListElementComponent } from './person-search-result-l import { Item } from '../../../../../core/shared/item.model'; import { TruncatePipe } from '../../../../../shared/utils/truncate.pipe'; import { TruncatableService } from '../../../../../shared/truncatable/truncatable.service'; +import { DSONameService } from '../../../../../core/breadcrumbs/dso-name.service'; +import { DSONameServiceMock } from '../../../../../shared/mocks/dso-name.service.mock'; let personListElementComponent: PersonSearchResultListElementComponent; let fixture: ComponentFixture; @@ -53,7 +55,8 @@ describe('PersonSearchResultListElementComponent', () => { TestBed.configureTestingModule({ declarations: [PersonSearchResultListElementComponent, TruncatePipe], providers: [ - { provide: TruncatableService, useValue: {} } + { provide: TruncatableService, useValue: {} }, + { provide: DSONameService, useClass: DSONameServiceMock } ], schemas: [NO_ERRORS_SCHEMA] diff --git a/src/app/entity-groups/research-entities/item-list-elements/search-result-list-elements/project/project-search-result-list-element.component.spec.ts b/src/app/entity-groups/research-entities/item-list-elements/search-result-list-elements/project/project-search-result-list-element.component.spec.ts index 1d45d98281..8b27a86f6d 100644 --- a/src/app/entity-groups/research-entities/item-list-elements/search-result-list-elements/project/project-search-result-list-element.component.spec.ts +++ b/src/app/entity-groups/research-entities/item-list-elements/search-result-list-elements/project/project-search-result-list-element.component.spec.ts @@ -6,6 +6,8 @@ import { ProjectSearchResultListElementComponent } from './project-search-result import { Item } from '../../../../../core/shared/item.model'; import { TruncatePipe } from '../../../../../shared/utils/truncate.pipe'; import { TruncatableService } from '../../../../../shared/truncatable/truncatable.service'; +import { DSONameService } from '../../../../../core/breadcrumbs/dso-name.service'; +import { DSONameServiceMock } from '../../../../../shared/mocks/dso-name.service.mock'; let projectListElementComponent: ProjectSearchResultListElementComponent; let fixture: ComponentFixture; @@ -53,7 +55,8 @@ describe('ProjectSearchResultListElementComponent', () => { TestBed.configureTestingModule({ declarations: [ProjectSearchResultListElementComponent, TruncatePipe], providers: [ - { provide: TruncatableService, useValue: {} } + { provide: TruncatableService, useValue: {} }, + { provide: DSONameService, useClass: DSONameServiceMock } ], schemas: [NO_ERRORS_SCHEMA] diff --git a/src/app/entity-groups/research-entities/item-list-elements/sidebar-search-list-elements/person/person-sidebar-search-list-element.component.ts b/src/app/entity-groups/research-entities/item-list-elements/sidebar-search-list-elements/person/person-sidebar-search-list-element.component.ts index ade080f2e2..281f22ddb4 100644 --- a/src/app/entity-groups/research-entities/item-list-elements/sidebar-search-list-elements/person/person-sidebar-search-list-element.component.ts +++ b/src/app/entity-groups/research-entities/item-list-elements/sidebar-search-list-elements/person/person-sidebar-search-list-element.component.ts @@ -9,6 +9,7 @@ import { isNotEmpty } from '../../../../../shared/empty.util'; import { TruncatableService } from '../../../../../shared/truncatable/truncatable.service'; import { LinkService } from '../../../../../core/cache/builders/link.service'; import { TranslateService } from '@ngx-translate/core'; +import { DSONameService } from '../../../../../core/breadcrumbs/dso-name.service'; @listableObjectComponent('PersonSearchResult', ViewMode.ListElement, Context.SideBarSearchModal) @listableObjectComponent('PersonSearchResult', ViewMode.ListElement, Context.SideBarSearchModalCurrent) @@ -23,8 +24,10 @@ import { TranslateService } from '@ngx-translate/core'; export class PersonSidebarSearchListElementComponent extends SidebarSearchListElementComponent { constructor(protected truncatableService: TruncatableService, protected linkService: LinkService, - protected translateService: TranslateService) { - super(truncatableService, linkService); + protected translateService: TranslateService, + protected dsoNameService: DSONameService + ) { + super(truncatableService, linkService, dsoNameService); } /** diff --git a/src/app/entity-groups/research-entities/submission/item-list-elements/org-unit/org-unit-search-result-list-submission-element.component.spec.ts b/src/app/entity-groups/research-entities/submission/item-list-elements/org-unit/org-unit-search-result-list-submission-element.component.spec.ts index ff74c6554f..13a307e18f 100644 --- a/src/app/entity-groups/research-entities/submission/item-list-elements/org-unit/org-unit-search-result-list-submission-element.component.spec.ts +++ b/src/app/entity-groups/research-entities/submission/item-list-elements/org-unit/org-unit-search-result-list-submission-element.component.spec.ts @@ -27,6 +27,8 @@ import { createSuccessfulRemoteDataObject$ } from '../../../../../shared/remote- import { TruncatableService } from '../../../../../shared/truncatable/truncatable.service'; import { TruncatePipe } from '../../../../../shared/utils/truncate.pipe'; import { OrgUnitSearchResultListSubmissionElementComponent } from './org-unit-search-result-list-submission-element.component'; +import { DSONameService } from '../../../../../core/breadcrumbs/dso-name.service'; +import { DSONameServiceMock } from '../../../../../shared/mocks/dso-name.service.mock'; let personListElementComponent: OrgUnitSearchResultListSubmissionElementComponent; let fixture: ComponentFixture; @@ -115,6 +117,7 @@ describe('OrgUnitSearchResultListSubmissionElementComponent', () => { { provide: DSOChangeAnalyzer, useValue: {} }, { provide: DefaultChangeAnalyzer, useValue: {} }, { provide: BitstreamDataService, useValue: mockBitstreamDataService }, + { provide: DSONameService, useClass: DSONameServiceMock } ], schemas: [NO_ERRORS_SCHEMA] diff --git a/src/app/entity-groups/research-entities/submission/item-list-elements/org-unit/org-unit-search-result-list-submission-element.component.ts b/src/app/entity-groups/research-entities/submission/item-list-elements/org-unit/org-unit-search-result-list-submission-element.component.ts index 0c6d2b450c..091549dcea 100644 --- a/src/app/entity-groups/research-entities/submission/item-list-elements/org-unit/org-unit-search-result-list-submission-element.component.ts +++ b/src/app/entity-groups/research-entities/submission/item-list-elements/org-unit/org-unit-search-result-list-submission-element.component.ts @@ -19,6 +19,8 @@ import { MetadataValue } from '../../../../../core/shared/metadata.models'; import { ItemDataService } from '../../../../../core/data/item-data.service'; import { SelectableListService } from '../../../../../shared/object-list/selectable-list/selectable-list.service'; import { NameVariantModalComponent } from '../../name-variant-modal/name-variant-modal.component'; +import { LinkService } from '../../../../../core/cache/builders/link.service'; +import { DSONameService } from '../../../../../core/breadcrumbs/dso-name.service'; @listableObjectComponent('OrgUnitSearchResult', ViewMode.ListElement, Context.EntitySearchModal) @listableObjectComponent('OrgUnitSearchResult', ViewMode.ListElement, Context.EntitySearchModalWithNameVariants) @@ -44,8 +46,10 @@ export class OrgUnitSearchResultListSubmissionElementComponent extends SearchRes private modalService: NgbModal, private itemDataService: ItemDataService, private bitstreamDataService: BitstreamDataService, - private selectableListService: SelectableListService) { - super(truncatableService); + private selectableListService: SelectableListService, + protected dsoNameService: DSONameService + ) { + super(truncatableService, dsoNameService); } ngOnInit() { diff --git a/src/app/entity-groups/research-entities/submission/item-list-elements/person/person-search-result-list-submission-element.component.ts b/src/app/entity-groups/research-entities/submission/item-list-elements/person/person-search-result-list-submission-element.component.ts index 96be3d1b4e..2d991d5c64 100644 --- a/src/app/entity-groups/research-entities/submission/item-list-elements/person/person-search-result-list-submission-element.component.ts +++ b/src/app/entity-groups/research-entities/submission/item-list-elements/person/person-search-result-list-submission-element.component.ts @@ -19,6 +19,8 @@ import { NameVariantModalComponent } from '../../name-variant-modal/name-variant import { MetadataValue } from '../../../../../core/shared/metadata.models'; import { ItemDataService } from '../../../../../core/data/item-data.service'; import { SelectableListService } from '../../../../../shared/object-list/selectable-list/selectable-list.service'; +import { LinkService } from '../../../../../core/cache/builders/link.service'; +import { DSONameService } from '../../../../../core/breadcrumbs/dso-name.service'; @listableObjectComponent('PersonSearchResult', ViewMode.ListElement, Context.EntitySearchModalWithNameVariants) @Component({ @@ -42,8 +44,10 @@ export class PersonSearchResultListSubmissionElementComponent extends SearchResu private modalService: NgbModal, private itemDataService: ItemDataService, private bitstreamDataService: BitstreamDataService, - private selectableListService: SelectableListService) { - super(truncatableService); + private selectableListService: SelectableListService, + protected dsoNameService: DSONameService + ) { + super(truncatableService, dsoNameService); } ngOnInit() { diff --git a/src/app/shared/mocks/dso-name.service.mock.ts b/src/app/shared/mocks/dso-name.service.mock.ts new file mode 100644 index 0000000000..f4947cc860 --- /dev/null +++ b/src/app/shared/mocks/dso-name.service.mock.ts @@ -0,0 +1,9 @@ +import { DSpaceObject } from '../../core/shared/dspace-object.model'; + +export const UNDEFINED_NAME = 'Undefined'; + +export class DSONameServiceMock { + public getName(dso: DSpaceObject) { + return UNDEFINED_NAME; + } +} diff --git a/src/app/shared/object-detail/my-dspace-result-detail-element/pool-search-result/pool-search-result-detail-element.component.spec.ts b/src/app/shared/object-detail/my-dspace-result-detail-element/pool-search-result/pool-search-result-detail-element.component.spec.ts index f5f19fc041..8e0458d49f 100644 --- a/src/app/shared/object-detail/my-dspace-result-detail-element/pool-search-result/pool-search-result-detail-element.component.spec.ts +++ b/src/app/shared/object-detail/my-dspace-result-detail-element/pool-search-result/pool-search-result-detail-element.component.spec.ts @@ -15,6 +15,8 @@ import { VarDirective } from '../../../utils/var.directive'; import { LinkService } from '../../../../core/cache/builders/link.service'; import { getMockLinkService } from '../../../mocks/link-service.mock'; import { By } from '@angular/platform-browser'; +import { DSONameService } from '../../../../core/breadcrumbs/dso-name.service'; +import { DSONameServiceMock } from '../../../mocks/dso-name.service.mock'; let component: PoolSearchResultDetailElementComponent; let fixture: ComponentFixture; @@ -67,7 +69,8 @@ describe('PoolSearchResultDetailElementComponent', () => { providers: [ { provide: 'objectElementProvider', useValue: (mockResultObject) }, { provide: 'indexElementProvider', useValue: (compIndex) }, - { provide: LinkService, useValue: linkService } + { provide: LinkService, useValue: linkService }, + { provide: DSONameService, useClass: DSONameServiceMock }, ], schemas: [NO_ERRORS_SCHEMA] }).overrideComponent(PoolSearchResultDetailElementComponent, { diff --git a/src/app/shared/object-detail/my-dspace-result-detail-element/workflow-item-search-result/workflow-item-search-result-detail-element.component.spec.ts b/src/app/shared/object-detail/my-dspace-result-detail-element/workflow-item-search-result/workflow-item-search-result-detail-element.component.spec.ts index 8745697fbe..536bd6d0bb 100644 --- a/src/app/shared/object-detail/my-dspace-result-detail-element/workflow-item-search-result/workflow-item-search-result-detail-element.component.spec.ts +++ b/src/app/shared/object-detail/my-dspace-result-detail-element/workflow-item-search-result/workflow-item-search-result-detail-element.component.spec.ts @@ -12,6 +12,8 @@ import { createSuccessfulRemoteDataObject } from '../../../remote-data.utils'; import { WorkflowItemSearchResult } from '../../../object-collection/shared/workflow-item-search-result.model'; import { getMockLinkService } from '../../../mocks/link-service.mock'; import { LinkService } from '../../../../core/cache/builders/link.service'; +import { DSONameService } from '../../../../core/breadcrumbs/dso-name.service'; +import { DSONameServiceMock } from '../../../mocks/dso-name.service.mock'; let component: WorkflowItemSearchResultDetailElementComponent; let fixture: ComponentFixture; @@ -62,7 +64,8 @@ describe('WorkflowItemSearchResultDetailElementComponent', () => { providers: [ { provide: 'objectElementProvider', useValue: (mockResultObject) }, { provide: 'indexElementProvider', useValue: (compIndex) }, - { provide: LinkService, useValue: linkService } + { provide: LinkService, useValue: linkService }, + { provide: DSONameService, useClass: DSONameServiceMock }, ], schemas: [NO_ERRORS_SCHEMA] }).overrideComponent(WorkflowItemSearchResultDetailElementComponent, { diff --git a/src/app/shared/object-detail/my-dspace-result-detail-element/workspace-item-search-result/workspace-item-search-result-detail-element.component.spec.ts b/src/app/shared/object-detail/my-dspace-result-detail-element/workspace-item-search-result/workspace-item-search-result-detail-element.component.spec.ts index 1662e033d7..00a20b006a 100644 --- a/src/app/shared/object-detail/my-dspace-result-detail-element/workspace-item-search-result/workspace-item-search-result-detail-element.component.spec.ts +++ b/src/app/shared/object-detail/my-dspace-result-detail-element/workspace-item-search-result/workspace-item-search-result-detail-element.component.spec.ts @@ -12,6 +12,8 @@ import { createSuccessfulRemoteDataObject } from '../../../remote-data.utils'; import { WorkflowItemSearchResult } from '../../../object-collection/shared/workflow-item-search-result.model'; import { getMockLinkService } from '../../../mocks/link-service.mock'; import { LinkService } from '../../../../core/cache/builders/link.service'; +import { DSONameService } from '../../../../core/breadcrumbs/dso-name.service'; +import { DSONameServiceMock } from '../../../mocks/dso-name.service.mock'; let component: WorkspaceItemSearchResultDetailElementComponent; let fixture: ComponentFixture; @@ -62,7 +64,8 @@ describe('WorkspaceItemSearchResultDetailElementComponent', () => { providers: [ { provide: 'objectElementProvider', useValue: (mockResultObject) }, { provide: 'indexElementProvider', useValue: (compIndex) }, - { provide: LinkService, useValue: linkService } + { provide: LinkService, useValue: linkService }, + { provide: DSONameService, useClass: DSONameServiceMock }, ], schemas: [NO_ERRORS_SCHEMA] }).overrideComponent(WorkspaceItemSearchResultDetailElementComponent, { diff --git a/src/app/shared/object-list/my-dspace-result-list-element/claimed-search-result/claimed-approved-search-result/claimed-approved-search-result-list-element.component.spec.ts b/src/app/shared/object-list/my-dspace-result-list-element/claimed-search-result/claimed-approved-search-result/claimed-approved-search-result-list-element.component.spec.ts index e56999472e..b85b31c8ba 100644 --- a/src/app/shared/object-list/my-dspace-result-list-element/claimed-search-result/claimed-approved-search-result/claimed-approved-search-result-list-element.component.spec.ts +++ b/src/app/shared/object-list/my-dspace-result-list-element/claimed-search-result/claimed-approved-search-result/claimed-approved-search-result-list-element.component.spec.ts @@ -15,6 +15,8 @@ import { LinkService } from '../../../../../core/cache/builders/link.service'; import { MyDspaceItemStatusType } from '../../../../object-collection/shared/mydspace-item-status/my-dspace-item-status-type'; import { ClaimedApprovedTaskSearchResult } from '../../../../object-collection/shared/claimed-approved-task-search-result.model'; import { ClaimedApprovedSearchResultListElementComponent } from './claimed-approved-search-result-list-element.component'; +import { DSONameService } from '../../../../../core/breadcrumbs/dso-name.service'; +import { DSONameServiceMock } from '../../../../mocks/dso-name.service.mock'; let component: ClaimedApprovedSearchResultListElementComponent; let fixture: ComponentFixture; @@ -64,7 +66,8 @@ describe('ClaimedApprovedSearchResultListElementComponent', () => { declarations: [ClaimedApprovedSearchResultListElementComponent, VarDirective], providers: [ { provide: TruncatableService, useValue: {} }, - { provide: LinkService, useValue: linkService } + { provide: LinkService, useValue: linkService }, + { provide: DSONameService, useClass: DSONameServiceMock } ], schemas: [NO_ERRORS_SCHEMA] }).overrideComponent(ClaimedApprovedSearchResultListElementComponent, { diff --git a/src/app/shared/object-list/my-dspace-result-list-element/claimed-search-result/claimed-approved-search-result/claimed-approved-search-result-list-element.component.ts b/src/app/shared/object-list/my-dspace-result-list-element/claimed-search-result/claimed-approved-search-result/claimed-approved-search-result-list-element.component.ts index 36e468808a..5571782ce2 100644 --- a/src/app/shared/object-list/my-dspace-result-list-element/claimed-search-result/claimed-approved-search-result/claimed-approved-search-result-list-element.component.ts +++ b/src/app/shared/object-list/my-dspace-result-list-element/claimed-search-result/claimed-approved-search-result/claimed-approved-search-result-list-element.component.ts @@ -12,6 +12,7 @@ import { followLink } from '../../../../utils/follow-link-config.model'; import { SearchResultListElementComponent } from '../../../search-result-list-element/search-result-list-element.component'; import { ClaimedTaskSearchResult } from '../../../../object-collection/shared/claimed-task-search-result.model'; import { ClaimedTask } from '../../../../../core/tasks/models/claimed-task-object.model'; +import { DSONameService } from '../../../../../core/breadcrumbs/dso-name.service'; /** * This component renders claimed task approved object for the search result in the list view. @@ -41,9 +42,10 @@ export class ClaimedApprovedSearchResultListElementComponent extends SearchResul public constructor( protected linkService: LinkService, - protected truncatableService: TruncatableService + protected truncatableService: TruncatableService, + protected dsoNameService: DSONameService ) { - super(truncatableService); + super(truncatableService, dsoNameService); } /** diff --git a/src/app/shared/object-list/my-dspace-result-list-element/claimed-search-result/claimed-declined-search-result/claimed-declided-search-result-list-element.component.spec.ts b/src/app/shared/object-list/my-dspace-result-list-element/claimed-search-result/claimed-declined-search-result/claimed-declided-search-result-list-element.component.spec.ts index 8a8d542063..291c8244b7 100644 --- a/src/app/shared/object-list/my-dspace-result-list-element/claimed-search-result/claimed-declined-search-result/claimed-declided-search-result-list-element.component.spec.ts +++ b/src/app/shared/object-list/my-dspace-result-list-element/claimed-search-result/claimed-declined-search-result/claimed-declided-search-result-list-element.component.spec.ts @@ -15,6 +15,8 @@ import { VarDirective } from '../../../../utils/var.directive'; import { TruncatableService } from '../../../../truncatable/truncatable.service'; import { LinkService } from '../../../../../core/cache/builders/link.service'; import { MyDspaceItemStatusType } from '../../../../object-collection/shared/mydspace-item-status/my-dspace-item-status-type'; +import { DSONameService } from '../../../../../core/breadcrumbs/dso-name.service'; +import { DSONameServiceMock } from '../../../../mocks/dso-name.service.mock'; let component: ClaimedDeclinedSearchResultListElementComponent; let fixture: ComponentFixture; @@ -64,7 +66,8 @@ describe('ClaimedDeclinedSearchResultListElementComponent', () => { declarations: [ClaimedDeclinedSearchResultListElementComponent, VarDirective], providers: [ { provide: TruncatableService, useValue: {} }, - { provide: LinkService, useValue: linkService } + { provide: LinkService, useValue: linkService }, + { provide: DSONameService, useClass: DSONameServiceMock } ], schemas: [NO_ERRORS_SCHEMA] }).overrideComponent(ClaimedDeclinedSearchResultListElementComponent, { diff --git a/src/app/shared/object-list/my-dspace-result-list-element/claimed-search-result/claimed-declined-search-result/claimed-declined-search-result-list-element.component.ts b/src/app/shared/object-list/my-dspace-result-list-element/claimed-search-result/claimed-declined-search-result/claimed-declined-search-result-list-element.component.ts index 7db12c1725..630aa699a7 100644 --- a/src/app/shared/object-list/my-dspace-result-list-element/claimed-search-result/claimed-declined-search-result/claimed-declined-search-result-list-element.component.ts +++ b/src/app/shared/object-list/my-dspace-result-list-element/claimed-search-result/claimed-declined-search-result/claimed-declined-search-result-list-element.component.ts @@ -13,6 +13,7 @@ import { followLink } from '../../../../utils/follow-link-config.model'; import { SearchResultListElementComponent } from '../../../search-result-list-element/search-result-list-element.component'; import { ClaimedTaskSearchResult } from '../../../../object-collection/shared/claimed-task-search-result.model'; import { ClaimedTask } from '../../../../../core/tasks/models/claimed-task-object.model'; +import { DSONameService } from '../../../../../core/breadcrumbs/dso-name.service'; /** * This component renders claimed task declined object for the search result in the list view. @@ -42,9 +43,10 @@ export class ClaimedDeclinedSearchResultListElementComponent extends SearchResul public constructor( protected linkService: LinkService, - protected truncatableService: TruncatableService + protected truncatableService: TruncatableService, + protected dsoNameService: DSONameService ) { - super(truncatableService); + super(truncatableService, dsoNameService); } /** diff --git a/src/app/shared/object-list/my-dspace-result-list-element/claimed-search-result/claimed-search-result-list-element.component.spec.ts b/src/app/shared/object-list/my-dspace-result-list-element/claimed-search-result/claimed-search-result-list-element.component.spec.ts index 5dad421f68..7896061a73 100644 --- a/src/app/shared/object-list/my-dspace-result-list-element/claimed-search-result/claimed-search-result-list-element.component.spec.ts +++ b/src/app/shared/object-list/my-dspace-result-list-element/claimed-search-result/claimed-search-result-list-element.component.spec.ts @@ -16,6 +16,8 @@ import { VarDirective } from '../../../utils/var.directive'; import { LinkService } from '../../../../core/cache/builders/link.service'; import { getMockLinkService } from '../../../mocks/link-service.mock'; import { By } from '@angular/platform-browser'; +import { DSONameService } from '../../../../core/breadcrumbs/dso-name.service'; +import { DSONameServiceMock } from '../../../mocks/dso-name.service.mock'; let component: ClaimedSearchResultListElementComponent; let fixture: ComponentFixture; @@ -65,7 +67,8 @@ describe('ClaimedSearchResultListElementComponent', () => { declarations: [ClaimedSearchResultListElementComponent, VarDirective], providers: [ { provide: TruncatableService, useValue: {} }, - { provide: LinkService, useValue: linkService } + { provide: LinkService, useValue: linkService }, + { provide: DSONameService, useClass: DSONameServiceMock } ], schemas: [NO_ERRORS_SCHEMA] }).overrideComponent(ClaimedSearchResultListElementComponent, { diff --git a/src/app/shared/object-list/my-dspace-result-list-element/claimed-search-result/claimed-search-result-list-element.component.ts b/src/app/shared/object-list/my-dspace-result-list-element/claimed-search-result/claimed-search-result-list-element.component.ts index cef1056401..dae3272889 100644 --- a/src/app/shared/object-list/my-dspace-result-list-element/claimed-search-result/claimed-search-result-list-element.component.ts +++ b/src/app/shared/object-list/my-dspace-result-list-element/claimed-search-result/claimed-search-result-list-element.component.ts @@ -12,6 +12,7 @@ import { WorkflowItem } from '../../../../core/submission/models/workflowitem.mo import { followLink } from '../../../utils/follow-link-config.model'; import { SearchResultListElementComponent } from '../../search-result-list-element/search-result-list-element.component'; import { ClaimedTask } from '../../../../core/tasks/models/claimed-task-object.model'; +import { DSONameService } from '../../../../core/breadcrumbs/dso-name.service'; @Component({ selector: 'ds-claimed-search-result-list-element', @@ -38,9 +39,10 @@ export class ClaimedSearchResultListElementComponent extends SearchResultListEle public constructor( protected linkService: LinkService, - protected truncatableService: TruncatableService + protected truncatableService: TruncatableService, + protected dsoNameService: DSONameService ) { - super(truncatableService); + super(truncatableService, dsoNameService); } /** diff --git a/src/app/shared/object-list/my-dspace-result-list-element/item-search-result/item-search-result-list-element-submission.component.spec.ts b/src/app/shared/object-list/my-dspace-result-list-element/item-search-result/item-search-result-list-element-submission.component.spec.ts index e2017e8748..d1871d0996 100644 --- a/src/app/shared/object-list/my-dspace-result-list-element/item-search-result/item-search-result-list-element-submission.component.spec.ts +++ b/src/app/shared/object-list/my-dspace-result-list-element/item-search-result/item-search-result-list-element-submission.component.spec.ts @@ -10,6 +10,8 @@ import { ItemSearchResult } from '../../../object-collection/shared/item-search- import { ItemSearchResultListElementSubmissionComponent } from './item-search-result-list-element-submission.component'; import { TruncatableService } from '../../../truncatable/truncatable.service'; import { By } from '@angular/platform-browser'; +import { DSONameService } from '../../../../core/breadcrumbs/dso-name.service'; +import { DSONameServiceMock } from '../../../mocks/dso-name.service.mock'; let component: ItemSearchResultListElementSubmissionComponent; let fixture: ComponentFixture; @@ -54,6 +56,7 @@ describe('ItemMyDSpaceResultListElementComponent', () => { declarations: [ItemSearchResultListElementSubmissionComponent], providers: [ { provide: TruncatableService, useValue: {} }, + { provide: DSONameService, useClass: DSONameServiceMock } ], schemas: [NO_ERRORS_SCHEMA] }).overrideComponent(ItemSearchResultListElementSubmissionComponent, { diff --git a/src/app/shared/object-list/my-dspace-result-list-element/pool-search-result/pool-search-result-list-element.component.spec.ts b/src/app/shared/object-list/my-dspace-result-list-element/pool-search-result/pool-search-result-list-element.component.spec.ts index e55b45aed7..18db9abd67 100644 --- a/src/app/shared/object-list/my-dspace-result-list-element/pool-search-result/pool-search-result-list-element.component.spec.ts +++ b/src/app/shared/object-list/my-dspace-result-list-element/pool-search-result/pool-search-result-list-element.component.spec.ts @@ -16,6 +16,8 @@ import { VarDirective } from '../../../utils/var.directive'; import { LinkService } from '../../../../core/cache/builders/link.service'; import { getMockLinkService } from '../../../mocks/link-service.mock'; import { By } from '@angular/platform-browser'; +import { DSONameService } from '../../../../core/breadcrumbs/dso-name.service'; +import { DSONameServiceMock } from '../../../mocks/dso-name.service.mock'; let component: PoolSearchResultListElementComponent; let fixture: ComponentFixture; @@ -65,7 +67,8 @@ describe('PoolSearchResultListElementComponent', () => { declarations: [PoolSearchResultListElementComponent, VarDirective], providers: [ { provide: TruncatableService, useValue: {} }, - { provide: LinkService, useValue: linkService } + { provide: LinkService, useValue: linkService }, + { provide: DSONameService, useClass: DSONameServiceMock } ], schemas: [NO_ERRORS_SCHEMA] }).overrideComponent(PoolSearchResultListElementComponent, { diff --git a/src/app/shared/object-list/my-dspace-result-list-element/pool-search-result/pool-search-result-list-element.component.ts b/src/app/shared/object-list/my-dspace-result-list-element/pool-search-result/pool-search-result-list-element.component.ts index b130d5001c..fe4fa715ee 100644 --- a/src/app/shared/object-list/my-dspace-result-list-element/pool-search-result/pool-search-result-list-element.component.ts +++ b/src/app/shared/object-list/my-dspace-result-list-element/pool-search-result/pool-search-result-list-element.component.ts @@ -13,6 +13,7 @@ import { SearchResultListElementComponent } from '../../search-result-list-eleme import { TruncatableService } from '../../../truncatable/truncatable.service'; import { followLink } from '../../../utils/follow-link-config.model'; import { LinkService } from '../../../../core/cache/builders/link.service'; +import { DSONameService } from '../../../../core/breadcrumbs/dso-name.service'; /** * This component renders pool task object for the search result in the list view. @@ -48,9 +49,10 @@ export class PoolSearchResultListElementComponent extends SearchResultListElemen constructor( protected linkService: LinkService, - protected truncatableService: TruncatableService + protected truncatableService: TruncatableService, + protected dsoNameService: DSONameService ) { - super(truncatableService); + super(truncatableService, dsoNameService); } /** diff --git a/src/app/shared/object-list/my-dspace-result-list-element/workflow-item-search-result/workflow-item-search-result-list-element.component.spec.ts b/src/app/shared/object-list/my-dspace-result-list-element/workflow-item-search-result/workflow-item-search-result-list-element.component.spec.ts index 3743a9bd22..61337b0cb3 100644 --- a/src/app/shared/object-list/my-dspace-result-list-element/workflow-item-search-result/workflow-item-search-result-list-element.component.spec.ts +++ b/src/app/shared/object-list/my-dspace-result-list-element/workflow-item-search-result/workflow-item-search-result-list-element.component.spec.ts @@ -16,6 +16,8 @@ import { createSuccessfulRemoteDataObject } from '../../../remote-data.utils'; import { TruncatableService } from '../../../truncatable/truncatable.service'; import { WorkflowItemSearchResultListElementComponent } from './workflow-item-search-result-list-element.component'; import { By } from '@angular/platform-browser'; +import { DSONameService } from '../../../../core/breadcrumbs/dso-name.service'; +import { DSONameServiceMock } from '../../../mocks/dso-name.service.mock'; let component: WorkflowItemSearchResultListElementComponent; let fixture: ComponentFixture; @@ -67,6 +69,7 @@ describe('WorkflowItemSearchResultListElementComponent', () => { { provide: TruncatableService, useValue: {} }, { provide: ItemDataService, useValue: {} }, { provide: LinkService, useValue: linkService }, + { provide: DSONameService, useClass: DSONameServiceMock } ], schemas: [NO_ERRORS_SCHEMA] }).overrideComponent(WorkflowItemSearchResultListElementComponent, { diff --git a/src/app/shared/object-list/my-dspace-result-list-element/workflow-item-search-result/workflow-item-search-result-list-element.component.ts b/src/app/shared/object-list/my-dspace-result-list-element/workflow-item-search-result/workflow-item-search-result-list-element.component.ts index 432f69f28c..836a3ee268 100644 --- a/src/app/shared/object-list/my-dspace-result-list-element/workflow-item-search-result/workflow-item-search-result-list-element.component.ts +++ b/src/app/shared/object-list/my-dspace-result-list-element/workflow-item-search-result/workflow-item-search-result-list-element.component.ts @@ -15,6 +15,7 @@ import { WorkflowItemSearchResult } from '../../../object-collection/shared/work import { TruncatableService } from '../../../truncatable/truncatable.service'; import { followLink } from '../../../utils/follow-link-config.model'; import { SearchResultListElementComponent } from '../../search-result-list-element/search-result-list-element.component'; +import { DSONameService } from '../../../../core/breadcrumbs/dso-name.service'; /** * This component renders workflowitem object for the search result in the list view. @@ -40,9 +41,10 @@ export class WorkflowItemSearchResultListElementComponent extends SearchResultLi constructor( protected truncatableService: TruncatableService, - protected linkService: LinkService + protected linkService: LinkService, + protected dsoNameService: DSONameService ) { - super(truncatableService); + super(truncatableService, dsoNameService); } /** diff --git a/src/app/shared/object-list/my-dspace-result-list-element/workspace-item-search-result/workspace-item-search-result-list-element.component.spec.ts b/src/app/shared/object-list/my-dspace-result-list-element/workspace-item-search-result/workspace-item-search-result-list-element.component.spec.ts index b1f2a2aeb9..87f5fd3733 100644 --- a/src/app/shared/object-list/my-dspace-result-list-element/workspace-item-search-result/workspace-item-search-result-list-element.component.spec.ts +++ b/src/app/shared/object-list/my-dspace-result-list-element/workspace-item-search-result/workspace-item-search-result-list-element.component.spec.ts @@ -16,6 +16,8 @@ import { createSuccessfulRemoteDataObject } from '../../../remote-data.utils'; import { TruncatableService } from '../../../truncatable/truncatable.service'; import { WorkspaceItemSearchResultListElementComponent } from './workspace-item-search-result-list-element.component'; import { By } from '@angular/platform-browser'; +import { DSONameService } from '../../../../core/breadcrumbs/dso-name.service'; +import { DSONameServiceMock } from '../../../mocks/dso-name.service.mock'; let component: WorkspaceItemSearchResultListElementComponent; let fixture: ComponentFixture; @@ -66,6 +68,7 @@ describe('WorkspaceItemSearchResultListElementComponent', () => { { provide: TruncatableService, useValue: {} }, { provide: ItemDataService, useValue: {} }, { provide: LinkService, useValue: linkService }, + { provide: DSONameService, useClass: DSONameServiceMock } ], schemas: [NO_ERRORS_SCHEMA] }).overrideComponent(WorkspaceItemSearchResultListElementComponent, { diff --git a/src/app/shared/object-list/my-dspace-result-list-element/workspace-item-search-result/workspace-item-search-result-list-element.component.ts b/src/app/shared/object-list/my-dspace-result-list-element/workspace-item-search-result/workspace-item-search-result-list-element.component.ts index b9d89ef6ab..5edfc1929e 100644 --- a/src/app/shared/object-list/my-dspace-result-list-element/workspace-item-search-result/workspace-item-search-result-list-element.component.ts +++ b/src/app/shared/object-list/my-dspace-result-list-element/workspace-item-search-result/workspace-item-search-result-list-element.component.ts @@ -15,6 +15,7 @@ import { WorkspaceItemSearchResult } from '../../../object-collection/shared/wor import { TruncatableService } from '../../../truncatable/truncatable.service'; import { followLink } from '../../../utils/follow-link-config.model'; import { SearchResultListElementComponent } from '../../search-result-list-element/search-result-list-element.component'; +import { DSONameService } from '../../../../core/breadcrumbs/dso-name.service'; /** * This component renders workspaceitem object for the search result in the list view. @@ -40,9 +41,10 @@ export class WorkspaceItemSearchResultListElementComponent extends SearchResultL constructor( protected truncatableService: TruncatableService, - protected linkService: LinkService + protected linkService: LinkService, + protected dsoNameService: DSONameService ) { - super(truncatableService); + super(truncatableService, dsoNameService); } /** diff --git a/src/app/shared/object-list/search-result-list-element/collection-search-result/collection-search-result-list-element.component.html b/src/app/shared/object-list/search-result-list-element/collection-search-result/collection-search-result-list-element.component.html index 1c081e2805..c98003cd1d 100644 --- a/src/app/shared/object-list/search-result-list-element/collection-search-result/collection-search-result-list-element.component.html +++ b/src/app/shared/object-list/search-result-list-element/collection-search-result/collection-search-result-list-element.component.html @@ -1,4 +1,4 @@ - - + +
diff --git a/src/app/shared/object-list/search-result-list-element/collection-search-result/collection-search-result-list-element.component.spec.ts b/src/app/shared/object-list/search-result-list-element/collection-search-result/collection-search-result-list-element.component.spec.ts index d50fdccb80..bdfe825c82 100644 --- a/src/app/shared/object-list/search-result-list-element/collection-search-result/collection-search-result-list-element.component.spec.ts +++ b/src/app/shared/object-list/search-result-list-element/collection-search-result/collection-search-result-list-element.component.spec.ts @@ -7,6 +7,8 @@ import { TruncatePipe } from '../../../utils/truncate.pipe'; import { Collection } from '../../../../core/shared/collection.model'; import { TruncatableService } from '../../../truncatable/truncatable.service'; import { CollectionSearchResult } from '../../../object-collection/shared/collection-search-result.model'; +import { DSONameService } from '../../../../core/breadcrumbs/dso-name.service'; +import { DSONameServiceMock } from '../../../mocks/dso-name.service.mock'; let collectionSearchResultListElementComponent: CollectionSearchResultListElementComponent; let fixture: ComponentFixture; @@ -47,6 +49,7 @@ describe('CollectionSearchResultListElementComponent', () => { declarations: [CollectionSearchResultListElementComponent, TruncatePipe], providers: [ { provide: TruncatableService, useValue: truncatableServiceStub }, + { provide: DSONameService, useClass: DSONameServiceMock } ], schemas: [NO_ERRORS_SCHEMA] }).overrideComponent(CollectionSearchResultListElementComponent, { diff --git a/src/app/shared/object-list/search-result-list-element/community-search-result/community-search-result-list-element.component.html b/src/app/shared/object-list/search-result-list-element/community-search-result/community-search-result-list-element.component.html index 08b02d123a..e0f0319ffc 100644 --- a/src/app/shared/object-list/search-result-list-element/community-search-result/community-search-result-list-element.component.html +++ b/src/app/shared/object-list/search-result-list-element/community-search-result/community-search-result-list-element.component.html @@ -1,4 +1,4 @@ - - + +
diff --git a/src/app/shared/object-list/search-result-list-element/community-search-result/community-search-result-list-element.component.spec.ts b/src/app/shared/object-list/search-result-list-element/community-search-result/community-search-result-list-element.component.spec.ts index c5588f5371..529594671c 100644 --- a/src/app/shared/object-list/search-result-list-element/community-search-result/community-search-result-list-element.component.spec.ts +++ b/src/app/shared/object-list/search-result-list-element/community-search-result/community-search-result-list-element.component.spec.ts @@ -7,6 +7,8 @@ import { TruncatePipe } from '../../../utils/truncate.pipe'; import { Community } from '../../../../core/shared/community.model'; import { TruncatableService } from '../../../truncatable/truncatable.service'; import { CommunitySearchResult } from '../../../object-collection/shared/community-search-result.model'; +import { DSONameService } from '../../../../core/breadcrumbs/dso-name.service'; +import { DSONameServiceMock } from '../../../mocks/dso-name.service.mock'; let communitySearchResultListElementComponent: CommunitySearchResultListElementComponent; let fixture: ComponentFixture; @@ -47,6 +49,7 @@ describe('CommunitySearchResultListElementComponent', () => { declarations: [CommunitySearchResultListElementComponent, TruncatePipe], providers: [ { provide: TruncatableService, useValue: truncatableServiceStub }, + { provide: DSONameService, useClass: DSONameServiceMock } ], schemas: [NO_ERRORS_SCHEMA] diff --git a/src/app/shared/object-list/search-result-list-element/item-search-result/item-types/item/item-search-result-list-element.component.html b/src/app/shared/object-list/search-result-list-element/item-search-result/item-types/item/item-search-result-list-element.component.html index 01a026eec9..80a4fd81fd 100644 --- a/src/app/shared/object-list/search-result-list-element/item-search-result/item-types/item/item-search-result-list-element.component.html +++ b/src/app/shared/object-list/search-result-list-element/item-search-result/item-types/item/item-search-result-list-element.component.html @@ -2,10 +2,10 @@ - + [routerLink]="[itemPageRoute]" class="lead item-list-title" + [innerHTML]="dsoTitle"> + diff --git a/src/app/shared/object-list/search-result-list-element/item-search-result/item-types/item/item-search-result-list-element.component.spec.ts b/src/app/shared/object-list/search-result-list-element/item-search-result/item-types/item/item-search-result-list-element.component.spec.ts index f8a8be415d..d32ac8058d 100644 --- a/src/app/shared/object-list/search-result-list-element/item-search-result/item-types/item/item-search-result-list-element.component.spec.ts +++ b/src/app/shared/object-list/search-result-list-element/item-search-result/item-types/item/item-search-result-list-element.component.spec.ts @@ -7,6 +7,8 @@ import { Item } from '../../../../../../core/shared/item.model'; import { TruncatePipe } from '../../../../../utils/truncate.pipe'; import { TruncatableService } from '../../../../../truncatable/truncatable.service'; import { ItemSearchResult } from '../../../../../object-collection/shared/item-search-result.model'; +import { DSONameService } from '../../../../../../core/breadcrumbs/dso-name.service'; +import { DSONameServiceMock, UNDEFINED_NAME } from '../../../../../mocks/dso-name.service.mock'; let publicationListElementComponent: ItemSearchResultListElementComponent; let fixture: ComponentFixture; @@ -53,23 +55,18 @@ const mockItemWithoutMetadata: ItemSearchResult = Object.assign(new ItemSearchRe indexableObject: Object.assign(new Item(), { bundles: observableOf({}), - metadata: { - 'dc.title': [ - { - language: 'en_US', - value: 'This is just another title' - } - ] - } + metadata: {} }) }); + describe('ItemListElementComponent', () => { beforeEach(waitForAsync(() => { TestBed.configureTestingModule({ declarations: [ItemSearchResultListElementComponent, TruncatePipe], providers: [ - { provide: TruncatableService, useValue: {} } + { provide: TruncatableService, useValue: {} }, + { provide: DSONameService, useClass: DSONameServiceMock } ], schemas: [NO_ERRORS_SCHEMA] @@ -179,4 +176,16 @@ describe('ItemListElementComponent', () => { expect(abstractField).toBeNull(); }); }); + + describe('When the item has no title', () => { + beforeEach(() => { + publicationListElementComponent.object = mockItemWithoutMetadata; + fixture.detectChanges(); + }); + + it('should show the fallback untitled translation', () => { + const titleField = fixture.debugElement.query(By.css('.item-list-title')); + expect(titleField.nativeElement.textContent.trim()).toEqual(UNDEFINED_NAME); + }); + }); }); diff --git a/src/app/shared/object-list/search-result-list-element/search-result-list-element.component.ts b/src/app/shared/object-list/search-result-list-element/search-result-list-element.component.ts index 3ad4f5e7e6..afd0363e7a 100644 --- a/src/app/shared/object-list/search-result-list-element/search-result-list-element.component.ts +++ b/src/app/shared/object-list/search-result-list-element/search-result-list-element.component.ts @@ -7,6 +7,7 @@ import { hasValue } from '../../empty.util'; import { AbstractListableElementComponent } from '../../object-collection/shared/object-collection-element/abstract-listable-element.component'; import { TruncatableService } from '../../truncatable/truncatable.service'; import { Metadata } from '../../../core/shared/metadata.utils'; +import { DSONameService } from '../../../core/breadcrumbs/dso-name.service'; @Component({ selector: 'ds-search-result-list-element', @@ -17,8 +18,9 @@ export class SearchResultListElementComponent, K exten * The DSpaceObject of the search result */ dso: K; + dsoTitle: string; - public constructor(protected truncatableService: TruncatableService) { + public constructor(protected truncatableService: TruncatableService, protected dsoNameService: DSONameService) { super(); } @@ -28,6 +30,7 @@ export class SearchResultListElementComponent, K exten ngOnInit(): void { if (hasValue(this.object)) { this.dso = this.object.indexableObject; + this.dsoTitle = this.dsoNameService.getName(this.dso); } } diff --git a/src/app/shared/object-list/sidebar-search-list-element/sidebar-search-list-element.component.spec.ts b/src/app/shared/object-list/sidebar-search-list-element/sidebar-search-list-element.component.spec.ts index 3d402ca0e4..31ad68ec63 100644 --- a/src/app/shared/object-list/sidebar-search-list-element/sidebar-search-list-element.component.spec.ts +++ b/src/app/shared/object-list/sidebar-search-list-element/sidebar-search-list-element.component.spec.ts @@ -10,6 +10,8 @@ import { LinkService } from '../../../core/cache/builders/link.service'; import { createSuccessfulRemoteDataObject$ } from '../../remote-data.utils'; import { HALResource } from '../../../core/shared/hal-resource.model'; import { ChildHALResource } from '../../../core/shared/child-hal-resource.model'; +import { DSONameService } from '../../../core/breadcrumbs/dso-name.service'; +import { DSONameServiceMock } from '../../mocks/dso-name.service.mock'; export function createSidebarSearchListElementTests( componentClass: any, @@ -38,6 +40,7 @@ export function createSidebarSearchListElementTests( providers: [ { provide: TruncatableService, useValue: {} }, { provide: LinkService, useValue: linkService }, + { provide: DSONameService, useClass: DSONameServiceMock }, ...extraProviders ], schemas: [NO_ERRORS_SCHEMA] diff --git a/src/app/shared/object-list/sidebar-search-list-element/sidebar-search-list-element.component.ts b/src/app/shared/object-list/sidebar-search-list-element/sidebar-search-list-element.component.ts index 478bf50771..a0d70a43c7 100644 --- a/src/app/shared/object-list/sidebar-search-list-element/sidebar-search-list-element.component.ts +++ b/src/app/shared/object-list/sidebar-search-list-element/sidebar-search-list-element.component.ts @@ -12,6 +12,7 @@ import { followLink } from '../../utils/follow-link-config.model'; import { RemoteData } from '../../../core/data/remote-data'; import { of as observableOf } from 'rxjs'; import { Context } from '../../../core/shared/context.model'; +import { DSONameService } from '../../../core/breadcrumbs/dso-name.service'; @Component({ selector: 'ds-sidebar-search-list-element', @@ -39,8 +40,10 @@ export class SidebarSearchListElementComponent, K exte description: string; public constructor(protected truncatableService: TruncatableService, - protected linkService: LinkService) { - super(truncatableService); + protected linkService: LinkService, + protected dsoNameService: DSONameService + ) { + super(truncatableService, dsoNameService); } /** diff --git a/src/assets/i18n/en.json5 b/src/assets/i18n/en.json5 index a16d41a9e3..f60abfb253 100644 --- a/src/assets/i18n/en.json5 +++ b/src/assets/i18n/en.json5 @@ -1098,6 +1098,10 @@ + "dso.name.untitled": "Untitled", + + + "dso-selector.create.collection.head": "New collection", "dso-selector.create.collection.sub-level": "Create a new collection in", From 01def4e8e4cd99193e22cf85c9fbca8cc0c6bfc3 Mon Sep 17 00:00:00 2001 From: Raf Ponsaerts Date: Wed, 17 Mar 2021 12:35:33 +0100 Subject: [PATCH 093/132] Fixed other item types title --- ...ournal-issue-search-result-list-element.component.html | 8 ++++---- ...urnal-volume-search-result-list-element.component.html | 8 ++++---- .../journal-search-result-list-element.component.html | 8 ++++---- .../project-search-result-list-element.component.html | 8 ++++---- 4 files changed, 16 insertions(+), 16 deletions(-) diff --git a/src/app/entity-groups/journal-entities/item-list-elements/search-result-list-elements/journal-issue/journal-issue-search-result-list-element.component.html b/src/app/entity-groups/journal-entities/item-list-elements/search-result-list-elements/journal-issue/journal-issue-search-result-list-element.component.html index 0e783a4843..fa4c06d36a 100644 --- a/src/app/entity-groups/journal-entities/item-list-elements/search-result-list-elements/journal-issue/journal-issue-search-result-list-element.component.html +++ b/src/app/entity-groups/journal-entities/item-list-elements/search-result-list-elements/journal-issue/journal-issue-search-result-list-element.component.html @@ -1,11 +1,11 @@ + [routerLink]="[itemPageRoute]" class="lead item-list-title" + [innerHTML]="dsoTitle"> + class="lead item-list-title" + [innerHTML]="dsoTitle"> + [routerLink]="[itemPageRoute]" class="lead item-list-title" + [innerHTML]="dsoTitle"> + class="lead item-list-title" + [innerHTML]="dsoTitle"> + [routerLink]="[itemPageRoute]" class="lead item-list-title" + [innerHTML]="dsoTitle"> + class="lead item-list-title" + [innerHTML]="dsoTitle"> + [routerLink]="[itemPageRoute]" class="lead item-list-title" + [innerHTML]="dsoTitle"> + class="lead item-list-title" + [innerHTML]="dsoTitle"> From 3a0dc277e48dc7ab3b4e90177646e2d68331761c Mon Sep 17 00:00:00 2001 From: Raf Ponsaerts Date: Wed, 17 Mar 2021 13:33:27 +0100 Subject: [PATCH 094/132] fix lgtm issues --- .../org-unit-search-result-list-submission-element.component.ts | 1 - .../person-search-result-list-submission-element.component.ts | 1 - 2 files changed, 2 deletions(-) diff --git a/src/app/entity-groups/research-entities/submission/item-list-elements/org-unit/org-unit-search-result-list-submission-element.component.ts b/src/app/entity-groups/research-entities/submission/item-list-elements/org-unit/org-unit-search-result-list-submission-element.component.ts index 091549dcea..e3cc8fccd3 100644 --- a/src/app/entity-groups/research-entities/submission/item-list-elements/org-unit/org-unit-search-result-list-submission-element.component.ts +++ b/src/app/entity-groups/research-entities/submission/item-list-elements/org-unit/org-unit-search-result-list-submission-element.component.ts @@ -19,7 +19,6 @@ import { MetadataValue } from '../../../../../core/shared/metadata.models'; import { ItemDataService } from '../../../../../core/data/item-data.service'; import { SelectableListService } from '../../../../../shared/object-list/selectable-list/selectable-list.service'; import { NameVariantModalComponent } from '../../name-variant-modal/name-variant-modal.component'; -import { LinkService } from '../../../../../core/cache/builders/link.service'; import { DSONameService } from '../../../../../core/breadcrumbs/dso-name.service'; @listableObjectComponent('OrgUnitSearchResult', ViewMode.ListElement, Context.EntitySearchModal) diff --git a/src/app/entity-groups/research-entities/submission/item-list-elements/person/person-search-result-list-submission-element.component.ts b/src/app/entity-groups/research-entities/submission/item-list-elements/person/person-search-result-list-submission-element.component.ts index 2d991d5c64..64cf73cfb9 100644 --- a/src/app/entity-groups/research-entities/submission/item-list-elements/person/person-search-result-list-submission-element.component.ts +++ b/src/app/entity-groups/research-entities/submission/item-list-elements/person/person-search-result-list-submission-element.component.ts @@ -19,7 +19,6 @@ import { NameVariantModalComponent } from '../../name-variant-modal/name-variant import { MetadataValue } from '../../../../../core/shared/metadata.models'; import { ItemDataService } from '../../../../../core/data/item-data.service'; import { SelectableListService } from '../../../../../shared/object-list/selectable-list/selectable-list.service'; -import { LinkService } from '../../../../../core/cache/builders/link.service'; import { DSONameService } from '../../../../../core/breadcrumbs/dso-name.service'; @listableObjectComponent('PersonSearchResult', ViewMode.ListElement, Context.EntitySearchModalWithNameVariants) From 7d774d43e8b9fdf3b8d4d8c8098f755cf68c0c5d Mon Sep 17 00:00:00 2001 From: lotte Date: Thu, 11 Mar 2021 15:41:27 +0100 Subject: [PATCH 095/132] fixed dropzone issues --- src/app/shared/uploader/uploader.component.ts | 6 ------ .../form/submission-form.component.html | 2 +- .../submission/form/submission-form.component.ts | 15 +++++++++++++-- 3 files changed, 14 insertions(+), 9 deletions(-) diff --git a/src/app/shared/uploader/uploader.component.ts b/src/app/shared/uploader/uploader.component.ts index 0e19c38b55..4e5b002b51 100644 --- a/src/app/shared/uploader/uploader.component.ts +++ b/src/app/shared/uploader/uploader.component.ts @@ -146,12 +146,6 @@ export class UploaderComponent { this.uploader.options.headers = [{ name: XSRF_REQUEST_HEADER, value: this.tokenExtractor.getToken() }]; this.onBeforeUpload(); this.isOverDocumentDropZone = observableOf(false); - - // Move page target to the uploader - const config: ScrollToConfigOptions = { - target: this.uploaderId - }; - this.scrollToService.scrollTo(config); }; if (hasValue(this.uploadProperties)) { this.uploader.onBuildItemForm = (item, form) => { diff --git a/src/app/submission/form/submission-form.component.html b/src/app/submission/form/submission-form.component.html index 7376b1e10b..a8e963d8ea 100644 --- a/src/app/submission/form/submission-form.component.html +++ b/src/app/submission/form/submission-form.component.html @@ -1,5 +1,5 @@
-
+
= observableOf(true); + /** + * Emits true when the submission config has bitstream uploading enabled in submission + */ + public uploadEnabled$ = new BehaviorSubject(false); + /** * Observable of the list of submission's sections * @type {Observable} @@ -128,7 +135,11 @@ export class SubmissionFormComponent implements OnChanges, OnDestroy { } else { return observableOf([]); } - })); + }), + tap((sectionList) => { + this.uploadEnabled$.next(isNotEmpty(sectionList) && sectionList.some(config => config.sectionType === SectionsType.Upload)); + }) + ); // check if is submission loading this.loading = this.submissionService.getSubmissionObject(this.submissionId).pipe( From df5666e52f2693b7ea5e4e525001c6745c81003f Mon Sep 17 00:00:00 2001 From: lotte Date: Fri, 12 Mar 2021 11:25:54 +0100 Subject: [PATCH 096/132] sticky progress bar for uploads in submission --- .../form/submission-form.component.html | 65 ++++++++++--------- 1 file changed, 33 insertions(+), 32 deletions(-) diff --git a/src/app/submission/form/submission-form.component.html b/src/app/submission/form/submission-form.component.html index a8e963d8ea..33b5d4be12 100644 --- a/src/app/submission/form/submission-form.component.html +++ b/src/app/submission/form/submission-form.component.html @@ -1,35 +1,36 @@
-
- -
-
-
-
- - -
-
- - -
-
+
+
+ +
+
-
- - - - -
- +
+ + +
+
+ + +
+
+ +
+ + + + +
+
From ff1014779e6f5445368ea3f44a37f5a4c3a988ea Mon Sep 17 00:00:00 2001 From: lotte Date: Fri, 12 Mar 2021 12:34:10 +0100 Subject: [PATCH 097/132] fix lgtm issue --- src/app/shared/uploader/uploader.component.ts | 19 +++---------------- 1 file changed, 3 insertions(+), 16 deletions(-) diff --git a/src/app/shared/uploader/uploader.component.ts b/src/app/shared/uploader/uploader.component.ts index 4e5b002b51..a0dd0e5bba 100644 --- a/src/app/shared/uploader/uploader.component.ts +++ b/src/app/shared/uploader/uploader.component.ts @@ -1,29 +1,16 @@ -import { - ChangeDetectionStrategy, - ChangeDetectorRef, - Component, - EventEmitter, - HostListener, - Input, - Output, - ViewEncapsulation, -} from '@angular/core'; +import { ChangeDetectionStrategy, ChangeDetectorRef, Component, EventEmitter, HostListener, Input, Output, ViewEncapsulation, } from '@angular/core'; import { of as observableOf } from 'rxjs'; import { FileUploader } from 'ng2-file-upload'; import { uniqueId } from 'lodash'; -import { ScrollToConfigOptions, ScrollToService } from '@nicky-lenaers/ngx-scroll-to'; +import { ScrollToService } from '@nicky-lenaers/ngx-scroll-to'; import { UploaderOptions } from './uploader-options.model'; import { hasValue, isNotEmpty, isUndefined } from '../empty.util'; import { UploaderService } from './uploader.service'; import { UploaderProperties } from './uploader-properties.model'; import { HttpXsrfTokenExtractor } from '@angular/common/http'; -import { - XSRF_REQUEST_HEADER, - XSRF_RESPONSE_HEADER, - XSRF_COOKIE -} from '../../core/xsrf/xsrf.interceptor'; +import { XSRF_COOKIE, XSRF_REQUEST_HEADER, XSRF_RESPONSE_HEADER } from '../../core/xsrf/xsrf.interceptor'; import { CookieService } from '../../core/services/cookie.service'; @Component({ From 5018d36377f4a8042a966f2842a0d39001f8f6b9 Mon Sep 17 00:00:00 2001 From: Yura Bondarenko Date: Fri, 19 Mar 2021 14:22:30 +0100 Subject: [PATCH 098/132] Fix lint error --- src/themes/custom/theme.module.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/themes/custom/theme.module.ts b/src/themes/custom/theme.module.ts index 095d4dde95..183aff8a6a 100644 --- a/src/themes/custom/theme.module.ts +++ b/src/themes/custom/theme.module.ts @@ -36,7 +36,7 @@ import { AppModule } from '../../app/app.module'; import { PublicationComponent } from './app/+item-page/simple/item-types/publication/publication.component'; import { ItemPageModule } from '../../app/+item-page/item-page.module'; import { RouterModule } from '@angular/router'; -import { AccessControlModule } from "../../app/access-control/access-control.module"; +import { AccessControlModule } from '../../app/access-control/access-control.module'; const DECLARATIONS = [ HomePageComponent, From 8d6156df37558607cb63061fdde5c1e4d703e3fd Mon Sep 17 00:00:00 2001 From: lotte Date: Tue, 23 Mar 2021 16:30:38 +0100 Subject: [PATCH 099/132] 77818: edit page permission fixes --- .../edit-item-page.component.html | 15 ++++++--- .../edit-item-page.component.ts | 29 ++++++++++++----- .../edit-item-page.routing.module.ts | 25 ++++++++++----- .../item-page-edit-metadata.guard.ts | 31 +++++++++++++++++++ .../+item-page/item-page-routing.module.ts | 4 +-- .../dso-page-feature.guard.ts | 12 ++++++- .../dso-page-edit-button.component.html | 2 +- src/assets/i18n/en.json5 | 2 ++ 8 files changed, 97 insertions(+), 23 deletions(-) create mode 100644 src/app/+item-page/item-page-edit-metadata.guard.ts diff --git a/src/app/+item-page/edit-item-page/edit-item-page.component.html b/src/app/+item-page/edit-item-page/edit-item-page.component.html index ca1c809cd9..6b6f74309c 100644 --- a/src/app/+item-page/edit-item-page/edit-item-page.component.html +++ b/src/app/+item-page/edit-item-page/edit-item-page.component.html @@ -5,11 +5,18 @@
diff --git a/src/app/+item-page/edit-item-page/edit-item-page.component.ts b/src/app/+item-page/edit-item-page/edit-item-page.component.ts index ec7cdb022d..d0b0fe9356 100644 --- a/src/app/+item-page/edit-item-page/edit-item-page.component.ts +++ b/src/app/+item-page/edit-item-page/edit-item-page.component.ts @@ -1,12 +1,13 @@ import { fadeIn, fadeInOut } from '../../shared/animations/fade'; -import { ChangeDetectionStrategy, Component, OnInit } from '@angular/core'; -import { ActivatedRoute, Router } from '@angular/router'; +import { ChangeDetectionStrategy, Component, Injector, OnInit } from '@angular/core'; +import { ActivatedRoute, CanActivate, Route, Router } from '@angular/router'; import { RemoteData } from '../../core/data/remote-data'; import { Item } from '../../core/shared/item.model'; -import { Observable } from 'rxjs'; -import { map } from 'rxjs/operators'; +import { combineLatest as observableCombineLatest, Observable, of as observableOf } from 'rxjs'; +import { map, tap } from 'rxjs/operators'; import { isNotEmpty } from '../../shared/empty.util'; import { getItemPageRoute } from '../item-page-routing-paths'; +import { GenericConstructor } from '../../core/shared/generic-constructor'; @Component({ selector: 'ds-edit-item-page', @@ -35,9 +36,9 @@ export class EditItemPageComponent implements OnInit { /** * All possible page outlet strings */ - pages: string[]; + pages: { page: string, enabled: Observable }[]; - constructor(private route: ActivatedRoute, private router: Router) { + constructor(private route: ActivatedRoute, private router: Router, private injector: Injector) { this.router.events.subscribe(() => { this.currentPage = this.route.snapshot.firstChild.routeConfig.path; }); @@ -45,8 +46,20 @@ export class EditItemPageComponent implements OnInit { ngOnInit(): void { this.pages = this.route.routeConfig.children - .map((child: any) => child.path) - .filter((path: string) => isNotEmpty(path)); // ignore reroutes + .filter((child: Route) => isNotEmpty(child.path)) + .map((child: Route) => { + let enabled = observableOf(true); + if (isNotEmpty(child.canActivate)) { + enabled = observableCombineLatest(child.canActivate.map((guardConstructor: GenericConstructor) => { + const guard: CanActivate = this.injector.get(guardConstructor); + return guard.canActivate(this.route.snapshot, this.router.routerState.snapshot); + }) + ).pipe( + map((canActivateOutcomes: any[]) => canActivateOutcomes.every((e) => e === true)) + ); + } + return { page: child.path, enabled: enabled }; + }); // ignore reroutes this.itemRD$ = this.route.data.pipe(map((data) => data.dso)); } diff --git a/src/app/+item-page/edit-item-page/edit-item-page.routing.module.ts b/src/app/+item-page/edit-item-page/edit-item-page.routing.module.ts index da10d33add..0e36cc9894 100644 --- a/src/app/+item-page/edit-item-page/edit-item-page.routing.module.ts +++ b/src/app/+item-page/edit-item-page/edit-item-page.routing.module.ts @@ -31,6 +31,9 @@ import { } from './edit-item-page.routing-paths'; import { ItemPageReinstateGuard } from './item-page-reinstate.guard'; import { ItemPageWithdrawGuard } from './item-page-withdraw.guard'; +import { ItemPageEditMetadataGuard } from '../item-page-edit-metadata.guard'; +import { ItemPageAdministratorGuard } from '../item-page-administrator.guard'; +import { AuthenticatedGuard } from '../../core/auth/authenticated.guard'; /** * Routing module that handles the routing for the Edit Item page administrator functionality @@ -57,22 +60,26 @@ import { ItemPageWithdrawGuard } from './item-page-withdraw.guard'; { path: 'status', component: ItemStatusComponent, - data: { title: 'item.edit.tabs.status.title', showBreadcrumbs: true } + data: { title: 'item.edit.tabs.status.title', showBreadcrumbs: true }, + canActivate: [ItemPageAdministratorGuard] }, { path: 'bitstreams', component: ItemBitstreamsComponent, - data: { title: 'item.edit.tabs.bitstreams.title', showBreadcrumbs: true } + data: { title: 'item.edit.tabs.bitstreams.title', showBreadcrumbs: true }, + canActivate: [ItemPageAdministratorGuard] }, { path: 'metadata', component: ItemMetadataComponent, - data: { title: 'item.edit.tabs.metadata.title', showBreadcrumbs: true } + data: { title: 'item.edit.tabs.metadata.title', showBreadcrumbs: true }, + canActivate: [ItemPageEditMetadataGuard] }, { path: 'relationships', component: ItemRelationshipsComponent, - data: { title: 'item.edit.tabs.relationships.title', showBreadcrumbs: true } + data: { title: 'item.edit.tabs.relationships.title', showBreadcrumbs: true }, + canActivate: [ItemPageEditMetadataGuard] }, /* TODO - uncomment & fix when view page exists { @@ -89,12 +96,14 @@ import { ItemPageWithdrawGuard } from './item-page-withdraw.guard'; { path: 'versionhistory', component: ItemVersionHistoryComponent, - data: { title: 'item.edit.tabs.versionhistory.title', showBreadcrumbs: true } + data: { title: 'item.edit.tabs.versionhistory.title', showBreadcrumbs: true }, + canActivate: [ItemPageAdministratorGuard] }, { path: 'mapper', component: ItemCollectionMapperComponent, - data: { title: 'item.edit.tabs.item-mapper.title', showBreadcrumbs: true } + data: { title: 'item.edit.tabs.item-mapper.title', showBreadcrumbs: true }, + canActivate: [ItemPageAdministratorGuard] } ] }, @@ -165,7 +174,9 @@ import { ItemPageWithdrawGuard } from './item-page-withdraw.guard'; ResourcePolicyResolver, ResourcePolicyTargetResolver, ItemPageReinstateGuard, - ItemPageWithdrawGuard + ItemPageWithdrawGuard, + ItemPageAdministratorGuard, + ItemPageEditMetadataGuard, ] }) export class EditItemPageRoutingModule { diff --git a/src/app/+item-page/item-page-edit-metadata.guard.ts b/src/app/+item-page/item-page-edit-metadata.guard.ts new file mode 100644 index 0000000000..821ca44c30 --- /dev/null +++ b/src/app/+item-page/item-page-edit-metadata.guard.ts @@ -0,0 +1,31 @@ +import { Injectable } from '@angular/core'; +import { ActivatedRouteSnapshot, Router, RouterStateSnapshot } from '@angular/router'; +import { AuthorizationDataService } from '../core/data/feature-authorization/authorization-data.service'; +import { ItemPageResolver } from './item-page.resolver'; +import { Item } from '../core/shared/item.model'; +import { DsoPageFeatureGuard } from '../core/data/feature-authorization/feature-authorization-guard/dso-page-feature.guard'; +import { Observable, of as observableOf } from 'rxjs'; +import { FeatureID } from '../core/data/feature-authorization/feature-id'; +import { AuthService } from '../core/auth/auth.service'; + +@Injectable({ + providedIn: 'root' +}) +/** + * Guard for preventing unauthorized access to certain {@link Item} pages requiring edit metadata rights + */ +export class ItemPageEditMetadataGuard extends DsoPageFeatureGuard { + constructor(protected resolver: ItemPageResolver, + protected authorizationService: AuthorizationDataService, + protected router: Router, + protected authService: AuthService) { + super(resolver, authorizationService, router, authService); + } + + /** + * Check administrator authorization rights + */ + getFeatureID(next: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable { + return observableOf(FeatureID.CanEditMetadata); + } +} diff --git a/src/app/+item-page/item-page-routing.module.ts b/src/app/+item-page/item-page-routing.module.ts index b04a783b2f..80564b5d21 100644 --- a/src/app/+item-page/item-page-routing.module.ts +++ b/src/app/+item-page/item-page-routing.module.ts @@ -13,6 +13,7 @@ import { UPLOAD_BITSTREAM_PATH, ITEM_EDIT_PATH } from './item-page-routing-paths import { ItemPageAdministratorGuard } from './item-page-administrator.guard'; import { MenuItemType } from '../shared/menu/initial-menus-state'; import { LinkMenuItemModel } from '../shared/menu/menu-item/models/link.model'; +import { ItemPageEditMetadataGuard } from './item-page-edit-metadata.guard'; @NgModule({ imports: [ @@ -38,7 +39,6 @@ import { LinkMenuItemModel } from '../shared/menu/menu-item/models/link.model'; path: ITEM_EDIT_PATH, loadChildren: () => import('./edit-item-page/edit-item-page.module') .then((m) => m.EditItemPageModule), - canActivate: [ItemPageAdministratorGuard] }, { path: UPLOAD_BITSTREAM_PATH, @@ -68,7 +68,7 @@ import { LinkMenuItemModel } from '../shared/menu/menu-item/models/link.model'; ItemBreadcrumbResolver, DSOBreadcrumbsService, LinkService, - ItemPageAdministratorGuard + ItemPageAdministratorGuard, ] }) diff --git a/src/app/core/data/feature-authorization/feature-authorization-guard/dso-page-feature.guard.ts b/src/app/core/data/feature-authorization/feature-authorization-guard/dso-page-feature.guard.ts index c9ac7155d4..c85af60913 100644 --- a/src/app/core/data/feature-authorization/feature-authorization-guard/dso-page-feature.guard.ts +++ b/src/app/core/data/feature-authorization/feature-authorization-guard/dso-page-feature.guard.ts @@ -7,6 +7,7 @@ import { map } from 'rxjs/operators'; import { DSpaceObject } from '../../../shared/dspace-object.model'; import { FeatureAuthorizationGuard } from './feature-authorization.guard'; import { AuthService } from '../../../auth/auth.service'; +import { hasNoValue, hasValue } from '../../../../shared/empty.util'; /** * Abstract Guard for preventing unauthorized access to {@link DSpaceObject} pages that require rights for a specific feature @@ -24,9 +25,18 @@ export abstract class DsoPageFeatureGuard extends Featur * Check authorization rights for the object resolved using the provided resolver */ getObjectUrl(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable { - return (this.resolver.resolve(route, state) as Observable>).pipe( + const routeWithObjectID = this.getRouteWithDSOId(route); + return (this.resolver.resolve(routeWithObjectID, state) as Observable>).pipe( getAllSucceededRemoteDataPayload(), map((dso) => dso.self) ); } + + protected getRouteWithDSOId(route: ActivatedRouteSnapshot): ActivatedRouteSnapshot { + let routeWithDSOId = route; + while (hasNoValue(routeWithDSOId.params.id) && hasValue(routeWithDSOId.parent)) { + routeWithDSOId = routeWithDSOId.parent; + } + return routeWithDSOId; + } } diff --git a/src/app/shared/dso-page/dso-page-edit-button/dso-page-edit-button.component.html b/src/app/shared/dso-page/dso-page-edit-button/dso-page-edit-button.component.html index 36661c895a..d845f852c8 100644 --- a/src/app/shared/dso-page/dso-page-edit-button/dso-page-edit-button.component.html +++ b/src/app/shared/dso-page/dso-page-edit-button/dso-page-edit-button.component.html @@ -1,5 +1,5 @@ diff --git a/src/assets/i18n/en.json5 b/src/assets/i18n/en.json5 index f60abfb253..e81df2f336 100644 --- a/src/assets/i18n/en.json5 +++ b/src/assets/i18n/en.json5 @@ -1471,6 +1471,8 @@ "item.edit.breadcrumbs": "Edit Item", + "item.edit.tabs.disabled.tooltip": "You don't have permission to access this tab", + "item.edit.tabs.mapper.head": "Collection Mapper", From 11f3962326d62ff91344bdb5b9f9a1b5a50f0bee Mon Sep 17 00:00:00 2001 From: lotte Date: Wed, 24 Mar 2021 14:33:32 +0100 Subject: [PATCH 100/132] added tests --- .../edit-item-page.component.spec.ts | 107 ++++++++++++++++++ .../dso-page-feature.guard.spec.ts | 21 +++- 2 files changed, 127 insertions(+), 1 deletion(-) create mode 100644 src/app/+item-page/edit-item-page/edit-item-page.component.spec.ts diff --git a/src/app/+item-page/edit-item-page/edit-item-page.component.spec.ts b/src/app/+item-page/edit-item-page/edit-item-page.component.spec.ts new file mode 100644 index 0000000000..6c9f79c36b --- /dev/null +++ b/src/app/+item-page/edit-item-page/edit-item-page.component.spec.ts @@ -0,0 +1,107 @@ +import { ComponentFixture, fakeAsync, TestBed, tick, waitForAsync } from '@angular/core/testing'; +import { TranslateLoader, TranslateModule } from '@ngx-translate/core'; +import { TranslateLoaderMock } from '../../shared/mocks/translate-loader.mock'; +import { ChangeDetectionStrategy, Injector, NO_ERRORS_SCHEMA } from '@angular/core'; +import { ActivatedRoute, ActivatedRouteSnapshot, CanActivate, Router, RouterStateSnapshot, UrlTree } from '@angular/router'; +import { EditItemPageComponent } from './edit-item-page.component'; +import { Observable, of as observableOf } from 'rxjs'; +import { By } from '@angular/platform-browser'; +import { createSuccessfulRemoteDataObject } from '../../shared/remote-data.utils'; +import { Item } from '../../core/shared/item.model'; + +describe('ItemPageComponent', () => { + let comp: EditItemPageComponent; + let fixture: ComponentFixture; + + class AcceptAllGuard implements CanActivate { + canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable | Promise | boolean | UrlTree { + return observableOf(true); + } + } + + // tslint:disable-next-line:max-classes-per-file + class AcceptNoneGuard implements CanActivate { + canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable | Promise | boolean | UrlTree { + console.log('BLA'); + return observableOf(false); + } + } + + const accesiblePages = ['accessible']; + const inaccesiblePages = ['inaccessible', 'inaccessibleDoubleGuard']; + const mockRoute = { + snapshot: { + firstChild: { + routeConfig: { + path: accesiblePages[0] + } + }, + routerState: { + snapshot: undefined + } + }, + routeConfig: { + children: [ + { + path: accesiblePages[0], + canActivate: [AcceptAllGuard] + }, { + path: inaccesiblePages[0], + canActivate: [AcceptNoneGuard] + }, { + path: inaccesiblePages[1], + canActivate: [AcceptAllGuard, AcceptNoneGuard] + }, + ] + }, + data: observableOf({dso: createSuccessfulRemoteDataObject(new Item())}) + }; + + const mockRouter = { + routerState: { + snapshot: undefined + }, + events: observableOf(undefined) + }; + + beforeEach(waitForAsync(() => { + TestBed.configureTestingModule({ + imports: [TranslateModule.forRoot({ + loader: { + provide: TranslateLoader, + useClass: TranslateLoaderMock + } + })], + declarations: [EditItemPageComponent], + providers: [ + { provide: ActivatedRoute, useValue: mockRoute }, + { provide: Router, useValue: mockRouter }, + AcceptAllGuard, + AcceptNoneGuard, + ], + + schemas: [NO_ERRORS_SCHEMA] + }).overrideComponent(EditItemPageComponent, { + set: { changeDetection: ChangeDetectionStrategy.Default } + }).compileComponents(); + })); + + beforeEach(waitForAsync(() => { + fixture = TestBed.createComponent(EditItemPageComponent); + comp = fixture.componentInstance; + spyOn((comp as any).injector, 'get').and.callFake((a) => new a()); + fixture.detectChanges(); + })); + + describe('ngOnInit', () => { + it('should enable tabs that the user can activate', fakeAsync(() => { + const enabledItems = fixture.debugElement.queryAll(By.css('a.nav-link')); + expect(enabledItems.length).toBe(accesiblePages.length); + })); + + it('should disable tabs that the user can not activate', () => { + const disabledItems = fixture.debugElement.queryAll(By.css('button.nav-link.disabled')); + expect(disabledItems.length).toBe(inaccesiblePages.length); + }); + }); +}); diff --git a/src/app/core/data/feature-authorization/feature-authorization-guard/dso-page-feature.guard.spec.ts b/src/app/core/data/feature-authorization/feature-authorization-guard/dso-page-feature.guard.spec.ts index 4041e588ed..f98e3f1837 100644 --- a/src/app/core/data/feature-authorization/feature-authorization-guard/dso-page-feature.guard.spec.ts +++ b/src/app/core/data/feature-authorization/feature-authorization-guard/dso-page-feature.guard.spec.ts @@ -32,6 +32,8 @@ describe('DsoPageAdministratorGuard', () => { let authService: AuthService; let resolver: Resolve>; let object: DSpaceObject; + let route; + let parentRoute; function init() { object = { @@ -50,6 +52,16 @@ describe('DsoPageAdministratorGuard', () => { authService = jasmine.createSpyObj('authService', { isAuthenticated: observableOf(true) }); + parentRoute = { + params: { + id: '3e1a5327-dabb-41ff-af93-e6cab9d032f0' + } + }; + route = { + params: { + }, + parent: parentRoute + }; guard = new DsoPageFeatureGuardImpl(resolver, authorizationService, router, authService, undefined); } @@ -59,10 +71,17 @@ describe('DsoPageAdministratorGuard', () => { describe('getObjectUrl', () => { it('should return the resolved object\'s selflink', (done) => { - guard.getObjectUrl(undefined, undefined).subscribe((selflink) => { + guard.getObjectUrl(route, undefined).subscribe((selflink) => { expect(selflink).toEqual(object.self); done(); }); }); }); + + describe('getRouteWithDSOId', () => { + it('should return the route that has the UUID of the DSO', () => { + const foundRoute = (guard as any).getRouteWithDSOId(route); + expect(foundRoute).toBe(parentRoute); + }); + }); }); From 650f7106c24d30836157fd94a4aec9a1648d9c68 Mon Sep 17 00:00:00 2001 From: lotte Date: Wed, 24 Mar 2021 14:36:23 +0100 Subject: [PATCH 101/132] removed unused imports --- .../edit-item-page/edit-item-page.component.spec.ts | 4 ++-- src/app/+item-page/edit-item-page/edit-item-page.component.ts | 2 +- src/app/+item-page/item-page-routing.module.ts | 3 +-- 3 files changed, 4 insertions(+), 5 deletions(-) diff --git a/src/app/+item-page/edit-item-page/edit-item-page.component.spec.ts b/src/app/+item-page/edit-item-page/edit-item-page.component.spec.ts index 6c9f79c36b..cff9104c01 100644 --- a/src/app/+item-page/edit-item-page/edit-item-page.component.spec.ts +++ b/src/app/+item-page/edit-item-page/edit-item-page.component.spec.ts @@ -1,7 +1,7 @@ -import { ComponentFixture, fakeAsync, TestBed, tick, waitForAsync } from '@angular/core/testing'; +import { ComponentFixture, fakeAsync, TestBed, waitForAsync } from '@angular/core/testing'; import { TranslateLoader, TranslateModule } from '@ngx-translate/core'; import { TranslateLoaderMock } from '../../shared/mocks/translate-loader.mock'; -import { ChangeDetectionStrategy, Injector, NO_ERRORS_SCHEMA } from '@angular/core'; +import { ChangeDetectionStrategy, NO_ERRORS_SCHEMA } from '@angular/core'; import { ActivatedRoute, ActivatedRouteSnapshot, CanActivate, Router, RouterStateSnapshot, UrlTree } from '@angular/router'; import { EditItemPageComponent } from './edit-item-page.component'; import { Observable, of as observableOf } from 'rxjs'; diff --git a/src/app/+item-page/edit-item-page/edit-item-page.component.ts b/src/app/+item-page/edit-item-page/edit-item-page.component.ts index d0b0fe9356..5f1889a404 100644 --- a/src/app/+item-page/edit-item-page/edit-item-page.component.ts +++ b/src/app/+item-page/edit-item-page/edit-item-page.component.ts @@ -4,7 +4,7 @@ import { ActivatedRoute, CanActivate, Route, Router } from '@angular/router'; import { RemoteData } from '../../core/data/remote-data'; import { Item } from '../../core/shared/item.model'; import { combineLatest as observableCombineLatest, Observable, of as observableOf } from 'rxjs'; -import { map, tap } from 'rxjs/operators'; +import { map } from 'rxjs/operators'; import { isNotEmpty } from '../../shared/empty.util'; import { getItemPageRoute } from '../item-page-routing-paths'; import { GenericConstructor } from '../../core/shared/generic-constructor'; diff --git a/src/app/+item-page/item-page-routing.module.ts b/src/app/+item-page/item-page-routing.module.ts index 80564b5d21..8d2853735b 100644 --- a/src/app/+item-page/item-page-routing.module.ts +++ b/src/app/+item-page/item-page-routing.module.ts @@ -9,11 +9,10 @@ import { ItemBreadcrumbResolver } from '../core/breadcrumbs/item-breadcrumb.reso import { DSOBreadcrumbsService } from '../core/breadcrumbs/dso-breadcrumbs.service'; import { LinkService } from '../core/cache/builders/link.service'; import { UploadBitstreamComponent } from './bitstreams/upload/upload-bitstream.component'; -import { UPLOAD_BITSTREAM_PATH, ITEM_EDIT_PATH } from './item-page-routing-paths'; +import { ITEM_EDIT_PATH, UPLOAD_BITSTREAM_PATH } from './item-page-routing-paths'; import { ItemPageAdministratorGuard } from './item-page-administrator.guard'; import { MenuItemType } from '../shared/menu/initial-menus-state'; import { LinkMenuItemModel } from '../shared/menu/menu-item/models/link.model'; -import { ItemPageEditMetadataGuard } from './item-page-edit-metadata.guard'; @NgModule({ imports: [ From 029308b52fb2c5ee51de8a0a3c7c466c4179610b Mon Sep 17 00:00:00 2001 From: lotte Date: Wed, 24 Mar 2021 15:06:27 +0100 Subject: [PATCH 102/132] Added missing typedoc --- src/app/+item-page/item-page-edit-metadata.guard.ts | 2 +- .../feature-authorization-guard/dso-page-feature.guard.ts | 4 ++++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/src/app/+item-page/item-page-edit-metadata.guard.ts b/src/app/+item-page/item-page-edit-metadata.guard.ts index 821ca44c30..a9b870b1cd 100644 --- a/src/app/+item-page/item-page-edit-metadata.guard.ts +++ b/src/app/+item-page/item-page-edit-metadata.guard.ts @@ -23,7 +23,7 @@ export class ItemPageEditMetadataGuard extends DsoPageFeatureGuard { } /** - * Check administrator authorization rights + * Check edit metadata authorization rights */ getFeatureID(next: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable { return observableOf(FeatureID.CanEditMetadata); diff --git a/src/app/core/data/feature-authorization/feature-authorization-guard/dso-page-feature.guard.ts b/src/app/core/data/feature-authorization/feature-authorization-guard/dso-page-feature.guard.ts index c85af60913..c50dd7f95d 100644 --- a/src/app/core/data/feature-authorization/feature-authorization-guard/dso-page-feature.guard.ts +++ b/src/app/core/data/feature-authorization/feature-authorization-guard/dso-page-feature.guard.ts @@ -32,6 +32,10 @@ export abstract class DsoPageFeatureGuard extends Featur ); } + /** + * Method to resolve resolve (parent) route that contains the UUID of the DSO + * @param route The current route + */ protected getRouteWithDSOId(route: ActivatedRouteSnapshot): ActivatedRouteSnapshot { let routeWithDSOId = route; while (hasNoValue(routeWithDSOId.params.id) && hasValue(routeWithDSOId.parent)) { From 623688304ddf674420912415dd8a730d6f4acf11 Mon Sep 17 00:00:00 2001 From: lotte Date: Wed, 24 Mar 2021 15:30:54 +0100 Subject: [PATCH 103/132] removed unused import --- .../edit-item-page/edit-item-page.routing.module.ts | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/app/+item-page/edit-item-page/edit-item-page.routing.module.ts b/src/app/+item-page/edit-item-page/edit-item-page.routing.module.ts index 0e36cc9894..b7d650d8c3 100644 --- a/src/app/+item-page/edit-item-page/edit-item-page.routing.module.ts +++ b/src/app/+item-page/edit-item-page/edit-item-page.routing.module.ts @@ -22,10 +22,10 @@ import { ResourcePolicyEditComponent } from '../../shared/resource-policies/edit import { I18nBreadcrumbsService } from '../../core/breadcrumbs/i18n-breadcrumbs.service'; import { ITEM_EDIT_AUTHORIZATIONS_PATH, - ITEM_EDIT_MOVE_PATH, ITEM_EDIT_DELETE_PATH, - ITEM_EDIT_PUBLIC_PATH, + ITEM_EDIT_MOVE_PATH, ITEM_EDIT_PRIVATE_PATH, + ITEM_EDIT_PUBLIC_PATH, ITEM_EDIT_REINSTATE_PATH, ITEM_EDIT_WITHDRAW_PATH } from './edit-item-page.routing-paths'; @@ -33,7 +33,6 @@ import { ItemPageReinstateGuard } from './item-page-reinstate.guard'; import { ItemPageWithdrawGuard } from './item-page-withdraw.guard'; import { ItemPageEditMetadataGuard } from '../item-page-edit-metadata.guard'; import { ItemPageAdministratorGuard } from '../item-page-administrator.guard'; -import { AuthenticatedGuard } from '../../core/auth/authenticated.guard'; /** * Routing module that handles the routing for the Edit Item page administrator functionality From 0c99557010b5f8ce9762fc5c8418f1fcc63e7eb0 Mon Sep 17 00:00:00 2001 From: Samuel Date: Wed, 24 Mar 2021 16:46:05 +0100 Subject: [PATCH 104/132] fix #1067 UI sends wrong request when creating new metadata field without qualifier --- .../core/registry/registry.service.spec.ts | 38 +++++++++++++++++++ src/app/core/registry/registry.service.ts | 6 +++ 2 files changed, 44 insertions(+) diff --git a/src/app/core/registry/registry.service.spec.ts b/src/app/core/registry/registry.service.spec.ts index fdfe1c9fac..5f2f123f01 100644 --- a/src/app/core/registry/registry.service.spec.ts +++ b/src/app/core/registry/registry.service.spec.ts @@ -326,6 +326,25 @@ describe('RegistryService', () => { }); }); + describe('when createMetadataField is called with a blank qualifier', () => { + let result: Observable; + let metadataField: MetadataField; + + beforeEach(() => { + metadataField = mockFieldsList[0]; + metadataField.qualifier = ''; + result = registryService.createMetadataField(metadataField, mockSchemasList[0]); + }); + + it('should return the created metadata field with a null qualifier', (done) => { + metadataField.qualifier = null; + result.subscribe((field: MetadataField) => { + expect(field).toEqual(metadataField); + done(); + }); + }); + }); + describe('when updateMetadataField is called', () => { let result: Observable; @@ -341,6 +360,25 @@ describe('RegistryService', () => { }); }); + describe('when updateMetadataField is called with a blank qualifier', () => { + let result: Observable; + let metadataField: MetadataField; + + beforeEach(() => { + metadataField = mockFieldsList[0]; + metadataField.qualifier = ''; + result = registryService.updateMetadataField(metadataField); + }); + + it('should return the updated metadata field with a null qualifier', (done) => { + metadataField.qualifier = null; + result.subscribe((field: MetadataField) => { + expect(field).toEqual(metadataField); + done(); + }); + }); + }); + describe('when deleteMetadataSchema is called', () => { let result: Observable>; diff --git a/src/app/core/registry/registry.service.ts b/src/app/core/registry/registry.service.ts index 9ac849bdd3..b7b35c6a5a 100644 --- a/src/app/core/registry/registry.service.ts +++ b/src/app/core/registry/registry.service.ts @@ -245,6 +245,9 @@ export class RegistryService { * @param schema The MetadataSchema to create the field in */ public createMetadataField(field: MetadataField, schema: MetadataSchema): Observable { + if (!field.qualifier) { + field.qualifier = null; + } return this.metadataFieldService.create(field, new RequestParam('schemaId', schema.id)).pipe( getFirstSucceededRemoteDataPayload(), hasValueOperator(), @@ -260,6 +263,9 @@ export class RegistryService { * @param field The MetadataField to update */ public updateMetadataField(field: MetadataField): Observable { + if (!field.qualifier) { + field.qualifier = null; + } return this.metadataFieldService.put(field).pipe( getFirstSucceededRemoteDataPayload(), hasValueOperator(), From 2f7060a7528048b6dbf138414291ec88ee32436e Mon Sep 17 00:00:00 2001 From: Art Lowel Date: Mon, 15 Mar 2021 14:07:43 +0100 Subject: [PATCH 105/132] fix issue where stale remotedata objects could be returned first from findBy methods on dataservices --- src/app/core/data/data.service.spec.ts | 484 ++++++++++++++++++++++++- src/app/core/data/data.service.ts | 62 ++-- 2 files changed, 519 insertions(+), 27 deletions(-) diff --git a/src/app/core/data/data.service.spec.ts b/src/app/core/data/data.service.spec.ts index a8bbfa79a0..88b15754af 100644 --- a/src/app/core/data/data.service.spec.ts +++ b/src/app/core/data/data.service.spec.ts @@ -20,6 +20,9 @@ import { getMockRequestService } from '../../shared/mocks/request.service.mock'; import { HALEndpointServiceStub } from '../../shared/testing/hal-endpoint-service.stub'; import { RequestParam } from '../cache/models/request-param.model'; import { getMockRemoteDataBuildService } from '../../shared/mocks/remote-data-build.service.mock'; +import { TestScheduler } from 'rxjs/testing'; +import { RemoteData } from './remote-data'; +import { RequestEntryState } from './request.reducer'; const endpoint = 'https://rest.api/core'; @@ -63,6 +66,10 @@ describe('DataService', () => { let comparator; let objectCache; let store; + let selfLink; + let linksToFollow; + let testScheduler; + let remoteDataMocks; function initTestService(): TestService { requestService = getMockRequestService(); @@ -81,6 +88,34 @@ describe('DataService', () => { } } as any; store = {} as Store; + selfLink = 'https://rest.api/endpoint/1698f1d3-be98-4c51-9fd8-6bfedcbd59b7'; + linksToFollow = [ + followLink('a'), + followLink('b') + ]; + + testScheduler = new TestScheduler((actual, expected) => { + // asserting the two objects are equal + // e.g. using chai. + expect(actual).toEqual(expected); + }); + + const timeStamp = new Date().getTime(); + const msToLive = 15 * 60 * 1000; + const payload = { foo: 'bar' }; + const statusCodeSuccess = 200; + const statusCodeError = 404; + const errorMessage = 'not found'; + remoteDataMocks = { + RequestPending: new RemoteData(undefined, msToLive, timeStamp, RequestEntryState.RequestPending, undefined, undefined, undefined), + ResponsePending: new RemoteData(undefined, msToLive, timeStamp, RequestEntryState.ResponsePending, undefined, undefined, undefined), + Success: new RemoteData(timeStamp, msToLive, timeStamp, RequestEntryState.Success, undefined, payload, statusCodeSuccess), + SuccessStale: new RemoteData(timeStamp, msToLive, timeStamp, RequestEntryState.SuccessStale, undefined, payload, statusCodeSuccess), + Error: new RemoteData(timeStamp, msToLive, timeStamp, RequestEntryState.Error, errorMessage, undefined, statusCodeError), + ErrorStale: new RemoteData(timeStamp, msToLive, timeStamp, RequestEntryState.ErrorStale, errorMessage, undefined, statusCodeError), + }; + + return new TestService( requestService, rdbService, @@ -307,14 +342,12 @@ describe('DataService', () => { describe('update', () => { let operations; - let selfLink; let dso; let dso2; const name1 = 'random string'; const name2 = 'another random string'; beforeEach(() => { operations = [{ op: 'replace', path: '/0/value', value: name2 } as Operation]; - selfLink = 'https://rest.api/endpoint/1698f1d3-be98-4c51-9fd8-6bfedcbd59b7'; dso = Object.assign(new DSpaceObject(), { _links: { self: { href: selfLink } }, @@ -340,5 +373,452 @@ describe('DataService', () => { expect(objectCache.addPatch).not.toHaveBeenCalled(); }); }); + + describe(`reRequestStaleRemoteData`, () => { + let callback: jasmine.Spy; + + beforeEach(() => { + callback = jasmine.createSpy(); + }); + + + describe(`when shouldReRequest is false`, () => { + it(`shouldn't do anything`, () => { + testScheduler.run(({ cold, expectObservable, flush }) => { + const expected = 'a-b-c-d-e-f'; + const values = { + a: remoteDataMocks.RequestPending, + b: remoteDataMocks.ResponsePending, + c: remoteDataMocks.Success, + d: remoteDataMocks.SuccessStale, + e: remoteDataMocks.Error, + f: remoteDataMocks.ErrorStale, + }; + + expectObservable((service as any).reRequestStaleRemoteData(false, callback)(cold(expected, values))).toBe(expected, values); + // since the callback happens in a tap(), flush to ensure it has been executed + flush(); + expect(callback).not.toHaveBeenCalled(); + }); + }); + }); + + describe(`when shouldReRequest is true`, () => { + it(`should call the callback for stale RemoteData objects, but still pass the source observable unmodified`, () => { + testScheduler.run(({ cold, expectObservable, flush }) => { + const expected = 'a-b'; + const values = { + a: remoteDataMocks.SuccessStale, + b: remoteDataMocks.ErrorStale, + }; + + expectObservable((service as any).reRequestStaleRemoteData(true, callback)(cold(expected, values))).toBe(expected, values); + // since the callback happens in a tap(), flush to ensure it has been executed + flush(); + expect(callback).toHaveBeenCalledTimes(2); + }); + }); + + it(`should only call the callback for stale RemoteData objects if something is subscribed to it`, (done) => { + testScheduler.run(({ cold, expectObservable }) => { + const expected = 'a'; + const values = { + a: remoteDataMocks.SuccessStale, + }; + + const result$ = (service as any).reRequestStaleRemoteData(true, callback)(cold(expected, values)); + expectObservable(result$).toBe(expected, values); + expect(callback).not.toHaveBeenCalled(); + result$.subscribe(() => { + expect(callback).toHaveBeenCalled(); + done(); + }); + }); + }); + + it(`shouldn't do anything for RemoteData objects that aren't stale`, () => { + testScheduler.run(({ cold, expectObservable, flush }) => { + const expected = 'a-b-c-d'; + const values = { + a: remoteDataMocks.RequestPending, + b: remoteDataMocks.ResponsePending, + c: remoteDataMocks.Success, + d: remoteDataMocks.Error, + }; + + expectObservable((service as any).reRequestStaleRemoteData(true, callback)(cold(expected, values))).toBe(expected, values); + // since the callback happens in a tap(), flush to ensure it has been executed + flush(); + expect(callback).not.toHaveBeenCalled(); + }); + }); + }); + + }); + + describe(`findByHref`, () => { + beforeEach(() => { + spyOn(service as any, 'createAndSendGetRequest').and.callFake((href$) => { href$.subscribe().unsubscribe(); }); + }); + + it(`should call buildHrefFromFindOptions with href and linksToFollow`, () => { + testScheduler.run(({ cold }) => { + spyOn(service, 'buildHrefFromFindOptions').and.returnValue(selfLink); + spyOn(rdbService, 'buildSingle').and.returnValue(cold('a', { a: remoteDataMocks.Success })); + spyOn(service as any, 'reRequestStaleRemoteData').and.returnValue(() => cold('a', { a: remoteDataMocks.Success })); + + service.findByHref(selfLink, true, true, ...linksToFollow); + expect(service.buildHrefFromFindOptions).toHaveBeenCalledWith(selfLink, {}, [], ...linksToFollow); + }); + }); + + it(`should call createAndSendGetRequest with the result from buildHrefFromFindOptions and useCachedVersionIfAvailable`, () => { + testScheduler.run(({ cold, expectObservable }) => { + spyOn(service, 'buildHrefFromFindOptions').and.returnValue('bingo!'); + spyOn(rdbService, 'buildSingle').and.returnValue(cold('a', { a: remoteDataMocks.Success })); + spyOn(service as any, 'reRequestStaleRemoteData').and.returnValue(() => cold('a', { a: remoteDataMocks.Success })); + + service.findByHref(selfLink, true, true, ...linksToFollow); + expect((service as any).createAndSendGetRequest).toHaveBeenCalledWith(jasmine.anything(), true); + expectObservable(rdbService.buildSingle.calls.argsFor(0)[0]).toBe('(a|)', { a: 'bingo!' }); + + service.findByHref(selfLink, false, true, ...linksToFollow); + expect((service as any).createAndSendGetRequest).toHaveBeenCalledWith(jasmine.anything(), false); + expectObservable(rdbService.buildSingle.calls.argsFor(1)[0]).toBe('(a|)', { a: 'bingo!' }); + }); + }); + + it(`should call rdbService.buildSingle with the result from buildHrefFromFindOptions and linksToFollow`, () => { + testScheduler.run(({ cold, expectObservable }) => { + spyOn(service, 'buildHrefFromFindOptions').and.returnValue('bingo!'); + spyOn(rdbService, 'buildSingle').and.returnValue(cold('a', { a: remoteDataMocks.Success })); + spyOn(service as any, 'reRequestStaleRemoteData').and.returnValue(() => cold('a', { a: remoteDataMocks.Success })); + + service.findByHref(selfLink, true, true, ...linksToFollow); + expect(rdbService.buildSingle).toHaveBeenCalledWith(jasmine.anything() as any, ...linksToFollow); + expectObservable(rdbService.buildSingle.calls.argsFor(0)[0]).toBe('(a|)', { a: 'bingo!' }); + }); + }); + + it(`should return a the output from reRequestStaleRemoteData`, () => { + testScheduler.run(({ cold, expectObservable }) => { + spyOn(service, 'buildHrefFromFindOptions').and.returnValue(selfLink); + spyOn(rdbService, 'buildSingle').and.returnValue(cold('a', { a: remoteDataMocks.Success })); + spyOn(service as any, 'reRequestStaleRemoteData').and.returnValue(() => cold('a', { a: 'bingo!' })); + const expected = 'a'; + const values = { + a: 'bingo!', + }; + + expectObservable(service.findByHref(selfLink, true, true, ...linksToFollow)).toBe(expected, values); + }); + }); + + it(`should call reRequestStaleRemoteData with reRequestOnStale and the exact same findByHref call as a callback`, () => { + testScheduler.run(({ cold, expectObservable }) => { + spyOn(service, 'buildHrefFromFindOptions').and.returnValue(selfLink); + spyOn(rdbService, 'buildSingle').and.returnValue(cold('a', { a: remoteDataMocks.SuccessStale })); + spyOn(service as any, 'reRequestStaleRemoteData').and.returnValue(() => cold('a', { a: remoteDataMocks.SuccessStale })); + + service.findByHref(selfLink, true, true, ...linksToFollow); + expect((service as any).reRequestStaleRemoteData.calls.argsFor(0)[0]).toBeTrue(); + spyOn(service, 'findByHref').and.returnValue(cold('a', { a: remoteDataMocks.SuccessStale })); + // prove that the spy we just added hasn't been called yet + expect(service.findByHref).not.toHaveBeenCalled(); + // call the callback passed to reRequestStaleRemoteData + (service as any).reRequestStaleRemoteData.calls.argsFor(0)[1](); + // verify that findByHref _has_ been called now, with the same params as the original call + expect(service.findByHref).toHaveBeenCalledWith(jasmine.anything(), true, true, ...linksToFollow); + // ... except for selflink, which will have been turned in to an observable. + expectObservable((service.findByHref as jasmine.Spy).calls.argsFor(0)[0]).toBe('(a|)', { a: selfLink }); + }); + }); + + describe(`when useCachedVersionIfAvailable is true`, () => { + beforeEach(() => { + spyOn(service, 'buildHrefFromFindOptions').and.returnValue(selfLink); + spyOn(service as any, 'reRequestStaleRemoteData').and.callFake(() => (source) => source); + }); + + it(`should emit a cached completed RemoteData immediately, and keep emitting if it gets rerequested`, () => { + testScheduler.run(({ cold, expectObservable }) => { + spyOn(rdbService, 'buildSingle').and.returnValue(cold('a-b-c-d-e', { + a: remoteDataMocks.Success, + b: remoteDataMocks.RequestPending, + c: remoteDataMocks.ResponsePending, + d: remoteDataMocks.Success, + e: remoteDataMocks.SuccessStale, + })); + const expected = 'a-b-c-d-e'; + const values = { + a: remoteDataMocks.Success, + b: remoteDataMocks.RequestPending, + c: remoteDataMocks.ResponsePending, + d: remoteDataMocks.Success, + e: remoteDataMocks.SuccessStale, + }; + + expectObservable(service.findByHref(selfLink, true, true, ...linksToFollow)).toBe(expected, values); + }); + }); + + it(`should not emit a cached stale RemoteData, but only start emitting after the state first changes to RequestPending`, () => { + testScheduler.run(({ cold, expectObservable }) => { + spyOn(rdbService, 'buildSingle').and.returnValue(cold('a-b-c-d-e', { + a: remoteDataMocks.SuccessStale, + b: remoteDataMocks.RequestPending, + c: remoteDataMocks.ResponsePending, + d: remoteDataMocks.Success, + e: remoteDataMocks.SuccessStale, + })); + const expected = '--b-c-d-e'; + const values = { + b: remoteDataMocks.RequestPending, + c: remoteDataMocks.ResponsePending, + d: remoteDataMocks.Success, + e: remoteDataMocks.SuccessStale, + }; + + expectObservable(service.findByHref(selfLink, true, true, ...linksToFollow)).toBe(expected, values); + }); + }); + + }); + + describe(`when useCachedVersionIfAvailable is false`, () => { + beforeEach(() => { + spyOn(service, 'buildHrefFromFindOptions').and.returnValue(selfLink); + spyOn(service as any, 'reRequestStaleRemoteData').and.callFake(() => (source) => source); + }); + + + it(`should not emit a cached completed RemoteData, but only start emitting after the state first changes to RequestPending`, () => { + testScheduler.run(({ cold, expectObservable }) => { + spyOn(rdbService, 'buildSingle').and.returnValue(cold('a-b-c-d-e', { + a: remoteDataMocks.Success, + b: remoteDataMocks.RequestPending, + c: remoteDataMocks.ResponsePending, + d: remoteDataMocks.Success, + e: remoteDataMocks.SuccessStale, + })); + const expected = '--b-c-d-e'; + const values = { + b: remoteDataMocks.RequestPending, + c: remoteDataMocks.ResponsePending, + d: remoteDataMocks.Success, + e: remoteDataMocks.SuccessStale, + }; + + expectObservable(service.findByHref(selfLink, false, true, ...linksToFollow)).toBe(expected, values); + }); + }); + + it(`should not emit a cached stale RemoteData, but only start emitting after the state first changes to RequestPending`, () => { + testScheduler.run(({ cold, expectObservable }) => { + spyOn(rdbService, 'buildSingle').and.returnValue(cold('a-b-c-d-e', { + a: remoteDataMocks.SuccessStale, + b: remoteDataMocks.RequestPending, + c: remoteDataMocks.ResponsePending, + d: remoteDataMocks.Success, + e: remoteDataMocks.SuccessStale, + })); + const expected = '--b-c-d-e'; + const values = { + b: remoteDataMocks.RequestPending, + c: remoteDataMocks.ResponsePending, + d: remoteDataMocks.Success, + e: remoteDataMocks.SuccessStale, + }; + + expectObservable(service.findByHref(selfLink, false, true, ...linksToFollow)).toBe(expected, values); + }); + }); + + }); + + }); + + describe(`findAllByHref`, () => { + let findListOptions; + beforeEach(() => { + findListOptions = { currentPage: 5 }; + spyOn(service as any, 'createAndSendGetRequest').and.callFake((href$) => { href$.subscribe().unsubscribe(); }); + }); + + it(`should call buildHrefFromFindOptions with href and linksToFollow`, () => { + testScheduler.run(({ cold }) => { + spyOn(service, 'buildHrefFromFindOptions').and.returnValue(selfLink); + spyOn(rdbService, 'buildList').and.returnValue(cold('a', { a: remoteDataMocks.Success })); + spyOn(service as any, 'reRequestStaleRemoteData').and.returnValue(() => cold('a', { a: remoteDataMocks.Success })); + + service.findAllByHref(selfLink, findListOptions, true, true, ...linksToFollow); + expect(service.buildHrefFromFindOptions).toHaveBeenCalledWith(selfLink, findListOptions, [], ...linksToFollow); + }); + }); + + it(`should call createAndSendGetRequest with the result from buildHrefFromFindOptions and useCachedVersionIfAvailable`, () => { + testScheduler.run(({ cold, expectObservable }) => { + spyOn(service, 'buildHrefFromFindOptions').and.returnValue('bingo!'); + spyOn(rdbService, 'buildList').and.returnValue(cold('a', { a: remoteDataMocks.Success })); + spyOn(service as any, 'reRequestStaleRemoteData').and.returnValue(() => cold('a', { a: remoteDataMocks.Success })); + + service.findAllByHref(selfLink, findListOptions, true, true, ...linksToFollow); + expect((service as any).createAndSendGetRequest).toHaveBeenCalledWith(jasmine.anything(), true); + expectObservable(rdbService.buildList.calls.argsFor(0)[0]).toBe('(a|)', { a: 'bingo!' }); + + service.findAllByHref(selfLink, findListOptions, false, true, ...linksToFollow); + expect((service as any).createAndSendGetRequest).toHaveBeenCalledWith(jasmine.anything(), false); + expectObservable(rdbService.buildList.calls.argsFor(1)[0]).toBe('(a|)', { a: 'bingo!' }); + }); + }); + + it(`should call rdbService.buildList with the result from buildHrefFromFindOptions and linksToFollow`, () => { + testScheduler.run(({ cold, expectObservable }) => { + spyOn(service, 'buildHrefFromFindOptions').and.returnValue('bingo!'); + spyOn(rdbService, 'buildList').and.returnValue(cold('a', { a: remoteDataMocks.Success })); + spyOn(service as any, 'reRequestStaleRemoteData').and.returnValue(() => cold('a', { a: remoteDataMocks.Success })); + + service.findAllByHref(selfLink, findListOptions, true, true, ...linksToFollow); + expect(rdbService.buildList).toHaveBeenCalledWith(jasmine.anything() as any, ...linksToFollow); + expectObservable(rdbService.buildList.calls.argsFor(0)[0]).toBe('(a|)', { a: 'bingo!' }); + }); + }); + + it(`should call reRequestStaleRemoteData with reRequestOnStale and the exact same findAllByHref call as a callback`, () => { + testScheduler.run(({ cold, expectObservable }) => { + spyOn(service, 'buildHrefFromFindOptions').and.returnValue('bingo!'); + spyOn(rdbService, 'buildList').and.returnValue(cold('a', { a: remoteDataMocks.SuccessStale })); + spyOn(service as any, 'reRequestStaleRemoteData').and.returnValue(() => cold('a', { a: remoteDataMocks.SuccessStale })); + + service.findAllByHref(selfLink, findListOptions, true, true, ...linksToFollow); + expect((service as any).reRequestStaleRemoteData.calls.argsFor(0)[0]).toBeTrue(); + spyOn(service, 'findAllByHref').and.returnValue(cold('a', { a: remoteDataMocks.SuccessStale })); + // prove that the spy we just added hasn't been called yet + expect(service.findAllByHref).not.toHaveBeenCalled(); + // call the callback passed to reRequestStaleRemoteData + (service as any).reRequestStaleRemoteData.calls.argsFor(0)[1](); + // verify that findAllByHref _has_ been called now, with the same params as the original call + expect(service.findAllByHref).toHaveBeenCalledWith(jasmine.anything(), findListOptions, true, true, ...linksToFollow); + // ... except for selflink, which will have been turned in to an observable. + expectObservable((service.findAllByHref as jasmine.Spy).calls.argsFor(0)[0]).toBe('(a|)', { a: selfLink }); + }); + }); + + it(`should return a the output from reRequestStaleRemoteData`, () => { + testScheduler.run(({ cold, expectObservable }) => { + spyOn(service, 'buildHrefFromFindOptions').and.returnValue(selfLink); + spyOn(rdbService, 'buildList').and.returnValue(cold('a', { a: remoteDataMocks.Success })); + spyOn(service as any, 'reRequestStaleRemoteData').and.returnValue(() => cold('a', { a: 'bingo!' })); + const expected = 'a'; + const values = { + a: 'bingo!', + }; + + expectObservable(service.findAllByHref(selfLink, findListOptions, true, true, ...linksToFollow)).toBe(expected, values); + }); + }); + + describe(`when useCachedVersionIfAvailable is true`, () => { + beforeEach(() => { + spyOn(service, 'buildHrefFromFindOptions').and.returnValue(selfLink); + spyOn(service as any, 'reRequestStaleRemoteData').and.callFake(() => (source) => source); + }); + + it(`should emit a cached completed RemoteData immediately, and keep emitting if it gets rerequested`, () => { + testScheduler.run(({ cold, expectObservable }) => { + spyOn(rdbService, 'buildList').and.returnValue(cold('a-b-c-d-e', { + a: remoteDataMocks.Success, + b: remoteDataMocks.RequestPending, + c: remoteDataMocks.ResponsePending, + d: remoteDataMocks.Success, + e: remoteDataMocks.SuccessStale, + })); + const expected = 'a-b-c-d-e'; + const values = { + a: remoteDataMocks.Success, + b: remoteDataMocks.RequestPending, + c: remoteDataMocks.ResponsePending, + d: remoteDataMocks.Success, + e: remoteDataMocks.SuccessStale, + }; + + expectObservable(service.findAllByHref(selfLink, findListOptions, true, true, ...linksToFollow)).toBe(expected, values); + }); + }); + + it(`should not emit a cached stale RemoteData, but only start emitting after the state first changes to RequestPending`, () => { + testScheduler.run(({ cold, expectObservable }) => { + spyOn(rdbService, 'buildList').and.returnValue(cold('a-b-c-d-e', { + a: remoteDataMocks.SuccessStale, + b: remoteDataMocks.RequestPending, + c: remoteDataMocks.ResponsePending, + d: remoteDataMocks.Success, + e: remoteDataMocks.SuccessStale, + })); + const expected = '--b-c-d-e'; + const values = { + b: remoteDataMocks.RequestPending, + c: remoteDataMocks.ResponsePending, + d: remoteDataMocks.Success, + e: remoteDataMocks.SuccessStale, + }; + + expectObservable(service.findAllByHref(selfLink, findListOptions, true, true, ...linksToFollow)).toBe(expected, values); + }); + }); + + }); + + describe(`when useCachedVersionIfAvailable is false`, () => { + beforeEach(() => { + spyOn(service, 'buildHrefFromFindOptions').and.returnValue(selfLink); + spyOn(service as any, 'reRequestStaleRemoteData').and.callFake(() => (source) => source); + }); + + + it(`should not emit a cached completed RemoteData, but only start emitting after the state first changes to RequestPending`, () => { + testScheduler.run(({ cold, expectObservable }) => { + spyOn(rdbService, 'buildList').and.returnValue(cold('a-b-c-d-e', { + a: remoteDataMocks.Success, + b: remoteDataMocks.RequestPending, + c: remoteDataMocks.ResponsePending, + d: remoteDataMocks.Success, + e: remoteDataMocks.SuccessStale, + })); + const expected = '--b-c-d-e'; + const values = { + b: remoteDataMocks.RequestPending, + c: remoteDataMocks.ResponsePending, + d: remoteDataMocks.Success, + e: remoteDataMocks.SuccessStale, + }; + + expectObservable(service.findAllByHref(selfLink, findListOptions, false, true, ...linksToFollow)).toBe(expected, values); + }); + }); + + it(`should not emit a cached stale RemoteData, but only start emitting after the state first changes to RequestPending`, () => { + testScheduler.run(({ cold, expectObservable }) => { + spyOn(rdbService, 'buildList').and.returnValue(cold('a-b-c-d-e', { + a: remoteDataMocks.SuccessStale, + b: remoteDataMocks.RequestPending, + c: remoteDataMocks.ResponsePending, + d: remoteDataMocks.Success, + e: remoteDataMocks.SuccessStale, + })); + const expected = '--b-c-d-e'; + const values = { + b: remoteDataMocks.RequestPending, + c: remoteDataMocks.ResponsePending, + d: remoteDataMocks.Success, + e: remoteDataMocks.SuccessStale, + }; + + expectObservable(service.findAllByHref(selfLink, findListOptions, false, true, ...linksToFollow)).toBe(expected, values); + }); + }); + + }); + }); }); /* tslint:enable:max-classes-per-file */ diff --git a/src/app/core/data/data.service.ts b/src/app/core/data/data.service.ts index 814c281a37..6bad02e776 100644 --- a/src/app/core/data/data.service.ts +++ b/src/app/core/data/data.service.ts @@ -12,6 +12,7 @@ import { takeWhile, switchMap, tap, + skipWhile, } from 'rxjs/operators'; import { hasValue, isNotEmpty, isNotEmptyOperator } from '../../shared/empty.util'; import { NotificationOptions } from '../../shared/notifications/models/notification-options.model'; @@ -45,29 +46,6 @@ import { UpdateDataService } from './update-data.service'; import { GenericConstructor } from '../shared/generic-constructor'; import { NoContent } from '../shared/NoContent.model'; -/** - * An operator that will call the given function if the incoming RemoteData is stale and - * shouldReRequest is true - * - * @param shouldReRequest Whether or not to call the re-request function if the RemoteData is stale - * @param requestFn The function to call if the RemoteData is stale and shouldReRequest is - * true - */ -export const reRequestStaleRemoteData = (shouldReRequest: boolean, requestFn: () => Observable>) => - (source: Observable>): Observable> => { - if (shouldReRequest === true) { - return source.pipe( - tap((remoteData: RemoteData) => { - if (hasValue(remoteData) && remoteData.isStale) { - requestFn(); - } - }) - ); - } else { - return source; - } - }; - export abstract class DataService implements UpdateDataService { protected abstract requestService: RequestService; protected abstract rdbService: RemoteDataBuildService; @@ -332,6 +310,30 @@ export abstract class DataService implements UpdateDa return this.findByHref(href$, useCachedVersionIfAvailable, reRequestOnStale, ...linksToFollow); } + /** + * An operator that will call the given function if the incoming RemoteData is stale and + * shouldReRequest is true + * + * @param shouldReRequest Whether or not to call the re-request function if the RemoteData is stale + * @param requestFn The function to call if the RemoteData is stale and shouldReRequest is + * true + */ + protected reRequestStaleRemoteData(shouldReRequest: boolean, requestFn: () => Observable>) { + return (source: Observable>): Observable> => { + if (shouldReRequest === true) { + return source.pipe( + tap((remoteData: RemoteData) => { + if (hasValue(remoteData) && remoteData.isStale) { + requestFn(); + } + }) + ); + } else { + return source; + } + }; + } + /** * Returns an observable of {@link RemoteData} of an object, based on an href, with a list of * {@link FollowLinkConfig}, to automatically resolve {@link HALLink}s of the object @@ -358,7 +360,12 @@ export abstract class DataService implements UpdateDa this.createAndSendGetRequest(requestHref$, useCachedVersionIfAvailable); return this.rdbService.buildSingle(requestHref$, ...linksToFollow).pipe( - reRequestStaleRemoteData(reRequestOnStale, () => + // This skip ensures that if a stale object is present in the cache when you do a + // call it isn't immediately returned, but we wait until the remote data for the new request + // is created. If useCachedVersionIfAvailable is false it also ensures you don't get a + // cached completed object + skipWhile((rd: RemoteData) => useCachedVersionIfAvailable ? rd.isStale : rd.hasCompleted), + this.reRequestStaleRemoteData(reRequestOnStale, () => this.findByHref(href$, useCachedVersionIfAvailable, reRequestOnStale, ...linksToFollow)) ); } @@ -390,7 +397,12 @@ export abstract class DataService implements UpdateDa this.createAndSendGetRequest(requestHref$, useCachedVersionIfAvailable); return this.rdbService.buildList(requestHref$, ...linksToFollow).pipe( - reRequestStaleRemoteData(reRequestOnStale, () => + // This skip ensures that if a stale object is present in the cache when you do a + // call it isn't immediately returned, but we wait until the remote data for the new request + // is created. If useCachedVersionIfAvailable is false it also ensures you don't get a + // cached completed object + skipWhile((rd: RemoteData>) => useCachedVersionIfAvailable ? rd.isStale : rd.hasCompleted), + this.reRequestStaleRemoteData(reRequestOnStale, () => this.findAllByHref(href$, findListOptions, useCachedVersionIfAvailable, reRequestOnStale, ...linksToFollow)) ); } From 9964f07ff676dca0f0bd6ee3a0b269e614793d32 Mon Sep 17 00:00:00 2001 From: Art Lowel Date: Mon, 15 Mar 2021 13:59:29 +0100 Subject: [PATCH 106/132] rewrite community scope test that sometimes failed at random --- src/app/core/data/comcol-data.service.spec.ts | 32 +++++++++++++------ 1 file changed, 23 insertions(+), 9 deletions(-) diff --git a/src/app/core/data/comcol-data.service.spec.ts b/src/app/core/data/comcol-data.service.spec.ts index 94b050855a..b188f4b50a 100644 --- a/src/app/core/data/comcol-data.service.spec.ts +++ b/src/app/core/data/comcol-data.service.spec.ts @@ -1,6 +1,6 @@ import { HttpClient } from '@angular/common/http'; import { Store } from '@ngrx/store'; -import { cold, getTestScheduler, hot } from 'jasmine-marbles'; +import { cold, getTestScheduler } from 'jasmine-marbles'; import { Observable, of as observableOf } from 'rxjs'; import { TestScheduler } from 'rxjs/testing'; import { getMockRequestService } from '../../shared/mocks/request.service.mock'; @@ -19,10 +19,10 @@ import { RequestService } from './request.service'; import { createFailedRemoteDataObject$, createNoContentRemoteDataObject$, - createSuccessfulRemoteDataObject$ + createSuccessfulRemoteDataObject$, + createFailedRemoteDataObject } from '../../shared/remote-data.utils'; import { BitstreamDataService } from './bitstream-data.service'; -import { take } from 'rxjs/operators'; const LINK_NAME = 'test'; @@ -59,6 +59,7 @@ describe('ComColDataService', () => { let halService: any = {}; let bitstreamDataService: BitstreamDataService; let rdbService: RemoteDataBuildService; + let testScheduler: TestScheduler; const store = {} as Store; const notificationsService = {} as NotificationsService; @@ -98,8 +99,8 @@ describe('ComColDataService', () => { } function initMockCommunityDataService(): CommunityDataService { - return jasmine.createSpyObj('responseCache', { - getEndpoint: hot('--a-', { a: communitiesEndpoint }), + return jasmine.createSpyObj('cds', { + getEndpoint: cold('--a-', { a: communitiesEndpoint }), getIDHref: communityEndpoint }); } @@ -134,7 +135,14 @@ describe('ComColDataService', () => { ); } + const initTestScheduler = (): TestScheduler => { + return new TestScheduler((actual, expected) => { + expect(actual).toEqual(expected); + }); + }; + beforeEach(() => { + testScheduler = initTestScheduler(); cds = initMockCommunityDataService(); requestService = getMockRequestService(); objectCache = initMockObjectCacheService(); @@ -165,10 +173,16 @@ describe('ComColDataService', () => { describe('if the scope Community can\'t be found', () => { it('should throw an error', () => { - const result = service.getBrowseEndpoint(options).pipe(take(1)); - const expected = cold('--#-', undefined, new Error(`The Community with scope ${scopeID} couldn't be retrieved`)); - - expect(result).toBeObservable(expected); + // tslint:disable-next-line:no-shadowed-variable + testScheduler.run(({ cold, expectObservable }) => { + // spies re-defined here to use the "cold" function from rxjs's TestScheduler + // rather than the one imported from jasmine-marbles. + // Mixing the two seems to lead to unpredictable results + (cds.getEndpoint as jasmine.Spy).and.returnValue(cold('a', { a: communitiesEndpoint })); + (rdbService.buildSingle as jasmine.Spy).and.returnValue(cold('a', { a: createFailedRemoteDataObject() })); + const expectedError = new Error(`The Community with scope ${scopeID} couldn't be retrieved`); + expectObservable(service.getBrowseEndpoint(options)).toBe('#', undefined, expectedError); + }); }); }); From 4a15720b4b1c09f42a7349c4c52fded174bbcc9e Mon Sep 17 00:00:00 2001 From: Art Lowel Date: Tue, 16 Mar 2021 12:55:15 +0100 Subject: [PATCH 107/132] rewrite all comcoldataservice tests in hopes of catching the one that sometimes fails at random --- src/app/core/data/comcol-data.service.spec.ts | 178 +++++++----------- 1 file changed, 73 insertions(+), 105 deletions(-) diff --git a/src/app/core/data/comcol-data.service.spec.ts b/src/app/core/data/comcol-data.service.spec.ts index b188f4b50a..864c583dc2 100644 --- a/src/app/core/data/comcol-data.service.spec.ts +++ b/src/app/core/data/comcol-data.service.spec.ts @@ -1,6 +1,6 @@ import { HttpClient } from '@angular/common/http'; import { Store } from '@ngrx/store'; -import { cold, getTestScheduler } from 'jasmine-marbles'; +import { cold } from 'jasmine-marbles'; import { Observable, of as observableOf } from 'rxjs'; import { TestScheduler } from 'rxjs/testing'; import { getMockRequestService } from '../../shared/mocks/request.service.mock'; @@ -13,14 +13,13 @@ import { HALEndpointService } from '../shared/hal-endpoint.service'; import { ComColDataService } from './comcol-data.service'; import { CommunityDataService } from './community-data.service'; import { DSOChangeAnalyzer } from './dso-change-analyzer.service'; -import { FindListOptions, GetRequest } from './request.models'; -import { RequestEntry } from './request.reducer'; +import { FindListOptions } from './request.models'; import { RequestService } from './request.service'; import { createFailedRemoteDataObject$, - createNoContentRemoteDataObject$, createSuccessfulRemoteDataObject$, - createFailedRemoteDataObject + createFailedRemoteDataObject, + createSuccessfulRemoteDataObject } from '../../shared/remote-data.utils'; import { BitstreamDataService } from './bitstream-data.service'; @@ -50,8 +49,8 @@ class TestService extends ComColDataService { } } +// tslint:disable:no-shadowed-variable describe('ComColDataService', () => { - let scheduler: TestScheduler; let service: TestService; let requestService: RequestService; let cds: CommunityDataService; @@ -60,6 +59,7 @@ describe('ComColDataService', () => { let bitstreamDataService: BitstreamDataService; let rdbService: RemoteDataBuildService; let testScheduler: TestScheduler; + let topEndpoint: string; const store = {} as Store; const notificationsService = {} as NotificationsService; @@ -70,17 +70,9 @@ describe('ComColDataService', () => { const options = Object.assign(new FindListOptions(), { scopeID: scopeID }); - const getRequestEntry$ = (successful: boolean) => { - return observableOf({ - response: { isSuccessful: successful } as any - } as RequestEntry); - }; - const communitiesEndpoint = 'https://rest.api/core/communities'; const communityEndpoint = `${communitiesEndpoint}/${scopeID}`; const scopedEndpoint = `${communityEndpoint}/${LINK_NAME}`; - const serviceEndpoint = `https://rest.api/core/${LINK_NAME}`; - const authHeader = 'Bearer eyJhbGciOiJIUzI1NiJ9.eyJlaWQiOiJhNjA4NmIzNC0zOTE4LTQ1YjctOGRkZC05MzI5YTcwMmEyNmEiLCJzZyI6W10sImV4cCI6MTUzNDk0MDcyNX0.RV5GAtiX6cpwBN77P_v16iG9ipeyiO7faNYSNMzq_sQ'; const mockHalService = { getEndpoint: (linkPath) => observableOf(communitiesEndpoint) @@ -142,6 +134,7 @@ describe('ComColDataService', () => { }; beforeEach(() => { + topEndpoint = 'https://rest.api/core/communities/search/top'; testScheduler = initTestScheduler(); cds = initMockCommunityDataService(); requestService = getMockRequestService(); @@ -153,27 +146,20 @@ describe('ComColDataService', () => { }); describe('getBrowseEndpoint', () => { - beforeEach(() => { - scheduler = getTestScheduler(); - }); - - it('should send a new FindByIDRequest for the scope Community', () => { - cds = initMockCommunityDataService(); - requestService = getMockRequestService(getRequestEntry$(true)); - objectCache = initMockObjectCacheService(); - service = initTestService(); - - const expected = new GetRequest(requestService.generateRequestId(), communityEndpoint); - - scheduler.schedule(() => service.getBrowseEndpoint(options).subscribe()); - scheduler.flush(); - - expect(requestService.send).toHaveBeenCalledWith(expected, true); + it(`should call createAndSendGetRequest with the scope Community's self link`, () => { + testScheduler.run(({ cold, flush, expectObservable }) => { + (cds.getEndpoint as jasmine.Spy).and.returnValue(cold('a', { a: communitiesEndpoint })); + (rdbService.buildSingle as jasmine.Spy).and.returnValue(cold('a', { a: createFailedRemoteDataObject() })); + spyOn(service as any, 'createAndSendGetRequest'); + service.getBrowseEndpoint(options); + flush(); + expectObservable((service as any).createAndSendGetRequest.calls.argsFor(0)[0]).toBe('(a|)', { a: communityEndpoint }); + expect((service as any).createAndSendGetRequest.calls.argsFor(0)[1]).toBeTrue(); + }); }); describe('if the scope Community can\'t be found', () => { it('should throw an error', () => { - // tslint:disable-next-line:no-shadowed-variable testScheduler.run(({ cold, expectObservable }) => { // spies re-defined here to use the "cold" function from rxjs's TestScheduler // rather than the one imported from jasmine-marbles. @@ -186,86 +172,68 @@ describe('ComColDataService', () => { }); }); - describe('cache refresh', () => { - let communityWithoutParentHref; - let data; + }); - beforeEach(() => { - spyOn(halService, 'getEndpoint').and.returnValue(observableOf('https://rest.api/core/communities/search/top')); + describe('cache refresh', () => { + let communityWithoutParentHref; + let communityWithParentHref; + + beforeEach(() => { + communityWithParentHref = { + _links: { + parentCommunity: { + href: 'topLevel/parentCommunity' + } + } + } as Community; + communityWithoutParentHref = { + _links: {} + } as Community; + }); + + describe('cache refreshed top level community', () => { + it(`should refresh the top level community cache when the dso has a parent link that can't be resolved`, () => { + testScheduler.run(({ flush, cold }) => { + spyOn(halService, 'getEndpoint').and.returnValue(cold('a', { a: topEndpoint })); + spyOn(service, 'findByHref').and.returnValue(cold('a', { a: createSuccessfulRemoteDataObject({}) })); + service.refreshCache(communityWithParentHref); + flush(); + expect(requestService.setStaleByHrefSubstring).toHaveBeenCalledWith(topEndpoint); + }); }); - - describe('cache refreshed top level community', () => { - beforeEach(() => { - (rdbService.buildSingle as jasmine.Spy).and.returnValue(createNoContentRemoteDataObject$()); - data = { - dso: Object.assign(new Community(), { - metadata: [{ - key: 'dc.title', - value: 'top level community' - }] - }), - _links: { - parentCommunity: { - href: 'topLevel/parentCommunity' - } - } - }; - communityWithoutParentHref = { - dso: Object.assign(new Community(), { - metadata: [{ - key: 'dc.title', - value: 'top level community' - }] - }), - _links: {} - }; - }); - it('top level community cache refreshed', () => { - scheduler.schedule(() => (service as any).refreshCache(data)); - scheduler.flush(); - expect(requestService.setStaleByHrefSubstring).toHaveBeenCalledWith('https://rest.api/core/communities/search/top'); - }); - it('top level community without parent link, cache not refreshed', () => { - scheduler.schedule(() => (service as any).refreshCache(communityWithoutParentHref)); - scheduler.flush(); + it(`shouldn't do anything when the dso doesn't have a parent link`, () => { + testScheduler.run(({ flush, cold }) => { + spyOn(halService, 'getEndpoint').and.returnValue(cold('a', { a: topEndpoint })); + spyOn(service, 'findByHref').and.returnValue(cold('a', { a: createSuccessfulRemoteDataObject({}) })); + service.refreshCache(communityWithoutParentHref); + flush(); expect(requestService.setStaleByHrefSubstring).not.toHaveBeenCalled(); }); }); - - describe('cache refreshed child community', () => { - beforeEach(() => { - const parentCommunity = Object.assign(new Community(), { - uuid: 'a20da287-e174-466a-9926-f66as300d399', - id: 'a20da287-e174-466a-9926-f66as300d399', - metadata: [{ - key: 'dc.title', - value: 'parent community' - }], - _links: {} - }); - (rdbService.buildSingle as jasmine.Spy).and.returnValue(createSuccessfulRemoteDataObject$(parentCommunity)); - data = { - dso: Object.assign(new Community(), { - metadata: [{ - key: 'dc.title', - value: 'child community' - }] - }), - _links: { - parentCommunity: { - href: 'child/parentCommunity' - } - } - }; - }); - it('child level community cache refreshed', () => { - scheduler.schedule(() => (service as any).refreshCache(data)); - scheduler.flush(); - expect(requestService.setStaleByHrefSubstring).toHaveBeenCalledWith('a20da287-e174-466a-9926-f66as300d399'); - }); - }); }); + describe('cache refreshed child community', () => { + let parentCommunity: Community; + beforeEach(() => { + parentCommunity = Object.assign(new Community(), { + uuid: 'a20da287-e174-466a-9926-f66as300d399', + id: 'a20da287-e174-466a-9926-f66as300d399', + metadata: [{ + key: 'dc.title', + value: 'parent community' + }], + _links: {} + }); + }); + it('should refresh a specific cached community when the parent link can be resolved', () => { + testScheduler.run(({ flush, cold }) => { + spyOn(halService, 'getEndpoint').and.returnValue(cold('a', { a: topEndpoint })); + spyOn(service, 'findByHref').and.returnValue(cold('a', { a: createSuccessfulRemoteDataObject(parentCommunity) })); + service.refreshCache(communityWithParentHref); + flush(); + expect(requestService.setStaleByHrefSubstring).toHaveBeenCalledWith('a20da287-e174-466a-9926-f66as300d399'); + }); + }); + }); }); - }); From d7a0f27f08a5031861ae4c121360a71c0d583c57 Mon Sep 17 00:00:00 2001 From: Art Lowel Date: Thu, 25 Mar 2021 17:23:27 +0100 Subject: [PATCH 108/132] remove workaround --- src/app/core/tasks/tasks.service.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/src/app/core/tasks/tasks.service.ts b/src/app/core/tasks/tasks.service.ts index f23c71e65e..7aeb522170 100644 --- a/src/app/core/tasks/tasks.service.ts +++ b/src/app/core/tasks/tasks.service.ts @@ -110,7 +110,6 @@ export abstract class TasksService extends DataServic find((href: string) => hasValue(href)), mergeMap((href) => this.findByHref(href, false, true).pipe( getAllCompletedRemoteData(), - filter((rd: RemoteData) => !rd.isSuccessStale), tap(() => this.requestService.setStaleByHrefSubstring(href))) ) ); From 6cc56176b2b721ae1259be57effc0fbd0f208fbb Mon Sep 17 00:00:00 2001 From: lotte Date: Thu, 25 Mar 2021 17:27:34 +0100 Subject: [PATCH 109/132] fixed path for custom theme item-page --- src/themes/custom/app/+item-page/simple/item-page.component.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/themes/custom/app/+item-page/simple/item-page.component.ts b/src/themes/custom/app/+item-page/simple/item-page.component.ts index 1ba534972e..dfd792b3e2 100644 --- a/src/themes/custom/app/+item-page/simple/item-page.component.ts +++ b/src/themes/custom/app/+item-page/simple/item-page.component.ts @@ -9,7 +9,7 @@ import { fadeInOut } from '../../../../../app/shared/animations/fade'; */ @Component({ selector: 'ds-item-page', - // styleUrls: ['../item-page.component.scss'], + // styleUrls: ['./item-page.component.scss'], styleUrls: ['../../../../../app/+item-page/simple/item-page.component.scss'], // templateUrl: './item-page.component.html', templateUrl: '../../../../../app/+item-page/simple/item-page.component.html', From 064c43a763a9f267741cbb8ed67cbcbe2c5a627e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?D=C3=A1niel=20P=C3=A9ter=20Sipos?= Date: Fri, 26 Mar 2021 18:01:12 +0100 Subject: [PATCH 110/132] #885 fix merge conflict --- src/app/+item-page/item-page.module.ts | 7 +++++++ src/styles/_global-styles.scss | 11 ++++++++++- 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/src/app/+item-page/item-page.module.ts b/src/app/+item-page/item-page.module.ts index fe326ddcf7..1c6cd83e9c 100644 --- a/src/app/+item-page/item-page.module.ts +++ b/src/app/+item-page/item-page.module.ts @@ -27,6 +27,10 @@ import { JournalEntitiesModule } from '../entity-groups/journal-entities/journal import { ResearchEntitiesModule } from '../entity-groups/research-entities/research-entities.module'; import { ThemedItemPageComponent } from './simple/themed-item-page.component'; import { ThemedFullItemPageComponent } from './full/themed-full-item-page.component'; +import { MediaViewerComponent } from './media-viewer/media-viewer.component'; +import { MediaViewerVideoComponent } from './media-viewer/media-viewer-video/media-viewer-video.component'; +import { MediaViewerImageComponent } from './media-viewer/media-viewer-image/media-viewer-image.component'; +import { NgxGalleryModule } from '@kolkov/ngx-gallery'; const ENTRY_COMPONENTS = [ // put only entry components that use custom decorator @@ -54,6 +58,9 @@ const DECLARATIONS = [ ItemComponent, UploadBitstreamComponent, AbstractIncrementalListComponent, + MediaViewerComponent, + MediaViewerVideoComponent, + MediaViewerImageComponent ]; @NgModule({ diff --git a/src/styles/_global-styles.scss b/src/styles/_global-styles.scss index b79cf52fbb..07eadee391 100644 --- a/src/styles/_global-styles.scss +++ b/src/styles/_global-styles.scss @@ -36,7 +36,7 @@ body { } ds-header-navbar-wrapper { - z-index: var(--ds-nav-z-index); + z-index: 0; } ds-admin-sidebar { @@ -47,3 +47,12 @@ ds-admin-sidebar { .ds-full-screen-loader { height: 100vh; } + +.media-viewer + .change-gallery + .ngx-gallery + ngx-gallery-preview.ngx-gallery-active { + right: 0; + left: auto; + width: 96%; +} From 61767c196cc341b04dc25bde1e3f1a850e4de872 Mon Sep 17 00:00:00 2001 From: Yura Bondarenko Date: Mon, 29 Mar 2021 14:01:36 +0200 Subject: [PATCH 111/132] 77205: Additional authorization checks for sidebar menu items --- .../admin-sidebar/admin-sidebar.component.ts | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/src/app/+admin/admin-sidebar/admin-sidebar.component.ts b/src/app/+admin/admin-sidebar/admin-sidebar.component.ts index 36959a7ffd..3bf5938487 100644 --- a/src/app/+admin/admin-sidebar/admin-sidebar.component.ts +++ b/src/app/+admin/admin-sidebar/admin-sidebar.component.ts @@ -114,7 +114,8 @@ export class AdminSidebarComponent extends MenuComponent implements OnInit { combineLatest([ this.authorizationService.isAuthorized(FeatureID.IsCollectionAdmin), this.authorizationService.isAuthorized(FeatureID.IsCommunityAdmin), - ]).subscribe(([isCollectionAdmin, isCommunityAdmin]) => { + this.authorizationService.isAuthorized(FeatureID.AdministratorOf) + ]).subscribe(([isCollectionAdmin, isCommunityAdmin, isSiteAdmin]) => { const menuList = [ /* News */ { @@ -132,7 +133,7 @@ export class AdminSidebarComponent extends MenuComponent implements OnInit { id: 'new_community', parentID: 'new', active: false, - visible: true, + visible: isCommunityAdmin, model: { type: MenuItemType.ONCLICK, text: 'menu.section.new_community', @@ -145,7 +146,7 @@ export class AdminSidebarComponent extends MenuComponent implements OnInit { id: 'new_collection', parentID: 'new', active: false, - visible: true, + visible: isCommunityAdmin, model: { type: MenuItemType.ONCLICK, text: 'menu.section.new_collection', @@ -171,7 +172,7 @@ export class AdminSidebarComponent extends MenuComponent implements OnInit { id: 'new_process', parentID: 'new', active: false, - visible: true, + visible: isCollectionAdmin, model: { type: MenuItemType.LINK, text: 'menu.section.new_process', @@ -246,7 +247,7 @@ export class AdminSidebarComponent extends MenuComponent implements OnInit { { id: 'curation_tasks', active: false, - visible: true, + visible: isCollectionAdmin, model: { type: MenuItemType.LINK, text: 'menu.section.curation_task', @@ -274,7 +275,7 @@ export class AdminSidebarComponent extends MenuComponent implements OnInit { { id: 'control_panel', active: false, - visible: true, + visible: isSiteAdmin, model: { type: MenuItemType.LINK, text: 'menu.section.control_panel', @@ -288,7 +289,7 @@ export class AdminSidebarComponent extends MenuComponent implements OnInit { { id: 'processes', active: false, - visible: true, + visible: isSiteAdmin, model: { type: MenuItemType.LINK, text: 'menu.section.processes', From 05545f703b9d15bbbcb1d2cdbe369f77cdd279ce Mon Sep 17 00:00:00 2001 From: Art Lowel Date: Mon, 29 Mar 2021 17:09:26 +0200 Subject: [PATCH 112/132] fix issue where the themed submission page would crash because the component couldn't be found --- src/app/submission/submit/themed-submission-submit.component.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/app/submission/submit/themed-submission-submit.component.ts b/src/app/submission/submit/themed-submission-submit.component.ts index ad313bf7bb..328113252f 100644 --- a/src/app/submission/submit/themed-submission-submit.component.ts +++ b/src/app/submission/submit/themed-submission-submit.component.ts @@ -12,7 +12,7 @@ import { SubmissionSubmitComponent } from './submission-submit.component'; }) export class ThemedSubmissionSubmitComponent extends ThemedComponent { protected getComponentName(): string { - return 'SubmissionImportExternalComponent'; + return 'SubmissionSubmitComponent'; } protected importThemedComponent(themeName: string): Promise { From 35773353990dd2ea867885ca2c1ad525ac9f5911 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?D=C3=A1niel=20P=C3=A9ter=20Sipos?= Date: Tue, 30 Mar 2021 13:48:03 +0200 Subject: [PATCH 113/132] #885 revert and fix width --- src/styles/_global-styles.scss | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/styles/_global-styles.scss b/src/styles/_global-styles.scss index 07eadee391..dcf75227ce 100644 --- a/src/styles/_global-styles.scss +++ b/src/styles/_global-styles.scss @@ -36,7 +36,7 @@ body { } ds-header-navbar-wrapper { - z-index: 0; + z-index: var(--ds-nav-z-index); } ds-admin-sidebar { @@ -54,5 +54,5 @@ ds-admin-sidebar { ngx-gallery-preview.ngx-gallery-active { right: 0; left: auto; - width: 96%; + width: calc(100% - 53px); } From d224333a1c014ae4d552d2c156db1322356ead6b Mon Sep 17 00:00:00 2001 From: Alessandro Martelli Date: Wed, 31 Mar 2021 11:47:10 +0200 Subject: [PATCH 114/132] [CST-3782] added hint to the last entity value --- .../ds-dynamic-form-control-container.component.html | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/app/shared/form/builder/ds-dynamic-form-ui/ds-dynamic-form-control-container.component.html b/src/app/shared/form/builder/ds-dynamic-form-ui/ds-dynamic-form-control-container.component.html index eb7b5b720f..bfa9c214e9 100644 --- a/src/app/shared/form/builder/ds-dynamic-form-ui/ds-dynamic-form-control-container.component.html +++ b/src/app/shared/form/builder/ds-dynamic-form-ui/ds-dynamic-form-control-container.component.html @@ -68,6 +68,8 @@ [relationshipOptions]="model.relationship" > +
From d47660b5c29d2ee693c32dba271cde688ad61eb3 Mon Sep 17 00:00:00 2001 From: Alessandro Martelli Date: Wed, 31 Mar 2021 11:56:37 +0200 Subject: [PATCH 115/132] [CST-3782] possibility to configure the isDraggable feature to DynamicRowArrayModel --- .../array-group/dynamic-form-array.component.html | 4 ++-- .../models/array-group/dynamic-form-array.component.ts | 10 +++++++++- .../models/ds-dynamic-row-array-model.ts | 3 +++ .../shared/form/builder/form-builder.service.spec.ts | 1 + src/app/shared/form/builder/parsers/field-parser.ts | 6 ++++++ src/app/shared/mocks/form-models.mock.ts | 1 + 6 files changed, 22 insertions(+), 3 deletions(-) diff --git a/src/app/shared/form/builder/ds-dynamic-form-ui/models/array-group/dynamic-form-array.component.html b/src/app/shared/form/builder/ds-dynamic-form-ui/models/array-group/dynamic-form-array.component.html index 1c14c0b994..09b1331f8b 100644 --- a/src/app/shared/form/builder/ds-dynamic-form-ui/models/array-group/dynamic-form-array.component.html +++ b/src/app/shared/form/builder/ds-dynamic-form-ui/models/array-group/dynamic-form-array.component.html @@ -12,7 +12,7 @@ [ngClass]="[getClass('element', 'group'), getClass('grid', 'group')]" cdkDrag cdkDragHandle - [cdkDragDisabled]="model.groups.length === 1"> + [cdkDragDisabled]="dragDisabled">
@@ -20,7 +20,7 @@
- + | undefined; /* tslint:disable:no-output-rename */ @@ -70,4 +71,11 @@ export class DsDynamicFormArrayComponent extends DynamicFormArrayComponent { this.onChange($event); } + + /** + * If the drag feature is disabled for this DynamicRowArrayModel. + */ + get dragDisabled(): boolean { + return this.model.groups.length === 1 || !this.model.isDraggable; + } } diff --git a/src/app/shared/form/builder/ds-dynamic-form-ui/models/ds-dynamic-row-array-model.ts b/src/app/shared/form/builder/ds-dynamic-form-ui/models/ds-dynamic-row-array-model.ts index 8925d8fd87..d0b07de885 100644 --- a/src/app/shared/form/builder/ds-dynamic-form-ui/models/ds-dynamic-row-array-model.ts +++ b/src/app/shared/form/builder/ds-dynamic-form-ui/models/ds-dynamic-row-array-model.ts @@ -9,6 +9,7 @@ export interface DynamicRowArrayModelConfig extends DynamicFormArrayModelConfig metadataKey: string; metadataFields: string[]; hasSelectableMetadata: boolean; + isDraggable: boolean; } export class DynamicRowArrayModel extends DynamicFormArrayModel { @@ -19,6 +20,7 @@ export class DynamicRowArrayModel extends DynamicFormArrayModel { @serializable() metadataKey: string; @serializable() metadataFields: string[]; @serializable() hasSelectableMetadata: boolean; + @serializable() isDraggable: boolean; isRowArray = true; constructor(config: DynamicRowArrayModelConfig, layout?: DynamicFormControlLayout) { @@ -30,5 +32,6 @@ export class DynamicRowArrayModel extends DynamicFormArrayModel { this.metadataKey = config.metadataKey; this.metadataFields = config.metadataFields; this.hasSelectableMetadata = config.hasSelectableMetadata; + this.isDraggable = config.isDraggable; } } diff --git a/src/app/shared/form/builder/form-builder.service.spec.ts b/src/app/shared/form/builder/form-builder.service.spec.ts index b81bb3285b..cea4d7df6e 100644 --- a/src/app/shared/form/builder/form-builder.service.spec.ts +++ b/src/app/shared/form/builder/form-builder.service.spec.ts @@ -295,6 +295,7 @@ describe('FormBuilderService test suite', () => { notRepeatable: false, relationshipConfig: undefined, submissionId: '1234', + isDraggable: true, groupFactory: () => { return [ new DynamicInputModel({ id: 'testFormRowArrayGroupInput' }) diff --git a/src/app/shared/form/builder/parsers/field-parser.ts b/src/app/shared/form/builder/parsers/field-parser.ts index 93f941e344..da304ca267 100644 --- a/src/app/shared/form/builder/parsers/field-parser.ts +++ b/src/app/shared/form/builder/parsers/field-parser.ts @@ -50,6 +50,11 @@ export abstract class FieldParser { if (Array.isArray(this.configData.selectableMetadata) && this.configData.selectableMetadata.length === 1) { metadataKey = this.configData.selectableMetadata[0].metadata; } + + let isDraggable = true; + if (this.configData.input.type === ParserType.Onebox && this.configData?.selectableMetadata?.length > 1) { + isDraggable = false; + } const config = { id: uniqueId() + '_array', label: this.configData.label, @@ -61,6 +66,7 @@ export abstract class FieldParser { metadataKey, metadataFields: this.getAllFieldIds(), hasSelectableMetadata: isNotEmpty(this.configData.selectableMetadata), + isDraggable, groupFactory: () => { let model; if ((arrayCounter === 0)) { diff --git a/src/app/shared/mocks/form-models.mock.ts b/src/app/shared/mocks/form-models.mock.ts index 739de944f0..c43138fa25 100644 --- a/src/app/shared/mocks/form-models.mock.ts +++ b/src/app/shared/mocks/form-models.mock.ts @@ -80,6 +80,7 @@ const rowArrayQualdropConfig = { id: 'row_QUALDROP_GROUP', initialCount: 1, notRepeatable: true, + isDraggable: false, relationshipConfig: undefined, groupFactory: () => { return [MockQualdropModel]; From 8c60bd42802aafda2b939f5dc19007bd17e8342d Mon Sep 17 00:00:00 2001 From: Alessandro Martelli Date: Wed, 31 Mar 2021 11:59:01 +0200 Subject: [PATCH 116/132] [CST-3782] restored submission save after openLookup --- .../ds-dynamic-form-control-container.component.ts | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/app/shared/form/builder/ds-dynamic-form-ui/ds-dynamic-form-control-container.component.ts b/src/app/shared/form/builder/ds-dynamic-form-ui/ds-dynamic-form-control-container.component.ts index 4fbc29f79d..fd403561e9 100644 --- a/src/app/shared/form/builder/ds-dynamic-form-ui/ds-dynamic-form-control-container.component.ts +++ b/src/app/shared/form/builder/ds-dynamic-form-ui/ds-dynamic-form-control-container.component.ts @@ -37,7 +37,6 @@ import { DynamicFormControl, DynamicFormControlContainerComponent, DynamicFormControlEvent, - DynamicFormControlEventType, DynamicFormControlModel, DynamicFormLayout, DynamicFormLayoutService, @@ -395,6 +394,10 @@ export class DsDynamicFormControlContainerComponent extends DynamicFormControlCo size: 'lg' }); + if (hasValue(this.model.value)) { + this.submissionService.dispatchSave(this.model.submissionId); + } + const modalComp = this.modalRef.componentInstance; if (hasValue(this.model.value) && !this.model.readOnly) { From 052dbdaf1e09b1853169a93d5984ce277120670e Mon Sep 17 00:00:00 2001 From: Alessandro Martelli Date: Wed, 31 Mar 2021 12:10:57 +0200 Subject: [PATCH 117/132] [CST-3782] patch add full array in case of DynamicRowArrayModel --- .../dynamic-form-array.component.ts | 2 +- .../form/builder/form-builder.service.ts | 6 +++ .../form/section-form-operations.service.ts | 42 +++++++++++-------- 3 files changed, 32 insertions(+), 18 deletions(-) diff --git a/src/app/shared/form/builder/ds-dynamic-form-ui/models/array-group/dynamic-form-array.component.ts b/src/app/shared/form/builder/ds-dynamic-form-ui/models/array-group/dynamic-form-array.component.ts index d349d553a2..8ab38454a7 100644 --- a/src/app/shared/form/builder/ds-dynamic-form-ui/models/array-group/dynamic-form-array.component.ts +++ b/src/app/shared/form/builder/ds-dynamic-form-ui/models/array-group/dynamic-form-array.component.ts @@ -3,7 +3,6 @@ import { Component, EventEmitter, Input, Output, QueryList } from '@angular/core import { FormGroup } from '@angular/forms'; import { DynamicFormArrayComponent, - DynamicFormArrayModel, DynamicFormControlCustomEvent, DynamicFormControlEvent, DynamicFormControlLayout, @@ -58,6 +57,7 @@ export class DsDynamicFormArrayComponent extends DynamicFormArrayComponent { this.onCustomEvent({ previousIndex: prevIndex, index, + arrayModel: this.model, model: this.model.groups[index].group[0], control: (this.control as any).controls[index] }, 'move'); diff --git a/src/app/shared/form/builder/form-builder.service.ts b/src/app/shared/form/builder/form-builder.service.ts index a7979bde94..85d70f20dc 100644 --- a/src/app/shared/form/builder/form-builder.service.ts +++ b/src/app/shared/form/builder/form-builder.service.ts @@ -31,6 +31,7 @@ import { FormFieldMetadataValueObject } from './models/form-field-metadata-value import { dateToString, isNgbDateStruct } from '../../date.util'; import { DYNAMIC_FORM_CONTROL_TYPE_RELATION_GROUP } from './ds-dynamic-form-ui/ds-dynamic-form-constants'; import { CONCAT_GROUP_SUFFIX, DynamicConcatModel } from './ds-dynamic-form-ui/models/ds-dynamic-concat.model'; +import { VIRTUAL_METADATA_PREFIX } from '../../../core/shared/metadata.models'; @Injectable() export class FormBuilderService extends DynamicFormService { @@ -121,6 +122,11 @@ export class FormBuilderService extends DynamicFormService { const normalizeValue = (controlModel, controlValue, controlModelIndex) => { const controlLanguage = (controlModel as DsDynamicInputModel).hasLanguages ? (controlModel as DsDynamicInputModel).language : null; + + if (controlModel?.metadataValue?.authority?.includes(VIRTUAL_METADATA_PREFIX)) { + return controlModel.metadataValue; + } + if (isString(controlValue)) { return new FormFieldMetadataValueObject(controlValue, controlLanguage, null, null, controlModelIndex); } else if (isNgbDateStruct(controlValue)) { diff --git a/src/app/submission/sections/form/section-form-operations.service.ts b/src/app/submission/sections/form/section-form-operations.service.ts index be0e397ddb..57ac7e1d7e 100644 --- a/src/app/submission/sections/form/section-form-operations.service.ts +++ b/src/app/submission/sections/form/section-form-operations.service.ts @@ -23,6 +23,7 @@ import { DynamicRelationGroupModel } from '../../../shared/form/builder/ds-dynam import { VocabularyEntryDetail } from '../../../core/submission/vocabularies/models/vocabulary-entry-detail.model'; import { deepClone } from 'fast-json-patch'; import { dateToString, isNgbDateStruct } from '../../../shared/date.util'; +import { DynamicRowArrayModel } from '../../../shared/form/builder/ds-dynamic-form-ui/models/ds-dynamic-row-array-model'; /** * The service handling all form section operations @@ -357,6 +358,13 @@ export class SectionFormOperationsService { event: DynamicFormControlEvent, previousValue: FormFieldPreviousValueObject, hasStoredValue: boolean): void { + + if (event.context && event.context instanceof DynamicFormArrayGroupModel) { + // Model is a DynamicRowArrayModel + this.handleArrayGroupPatch(pathCombiner, event, (event as any).context.context); + return; + } + const path = this.getFieldPathFromEvent(event); const segmentedPath = this.getFieldPathSegmentedFromChangeEvent(event); const value = this.getFieldValueFromChangeEvent(event); @@ -483,23 +491,23 @@ export class SectionFormOperationsService { event: DynamicFormControlEvent, previousValue: FormFieldPreviousValueObject) { - const customEvent = event.$event; + return this.handleArrayGroupPatch(pathCombiner, event.$event, (event as any).$event.arrayModel); + } - if (this.formBuilder.isQualdropGroup(customEvent.model.parent as DynamicFormControlModel) - || this.formBuilder.isQualdropGroup(customEvent.model as DynamicFormControlModel)) { - // It's a qualdrup model - this.dispatchOperationsFromMap(this.getQualdropValueMap(customEvent), pathCombiner, customEvent, previousValue); - return; - } - const path = this.getFieldPathFromEvent(customEvent); - const segmentedPath = this.getFieldPathSegmentedFromChangeEvent(customEvent); - const moveTo = pathCombiner.getPath(path); - const moveFrom = pathCombiner.getPath(segmentedPath + '/' + customEvent.previousIndex); - if (isNotEmpty(moveFrom.path) && isNotEmpty(moveTo.path) && moveFrom.path !== moveTo.path) { - this.operationsBuilder.move( - moveTo, - moveFrom.path - ); - } + /** + * Specific patch handler for a DynamicRowArrayModel. + * Configure a Patch ADD with the current array value. + * @param pathCombiner + * @param event + * @param model + */ + private handleArrayGroupPatch(pathCombiner: JsonPatchOperationPathCombiner, + event, + model: DynamicRowArrayModel) { + const arrayValue = this.formBuilder.getValueFromModel([model]); + const segmentedPath2 = this.getFieldPathSegmentedFromChangeEvent(event); + this.operationsBuilder.add( + pathCombiner.getPath(segmentedPath2), + arrayValue[segmentedPath2], false); } } From f9e80ea2886eba71f0c3553945361153bfeeaa07 Mon Sep 17 00:00:00 2001 From: Alessandro Martelli Date: Wed, 31 Mar 2021 12:27:39 +0200 Subject: [PATCH 118/132] [CST-3782] restored correct drag styles after merge --- .../dynamic-form-array.component.scss | 49 +++++++++---------- 1 file changed, 24 insertions(+), 25 deletions(-) diff --git a/src/app/shared/form/builder/ds-dynamic-form-ui/models/array-group/dynamic-form-array.component.scss b/src/app/shared/form/builder/ds-dynamic-form-ui/models/array-group/dynamic-form-array.component.scss index 36e5fc2131..634a197123 100644 --- a/src/app/shared/form/builder/ds-dynamic-form-ui/models/array-group/dynamic-form-array.component.scss +++ b/src/app/shared/form/builder/ds-dynamic-form-ui/models/array-group/dynamic-form-array.component.scss @@ -5,42 +5,41 @@ } .cdk-drag { - margin-left: calc(-2 * var(--bs-spacer)); - margin-right: calc(-0.5 * var(--bs-spacer)); - padding-right: calc(0.5 * var(--bs-spacer)); - .drag-icon { - visibility: hidden; - width: calc(2 * var(--bs-spacer)); - color: var(--bs-gray-600); - margin: var(--bs-btn-padding-y) 0; - line-height: var(--bs-btn-line-height); - text-indent: calc(0.5 * var(--bs-spacer)); - cursor: grab; - } + margin-left: calc(-2.3 * var(--bs-spacer)); + margin-right: calc(-0.5 * var(--bs-spacer)); + padding-right: calc(0.5 * var(--bs-spacer)); + .drag-icon { + visibility: hidden; + width: calc(2 * var(--bs-spacer)); + color: var(--bs-gray-600); + margin: var(--bs-btn-padding-y) 0; + line-height: var(--bs-btn-line-height); + text-indent: calc(0.5 * var(--bs-spacer)) + } - &:hover, &:focus { - cursor: grab; - .drag-icon { - visibility: visible; - } + &:hover, &:focus { + cursor: grab; + .drag-icon { + visibility: visible; } + } } .cdk-drop-list-dragging { - .cdk-drag { - cursor: grabbing; - .drag-icon { - visibility: hidden; - } + .cdk-drag { + cursor: grabbing; + .drag-icon { + visibility: hidden; } + } } .cdk-drag-preview { - margin: 0px; - padding: 0px; + margin: 0; + padding: 0; } .cdk-drag-placeholder { - opacity: 0; + opacity: 0; } From ff8ff7f4968428c441a8c2e4fd60b5c646e0c140 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?D=C3=A1niel=20P=C3=A9ter=20Sipos?= Date: Wed, 31 Mar 2021 13:21:33 +0200 Subject: [PATCH 119/132] #885 fix media image viewer --- src/styles/_global-styles.scss | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/styles/_global-styles.scss b/src/styles/_global-styles.scss index dcf75227ce..bf8efeca8b 100644 --- a/src/styles/_global-styles.scss +++ b/src/styles/_global-styles.scss @@ -35,10 +35,6 @@ body { margin: 0; } -ds-header-navbar-wrapper { - z-index: var(--ds-nav-z-index); -} - ds-admin-sidebar { position: fixed; z-index: var(--ds-sidebar-z-index); @@ -48,6 +44,10 @@ ds-admin-sidebar { height: 100vh; } +.sticky-top { + z-index: 0; +} + .media-viewer .change-gallery .ngx-gallery From 7afcebfd119df4b6a36c0273701d256449eab4a1 Mon Sep 17 00:00:00 2001 From: lotte Date: Wed, 31 Mar 2021 13:51:40 +0200 Subject: [PATCH 120/132] changed replace to global replace --- src/app/core/shared/metadata.utils.spec.ts | 3 ++- src/app/core/shared/metadata.utils.ts | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/src/app/core/shared/metadata.utils.spec.ts b/src/app/core/shared/metadata.utils.spec.ts index d9068dd900..bc91d0585e 100644 --- a/src/app/core/shared/metadata.utils.spec.ts +++ b/src/app/core/shared/metadata.utils.spec.ts @@ -32,7 +32,8 @@ const multiMap = { }; const regexTestMap = { - 'foolbar.baz': [test] + 'foolbar.baz': [test], + 'foo.bard': [test], }; const multiViewModelList = [ diff --git a/src/app/core/shared/metadata.utils.ts b/src/app/core/shared/metadata.utils.ts index 6e69109dd7..777b71b872 100644 --- a/src/app/core/shared/metadata.utils.ts +++ b/src/app/core/shared/metadata.utils.ts @@ -156,7 +156,7 @@ export class Metadata { const outputKeys: string[] = []; for (const inputKey of inputKeys) { if (inputKey.includes('*')) { - const inputKeyRegex = new RegExp('^' + inputKey.replace('.', '\\.').replace('*', '.*') + '$'); + const inputKeyRegex = new RegExp('^' + inputKey.replace(/\./g, '\\.').replace('*', '.*') + '$'); for (const mapKey of Object.keys(mdMap)) { if (!outputKeys.includes(mapKey) && inputKeyRegex.test(mapKey)) { outputKeys.push(mapKey); From 947d792f2702ba79e7034df2e9da38c3b1b500f3 Mon Sep 17 00:00:00 2001 From: Raf Ponsaerts Date: Wed, 31 Mar 2021 14:49:32 +0200 Subject: [PATCH 121/132] Fixed * replace all --- src/app/core/shared/metadata.utils.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/app/core/shared/metadata.utils.ts b/src/app/core/shared/metadata.utils.ts index 777b71b872..3fbeb205d2 100644 --- a/src/app/core/shared/metadata.utils.ts +++ b/src/app/core/shared/metadata.utils.ts @@ -156,7 +156,7 @@ export class Metadata { const outputKeys: string[] = []; for (const inputKey of inputKeys) { if (inputKey.includes('*')) { - const inputKeyRegex = new RegExp('^' + inputKey.replace(/\./g, '\\.').replace('*', '.*') + '$'); + const inputKeyRegex = new RegExp('^' + inputKey.replace(/\./g, '\\.').replace(/\*/g, '.*') + '$'); for (const mapKey of Object.keys(mdMap)) { if (!outputKeys.includes(mapKey) && inputKeyRegex.test(mapKey)) { outputKeys.push(mapKey); From 08afa4723b2c28ac9a9d3daeb217d234e2f64aab Mon Sep 17 00:00:00 2001 From: Alessandro Martelli Date: Wed, 31 Mar 2021 14:20:44 +0200 Subject: [PATCH 122/132] [CST-3782] patch add entire array on item remove --- src/app/shared/form/form.component.ts | 3 ++- .../sections/form/section-form-operations.service.ts | 7 +++++++ 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/src/app/shared/form/form.component.ts b/src/app/shared/form/form.component.ts index 39cc3bdafb..8d7a87c03c 100644 --- a/src/app/shared/form/form.component.ts +++ b/src/app/shared/form/form.component.ts @@ -303,9 +303,10 @@ export class FormComponent implements OnDestroy, OnInit { removeItem($event, arrayContext: DynamicFormArrayModel, index: number): void { const formArrayControl = this.formGroup.get(this.formBuilderService.getPath(arrayContext)) as FormArray; - this.removeArrayItem.emit(this.getEvent($event, arrayContext, index, 'remove')); + const event = this.getEvent($event, arrayContext, index, 'remove'); this.formBuilderService.removeFormArrayGroup(index, formArrayControl, arrayContext); this.formService.changeForm(this.formId, this.formModel); + this.removeArrayItem.emit(event); } insertItem($event, arrayContext: DynamicFormArrayModel, index: number): void { diff --git a/src/app/submission/sections/form/section-form-operations.service.ts b/src/app/submission/sections/form/section-form-operations.service.ts index 57ac7e1d7e..a1bb99e3cd 100644 --- a/src/app/submission/sections/form/section-form-operations.service.ts +++ b/src/app/submission/sections/form/section-form-operations.service.ts @@ -296,6 +296,13 @@ export class SectionFormOperationsService { protected dispatchOperationsFromRemoveEvent(pathCombiner: JsonPatchOperationPathCombiner, event: DynamicFormControlEvent, previousValue: FormFieldPreviousValueObject): void { + + if (event.context && event.context instanceof DynamicFormArrayGroupModel) { + // Model is a DynamicRowArrayModel + this.handleArrayGroupPatch(pathCombiner, event, (event as any).context.context); + return; + } + const path = this.getFieldPathFromEvent(event); const value = this.getFieldValueFromChangeEvent(event); console.log(value); From d36ac7e6fa4fa9353798e70e6b76ad0c1fe832a1 Mon Sep 17 00:00:00 2001 From: Tim Donohue Date: Fri, 12 Mar 2021 14:06:45 -0600 Subject: [PATCH 123/132] Rename / move 'relationship.type' metadata field to 'dspace.entity.type' --- .../edit-item-page/item-delete/item-delete.component.ts | 2 +- .../item-relationships/item-relationships.component.ts | 2 +- .../specific-field/title/item-page-title-field.component.html | 2 +- src/app/core/shared/item.model.ts | 2 +- .../item/item-metadata-representation.model.spec.ts | 4 ++-- .../item/item-metadata-representation.model.ts | 2 +- .../relation-lookup-modal/relationship.effects.spec.ts | 4 ++-- .../relation-lookup-modal/relationship.effects.ts | 4 ++-- .../metadata-representation-loader.component.ts | 2 +- .../listable-object-component-loader.component.ts | 2 +- .../item-list-preview/item-list-preview.component.spec.ts | 2 +- .../object-list/type-badge/type-badge.component.spec.ts | 2 +- src/assets/i18n/ar.json5 | 4 ++-- src/assets/i18n/cs.json5 | 4 ++-- src/assets/i18n/de.json5 | 4 ++-- src/assets/i18n/en.json5 | 2 +- src/assets/i18n/es.json5 | 4 ++-- src/assets/i18n/fi.json5 | 4 ++-- src/assets/i18n/fr.json5 | 4 ++-- src/assets/i18n/hu.json5 | 4 ++-- src/assets/i18n/ja.json5 | 4 ++-- src/assets/i18n/lv.json5 | 4 ++-- src/assets/i18n/nl.json5 | 4 ++-- src/assets/i18n/pl.json5 | 4 ++-- src/assets/i18n/pt-BR.json5 | 4 ++-- src/assets/i18n/pt-PT.json5 | 4 ++-- src/assets/i18n/sw.json5 | 4 ++-- src/assets/i18n/tr.json5 | 4 ++-- 28 files changed, 46 insertions(+), 46 deletions(-) diff --git a/src/app/+item-page/edit-item-page/item-delete/item-delete.component.ts b/src/app/+item-page/edit-item-page/item-delete/item-delete.component.ts index 366b22bec7..bd1c44cebc 100644 --- a/src/app/+item-page/edit-item-page/item-delete/item-delete.component.ts +++ b/src/app/+item-page/edit-item-page/item-delete/item-delete.component.ts @@ -112,7 +112,7 @@ export class ItemDeleteComponent super.ngOnInit(); this.url = this.router.url; - const label = this.item.firstMetadataValue('relationship.type'); + const label = this.item.firstMetadataValue('dspace.entity.type'); if (label !== undefined) { this.types$ = this.entityTypeService.getEntityTypeByLabel(label).pipe( getFirstSucceededRemoteData(), diff --git a/src/app/+item-page/edit-item-page/item-relationships/item-relationships.component.ts b/src/app/+item-page/edit-item-page/item-relationships/item-relationships.component.ts index 785d548860..1c5ed3c02b 100644 --- a/src/app/+item-page/edit-item-page/item-relationships/item-relationships.component.ts +++ b/src/app/+item-page/edit-item-page/item-relationships/item-relationships.component.ts @@ -75,7 +75,7 @@ export class ItemRelationshipsComponent extends AbstractItemUpdateComponent { */ public initializeUpdates(): void { - const label = this.item.firstMetadataValue('relationship.type'); + const label = this.item.firstMetadataValue('dspace.entity.type'); if (label !== undefined) { this.entityType$ = this.entityTypeService.getEntityTypeByLabel(label).pipe( diff --git a/src/app/+item-page/simple/field-components/specific-field/title/item-page-title-field.component.html b/src/app/+item-page/simple/field-components/specific-field/title/item-page-title-field.component.html index 43bd20d0f6..12987dc6d3 100644 --- a/src/app/+item-page/simple/field-components/specific-field/title/item-page-title-field.component.html +++ b/src/app/+item-page/simple/field-components/specific-field/title/item-page-title-field.component.html @@ -1,5 +1,5 @@

-
+
{{ type.toLowerCase() + '.page.titleprefix' | translate }}
diff --git a/src/app/core/shared/item.model.ts b/src/app/core/shared/item.model.ts index 10b723c202..53eb5e3ce2 100644 --- a/src/app/core/shared/item.model.ts +++ b/src/app/core/shared/item.model.ts @@ -104,7 +104,7 @@ export class Item extends DSpaceObject implements ChildHALResource { * Method that returns as which type of object this object should be rendered */ getRenderTypes(): (string | GenericConstructor)[] { - const entityType = this.firstMetadataValue('relationship.type'); + const entityType = this.firstMetadataValue('dspace.entity.type'); if (isEmpty(entityType)) { return super.getRenderTypes(); } diff --git a/src/app/core/shared/metadata-representation/item/item-metadata-representation.model.spec.ts b/src/app/core/shared/metadata-representation/item/item-metadata-representation.model.spec.ts index 791fc43fbe..b46dab7180 100644 --- a/src/app/core/shared/metadata-representation/item/item-metadata-representation.model.spec.ts +++ b/src/app/core/shared/metadata-representation/item/item-metadata-representation.model.spec.ts @@ -24,7 +24,7 @@ describe('ItemMetadataRepresentation', () => { for (const metadataField of Object.keys(item.metadata)) { describe(`when creating an ItemMetadataRepresentation`, () => { beforeEach(() => { - item.metadata['relationship.type'] = [ + item.metadata['dspace.entity.type'] = [ Object.assign(new MetadataValue(), { value: itemType }) @@ -41,7 +41,7 @@ describe('ItemMetadataRepresentation', () => { }); it('should return the correct item type', () => { - expect(itemMetadataRepresentation.itemType).toEqual(item.firstMetadataValue('relationship.type')); + expect(itemMetadataRepresentation.itemType).toEqual(item.firstMetadataValue('dspace.entity.type')); }); }); } diff --git a/src/app/core/shared/metadata-representation/item/item-metadata-representation.model.ts b/src/app/core/shared/metadata-representation/item/item-metadata-representation.model.ts index b688673b65..8c50e0b597 100644 --- a/src/app/core/shared/metadata-representation/item/item-metadata-representation.model.ts +++ b/src/app/core/shared/metadata-representation/item/item-metadata-representation.model.ts @@ -21,7 +21,7 @@ export class ItemMetadataRepresentation extends Item implements MetadataRepresen * The type of item this item can be represented as */ get itemType(): string { - return this.firstMetadataValue('relationship.type'); + return this.firstMetadataValue('dspace.entity.type'); } /** diff --git a/src/app/shared/form/builder/ds-dynamic-form-ui/relation-lookup-modal/relationship.effects.spec.ts b/src/app/shared/form/builder/ds-dynamic-form-ui/relation-lookup-modal/relationship.effects.spec.ts index 432ac44859..5e2ffd30fb 100644 --- a/src/app/shared/form/builder/ds-dynamic-form-ui/relation-lookup-modal/relationship.effects.spec.ts +++ b/src/app/shared/form/builder/ds-dynamic-form-ui/relation-lookup-modal/relationship.effects.spec.ts @@ -66,12 +66,12 @@ describe('RelationshipEffects', () => { leftItem = Object.assign(new Item(), { uuid: testUUID1, - metadata: { 'relationship.type': [leftTypeMD] } + metadata: { 'dspace.entity.type': [leftTypeMD] } }); rightItem = Object.assign(new Item(), { uuid: testUUID2, - metadata: { 'relationship.type': [rightTypeMD] } + metadata: { 'dspace.entity.type': [rightTypeMD] } }); relationshipType = Object.assign(new RelationshipType(), { diff --git a/src/app/shared/form/builder/ds-dynamic-form-ui/relation-lookup-modal/relationship.effects.ts b/src/app/shared/form/builder/ds-dynamic-form-ui/relation-lookup-modal/relationship.effects.ts index e68152f74d..5a20ed8b51 100644 --- a/src/app/shared/form/builder/ds-dynamic-form-ui/relation-lookup-modal/relationship.effects.ts +++ b/src/app/shared/form/builder/ds-dynamic-form-ui/relation-lookup-modal/relationship.effects.ts @@ -167,8 +167,8 @@ export class RelationshipEffects { } private addRelationship(item1: Item, item2: Item, relationshipType: string, submissionId: string, nameVariant?: string) { - const type1: string = item1.firstMetadataValue('relationship.type'); - const type2: string = item2.firstMetadataValue('relationship.type'); + const type1: string = item1.firstMetadataValue('dspace.entity.type'); + const type2: string = item2.firstMetadataValue('dspace.entity.type'); return this.relationshipTypeService.getRelationshipTypeByLabelAndTypes(relationshipType, type1, type2) .pipe( mergeMap((type: RelationshipType) => { diff --git a/src/app/shared/metadata-representation/metadata-representation-loader.component.ts b/src/app/shared/metadata-representation/metadata-representation-loader.component.ts index 40fae2e5a6..2f2c96dc43 100644 --- a/src/app/shared/metadata-representation/metadata-representation-loader.component.ts +++ b/src/app/shared/metadata-representation/metadata-representation-loader.component.ts @@ -14,7 +14,7 @@ import { ThemeService } from '../theme-support/theme.service'; templateUrl: './metadata-representation-loader.component.html' }) /** - * Component for determining what component to use depending on the item's relationship type (relationship.type), its metadata representation and, optionally, its context + * Component for determining what component to use depending on the item's entity type (dspace.entity.type), its metadata representation and, optionally, its context */ export class MetadataRepresentationLoaderComponent implements OnInit { private componentRefInstance: MetadataRepresentationListElementComponent; diff --git a/src/app/shared/object-collection/shared/listable-object/listable-object-component-loader.component.ts b/src/app/shared/object-collection/shared/listable-object/listable-object-component-loader.component.ts index b02ab3cfeb..7b2e994965 100644 --- a/src/app/shared/object-collection/shared/listable-object/listable-object-component-loader.component.ts +++ b/src/app/shared/object-collection/shared/listable-object/listable-object-component-loader.component.ts @@ -27,7 +27,7 @@ import { ThemeService } from '../../../theme-support/theme.service'; templateUrl: './listable-object-component-loader.component.html' }) /** - * Component for determining what component to use depending on the item's relationship type (relationship.type) + * Component for determining what component to use depending on the item's entity type (dspace.entity.type) */ export class ListableObjectComponentLoaderComponent implements OnInit, OnDestroy { /** diff --git a/src/app/shared/object-list/my-dspace-result-list-element/item-list-preview/item-list-preview.component.spec.ts b/src/app/shared/object-list/my-dspace-result-list-element/item-list-preview/item-list-preview.component.spec.ts index 9aec785f08..023b51a8dd 100644 --- a/src/app/shared/object-list/my-dspace-result-list-element/item-list-preview/item-list-preview.component.spec.ts +++ b/src/app/shared/object-list/my-dspace-result-list-element/item-list-preview/item-list-preview.component.spec.ts @@ -57,7 +57,7 @@ const mockItemWithEntityType: Item = Object.assign(new Item(), { value: 'This is just another title' } ], - 'relationship.type': [ + 'dspace.entity.type': [ { language: null, value: 'Publication' diff --git a/src/app/shared/object-list/type-badge/type-badge.component.spec.ts b/src/app/shared/object-list/type-badge/type-badge.component.spec.ts index a8659e28ac..a92081dcd5 100644 --- a/src/app/shared/object-list/type-badge/type-badge.component.spec.ts +++ b/src/app/shared/object-list/type-badge/type-badge.component.spec.ts @@ -15,7 +15,7 @@ const type = 'authorOfPublication'; const mockItemWithRelationshipType = Object.assign(new Item(), { bundles: observableOf({}), metadata: { - 'relationship.type': [ + 'dspace.entity.type': [ { language: 'en_US', value: type diff --git a/src/assets/i18n/ar.json5 b/src/assets/i18n/ar.json5 index c4ea2a0d9e..8383c440cd 100644 --- a/src/assets/i18n/ar.json5 +++ b/src/assets/i18n/ar.json5 @@ -3180,9 +3180,9 @@ // TODO New key - Add a translation "item.edit.relationships.save-button": "Save", - // "item.edit.relationships.no-entity-type": "Add 'relationship.type' metadata to enable relationships for this item", + // "item.edit.relationships.no-entity-type": "Add 'dspace.entity.type' metadata to enable relationships for this item", // TODO New key - Add a translation - "item.edit.relationships.no-entity-type": "Add 'relationship.type' metadata to enable relationships for this item", + "item.edit.relationships.no-entity-type": "Add 'dspace.entity.type' metadata to enable relationships for this item", diff --git a/src/assets/i18n/cs.json5 b/src/assets/i18n/cs.json5 index 9bc6ea36ed..2c7ca09930 100644 --- a/src/assets/i18n/cs.json5 +++ b/src/assets/i18n/cs.json5 @@ -3120,9 +3120,9 @@ // TODO New key - Add a translation "item.edit.relationships.save-button": "Save", - // "item.edit.relationships.no-entity-type": "Add 'relationship.type' metadata to enable relationships for this item", + // "item.edit.relationships.no-entity-type": "Add 'dspace.entity.type' metadata to enable relationships for this item", // TODO New key - Add a translation - "item.edit.relationships.no-entity-type": "Add 'relationship.type' metadata to enable relationships for this item", + "item.edit.relationships.no-entity-type": "Add 'dspace.entity.type' metadata to enable relationships for this item", diff --git a/src/assets/i18n/de.json5 b/src/assets/i18n/de.json5 index 4a5b799c29..306f1fcc51 100644 --- a/src/assets/i18n/de.json5 +++ b/src/assets/i18n/de.json5 @@ -2789,9 +2789,9 @@ // "item.edit.relationships.save-button": "Save", "item.edit.relationships.save-button": "Speichern", - // "item.edit.relationships.no-entity-type": "Add 'relationship.type' metadata to enable relationships for this item", + // "item.edit.relationships.no-entity-type": "Add 'dspace.entity.type' metadata to enable relationships for this item", // TODO New key - Add a translation - "item.edit.relationships.no-entity-type": "Add 'relationship.type' metadata to enable relationships for this item", + "item.edit.relationships.no-entity-type": "Add 'dspace.entity.type' metadata to enable relationships for this item", diff --git a/src/assets/i18n/en.json5 b/src/assets/i18n/en.json5 index eb429cf546..c11c6cf40f 100644 --- a/src/assets/i18n/en.json5 +++ b/src/assets/i18n/en.json5 @@ -1668,7 +1668,7 @@ "item.edit.relationships.save-button": "Save", - "item.edit.relationships.no-entity-type": "Add 'relationship.type' metadata to enable relationships for this item", + "item.edit.relationships.no-entity-type": "Add 'dspace.entity.type' metadata to enable relationships for this item", diff --git a/src/assets/i18n/es.json5 b/src/assets/i18n/es.json5 index dedf74d32d..5edaaf0cf1 100644 --- a/src/assets/i18n/es.json5 +++ b/src/assets/i18n/es.json5 @@ -2861,9 +2861,9 @@ // "item.edit.relationships.save-button": "Save", "item.edit.relationships.save-button": "Guardar", - // "item.edit.relationships.no-entity-type": "Add 'relationship.type' metadata to enable relationships for this item", + // "item.edit.relationships.no-entity-type": "Add 'dspace.entity.type' metadata to enable relationships for this item", // TODO New key - Add a translation - "item.edit.relationships.no-entity-type": "Add 'relationship.type' metadata to enable relationships for this item", + "item.edit.relationships.no-entity-type": "Add 'dspace.entity.type' metadata to enable relationships for this item", diff --git a/src/assets/i18n/fi.json5 b/src/assets/i18n/fi.json5 index 4932e49bbc..89d5955725 100644 --- a/src/assets/i18n/fi.json5 +++ b/src/assets/i18n/fi.json5 @@ -2625,9 +2625,9 @@ // "item.edit.relationships.save-button": "Save", "item.edit.relationships.save-button": "Tallenna", - // "item.edit.relationships.no-entity-type": "Add 'relationship.type' metadata to enable relationships for this item", + // "item.edit.relationships.no-entity-type": "Add 'dspace.entity.type' metadata to enable relationships for this item", // TODO New key - Add a translation - "item.edit.relationships.no-entity-type": "Add 'relationship.type' metadata to enable relationships for this item", + "item.edit.relationships.no-entity-type": "Add 'dspace.entity.type' metadata to enable relationships for this item", diff --git a/src/assets/i18n/fr.json5 b/src/assets/i18n/fr.json5 index 42fad7c682..7b43330e10 100644 --- a/src/assets/i18n/fr.json5 +++ b/src/assets/i18n/fr.json5 @@ -2864,9 +2864,9 @@ // "item.edit.relationships.save-button": "Save", "item.edit.relationships.save-button": "Sauvegarder", - // "item.edit.relationships.no-entity-type": "Add 'relationship.type' metadata to enable relationships for this item", + // "item.edit.relationships.no-entity-type": "Add 'dspace.entity.type' metadata to enable relationships for this item", // TODO New key - Add a translation - "item.edit.relationships.no-entity-type": "Add 'relationship.type' metadata to enable relationships for this item", + "item.edit.relationships.no-entity-type": "Add 'dspace.entity.type' metadata to enable relationships for this item", diff --git a/src/assets/i18n/hu.json5 b/src/assets/i18n/hu.json5 index 6fec12cf21..15b05c93e8 100644 --- a/src/assets/i18n/hu.json5 +++ b/src/assets/i18n/hu.json5 @@ -2430,8 +2430,8 @@ // "item.edit.relationships.save-button": "Save", "item.edit.relationships.save-button": "Mentés", - // "item.edit.relationships.no-entity-type": "Add 'relationship.type' metadata to enable relationships for this item", - "item.edit.relationships.no-entity-type": "Adja hozzá a 'relationship.type' metaadatot ezen elem hivatkozásánek engedélyezéséhez", + // "item.edit.relationships.no-entity-type": "Add 'dspace.entity.type' metadata to enable relationships for this item", + "item.edit.relationships.no-entity-type": "Adja hozzá a 'dspace.entity.type' metaadatot ezen elem hivatkozásánek engedélyezéséhez", diff --git a/src/assets/i18n/ja.json5 b/src/assets/i18n/ja.json5 index c4ea2a0d9e..8383c440cd 100644 --- a/src/assets/i18n/ja.json5 +++ b/src/assets/i18n/ja.json5 @@ -3180,9 +3180,9 @@ // TODO New key - Add a translation "item.edit.relationships.save-button": "Save", - // "item.edit.relationships.no-entity-type": "Add 'relationship.type' metadata to enable relationships for this item", + // "item.edit.relationships.no-entity-type": "Add 'dspace.entity.type' metadata to enable relationships for this item", // TODO New key - Add a translation - "item.edit.relationships.no-entity-type": "Add 'relationship.type' metadata to enable relationships for this item", + "item.edit.relationships.no-entity-type": "Add 'dspace.entity.type' metadata to enable relationships for this item", diff --git a/src/assets/i18n/lv.json5 b/src/assets/i18n/lv.json5 index 898b8db31a..ff998ab774 100644 --- a/src/assets/i18n/lv.json5 +++ b/src/assets/i18n/lv.json5 @@ -2620,9 +2620,9 @@ // "item.edit.relationships.save-button": "Save", "item.edit.relationships.save-button": "Saglabāt", - // "item.edit.relationships.no-entity-type": "Add 'relationship.type' metadata to enable relationships for this item", + // "item.edit.relationships.no-entity-type": "Add 'dspace.entity.type' metadata to enable relationships for this item", // TODO New key - Add a translation - "item.edit.relationships.no-entity-type": "Add 'relationship.type' metadata to enable relationships for this item", + "item.edit.relationships.no-entity-type": "Add 'dspace.entity.type' metadata to enable relationships for this item", diff --git a/src/assets/i18n/nl.json5 b/src/assets/i18n/nl.json5 index b831dbb3ad..8acbe901f0 100644 --- a/src/assets/i18n/nl.json5 +++ b/src/assets/i18n/nl.json5 @@ -2860,9 +2860,9 @@ // "item.edit.relationships.save-button": "Save", "item.edit.relationships.save-button": "Opslaan", - // "item.edit.relationships.no-entity-type": "Add 'relationship.type' metadata to enable relationships for this item", + // "item.edit.relationships.no-entity-type": "Add 'dspace.entity.type' metadata to enable relationships for this item", // TODO New key - Add a translation - "item.edit.relationships.no-entity-type": "Add 'relationship.type' metadata to enable relationships for this item", + "item.edit.relationships.no-entity-type": "Add 'dspace.entity.type' metadata to enable relationships for this item", diff --git a/src/assets/i18n/pl.json5 b/src/assets/i18n/pl.json5 index c4ea2a0d9e..8383c440cd 100644 --- a/src/assets/i18n/pl.json5 +++ b/src/assets/i18n/pl.json5 @@ -3180,9 +3180,9 @@ // TODO New key - Add a translation "item.edit.relationships.save-button": "Save", - // "item.edit.relationships.no-entity-type": "Add 'relationship.type' metadata to enable relationships for this item", + // "item.edit.relationships.no-entity-type": "Add 'dspace.entity.type' metadata to enable relationships for this item", // TODO New key - Add a translation - "item.edit.relationships.no-entity-type": "Add 'relationship.type' metadata to enable relationships for this item", + "item.edit.relationships.no-entity-type": "Add 'dspace.entity.type' metadata to enable relationships for this item", diff --git a/src/assets/i18n/pt-BR.json5 b/src/assets/i18n/pt-BR.json5 index 3b152196bd..4c7d75e11a 100644 --- a/src/assets/i18n/pt-BR.json5 +++ b/src/assets/i18n/pt-BR.json5 @@ -2818,9 +2818,9 @@ // "item.edit.relationships.save-button": "Save", "item.edit.relationships.save-button": "Salvar", - // "item.edit.relationships.no-entity-type": "Add 'relationship.type' metadata to enable relationships for this item", + // "item.edit.relationships.no-entity-type": "Add 'dspace.entity.type' metadata to enable relationships for this item", // TODO New key - Add a translation - "item.edit.relationships.no-entity-type": "Add 'relationship.type' metadata to enable relationships for this item", + "item.edit.relationships.no-entity-type": "Add 'dspace.entity.type' metadata to enable relationships for this item", diff --git a/src/assets/i18n/pt-PT.json5 b/src/assets/i18n/pt-PT.json5 index 3b152196bd..4c7d75e11a 100644 --- a/src/assets/i18n/pt-PT.json5 +++ b/src/assets/i18n/pt-PT.json5 @@ -2818,9 +2818,9 @@ // "item.edit.relationships.save-button": "Save", "item.edit.relationships.save-button": "Salvar", - // "item.edit.relationships.no-entity-type": "Add 'relationship.type' metadata to enable relationships for this item", + // "item.edit.relationships.no-entity-type": "Add 'dspace.entity.type' metadata to enable relationships for this item", // TODO New key - Add a translation - "item.edit.relationships.no-entity-type": "Add 'relationship.type' metadata to enable relationships for this item", + "item.edit.relationships.no-entity-type": "Add 'dspace.entity.type' metadata to enable relationships for this item", diff --git a/src/assets/i18n/sw.json5 b/src/assets/i18n/sw.json5 index c4ea2a0d9e..8383c440cd 100644 --- a/src/assets/i18n/sw.json5 +++ b/src/assets/i18n/sw.json5 @@ -3180,9 +3180,9 @@ // TODO New key - Add a translation "item.edit.relationships.save-button": "Save", - // "item.edit.relationships.no-entity-type": "Add 'relationship.type' metadata to enable relationships for this item", + // "item.edit.relationships.no-entity-type": "Add 'dspace.entity.type' metadata to enable relationships for this item", // TODO New key - Add a translation - "item.edit.relationships.no-entity-type": "Add 'relationship.type' metadata to enable relationships for this item", + "item.edit.relationships.no-entity-type": "Add 'dspace.entity.type' metadata to enable relationships for this item", diff --git a/src/assets/i18n/tr.json5 b/src/assets/i18n/tr.json5 index c4ea2a0d9e..8383c440cd 100644 --- a/src/assets/i18n/tr.json5 +++ b/src/assets/i18n/tr.json5 @@ -3180,9 +3180,9 @@ // TODO New key - Add a translation "item.edit.relationships.save-button": "Save", - // "item.edit.relationships.no-entity-type": "Add 'relationship.type' metadata to enable relationships for this item", + // "item.edit.relationships.no-entity-type": "Add 'dspace.entity.type' metadata to enable relationships for this item", // TODO New key - Add a translation - "item.edit.relationships.no-entity-type": "Add 'relationship.type' metadata to enable relationships for this item", + "item.edit.relationships.no-entity-type": "Add 'dspace.entity.type' metadata to enable relationships for this item", From c308e5fd4d5a7c66fdff379f97fb307a9c2d387f Mon Sep 17 00:00:00 2001 From: Tim Donohue Date: Fri, 12 Mar 2021 14:18:08 -0600 Subject: [PATCH 124/132] Other minor corrections of "relationship type" to "entity type" --- ...m-admin-search-result-grid-element.component.ts | 2 +- ...result-admin-workflow-grid-element.component.ts | 2 +- .../metadata-representation-loader.component.ts | 2 +- .../listable-object-component-loader.component.ts | 2 +- .../type-badge/type-badge.component.spec.ts | 14 +++++++------- 5 files changed, 11 insertions(+), 11 deletions(-) diff --git a/src/app/+admin/admin-search-page/admin-search-results/admin-search-result-grid-element/item-search-result/item-admin-search-result-grid-element.component.ts b/src/app/+admin/admin-search-page/admin-search-results/admin-search-result-grid-element/item-search-result/item-admin-search-result-grid-element.component.ts index 13158204c5..1ab8fee8c2 100644 --- a/src/app/+admin/admin-search-page/admin-search-results/admin-search-result-grid-element/item-search-result/item-admin-search-result-grid-element.component.ts +++ b/src/app/+admin/admin-search-page/admin-search-results/admin-search-result-grid-element/item-search-result/item-admin-search-result-grid-element.component.ts @@ -61,7 +61,7 @@ export class ItemAdminSearchResultGridElementComponent extends SearchResultGridE } /** - * Fetch the component depending on the item's relationship type, view mode and context + * Fetch the component depending on the item's entity type, view mode and context * @returns {GenericConstructor} */ private getComponent(): GenericConstructor { diff --git a/src/app/+admin/admin-workflow-page/admin-workflow-search-results/admin-workflow-search-result-grid-element/workflow-item/workflow-item-search-result-admin-workflow-grid-element.component.ts b/src/app/+admin/admin-workflow-page/admin-workflow-search-results/admin-workflow-search-result-grid-element/workflow-item/workflow-item-search-result-admin-workflow-grid-element.component.ts index cf5746391c..68f10916d5 100644 --- a/src/app/+admin/admin-workflow-page/admin-workflow-search-results/admin-workflow-search-result-grid-element/workflow-item/workflow-item-search-result-admin-workflow-grid-element.component.ts +++ b/src/app/+admin/admin-workflow-page/admin-workflow-search-results/admin-workflow-search-result-grid-element/workflow-item/workflow-item-search-result-admin-workflow-grid-element.component.ts @@ -96,7 +96,7 @@ export class WorkflowItemSearchResultAdminWorkflowGridElementComponent extends S } /** - * Fetch the component depending on the item's relationship type, view mode and context + * Fetch the component depending on the item's entity type, view mode and context * @returns {GenericConstructor} */ private getComponent(item: Item): GenericConstructor { diff --git a/src/app/shared/metadata-representation/metadata-representation-loader.component.ts b/src/app/shared/metadata-representation/metadata-representation-loader.component.ts index 2f2c96dc43..976dfdbda8 100644 --- a/src/app/shared/metadata-representation/metadata-representation-loader.component.ts +++ b/src/app/shared/metadata-representation/metadata-representation-loader.component.ts @@ -64,7 +64,7 @@ export class MetadataRepresentationLoaderComponent implements OnInit { } /** - * Fetch the component depending on the item's relationship type, metadata representation type and context + * Fetch the component depending on the item's entity type, metadata representation type and context * @returns {string} */ private getComponent(): GenericConstructor { diff --git a/src/app/shared/object-collection/shared/listable-object/listable-object-component-loader.component.ts b/src/app/shared/object-collection/shared/listable-object/listable-object-component-loader.component.ts index 7b2e994965..30ad91c1e2 100644 --- a/src/app/shared/object-collection/shared/listable-object/listable-object-component-loader.component.ts +++ b/src/app/shared/object-collection/shared/listable-object/listable-object-component-loader.component.ts @@ -179,7 +179,7 @@ export class ListableObjectComponentLoaderComponent implements OnInit, OnDestroy } /** - * Fetch the component depending on the item's relationship type, view mode and context + * Fetch the component depending on the item's entity type, view mode and context * @returns {GenericConstructor} */ getComponent(renderTypes: (string | GenericConstructor)[], diff --git a/src/app/shared/object-list/type-badge/type-badge.component.spec.ts b/src/app/shared/object-list/type-badge/type-badge.component.spec.ts index a92081dcd5..9a7e22c551 100644 --- a/src/app/shared/object-list/type-badge/type-badge.component.spec.ts +++ b/src/app/shared/object-list/type-badge/type-badge.component.spec.ts @@ -12,7 +12,7 @@ let fixture: ComponentFixture; const type = 'authorOfPublication'; -const mockItemWithRelationshipType = Object.assign(new Item(), { +const mockItemWithEntityType = Object.assign(new Item(), { bundles: observableOf({}), metadata: { 'dspace.entity.type': [ @@ -24,7 +24,7 @@ const mockItemWithRelationshipType = Object.assign(new Item(), { } }); -const mockItemWithoutRelationshipType = Object.assign(new Item(), { +const mockItemWithoutEntityType = Object.assign(new Item(), { bundles: observableOf({}), metadata: { 'dc.title': [ @@ -52,21 +52,21 @@ describe('ItemTypeBadgeComponent', () => { comp = fixture.componentInstance; })); - describe('When the item has a relationship type', () => { + describe('When the item has an entity type', () => { beforeEach(() => { - comp.object = mockItemWithRelationshipType; + comp.object = mockItemWithEntityType; fixture.detectChanges(); }); - it('should show the relationship type badge', () => { + it('should show the entity type badge', () => { const badge = fixture.debugElement.query(By.css('span.badge')); expect(badge.nativeElement.textContent).toContain(type.toLowerCase()); }); }); - describe('When the item has no relationship type', () => { + describe('When the item has no entity type', () => { beforeEach(() => { - comp.object = mockItemWithoutRelationshipType; + comp.object = mockItemWithoutEntityType; fixture.detectChanges(); }); From ae240ff36babb89e3e437275fc74408e146da2fe Mon Sep 17 00:00:00 2001 From: Tim Donohue Date: Wed, 31 Mar 2021 15:33:01 -0500 Subject: [PATCH 125/132] After rebase, replace new references to relationship.type with dspace.entity.type --- src/app/+item-page/item-page-routing-paths.ts | 4 ++-- src/app/core/data/dso-redirect-data.service.spec.ts | 2 +- .../mocks/dspace-rest/mocks/mock-publication-response.json | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/app/+item-page/item-page-routing-paths.ts b/src/app/+item-page/item-page-routing-paths.ts index 8ad5583269..43b37f954a 100644 --- a/src/app/+item-page/item-page-routing-paths.ts +++ b/src/app/+item-page/item-page-routing-paths.ts @@ -10,11 +10,11 @@ export function getItemModuleRoute() { /** * Get the route to an item's page - * Depending on the item's relationship type, the route will either start with /items or /entities + * Depending on the item's entity type, the route will either start with /items or /entities * @param item The item to retrieve the route for */ export function getItemPageRoute(item: Item) { - const type = item.firstMetadataValue('relationship.type'); + const type = item.firstMetadataValue('dspace.entity.type'); return getEntityPageRoute(type, item.uuid); } diff --git a/src/app/core/data/dso-redirect-data.service.spec.ts b/src/app/core/data/dso-redirect-data.service.spec.ts index 43489fbf6d..d64f37ad78 100644 --- a/src/app/core/data/dso-redirect-data.service.spec.ts +++ b/src/app/core/data/dso-redirect-data.service.spec.ts @@ -120,7 +120,7 @@ describe('DsoRedirectDataService', () => { it('should navigate to entities route with the corresponding entity type', () => { remoteData.payload.type = 'item'; remoteData.payload.metadata = { - 'relationship.type': [ + 'dspace.entity.type': [ { language: 'en_US', value: 'Publication' diff --git a/src/app/shared/mocks/dspace-rest/mocks/mock-publication-response.json b/src/app/shared/mocks/dspace-rest/mocks/mock-publication-response.json index d298812e5d..cc4cb5fa46 100644 --- a/src/app/shared/mocks/dspace-rest/mocks/mock-publication-response.json +++ b/src/app/shared/mocks/dspace-rest/mocks/mock-publication-response.json @@ -157,7 +157,7 @@ "place": 0 } ], - "relationship.type": [ + "dspace.entity.type": [ { "value": "Publication", "language": null, From 41e1d0659438e7e9dad5052a53d5e3350b49f5e5 Mon Sep 17 00:00:00 2001 From: lotte Date: Thu, 1 Apr 2021 12:23:26 +0200 Subject: [PATCH 126/132] applied feedback for submission upload section --- .../form/submission-form.component.spec.ts | 9 +++++---- .../form/submission-form.component.ts | 17 +++++++++-------- 2 files changed, 14 insertions(+), 12 deletions(-) diff --git a/src/app/submission/form/submission-form.component.spec.ts b/src/app/submission/form/submission-form.component.spec.ts index d719472adf..94d1033079 100644 --- a/src/app/submission/form/submission-form.component.spec.ts +++ b/src/app/submission/form/submission-form.component.spec.ts @@ -24,7 +24,7 @@ import { HALEndpointServiceStub } from '../../shared/testing/hal-endpoint-servic import { createTestComponent } from '../../shared/testing/utils.test'; import { Item } from '../../core/shared/item.model'; import { TestScheduler } from 'rxjs/testing'; - +import { SectionsService } from '../sections/sections.service'; describe('SubmissionFormComponent Component', () => { @@ -55,6 +55,7 @@ describe('SubmissionFormComponent Component', () => { { provide: AuthService, useClass: AuthServiceStub }, { provide: HALEndpointService, useValue: new HALEndpointServiceStub('workspaceitems') }, { provide: SubmissionService, useValue: submissionServiceStub }, + { provide: SectionsService, useValue: { isSectionAvailable: () => observableOf(true) } }, ChangeDetectorRef, SubmissionFormComponent ], @@ -115,7 +116,7 @@ describe('SubmissionFormComponent Component', () => { expect(compAsAny.submissionSections).toBeUndefined(); expect(compAsAny.subs).toEqual([]); expect(submissionServiceStub.startAutoSave).not.toHaveBeenCalled(); - expect(comp.loading).toBeObservable(cold('(a|)', {a: true})); + expect(comp.loading).toBeObservable(cold('(a|)', { a: true })); done(); }); @@ -140,7 +141,7 @@ describe('SubmissionFormComponent Component', () => { }); scheduler.flush(); - expect(comp.submissionSections).toBeObservable(cold('(a|)', {a: sectionsList})); + expect(comp.submissionSections).toBeObservable(cold('(a|)', { a: sectionsList })); expect(submissionServiceStub.dispatchInit).toHaveBeenCalledWith( collectionId, @@ -201,7 +202,7 @@ describe('SubmissionFormComponent Component', () => { submissionDefinition: { name: 'traditional' } - } as any); + } as any); fixture.detectChanges(); }); scheduler.flush(); diff --git a/src/app/submission/form/submission-form.component.ts b/src/app/submission/form/submission-form.component.ts index a2f4443c3a..d5107fb81a 100644 --- a/src/app/submission/form/submission-form.component.ts +++ b/src/app/submission/form/submission-form.component.ts @@ -16,7 +16,7 @@ import { SectionDataObject } from '../sections/models/section-data.model'; import { SubmissionService } from '../submission.service'; import { Item } from '../../core/shared/item.model'; import { SectionsType } from '../sections/sections-type'; -import { BehaviorSubject } from 'rxjs/internal/BehaviorSubject'; +import { SectionsService } from '../sections/sections.service'; /** * This component represents the submission form. @@ -74,7 +74,7 @@ export class SubmissionFormComponent implements OnChanges, OnDestroy { /** * Emits true when the submission config has bitstream uploading enabled in submission */ - public uploadEnabled$ = new BehaviorSubject(false); + public uploadEnabled$: Observable; /** * Observable of the list of submission's sections @@ -107,12 +107,14 @@ export class SubmissionFormComponent implements OnChanges, OnDestroy { * @param {ChangeDetectorRef} changeDetectorRef * @param {HALEndpointService} halService * @param {SubmissionService} submissionService + * @param {SectionsService} sectionsService */ constructor( private authService: AuthService, private changeDetectorRef: ChangeDetectorRef, private halService: HALEndpointService, - private submissionService: SubmissionService) { + private submissionService: SubmissionService, + private sectionsService: SectionsService) { this.isActive = true; } @@ -135,12 +137,11 @@ export class SubmissionFormComponent implements OnChanges, OnDestroy { } else { return observableOf([]); } - }), - tap((sectionList) => { - this.uploadEnabled$.next(isNotEmpty(sectionList) && sectionList.some(config => config.sectionType === SectionsType.Upload)); - }) - ); + })); + debugger; + this.uploadEnabled$ = this.sectionsService.isSectionAvailable(this.submissionId, SectionsType.Upload); + this.uploadEnabled$.subscribe((t) => {console.log('this.uploadEnabled$', t)}); // check if is submission loading this.loading = this.submissionService.getSubmissionObject(this.submissionId).pipe( filter(() => this.isActive), From 7c5dbae549d8cf8deeafdffc449f50dbbcce00d4 Mon Sep 17 00:00:00 2001 From: lotte Date: Thu, 1 Apr 2021 12:38:43 +0200 Subject: [PATCH 127/132] removed unnecessary import --- src/app/submission/form/submission-form.component.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/app/submission/form/submission-form.component.ts b/src/app/submission/form/submission-form.component.ts index d5107fb81a..0fc0c89cf4 100644 --- a/src/app/submission/form/submission-form.component.ts +++ b/src/app/submission/form/submission-form.component.ts @@ -1,7 +1,7 @@ import { ChangeDetectorRef, Component, Input, OnChanges, OnDestroy, SimpleChanges } from '@angular/core'; import { Observable, of as observableOf, Subscription } from 'rxjs'; -import { distinctUntilChanged, filter, map, switchMap, tap } from 'rxjs/operators'; +import { distinctUntilChanged, filter, map, switchMap } from 'rxjs/operators'; import { AuthService } from '../../core/auth/auth.service'; import { SubmissionDefinitionsModel } from '../../core/config/models/config-submission-definitions.model'; import { Collection } from '../../core/shared/collection.model'; From d3763ea6423f5aa0c367f39cce445c8462122b90 Mon Sep 17 00:00:00 2001 From: lotte Date: Thu, 1 Apr 2021 14:23:02 +0200 Subject: [PATCH 128/132] cleaned up debugging remnants --- src/app/submission/form/submission-form.component.ts | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/app/submission/form/submission-form.component.ts b/src/app/submission/form/submission-form.component.ts index 0fc0c89cf4..328ece199b 100644 --- a/src/app/submission/form/submission-form.component.ts +++ b/src/app/submission/form/submission-form.component.ts @@ -138,10 +138,8 @@ export class SubmissionFormComponent implements OnChanges, OnDestroy { return observableOf([]); } })); - debugger; this.uploadEnabled$ = this.sectionsService.isSectionAvailable(this.submissionId, SectionsType.Upload); - this.uploadEnabled$.subscribe((t) => {console.log('this.uploadEnabled$', t)}); // check if is submission loading this.loading = this.submissionService.getSubmissionObject(this.submissionId).pipe( filter(() => this.isActive), From 94c0af5d861b7ca131aa724552709467b64355fc Mon Sep 17 00:00:00 2001 From: Giuseppe Digilio Date: Thu, 1 Apr 2021 20:03:54 +0200 Subject: [PATCH 129/132] [CST-3620] Remove drag and drop placeholder --- .../models/array-group/dynamic-form-array.component.html | 9 ++------- src/styles/_global-styles.scss | 7 +++++++ 2 files changed, 9 insertions(+), 7 deletions(-) diff --git a/src/app/shared/form/builder/ds-dynamic-form-ui/models/array-group/dynamic-form-array.component.html b/src/app/shared/form/builder/ds-dynamic-form-ui/models/array-group/dynamic-form-array.component.html index 09b1331f8b..fe0c65ea73 100644 --- a/src/app/shared/form/builder/ds-dynamic-form-ui/models/array-group/dynamic-form-array.component.html +++ b/src/app/shared/form/builder/ds-dynamic-form-ui/models/array-group/dynamic-form-array.component.html @@ -12,14 +12,9 @@ [ngClass]="[getClass('element', 'group'), getClass('grid', 'group')]" cdkDrag cdkDragHandle - [cdkDragDisabled]="dragDisabled"> + [cdkDragDisabled]="dragDisabled" + [cdkDragPreviewClass]="'ds-submission-reorder-dragging'"> -
-
- {{ 'form.repeatable.sort.tip' | translate }} -
-
- Date: Fri, 2 Apr 2021 15:22:17 +0200 Subject: [PATCH 130/132] Add isSectionTypeAvailable method and use it to check if upload section is available --- src/app/shared/mocks/submission.mock.ts | 85 +++++++++++++++++++ .../form/submission-form.component.spec.ts | 2 +- .../form/submission-form.component.ts | 2 +- .../sections/sections.service.spec.ts | 34 ++++++-- .../submission/sections/sections.service.ts | 25 +++++- 5 files changed, 136 insertions(+), 12 deletions(-) diff --git a/src/app/shared/mocks/submission.mock.ts b/src/app/shared/mocks/submission.mock.ts index 16cc9b6262..1ee097af71 100644 --- a/src/app/shared/mocks/submission.mock.ts +++ b/src/app/shared/mocks/submission.mock.ts @@ -1101,6 +1101,91 @@ export const mockSubmissionState: SubmissionObjectState = Object.assign({}, { } }); +export const mockSubmissionStateWithoutUpload: SubmissionObjectState = Object.assign({}, { + 826: { + collection: mockSubmissionCollectionId, + definition: 'traditional', + selfUrl: mockSubmissionSelfUrl, + activeSection: null, + sections: { + extraction: { + config: '', + mandatory: true, + sectionType: 'utils', + visibility: { + main: 'HIDDEN', + other: 'HIDDEN' + }, + collapsed: false, + enabled: true, + data: {}, + errors: [], + isLoading: false, + isValid: false + } as any, + collection: { + config: '', + mandatory: true, + sectionType: 'collection', + visibility: { + main: 'HIDDEN', + other: 'HIDDEN' + }, + collapsed: false, + enabled: true, + data: {}, + errors: [], + isLoading: false, + isValid: false + } as any, + traditionalpageone: { + header: 'submit.progressbar.describe.stepone', + config: 'https://rest.api/dspace-spring-rest/api/config/submissionforms/traditionalpageone', + mandatory: true, + sectionType: 'submission-form', + collapsed: false, + enabled: true, + data: {}, + errors: [], + formId: '2_traditionalpageone', + isLoading: false, + isValid: false + } as any, + traditionalpagetwo: { + header: 'submit.progressbar.describe.steptwo', + config: 'https://rest.api/dspace-spring-rest/api/config/submissionforms/traditionalpagetwo', + mandatory: false, + sectionType: 'submission-form', + collapsed: false, + enabled: false, + data: {}, + errors: [], + isLoading: false, + isValid: false + } as any, + license: { + header: 'submit.progressbar.license', + config: '', + mandatory: true, + sectionType: 'license', + visibility: { + main: null, + other: 'READONLY' + }, + collapsed: false, + enabled: true, + data: {}, + errors: [], + isLoading: false, + isValid: false + } as any + }, + isLoading: false, + savePending: false, + depositPending: false + } +}); + export const mockSectionsState = Object.assign({}, { extraction: { config: '', diff --git a/src/app/submission/form/submission-form.component.spec.ts b/src/app/submission/form/submission-form.component.spec.ts index 94d1033079..dd8e6d0ea3 100644 --- a/src/app/submission/form/submission-form.component.spec.ts +++ b/src/app/submission/form/submission-form.component.spec.ts @@ -55,7 +55,7 @@ describe('SubmissionFormComponent Component', () => { { provide: AuthService, useClass: AuthServiceStub }, { provide: HALEndpointService, useValue: new HALEndpointServiceStub('workspaceitems') }, { provide: SubmissionService, useValue: submissionServiceStub }, - { provide: SectionsService, useValue: { isSectionAvailable: () => observableOf(true) } }, + { provide: SectionsService, useValue: { isSectionTypeAvailable: () => observableOf(true) } }, ChangeDetectorRef, SubmissionFormComponent ], diff --git a/src/app/submission/form/submission-form.component.ts b/src/app/submission/form/submission-form.component.ts index 328ece199b..8df0ab1658 100644 --- a/src/app/submission/form/submission-form.component.ts +++ b/src/app/submission/form/submission-form.component.ts @@ -138,7 +138,7 @@ export class SubmissionFormComponent implements OnChanges, OnDestroy { return observableOf([]); } })); - this.uploadEnabled$ = this.sectionsService.isSectionAvailable(this.submissionId, SectionsType.Upload); + this.uploadEnabled$ = this.sectionsService.isSectionTypeAvailable(this.submissionId, SectionsType.Upload); // check if is submission loading this.loading = this.submissionService.getSubmissionObject(this.submissionId).pipe( diff --git a/src/app/submission/sections/sections.service.spec.ts b/src/app/submission/sections/sections.service.spec.ts index 6bdf26a082..0d63beeaea 100644 --- a/src/app/submission/sections/sections.service.spec.ts +++ b/src/app/submission/sections/sections.service.spec.ts @@ -1,4 +1,4 @@ -import { waitForAsync, TestBed } from '@angular/core/testing'; +import { TestBed, waitForAsync } from '@angular/core/testing'; import { cold, getTestScheduler } from 'jasmine-marbles'; import { of as observableOf } from 'rxjs'; @@ -17,7 +17,8 @@ import { SectionsService } from './sections.service'; import { mockSectionsData, mockSectionsErrors, - mockSubmissionState + mockSubmissionState, + mockSubmissionStateWithoutUpload } from '../../shared/mocks/submission.mock'; import { DisableSectionAction, @@ -27,11 +28,7 @@ import { SectionStatusChangeAction, UpdateSectionDataAction } from '../objects/submission-objects.actions'; -import { - FormAddError, - FormClearErrorsAction, - FormRemoveErrorAction -} from '../../shared/form/form.actions'; +import { FormAddError, FormClearErrorsAction, FormRemoveErrorAction } from '../../shared/form/form.actions'; import parseSectionErrors from '../utils/parseSectionErrors'; import { SubmissionScopeType } from '../../core/submission/submission-scope-type'; import { SubmissionSectionError } from '../objects/submission-objects.reducer'; @@ -52,6 +49,7 @@ describe('SectionsService test suite', () => { const sectionErrors: any = parseSectionErrors(mockSectionsErrors); const sectionData: any = mockSectionsData; const submissionState: any = Object.assign({}, mockSubmissionState[submissionId]); + const submissionStateWithoutUpload: any = Object.assign({}, mockSubmissionStateWithoutUpload[submissionId]); const sectionState: any = Object.assign({}, mockSubmissionState['826'].sections[sectionId]); const store: any = jasmine.createSpyObj('store', { @@ -314,6 +312,28 @@ describe('SectionsService test suite', () => { }); }); + describe('isSectionTypeAvailable', () => { + it('should return an observable of true when section is available', () => { + store.select.and.returnValue(observableOf(submissionState)); + + const expected = cold('(b|)', { + b: true + }); + + expect(service.isSectionTypeAvailable(submissionId, SectionsType.Upload)).toBeObservable(expected); + }); + + it('should return an observable of false when section is not available', () => { + store.select.and.returnValue(observableOf(submissionStateWithoutUpload)); + + const expected = cold('(b|)', { + b: false + }); + + expect(service.isSectionAvailable(submissionId, SectionsType.Upload)).toBeObservable(expected); + }); + }); + describe('addSection', () => { it('should dispatch a new EnableSectionAction a move target to new section', () => { diff --git a/src/app/submission/sections/sections.service.ts b/src/app/submission/sections/sections.service.ts index b2bc0e4f98..d8d1491cb7 100644 --- a/src/app/submission/sections/sections.service.ts +++ b/src/app/submission/sections/sections.service.ts @@ -5,7 +5,7 @@ import { distinctUntilChanged, filter, map, take } from 'rxjs/operators'; import { Store } from '@ngrx/store'; import { TranslateService } from '@ngx-translate/core'; import { ScrollToConfigOptions, ScrollToService } from '@nicky-lenaers/ngx-scroll-to'; -import { isEqual } from 'lodash'; +import { findKey, isEqual } from 'lodash'; import { SubmissionState } from '../submission.reducers'; import { hasValue, isEmpty, isNotEmpty, isNotUndefined } from '../../shared/empty.util'; @@ -291,14 +291,14 @@ export class SectionsService { } /** - * Check if a given section is a read only available + * Check if a given section id is present in the list of sections * * @param submissionId * The submission id * @param sectionId * The section id * @return Observable - * Emits true whenever a given section should be available + * Emits true whenever a given section id should be available */ public isSectionAvailable(submissionId: string, sectionId: string): Observable { return this.store.select(submissionObjectFromIdSelector(submissionId)).pipe( @@ -309,6 +309,25 @@ export class SectionsService { distinctUntilChanged()); } + /** + * Check if a given section type is present in the list of sections + * + * @param submissionId + * The submission id + * @param sectionType + * The section type + * @return Observable + * Emits true whenever a given section type should be available + */ + public isSectionTypeAvailable(submissionId: string, sectionType: SectionsType): Observable { + return this.store.select(submissionObjectFromIdSelector(submissionId)).pipe( + filter((submissionState: SubmissionObjectEntry) => isNotUndefined(submissionState)), + map((submissionState: SubmissionObjectEntry) => { + return isNotUndefined(submissionState.sections) && isNotUndefined(findKey(submissionState.sections, {sectionType: sectionType})); + }), + distinctUntilChanged()); + } + /** * Dispatch a new [EnableSectionAction] to add a new section and move page target to it * From 740228695477889320e161b49626149e20a43fe2 Mon Sep 17 00:00:00 2001 From: Giuseppe Date: Fri, 2 Apr 2021 16:14:56 +0200 Subject: [PATCH 131/132] #728 accessibility theming (#1057) * [CST-3763] Change base theme colors * [CST-3763] added new custom variables * [CST-3763] applied changes to the header in order to have two different navbar * [CST-3763] applied changes to breadcrumbs navbar * [CST-3763] fix sidebar colors * [CST-3763] applied changes footer in order to have two different sections * [CST-3763] change home news jumbotron background color * [CST-3763] fix issue with search-navbar.component z-index * [CST-3763] fix issue with search-form.component that didn't use the brand colo parameter * [CST-3763] fix issue with menu navbar on small window view * [CST-3763] changed position for browse all button in the access control pages * [CST-3763] Change form.component in order to have possibilities to display better additional form buttons * [CST-3763] Change confirmation-modal.component in order to allow different colors and icons for confirm button * [CST-3763] added confirmation icon * [CST-3763] fixed accessibility for admin access control components * [CST-3763] Added placeholder for search boxes * [CST-3763] Added repository logo alt label * [CST-3763] Adjust notification icons * [CST-3763] Fix issue with hideReturnButton param in edit-comcol-page.component that was not initialized on page refresh * Accessibility fix * [CST-3763] Adjust usability for community/collection edit * [CST-3763] fix error while running test * [CST-3763] Added dynamically a title prefix to all dspace page * [CST-3763] add breadcrumbs to the page where are missing * [CST-3763] fixed failed tests * [CST-3763] fixed failed e2e test * [CST-3763] fixed failed e2e test * Buttons fixes for accessibility * [CST-3973] fixed issue with redirect after changing language * Buttons and sections fixes for accessibility * Buttons and sections fixes for accessibility * [CST-3763] fixed colors for chips component * [CST-3977] fixed issue with selecting a tag submission field * [CST-3763] add breadcrumbs to the page where are missing * [CST-3763] fixed edit workflowitem buttons color * [CST-3977] removed unintentional committed log * [CST-3763] Fix issue with tab selection in item edit page * [CST-3763] Fix position of back button in the item edit page * [CST-3763] icon and colors for search and browse all buttons * [CST-3763] added atkinson font * [CST-3763] remove dspace logo from home news * [CST-3763] fix buttons colors for administrative search * [CST-3763] Change background color for user menu * [CST-3763] remove gradient from home page news component * [CST-3763] fix issue with edit dso button * [CST-3763] revert color schema * [CST-3763] remove Atkinson-Hyperlegible font * [CST-3763] fix use of header-logo-height variable * [CST-3763] fix homepage link color * [CST-3763] fix contrast color issue for navbar menu entries * [CST-3763] add variable to show/hide top footer container * [CST-3763] change dso edit button style * [CST-3763] ensure to use "back" and "save" labels * [CST-3763] Remove border from header * [CST-3763] Change header in order to have only navigation bar in a single row * Update src/app/root/root.component.html Co-authored-by: Art Lowel * [CST-3763] Fix issue with wrong grid-breakpoints that cause issue on navbar collapsing * [CST-3763] Fix issue with language dropdown when navbar is collapsed * [CST-3763] Fix issue after merging Co-authored-by: Matteo Perelli Co-authored-by: Art Lowel --- .vscode/settings.json | 6 +- e2e/src/search-navbar/search-navbar.po.ts | 10 +- package.json | 2 +- ...admin-search-result-actions.component.html | 33 ++-- .../admin-sidebar-section.component.html | 12 +- .../admin-sidebar.component.html | 9 +- .../admin-sidebar/admin-sidebar.component.ts | 6 +- ...dable-admin-sidebar-section.component.html | 6 +- ...dable-admin-sidebar-section.component.scss | 4 + .../collection-form.component.ts | 6 +- .../collection-item-mapper.component.html | 1 + .../create-collection-page.component.html | 4 +- .../delete-collection-page.component.html | 19 ++- .../collection-metadata.component.html | 8 +- .../collection-roles.component.spec.ts | 2 + .../collection-source.component.html | 1 + .../edit-collection-page.component.spec.ts | 9 +- .../edit-collection-page.routing.module.ts | 2 +- .../community-form.component.ts | 6 +- .../create-community-page.component.html | 4 +- .../delete-community-page.component.html | 20 +-- .../community-metadata.component.html | 9 +- .../community-roles.component.spec.ts | 2 + .../edit-community-page.component.spec.ts | 9 +- .../home-news/home-news.component.html | 1 - .../home-news/home-news.component.scss | 13 +- src/app/+home-page/home-page.component.html | 2 +- .../edit-item-page.component.html | 6 +- .../edit-item-page.component.ts | 12 +- .../item-bitstreams.component.html | 26 ++-- .../item-collection-mapper.component.html | 1 + .../item-metadata.component.html | 32 ++-- .../item-operation.component.html | 4 +- .../publication/publication.component.html | 4 +- .../untyped-item/untyped-item.component.html | 4 +- src/app/+login-page/login-page.component.html | 2 +- .../my-dspace-new-submission.component.html | 6 +- .../my-dspace-page-routing.module.ts | 6 +- .../my-dspace-page.component.html | 3 +- src/app/+search-page/search.component.html | 3 +- .../submit-page-routing.module.ts | 6 +- .../workflowitems-edit-page-routing.module.ts | 22 ++- ...workspaceitems-edit-page-routing.module.ts | 6 +- .../access-control-routing.module.ts | 33 +++- .../epeople-registry.component.html | 41 +++-- .../epeople-registry.component.ts | 10 ++ .../eperson-form/eperson-form.component.html | 32 ++-- .../eperson-form/eperson-form.component.ts | 2 + .../group-form/group-form.component.html | 32 ++-- .../group-form/group-form.component.ts | 2 + .../members-list/members-list.component.html | 17 +- .../subgroups-list.component.html | 20 ++- .../groups-registry.component.html | 47 +++--- .../groups-registry.component.ts | 7 + src/app/app.module.ts | 6 - .../breadcrumbs/breadcrumbs.component.html | 4 +- .../breadcrumbs/breadcrumbs.component.scss | 22 +++ .../community-list-page.routing.module.ts | 6 +- .../community-list.component.html | 5 +- src/app/core/locale/locale.service.spec.ts | 9 +- src/app/core/locale/locale.service.ts | 13 +- .../core/metadata/metadata.service.spec.ts | 11 +- src/app/core/metadata/metadata.service.ts | 10 +- src/app/core/services/route.service.spec.ts | 28 ++++ src/app/core/services/route.service.ts | 12 ++ src/app/footer/footer.component.html | 90 ++++++++--- src/app/footer/footer.component.scss | 42 ++--- src/app/footer/footer.component.ts | 5 + .../header-navbar-wrapper.component.html | 1 - src/app/header/header.component.html | 23 +-- src/app/header/header.component.scss | 24 ++- .../expandable-navbar-section.component.html | 2 +- .../navbar-section.component.html | 2 +- src/app/navbar/navbar.component.html | 31 ++-- src/app/navbar/navbar.component.scss | 24 ++- src/app/navbar/navbar.component.ts | 23 ++- src/app/navbar/navbar.module.ts | 2 + .../profile-page-metadata-form.component.html | 3 +- .../profile-page-security-form.component.html | 3 +- .../profile-page/profile-page.component.html | 4 +- src/app/root/root.component.html | 12 +- .../search-navbar.component.html | 2 +- .../search-navbar.component.scss | 10 +- .../auth-nav-menu.component.html | 16 +- .../auth-nav-menu.component.scss | 8 + .../shared/browse-by/browse-by.component.html | 6 +- src/app/shared/chips/chips.component.html | 7 +- src/app/shared/chips/chips.component.scss | 2 +- src/app/shared/chips/chips.component.ts | 4 + .../comcol-form/comcol-form.component.html | 16 +- .../comcol-form/comcol-form.component.spec.ts | 7 - .../comcol-form/comcol-form.component.ts | 16 +- .../create-comcol-page.component.ts | 7 + .../comcol-role/comcol-role.component.html | 40 ++--- .../comcol-role/comcol-role.component.spec.ts | 2 + .../comcol-role/comcol-role.component.ts | 1 + .../edit-comcol-page.component.html | 15 +- .../edit-comcol-page.component.ts | 20 ++- .../confirmation-modal.component.html | 10 +- .../confirmation-modal.component.ts | 6 + .../dso-page-edit-button.component.html | 5 +- .../export-metadata-selector.component.ts | 1 + .../dynamic-relation-group.component.html | 1 + .../models/tag/dynamic-tag.component.html | 4 +- ...elation-external-source-tab.component.html | 5 +- ...-lookup-relation-search-tab.component.html | 5 +- src/app/shared/form/form.component.html | 15 +- src/app/shared/form/form.component.spec.ts | 6 +- src/app/shared/form/form.component.ts | 7 +- .../lang-switch/lang-switch.component.html | 6 +- .../lang-switch/lang-switch.component.scss | 10 ++ .../password/log-in-password.component.html | 2 +- .../log-in-shibboleth.component.html | 8 +- src/app/shared/log-out/log-out.component.html | 2 +- .../notification/notification.component.html | 4 +- .../collection-select.component.html | 4 +- .../pagination/pagination.component.html | 2 +- .../eperson-search-box.component.html | 4 +- .../group-search-box.component.html | 4 +- .../form/resource-policy-form.component.html | 3 +- .../search-form/search-form.component.html | 5 +- .../search-form/search-form.component.ts | 6 +- .../search-filter.component.html | 4 +- .../search-range-filter.component.scss | 4 + .../search-filters.component.html | 2 +- src/app/shared/shared.module.ts | 2 + .../date/starts-with-date.component.html | 8 +- .../text/starts-with-text.component.html | 2 +- .../submission-form-footer.component.html | 20 ++- .../sections/form/section-form.component.html | 1 + .../license/section-license.component.html | 1 + .../section-upload-file-edit.component.html | 1 + src/assets/i18n/en.json5 | 146 +++++++++++++----- src/styles/_bootstrap_variables.scss | 20 +-- src/styles/_custom_variables.scss | 32 +++- yarn.lock | 8 +- 136 files changed, 1041 insertions(+), 523 deletions(-) diff --git a/.vscode/settings.json b/.vscode/settings.json index ccdda087eb..e8522b85d7 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,3 +1,7 @@ { - "typescript.check.workspaceVersion": false + "typescript.check.workspaceVersion": false, + "i18n-ally.localesPaths": [ + "src/assets/i18n", + "src/app/core/locale" + ] } \ No newline at end of file diff --git a/e2e/src/search-navbar/search-navbar.po.ts b/e2e/src/search-navbar/search-navbar.po.ts index 7401e881e7..c1ac817fd2 100644 --- a/e2e/src/search-navbar/search-navbar.po.ts +++ b/e2e/src/search-navbar/search-navbar.po.ts @@ -14,22 +14,22 @@ export class ProtractorPage { } getCurrentQuery(): promise.Promise { - return element(by.css('#search-navbar-container form input')).getAttribute('value'); + return element(by.css('.navbar-container #search-navbar-container form input')).getAttribute('value'); } expandAndFocusSearchBox() { - element(by.css('#search-navbar-container form a')).click(); + element(by.css('.navbar-container #search-navbar-container form a')).click(); } setCurrentQuery(query: string) { - element(by.css('#search-navbar-container form input[name="query"]')).sendKeys(query); + element(by.css('.navbar-container #search-navbar-container form input[name="query"]')).sendKeys(query); } submitNavbarSearchForm() { - element(by.css('#search-navbar-container form .submit-icon')).click(); + element(by.css('.navbar-container #search-navbar-container form .submit-icon')).click(); } submitByPressingEnter() { - element(by.css('#search-navbar-container form input[name="query"]')).sendKeys(protractor.Key.ENTER); + element(by.css('.navbar-container #search-navbar-container form input[name="query"]')).sendKeys(protractor.Key.ENTER); } } diff --git a/package.json b/package.json index 8c416ee4e1..4008bb0ac3 100644 --- a/package.json +++ b/package.json @@ -119,7 +119,7 @@ "rxjs": "^6.6.3", "rxjs-spy": "^7.5.3", "sass-resources-loader": "^2.1.1", - "sortablejs": "1.10.1", + "sortablejs": "1.13.0", "tslib": "^2.0.0", "webfontloader": "1.6.28", "zone.js": "^0.10.3", diff --git a/src/app/+admin/admin-search-page/admin-search-results/item-admin-search-result-actions.component.html b/src/app/+admin/admin-search-page/admin-search-results/item-admin-search-result-actions.component.html index 2ee828e870..fbbbbb255c 100644 --- a/src/app/+admin/admin-search-page/admin-search-results/item-admin-search-result-actions.component.html +++ b/src/app/+admin/admin-search-page/admin-search-results/item-admin-search-result-actions.component.html @@ -1,27 +1,28 @@ -
- {{"admin.search.item.edit" | translate}} + + {{"admin.search.item.move" | translate}} - - {{"admin.search.item.withdraw" | translate}} - - - - {{"admin.search.item.reinstate" | translate}} - - - + {{"admin.search.item.make-private" | translate}} - + {{"admin.search.item.make-public" | translate}} - + + {{"admin.search.item.edit" | translate}} + + + + {{"admin.search.item.withdraw" | translate}} + + + + {{"admin.search.item.reinstate" | translate}} + + + {{"admin.search.item.delete" | translate}} - - {{"admin.search.item.move" | translate}} - diff --git a/src/app/+admin/admin-sidebar/admin-sidebar-section/admin-sidebar-section.component.html b/src/app/+admin/admin-sidebar/admin-sidebar-section/admin-sidebar-section.component.html index eb06df3630..4c13c7c570 100644 --- a/src/app/+admin/admin-sidebar/admin-sidebar-section/admin-sidebar-section.component.html +++ b/src/app/+admin/admin-sidebar/admin-sidebar-section/admin-sidebar-section.component.html @@ -1,11 +1,11 @@ diff --git a/src/app/+admin/admin-sidebar/admin-sidebar.component.html b/src/app/+admin/admin-sidebar/admin-sidebar.component.html index 357ed058d1..4dddc89920 100644 --- a/src/app/+admin/admin-sidebar/admin-sidebar.component.html +++ b/src/app/+admin/admin-sidebar/admin-sidebar.component.html @@ -1,11 +1,12 @@
- +

diff --git a/src/app/+collection-page/delete-collection-page/delete-collection-page.component.html b/src/app/+collection-page/delete-collection-page/delete-collection-page.component.html index cfd09f2bbd..737c40264b 100644 --- a/src/app/+collection-page/delete-collection-page/delete-collection-page.component.html +++ b/src/app/+collection-page/delete-collection-page/delete-collection-page.component.html @@ -2,15 +2,18 @@
- +

{{ 'community.delete.text' | translate:{ dso: dso.name } }}

- - +
+
+ + +
+
diff --git a/src/app/+collection-page/edit-collection-page/collection-metadata/collection-metadata.component.html b/src/app/+collection-page/edit-collection-page/collection-metadata/collection-metadata.component.html index b4eaf46bfb..9818813e32 100644 --- a/src/app/+collection-page/edit-collection-page/collection-metadata/collection-metadata.component.html +++ b/src/app/+collection-page/edit-collection-page/collection-metadata/collection-metadata.component.html @@ -16,9 +16,7 @@
- -{{'collection.edit.delete' - | translate}} diff --git a/src/app/+collection-page/edit-collection-page/collection-roles/collection-roles.component.spec.ts b/src/app/+collection-page/edit-collection-page/collection-roles/collection-roles.component.spec.ts index da26e2b451..401065a661 100644 --- a/src/app/+collection-page/edit-collection-page/collection-roles/collection-roles.component.spec.ts +++ b/src/app/+collection-page/edit-collection-page/collection-roles/collection-roles.component.spec.ts @@ -11,6 +11,7 @@ import { GroupDataService } from '../../../core/eperson/group-data.service'; import { RequestService } from '../../../core/data/request.service'; import { RouterTestingModule } from '@angular/router/testing'; import { createSuccessfulRemoteDataObject, createSuccessfulRemoteDataObject$ } from '../../../shared/remote-data.utils'; +import { NoopAnimationsModule } from '@angular/platform-browser/animations'; describe('CollectionRolesComponent', () => { @@ -67,6 +68,7 @@ describe('CollectionRolesComponent', () => { SharedModule, RouterTestingModule.withRoutes([]), TranslateModule.forRoot(), + NoopAnimationsModule ], declarations: [ CollectionRolesComponent, diff --git a/src/app/+collection-page/edit-collection-page/collection-source/collection-source.component.html b/src/app/+collection-page/edit-collection-page/collection-source/collection-source.component.html index 4192922c7e..de7f0b4708 100644 --- a/src/app/+collection-page/edit-collection-page/collection-source/collection-source.component.html +++ b/src/app/+collection-page/edit-collection-page/collection-source/collection-source.component.html @@ -31,6 +31,7 @@ [formModel]="formModel" [formLayout]="formLayout" [displaySubmit]="false" + [displayCancel]="false" (dfChange)="onChange($event)" (submitForm)="onSubmit()" (cancel)="onCancel()"> diff --git a/src/app/+collection-page/edit-collection-page/edit-collection-page.component.spec.ts b/src/app/+collection-page/edit-collection-page/edit-collection-page.component.spec.ts index 37adf4dece..00f05f50c0 100644 --- a/src/app/+collection-page/edit-collection-page/edit-collection-page.component.spec.ts +++ b/src/app/+collection-page/edit-collection-page/edit-collection-page.component.spec.ts @@ -18,7 +18,14 @@ describe('EditCollectionPageComponent', () => { dso: { payload: {} } }), routeConfig: { - children: [] + children: [ + { + path: 'mockUrl', + data: { + hideReturnButton: false + } + } + ] }, snapshot: { firstChild: { diff --git a/src/app/+collection-page/edit-collection-page/edit-collection-page.routing.module.ts b/src/app/+collection-page/edit-collection-page/edit-collection-page.routing.module.ts index e523cee991..92fc6efeff 100644 --- a/src/app/+collection-page/edit-collection-page/edit-collection-page.routing.module.ts +++ b/src/app/+collection-page/edit-collection-page/edit-collection-page.routing.module.ts @@ -93,7 +93,7 @@ import { CollectionAdministratorGuard } from '../../core/data/feature-authorizat { path: 'mapper', component: CollectionItemMapperComponent, - data: { title: 'collection.edit.tabs.item-mapper.title', showBreadcrumbs: true } + data: { title: 'collection.edit.tabs.item-mapper.title', hideReturnButton: true, showBreadcrumbs: true } }, ] } diff --git a/src/app/+community-page/community-form/community-form.component.ts b/src/app/+community-page/community-form/community-form.component.ts index e9bd2f66c8..59480e8f68 100644 --- a/src/app/+community-page/community-form/community-form.component.ts +++ b/src/app/+community-page/community-form/community-form.component.ts @@ -7,7 +7,6 @@ import { } from '@ng-dynamic-forms/core'; import { Community } from '../../core/shared/community.model'; import { ComColFormComponent } from '../../shared/comcol-forms/comcol-form/comcol-form.component'; -import { Location } from '@angular/common'; import { TranslateService } from '@ngx-translate/core'; import { NotificationsService } from '../../shared/notifications/notifications.service'; import { CommunityDataService } from '../../core/data/community-data.service'; @@ -68,14 +67,13 @@ export class CommunityFormComponent extends ComColFormComponent { }), ]; - public constructor(protected location: Location, - protected formService: DynamicFormService, + public constructor(protected formService: DynamicFormService, protected translate: TranslateService, protected notificationsService: NotificationsService, protected authService: AuthService, protected dsoService: CommunityDataService, protected requestService: RequestService, protected objectCache: ObjectCacheService) { - super(location, formService, translate, notificationsService, authService, requestService, objectCache); + super(formService, translate, notificationsService, authService, requestService, objectCache); } } diff --git a/src/app/+community-page/create-community-page/create-community-page.component.html b/src/app/+community-page/create-community-page/create-community-page.component.html index 4f75771f6d..71a580b0aa 100644 --- a/src/app/+community-page/create-community-page/create-community-page.component.html +++ b/src/app/+community-page/create-community-page/create-community-page.component.html @@ -7,5 +7,7 @@
- +
diff --git a/src/app/+community-page/delete-community-page/delete-community-page.component.html b/src/app/+community-page/delete-community-page/delete-community-page.component.html index cfd09f2bbd..85aa8b1bce 100644 --- a/src/app/+community-page/delete-community-page/delete-community-page.component.html +++ b/src/app/+community-page/delete-community-page/delete-community-page.component.html @@ -2,18 +2,20 @@
- +

{{ 'community.delete.text' | translate:{ dso: dso.name } }}

- - +
+
+ + +
+
-
diff --git a/src/app/+community-page/edit-community-page/community-metadata/community-metadata.component.html b/src/app/+community-page/edit-community-page/community-metadata/community-metadata.component.html index 6b441dbabd..2ca5b768e4 100644 --- a/src/app/+community-page/edit-community-page/community-metadata/community-metadata.component.html +++ b/src/app/+community-page/edit-community-page/community-metadata/community-metadata.component.html @@ -1,6 +1,5 @@ - -{{'community.edit.delete' - | translate}} + diff --git a/src/app/+community-page/edit-community-page/community-roles/community-roles.component.spec.ts b/src/app/+community-page/edit-community-page/community-roles/community-roles.component.spec.ts index b5229143ff..b61705126c 100644 --- a/src/app/+community-page/edit-community-page/community-roles/community-roles.component.spec.ts +++ b/src/app/+community-page/edit-community-page/community-roles/community-roles.component.spec.ts @@ -11,6 +11,7 @@ import { GroupDataService } from '../../../core/eperson/group-data.service'; import { SharedModule } from '../../../shared/shared.module'; import { RouterTestingModule } from '@angular/router/testing'; import { createSuccessfulRemoteDataObject, createSuccessfulRemoteDataObject$ } from '../../../shared/remote-data.utils'; +import { NoopAnimationsModule } from '@angular/platform-browser/animations'; describe('CommunityRolesComponent', () => { @@ -52,6 +53,7 @@ describe('CommunityRolesComponent', () => { SharedModule, RouterTestingModule.withRoutes([]), TranslateModule.forRoot(), + NoopAnimationsModule ], declarations: [ CommunityRolesComponent, diff --git a/src/app/+community-page/edit-community-page/edit-community-page.component.spec.ts b/src/app/+community-page/edit-community-page/edit-community-page.component.spec.ts index bea310c8fb..3a4c3351c3 100644 --- a/src/app/+community-page/edit-community-page/edit-community-page.component.spec.ts +++ b/src/app/+community-page/edit-community-page/edit-community-page.component.spec.ts @@ -18,7 +18,14 @@ describe('EditCommunityPageComponent', () => { dso: { payload: {} } }), routeConfig: { - children: [] + children: [ + { + path: 'mockUrl', + data: { + hideReturnButton: false + } + } + ] }, snapshot: { firstChild: { diff --git a/src/app/+home-page/home-news/home-news.component.html b/src/app/+home-page/home-news/home-news.component.html index 28e10c5804..812c38f798 100644 --- a/src/app/+home-page/home-news/home-news.component.html +++ b/src/app/+home-page/home-news/home-news.component.html @@ -1,7 +1,6 @@
-

Welcome to the DSpace 7 Preview

DSpace is the world leading open source repository platform that enables organisations to:

diff --git a/src/app/+home-page/home-news/home-news.component.scss b/src/app/+home-page/home-news/home-news.component.scss index e58dd08ccf..9ab24daa25 100644 --- a/src/app/+home-page/home-news/home-news.component.scss +++ b/src/app/+home-page/home-news/home-news.component.scss @@ -8,7 +8,14 @@ word-break: break-word; } -.dspace-logo { - height: 110px; - width: 110px; +.jumbotron { + background-color: var(--ds-home-news-background-color); +} + +a { + color: var(--ds-home-news-link-color); + + @include hover { + color: var(--ds-home-news-link-hover-color); + } } diff --git a/src/app/+home-page/home-page.component.html b/src/app/+home-page/home-page.component.html index 5902fa30af..0f7db182f0 100644 --- a/src/app/+home-page/home-page.component.html +++ b/src/app/+home-page/home-page.component.html @@ -3,6 +3,6 @@ - +
diff --git a/src/app/+item-page/edit-item-page/edit-item-page.component.html b/src/app/+item-page/edit-item-page/edit-item-page.component.html index 6b6f74309c..28cc4277dc 100644 --- a/src/app/+item-page/edit-item-page/edit-item-page.component.html +++ b/src/app/+item-page/edit-item-page/edit-item-page.component.html @@ -23,7 +23,11 @@
- Cancel +
diff --git a/src/app/+item-page/edit-item-page/edit-item-page.component.ts b/src/app/+item-page/edit-item-page/edit-item-page.component.ts index 5f1889a404..652b85916e 100644 --- a/src/app/+item-page/edit-item-page/edit-item-page.component.ts +++ b/src/app/+item-page/edit-item-page/edit-item-page.component.ts @@ -39,12 +39,11 @@ export class EditItemPageComponent implements OnInit { pages: { page: string, enabled: Observable }[]; constructor(private route: ActivatedRoute, private router: Router, private injector: Injector) { - this.router.events.subscribe(() => { - this.currentPage = this.route.snapshot.firstChild.routeConfig.path; - }); + this.router.events.subscribe(() => this.initPageParamsByRoute()); } ngOnInit(): void { + this.initPageParamsByRoute(); this.pages = this.route.routeConfig.children .filter((child: Route) => isNotEmpty(child.path)) .map((child: Route) => { @@ -70,4 +69,11 @@ export class EditItemPageComponent implements OnInit { getItemPage(item: Item): string { return getItemPageRoute(item); } + + /** + * Set page params depending on the route + */ + initPageParamsByRoute() { + this.currentPage = this.route.snapshot.firstChild.routeConfig.path; + } } diff --git a/src/app/+item-page/edit-item-page/item-bitstreams/item-bitstreams.component.html b/src/app/+item-page/edit-item-page/item-bitstreams/item-bitstreams.component.html index 9ab2029896..315498378a 100644 --- a/src/app/+item-page/edit-item-page/item-bitstreams/item-bitstreams.component.html +++ b/src/app/+item-page/edit-item-page/item-bitstreams/item-bitstreams.component.html @@ -5,22 +5,22 @@ class="fas fa-upload">  {{"item.edit.bitstreams.upload-button" | translate}} - - +
@@ -48,12 +48,6 @@
- +
diff --git a/src/app/+item-page/edit-item-page/item-collection-mapper/item-collection-mapper.component.html b/src/app/+item-page/edit-item-page/item-collection-mapper/item-collection-mapper.component.html index a65111eaec..589981d3c9 100644 --- a/src/app/+item-page/edit-item-page/item-collection-mapper/item-collection-mapper.component.html +++ b/src/app/+item-page/edit-item-page/item-collection-mapper/item-collection-mapper.component.html @@ -29,6 +29,7 @@ [query]="(searchOptions$ | async)?.query" [currentUrl]="'./'" [inPlaceSearch]="true" + [searchPlaceholder]="'item.edit.item-mapper.search-form.placeholder' | translate" (submitSearch)="performedSearch = true"> diff --git a/src/app/+item-page/edit-item-page/item-metadata/item-metadata.component.html b/src/app/+item-page/edit-item-page/item-metadata/item-metadata.component.html index b743ef2745..008708d3fb 100644 --- a/src/app/+item-page/edit-item-page/item-metadata/item-metadata.component.html +++ b/src/app/+item-page/edit-item-page/item-metadata/item-metadata.component.html @@ -5,12 +5,6 @@ class="fas fa-plus">  {{"item.edit.metadata.add-button" | translate}} - + @@ -47,20 +47,20 @@
-
- + + - -
diff --git a/src/app/+item-page/edit-item-page/item-operation/item-operation.component.html b/src/app/+item-page/edit-item-page/item-operation/item-operation.component.html index 3a52fd0d12..e3989f02f3 100644 --- a/src/app/+item-page/edit-item-page/item-operation/item-operation.component.html +++ b/src/app/+item-page/edit-item-page/item-operation/item-operation.component.html @@ -4,7 +4,7 @@ @@ -12,4 +12,4 @@ {{'item.edit.tabs.status.buttons.' + operation.operationKey + '.button' | translate}} - \ No newline at end of file + diff --git a/src/app/+item-page/simple/item-types/publication/publication.component.html b/src/app/+item-page/simple/item-types/publication/publication.component.html index a004712e0f..73219cbb8f 100644 --- a/src/app/+item-page/simple/item-types/publication/publication.component.html +++ b/src/app/+item-page/simple/item-types/publication/publication.component.html @@ -79,8 +79,8 @@ diff --git a/src/app/+item-page/simple/item-types/untyped-item/untyped-item.component.html b/src/app/+item-page/simple/item-types/untyped-item/untyped-item.component.html index 7a1366dda9..8d46a2c5a9 100644 --- a/src/app/+item-page/simple/item-types/untyped-item/untyped-item.component.html +++ b/src/app/+item-page/simple/item-types/untyped-item/untyped-item.component.html @@ -64,8 +64,8 @@ diff --git a/src/app/+login-page/login-page.component.html b/src/app/+login-page/login-page.component.html index 84059877f4..2a95e0ce1c 100644 --- a/src/app/+login-page/login-page.component.html +++ b/src/app/+login-page/login-page.component.html @@ -1,7 +1,7 @@
- +

{{"login.form.header" | translate}}

diff --git a/src/app/+my-dspace-page/my-dspace-new-submission/my-dspace-new-submission.component.html b/src/app/+my-dspace-page/my-dspace-new-submission/my-dspace-new-submission.component.html index 9ae38a2205..028b7df5a5 100644 --- a/src/app/+my-dspace-page/my-dspace-new-submission/my-dspace-new-submission.component.html +++ b/src/app/+my-dspace-page/my-dspace-new-submission/my-dspace-new-submission.component.html @@ -8,12 +8,12 @@
-
diff --git a/src/app/+my-dspace-page/my-dspace-page-routing.module.ts b/src/app/+my-dspace-page/my-dspace-page-routing.module.ts index 46deb36e20..6894194344 100644 --- a/src/app/+my-dspace-page/my-dspace-page-routing.module.ts +++ b/src/app/+my-dspace-page/my-dspace-page-routing.module.ts @@ -2,6 +2,7 @@ import { NgModule } from '@angular/core'; import { RouterModule } from '@angular/router'; import { MyDSpaceGuard } from './my-dspace.guard'; import { ThemedMyDSpacePageComponent } from './themed-my-dspace-page.component'; +import { I18nBreadcrumbResolver } from '../core/breadcrumbs/i18n-breadcrumb.resolver'; @NgModule({ imports: [ @@ -9,7 +10,10 @@ import { ThemedMyDSpacePageComponent } from './themed-my-dspace-page.component'; { path: '', component: ThemedMyDSpacePageComponent, - data: { title: 'mydspace.title' }, + resolve: { + breadcrumb: I18nBreadcrumbResolver + }, + data: { title: 'mydspace.title', breadcrumbKey: 'mydspace' }, canActivate: [ MyDSpaceGuard ] diff --git a/src/app/+my-dspace-page/my-dspace-page.component.html b/src/app/+my-dspace-page/my-dspace-page.component.html index 55d1e304d0..c911e2c319 100644 --- a/src/app/+my-dspace-page/my-dspace-page.component.html +++ b/src/app/+my-dspace-page/my-dspace-page.component.html @@ -14,7 +14,8 @@ [scope]="(searchOptions$ | async)?.scope" [currentUrl]="getSearchLink()" [scopes]="(scopeListRD$ | async)" - [inPlaceSearch]="inPlaceSearch"> + [inPlaceSearch]="inPlaceSearch" + [searchPlaceholder]="'mydspace.search-form.placeholder' | translate">
diff --git a/src/app/+search-page/search.component.html b/src/app/+search-page/search.component.html index ee96f703f2..7cb16caebe 100644 --- a/src/app/+search-page/search.component.html +++ b/src/app/+search-page/search.component.html @@ -45,7 +45,8 @@ [scope]="(searchOptions$ | async)?.scope" [currentUrl]="searchLink" [scopes]="(scopeListRD$ | async)" - [inPlaceSearch]="inPlaceSearch"> + [inPlaceSearch]="inPlaceSearch" + [searchPlaceholder]="'search.search-form.placeholder' | translate">
diff --git a/src/app/+submit-page/submit-page-routing.module.ts b/src/app/+submit-page/submit-page-routing.module.ts index 92c9bd8cdf..1572580b6a 100644 --- a/src/app/+submit-page/submit-page-routing.module.ts +++ b/src/app/+submit-page/submit-page-routing.module.ts @@ -3,6 +3,7 @@ import { RouterModule } from '@angular/router'; import { AuthenticatedGuard } from '../core/auth/authenticated.guard'; import { ThemedSubmissionSubmitComponent } from '../submission/submit/themed-submission-submit.component'; +import { I18nBreadcrumbResolver } from '../core/breadcrumbs/i18n-breadcrumb.resolver'; @NgModule({ imports: [ @@ -12,7 +13,10 @@ import { ThemedSubmissionSubmitComponent } from '../submission/submit/themed-sub path: '', pathMatch: 'full', component: ThemedSubmissionSubmitComponent, - data: { title: 'submission.submit.title' } + resolve: { + breadcrumb: I18nBreadcrumbResolver + }, + data: { title: 'submission.submit.title', breadcrumbKey: 'submission.submit' } } ]) ] diff --git a/src/app/+workflowitems-edit-page/workflowitems-edit-page-routing.module.ts b/src/app/+workflowitems-edit-page/workflowitems-edit-page-routing.module.ts index 2d104cf376..733eebecc2 100644 --- a/src/app/+workflowitems-edit-page/workflowitems-edit-page-routing.module.ts +++ b/src/app/+workflowitems-edit-page/workflowitems-edit-page-routing.module.ts @@ -3,10 +3,15 @@ import { RouterModule } from '@angular/router'; import { AuthenticatedGuard } from '../core/auth/authenticated.guard'; import { WorkflowItemPageResolver } from './workflow-item-page.resolver'; -import { WORKFLOW_ITEM_DELETE_PATH, WORKFLOW_ITEM_EDIT_PATH, WORKFLOW_ITEM_SEND_BACK_PATH } from './workflowitems-edit-page-routing-paths'; +import { + WORKFLOW_ITEM_DELETE_PATH, + WORKFLOW_ITEM_EDIT_PATH, + WORKFLOW_ITEM_SEND_BACK_PATH +} from './workflowitems-edit-page-routing-paths'; import { ThemedSubmissionEditComponent } from '../submission/edit/themed-submission-edit.component'; import { ThemedWorkflowItemDeleteComponent } from './workflow-item-delete/themed-workflow-item-delete.component'; import { ThemedWorkflowItemSendBackComponent } from './workflow-item-send-back/themed-workflow-item-send-back.component'; +import { I18nBreadcrumbResolver } from '../core/breadcrumbs/i18n-breadcrumb.resolver'; @NgModule({ imports: [ @@ -19,19 +24,28 @@ import { ThemedWorkflowItemSendBackComponent } from './workflow-item-send-back/t canActivate: [AuthenticatedGuard], path: WORKFLOW_ITEM_EDIT_PATH, component: ThemedSubmissionEditComponent, - data: { title: 'submission.edit.title' } + resolve: { + breadcrumb: I18nBreadcrumbResolver + }, + data: { title: 'workflow-item.edit.title', breadcrumbKey: 'workflow-item.edit' } }, { canActivate: [AuthenticatedGuard], path: WORKFLOW_ITEM_DELETE_PATH, component: ThemedWorkflowItemDeleteComponent, - data: { title: 'workflow-item.delete.title' } + resolve: { + breadcrumb: I18nBreadcrumbResolver + }, + data: { title: 'workflow-item.delete.title', breadcrumbKey: 'workflow-item.edit' } }, { canActivate: [AuthenticatedGuard], path: WORKFLOW_ITEM_SEND_BACK_PATH, component: ThemedWorkflowItemSendBackComponent, - data: { title: 'workflow-item.send-back.title' } + resolve: { + breadcrumb: I18nBreadcrumbResolver + }, + data: { title: 'workflow-item.send-back.title', breadcrumbKey: 'workflow-item.edit' } } ] }] diff --git a/src/app/+workspaceitems-edit-page/workspaceitems-edit-page-routing.module.ts b/src/app/+workspaceitems-edit-page/workspaceitems-edit-page-routing.module.ts index 791bb4f9aa..1a58417d0c 100644 --- a/src/app/+workspaceitems-edit-page/workspaceitems-edit-page-routing.module.ts +++ b/src/app/+workspaceitems-edit-page/workspaceitems-edit-page-routing.module.ts @@ -3,6 +3,7 @@ import { RouterModule } from '@angular/router'; import { AuthenticatedGuard } from '../core/auth/authenticated.guard'; import { ThemedSubmissionEditComponent } from '../submission/edit/themed-submission-edit.component'; +import { I18nBreadcrumbResolver } from '../core/breadcrumbs/i18n-breadcrumb.resolver'; @NgModule({ imports: [ @@ -12,7 +13,10 @@ import { ThemedSubmissionEditComponent } from '../submission/edit/themed-submiss canActivate: [AuthenticatedGuard], path: ':id/edit', component: ThemedSubmissionEditComponent, - data: { title: 'submission.edit.title' } + resolve: { + breadcrumb: I18nBreadcrumbResolver + }, + data: { title: 'submission.edit.title', breadcrumbKey: 'submission.edit' } } ]) ] diff --git a/src/app/access-control/access-control-routing.module.ts b/src/app/access-control/access-control-routing.module.ts index 2dbba19f70..cac49938a9 100644 --- a/src/app/access-control/access-control-routing.module.ts +++ b/src/app/access-control/access-control-routing.module.ts @@ -4,22 +4,43 @@ import { EPeopleRegistryComponent } from './epeople-registry/epeople-registry.co import { GroupFormComponent } from './group-registry/group-form/group-form.component'; import { GroupsRegistryComponent } from './group-registry/groups-registry.component'; import { GROUP_EDIT_PATH } from './access-control-routing-paths'; +import { I18nBreadcrumbResolver } from '../core/breadcrumbs/i18n-breadcrumb.resolver'; @NgModule({ imports: [ RouterModule.forChild([ - { path: 'epeople', component: EPeopleRegistryComponent, data: { title: 'admin.access-control.epeople.title' } }, - { path: GROUP_EDIT_PATH, component: GroupsRegistryComponent, data: { title: 'admin.access-control.groups.title' } }, { - path: `${GROUP_EDIT_PATH}/:groupId`, - component: GroupFormComponent, - data: {title: 'admin.access-control.groups.title.singleGroup'} + path: 'epeople', + component: EPeopleRegistryComponent, + resolve: { + breadcrumb: I18nBreadcrumbResolver + }, + data: { title: 'admin.access-control.epeople.title', breadcrumbKey: 'admin.access-control.epeople' } + }, + { + path: GROUP_EDIT_PATH, + component: GroupsRegistryComponent, + resolve: { + breadcrumb: I18nBreadcrumbResolver + }, + data: { title: 'admin.access-control.groups.title', breadcrumbKey: 'admin.access-control.groups' } }, { path: `${GROUP_EDIT_PATH}/newGroup`, component: GroupFormComponent, - data: {title: 'admin.access-control.groups.title.addGroup'} + resolve: { + breadcrumb: I18nBreadcrumbResolver + }, + data: { title: 'admin.access-control.groups.title.addGroup', breadcrumbKey: 'admin.access-control.groups.addGroup' } }, + { + path: `${GROUP_EDIT_PATH}/:groupId`, + component: GroupFormComponent, + resolve: { + breadcrumb: I18nBreadcrumbResolver + }, + data: { title: 'admin.access-control.groups.title.singleGroup', breadcrumbKey: 'admin.access-control.groups.singleGroup' } + } ]) ] }) diff --git a/src/app/access-control/epeople-registry/epeople-registry.component.html b/src/app/access-control/epeople-registry/epeople-registry.component.html index f478557e00..1a2e8e1e13 100644 --- a/src/app/access-control/epeople-registry/epeople-registry.component.html +++ b/src/app/access-control/epeople-registry/epeople-registry.component.html @@ -1,46 +1,53 @@
+
+ - - - - -
-
+
+
+ + +
-
-
+ +
-
+
+ class="form-control" attr.aria-label="{{labelPrefix + 'search.placeholder' | translate}}" + [placeholder]="(labelPrefix + 'search.placeholder' | translate)"> - - + +
+
+ +
+ = new BehaviorSubject(undefined); + /** + * A boolean representing if a search is pending + */ + searching$: BehaviorSubject = new BehaviorSubject(false); + /** * Pagination config used to display the list of epeople */ @@ -106,6 +111,7 @@ export class EPeopleRegistryComponent implements OnInit, OnDestroy { * This method will initialise the page */ initialisePage() { + this.searching$.next(true); this.isEPersonFormShown = false; this.search({ scope: this.currentSearchScope, query: this.currentSearchQuery }); this.subs.push(this.epersonService.getActiveEPerson().subscribe((eperson: EPerson) => { @@ -133,6 +139,7 @@ export class EPeopleRegistryComponent implements OnInit, OnDestroy { return [epeople]; } })).subscribe((value: PaginatedList) => { + this.searching$.next(false); this.ePeopleDto$.next(value); this.pageInfoState$.next(value.pageInfo); })); @@ -154,6 +161,7 @@ export class EPeopleRegistryComponent implements OnInit, OnDestroy { * @param data Contains scope and query param */ search(data: any) { + this.searching$.next(true); const query: string = data.query; const scope: string = data.scope; if (query != null && this.currentSearchQuery !== query) { @@ -228,6 +236,8 @@ export class EPeopleRegistryComponent implements OnInit, OnDestroy { modalRef.componentInstance.infoLabel = 'confirmation-modal.delete-eperson.info'; modalRef.componentInstance.cancelLabel = 'confirmation-modal.delete-eperson.cancel'; modalRef.componentInstance.confirmLabel = 'confirmation-modal.delete-eperson.confirm'; + modalRef.componentInstance.brandColor = 'danger'; + modalRef.componentInstance.confirmIcon = 'fas fa-trash'; modalRef.componentInstance.response.pipe(take(1)).subscribe((confirm: boolean) => { if (confirm) { if (hasValue(ePerson.id)) { diff --git a/src/app/access-control/epeople-registry/eperson-form/eperson-form.component.html b/src/app/access-control/epeople-registry/eperson-form/eperson-form.component.html index 3f744240e5..c613cfdcad 100644 --- a/src/app/access-control/epeople-registry/eperson-form/eperson-form.component.html +++ b/src/app/access-control/epeople-registry/eperson-form/eperson-form.component.html @@ -12,19 +12,27 @@ [formModel]="formModel" [formGroup]="formGroup" [formLayout]="formLayout" - (cancel)="onCancel()" + [displayCancel]="false" (submitForm)="onSubmit()"> - - - - +
+
+ +
+
+ + +
+ diff --git a/src/app/access-control/epeople-registry/eperson-form/eperson-form.component.ts b/src/app/access-control/epeople-registry/eperson-form/eperson-form.component.ts index ecb4606ae4..285cbbefa6 100644 --- a/src/app/access-control/epeople-registry/eperson-form/eperson-form.component.ts +++ b/src/app/access-control/epeople-registry/eperson-form/eperson-form.component.ts @@ -436,6 +436,8 @@ export class EPersonFormComponent implements OnInit, OnDestroy { modalRef.componentInstance.infoLabel = 'confirmation-modal.delete-eperson.info'; modalRef.componentInstance.cancelLabel = 'confirmation-modal.delete-eperson.cancel'; modalRef.componentInstance.confirmLabel = 'confirmation-modal.delete-eperson.confirm'; + modalRef.componentInstance.brandColor = 'danger'; + modalRef.componentInstance.confirmIcon = 'fas fa-trash'; modalRef.componentInstance.response.pipe(take(1)).subscribe((confirm: boolean) => { if (confirm) { if (hasValue(eperson.id)) { diff --git a/src/app/access-control/group-registry/group-form/group-form.component.html b/src/app/access-control/group-registry/group-form/group-form.component.html index a0d8a45255..0fc5a574b7 100644 --- a/src/app/access-control/group-registry/group-form/group-form.component.html +++ b/src/app/access-control/group-registry/group-form/group-form.component.html @@ -1,11 +1,6 @@
- - -
@@ -17,29 +12,38 @@

{{messagePrefix + '.head.edit' | translate}}

+ + + + -
- +
+
+
- +
+ +
-
- -
+
diff --git a/src/app/access-control/group-registry/group-form/group-form.component.ts b/src/app/access-control/group-registry/group-form/group-form.component.ts index 2b834bde1d..9b74d26fe8 100644 --- a/src/app/access-control/group-registry/group-form/group-form.component.ts +++ b/src/app/access-control/group-registry/group-form/group-form.component.ts @@ -368,6 +368,8 @@ export class GroupFormComponent implements OnInit, OnDestroy { modalRef.componentInstance.infoLabel = this.messagePrefix + '.delete-group.modal.info'; modalRef.componentInstance.cancelLabel = this.messagePrefix + '.delete-group.modal.cancel'; modalRef.componentInstance.confirmLabel = this.messagePrefix + '.delete-group.modal.confirm'; + modalRef.componentInstance.brandColor = 'danger'; + modalRef.componentInstance.confirmIcon = 'fas fa-trash'; modalRef.componentInstance.response.pipe(take(1)).subscribe((confirm: boolean) => { if (confirm) { if (hasValue(group.id)) { diff --git a/src/app/access-control/group-registry/group-form/members-list/members-list.component.html b/src/app/access-control/group-registry/group-form/members-list/members-list.component.html index 8e2d23f8d5..f54936148c 100644 --- a/src/app/access-control/group-registry/group-form/members-list/members-list.component.html +++ b/src/app/access-control/group-registry/group-form/members-list/members-list.component.html @@ -2,26 +2,29 @@

{{messagePrefix + '.head' | translate}}

-
-
+ +
-
+
- +
+
+ +
{{messagePrefix + '.head' | translate}} -
-
-
+ +
+
- + +
+
+ +
- - - -
- +
+ +
+ +
- -
-
+ + +
+ class="form-control" attr.aria-label="{{messagePrefix + 'search.placeholder' | translate}}" + [placeholder]="(messagePrefix + 'search.placeholder' | translate)" > - - + +
+
+ +
+ -
+
diff --git a/src/app/access-control/group-registry/groups-registry.component.ts b/src/app/access-control/group-registry/groups-registry.component.ts index bfe6d50c43..19dcc3c552 100644 --- a/src/app/access-control/group-registry/groups-registry.component.ts +++ b/src/app/access-control/group-registry/groups-registry.component.ts @@ -70,6 +70,11 @@ export class GroupsRegistryComponent implements OnInit, OnDestroy { // The search form searchForm; + /** + * A boolean representing if a search is pending + */ + searching$: BehaviorSubject = new BehaviorSubject(false); + // Current search in groups registry currentSearchQuery: string; @@ -117,6 +122,7 @@ export class GroupsRegistryComponent implements OnInit, OnDestroy { * @param data Contains query param */ search(data: any) { + this.searching$.next(true); const query: string = data.query; if (query != null && this.currentSearchQuery !== query) { this.router.navigateByUrl(this.groupService.getGroupRegistryRouterLink()); @@ -163,6 +169,7 @@ export class GroupsRegistryComponent implements OnInit, OnDestroy { })).subscribe((value: PaginatedList) => { this.groupsDto$.next(value); this.pageInfoState$.next(value.pageInfo); + this.searching$.next(false); }); this.subs.push(this.searchSub); } diff --git a/src/app/app.module.ts b/src/app/app.module.ts index 5bfa593ef1..03cd819625 100755 --- a/src/app/app.module.ts +++ b/src/app/app.module.ts @@ -15,14 +15,11 @@ import { AdminSidebarSectionComponent } from './+admin/admin-sidebar/admin-sideb import { AdminSidebarComponent } from './+admin/admin-sidebar/admin-sidebar.component'; import { ExpandableAdminSidebarSectionComponent } from './+admin/admin-sidebar/expandable-admin-sidebar-section/expandable-admin-sidebar-section.component'; import { AppRoutingModule } from './app-routing.module'; - import { AppComponent } from './app.component'; - import { appEffects } from './app.effects'; import { appMetaReducers, debugMetaReducers } from './app.metareducers'; import { appReducers, AppState, storeModuleConfig } from './app.reducer'; import { CheckAuthenticationTokenAction } from './core/auth/auth.actions'; - import { CoreModule } from './core/core.module'; import { ClientCookieService } from './core/services/client-cookie.service'; import { FooterComponent } from './footer/footer.component'; @@ -30,8 +27,6 @@ import { HeaderNavbarWrapperComponent } from './header-nav-wrapper/header-navbar import { HeaderComponent } from './header/header.component'; import { NavbarModule } from './navbar/navbar.module'; import { PageNotFoundComponent } from './pagenotfound/pagenotfound.component'; -import { SearchNavbarComponent } from './search-navbar/search-navbar.component'; - import { DSpaceRouterStateSerializer } from './shared/ngrx/dspace-router-state-serializer'; import { NotificationComponent } from './shared/notifications/notification/notification.component'; import { NotificationsBoardComponent } from './shared/notifications/notifications-board/notifications-board.component'; @@ -143,7 +138,6 @@ const DECLARATIONS = [ ThemedPageNotFoundComponent, NotificationComponent, NotificationsBoardComponent, - SearchNavbarComponent, BreadcrumbsComponent, ThemedBreadcrumbsComponent, ForbiddenComponent, diff --git a/src/app/breadcrumbs/breadcrumbs.component.html b/src/app/breadcrumbs/breadcrumbs.component.html index a6072ed58a..beb5039178 100644 --- a/src/app/breadcrumbs/breadcrumbs.component.html +++ b/src/app/breadcrumbs/breadcrumbs.component.html @@ -1,6 +1,6 @@ - + + diff --git a/src/app/header/header.component.scss b/src/app/header/header.component.scss index 0263a566cc..c85daf8516 100644 --- a/src/app/header/header.component.scss +++ b/src/app/header/header.component.scss @@ -1,21 +1,19 @@ +@media screen and (min-width: map-get($grid-breakpoints, md)) { + nav.navbar { + display: none; + } + .header { + background-color: var(--ds-header-bg); + } +} + .navbar-brand img { - height: var(--ds-header-logo-height); - @media screen and (max-width: map-get($grid-breakpoints, sm)) { + @media screen and (max-width: map-get($grid-breakpoints, md)) { height: var(--ds-header-logo-height-xs); } } .navbar-toggler .navbar-toggler-icon { background-image: none !important; line-height: 1.5; + color: var(--bs-link-color); } - -.navbar ::ng-deep { - a { - color: var(--ds-header-icon-color); - - &:hover, &focus { - color: var(--ds-header-icon-color-hover); - } - } -} - diff --git a/src/app/navbar/expandable-navbar-section/expandable-navbar-section.component.html b/src/app/navbar/expandable-navbar-section/expandable-navbar-section.component.html index a7cf7c1856..a1c02bfa31 100644 --- a/src/app/navbar/expandable-navbar-section/expandable-navbar-section.component.html +++ b/src/app/navbar/expandable-navbar-section/expandable-navbar-section.component.html @@ -1,4 +1,4 @@ - diff --git a/src/app/navbar/navbar.component.html b/src/app/navbar/navbar.component.html index 2356077e43..50e526b78b 100644 --- a/src/app/navbar/navbar.component.html +++ b/src/app/navbar/navbar.component.html @@ -1,17 +1,24 @@ diff --git a/src/app/navbar/navbar.component.scss b/src/app/navbar/navbar.component.scss index cca6284b72..be6e8ac55e 100644 --- a/src/app/navbar/navbar.component.scss +++ b/src/app/navbar/navbar.component.scss @@ -1,6 +1,8 @@ nav.navbar { - border-bottom: 1px var(--bs-gray-400) solid; + border-top: 1px var(--ds-header-navbar-border-top-color) solid; + border-bottom: 1px var(--ds-header-navbar-border-bottom-color) solid; align-items: baseline; + color: var(--ds-header-icon-color); } /** Mobile menu styling **/ @@ -29,7 +31,27 @@ nav.navbar { @media screen and (max-width: map-get($grid-breakpoints, md)) { > .container { padding: 0 var(--bs-spacer); + a.navbar-brand { + display: none; + } + .navbar-collapsed { + display: none; + } } padding: 0; } + height: 80px; +} + +a.navbar-brand img { + max-height: var(--ds-header-logo-height); +} + +.navbar-nav { + ::ng-deep a.nav-link { + color: var(--ds-navbar-link-color); + } + ::ng-deep a.nav-link:hover { + color: var(--ds-navbar-link-color-hover); + } } diff --git a/src/app/navbar/navbar.component.ts b/src/app/navbar/navbar.component.ts index 1a306ea932..ae5fb262ae 100644 --- a/src/app/navbar/navbar.component.ts +++ b/src/app/navbar/navbar.component.ts @@ -41,6 +41,17 @@ export class NavbarComponent extends MenuComponent { */ createMenu() { const menuList: any[] = [ + /* Communities & Collections tree */ + { + id: `browse_global_communities_and_collections`, + active: false, + visible: true, + model: { + type: MenuItemType.LINK, + text: `menu.section.browse_global_communities_and_collections`, + link: `/community-list` + } as LinkMenuItemModel + }, /* News */ { id: 'browse_global', @@ -52,18 +63,6 @@ export class NavbarComponent extends MenuComponent { } as TextMenuItemModel, index: 0 }, - /* Communities & Collections tree */ - { - id: `browse_global_communities_and_collections`, - parentID: 'browse_global', - active: false, - visible: true, - model: { - type: MenuItemType.LINK, - text: `menu.section.browse_global_communities_and_collections`, - link: `/community-list` - } as LinkMenuItemModel - }, ]; // Read the different Browse-By types from config and add them to the browse menu const types = environment.browseBy.types; diff --git a/src/app/navbar/navbar.module.ts b/src/app/navbar/navbar.module.ts index 5299c6cfc3..6591cd3453 100644 --- a/src/app/navbar/navbar.module.ts +++ b/src/app/navbar/navbar.module.ts @@ -9,6 +9,7 @@ import { NavbarSectionComponent } from './navbar-section/navbar-section.componen import { ExpandableNavbarSectionComponent } from './expandable-navbar-section/expandable-navbar-section.component'; import { NavbarComponent } from './navbar.component'; import { MenuModule } from '../shared/menu/menu.module'; +import { SharedModule } from '../shared/shared.module'; import { FormsModule } from '@angular/forms'; import { ThemedNavbarComponent } from './themed-navbar.component'; @@ -25,6 +26,7 @@ const ENTRY_COMPONENTS = [ @NgModule({ imports: [ CommonModule, + SharedModule, MenuModule, FormsModule, EffectsModule.forFeature(effects), diff --git a/src/app/profile-page/profile-page-metadata-form/profile-page-metadata-form.component.html b/src/app/profile-page/profile-page-metadata-form/profile-page-metadata-form.component.html index c1c1cff0f3..b9142fa2c6 100644 --- a/src/app/profile-page/profile-page-metadata-form/profile-page-metadata-form.component.html +++ b/src/app/profile-page/profile-page-metadata-form/profile-page-metadata-form.component.html @@ -2,5 +2,6 @@ [formId]="'profile-page-metadata-form-id'" [formModel]="formModel" [formGroup]="formGroup" - [displaySubmit]="false"> + [displaySubmit]="false" + [displayCancel]="false"> diff --git a/src/app/profile-page/profile-page-security-form/profile-page-security-form.component.html b/src/app/profile-page/profile-page-security-form/profile-page-security-form.component.html index ad9f768297..cdaa3ce31c 100644 --- a/src/app/profile-page/profile-page-security-form/profile-page-security-form.component.html +++ b/src/app/profile-page/profile-page-security-form/profile-page-security-form.component.html @@ -3,7 +3,8 @@ [formId]="FORM_PREFIX" [formModel]="formModel" [formGroup]="formGroup" - [displaySubmit]="false"> + [displaySubmit]="false" + [displayCancel]="false">
{{FORM_PREFIX + 'error.password-length' | translate}}
{{FORM_PREFIX + 'error.matching-passwords' | translate}}
diff --git a/src/app/profile-page/profile-page.component.html b/src/app/profile-page/profile-page.component.html index ab8f1ce026..619e4a2411 100644 --- a/src/app/profile-page/profile-page.component.html +++ b/src/app/profile-page/profile-page.component.html @@ -17,7 +17,9 @@ > - +
+ +
diff --git a/src/app/root/root.component.html b/src/app/root/root.component.html index af59e0d2ad..aef07d79f4 100644 --- a/src/app/root/root.component.html +++ b/src/app/root/root.component.html @@ -10,14 +10,14 @@ [options]="notificationOptions">
-
- -
+ -
- +
+ +
+
+
-
diff --git a/src/app/search-navbar/search-navbar.component.html b/src/app/search-navbar/search-navbar.component.html index 13d792c80f..3ce1215a0c 100644 --- a/src/app/search-navbar/search-navbar.component.html +++ b/src/app/search-navbar/search-navbar.component.html @@ -4,7 +4,7 @@ - + diff --git a/src/app/search-navbar/search-navbar.component.scss b/src/app/search-navbar/search-navbar.component.scss index dfebd2c94d..34a9257af9 100644 --- a/src/app/search-navbar/search-navbar.component.scss +++ b/src/app/search-navbar/search-navbar.component.scss @@ -12,14 +12,18 @@ input[type="text"] { a.submit-icon { cursor: pointer; + position: sticky; + top: 0; } - - -@media screen and (max-width: map-get($grid-breakpoints, sm)) { +@media screen and (max-width: map-get($grid-breakpoints, md)) { #query:focus { max-width: 250px !important; width: 40vw !important; } + + a.submit-icon { + color: var(--bs-link-color); + } } diff --git a/src/app/shared/auth-nav-menu/auth-nav-menu.component.html b/src/app/shared/auth-nav-menu/auth-nav-menu.component.html index fa92939e0f..59fd1ccb01 100644 --- a/src/app/shared/auth-nav-menu/auth-nav-menu.component.html +++ b/src/app/shared/auth-nav-menu/auth-nav-menu.component.html @@ -12,22 +12,24 @@
diff --git a/src/app/shared/auth-nav-menu/auth-nav-menu.component.scss b/src/app/shared/auth-nav-menu/auth-nav-menu.component.scss index 7b7e7af12f..11baa4b116 100644 --- a/src/app/shared/auth-nav-menu/auth-nav-menu.component.scss +++ b/src/app/shared/auth-nav-menu/auth-nav-menu.component.scss @@ -11,3 +11,11 @@ .dropdown-item:hover, .dropdown-item:focus { background-color: transparent !important; } + +.dropdown-toggle { + color: var(--ds-header-icon-color) !important; + + &:hover, &focus { + color: var(--ds-header-icon-color-hover); + } +} diff --git a/src/app/shared/browse-by/browse-by.component.html b/src/app/shared/browse-by/browse-by.component.html index 09d3cd3d60..c133324681 100644 --- a/src/app/shared/browse-by/browse-by.component.html +++ b/src/app/shared/browse-by/browse-by.component.html @@ -13,7 +13,7 @@
- +
@@ -29,8 +29,8 @@
- - + +
diff --git a/src/app/shared/chips/chips.component.html b/src/app/shared/chips/chips.component.html index 74006c80ca..b9cad31761 100644 --- a/src/app/shared/chips/chips.component.html +++ b/src/app/shared/chips/chips.component.html @@ -15,7 +15,7 @@ (dragend)="onDragEnd(i)" (mouseover)="showTooltip(t, i)" (mouseout)="t.close()"> - @@ -42,7 +42,8 @@ - - +
+ +
diff --git a/src/app/shared/chips/chips.component.scss b/src/app/shared/chips/chips.component.scss index a79deb0f2f..a894448730 100644 --- a/src/app/shared/chips/chips.component.scss +++ b/src/app/shared/chips/chips.component.scss @@ -1,5 +1,5 @@ .chip-selected { - background-color: var(--bs-info) !important; + background-color: var(--bs-secondary) !important; } .chip-label { diff --git a/src/app/shared/chips/chips.component.ts b/src/app/shared/chips/chips.component.ts index 9c836a6d58..1dc7641c25 100644 --- a/src/app/shared/chips/chips.component.ts +++ b/src/app/shared/chips/chips.component.ts @@ -8,6 +8,7 @@ import { ChipsItem } from './models/chips-item.model'; import { UploaderService } from '../uploader/uploader.service'; import { TranslateService } from '@ngx-translate/core'; import { Options } from 'sortablejs'; +import { BehaviorSubject } from 'rxjs/internal/BehaviorSubject'; @Component({ selector: 'ds-chips', @@ -25,6 +26,7 @@ export class ChipsComponent implements OnChanges { @Output() remove: EventEmitter = new EventEmitter(); @Output() change: EventEmitter = new EventEmitter(); + isDragging: BehaviorSubject = new BehaviorSubject(false); options: Options; dragged = -1; tipText: string[]; @@ -73,6 +75,7 @@ export class ChipsComponent implements OnChanges { } onDragStart(index) { + this.isDragging.next(true); this.uploaderService.overrideDragOverPage(); this.dragged = index; } @@ -81,6 +84,7 @@ export class ChipsComponent implements OnChanges { this.uploaderService.allowDragOverPage(); this.dragged = -1; this.chips.updateOrder(); + this.isDragging.next(false); } showTooltip(tooltip: NgbTooltip, index, field?) { diff --git a/src/app/shared/comcol-forms/comcol-form/comcol-form.component.html b/src/app/shared/comcol-forms/comcol-form/comcol-form.component.html index 6d0a0f90be..5d7b092f74 100644 --- a/src/app/shared/comcol-forms/comcol-form/comcol-form.component.html +++ b/src/app/shared/comcol-forms/comcol-form/comcol-form.component.html @@ -11,10 +11,14 @@
- -
@@ -35,4 +39,10 @@
+ [formModel]="formModel" + [displayCancel]="false" + (submitForm)="onSubmit()"> + + diff --git a/src/app/shared/comcol-forms/comcol-form/comcol-form.component.spec.ts b/src/app/shared/comcol-forms/comcol-form/comcol-form.component.spec.ts index 4ee2c1c1b1..c7c6e2e5e7 100644 --- a/src/app/shared/comcol-forms/comcol-form/comcol-form.component.spec.ts +++ b/src/app/shared/comcol-forms/comcol-form/comcol-form.component.spec.ts @@ -153,13 +153,6 @@ describe('ComColFormComponent', () => { }); }); - describe('onCancel', () => { - it('should call the back method on the Location service', () => { - comp.onCancel(); - expect(locationStub.back).toHaveBeenCalled(); - }); - }); - describe('onCompleteItem', () => { beforeEach(() => { spyOn(comp.finish, 'emit'); diff --git a/src/app/shared/comcol-forms/comcol-form/comcol-form.component.ts b/src/app/shared/comcol-forms/comcol-form/comcol-form.component.ts index c60879f84d..ef7a5e55e8 100644 --- a/src/app/shared/comcol-forms/comcol-form/comcol-form.component.ts +++ b/src/app/shared/comcol-forms/comcol-form/comcol-form.component.ts @@ -1,4 +1,3 @@ -import { Location } from '@angular/common'; import { Component, EventEmitter, @@ -99,6 +98,11 @@ export class ComColFormComponent implements On operations: Operation[], }> = new EventEmitter(); + /** + * Event emitted on back + */ + @Output() back: EventEmitter = new EventEmitter(); + /** * Fires an event when the logo has finished uploading (with or without errors) or was removed */ @@ -126,8 +130,7 @@ export class ComColFormComponent implements On */ protected dsoService: ComColDataService; - public constructor(protected location: Location, - protected formService: DynamicFormService, + public constructor(protected formService: DynamicFormService, protected translate: TranslateService, protected notificationsService: NotificationsService, protected authService: AuthService, @@ -300,13 +303,6 @@ export class ComColFormComponent implements On this.finish.emit(); } - /** - * Cancel the form and return to the previous page - */ - onCancel() { - this.location.back(); - } - /** * Unsubscribe from open subscriptions */ diff --git a/src/app/shared/comcol-forms/create-comcol-page/create-comcol-page.component.ts b/src/app/shared/comcol-forms/create-comcol-page/create-comcol-page.component.ts index 92c0c47728..b1be5ae9be 100644 --- a/src/app/shared/comcol-forms/create-comcol-page/create-comcol-page.component.ts +++ b/src/app/shared/comcol-forms/create-comcol-page/create-comcol-page.component.ts @@ -103,6 +103,13 @@ export class CreateComColPageComponent i }); } + /** + * Navigate to home page + */ + navigateToHome() { + this.router.navigate(['/home']); + } + /** * Navigate to the page of the newly created object */ diff --git a/src/app/shared/comcol-forms/edit-comcol-page/comcol-role/comcol-role.component.html b/src/app/shared/comcol-forms/edit-comcol-page/comcol-role/comcol-role.component.html index 9bfb12a381..b0a319b4ff 100644 --- a/src/app/shared/comcol-forms/edit-comcol-page/comcol-role/comcol-role.component.html +++ b/src/app/shared/comcol-forms/edit-comcol-page/comcol-role/comcol-role.component.html @@ -3,13 +3,16 @@
-
+
+ {{'comcol-role.edit.' + (comcolRole$ | async)?.name + '.name' | translate}} +
-
- {{'comcol-role.edit.' + (comcolRole$ | async)?.name + '.name' | translate}} -
+
+ {{'comcol-role.edit.' + (comcolRole$ | async)?.name + '.description' | translate}} +
-
+
+
{{'comcol-role.edit.no-group' | translate}} @@ -23,29 +26,26 @@
-
-
+
- -
+
+ {{'comcol-role.edit.delete' | translate}} +
-
- {{'comcol-role.edit.' + (comcolRole$ | async)?.name + '.description' | translate}} -
diff --git a/src/app/shared/comcol-forms/edit-comcol-page/comcol-role/comcol-role.component.spec.ts b/src/app/shared/comcol-forms/edit-comcol-page/comcol-role/comcol-role.component.spec.ts index eb7d9e637f..cc5b64b9b5 100644 --- a/src/app/shared/comcol-forms/edit-comcol-page/comcol-role/comcol-role.component.spec.ts +++ b/src/app/shared/comcol-forms/edit-comcol-page/comcol-role/comcol-role.component.spec.ts @@ -9,6 +9,7 @@ import { RequestService } from '../../../../core/data/request.service'; import { of as observableOf } from 'rxjs'; import { RouterTestingModule } from '@angular/router/testing'; import { createFailedRemoteDataObject$, createSuccessfulRemoteDataObject$ } from '../../../remote-data.utils'; +import { NoopAnimationsModule } from '@angular/platform-browser/animations'; describe('ComcolRoleComponent', () => { @@ -34,6 +35,7 @@ describe('ComcolRoleComponent', () => { SharedModule, RouterTestingModule.withRoutes([]), TranslateModule.forRoot(), + NoopAnimationsModule ], providers: [ { provide: GroupDataService, useValue: groupService }, diff --git a/src/app/shared/comcol-forms/edit-comcol-page/comcol-role/comcol-role.component.ts b/src/app/shared/comcol-forms/edit-comcol-page/comcol-role/comcol-role.component.ts index d155d66a0a..4eb364a3cc 100644 --- a/src/app/shared/comcol-forms/edit-comcol-page/comcol-role/comcol-role.component.ts +++ b/src/app/shared/comcol-forms/edit-comcol-page/comcol-role/comcol-role.component.ts @@ -96,6 +96,7 @@ export class ComcolRoleComponent implements OnInit { this.groupService.createComcolGroup(this.dso, this.comcolRole.name, this.groupLink).pipe( getFirstCompletedRemoteData() ).subscribe((rd: RemoteData) => { + if (rd.hasSucceeded) { this.groupService.clearGroupsRequests(); this.requestService.setStaleByHrefSubstring(this.comcolRole.href); diff --git a/src/app/shared/comcol-forms/edit-comcol-page/edit-comcol-page.component.html b/src/app/shared/comcol-forms/edit-comcol-page/edit-comcol-page.component.html index ad270aab80..819d080f89 100644 --- a/src/app/shared/comcol-forms/edit-comcol-page/edit-comcol-page.component.html +++ b/src/app/shared/comcol-forms/edit-comcol-page/edit-comcol-page.component.html @@ -1,7 +1,14 @@
-

{{ type + '.edit.head' | translate }}

+
+

{{ type + '.edit.head' | translate }}

+ +
diff --git a/src/app/shared/comcol-forms/edit-comcol-page/edit-comcol-page.component.ts b/src/app/shared/comcol-forms/edit-comcol-page/edit-comcol-page.component.ts index 2fa05fa28b..793065096f 100644 --- a/src/app/shared/comcol-forms/edit-comcol-page/edit-comcol-page.component.ts +++ b/src/app/shared/comcol-forms/edit-comcol-page/edit-comcol-page.component.ts @@ -1,9 +1,11 @@ import { Component, OnInit } from '@angular/core'; + import { Observable } from 'rxjs'; +import { first, map } from 'rxjs/operators'; + import { ActivatedRoute, Router } from '@angular/router'; import { RemoteData } from '../../../core/data/remote-data'; import { isNotEmpty } from '../../empty.util'; -import { first, map } from 'rxjs/operators'; import { DSpaceObject } from '../../../core/shared/dspace-object.model'; /** @@ -43,14 +45,11 @@ export class EditComColPageComponent implements On protected router: Router, protected route: ActivatedRoute ) { - this.router.events.subscribe(() => { - this.currentPage = this.route.snapshot.firstChild.routeConfig.path; - this.hideReturnButton = this.route.routeConfig.children - .find((child: any) => child.path === this.currentPage).data.hideReturnButton; - }); + this.router.events.subscribe(() => this.initPageParamsByRoute()); } ngOnInit(): void { + this.initPageParamsByRoute(); this.pages = this.route.routeConfig.children .map((child: any) => child.path) .filter((path: string) => isNotEmpty(path)); // ignore reroutes @@ -65,4 +64,13 @@ export class EditComColPageComponent implements On getPageUrl(dso: TDomain): string { return this.router.url; } + + /** + * Set page params depending on the route + */ + initPageParamsByRoute() { + this.currentPage = this.route.snapshot.firstChild.routeConfig.path; + this.hideReturnButton = this.route.routeConfig.children + .find((child: any) => child.path === this.currentPage).data.hideReturnButton; + } } diff --git a/src/app/shared/confirmation-modal/confirmation-modal.component.html b/src/app/shared/confirmation-modal/confirmation-modal.component.html index bb67213ed3..82c70b662b 100644 --- a/src/app/shared/confirmation-modal/confirmation-modal.component.html +++ b/src/app/shared/confirmation-modal/confirmation-modal.component.html @@ -6,11 +6,13 @@
+
diff --git a/src/app/shared/confirmation-modal/confirmation-modal.component.ts b/src/app/shared/confirmation-modal/confirmation-modal.component.ts index c4e185a511..c18025427a 100644 --- a/src/app/shared/confirmation-modal/confirmation-modal.component.ts +++ b/src/app/shared/confirmation-modal/confirmation-modal.component.ts @@ -12,6 +12,12 @@ export class ConfirmationModalComponent { @Input() infoLabel: string; @Input() cancelLabel: string; @Input() confirmLabel: string; + @Input() confirmIcon: string; + /** + * The brand color of the confirm button + */ + @Input() brandColor = 'primary'; + @Input() dso: DSpaceObject; /** diff --git a/src/app/shared/dso-page/dso-page-edit-button/dso-page-edit-button.component.html b/src/app/shared/dso-page/dso-page-edit-button/dso-page-edit-button.component.html index d845f852c8..d680c140d8 100644 --- a/src/app/shared/dso-page/dso-page-edit-button/dso-page-edit-button.component.html +++ b/src/app/shared/dso-page/dso-page-edit-button/dso-page-edit-button.component.html @@ -1,6 +1,7 @@ + class="edit-button btn btn-dark btn-sm" + [ngbTooltip]="tooltipMsg | translate" + role="button" [title]="tooltipMsg |translate" [attr.aria-label]="tooltipMsg |translate"> diff --git a/src/app/shared/dso-selector/modal-wrappers/export-metadata-selector/export-metadata-selector.component.ts b/src/app/shared/dso-selector/modal-wrappers/export-metadata-selector/export-metadata-selector.component.ts index 4b315617ac..24aa1704c6 100644 --- a/src/app/shared/dso-selector/modal-wrappers/export-metadata-selector/export-metadata-selector.component.ts +++ b/src/app/shared/dso-selector/modal-wrappers/export-metadata-selector/export-metadata-selector.component.ts @@ -53,6 +53,7 @@ export class ExportMetadataSelectorComponent extends DSOSelectorModalWrapperComp modalRef.componentInstance.infoLabel = 'confirmation-modal.export-metadata.info'; modalRef.componentInstance.cancelLabel = 'confirmation-modal.export-metadata.cancel'; modalRef.componentInstance.confirmLabel = 'confirmation-modal.export-metadata.confirm'; + modalRef.componentInstance.confirmIcon = 'fas fa-file-export'; const resp$ = modalRef.componentInstance.response.pipe(switchMap((confirm: boolean) => { if (confirm) { const startScriptSucceeded$ = this.startScriptNotifyAndRedirect(dso, dso.handle); diff --git a/src/app/shared/form/builder/ds-dynamic-form-ui/models/relation-group/dynamic-relation-group.component.html b/src/app/shared/form/builder/ds-dynamic-form-ui/models/relation-group/dynamic-relation-group.component.html index f584a75611..84bc0f4ffe 100644 --- a/src/app/shared/form/builder/ds-dynamic-form-ui/models/relation-group/dynamic-relation-group.component.html +++ b/src/app/shared/form/builder/ds-dynamic-form-ui/models/relation-group/dynamic-relation-group.component.html @@ -22,6 +22,7 @@ [formId]="formId" [formModel]="formModel" [displaySubmit]="false" + [displayCancel]="false" [emitChange]="false" (dfBlur)="onBlur($event)" (dfFocus)="onFocus($event)"> diff --git a/src/app/shared/form/builder/ds-dynamic-form-ui/models/tag/dynamic-tag.component.html b/src/app/shared/form/builder/ds-dynamic-form-ui/models/tag/dynamic-tag.component.html index c0c5c3f424..4bc85c5656 100644 --- a/src/app/shared/form/builder/ds-dynamic-form-ui/models/tag/dynamic-tag.component.html +++ b/src/app/shared/form/builder/ds-dynamic-form-ui/models/tag/dynamic-tag.component.html @@ -9,7 +9,7 @@ [wrapperClass]="'border-bottom border-light'">
- + +

{{ 'submission.sections.describe.relationship-lookup.selection-tab.title.' + externalSource.id | translate}}

diff --git a/src/app/shared/form/builder/ds-dynamic-form-ui/relation-lookup-modal/search-tab/dynamic-lookup-relation-search-tab.component.html b/src/app/shared/form/builder/ds-dynamic-form-ui/relation-lookup-modal/search-tab/dynamic-lookup-relation-search-tab.component.html index a1b1561e36..9cd856c013 100644 --- a/src/app/shared/form/builder/ds-dynamic-form-ui/relation-lookup-modal/search-tab/dynamic-lookup-relation-search-tab.component.html +++ b/src/app/shared/form/builder/ds-dynamic-form-ui/relation-lookup-modal/search-tab/dynamic-lookup-relation-search-tab.component.html @@ -3,7 +3,10 @@ [resultCount]="(resultsRD$ | async)?.payload?.totalElements" [inPlaceSearch]="true" [showViewModes]="false">
- + + diff --git a/src/app/shared/form/form.component.html b/src/app/shared/form/form.component.html index 10ec8da3b9..39ccda360f 100644 --- a/src/app/shared/form/form.component.html +++ b/src/app/shared/form/form.component.html @@ -49,16 +49,21 @@ - + -
+

- - + + +
diff --git a/src/app/shared/form/form.component.spec.ts b/src/app/shared/form/form.component.spec.ts index 4dd733a554..2f3be3fded 100644 --- a/src/app/shared/form/form.component.spec.ts +++ b/src/app/shared/form/form.component.spec.ts @@ -170,7 +170,8 @@ describe('FormComponent test suite', () => { `; + [displaySubmit]="displaySubmit" + [displayCancel]="displayCancel">`; testFixture = createTestComponent(html, TestComponent) as ComponentFixture; testComp = testFixture.componentInstance; @@ -197,6 +198,7 @@ describe('FormComponent test suite', () => { formComp.formId = 'testForm'; formComp.formModel = TEST_FORM_MODEL; formComp.displaySubmit = false; + formComp.displayCancel = false; form = new BehaviorSubject(formState); valid = new BehaviorSubject(false); spyOn((formComp as any).formService, 'getForm').and.returnValue(form); @@ -388,6 +390,7 @@ describe('FormComponent test suite', () => { formComp.formId = 'testFormArray'; formComp.formModel = TEST_FORM_MODEL_WITH_ARRAY; formComp.displaySubmit = false; + formComp.displayCancel = false; formFixture.detectChanges(); spyOn(store, 'dispatch'); }); @@ -443,6 +446,7 @@ class TestComponent { public formId; public formModel: DynamicFormControlModel[]; public displaySubmit = false; + public displayCancel = false; constructor() { this.formId = 'testForm'; diff --git a/src/app/shared/form/form.component.ts b/src/app/shared/form/form.component.ts index 8d7a87c03c..42469ddba2 100644 --- a/src/app/shared/form/form.component.ts +++ b/src/app/shared/form/form.component.ts @@ -34,10 +34,15 @@ export class FormComponent implements OnDestroy, OnInit { private formValid: boolean; /** - * A boolean that indicate if to display form's submit and cancel buttons + * A boolean that indicate if to display form's submit button */ @Input() displaySubmit = true; + /** + * A boolean that indicate if to display form's cancel button + */ + @Input() displayCancel = true; + /** * A boolean that indicate if to emit a form change event */ diff --git a/src/app/shared/lang-switch/lang-switch.component.html b/src/app/shared/lang-switch/lang-switch.component.html index b61ec5592e..b60a107a0b 100644 --- a/src/app/shared/lang-switch/lang-switch.component.html +++ b/src/app/shared/lang-switch/lang-switch.component.html @@ -1,6 +1,6 @@ - diff --git a/src/app/shared/notifications/notification/notification.component.html b/src/app/shared/notifications/notification/notification.component.html index c5afdd5758..e8b3d37b5f 100644 --- a/src/app/shared/notifications/notification/notification.component.html +++ b/src/app/shared/notifications/notification/notification.component.html @@ -16,10 +16,10 @@
diff --git a/src/app/shared/object-select/collection-select/collection-select.component.html b/src/app/shared/object-select/collection-select/collection-select.component.html index c8a0c4b879..27ebcd9643 100644 --- a/src/app/shared/object-select/collection-select/collection-select.component.html +++ b/src/app/shared/object-select/collection-select/collection-select.component.html @@ -30,12 +30,12 @@
- +
diff --git a/src/app/shared/pagination/pagination.component.html b/src/app/shared/pagination/pagination.component.html index 649fe686ff..6c67b58a90 100644 --- a/src/app/shared/pagination/pagination.component.html +++ b/src/app/shared/pagination/pagination.component.html @@ -7,7 +7,7 @@
- +
diff --git a/src/app/shared/resource-policies/form/eperson-group-list/eperson-search-box/eperson-search-box.component.html b/src/app/shared/resource-policies/form/eperson-group-list/eperson-search-box/eperson-search-box.component.html index 0d130c723c..fb330a536a 100644 --- a/src/app/shared/resource-policies/form/eperson-group-list/eperson-search-box/eperson-search-box.component.html +++ b/src/app/shared/resource-policies/form/eperson-group-list/eperson-search-box/eperson-search-box.component.html @@ -12,8 +12,8 @@ -
diff --git a/src/app/shared/resource-policies/form/eperson-group-list/group-search-box/group-search-box.component.html b/src/app/shared/resource-policies/form/eperson-group-list/group-search-box/group-search-box.component.html index 418996c564..e5a3e1a876 100644 --- a/src/app/shared/resource-policies/form/eperson-group-list/group-search-box/group-search-box.component.html +++ b/src/app/shared/resource-policies/form/eperson-group-list/group-search-box/group-search-box.component.html @@ -6,8 +6,8 @@ -
diff --git a/src/app/shared/resource-policies/form/resource-policy-form.component.html b/src/app/shared/resource-policies/form/resource-policy-form.component.html index bdfb9ce3e6..5a082d9ba3 100644 --- a/src/app/shared/resource-policies/form/resource-policy-form.component.html +++ b/src/app/shared/resource-policies/form/resource-policy-form.component.html @@ -3,7 +3,8 @@ #formRef="formComponent" [formId]="formId" [formModel]="formModel" - [displaySubmit]="false"> + [displaySubmit]="false" + [displayCancel]="false">
diff --git a/src/app/shared/search-form/search-form.component.html b/src/app/shared/search-form/search-form.component.html index 19c6f8f1ac..bb75f449ff 100644 --- a/src/app/shared/search-form/search-form.component.html +++ b/src/app/shared/search-form/search-form.component.html @@ -7,9 +7,10 @@
- + - +
diff --git a/src/app/shared/search-form/search-form.component.ts b/src/app/shared/search-form/search-form.component.ts index 97541c4786..7bd7af2f02 100644 --- a/src/app/shared/search-form/search-form.component.ts +++ b/src/app/shared/search-form/search-form.component.ts @@ -14,7 +14,6 @@ import { currentPath } from '../utils/route.utils'; @Component({ selector: 'ds-search-form', styleUrls: ['./search-form.component.scss'], - // templateUrl: './search-form.component.html', templateUrl: './search-form.component.html' }) @@ -55,6 +54,11 @@ export class SearchFormComponent { */ @Input() brandColor = 'primary'; + /** + * The placeholder of the search input + */ + @Input() searchPlaceholder: string; + /** * Output the search data on submit */ diff --git a/src/app/shared/search/search-filters/search-filter/search-filter.component.html b/src/app/shared/search/search-filters/search-filter/search-filter.component.html index a03a0de451..eb2105f4e7 100644 --- a/src/app/shared/search/search-filters/search-filter/search-filter.component.html +++ b/src/app/shared/search/search-filters/search-filter/search-filter.component.html @@ -4,7 +4,9 @@ {{'search.filters.filter.' + filter.name + '.head'| translate}} + [ngClass]="(collapsed$ | async) ? 'fa-plus' : 'fa-minus'" + [title]="((collapsed$ | async) ? 'search.filters.filter.expand' : 'search.filters.filter.collapse') | translate" + [attr.aria-label]="((collapsed$ | async) ? 'search.filters.filter.expand' : 'search.filters.filter.collapse') | translate">
-{{"search.filters.reset" | translate}} + {{"search.filters.reset" | translate}} diff --git a/src/app/shared/shared.module.ts b/src/app/shared/shared.module.ts index 406c7f92fc..e9f9d69918 100644 --- a/src/app/shared/shared.module.ts +++ b/src/app/shared/shared.module.ts @@ -233,6 +233,7 @@ import { LinkMenuItemComponent } from './menu/menu-item/link-menu-item.component import { OnClickMenuItemComponent } from './menu/menu-item/onclick-menu-item.component'; import { TextMenuItemComponent } from './menu/menu-item/text-menu-item.component'; import { ThemedConfigurationSearchPageComponent } from '../+search-page/themed-configuration-search-page.component'; +import { SearchNavbarComponent } from '../search-navbar/search-navbar.component'; /** * Declaration needed to make sure all decorator functions are called in time @@ -458,6 +459,7 @@ const COMPONENTS = [ PublicationSidebarSearchListElementComponent, CollectionSidebarSearchListElementComponent, CommunitySidebarSearchListElementComponent, + SearchNavbarComponent ]; const ENTRY_COMPONENTS = [ diff --git a/src/app/shared/starts-with/date/starts-with-date.component.html b/src/app/shared/starts-with/date/starts-with-date.component.html index 3f024c3254..b350d9896c 100644 --- a/src/app/shared/starts-with/date/starts-with-date.component.html +++ b/src/app/shared/starts-with/date/starts-with-date.component.html @@ -4,7 +4,7 @@ {{'browse.startsWith.jump' | translate}}
- @@ -16,7 +16,7 @@
-
- + - +
diff --git a/src/app/shared/starts-with/text/starts-with-text.component.html b/src/app/shared/starts-with/text/starts-with-text.component.html index dd7f4de278..7a93adf7ac 100644 --- a/src/app/shared/starts-with/text/starts-with-text.component.html +++ b/src/app/shared/starts-with/text/starts-with-text.component.html @@ -22,7 +22,7 @@
- +
diff --git a/src/app/submission/form/footer/submission-form-footer.component.html b/src/app/submission/form/footer/submission-form-footer.component.html index 459241ae1c..9771e34cec 100644 --- a/src/app/submission/form/footer/submission-form-footer.component.html +++ b/src/app/submission/form/footer/submission-form-footer.component.html @@ -1,6 +1,6 @@
- +
@@ -10,24 +10,32 @@
+
diff --git a/src/app/submission/sections/form/section-form.component.html b/src/app/submission/sections/form/section-form.component.html index 64e8a05d80..cd7b45bb00 100644 --- a/src/app/submission/sections/form/section-form.component.html +++ b/src/app/submission/sections/form/section-form.component.html @@ -3,6 +3,7 @@ [formId]="formId" [formModel]="formModel" [displaySubmit]="false" + [displayCancel]="false" (dfChange)="onChange($event)" (dfFocus)="onFocus($event)" (remove)="onRemove($event)" diff --git a/src/app/submission/sections/license/section-license.component.html b/src/app/submission/sections/license/section-license.component.html index 7b0faad5e3..b8d0f601d2 100644 --- a/src/app/submission/sections/license/section-license.component.html +++ b/src/app/submission/sections/license/section-license.component.html @@ -5,4 +5,5 @@ [formModel]="formModel" [formLayout]="formLayout" [displaySubmit]="displaySubmit" + [displayCancel]="false" (dfChange)="onChange($event)"> diff --git a/src/app/submission/sections/upload/file/edit/section-upload-file-edit.component.html b/src/app/submission/sections/upload/file/edit/section-upload-file-edit.component.html index bfb322052c..f6e0646974 100644 --- a/src/app/submission/sections/upload/file/edit/section-upload-file-edit.component.html +++ b/src/app/submission/sections/upload/file/edit/section-upload-file-edit.component.html @@ -4,5 +4,6 @@ [formId]="formId" [formModel]="formModel" [displaySubmit]="false" + [displayCancel]="false" (dfChange)="onChange($event)">
diff --git a/src/assets/i18n/en.json5 b/src/assets/i18n/en.json5 index 4abf57f258..e41e3794ce 100644 --- a/src/assets/i18n/en.json5 +++ b/src/assets/i18n/en.json5 @@ -106,7 +106,7 @@ "admin.registries.bitstream-formats.table.name": "Name", - "admin.registries.bitstream-formats.table.return": "Return", + "admin.registries.bitstream-formats.table.return": "Back", "admin.registries.bitstream-formats.table.supportLevel.KNOWN": "Known", @@ -116,7 +116,7 @@ "admin.registries.bitstream-formats.table.supportLevel.head": "Support Level", - "admin.registries.bitstream-formats.title": "DSpace Angular :: Bitstream Format Registry", + "admin.registries.bitstream-formats.title": "Bitstream Format Registry", @@ -144,7 +144,7 @@ "admin.registries.metadata.schemas.table.namespace": "Namespace", - "admin.registries.metadata.title": "DSpace Angular :: Metadata Registry", + "admin.registries.metadata.title": "Metadata Registry", @@ -194,9 +194,9 @@ "admin.registries.schema.notification.success": "Success", - "admin.registries.schema.return": "Return", + "admin.registries.schema.return": "Back", - "admin.registries.schema.title": "DSpace Angular :: Metadata Schema Registry", + "admin.registries.schema.title": "Metadata Schema Registry", @@ -208,7 +208,9 @@ "admin.access-control.epeople.actions.stop-impersonating": "Stop impersonating EPerson", - "admin.access-control.epeople.title": "DSpace Angular :: EPeople", + "admin.access-control.epeople.breadcrumbs": "EPeople", + + "admin.access-control.epeople.title": "EPeople", "admin.access-control.epeople.head": "EPeople", @@ -222,6 +224,8 @@ "admin.access-control.epeople.search.button": "Search", + "admin.access-control.epeople.search.placeholder": "Search people...", + "admin.access-control.epeople.button.add": "Add EPerson", "admin.access-control.epeople.table.id": "ID", @@ -254,6 +258,8 @@ "admin.access-control.epeople.form.requireCertificate": "Requires certificate", + "admin.access-control.epeople.form.return": "Back", + "admin.access-control.epeople.form.notification.created.success": "Successfully created EPerson \"{{name}}\"", "admin.access-control.epeople.form.notification.created.failure": "Failed to create EPerson \"{{name}}\"", @@ -286,11 +292,17 @@ - "admin.access-control.groups.title": "DSpace Angular :: Groups", + "admin.access-control.groups.title": "Groups", - "admin.access-control.groups.title.singleGroup": "DSpace Angular :: Edit Group", + "admin.access-control.groups.breadcrumbs": "Groups", - "admin.access-control.groups.title.addGroup": "DSpace Angular :: New Group", + "admin.access-control.groups.singleGroup.breadcrumbs": "Edit Group", + + "admin.access-control.groups.title.singleGroup": "Edit Group", + + "admin.access-control.groups.title.addGroup": "New Group", + + "admin.access-control.groups.addGroup.breadcrumbs": "New Group", "admin.access-control.groups.head": "Groups", @@ -302,6 +314,8 @@ "admin.access-control.groups.search.button": "Search", + "admin.access-control.groups.search.placeholder": "Search groups...", + "admin.access-control.groups.table.id": "ID", "admin.access-control.groups.table.name": "Name", @@ -442,7 +456,7 @@ "admin.access-control.groups.form.subgroups-list.no-subgroups-yet": "No subgroups in group yet.", - "admin.access-control.groups.form.return": "Return to groups", + "admin.access-control.groups.form.return": "Back", @@ -497,7 +511,7 @@ "admin.metadata-import.page.dropMsgReplace": "Drop to replace the metadata CSV to import", - "admin.metadata-import.page.button.return": "Return", + "admin.metadata-import.page.button.return": "Back", "admin.metadata-import.page.button.proceed": "Proceed", @@ -576,10 +590,16 @@ "browse.metadata.title.breadcrumbs": "Browse by Title", + "browse.next.button": "Next", + + "browse.previous.button": "Previous", + "browse.startsWith.choose_start": "(Choose start)", "browse.startsWith.choose_year": "(Choose year)", + "browse.startsWith.choose_year.label": "Choose the issue year", + "browse.startsWith.jump": "Jump to a point in the index:", "browse.startsWith.months.april": "April", @@ -602,17 +622,21 @@ "browse.startsWith.months.none": "(Choose month)", + "browse.startsWith.months.none.label": "Choose the issue month", + "browse.startsWith.months.november": "November", "browse.startsWith.months.october": "October", "browse.startsWith.months.september": "September", - "browse.startsWith.submit": "Go", + "browse.startsWith.submit": "Browse", - "browse.startsWith.type_date": "Or type in a date (year-month):", + "browse.startsWith.type_date": "Or type in a date (year-month) and click 'Browse'", - "browse.startsWith.type_text": "Or enter first few letters:", + "browse.startsWith.type_date.label": "Or type in a date (year-month) and click on the Browse button", + + "browse.startsWith.type_text": "Type the first few letters and click on the Browse button", "browse.title": "Browsing {{ collection }} by {{ field }} {{ value }}", @@ -685,12 +709,18 @@ "collection.edit.item-mapper.remove": "Remove selected item mappings", + "collection.edit.item-mapper.search-form.placeholder": "Search items...", + "collection.edit.item-mapper.tabs.browse": "Browse mapped items", "collection.edit.item-mapper.tabs.map": "Map new items", + "collection.edit.logo.delete.title": "Delete logo", + + "collection.edit.logo.delete-undo.title": "Undo delete", + "collection.edit.logo.label": "Collection logo", "collection.edit.logo.notifications.add.error": "Uploading Collection logo failed. Please verify the content before retrying.", @@ -709,7 +739,7 @@ "collection.edit.notifications.success": "Successfully edited the Collection", - "collection.edit.return": "Return", + "collection.edit.return": "Back", @@ -843,7 +873,9 @@ - "communityList.tabTitle": "DSpace - Community List", + "communityList.breadcrumbs": "Community List", + + "communityList.tabTitle": "Community List", "communityList.title": "List of Communities", @@ -878,6 +910,10 @@ "community.edit.breadcrumbs": "Edit Community", + "community.edit.logo.delete.title": "Delete logo", + + "community.edit.logo.delete-undo.title": "Undo delete", + "community.edit.logo.label": "Community logo", "community.edit.logo.notifications.add.error": "Uploading Community logo failed. Please verify the content before retrying.", @@ -900,7 +936,7 @@ "community.edit.notifications.error": "An error occured while editing the Community", - "community.edit.return": "Return", + "community.edit.return": "Back", @@ -1223,7 +1259,7 @@ "forgot-email.form.email.hint": "This address will be verified and used as your login name.", - "forgot-email.form.submit": "Submit", + "forgot-email.form.submit": "Save", "forgot-email.form.success.head": "Verification email sent", @@ -1317,7 +1353,7 @@ "form.search-help": "Click here to look for an existing correspondence", - "form.submit": "Submit", + "form.submit": "Save", "form.repeatable.sort.tip": "Drop the item in the new position", @@ -1326,7 +1362,9 @@ "home.breadcrumbs": "Home", - "home.title": "DSpace Angular :: Home", + "home.search-form.placeholder": "Search the repository ...", + + "home.title": "Home", "home.top-level-communities.head": "Communities in DSpace", @@ -1515,6 +1553,8 @@ "item.edit.item-mapper.notifications.remove.success.head": "Removal of mapping completed", + "item.edit.item-mapper.search-form.placeholder": "Search collections...", + "item.edit.item-mapper.tabs.browse": "Browse mapped collections", "item.edit.item-mapper.tabs.map": "Map new collections", @@ -1674,6 +1714,8 @@ "item.edit.relationships.no-entity-type": "Add 'relationship.type' metadata to enable relationships for this item", + "item.edit.return": "Back", + "item.edit.tabs.bitstreams.head": "Bitstreams", @@ -1781,7 +1823,7 @@ "item.search.results.head": "Item Search Results", - "item.search.title": "DSpace Angular :: Item Search", + "item.search.title": "Item Search", @@ -1879,7 +1921,7 @@ "item.version.history.head": "Version History", - "item.version.history.return": "Return", + "item.version.history.return": "Back", "item.version.history.selected": "Selected version", @@ -1915,7 +1957,7 @@ "journal.search.results.head": "Journal Search Results", - "journal.search.title": "DSpace Angular :: Journal Search", + "journal.search.title": "Journal Search", @@ -2021,10 +2063,12 @@ - "menu.header.admin": "Admin", + "menu.header.admin": "Management", "menu.header.image.logo": "Repository logo", + "menu.header.admin.description": "Management menu", + "menu.section.access_control": "Access Control", @@ -2191,6 +2235,8 @@ "menu.section.workflow": "Administer Workflow", + "mydspace.breadcrumbs": "MyDSpace", + "mydspace.description": "", "mydspace.general.text-here": "here", @@ -2245,6 +2291,8 @@ "mydspace.results.no-uri": "No Uri", + "mydspace.search-form.placeholder": "Search in mydspace...", + "mydspace.show.workflow": "All tasks", "mydspace.show.workspace": "Your Submissions", @@ -2283,7 +2331,9 @@ "nav.login": "Log In", - "nav.logout": "Log Out", + "nav.logout": "User profile menu and Log Out", + + "nav.main.description": "Main navigation bar", "nav.mydspace": "MyDSpace", @@ -2295,6 +2345,8 @@ "nav.stop-impersonating": "Stop impersonating EPerson", + "nav.user.description" : "User profile bar", + "orgunit.listelement.badge": "Organizational Unit", @@ -2315,6 +2367,8 @@ + "pagination.options.description": "Pagination options", + "pagination.results-per-page": "Results Per Page", "pagination.showing.detail": "{{ range }} of {{ total }}", @@ -2351,7 +2405,7 @@ "person.search.results.head": "Person Search Results", - "person.search.title": "DSpace Angular :: Person Search", + "person.search.title": "Person Search", @@ -2359,7 +2413,7 @@ "process.new.cancel": "Cancel", - "process.new.submit": "Submit", + "process.new.submit": "Save", "process.new.select-script": "Script", @@ -2452,7 +2506,7 @@ "profile.card.security": "Security", - "profile.form.submit": "Update Profile", + "profile.form.submit": "Save", "profile.groups.head": "Authorization groups you belong to", @@ -2546,8 +2600,8 @@ "publication.search.results.head": "Publication Search Results", - "publication.search.title": "DSpace Angular :: Publication Search", - + "publication.search.title": "Publication Search", + "media-viewer.next": "Next", @@ -2662,6 +2716,10 @@ "relationships.isContributorOf": "Contributors", + "repository.image.logo": "Repository logo", + + "repository.title.prefix": "DSpace Angular :: ", + "resource-policies.add.button": "Add", @@ -2769,10 +2827,12 @@ "search.switch-configuration.title": "Show", - "search.title": "DSpace Angular :: Search", + "search.title": "Search", "search.breadcrumbs": "Search", + "search.search-form.placeholder": "Search the repository ...", + "search.filters.applied.f.author": "Author", @@ -2814,6 +2874,8 @@ "search.filters.filter.birthDate.placeholder": "Birth Date", + "search.filters.filter.collapse": "Collapse filter", + "search.filters.filter.creativeDatePublished.head": "Date Published", "search.filters.filter.creativeDatePublished.placeholder": "Date Published", @@ -2848,6 +2910,8 @@ "search.filters.filter.entityType.placeholder": "Item Type", + "search.filters.filter.expand": "Expand filter", + "search.filters.filter.has_content_in_original_bundle.head": "Has files", "search.filters.filter.itemtype.head": "Type", @@ -2927,9 +2991,7 @@ "search.form.search": "Search", - "search.form.search_dspace": "Search DSpace", - - "search.form.search_mydspace": "Search MyDSpace", + "search.form.search_dspace": "All repository", @@ -3003,8 +3065,12 @@ + "submission.edit.breadcrumbs": "Edit Submission", + "submission.edit.title": "Edit Submission", + "submission.general.cancel": "Cancel", + "submission.general.cannot_submit": "You have not the privilege to make a new submission.", "submission.general.deposit": "Deposit", @@ -3138,6 +3204,8 @@ "submission.sections.describe.relationship-lookup.search-tab.search": "Go", + "submission.sections.describe.relationship-lookup.search-tab.search-form.placeholder": "Search...", + "submission.sections.describe.relationship-lookup.search-tab.select-all": "Select all", "submission.sections.describe.relationship-lookup.search-tab.select-page": "Select page", @@ -3185,6 +3253,8 @@ "submission.sections.describe.relationship-lookup.search-tab.tab-title.isChildOrgUnitOf": "Search for Organizational Units", + "submission.sections.describe.relationship-lookup.selection-tab.search-form.placeholder": "Search...", + "submission.sections.describe.relationship-lookup.selection-tab.tab-title": "Current Selection ({{ count }})", "submission.sections.describe.relationship-lookup.title.isJournalIssueOfPublication": "Journal Issues", @@ -3381,7 +3451,9 @@ - "submission.submit.title": "Submission", + "submission.submit.breadcrumbs": "New submission", + + "submission.submit.title": "New submission", @@ -3487,6 +3559,10 @@ + "workflow-item.edit.breadcrumbs": "Edit workflowitem", + + "workflow-item.edit.title": "Edit workflowitem", + "workflow-item.delete.notification.success.title": "Deleted", "workflow-item.delete.notification.success.content": "This workflow item was successfully deleted", diff --git a/src/styles/_bootstrap_variables.scss b/src/styles/_bootstrap_variables.scss index ee997f4d8a..58f599c516 100644 --- a/src/styles/_bootstrap_variables.scss +++ b/src/styles/_bootstrap_variables.scss @@ -1,5 +1,3 @@ -// @import '_themed_bootstrap_variables'; - /** Help Variables **/ $fa-fixed-width: 1.25rem !default; $icon-padding: 1rem !default; @@ -22,12 +20,12 @@ $gray-600: lighten($gray-base, 73.3%) !default; // #bbb $gray-100: lighten($gray-base, 93.5%) !default; // #eee /* Reassign color vars to semantic color scheme */ -$blue: #2B4E72 !default; -$green: #94BA65 !default; -$cyan: #2790B0 !default; +$blue: #2B4E72 !default; +$green: #94BA65 !default; +$cyan: #006666 !default; $yellow: #ec9433 !default; -$red: #CF4444 !default; -$dark: darken($blue, 17%) !default; +$red: #CF4444 !default; +$dark: darken($blue, 17%) !default; $theme-colors: ( primary: $blue, @@ -49,12 +47,4 @@ $navbar-light-toggler-icon-bg: url("data:image/svg+xml;charset=utf8, Date: Fri, 2 Apr 2021 16:28:40 -0500 Subject: [PATCH 132/132] Revert "Submission dropzone issues" --- src/app/shared/mocks/submission.mock.ts | 85 ------------------- src/app/shared/uploader/uploader.component.ts | 25 +++++- .../form/submission-form.component.html | 65 +++++++------- .../form/submission-form.component.spec.ts | 9 +- .../form/submission-form.component.ts | 12 +-- .../sections/sections.service.spec.ts | 34 ++------ .../submission/sections/sections.service.ts | 25 +----- 7 files changed, 69 insertions(+), 186 deletions(-) diff --git a/src/app/shared/mocks/submission.mock.ts b/src/app/shared/mocks/submission.mock.ts index 1ee097af71..16cc9b6262 100644 --- a/src/app/shared/mocks/submission.mock.ts +++ b/src/app/shared/mocks/submission.mock.ts @@ -1101,91 +1101,6 @@ export const mockSubmissionState: SubmissionObjectState = Object.assign({}, { } }); -export const mockSubmissionStateWithoutUpload: SubmissionObjectState = Object.assign({}, { - 826: { - collection: mockSubmissionCollectionId, - definition: 'traditional', - selfUrl: mockSubmissionSelfUrl, - activeSection: null, - sections: { - extraction: { - config: '', - mandatory: true, - sectionType: 'utils', - visibility: { - main: 'HIDDEN', - other: 'HIDDEN' - }, - collapsed: false, - enabled: true, - data: {}, - errors: [], - isLoading: false, - isValid: false - } as any, - collection: { - config: '', - mandatory: true, - sectionType: 'collection', - visibility: { - main: 'HIDDEN', - other: 'HIDDEN' - }, - collapsed: false, - enabled: true, - data: {}, - errors: [], - isLoading: false, - isValid: false - } as any, - traditionalpageone: { - header: 'submit.progressbar.describe.stepone', - config: 'https://rest.api/dspace-spring-rest/api/config/submissionforms/traditionalpageone', - mandatory: true, - sectionType: 'submission-form', - collapsed: false, - enabled: true, - data: {}, - errors: [], - formId: '2_traditionalpageone', - isLoading: false, - isValid: false - } as any, - traditionalpagetwo: { - header: 'submit.progressbar.describe.steptwo', - config: 'https://rest.api/dspace-spring-rest/api/config/submissionforms/traditionalpagetwo', - mandatory: false, - sectionType: 'submission-form', - collapsed: false, - enabled: false, - data: {}, - errors: [], - isLoading: false, - isValid: false - } as any, - license: { - header: 'submit.progressbar.license', - config: '', - mandatory: true, - sectionType: 'license', - visibility: { - main: null, - other: 'READONLY' - }, - collapsed: false, - enabled: true, - data: {}, - errors: [], - isLoading: false, - isValid: false - } as any - }, - isLoading: false, - savePending: false, - depositPending: false - } -}); - export const mockSectionsState = Object.assign({}, { extraction: { config: '', diff --git a/src/app/shared/uploader/uploader.component.ts b/src/app/shared/uploader/uploader.component.ts index a0dd0e5bba..0e19c38b55 100644 --- a/src/app/shared/uploader/uploader.component.ts +++ b/src/app/shared/uploader/uploader.component.ts @@ -1,16 +1,29 @@ -import { ChangeDetectionStrategy, ChangeDetectorRef, Component, EventEmitter, HostListener, Input, Output, ViewEncapsulation, } from '@angular/core'; +import { + ChangeDetectionStrategy, + ChangeDetectorRef, + Component, + EventEmitter, + HostListener, + Input, + Output, + ViewEncapsulation, +} from '@angular/core'; import { of as observableOf } from 'rxjs'; import { FileUploader } from 'ng2-file-upload'; import { uniqueId } from 'lodash'; -import { ScrollToService } from '@nicky-lenaers/ngx-scroll-to'; +import { ScrollToConfigOptions, ScrollToService } from '@nicky-lenaers/ngx-scroll-to'; import { UploaderOptions } from './uploader-options.model'; import { hasValue, isNotEmpty, isUndefined } from '../empty.util'; import { UploaderService } from './uploader.service'; import { UploaderProperties } from './uploader-properties.model'; import { HttpXsrfTokenExtractor } from '@angular/common/http'; -import { XSRF_COOKIE, XSRF_REQUEST_HEADER, XSRF_RESPONSE_HEADER } from '../../core/xsrf/xsrf.interceptor'; +import { + XSRF_REQUEST_HEADER, + XSRF_RESPONSE_HEADER, + XSRF_COOKIE +} from '../../core/xsrf/xsrf.interceptor'; import { CookieService } from '../../core/services/cookie.service'; @Component({ @@ -133,6 +146,12 @@ export class UploaderComponent { this.uploader.options.headers = [{ name: XSRF_REQUEST_HEADER, value: this.tokenExtractor.getToken() }]; this.onBeforeUpload(); this.isOverDocumentDropZone = observableOf(false); + + // Move page target to the uploader + const config: ScrollToConfigOptions = { + target: this.uploaderId + }; + this.scrollToService.scrollTo(config); }; if (hasValue(this.uploadProperties)) { this.uploader.onBuildItemForm = (item, form) => { diff --git a/src/app/submission/form/submission-form.component.html b/src/app/submission/form/submission-form.component.html index 33b5d4be12..7376b1e10b 100644 --- a/src/app/submission/form/submission-form.component.html +++ b/src/app/submission/form/submission-form.component.html @@ -1,36 +1,35 @@
-
-
- -
-
+
+ +
+
+
+
+ + +
+
+ + +
+
-
- - -
-
- - -
-
- -
- - - - -
- +
+ + + + +
+
diff --git a/src/app/submission/form/submission-form.component.spec.ts b/src/app/submission/form/submission-form.component.spec.ts index dd8e6d0ea3..d719472adf 100644 --- a/src/app/submission/form/submission-form.component.spec.ts +++ b/src/app/submission/form/submission-form.component.spec.ts @@ -24,7 +24,7 @@ import { HALEndpointServiceStub } from '../../shared/testing/hal-endpoint-servic import { createTestComponent } from '../../shared/testing/utils.test'; import { Item } from '../../core/shared/item.model'; import { TestScheduler } from 'rxjs/testing'; -import { SectionsService } from '../sections/sections.service'; + describe('SubmissionFormComponent Component', () => { @@ -55,7 +55,6 @@ describe('SubmissionFormComponent Component', () => { { provide: AuthService, useClass: AuthServiceStub }, { provide: HALEndpointService, useValue: new HALEndpointServiceStub('workspaceitems') }, { provide: SubmissionService, useValue: submissionServiceStub }, - { provide: SectionsService, useValue: { isSectionTypeAvailable: () => observableOf(true) } }, ChangeDetectorRef, SubmissionFormComponent ], @@ -116,7 +115,7 @@ describe('SubmissionFormComponent Component', () => { expect(compAsAny.submissionSections).toBeUndefined(); expect(compAsAny.subs).toEqual([]); expect(submissionServiceStub.startAutoSave).not.toHaveBeenCalled(); - expect(comp.loading).toBeObservable(cold('(a|)', { a: true })); + expect(comp.loading).toBeObservable(cold('(a|)', {a: true})); done(); }); @@ -141,7 +140,7 @@ describe('SubmissionFormComponent Component', () => { }); scheduler.flush(); - expect(comp.submissionSections).toBeObservable(cold('(a|)', { a: sectionsList })); + expect(comp.submissionSections).toBeObservable(cold('(a|)', {a: sectionsList})); expect(submissionServiceStub.dispatchInit).toHaveBeenCalledWith( collectionId, @@ -202,7 +201,7 @@ describe('SubmissionFormComponent Component', () => { submissionDefinition: { name: 'traditional' } - } as any); + } as any); fixture.detectChanges(); }); scheduler.flush(); diff --git a/src/app/submission/form/submission-form.component.ts b/src/app/submission/form/submission-form.component.ts index 8df0ab1658..dc6f264d9b 100644 --- a/src/app/submission/form/submission-form.component.ts +++ b/src/app/submission/form/submission-form.component.ts @@ -15,8 +15,6 @@ import { SubmissionObjectEntry } from '../objects/submission-objects.reducer'; import { SectionDataObject } from '../sections/models/section-data.model'; import { SubmissionService } from '../submission.service'; import { Item } from '../../core/shared/item.model'; -import { SectionsType } from '../sections/sections-type'; -import { SectionsService } from '../sections/sections.service'; /** * This component represents the submission form. @@ -71,11 +69,6 @@ export class SubmissionFormComponent implements OnChanges, OnDestroy { */ public loading: Observable = observableOf(true); - /** - * Emits true when the submission config has bitstream uploading enabled in submission - */ - public uploadEnabled$: Observable; - /** * Observable of the list of submission's sections * @type {Observable} @@ -107,14 +100,12 @@ export class SubmissionFormComponent implements OnChanges, OnDestroy { * @param {ChangeDetectorRef} changeDetectorRef * @param {HALEndpointService} halService * @param {SubmissionService} submissionService - * @param {SectionsService} sectionsService */ constructor( private authService: AuthService, private changeDetectorRef: ChangeDetectorRef, private halService: HALEndpointService, - private submissionService: SubmissionService, - private sectionsService: SectionsService) { + private submissionService: SubmissionService) { this.isActive = true; } @@ -138,7 +129,6 @@ export class SubmissionFormComponent implements OnChanges, OnDestroy { return observableOf([]); } })); - this.uploadEnabled$ = this.sectionsService.isSectionTypeAvailable(this.submissionId, SectionsType.Upload); // check if is submission loading this.loading = this.submissionService.getSubmissionObject(this.submissionId).pipe( diff --git a/src/app/submission/sections/sections.service.spec.ts b/src/app/submission/sections/sections.service.spec.ts index 0d63beeaea..6bdf26a082 100644 --- a/src/app/submission/sections/sections.service.spec.ts +++ b/src/app/submission/sections/sections.service.spec.ts @@ -1,4 +1,4 @@ -import { TestBed, waitForAsync } from '@angular/core/testing'; +import { waitForAsync, TestBed } from '@angular/core/testing'; import { cold, getTestScheduler } from 'jasmine-marbles'; import { of as observableOf } from 'rxjs'; @@ -17,8 +17,7 @@ import { SectionsService } from './sections.service'; import { mockSectionsData, mockSectionsErrors, - mockSubmissionState, - mockSubmissionStateWithoutUpload + mockSubmissionState } from '../../shared/mocks/submission.mock'; import { DisableSectionAction, @@ -28,7 +27,11 @@ import { SectionStatusChangeAction, UpdateSectionDataAction } from '../objects/submission-objects.actions'; -import { FormAddError, FormClearErrorsAction, FormRemoveErrorAction } from '../../shared/form/form.actions'; +import { + FormAddError, + FormClearErrorsAction, + FormRemoveErrorAction +} from '../../shared/form/form.actions'; import parseSectionErrors from '../utils/parseSectionErrors'; import { SubmissionScopeType } from '../../core/submission/submission-scope-type'; import { SubmissionSectionError } from '../objects/submission-objects.reducer'; @@ -49,7 +52,6 @@ describe('SectionsService test suite', () => { const sectionErrors: any = parseSectionErrors(mockSectionsErrors); const sectionData: any = mockSectionsData; const submissionState: any = Object.assign({}, mockSubmissionState[submissionId]); - const submissionStateWithoutUpload: any = Object.assign({}, mockSubmissionStateWithoutUpload[submissionId]); const sectionState: any = Object.assign({}, mockSubmissionState['826'].sections[sectionId]); const store: any = jasmine.createSpyObj('store', { @@ -312,28 +314,6 @@ describe('SectionsService test suite', () => { }); }); - describe('isSectionTypeAvailable', () => { - it('should return an observable of true when section is available', () => { - store.select.and.returnValue(observableOf(submissionState)); - - const expected = cold('(b|)', { - b: true - }); - - expect(service.isSectionTypeAvailable(submissionId, SectionsType.Upload)).toBeObservable(expected); - }); - - it('should return an observable of false when section is not available', () => { - store.select.and.returnValue(observableOf(submissionStateWithoutUpload)); - - const expected = cold('(b|)', { - b: false - }); - - expect(service.isSectionAvailable(submissionId, SectionsType.Upload)).toBeObservable(expected); - }); - }); - describe('addSection', () => { it('should dispatch a new EnableSectionAction a move target to new section', () => { diff --git a/src/app/submission/sections/sections.service.ts b/src/app/submission/sections/sections.service.ts index d8d1491cb7..b2bc0e4f98 100644 --- a/src/app/submission/sections/sections.service.ts +++ b/src/app/submission/sections/sections.service.ts @@ -5,7 +5,7 @@ import { distinctUntilChanged, filter, map, take } from 'rxjs/operators'; import { Store } from '@ngrx/store'; import { TranslateService } from '@ngx-translate/core'; import { ScrollToConfigOptions, ScrollToService } from '@nicky-lenaers/ngx-scroll-to'; -import { findKey, isEqual } from 'lodash'; +import { isEqual } from 'lodash'; import { SubmissionState } from '../submission.reducers'; import { hasValue, isEmpty, isNotEmpty, isNotUndefined } from '../../shared/empty.util'; @@ -291,14 +291,14 @@ export class SectionsService { } /** - * Check if a given section id is present in the list of sections + * Check if a given section is a read only available * * @param submissionId * The submission id * @param sectionId * The section id * @return Observable - * Emits true whenever a given section id should be available + * Emits true whenever a given section should be available */ public isSectionAvailable(submissionId: string, sectionId: string): Observable { return this.store.select(submissionObjectFromIdSelector(submissionId)).pipe( @@ -309,25 +309,6 @@ export class SectionsService { distinctUntilChanged()); } - /** - * Check if a given section type is present in the list of sections - * - * @param submissionId - * The submission id - * @param sectionType - * The section type - * @return Observable - * Emits true whenever a given section type should be available - */ - public isSectionTypeAvailable(submissionId: string, sectionType: SectionsType): Observable { - return this.store.select(submissionObjectFromIdSelector(submissionId)).pipe( - filter((submissionState: SubmissionObjectEntry) => isNotUndefined(submissionState)), - map((submissionState: SubmissionObjectEntry) => { - return isNotUndefined(submissionState.sections) && isNotUndefined(findKey(submissionState.sections, {sectionType: sectionType})); - }), - distinctUntilChanged()); - } - /** * Dispatch a new [EnableSectionAction] to add a new section and move page target to it *