From cdb2c30bd45e233a5de336cbc67f0ddd0b566361 Mon Sep 17 00:00:00 2001 From: Yana De Pauw Date: Wed, 10 Jul 2019 11:14:21 +0200 Subject: [PATCH 01/26] 63667: Extract update tracker --- src/app/shared/shared.module.ts | 5 +- .../abstract-trackable.component.spec.ts | 101 ++++++++++++++++++ .../trackable/abstract-trackable.component.ts | 78 ++++++++++++++ 3 files changed, 183 insertions(+), 1 deletion(-) create mode 100644 src/app/shared/trackable/abstract-trackable.component.spec.ts create mode 100644 src/app/shared/trackable/abstract-trackable.component.ts diff --git a/src/app/shared/shared.module.ts b/src/app/shared/shared.module.ts index 816139c8b9..4654789b90 100644 --- a/src/app/shared/shared.module.ts +++ b/src/app/shared/shared.module.ts @@ -138,6 +138,7 @@ import { RoleDirective } from './roles/role.directive'; import { UserMenuComponent } from './auth-nav-menu/user-menu/user-menu.component'; import { ClaimedTaskActionsReturnToPoolComponent } from './mydspace-actions/claimed-task/return-to-pool/claimed-task-actions-return-to-pool.component'; import { ItemDetailPreviewFieldComponent } from './object-detail/my-dspace-result-detail-element/item-detail-preview/item-detail-preview-field/item-detail-preview-field.component'; +import { AbstractTrackableComponent } from './trackable/abstract-trackable.component'; const MODULES = [ // Do NOT include UniversalModule, HttpModule, or JsonpModule here @@ -257,7 +258,8 @@ const COMPONENTS = [ ItemSearchResultListElementComponent, TypedItemSearchResultListElementComponent, ItemTypeSwitcherComponent, - BrowseByComponent + BrowseByComponent, + AbstractTrackableComponent ]; const ENTRY_COMPONENTS = [ @@ -311,6 +313,7 @@ const SHARED_ITEM_PAGE_COMPONENTS = [ const PROVIDERS = [ TruncatableService, MockAdminGuard, + AbstractTrackableComponent, { provide: DYNAMIC_FORM_CONTROL_MAP_FN, useValue: dsDynamicFormControlMapFn diff --git a/src/app/shared/trackable/abstract-trackable.component.spec.ts b/src/app/shared/trackable/abstract-trackable.component.spec.ts new file mode 100644 index 0000000000..3755092263 --- /dev/null +++ b/src/app/shared/trackable/abstract-trackable.component.spec.ts @@ -0,0 +1,101 @@ +import { async, ComponentFixture, TestBed } from '@angular/core/testing'; +import { AbstractTrackableComponent } from './abstract-trackable.component'; +import { INotification, Notification } from '../notifications/models/notification.model'; +import { NotificationType } from '../notifications/models/notification-type'; +import { of as observableOf } from 'rxjs'; +import { TranslateModule } from '@ngx-translate/core'; +import { ObjectUpdatesService } from '../../core/data/object-updates/object-updates.service'; +import { NotificationsService } from '../notifications/notifications.service'; +import { NO_ERRORS_SCHEMA } from '@angular/core'; +import { TestScheduler } from 'rxjs/testing'; +import { getTestScheduler } from 'jasmine-marbles'; + +describe('AbstractTrackableComponent', () => { + let comp: AbstractTrackableComponent; + let fixture: ComponentFixture; + let objectUpdatesService; + let scheduler: TestScheduler; + + const infoNotification: INotification = new Notification('id', NotificationType.Info, 'info'); + const warningNotification: INotification = new Notification('id', NotificationType.Warning, 'warning'); + const successNotification: INotification = new Notification('id', NotificationType.Success, 'success'); + + const notificationsService = jasmine.createSpyObj('notificationsService', + { + info: infoNotification, + warning: warningNotification, + success: successNotification + } + ); + + const url = 'http://test-url.com/test-url'; + + beforeEach(async(() => { + objectUpdatesService = jasmine.createSpyObj('objectUpdatesService', + { + saveAddFieldUpdate: {}, + discardFieldUpdates: {}, + reinstateFieldUpdates: observableOf(true), + initialize: {}, + hasUpdates: observableOf(true), + isReinstatable: observableOf(false), // should always return something --> its in ngOnInit + isValidPage: observableOf(true) + } + ); + + scheduler = getTestScheduler(); + + TestBed.configureTestingModule({ + imports: [TranslateModule.forRoot()], + declarations: [AbstractTrackableComponent], + providers: [ + {provide: ObjectUpdatesService, useValue: objectUpdatesService}, + {provide: NotificationsService, useValue: notificationsService}, + ], schemas: [ + NO_ERRORS_SCHEMA + ] + }).compileComponents(); + })); + + beforeEach(() => { + fixture = TestBed.createComponent(AbstractTrackableComponent); + comp = fixture.componentInstance; + comp.url = url; + + fixture.detectChanges(); + }); + + it('should discard object updates', () => { + comp.discard(); + + expect(objectUpdatesService.discardFieldUpdates).toHaveBeenCalledWith(url, infoNotification); + }); + it('should undo the discard of object updates', () => { + comp.reinstate(); + + expect(objectUpdatesService.reinstateFieldUpdates).toHaveBeenCalledWith(url); + }); + + describe('isReinstatable', () => { + beforeEach(() => { + objectUpdatesService.isReinstatable.and.returnValue(observableOf(true)); + }); + + it('should return an observable that emits true', () => { + const expected = '(a|)'; + scheduler.expectObservable(comp.isReinstatable()).toBe(expected, {a: true}); + }); + }); + + describe('hasChanges', () => { + beforeEach(() => { + objectUpdatesService.hasUpdates.and.returnValue(observableOf(true)); + }); + + it('should return an observable that emits true', () => { + const expected = '(a|)'; + scheduler.expectObservable(comp.hasChanges()).toBe(expected, {a: true}); + }); + }); + +}); diff --git a/src/app/shared/trackable/abstract-trackable.component.ts b/src/app/shared/trackable/abstract-trackable.component.ts new file mode 100644 index 0000000000..cd1b425f10 --- /dev/null +++ b/src/app/shared/trackable/abstract-trackable.component.ts @@ -0,0 +1,78 @@ +import { ObjectUpdatesService } from '../../core/data/object-updates/object-updates.service'; +import { NotificationsService } from '../notifications/notifications.service'; +import { TranslateService } from '@ngx-translate/core'; +import { Observable } from 'rxjs'; +import { Component } from '@angular/core'; + +/** + * Abstract Component that is able to track changes made in the inheriting component using the ObjectUpdateService + */ +@Component({ + selector: 'ds-abstract-trackable', + template: '' +}) +export class AbstractTrackableComponent { + + /** + * The time span for being able to undo discarding changes + */ + public discardTimeOut: number; + public message: string; + public url: string; + public notificationsPrefix = 'static-pages.form.notification'; + + constructor( + public objectUpdatesService: ObjectUpdatesService, + public notificationsService: NotificationsService, + public translateService: TranslateService, + ) { + + } + + /** + * Request the object updates service to discard all current changes to this item + * Shows a notification to remind the user that they can undo this + */ + discard() { + const undoNotification = this.notificationsService.info(this.getNotificationTitle('discarded'), this.getNotificationContent('discarded'), {timeOut: this.discardTimeOut}); + this.objectUpdatesService.discardFieldUpdates(this.url, undoNotification); + } + + /** + * Request the object updates service to undo discarding all changes to this item + */ + reinstate() { + this.objectUpdatesService.reinstateFieldUpdates(this.url); + } + + /** + * Checks whether or not the object is currently reinstatable + */ + isReinstatable(): Observable { + return this.objectUpdatesService.isReinstatable(this.url); + } + + /** + * Checks whether or not there are currently updates for this object + */ + hasChanges(): Observable { + return this.objectUpdatesService.hasUpdates(this.url); + } + + /** + * Get translated notification title + * @param key + */ + private getNotificationTitle(key: string) { + return this.translateService.instant(this.notificationsPrefix + key + '.title'); + } + + /** + * Get translated notification content + * @param key + */ + private getNotificationContent(key: string) { + return this.translateService.instant(this.notificationsPrefix + key + '.content'); + + } +} From 3d9af688e775b6de60b1209f4db2ff95ee83770a Mon Sep 17 00:00:00 2001 From: Kristof De Langhe Date: Wed, 10 Jul 2019 16:43:20 +0200 Subject: [PATCH 02/26] 63669: Edit Communtiy/Collection Tabs --- resources/i18n/en.json | 38 +++++++++++- .../collection-page-routing.module.ts | 9 +-- .../collection-page.module.ts | 5 +- .../collection-curate.component.html} | 0 .../collection-curate.component.ts | 9 +++ .../collection-metadata.component.html | 4 ++ .../collection-metadata.component.ts | 21 +++++++ .../collection-roles.component.html | 0 .../collection-roles.component.ts | 9 +++ .../collection-source.component.html | 0 .../collection-source.component.ts | 9 +++ .../edit-collection-page.component.html | 11 ---- .../edit-collection-page.component.scss | 1 - .../edit-collection-page.component.ts | 18 ++++-- .../edit-collection-page.module.ts | 32 ++++++++++ .../edit-collection-page.routing.module.ts | 58 +++++++++++++++++++ .../community-page-routing.module.ts | 9 +-- .../+community-page/community-page.module.ts | 5 +- .../community-curate.component.html | 0 .../community-curate.component.ts | 9 +++ .../community-metadata.component.html | 4 ++ .../community-metadata.component.ts | 21 +++++++ .../community-roles.component.html | 0 .../community-roles.component.ts | 9 +++ .../edit-community-page.component.html | 12 ---- .../edit-community-page.component.scss | 1 - .../edit-community-page.component.ts | 18 ++++-- .../edit-community-page.module.ts | 30 ++++++++++ .../edit-community-page.routing.module.ts | 52 +++++++++++++++++ .../comcol-metadata.component.ts | 48 +++++++++++++++ .../edit-comcol-page.component.html | 24 ++++++++ .../edit-comcol-page.component.ts | 41 +++++++------ src/app/shared/shared.module.ts | 4 +- 33 files changed, 436 insertions(+), 75 deletions(-) rename src/app/{shared/mocks/mock-store.ts => +collection-page/edit-collection-page/collection-curate/collection-curate.component.html} (100%) create mode 100644 src/app/+collection-page/edit-collection-page/collection-curate/collection-curate.component.ts create mode 100644 src/app/+collection-page/edit-collection-page/collection-metadata/collection-metadata.component.html create mode 100644 src/app/+collection-page/edit-collection-page/collection-metadata/collection-metadata.component.ts create mode 100644 src/app/+collection-page/edit-collection-page/collection-roles/collection-roles.component.html create mode 100644 src/app/+collection-page/edit-collection-page/collection-roles/collection-roles.component.ts create mode 100644 src/app/+collection-page/edit-collection-page/collection-source/collection-source.component.html create mode 100644 src/app/+collection-page/edit-collection-page/collection-source/collection-source.component.ts delete mode 100644 src/app/+collection-page/edit-collection-page/edit-collection-page.component.html delete mode 100644 src/app/+collection-page/edit-collection-page/edit-collection-page.component.scss create mode 100644 src/app/+collection-page/edit-collection-page/edit-collection-page.module.ts create mode 100644 src/app/+collection-page/edit-collection-page/edit-collection-page.routing.module.ts create mode 100644 src/app/+community-page/edit-community-page/community-curate/community-curate.component.html create mode 100644 src/app/+community-page/edit-community-page/community-curate/community-curate.component.ts create mode 100644 src/app/+community-page/edit-community-page/community-metadata/community-metadata.component.html create mode 100644 src/app/+community-page/edit-community-page/community-metadata/community-metadata.component.ts create mode 100644 src/app/+community-page/edit-community-page/community-roles/community-roles.component.html create mode 100644 src/app/+community-page/edit-community-page/community-roles/community-roles.component.ts delete mode 100644 src/app/+community-page/edit-community-page/edit-community-page.component.html delete mode 100644 src/app/+community-page/edit-community-page/edit-community-page.component.scss create mode 100644 src/app/+community-page/edit-community-page/edit-community-page.module.ts create mode 100644 src/app/+community-page/edit-community-page/edit-community-page.routing.module.ts create mode 100644 src/app/shared/comcol-forms/edit-comcol-page/comcol-metadata/comcol-metadata.component.ts create mode 100644 src/app/shared/comcol-forms/edit-comcol-page/edit-comcol-page.component.html diff --git a/resources/i18n/en.json b/resources/i18n/en.json index a066ffe9d0..76e925f1a2 100644 --- a/resources/i18n/en.json +++ b/resources/i18n/en.json @@ -30,7 +30,26 @@ }, "edit": { "head": "Edit Collection", - "delete": "Delete this collection" + "delete": "Delete this collection", + "tabs": { + "metadata": { + "title": "Collection Edit - Metadata", + "head": "Edit Metadata" + }, + "roles": { + "title": "Collection Edit - Roles", + "head": "Assign Roles" + }, + "source": { + "title": "Collection Edit - Content Source", + "head": "Content Source" + }, + "curate": { + "title": "Collection Edit - Curate", + "head": "Curate" + } + }, + "return": "Return" }, "create": { "head": "Create a Collection", @@ -72,7 +91,22 @@ }, "edit": { "head": "Edit Community", - "delete": "Delete this community" + "delete": "Delete this community", + "tabs": { + "metadata": { + "title": "Community Edit - Metadata", + "head": "Edit Metadata" + }, + "roles": { + "title": "Community Edit - Roles", + "head": "Assign Roles" + }, + "curate": { + "title": "Community Edit - Curate", + "head": "Curate" + } + }, + "return": "Return" }, "create": { "head": "Create a Community", diff --git a/src/app/+collection-page/collection-page-routing.module.ts b/src/app/+collection-page/collection-page-routing.module.ts index cdbd7650b2..ad142e8fcf 100644 --- a/src/app/+collection-page/collection-page-routing.module.ts +++ b/src/app/+collection-page/collection-page-routing.module.ts @@ -5,7 +5,6 @@ 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'; -import { EditCollectionPageComponent } from './edit-collection-page/edit-collection-page.component'; import { CreateCollectionPageGuard } from './create-collection-page/create-collection-page.guard'; import { DeleteCollectionPageComponent } from './delete-collection-page/delete-collection-page.component'; import { URLCombiner } from '../core/url-combiner/url-combiner'; @@ -38,12 +37,8 @@ const COLLECTION_EDIT_PATH = ':id/edit'; }, { path: COLLECTION_EDIT_PATH, - pathMatch: 'full', - component: EditCollectionPageComponent, - canActivate: [AuthenticatedGuard], - resolve: { - dso: CollectionPageResolver - } + loadChildren: './edit-collection-page/edit-collection-page.module#EditCollectionPageModule', + canActivate: [AuthenticatedGuard] }, { path: ':id/delete', diff --git a/src/app/+collection-page/collection-page.module.ts b/src/app/+collection-page/collection-page.module.ts index bdeffa34f3..f7059deda0 100644 --- a/src/app/+collection-page/collection-page.module.ts +++ b/src/app/+collection-page/collection-page.module.ts @@ -7,7 +7,6 @@ import { CollectionPageComponent } from './collection-page.component'; import { CollectionPageRoutingModule } from './collection-page-routing.module'; import { CreateCollectionPageComponent } from './create-collection-page/create-collection-page.component'; import { CollectionFormComponent } from './collection-form/collection-form.component'; -import { EditCollectionPageComponent } from './edit-collection-page/edit-collection-page.component'; import { DeleteCollectionPageComponent } from './delete-collection-page/delete-collection-page.component'; import { SearchService } from '../+search-page/search-service/search.service'; @@ -20,10 +19,12 @@ import { SearchService } from '../+search-page/search-service/search.service'; declarations: [ CollectionPageComponent, CreateCollectionPageComponent, - EditCollectionPageComponent, DeleteCollectionPageComponent, CollectionFormComponent ], + exports: [ + CollectionFormComponent + ], providers: [ SearchService ] diff --git a/src/app/shared/mocks/mock-store.ts b/src/app/+collection-page/edit-collection-page/collection-curate/collection-curate.component.html similarity index 100% rename from src/app/shared/mocks/mock-store.ts rename to src/app/+collection-page/edit-collection-page/collection-curate/collection-curate.component.html diff --git a/src/app/+collection-page/edit-collection-page/collection-curate/collection-curate.component.ts b/src/app/+collection-page/edit-collection-page/collection-curate/collection-curate.component.ts new file mode 100644 index 0000000000..1445c343fe --- /dev/null +++ b/src/app/+collection-page/edit-collection-page/collection-curate/collection-curate.component.ts @@ -0,0 +1,9 @@ +import { Component } from '@angular/core'; + +@Component({ + selector: 'ds-collection-curate', + templateUrl: './collection-curate.component.html', +}) +export class CollectionCurateComponent { + /* TODO: Implement Collection Edit - Curate */ +} 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 new file mode 100644 index 0000000000..cc7a0d5de0 --- /dev/null +++ b/src/app/+collection-page/edit-collection-page/collection-metadata/collection-metadata.component.html @@ -0,0 +1,4 @@ + +{{'collection.edit.delete' + | translate}} diff --git a/src/app/+collection-page/edit-collection-page/collection-metadata/collection-metadata.component.ts b/src/app/+collection-page/edit-collection-page/collection-metadata/collection-metadata.component.ts new file mode 100644 index 0000000000..350ccc0b46 --- /dev/null +++ b/src/app/+collection-page/edit-collection-page/collection-metadata/collection-metadata.component.ts @@ -0,0 +1,21 @@ +import { Component } from '@angular/core'; +import { ComcolMetadataComponent } from '../../../shared/comcol-forms/edit-comcol-page/comcol-metadata/comcol-metadata.component'; +import { Collection } from '../../../core/shared/collection.model'; +import { CollectionDataService } from '../../../core/data/collection-data.service'; +import { ActivatedRoute, Router } from '@angular/router'; + +@Component({ + selector: 'ds-collection-metadata', + templateUrl: './collection-metadata.component.html', +}) +export class CollectionMetadataComponent extends ComcolMetadataComponent { + protected frontendURL = '/collections/'; + + public constructor( + protected collectionDataService: CollectionDataService, + protected router: Router, + protected route: ActivatedRoute + ) { + super(collectionDataService, router, route); + } +} diff --git a/src/app/+collection-page/edit-collection-page/collection-roles/collection-roles.component.html b/src/app/+collection-page/edit-collection-page/collection-roles/collection-roles.component.html new file mode 100644 index 0000000000..e69de29bb2 diff --git a/src/app/+collection-page/edit-collection-page/collection-roles/collection-roles.component.ts b/src/app/+collection-page/edit-collection-page/collection-roles/collection-roles.component.ts new file mode 100644 index 0000000000..ffa3f7709c --- /dev/null +++ b/src/app/+collection-page/edit-collection-page/collection-roles/collection-roles.component.ts @@ -0,0 +1,9 @@ +import { Component } from '@angular/core'; + +@Component({ + selector: 'ds-collection-roles', + templateUrl: './collection-roles.component.html', +}) +export class CollectionRolesComponent { + /* TODO: Implement Collection Edit - Roles */ +} 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 new file mode 100644 index 0000000000..e69de29bb2 diff --git a/src/app/+collection-page/edit-collection-page/collection-source/collection-source.component.ts b/src/app/+collection-page/edit-collection-page/collection-source/collection-source.component.ts new file mode 100644 index 0000000000..a6fc92eec3 --- /dev/null +++ b/src/app/+collection-page/edit-collection-page/collection-source/collection-source.component.ts @@ -0,0 +1,9 @@ +import { Component } from '@angular/core'; + +@Component({ + selector: 'ds-collection-source', + templateUrl: './collection-source.component.html', +}) +export class CollectionSourceComponent { + /* TODO: Implement Collection Edit - Content Source */ +} diff --git a/src/app/+collection-page/edit-collection-page/edit-collection-page.component.html b/src/app/+collection-page/edit-collection-page/edit-collection-page.component.html deleted file mode 100644 index c389c681ce..0000000000 --- a/src/app/+collection-page/edit-collection-page/edit-collection-page.component.html +++ /dev/null @@ -1,11 +0,0 @@ -
-
-
- - - {{'collection.edit.delete' - | translate}} -
-
-
diff --git a/src/app/+collection-page/edit-collection-page/edit-collection-page.component.scss b/src/app/+collection-page/edit-collection-page/edit-collection-page.component.scss deleted file mode 100644 index 8b13789179..0000000000 --- a/src/app/+collection-page/edit-collection-page/edit-collection-page.component.scss +++ /dev/null @@ -1 +0,0 @@ - diff --git a/src/app/+collection-page/edit-collection-page/edit-collection-page.component.ts b/src/app/+collection-page/edit-collection-page/edit-collection-page.component.ts index ba70bd26c6..21671fe112 100644 --- a/src/app/+collection-page/edit-collection-page/edit-collection-page.component.ts +++ b/src/app/+collection-page/edit-collection-page/edit-collection-page.component.ts @@ -2,24 +2,30 @@ import { Component } from '@angular/core'; import { ActivatedRoute, Router } from '@angular/router'; import { EditComColPageComponent } from '../../shared/comcol-forms/edit-comcol-page/edit-comcol-page.component'; import { Collection } from '../../core/shared/collection.model'; -import { CollectionDataService } from '../../core/data/collection-data.service'; +import { getCollectionPageRoute } from '../collection-page-routing.module'; /** * Component that represents the page where a user can edit an existing Collection */ @Component({ selector: 'ds-edit-collection', - styleUrls: ['./edit-collection-page.component.scss'], - templateUrl: './edit-collection-page.component.html' + templateUrl: '../../shared/comcol-forms/edit-comcol-page/edit-comcol-page.component.html' }) export class EditCollectionPageComponent extends EditComColPageComponent { - protected frontendURL = '/collections/'; + protected type = 'collection'; public constructor( - protected collectionDataService: CollectionDataService, protected router: Router, protected route: ActivatedRoute ) { - super(collectionDataService, router, route); + super(router, route); + } + + /** + * Get the collection page url + * @param collection The collection for which the url is requested + */ + getPageUrl(collection: Collection): string { + return getCollectionPageRoute(collection.id) } } diff --git a/src/app/+collection-page/edit-collection-page/edit-collection-page.module.ts b/src/app/+collection-page/edit-collection-page/edit-collection-page.module.ts new file mode 100644 index 0000000000..f442aae4d6 --- /dev/null +++ b/src/app/+collection-page/edit-collection-page/edit-collection-page.module.ts @@ -0,0 +1,32 @@ +import { NgModule } from '@angular/core'; +import { EditCollectionPageComponent } from './edit-collection-page.component'; +import { CommonModule } from '@angular/common'; +import { SharedModule } from '../../shared/shared.module'; +import { EditCollectionPageRoutingModule } from './edit-collection-page.routing.module'; +import { CollectionMetadataComponent } from './collection-metadata/collection-metadata.component'; +import { CollectionPageModule } from '../collection-page.module'; +import { CollectionRolesComponent } from './collection-roles/collection-roles.component'; +import { CollectionCurateComponent } from './collection-curate/collection-curate.component'; +import { CollectionSourceComponent } from './collection-source/collection-source.component'; + +/** + * Module that contains all components related to the Edit Collection page administrator functionality + */ +@NgModule({ + imports: [ + CommonModule, + SharedModule, + EditCollectionPageRoutingModule, + CollectionPageModule + ], + declarations: [ + EditCollectionPageComponent, + CollectionMetadataComponent, + CollectionRolesComponent, + CollectionCurateComponent, + CollectionSourceComponent + ] +}) +export class EditCollectionPageModule { + +} 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 new file mode 100644 index 0000000000..a3eab30d73 --- /dev/null +++ b/src/app/+collection-page/edit-collection-page/edit-collection-page.routing.module.ts @@ -0,0 +1,58 @@ +import { RouterModule } from '@angular/router'; +import { NgModule } from '@angular/core'; +import { EditCollectionPageComponent } from './edit-collection-page.component'; +import { CollectionPageResolver } from '../collection-page.resolver'; +import { CollectionMetadataComponent } from './collection-metadata/collection-metadata.component'; +import { CollectionRolesComponent } from './collection-roles/collection-roles.component'; +import { CollectionSourceComponent } from './collection-source/collection-source.component'; +import { CollectionCurateComponent } from './collection-curate/collection-curate.component'; + +/** + * Routing module that handles the routing for the Edit Collection page administrator functionality + */ +@NgModule({ + imports: [ + RouterModule.forChild([ + { + path: '', + component: EditCollectionPageComponent, + resolve: { + dso: CollectionPageResolver + }, + children: [ + { + path: '', + redirectTo: 'metadata', + pathMatch: 'full' + }, + { + path: 'metadata', + component: CollectionMetadataComponent, + data: { title: 'collection.edit.tabs.metadata.title' } + }, + { + path: 'roles', + component: CollectionRolesComponent, + data: { title: 'collection.edit.tabs.roles.title' } + }, + { + path: 'source', + component: CollectionSourceComponent, + data: { title: 'collection.edit.tabs.source.title' } + }, + { + path: 'curate', + component: CollectionCurateComponent, + data: { title: 'collection.edit.tabs.curate.title' } + } + ] + } + ]) + ], + providers: [ + CollectionPageResolver, + ] +}) +export class EditCollectionPageRoutingModule { + +} diff --git a/src/app/+community-page/community-page-routing.module.ts b/src/app/+community-page/community-page-routing.module.ts index cecd17ec10..df548e0617 100644 --- a/src/app/+community-page/community-page-routing.module.ts +++ b/src/app/+community-page/community-page-routing.module.ts @@ -5,7 +5,6 @@ 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'; -import { EditCommunityPageComponent } from './edit-community-page/edit-community-page.component'; import { CreateCommunityPageGuard } from './create-community-page/create-community-page.guard'; import { DeleteCommunityPageComponent } from './delete-community-page/delete-community-page.component'; import { URLCombiner } from '../core/url-combiner/url-combiner'; @@ -38,12 +37,8 @@ const COMMUNITY_EDIT_PATH = ':id/edit'; }, { path: COMMUNITY_EDIT_PATH, - pathMatch: 'full', - component: EditCommunityPageComponent, - canActivate: [AuthenticatedGuard], - resolve: { - dso: CommunityPageResolver - } + loadChildren: './edit-community-page/edit-community-page.module#EditCommunityPageModule', + canActivate: [AuthenticatedGuard] }, { path: ':id/delete', diff --git a/src/app/+community-page/community-page.module.ts b/src/app/+community-page/community-page.module.ts index 6d63cadcc8..534c96989e 100644 --- a/src/app/+community-page/community-page.module.ts +++ b/src/app/+community-page/community-page.module.ts @@ -9,7 +9,6 @@ import { CommunityPageRoutingModule } from './community-page-routing.module'; import {CommunityPageSubCommunityListComponent} from './sub-community-list/community-page-sub-community-list.component'; import { CreateCommunityPageComponent } from './create-community-page/create-community-page.component'; import { CommunityFormComponent } from './community-form/community-form.component'; -import { EditCommunityPageComponent } from './edit-community-page/edit-community-page.component'; import { DeleteCommunityPageComponent } from './delete-community-page/delete-community-page.component'; @NgModule({ @@ -23,9 +22,11 @@ import { DeleteCommunityPageComponent } from './delete-community-page/delete-com CommunityPageSubCollectionListComponent, CommunityPageSubCommunityListComponent, CreateCommunityPageComponent, - EditCommunityPageComponent, DeleteCommunityPageComponent, CommunityFormComponent + ], + exports: [ + CommunityFormComponent ] }) diff --git a/src/app/+community-page/edit-community-page/community-curate/community-curate.component.html b/src/app/+community-page/edit-community-page/community-curate/community-curate.component.html new file mode 100644 index 0000000000..e69de29bb2 diff --git a/src/app/+community-page/edit-community-page/community-curate/community-curate.component.ts b/src/app/+community-page/edit-community-page/community-curate/community-curate.component.ts new file mode 100644 index 0000000000..cf2d75ba6a --- /dev/null +++ b/src/app/+community-page/edit-community-page/community-curate/community-curate.component.ts @@ -0,0 +1,9 @@ +import { Component } from '@angular/core'; + +@Component({ + selector: 'ds-community-curate', + templateUrl: './community-curate.component.html', +}) +export class CommunityCurateComponent { + /* TODO: Implement Community Edit - Curate */ +} 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 new file mode 100644 index 0000000000..9a59be9067 --- /dev/null +++ b/src/app/+community-page/edit-community-page/community-metadata/community-metadata.component.html @@ -0,0 +1,4 @@ + +{{'community.edit.delete' + | translate}} diff --git a/src/app/+community-page/edit-community-page/community-metadata/community-metadata.component.ts b/src/app/+community-page/edit-community-page/community-metadata/community-metadata.component.ts new file mode 100644 index 0000000000..feecdf47c8 --- /dev/null +++ b/src/app/+community-page/edit-community-page/community-metadata/community-metadata.component.ts @@ -0,0 +1,21 @@ +import { Component } from '@angular/core'; +import { ComcolMetadataComponent } from '../../../shared/comcol-forms/edit-comcol-page/comcol-metadata/comcol-metadata.component'; +import { ActivatedRoute, Router } from '@angular/router'; +import { Community } from '../../../core/shared/community.model'; +import { CommunityDataService } from '../../../core/data/community-data.service'; + +@Component({ + selector: 'ds-community-metadata', + templateUrl: './community-metadata.component.html', +}) +export class CommunityMetadataComponent extends ComcolMetadataComponent { + protected frontendURL = '/communities/'; + + public constructor( + protected communityDataService: CommunityDataService, + protected router: Router, + protected route: ActivatedRoute + ) { + super(communityDataService, router, route); + } +} diff --git a/src/app/+community-page/edit-community-page/community-roles/community-roles.component.html b/src/app/+community-page/edit-community-page/community-roles/community-roles.component.html new file mode 100644 index 0000000000..e69de29bb2 diff --git a/src/app/+community-page/edit-community-page/community-roles/community-roles.component.ts b/src/app/+community-page/edit-community-page/community-roles/community-roles.component.ts new file mode 100644 index 0000000000..b6f84c8ba6 --- /dev/null +++ b/src/app/+community-page/edit-community-page/community-roles/community-roles.component.ts @@ -0,0 +1,9 @@ +import { Component } from '@angular/core'; + +@Component({ + selector: 'ds-community-roles', + templateUrl: './community-roles.component.html', +}) +export class CommunityRolesComponent { + /* TODO: Implement Community Edit - Roles */ +} diff --git a/src/app/+community-page/edit-community-page/edit-community-page.component.html b/src/app/+community-page/edit-community-page/edit-community-page.component.html deleted file mode 100644 index cedb771c14..0000000000 --- a/src/app/+community-page/edit-community-page/edit-community-page.component.html +++ /dev/null @@ -1,12 +0,0 @@ -
-
-
- - - {{'community.edit.delete' - | translate}} -
-
-
diff --git a/src/app/+community-page/edit-community-page/edit-community-page.component.scss b/src/app/+community-page/edit-community-page/edit-community-page.component.scss deleted file mode 100644 index 8b13789179..0000000000 --- a/src/app/+community-page/edit-community-page/edit-community-page.component.scss +++ /dev/null @@ -1 +0,0 @@ - diff --git a/src/app/+community-page/edit-community-page/edit-community-page.component.ts b/src/app/+community-page/edit-community-page/edit-community-page.component.ts index 9f49ac49dd..a8d4d32b7d 100644 --- a/src/app/+community-page/edit-community-page/edit-community-page.component.ts +++ b/src/app/+community-page/edit-community-page/edit-community-page.component.ts @@ -1,25 +1,31 @@ import { Component } from '@angular/core'; import { Community } from '../../core/shared/community.model'; -import { CommunityDataService } from '../../core/data/community-data.service'; import { ActivatedRoute, Router } from '@angular/router'; import { EditComColPageComponent } from '../../shared/comcol-forms/edit-comcol-page/edit-comcol-page.component'; +import { getCommunityPageRoute } from '../community-page-routing.module'; /** * Component that represents the page where a user can edit an existing Community */ @Component({ selector: 'ds-edit-community', - styleUrls: ['./edit-community-page.component.scss'], - templateUrl: './edit-community-page.component.html' + templateUrl: '../../shared/comcol-forms/edit-comcol-page/edit-comcol-page.component.html' }) export class EditCommunityPageComponent extends EditComColPageComponent { - protected frontendURL = '/communities/'; + protected type = 'community'; public constructor( - protected communityDataService: CommunityDataService, protected router: Router, protected route: ActivatedRoute ) { - super(communityDataService, router, route); + super(router, route); + } + + /** + * Get the community page url + * @param community The community for which the url is requested + */ + getPageUrl(community: Community): string { + return getCommunityPageRoute(community.id) } } diff --git a/src/app/+community-page/edit-community-page/edit-community-page.module.ts b/src/app/+community-page/edit-community-page/edit-community-page.module.ts new file mode 100644 index 0000000000..f9a1e11a14 --- /dev/null +++ b/src/app/+community-page/edit-community-page/edit-community-page.module.ts @@ -0,0 +1,30 @@ +import { NgModule } from '@angular/core'; +import { CommonModule } from '@angular/common'; +import { SharedModule } from '../../shared/shared.module'; +import { EditCommunityPageRoutingModule } from './edit-community-page.routing.module'; +import { CommunityPageModule } from '../community-page.module'; +import { EditCommunityPageComponent } from './edit-community-page.component'; +import { CommunityCurateComponent } from './community-curate/community-curate.component'; +import { CommunityMetadataComponent } from './community-metadata/community-metadata.component'; +import { CommunityRolesComponent } from './community-roles/community-roles.component'; + +/** + * Module that contains all components related to the Edit Community page administrator functionality + */ +@NgModule({ + imports: [ + CommonModule, + SharedModule, + EditCommunityPageRoutingModule, + CommunityPageModule + ], + declarations: [ + EditCommunityPageComponent, + CommunityCurateComponent, + CommunityMetadataComponent, + CommunityRolesComponent + ] +}) +export class EditCommunityPageModule { + +} 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 new file mode 100644 index 0000000000..527b3c018f --- /dev/null +++ b/src/app/+community-page/edit-community-page/edit-community-page.routing.module.ts @@ -0,0 +1,52 @@ +import { CommunityPageResolver } from '../community-page.resolver'; +import { EditCommunityPageComponent } from './edit-community-page.component'; +import { RouterModule } from '@angular/router'; +import { NgModule } from '@angular/core'; +import { CommunityMetadataComponent } from './community-metadata/community-metadata.component'; +import { CommunityRolesComponent } from './community-roles/community-roles.component'; +import { CommunityCurateComponent } from './community-curate/community-curate.component'; + +/** + * Routing module that handles the routing for the Edit Community page administrator functionality + */ +@NgModule({ + imports: [ + RouterModule.forChild([ + { + path: '', + component: EditCommunityPageComponent, + resolve: { + dso: CommunityPageResolver + }, + children: [ + { + path: '', + redirectTo: 'metadata', + pathMatch: 'full' + }, + { + path: 'metadata', + component: CommunityMetadataComponent, + data: { title: 'community.edit.tabs.metadata.title' } + }, + { + path: 'roles', + component: CommunityRolesComponent, + data: { title: 'community.edit.tabs.roles.title' } + }, + { + path: 'curate', + component: CommunityCurateComponent, + data: { title: 'community.edit.tabs.curate.title' } + } + ] + } + ]) + ], + providers: [ + CommunityPageResolver, + ] +}) +export class EditCommunityPageRoutingModule { + +} diff --git a/src/app/shared/comcol-forms/edit-comcol-page/comcol-metadata/comcol-metadata.component.ts b/src/app/shared/comcol-forms/edit-comcol-page/comcol-metadata/comcol-metadata.component.ts new file mode 100644 index 0000000000..3806da5a84 --- /dev/null +++ b/src/app/shared/comcol-forms/edit-comcol-page/comcol-metadata/comcol-metadata.component.ts @@ -0,0 +1,48 @@ +import { Component, OnInit } from '@angular/core'; +import { DSpaceObject } from '../../../../core/shared/dspace-object.model'; +import { Observable } from 'rxjs/internal/Observable'; +import { RemoteData } from '../../../../core/data/remote-data'; +import { ActivatedRoute, Router } from '@angular/router'; +import { first, map } from 'rxjs/operators'; +import { getSucceededRemoteData } from '../../../../core/shared/operators'; +import { isNotUndefined } from '../../../empty.util'; +import { DataService } from '../../../../core/data/data.service'; + +@Component({ + selector: 'ds-comcol-metadata', + template: '' +}) +export class ComcolMetadataComponent implements OnInit { + /** + * Frontend endpoint for this type of DSO + */ + protected frontendURL: string; + + public dsoRD$: Observable>; + + public constructor( + protected dsoDataService: DataService, + protected router: Router, + protected route: ActivatedRoute + ) { + } + + ngOnInit(): void { + this.dsoRD$ = this.route.parent.data.pipe(first(), map((data) => data.dso)); + } + + /** + * @param {TDomain} dso The updated version of the DSO + * Updates an existing DSO based on the submitted user data and navigates to the edited object's home page + */ + onSubmit(dso: TDomain) { + this.dsoDataService.update(dso) + .pipe(getSucceededRemoteData()) + .subscribe((dsoRD: RemoteData) => { + if (isNotUndefined(dsoRD)) { + const newUUID = dsoRD.payload.uuid; + this.router.navigate([this.frontendURL + newUUID]); + } + }); + } +} 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 new file mode 100644 index 0000000000..964fea35e3 --- /dev/null +++ b/src/app/shared/comcol-forms/edit-comcol-page/edit-comcol-page.component.html @@ -0,0 +1,24 @@ +
+
+
+

{{ 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 24181b5e61..7e3b9957e2 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 @@ -2,7 +2,7 @@ import { Component, OnInit } from '@angular/core'; import { Observable } from 'rxjs'; import { ActivatedRoute, Router } from '@angular/router'; import { RemoteData } from '../../../core/data/remote-data'; -import { isNotUndefined } from '../../empty.util'; +import { isNotEmpty, isNotUndefined } from '../../empty.util'; import { first, map } from 'rxjs/operators'; import { getSucceededRemoteData } from '../../../core/shared/operators'; import { DataService } from '../../../core/data/data.service'; @@ -13,41 +13,48 @@ import { DSpaceObject } from '../../../core/shared/dspace-object.model'; */ @Component({ selector: 'ds-edit-comcol', - template: '' + templateUrl: './edit-comcol-page.component.html' }) export class EditComColPageComponent implements OnInit { /** - * Frontend endpoint for this type of DSO + * The type of DSpaceObject (used to create i18n messages) */ - protected frontendURL: string; + protected type: string; + /** - * The initial DSO object + * The current page outlet string */ + public currentPage: string; + + /** + * All possible page outlet strings + */ + public pages: string[]; + public dsoRD$: Observable>; public constructor( - protected dsoDataService: DataService, protected router: Router, protected route: ActivatedRoute ) { + this.router.events.subscribe(() => { + this.currentPage = this.route.snapshot.firstChild.routeConfig.path; + }); } ngOnInit(): void { + this.pages = this.route.routeConfig.children + .map((child: any) => child.path) + .filter((path: string) => isNotEmpty(path)); // ignore reroutes this.dsoRD$ = this.route.data.pipe(first(), map((data) => data.dso)); } /** - * @param {TDomain} dso The updated version of the DSO - * Updates an existing DSO based on the submitted user data and navigates to the edited object's home page + * Get the dso's page url + * This method is expected to be overridden in the edit community/collection page components + * @param dso The DSpaceObject for which the url is requested */ - onSubmit(dso: TDomain) { - this.dsoDataService.update(dso) - .pipe(getSucceededRemoteData()) - .subscribe((dsoRD: RemoteData) => { - if (isNotUndefined(dsoRD)) { - const newUUID = dsoRD.payload.uuid; - this.router.navigate([this.frontendURL + newUUID]); - } - }); + getPageUrl(dso: TDomain): string { + return this.router.url; } } diff --git a/src/app/shared/shared.module.ts b/src/app/shared/shared.module.ts index 4654789b90..c134b89718 100644 --- a/src/app/shared/shared.module.ts +++ b/src/app/shared/shared.module.ts @@ -139,6 +139,7 @@ import { UserMenuComponent } from './auth-nav-menu/user-menu/user-menu.component import { ClaimedTaskActionsReturnToPoolComponent } from './mydspace-actions/claimed-task/return-to-pool/claimed-task-actions-return-to-pool.component'; import { ItemDetailPreviewFieldComponent } from './object-detail/my-dspace-result-detail-element/item-detail-preview/item-detail-preview-field/item-detail-preview-field.component'; import { AbstractTrackableComponent } from './trackable/abstract-trackable.component'; +import { ComcolMetadataComponent } from './comcol-forms/edit-comcol-page/comcol-metadata/comcol-metadata.component'; const MODULES = [ // Do NOT include UniversalModule, HttpModule, or JsonpModule here @@ -259,7 +260,8 @@ const COMPONENTS = [ TypedItemSearchResultListElementComponent, ItemTypeSwitcherComponent, BrowseByComponent, - AbstractTrackableComponent + AbstractTrackableComponent, + ComcolMetadataComponent ]; const ENTRY_COMPONENTS = [ From 09c6a167fb4edeca85fded87a694fd272645f989 Mon Sep 17 00:00:00 2001 From: Kristof De Langhe Date: Wed, 10 Jul 2019 17:43:01 +0200 Subject: [PATCH 03/26] 63669: Edit Col/Com Tabs Tests + JSDocs --- .../collection-metadata.component.spec.ts | 39 +++++++ .../edit-collection-page.component.spec.ts | 24 +++- .../community-metadata.component.spec.ts | 39 +++++++ .../edit-community-page.component.spec.ts | 24 +++- .../comcol-metadata.component.spec.ts | 108 ++++++++++++++++++ .../edit-comcol-page.component.spec.ts | 65 ++++------- .../edit-comcol-page.component.ts | 5 +- 7 files changed, 251 insertions(+), 53 deletions(-) create mode 100644 src/app/+collection-page/edit-collection-page/collection-metadata/collection-metadata.component.spec.ts create mode 100644 src/app/+community-page/edit-community-page/community-metadata/community-metadata.component.spec.ts create mode 100644 src/app/shared/comcol-forms/edit-comcol-page/comcol-metadata/comcol-metadata.component.spec.ts diff --git a/src/app/+collection-page/edit-collection-page/collection-metadata/collection-metadata.component.spec.ts b/src/app/+collection-page/edit-collection-page/collection-metadata/collection-metadata.component.spec.ts new file mode 100644 index 0000000000..67eab669d5 --- /dev/null +++ b/src/app/+collection-page/edit-collection-page/collection-metadata/collection-metadata.component.spec.ts @@ -0,0 +1,39 @@ +import { async, ComponentFixture, TestBed } from '@angular/core/testing'; +import { TranslateModule } from '@ngx-translate/core'; +import { SharedModule } from '../../../shared/shared.module'; +import { CommonModule } from '@angular/common'; +import { RouterTestingModule } from '@angular/router/testing'; +import { CollectionDataService } from '../../../core/data/collection-data.service'; +import { ActivatedRoute } from '@angular/router'; +import { of as observableOf } from 'rxjs/internal/observable/of'; +import { NO_ERRORS_SCHEMA } from '@angular/core'; +import { CollectionMetadataComponent } from './collection-metadata.component'; + +describe('CollectionMetadataComponent', () => { + let comp: CollectionMetadataComponent; + let fixture: ComponentFixture; + + beforeEach(async(() => { + TestBed.configureTestingModule({ + imports: [TranslateModule.forRoot(), SharedModule, CommonModule, RouterTestingModule], + declarations: [CollectionMetadataComponent], + providers: [ + { provide: CollectionDataService, useValue: {} }, + { provide: ActivatedRoute, useValue: { parent: { data: observableOf({ dso: { payload: {} } }) } } }, + ], + schemas: [NO_ERRORS_SCHEMA] + }).compileComponents(); + })); + + beforeEach(() => { + fixture = TestBed.createComponent(CollectionMetadataComponent); + comp = fixture.componentInstance; + fixture.detectChanges(); + }); + + describe('frontendURL', () => { + it('should have the right frontendURL set', () => { + expect((comp as any).frontendURL).toEqual('/collections/'); + }) + }); +}); 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 193cb293e4..9f915d2d7a 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 @@ -13,13 +13,29 @@ describe('EditCollectionPageComponent', () => { let comp: EditCollectionPageComponent; let fixture: ComponentFixture; + const routeStub = { + data: observableOf({ + dso: { payload: {} } + }), + routeConfig: { + children: [] + }, + snapshot: { + firstChild: { + routeConfig: { + path: 'mockUrl' + } + } + } + }; + beforeEach(async(() => { TestBed.configureTestingModule({ imports: [TranslateModule.forRoot(), SharedModule, CommonModule, RouterTestingModule], declarations: [EditCollectionPageComponent], providers: [ { provide: CollectionDataService, useValue: {} }, - { provide: ActivatedRoute, useValue: { data: observableOf({ dso: { payload: {} } }) } }, + { provide: ActivatedRoute, useValue: routeStub }, ], schemas: [NO_ERRORS_SCHEMA] }).compileComponents(); @@ -31,9 +47,9 @@ describe('EditCollectionPageComponent', () => { fixture.detectChanges(); }); - describe('frontendURL', () => { - it('should have the right frontendURL set', () => { - expect((comp as any).frontendURL).toEqual('/collections/'); + describe('type', () => { + it('should have the right type set', () => { + expect((comp as any).type).toEqual('collection'); }) }); }); diff --git a/src/app/+community-page/edit-community-page/community-metadata/community-metadata.component.spec.ts b/src/app/+community-page/edit-community-page/community-metadata/community-metadata.component.spec.ts new file mode 100644 index 0000000000..52ee73bfab --- /dev/null +++ b/src/app/+community-page/edit-community-page/community-metadata/community-metadata.component.spec.ts @@ -0,0 +1,39 @@ +import { async, ComponentFixture, TestBed } from '@angular/core/testing'; +import { TranslateModule } from '@ngx-translate/core'; +import { SharedModule } from '../../../shared/shared.module'; +import { CommonModule } from '@angular/common'; +import { RouterTestingModule } from '@angular/router/testing'; +import { ActivatedRoute } from '@angular/router'; +import { of as observableOf } from 'rxjs/internal/observable/of'; +import { NO_ERRORS_SCHEMA } from '@angular/core'; +import { CommunityMetadataComponent } from './community-metadata.component'; +import { CommunityDataService } from '../../../core/data/community-data.service'; + +describe('CommunityMetadataComponent', () => { + let comp: CommunityMetadataComponent; + let fixture: ComponentFixture; + + beforeEach(async(() => { + TestBed.configureTestingModule({ + imports: [TranslateModule.forRoot(), SharedModule, CommonModule, RouterTestingModule], + declarations: [CommunityMetadataComponent], + providers: [ + { provide: CommunityDataService, useValue: {} }, + { provide: ActivatedRoute, useValue: { parent: { data: observableOf({ dso: { payload: {} } }) } } }, + ], + schemas: [NO_ERRORS_SCHEMA] + }).compileComponents(); + })); + + beforeEach(() => { + fixture = TestBed.createComponent(CommunityMetadataComponent); + comp = fixture.componentInstance; + fixture.detectChanges(); + }); + + describe('frontendURL', () => { + it('should have the right frontendURL set', () => { + expect((comp as any).frontendURL).toEqual('/communities/'); + }) + }); +}); 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 54f2133ce7..b61924dd00 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 @@ -13,13 +13,29 @@ describe('EditCommunityPageComponent', () => { let comp: EditCommunityPageComponent; let fixture: ComponentFixture; + const routeStub = { + data: observableOf({ + dso: { payload: {} } + }), + routeConfig: { + children: [] + }, + snapshot: { + firstChild: { + routeConfig: { + path: 'mockUrl' + } + } + } + }; + beforeEach(async(() => { TestBed.configureTestingModule({ imports: [TranslateModule.forRoot(), SharedModule, CommonModule, RouterTestingModule], declarations: [EditCommunityPageComponent], providers: [ { provide: CommunityDataService, useValue: {} }, - { provide: ActivatedRoute, useValue: { data: observableOf({ dso: { payload: {} } }) } }, + { provide: ActivatedRoute, useValue: routeStub }, ], schemas: [NO_ERRORS_SCHEMA] }).compileComponents(); @@ -31,9 +47,9 @@ describe('EditCommunityPageComponent', () => { fixture.detectChanges(); }); - describe('frontendURL', () => { - it('should have the right frontendURL set', () => { - expect((comp as any).frontendURL).toEqual('/communities/'); + describe('type', () => { + it('should have the right type set', () => { + expect((comp as any).type).toEqual('community'); }) }); }); diff --git a/src/app/shared/comcol-forms/edit-comcol-page/comcol-metadata/comcol-metadata.component.spec.ts b/src/app/shared/comcol-forms/edit-comcol-page/comcol-metadata/comcol-metadata.component.spec.ts new file mode 100644 index 0000000000..26002d555d --- /dev/null +++ b/src/app/shared/comcol-forms/edit-comcol-page/comcol-metadata/comcol-metadata.component.spec.ts @@ -0,0 +1,108 @@ +import { DSpaceObject } from '../../../../core/shared/dspace-object.model'; +import { async, ComponentFixture, TestBed } from '@angular/core/testing'; +import { CommunityDataService } from '../../../../core/data/community-data.service'; +import { ActivatedRoute, Router } from '@angular/router'; +import { Community } from '../../../../core/shared/community.model'; +import { of as observableOf } from 'rxjs/internal/observable/of'; +import { RemoteData } from '../../../../core/data/remote-data'; +import { TranslateModule } from '@ngx-translate/core'; +import { SharedModule } from '../../../shared.module'; +import { CommonModule } from '@angular/common'; +import { RouterTestingModule } from '@angular/router/testing'; +import { DataService } from '../../../../core/data/data.service'; +import { NO_ERRORS_SCHEMA } from '@angular/core'; +import { ComcolMetadataComponent } from './comcol-metadata.component'; + +describe('ComColMetadataComponent', () => { + let comp: ComcolMetadataComponent; + let fixture: ComponentFixture>; + let dsoDataService: CommunityDataService; + let router: Router; + + let community; + let newCommunity; + let communityDataServiceStub; + let routerStub; + let routeStub; + + function initializeVars() { + community = Object.assign(new Community(), { + uuid: 'a20da287-e174-466a-9926-f66b9300d347', + metadata: [{ + key: 'dc.title', + value: 'test community' + }] + }); + + newCommunity = Object.assign(new Community(), { + uuid: '1ff59938-a69a-4e62-b9a4-718569c55d48', + metadata: [{ + key: 'dc.title', + value: 'new community' + }] + }); + + communityDataServiceStub = { + update: (com, uuid?) => observableOf(new RemoteData(false, false, true, undefined, newCommunity)) + + }; + + routerStub = { + navigate: (commands) => commands + }; + + routeStub = { + parent: { + data: observableOf(community) + } + }; + + } + + beforeEach(async(() => { + initializeVars(); + TestBed.configureTestingModule({ + imports: [TranslateModule.forRoot(), SharedModule, CommonModule, RouterTestingModule], + providers: [ + { provide: DataService, useValue: communityDataServiceStub }, + { provide: Router, useValue: routerStub }, + { provide: ActivatedRoute, useValue: routeStub }, + ], + schemas: [NO_ERRORS_SCHEMA] + }).compileComponents(); + })); + + beforeEach(() => { + fixture = TestBed.createComponent(ComcolMetadataComponent); + comp = fixture.componentInstance; + fixture.detectChanges(); + dsoDataService = (comp as any).dsoDataService; + router = (comp as any).router; + }); + + describe('onSubmit', () => { + let data; + beforeEach(() => { + data = Object.assign(new Community(), { + metadata: [{ + key: 'dc.title', + value: 'test' + }] + }); + }); + it('should navigate when successful', () => { + spyOn(router, 'navigate'); + comp.onSubmit(data); + fixture.detectChanges(); + expect(router.navigate).toHaveBeenCalled(); + }); + + it('should not navigate on failure', () => { + spyOn(router, 'navigate'); + spyOn(dsoDataService, 'update').and.returnValue(observableOf(new RemoteData(true, true, false, undefined, newCommunity))); + comp.onSubmit(data); + fixture.detectChanges(); + expect(router.navigate).not.toHaveBeenCalled(); + }); + }); +}); diff --git a/src/app/shared/comcol-forms/edit-comcol-page/edit-comcol-page.component.spec.ts b/src/app/shared/comcol-forms/edit-comcol-page/edit-comcol-page.component.spec.ts index 75b7fe40e7..8d1023e66d 100644 --- a/src/app/shared/comcol-forms/edit-comcol-page/edit-comcol-page.component.spec.ts +++ b/src/app/shared/comcol-forms/edit-comcol-page/edit-comcol-page.component.spec.ts @@ -1,9 +1,7 @@ import { async, ComponentFixture, TestBed } from '@angular/core/testing'; -import { CommunityDataService } from '../../../core/data/community-data.service'; import { ActivatedRoute, Router } from '@angular/router'; import { TranslateModule } from '@ngx-translate/core'; import { of as observableOf } from 'rxjs'; -import { RemoteData } from '../../../core/data/remote-data'; import { Community } from '../../../core/shared/community.model'; import { SharedModule } from '../../shared.module'; import { CommonModule } from '@angular/common'; @@ -11,17 +9,13 @@ import { RouterTestingModule } from '@angular/router/testing'; import { NO_ERRORS_SCHEMA } from '@angular/core'; import { DSpaceObject } from '../../../core/shared/dspace-object.model'; import { EditComColPageComponent } from './edit-comcol-page.component'; -import { DataService } from '../../../core/data/data.service'; describe('EditComColPageComponent', () => { let comp: EditComColPageComponent; let fixture: ComponentFixture>; - let dsoDataService: CommunityDataService; let router: Router; let community; - let newCommunity; - let communityDataServiceStub; let routerStub; let routeStub; @@ -34,25 +28,26 @@ describe('EditComColPageComponent', () => { }] }); - newCommunity = Object.assign(new Community(), { - uuid: '1ff59938-a69a-4e62-b9a4-718569c55d48', - metadata: [{ - key: 'dc.title', - value: 'new community' - }] - }); - - communityDataServiceStub = { - update: (com, uuid?) => observableOf(new RemoteData(false, false, true, undefined, newCommunity)) - - }; - routerStub = { - navigate: (commands) => commands + navigate: (commands) => commands, + events: observableOf({}), + url: 'mockUrl' }; routeStub = { - data: observableOf(community) + data: observableOf({ + dso: community + }), + routeConfig: { + children: [] + }, + snapshot: { + firstChild: { + routeConfig: { + path: 'mockUrl' + } + } + } }; } @@ -62,7 +57,6 @@ describe('EditComColPageComponent', () => { TestBed.configureTestingModule({ imports: [TranslateModule.forRoot(), SharedModule, CommonModule, RouterTestingModule], providers: [ - { provide: DataService, useValue: communityDataServiceStub }, { provide: Router, useValue: routerStub }, { provide: ActivatedRoute, useValue: routeStub }, ], @@ -74,33 +68,16 @@ describe('EditComColPageComponent', () => { fixture = TestBed.createComponent(EditComColPageComponent); comp = fixture.componentInstance; fixture.detectChanges(); - dsoDataService = (comp as any).dsoDataService; router = (comp as any).router; }); - describe('onSubmit', () => { - let data; + describe('getPageUrl', () => { + let url; beforeEach(() => { - data = Object.assign(new Community(), { - metadata: [{ - key: 'dc.title', - value: 'test' - }] - }); + url = comp.getPageUrl(community); }); - it('should navigate when successful', () => { - spyOn(router, 'navigate'); - comp.onSubmit(data); - fixture.detectChanges(); - expect(router.navigate).toHaveBeenCalled(); - }); - - it('should not navigate on failure', () => { - spyOn(router, 'navigate'); - spyOn(dsoDataService, 'update').and.returnValue(observableOf(new RemoteData(true, true, false, undefined, newCommunity))); - comp.onSubmit(data); - fixture.detectChanges(); - expect(router.navigate).not.toHaveBeenCalled(); + it('should return the current url as a fallback', () => { + expect(url).toEqual(routerStub.url); }); }); }); 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 7e3b9957e2..9face94abd 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 @@ -13,7 +13,7 @@ import { DSpaceObject } from '../../../core/shared/dspace-object.model'; */ @Component({ selector: 'ds-edit-comcol', - templateUrl: './edit-comcol-page.component.html' + template: '' }) export class EditComColPageComponent implements OnInit { /** @@ -31,6 +31,9 @@ export class EditComColPageComponent implements On */ public pages: string[]; + /** + * The DSO to render the edit page for + */ public dsoRD$: Observable>; public constructor( From 12f57e397533cfdb7e713f04bc8376eaaffd1a4f Mon Sep 17 00:00:00 2001 From: Kristof De Langhe Date: Thu, 11 Jul 2019 12:05:28 +0200 Subject: [PATCH 04/26] 63669: Missing JSDocs --- .../collection-curate/collection-curate.component.ts | 3 +++ .../collection-metadata/collection-metadata.component.ts | 3 +++ .../collection-roles/collection-roles.component.ts | 3 +++ .../collection-source/collection-source.component.ts | 3 +++ .../community-curate/community-curate.component.ts | 3 +++ .../community-metadata/community-metadata.component.ts | 3 +++ .../community-roles/community-roles.component.ts | 3 +++ 7 files changed, 21 insertions(+) diff --git a/src/app/+collection-page/edit-collection-page/collection-curate/collection-curate.component.ts b/src/app/+collection-page/edit-collection-page/collection-curate/collection-curate.component.ts index 1445c343fe..d7deaea982 100644 --- a/src/app/+collection-page/edit-collection-page/collection-curate/collection-curate.component.ts +++ b/src/app/+collection-page/edit-collection-page/collection-curate/collection-curate.component.ts @@ -1,5 +1,8 @@ import { Component } from '@angular/core'; +/** + * Component for managing a collection's curation tasks + */ @Component({ selector: 'ds-collection-curate', templateUrl: './collection-curate.component.html', diff --git a/src/app/+collection-page/edit-collection-page/collection-metadata/collection-metadata.component.ts b/src/app/+collection-page/edit-collection-page/collection-metadata/collection-metadata.component.ts index 350ccc0b46..3a9d9c8af5 100644 --- a/src/app/+collection-page/edit-collection-page/collection-metadata/collection-metadata.component.ts +++ b/src/app/+collection-page/edit-collection-page/collection-metadata/collection-metadata.component.ts @@ -4,6 +4,9 @@ import { Collection } from '../../../core/shared/collection.model'; import { CollectionDataService } from '../../../core/data/collection-data.service'; import { ActivatedRoute, Router } from '@angular/router'; +/** + * Component for editing a collection's metadata + */ @Component({ selector: 'ds-collection-metadata', templateUrl: './collection-metadata.component.html', diff --git a/src/app/+collection-page/edit-collection-page/collection-roles/collection-roles.component.ts b/src/app/+collection-page/edit-collection-page/collection-roles/collection-roles.component.ts index ffa3f7709c..39f72fd2ce 100644 --- a/src/app/+collection-page/edit-collection-page/collection-roles/collection-roles.component.ts +++ b/src/app/+collection-page/edit-collection-page/collection-roles/collection-roles.component.ts @@ -1,5 +1,8 @@ import { Component } from '@angular/core'; +/** + * Component for managing a collection's roles + */ @Component({ selector: 'ds-collection-roles', templateUrl: './collection-roles.component.html', diff --git a/src/app/+collection-page/edit-collection-page/collection-source/collection-source.component.ts b/src/app/+collection-page/edit-collection-page/collection-source/collection-source.component.ts index a6fc92eec3..6ec5be884d 100644 --- a/src/app/+collection-page/edit-collection-page/collection-source/collection-source.component.ts +++ b/src/app/+collection-page/edit-collection-page/collection-source/collection-source.component.ts @@ -1,5 +1,8 @@ import { Component } from '@angular/core'; +/** + * Component for managing the content source of the collection + */ @Component({ selector: 'ds-collection-source', templateUrl: './collection-source.component.html', diff --git a/src/app/+community-page/edit-community-page/community-curate/community-curate.component.ts b/src/app/+community-page/edit-community-page/community-curate/community-curate.component.ts index cf2d75ba6a..6151d3fe9a 100644 --- a/src/app/+community-page/edit-community-page/community-curate/community-curate.component.ts +++ b/src/app/+community-page/edit-community-page/community-curate/community-curate.component.ts @@ -1,5 +1,8 @@ import { Component } from '@angular/core'; +/** + * Component for managing a community's curation tasks + */ @Component({ selector: 'ds-community-curate', templateUrl: './community-curate.component.html', diff --git a/src/app/+community-page/edit-community-page/community-metadata/community-metadata.component.ts b/src/app/+community-page/edit-community-page/community-metadata/community-metadata.component.ts index feecdf47c8..c57c74175d 100644 --- a/src/app/+community-page/edit-community-page/community-metadata/community-metadata.component.ts +++ b/src/app/+community-page/edit-community-page/community-metadata/community-metadata.component.ts @@ -4,6 +4,9 @@ import { ActivatedRoute, Router } from '@angular/router'; import { Community } from '../../../core/shared/community.model'; import { CommunityDataService } from '../../../core/data/community-data.service'; +/** + * Component for editing a community's metadata + */ @Component({ selector: 'ds-community-metadata', templateUrl: './community-metadata.component.html', diff --git a/src/app/+community-page/edit-community-page/community-roles/community-roles.component.ts b/src/app/+community-page/edit-community-page/community-roles/community-roles.component.ts index b6f84c8ba6..afa1fe14d1 100644 --- a/src/app/+community-page/edit-community-page/community-roles/community-roles.component.ts +++ b/src/app/+community-page/edit-community-page/community-roles/community-roles.component.ts @@ -1,5 +1,8 @@ import { Component } from '@angular/core'; +/** + * Component for managing a community's roles + */ @Component({ selector: 'ds-community-roles', templateUrl: './community-roles.component.html', From a2695edbac5ea198146c50c082584d1e1cd82122 Mon Sep 17 00:00:00 2001 From: Kristof De Langhe Date: Tue, 1 Oct 2019 14:42:25 +0200 Subject: [PATCH 05/26] 65240: Add community/collection logo on create/edit pages --- resources/i18n/en.json5 | 8 ++ .../collection-form.component.ts | 36 ++++- .../create-collection-page.component.html | 2 +- .../edit-collection-page.component.html | 4 +- .../community-form.component.ts | 36 ++++- .../create-community-page.component.html | 2 +- .../edit-community-page.component.html | 3 +- .../my-dspace-new-submission.component.ts | 3 +- src/app/core/data/comcol-data.service.ts | 12 +- src/app/core/shared/hal-endpoint.service.ts | 4 +- .../comcol-form/comcol-form.component.html | 11 ++ .../comcol-form/comcol-form.component.ts | 127 ++++++++++++++++-- .../create-comcol-page.component.ts | 37 ++++- .../edit-comcol-page.component.ts | 33 ++++- .../shared/uploader/uploader-options.model.ts | 2 + .../shared/uploader/uploader.component.html | 6 +- src/app/shared/uploader/uploader.component.ts | 7 +- .../form/submission-form.component.ts | 3 +- 18 files changed, 300 insertions(+), 36 deletions(-) diff --git a/resources/i18n/en.json5 b/resources/i18n/en.json5 index 6570d5bf3a..cc6d49814b 100644 --- a/resources/i18n/en.json5 +++ b/resources/i18n/en.json5 @@ -130,6 +130,10 @@ "collection.delete.text": "Are you sure you want to delete collection \"{{ dso }}\"", "collection.edit.delete": "Delete this collection", "collection.edit.head": "Edit Collection", + "collection.edit.logo.label": "Collection logo", + "collection.edit.logo.notifications.error": "Uploading Collection logo failed. Please verify the content before retrying.", + "collection.edit.logo.notifications.success": "Upload Collection logo successful.", + "collection.edit.logo.upload": "Drop a Collection Logo to upload", "collection.form.abstract": "Short Description", "collection.form.description": "Introductory text (HTML)", "collection.form.errors.title.required": "Please enter a collection name", @@ -153,6 +157,10 @@ "community.delete.text": "Are you sure you want to delete community \"{{ dso }}\"", "community.edit.delete": "Delete this community", "community.edit.head": "Edit Community", + "community.edit.logo.label": "Community logo", + "community.edit.logo.notifications.error": "Uploading Community logo failed. Please verify the content before retrying.", + "community.edit.logo.notifications.success": "Upload Community logo successful.", + "community.edit.logo.upload": "Drop a Community Logo to upload", "community.form.abstract": "Short Description", "community.form.description": "Introductory text (HTML)", "community.form.errors.title.required": "Please enter a community name", diff --git a/src/app/+collection-page/collection-form/collection-form.component.ts b/src/app/+collection-page/collection-form/collection-form.component.ts index 21b494f41f..e3ca07a2ad 100644 --- a/src/app/+collection-page/collection-form/collection-form.component.ts +++ b/src/app/+collection-page/collection-form/collection-form.component.ts @@ -1,9 +1,14 @@ import { Component, Input } from '@angular/core'; -import { DynamicInputModel, DynamicTextAreaModel } from '@ng-dynamic-forms/core'; +import { DynamicFormService, DynamicInputModel, DynamicTextAreaModel } from '@ng-dynamic-forms/core'; import { DynamicFormControlModel } from '@ng-dynamic-forms/core/src/model/dynamic-form-control.model'; import { Collection } from '../../core/shared/collection.model'; import { ComColFormComponent } from '../../shared/comcol-forms/comcol-form/comcol-form.component'; import { NormalizedCollection } from '../../core/cache/models/normalized-collection.model'; +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'; +import { AuthService } from '../../core/auth/auth.service'; /** * Form used for creating and editing collections @@ -19,6 +24,26 @@ export class CollectionFormComponent extends ComColFormComponent { */ @Input() dso: Collection = new Collection(); + /** + * i18n key for the logo's label + */ + protected logoLabelMsg = 'collection.edit.logo.label'; + + /** + * i18n key for the logo's drop message + */ + protected logoDropMsg = 'collection.edit.logo.upload'; + + /** + * i18n key for the logo's upload success message + */ + protected logoSuccessMsg = 'collection.edit.logo.notifications.success'; + + /** + * i18n key for the logo's upload error message + */ + protected logoErrorMsg = 'collection.edit.logo.notifications.error'; + /** * @type {Collection.type} This is a collection-type form */ @@ -65,4 +90,13 @@ export class CollectionFormComponent extends ComColFormComponent { name: 'dc.description.provenance', }), ]; + + public constructor(protected location: Location, + protected formService: DynamicFormService, + protected translate: TranslateService, + protected notificationsService: NotificationsService, + protected authService: AuthService, + protected dsoService: CommunityDataService) { + super(location, formService, translate, notificationsService, authService); + } } diff --git a/src/app/+collection-page/create-collection-page/create-collection-page.component.html b/src/app/+collection-page/create-collection-page/create-collection-page.component.html index b3f4361bc6..dc5c5b186a 100644 --- a/src/app/+collection-page/create-collection-page/create-collection-page.component.html +++ b/src/app/+collection-page/create-collection-page/create-collection-page.component.html @@ -4,5 +4,5 @@

{{'collection.create.sub-head' | translate:{ parent: (parentRD$| async)?.payload.name } }}

- + diff --git a/src/app/+collection-page/edit-collection-page/edit-collection-page.component.html b/src/app/+collection-page/edit-collection-page/edit-collection-page.component.html index c389c681ce..b4429d0f7c 100644 --- a/src/app/+collection-page/edit-collection-page/edit-collection-page.component.html +++ b/src/app/+collection-page/edit-collection-page/edit-collection-page.component.html @@ -2,7 +2,9 @@
- + {{'collection.edit.delete' | translate}} 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 17d601e251..29149f4d01 100644 --- a/src/app/+community-page/community-form/community-form.component.ts +++ b/src/app/+community-page/community-form/community-form.component.ts @@ -1,9 +1,14 @@ import { Component, Input } from '@angular/core'; -import { DynamicInputModel, DynamicTextAreaModel } from '@ng-dynamic-forms/core'; +import { DynamicFormService, DynamicInputModel, DynamicTextAreaModel } from '@ng-dynamic-forms/core'; import { DynamicFormControlModel } from '@ng-dynamic-forms/core/src/model/dynamic-form-control.model'; import { Community } from '../../core/shared/community.model'; import { ResourceType } from '../../core/shared/resource-type'; 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'; +import { AuthService } from '../../core/auth/auth.service'; /** * Form used for creating and editing communities @@ -19,6 +24,26 @@ export class CommunityFormComponent extends ComColFormComponent { */ @Input() dso: Community = new Community(); + /** + * i18n key for the logo's label + */ + protected logoLabelMsg = 'community.edit.logo.label'; + + /** + * i18n key for the logo's drop message + */ + protected logoDropMsg = 'community.edit.logo.upload'; + + /** + * i18n key for the logo's upload success message + */ + protected logoSuccessMsg = 'community.edit.logo.notifications.success'; + + /** + * i18n key for the logo's upload error message + */ + protected logoErrorMsg = 'community.edit.logo.notifications.error'; + /** * @type {Community.type} This is a community-type form */ @@ -57,4 +82,13 @@ export class CommunityFormComponent extends ComColFormComponent { name: 'dc.description.tableofcontents', }), ]; + + public constructor(protected location: Location, + protected formService: DynamicFormService, + protected translate: TranslateService, + protected notificationsService: NotificationsService, + protected authService: AuthService, + protected dsoService: CommunityDataService) { + super(location, formService, translate, notificationsService, authService); + } } 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 55a080d2a1..c1b0cf5971 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,5 @@
- + diff --git a/src/app/+community-page/edit-community-page/edit-community-page.component.html b/src/app/+community-page/edit-community-page/edit-community-page.component.html index cedb771c14..ba3a3ce32b 100644 --- a/src/app/+community-page/edit-community-page/edit-community-page.component.html +++ b/src/app/+community-page/edit-community-page/edit-community-page.component.html @@ -3,7 +3,8 @@
+ [dso]="(dsoRD$ | async)?.payload" + (finishUpload)="navigateToHomePage()"> {{'community.edit.delete' | translate}} diff --git a/src/app/+my-dspace-page/my-dspace-new-submission/my-dspace-new-submission.component.ts b/src/app/+my-dspace-page/my-dspace-new-submission/my-dspace-new-submission.component.ts index 938a1ec899..26ed4110b3 100644 --- a/src/app/+my-dspace-page/my-dspace-new-submission/my-dspace-new-submission.component.ts +++ b/src/app/+my-dspace-page/my-dspace-new-submission/my-dspace-new-submission.component.ts @@ -34,7 +34,8 @@ export class MyDSpaceNewSubmissionComponent implements OnDestroy, OnInit { url: '', authToken: null, disableMultipart: false, - itemAlias: null + itemAlias: null, + autoUpload: true }; /** diff --git a/src/app/core/data/comcol-data.service.ts b/src/app/core/data/comcol-data.service.ts index 68eb3e4880..42c414a8a7 100644 --- a/src/app/core/data/comcol-data.service.ts +++ b/src/app/core/data/comcol-data.service.ts @@ -1,4 +1,4 @@ -import { distinctUntilChanged, filter, map, mergeMap, share, take, tap } from 'rxjs/operators'; +import { distinctUntilChanged, filter, map, mergeMap, share, switchMap, take, tap } from 'rxjs/operators'; import { merge as observableMerge, Observable, throwError as observableThrowError } from 'rxjs'; import { isEmpty, isNotEmpty } from '../../shared/empty.util'; import { NormalizedCommunity } from '../cache/models/normalized-community.model'; @@ -57,4 +57,14 @@ export abstract class ComColDataService extends DataS return observableMerge(errorResponses, successResponses).pipe(distinctUntilChanged(), share()); } } + + /** + * Get the endpoint for the community or collection's logo + * @param id The community or collection's ID + */ + public getLogoEndpoint(id: string): Observable { + return this.halService.getEndpoint(this.linkPath).pipe( + switchMap((href: string) => this.halService.getEndpoint('logo', `${href}/${id}`)) + ) + } } diff --git a/src/app/core/shared/hal-endpoint.service.ts b/src/app/core/shared/hal-endpoint.service.ts index a93d54db64..117cc074ca 100644 --- a/src/app/core/shared/hal-endpoint.service.ts +++ b/src/app/core/shared/hal-endpoint.service.ts @@ -43,8 +43,8 @@ export class HALEndpointService { ); } - public getEndpoint(linkPath: string): Observable { - return this.getEndpointAt(this.getRootHref(), ...linkPath.split('/')); + public getEndpoint(linkPath: string, startHref?: string): Observable { + return this.getEndpointAt(startHref || this.getRootHref(), ...linkPath.split('/')); } /** 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 6c67937063..8e1e280b22 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 @@ -1,3 +1,14 @@ +
+ + + +
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 8d1d5c1dca..7f59b73c6a 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,4 @@ -import { Component, EventEmitter, Input, OnInit, Output } from '@angular/core'; +import { Component, EventEmitter, Input, OnDestroy, OnInit, Output, ViewChild } from '@angular/core'; import { Location } from '@angular/common'; import { DynamicFormService, @@ -10,8 +10,16 @@ import { TranslateService } from '@ngx-translate/core'; import { DSpaceObject } from '../../../core/shared/dspace-object.model'; import { MetadataMap, MetadataValue } from '../../../core/shared/metadata.models'; import { ResourceType } from '../../../core/shared/resource-type'; -import { isNotEmpty } from '../../empty.util'; +import { hasValue, isNotEmpty, isUndefined } from '../../empty.util'; +import { UploaderOptions } from '../../uploader/uploader-options.model'; +import { NotificationsService } from '../../notifications/notifications.service'; +import { ComColDataService } from '../../../core/data/comcol-data.service'; +import { Subscription } from 'rxjs/internal/Subscription'; +import { AuthService } from '../../../core/auth/auth.service'; import { Community } from '../../../core/shared/community.model'; +import { Collection } from '../../../core/shared/collection.model'; +import { UploaderComponent } from '../../uploader/uploader.component'; +import { FileUploader } from 'ng2-file-upload'; /** * A form for creating and editing Communities or Collections @@ -21,12 +29,38 @@ import { Community } from '../../../core/shared/community.model'; styleUrls: ['./comcol-form.component.scss'], templateUrl: './comcol-form.component.html' }) -export class ComColFormComponent implements OnInit { +export class ComColFormComponent implements OnInit, OnDestroy { + + /** + * The logo uploader component + */ + @ViewChild(UploaderComponent) uploaderComponent: UploaderComponent; + /** * DSpaceObject that the form represents */ @Input() dso: T; + /** + * i18n key for the logo's label + */ + protected logoLabelMsg: string; + + /** + * i18n key for the logo's drop message + */ + protected logoDropMsg: string; + + /** + * i18n key for the logo's upload success message + */ + protected logoSuccessMsg: string; + + /** + * i18n key for the logo's upload error message + */ + protected logoErrorMsg: string; + /** * Type of DSpaceObject that the form represents */ @@ -53,14 +87,46 @@ export class ComColFormComponent implements OnInit { formGroup: FormGroup; /** - * Emits DSO when the form is submitted - * @type {EventEmitter} + * The uploader configuration options + * @type {UploaderOptions} */ - @Output() submitForm: EventEmitter = new EventEmitter(); + uploadFilesOptions: UploaderOptions = { + url: '', + authToken: null, + disableMultipart: true, + itemAlias: null, + autoUpload: false + }; - public constructor(private location: Location, - private formService: DynamicFormService, - private translate: TranslateService) { + /** + * Emits DSO and Uploader when the form is submitted + */ + @Output() submitForm: EventEmitter<{ + dso: T, + uploader: FileUploader + }> = new EventEmitter(); + + /** + * Fires an event when the logo has finished uploading (with or without errors) + */ + @Output() finishUpload: EventEmitter = new EventEmitter(); + + /** + * Array to track all subscriptions and unsubscribe them onDestroy + * @type {Array} + */ + protected subs: Subscription[] = []; + + /** + * The service used to fetch from or send data to + */ + protected dsoService: ComColDataService; + + public constructor(protected location: Location, + protected formService: DynamicFormService, + protected translate: TranslateService, + protected notificationsService: NotificationsService, + protected authService: AuthService) { } ngOnInit(): void { @@ -76,6 +142,19 @@ export class ComColFormComponent implements OnInit { .subscribe(() => { this.updateFieldTranslations(); }); + + if (hasValue(this.dso.id)) { + this.subs.push( + this.dsoService.getLogoEndpoint(this.dso.id).subscribe((href: string) => { + this.uploadFilesOptions.url = href; + this.uploadFilesOptions.authToken = this.authService.buildAuthHeader(); + }) + ); + } else { + // Set a placeholder URL to not break the uploader component. This will be replaced once the object is created. + this.uploadFilesOptions.url = 'placeholder'; + this.uploadFilesOptions.authToken = this.authService.buildAuthHeader(); + } } /** @@ -102,7 +181,10 @@ export class ComColFormComponent implements OnInit { }, type: Community.type }); - this.submitForm.emit(updatedDSO); + this.submitForm.emit({ + dso: updatedDSO, + uploader: this.uploaderComponent.uploader + }); } /** @@ -122,7 +204,32 @@ export class ComColFormComponent implements OnInit { ); } + /** + * The request was successful, display a success notification + */ + public onCompleteItem() { + this.notificationsService.success(null, this.translate.get(this.logoSuccessMsg)); + this.finishUpload.emit(); + } + + /** + * The request was unsuccessful, display an error notification + */ + public onUploadError() { + this.notificationsService.error(null, this.translate.get(this.logoErrorMsg)); + this.finishUpload.emit(); + } + onCancel() { this.location.back(); } + + /** + * Unsubscribe from open subscriptions + */ + ngOnDestroy(): void { + this.subs + .filter((subscription) => hasValue(subscription)) + .forEach((subscription) => subscription.unsubscribe()); + } } 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 e07f2a5a0a..baa05ac5e7 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 @@ -5,11 +5,12 @@ import { Observable } from 'rxjs'; import { RouteService } from '../../../core/services/route.service'; import { Router } from '@angular/router'; import { RemoteData } from '../../../core/data/remote-data'; -import { isNotEmpty, isNotUndefined } from '../../empty.util'; +import { hasValue, isNotEmpty, isNotUndefined } from '../../empty.util'; import { take } from 'rxjs/operators'; import { getSucceededRemoteData } from '../../../core/shared/operators'; import { DSpaceObject } from '../../../core/shared/dspace-object.model'; import { DataService } from '../../../core/data/data.service'; +import { ComColDataService } from '../../../core/data/comcol-data.service'; /** * Component representing the create page for communities and collections @@ -34,8 +35,13 @@ export class CreateComColPageComponent implements */ public parentRD$: Observable>; + /** + * The UUID of the newly created object + */ + private newUUID: string; + public constructor( - protected dsoDataService: DataService, + protected dsoDataService: ComColDataService, protected parentDataService: CommunityDataService, protected routeService: RouteService, protected router: Router @@ -53,20 +59,39 @@ export class CreateComColPageComponent implements } /** - * @param {TDomain} dso The updated version of the DSO * Creates a new DSO based on the submitted user data and navigates to the new object's home page + * @param event The event returned by the community/collection form. Contains the new dso and logo uploader */ - onSubmit(dso: TDomain) { + onSubmit(event) { + const dso = event.dso; + const uploader = event.uploader; + this.parentUUID$.pipe(take(1)).subscribe((uuid: string) => { this.dsoDataService.create(dso, uuid) .pipe(getSucceededRemoteData()) .subscribe((dsoRD: RemoteData) => { if (isNotUndefined(dsoRD)) { - const newUUID = dsoRD.payload.uuid; - this.router.navigate([this.frontendURL + newUUID]); + this.newUUID = dsoRD.payload.uuid; + if (uploader.queue.length > 0) { + this.dsoDataService.getLogoEndpoint(this.newUUID).pipe(take(1)).subscribe((href: string) => { + uploader.options.url = href; + uploader.uploadAll(); + }); + } else { + this.navigateToNewPage(); + } } }); }); } + /** + * Navigate to the page of the newly created object + */ + navigateToNewPage() { + if (hasValue(this.newUUID)) { + this.router.navigate([this.frontendURL + this.newUUID]); + } + } + } 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 24181b5e61..ec4a7fd745 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 @@ -3,10 +3,11 @@ import { Observable } from 'rxjs'; import { ActivatedRoute, Router } from '@angular/router'; import { RemoteData } from '../../../core/data/remote-data'; import { isNotUndefined } from '../../empty.util'; -import { first, map } from 'rxjs/operators'; +import { first, map, take } from 'rxjs/operators'; import { getSucceededRemoteData } from '../../../core/shared/operators'; import { DataService } from '../../../core/data/data.service'; import { DSpaceObject } from '../../../core/shared/dspace-object.model'; +import { ComColDataService } from '../../../core/data/comcol-data.service'; /** * Component representing the edit page for communities and collections @@ -26,7 +27,7 @@ export class EditComColPageComponent implements On public dsoRD$: Observable>; public constructor( - protected dsoDataService: DataService, + protected dsoDataService: ComColDataService, protected router: Router, protected route: ActivatedRoute ) { @@ -37,17 +38,39 @@ export class EditComColPageComponent implements On } /** - * @param {TDomain} dso The updated version of the DSO * Updates an existing DSO based on the submitted user data and navigates to the edited object's home page + * @param event The event returned by the community/collection form. Contains the new dso and logo uploader */ - onSubmit(dso: TDomain) { + onSubmit(event) { + const dso = event.dso; + const uploader = event.uploader; + this.dsoDataService.update(dso) .pipe(getSucceededRemoteData()) .subscribe((dsoRD: RemoteData) => { if (isNotUndefined(dsoRD)) { const newUUID = dsoRD.payload.uuid; - this.router.navigate([this.frontendURL + newUUID]); + if (uploader.queue.length > 0) { + this.dsoDataService.getLogoEndpoint(newUUID).pipe(take(1)).subscribe((href: string) => { + uploader.options.url = href; + uploader.uploadAll(); + }); + } else { + this.router.navigate([this.frontendURL + newUUID]); + } } }); } + + /** + * Navigate to the home page of the object + */ + navigateToHomePage() { + this.dsoRD$.pipe( + getSucceededRemoteData(), + take(1) + ).subscribe((dsoRD: RemoteData) => { + this.router.navigate([this.frontendURL + dsoRD.payload.id]); + }); + } } diff --git a/src/app/shared/uploader/uploader-options.model.ts b/src/app/shared/uploader/uploader-options.model.ts index 0bd6412b17..fa77a36d11 100644 --- a/src/app/shared/uploader/uploader-options.model.ts +++ b/src/app/shared/uploader/uploader-options.model.ts @@ -10,4 +10,6 @@ export class UploaderOptions { disableMultipart = false; itemAlias: string; + + autoUpload = true; } diff --git a/src/app/shared/uploader/uploader.component.html b/src/app/shared/uploader/uploader.component.html index 9d994313c6..a3181be21c 100644 --- a/src/app/shared/uploader/uploader.component.html +++ b/src/app/shared/uploader/uploader.component.html @@ -29,13 +29,15 @@
- {{'uploader.queue-length' | translate}}: {{ uploader?.queue?.length }} | {{ uploader?.queue[0]?.file.name }} + + {{'uploader.queue-length' | translate}}: {{ uploader?.queue?.length }} | {{ uploader?.queue[0]?.file.name }} +
- {{ uploader.progress }}% + {{ uploader.progress }}% {{'uploader.processing' | translate}}...
diff --git a/src/app/shared/uploader/uploader.component.ts b/src/app/shared/uploader/uploader.component.ts index ad52f4a93f..794b5cb4b3 100644 --- a/src/app/shared/uploader/uploader.component.ts +++ b/src/app/shared/uploader/uploader.component.ts @@ -95,7 +95,7 @@ export class UploaderComponent { disableMultipart: this.uploadFilesOptions.disableMultipart, itemAlias: this.uploadFilesOptions.itemAlias, removeAfterUpload: true, - autoUpload: true + autoUpload: this.uploadFilesOptions.autoUpload }); if (isUndefined(this.enableDragOverDocument)) { @@ -117,7 +117,10 @@ export class UploaderComponent { if (isUndefined(this.onBeforeUpload)) { this.onBeforeUpload = () => {return}; } - this.uploader.onBeforeUploadItem = () => { + this.uploader.onBeforeUploadItem = (item) => { + if (item.url !== this.uploader.options.url) { + item.url = this.uploader.options.url; + } this.onBeforeUpload(); this.isOverDocumentDropZone = observableOf(false); diff --git a/src/app/submission/form/submission-form.component.ts b/src/app/submission/form/submission-form.component.ts index b592972839..7ed7bec04b 100644 --- a/src/app/submission/form/submission-form.component.ts +++ b/src/app/submission/form/submission-form.component.ts @@ -81,7 +81,8 @@ export class SubmissionFormComponent implements OnChanges, OnDestroy { url: '', authToken: null, disableMultipart: false, - itemAlias: null + itemAlias: null, + autoUpload: true }; /** From ed91e96d4282163a373d336572af3c52a1475b04 Mon Sep 17 00:00:00 2001 From: Kristof De Langhe Date: Tue, 1 Oct 2019 15:26:09 +0200 Subject: [PATCH 06/26] 65240: Message cleanup --- .../collection-form.component.ts | 20 ---------------- .../community-form.component.ts | 20 ---------------- .../comcol-form/comcol-form.component.html | 6 ++--- .../comcol-form/comcol-form.component.ts | 24 ++----------------- 4 files changed, 5 insertions(+), 65 deletions(-) diff --git a/src/app/+collection-page/collection-form/collection-form.component.ts b/src/app/+collection-page/collection-form/collection-form.component.ts index e3ca07a2ad..d91d9fc1fb 100644 --- a/src/app/+collection-page/collection-form/collection-form.component.ts +++ b/src/app/+collection-page/collection-form/collection-form.component.ts @@ -24,26 +24,6 @@ export class CollectionFormComponent extends ComColFormComponent { */ @Input() dso: Collection = new Collection(); - /** - * i18n key for the logo's label - */ - protected logoLabelMsg = 'collection.edit.logo.label'; - - /** - * i18n key for the logo's drop message - */ - protected logoDropMsg = 'collection.edit.logo.upload'; - - /** - * i18n key for the logo's upload success message - */ - protected logoSuccessMsg = 'collection.edit.logo.notifications.success'; - - /** - * i18n key for the logo's upload error message - */ - protected logoErrorMsg = 'collection.edit.logo.notifications.error'; - /** * @type {Collection.type} This is a collection-type form */ 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 29149f4d01..fc1e77c445 100644 --- a/src/app/+community-page/community-form/community-form.component.ts +++ b/src/app/+community-page/community-form/community-form.component.ts @@ -24,26 +24,6 @@ export class CommunityFormComponent extends ComColFormComponent { */ @Input() dso: Community = new Community(); - /** - * i18n key for the logo's label - */ - protected logoLabelMsg = 'community.edit.logo.label'; - - /** - * i18n key for the logo's drop message - */ - protected logoDropMsg = 'community.edit.logo.upload'; - - /** - * i18n key for the logo's upload success message - */ - protected logoSuccessMsg = 'community.edit.logo.notifications.success'; - - /** - * i18n key for the logo's upload error message - */ - protected logoErrorMsg = 'community.edit.logo.notifications.error'; - /** * @type {Community.type} This is a community-type form */ 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 8e1e280b22..fff1908823 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 @@ -1,9 +1,9 @@
- + implements OnInit, OnDe */ @Input() dso: T; - /** - * i18n key for the logo's label - */ - protected logoLabelMsg: string; - - /** - * i18n key for the logo's drop message - */ - protected logoDropMsg: string; - - /** - * i18n key for the logo's upload success message - */ - protected logoSuccessMsg: string; - - /** - * i18n key for the logo's upload error message - */ - protected logoErrorMsg: string; - /** * Type of DSpaceObject that the form represents */ @@ -208,7 +188,7 @@ export class ComColFormComponent implements OnInit, OnDe * The request was successful, display a success notification */ public onCompleteItem() { - this.notificationsService.success(null, this.translate.get(this.logoSuccessMsg)); + this.notificationsService.success(null, this.translate.get(this.type.value + '.edit.logo.notifications.success')); this.finishUpload.emit(); } @@ -216,7 +196,7 @@ export class ComColFormComponent implements OnInit, OnDe * The request was unsuccessful, display an error notification */ public onUploadError() { - this.notificationsService.error(null, this.translate.get(this.logoErrorMsg)); + this.notificationsService.error(null, this.translate.get(this.type.value + '.edit.logo.notifications.error')); this.finishUpload.emit(); } From ecef1b35d15c2734e8e8521005d75714490b4477 Mon Sep 17 00:00:00 2001 From: Kristof De Langhe Date: Tue, 1 Oct 2019 16:12:08 +0200 Subject: [PATCH 07/26] 65240: Delete logo button and service method --- resources/i18n/en.json5 | 14 +++++--- src/app/core/data/comcol-data.service.ts | 18 ++++++++-- .../comcol-form/comcol-form.component.html | 11 ++++-- .../comcol-form/comcol-form.component.ts | 36 +++++++++++++++++-- 4 files changed, 69 insertions(+), 10 deletions(-) diff --git a/resources/i18n/en.json5 b/resources/i18n/en.json5 index cc6d49814b..cf155c0841 100644 --- a/resources/i18n/en.json5 +++ b/resources/i18n/en.json5 @@ -131,8 +131,11 @@ "collection.edit.delete": "Delete this collection", "collection.edit.head": "Edit Collection", "collection.edit.logo.label": "Collection logo", - "collection.edit.logo.notifications.error": "Uploading Collection logo failed. Please verify the content before retrying.", - "collection.edit.logo.notifications.success": "Upload Collection logo successful.", + "collection.edit.logo.notifications.add.error": "Uploading Collection logo failed. Please verify the content before retrying.", + "collection.edit.logo.notifications.add.success": "Upload Collection logo successful.", + "collection.edit.logo.notifications.delete.success.title": "Logo deleted", + "collection.edit.logo.notifications.delete.success.content": "Successfully deleted the collection's logo", + "collection.edit.logo.notifications.delete.error.title": "Error deleting logo", "collection.edit.logo.upload": "Drop a Collection Logo to upload", "collection.form.abstract": "Short Description", "collection.form.description": "Introductory text (HTML)", @@ -158,8 +161,11 @@ "community.edit.delete": "Delete this community", "community.edit.head": "Edit Community", "community.edit.logo.label": "Community logo", - "community.edit.logo.notifications.error": "Uploading Community logo failed. Please verify the content before retrying.", - "community.edit.logo.notifications.success": "Upload Community logo successful.", + "community.edit.logo.notifications.add.error": "Uploading Community logo failed. Please verify the content before retrying.", + "community.edit.logo.notifications.add.success": "Upload Community logo successful.", + "community.edit.logo.notifications.delete.success.title": "Logo deleted", + "community.edit.logo.notifications.delete.success.content": "Successfully deleted the community's logo", + "community.edit.logo.notifications.delete.error.title": "Error deleting logo", "community.edit.logo.upload": "Drop a Community Logo to upload", "community.form.abstract": "Short Description", "community.form.description": "Introductory text (HTML)", diff --git a/src/app/core/data/comcol-data.service.ts b/src/app/core/data/comcol-data.service.ts index 42c414a8a7..ba17d04d76 100644 --- a/src/app/core/data/comcol-data.service.ts +++ b/src/app/core/data/comcol-data.service.ts @@ -6,10 +6,11 @@ import { ObjectCacheService } from '../cache/object-cache.service'; import { CommunityDataService } from './community-data.service'; import { DataService } from './data.service'; -import { FindAllOptions, FindByIDRequest } from './request.models'; +import { DeleteRequest, FindAllOptions, FindByIDRequest, RestRequest } from './request.models'; import { HALEndpointService } from '../shared/hal-endpoint.service'; -import { getResponseFromEntry } from '../shared/operators'; +import { configureRequest, getResponseFromEntry } from '../shared/operators'; import { CacheableObject } from '../cache/object-cache.reducer'; +import { RestResponse } from '../cache/response.models'; export abstract class ComColDataService extends DataService { protected abstract cds: CommunityDataService; @@ -67,4 +68,17 @@ export abstract class ComColDataService extends DataS switchMap((href: string) => this.halService.getEndpoint('logo', `${href}/${id}`)) ) } + + /** + * Delete the logo from the community or collection + * @param id The community or collection's ID + */ + public deleteLogo(id: string): Observable { + return this.getLogoEndpoint(id).pipe( + map((href: string) => new DeleteRequest(this.requestService.generateRequestId(), href)), + configureRequest(this.requestService), + switchMap((restRequest: RestRequest) => this.requestService.getByUUID(restRequest.uuid)), + getResponseFromEntry() + ); + } } 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 fff1908823..b65e6e8f80 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 @@ -1,7 +1,14 @@
- - + +
+ +
+ + implements OnInit, OnDe */ @Output() finishUpload: EventEmitter = new EventEmitter(); + /** + * Observable keeping track whether or not the uploader has finished initializing + * Used to start rendering the uploader component + */ + private initializedUploaderOptions = new BehaviorSubject(false); + /** * Array to track all subscriptions and unsubscribe them onDestroy * @type {Array} @@ -128,12 +136,14 @@ export class ComColFormComponent implements OnInit, OnDe this.dsoService.getLogoEndpoint(this.dso.id).subscribe((href: string) => { this.uploadFilesOptions.url = href; this.uploadFilesOptions.authToken = this.authService.buildAuthHeader(); + this.initializedUploaderOptions.next(true); }) ); } else { // Set a placeholder URL to not break the uploader component. This will be replaced once the object is created. this.uploadFilesOptions.url = 'placeholder'; this.uploadFilesOptions.authToken = this.authService.buildAuthHeader(); + this.initializedUploaderOptions.next(true); } } @@ -184,11 +194,33 @@ export class ComColFormComponent implements OnInit, OnDe ); } + /** + * Send out a delete request to remove the logo from the community/collection and display notifications + */ + deleteLogo() { + if (hasValue(this.dso.id)) { + this.dsoService.deleteLogo(this.dso.id).subscribe((response: RestResponse) => { + if (response.isSuccessful) { + this.notificationsService.success( + this.translate.get(this.type.value + '.edit.logo.notifications.delete.success.title'), + this.translate.get(this.type.value + '.edit.logo.notifications.delete.success.content') + ); + } else { + const errorResponse = response as ErrorResponse; + this.notificationsService.error( + this.translate.get(this.type.value + '.edit.logo.notifications.delete.error.title'), + errorResponse.errorMessage + ); + } + }); + } + } + /** * The request was successful, display a success notification */ public onCompleteItem() { - this.notificationsService.success(null, this.translate.get(this.type.value + '.edit.logo.notifications.success')); + this.notificationsService.success(null, this.translate.get(this.type.value + '.edit.logo.notifications.add.success')); this.finishUpload.emit(); } @@ -196,7 +228,7 @@ export class ComColFormComponent implements OnInit, OnDe * The request was unsuccessful, display an error notification */ public onUploadError() { - this.notificationsService.error(null, this.translate.get(this.type.value + '.edit.logo.notifications.error')); + this.notificationsService.error(null, this.translate.get(this.type.value + '.edit.logo.notifications.add.error')); this.finishUpload.emit(); } From eade3e7d375fa826569b4e4cd344870b2213fd0a Mon Sep 17 00:00:00 2001 From: Kristof De Langhe Date: Tue, 1 Oct 2019 16:53:21 +0200 Subject: [PATCH 08/26] 65240: Set uploader method to PUT if object already contains a logo --- .../my-dspace-new-submission.component.ts | 8 +---- .../comcol-form/comcol-form.component.ts | 30 ++++++++++++------- .../shared/uploader/uploader-options.model.ts | 11 ++++++- src/app/shared/uploader/uploader.component.ts | 3 +- .../form/submission-form.component.ts | 8 +---- 5 files changed, 33 insertions(+), 27 deletions(-) diff --git a/src/app/+my-dspace-page/my-dspace-new-submission/my-dspace-new-submission.component.ts b/src/app/+my-dspace-page/my-dspace-new-submission/my-dspace-new-submission.component.ts index 26ed4110b3..342e3f44e3 100644 --- a/src/app/+my-dspace-page/my-dspace-new-submission/my-dspace-new-submission.component.ts +++ b/src/app/+my-dspace-page/my-dspace-new-submission/my-dspace-new-submission.component.ts @@ -30,13 +30,7 @@ export class MyDSpaceNewSubmissionComponent implements OnDestroy, OnInit { /** * The UploaderOptions object */ - public uploadFilesOptions: UploaderOptions = { - url: '', - authToken: null, - disableMultipart: false, - itemAlias: null, - autoUpload: true - }; + public uploadFilesOptions: UploaderOptions = new UploaderOptions(); /** * Subscription to unsubscribe from 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 06c507b3ea..6e8b04e589 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,16 +1,13 @@ import { Component, EventEmitter, Input, OnDestroy, OnInit, Output, ViewChild } from '@angular/core'; import { Location } from '@angular/common'; -import { - DynamicFormService, - DynamicInputModel -} from '@ng-dynamic-forms/core'; +import { DynamicFormService, DynamicInputModel } from '@ng-dynamic-forms/core'; import { FormGroup } from '@angular/forms'; import { DynamicFormControlModel } from '@ng-dynamic-forms/core/src/model/dynamic-form-control.model'; import { TranslateService } from '@ngx-translate/core'; import { DSpaceObject } from '../../../core/shared/dspace-object.model'; import { MetadataMap, MetadataValue } from '../../../core/shared/metadata.models'; import { ResourceType } from '../../../core/shared/resource-type'; -import { hasValue, isNotEmpty, isUndefined } from '../../empty.util'; +import { hasValue, isNotEmpty } from '../../empty.util'; import { UploaderOptions } from '../../uploader/uploader-options.model'; import { NotificationsService } from '../../notifications/notifications.service'; import { ComColDataService } from '../../../core/data/comcol-data.service'; @@ -22,6 +19,10 @@ import { UploaderComponent } from '../../uploader/uploader.component'; import { FileUploader } from 'ng2-file-upload'; import { ErrorResponse, RestResponse } from '../../../core/cache/response.models'; import { BehaviorSubject } from 'rxjs/internal/BehaviorSubject'; +import { RemoteData } from '../../../core/data/remote-data'; +import { Bitstream } from '../../../core/shared/bitstream.model'; +import { combineLatest as observableCombineLatest } from 'rxjs'; +import { RestRequestMethod } from '../../../core/data/rest-request-method'; /** * A form for creating and editing Communities or Collections @@ -72,13 +73,10 @@ export class ComColFormComponent implements OnInit, OnDe * The uploader configuration options * @type {UploaderOptions} */ - uploadFilesOptions: UploaderOptions = { - url: '', - authToken: null, + uploadFilesOptions: UploaderOptions = Object.assign(new UploaderOptions(), { disableMultipart: true, - itemAlias: null, autoUpload: false - }; + }); /** * Emits DSO and Uploader when the form is submitted @@ -133,9 +131,16 @@ export class ComColFormComponent implements OnInit, OnDe if (hasValue(this.dso.id)) { this.subs.push( - this.dsoService.getLogoEndpoint(this.dso.id).subscribe((href: string) => { + observableCombineLatest( + this.dsoService.getLogoEndpoint(this.dso.id), + (this.dso as any).logo + ).subscribe(([href, logoRD]: [string, RemoteData]) => { this.uploadFilesOptions.url = href; this.uploadFilesOptions.authToken = this.authService.buildAuthHeader(); + // If the object already contains a logo, send out a PUT request instead of POST for setting a new logo + if (hasValue(logoRD.payload)) { + this.uploadFilesOptions.method = RestRequestMethod.PUT; + } this.initializedUploaderOptions.next(true); }) ); @@ -232,6 +237,9 @@ export class ComColFormComponent implements OnInit, OnDe this.finishUpload.emit(); } + /** + * Cancel the form and return to the previous page + */ onCancel() { this.location.back(); } diff --git a/src/app/shared/uploader/uploader-options.model.ts b/src/app/shared/uploader/uploader-options.model.ts index fa77a36d11..f195b0930e 100644 --- a/src/app/shared/uploader/uploader-options.model.ts +++ b/src/app/shared/uploader/uploader-options.model.ts @@ -1,3 +1,4 @@ +import { RestRequestMethod } from '../../core/data/rest-request-method'; export class UploaderOptions { /** @@ -9,7 +10,15 @@ export class UploaderOptions { disableMultipart = false; - itemAlias: string; + itemAlias: string = null; + /** + * Automatically send out an upload request when adding files + */ autoUpload = true; + + /** + * The request method to use for the file upload request + */ + method: RestRequestMethod = RestRequestMethod.POST; } diff --git a/src/app/shared/uploader/uploader.component.ts b/src/app/shared/uploader/uploader.component.ts index 794b5cb4b3..935d196d08 100644 --- a/src/app/shared/uploader/uploader.component.ts +++ b/src/app/shared/uploader/uploader.component.ts @@ -95,7 +95,8 @@ export class UploaderComponent { disableMultipart: this.uploadFilesOptions.disableMultipart, itemAlias: this.uploadFilesOptions.itemAlias, removeAfterUpload: true, - autoUpload: this.uploadFilesOptions.autoUpload + autoUpload: this.uploadFilesOptions.autoUpload, + method: this.uploadFilesOptions.method }); if (isUndefined(this.enableDragOverDocument)) { diff --git a/src/app/submission/form/submission-form.component.ts b/src/app/submission/form/submission-form.component.ts index 7ed7bec04b..a11ad43db3 100644 --- a/src/app/submission/form/submission-form.component.ts +++ b/src/app/submission/form/submission-form.component.ts @@ -77,13 +77,7 @@ export class SubmissionFormComponent implements OnChanges, OnDestroy { * The uploader configuration options * @type {UploaderOptions} */ - public uploadFilesOptions: UploaderOptions = { - url: '', - authToken: null, - disableMultipart: false, - itemAlias: null, - autoUpload: true - }; + public uploadFilesOptions: UploaderOptions = new UploaderOptions(); /** * A boolean representing if component is active From f3a032470dac20e1ca8f9f9eefb5541247877e27 Mon Sep 17 00:00:00 2001 From: Kristof De Langhe Date: Wed, 2 Oct 2019 10:19:21 +0200 Subject: [PATCH 09/26] 65240: Fixed current tests --- .../comcol-form/comcol-form.component.spec.ts | 41 ++++++++++++------- .../create-comcol-page.component.spec.ts | 24 +++++++---- .../edit-comcol-page.component.spec.ts | 24 +++++++---- src/app/shared/mocks/mock-auth.service.ts | 3 ++ 4 files changed, 64 insertions(+), 28 deletions(-) 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 1b44970402..c896614ca9 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 @@ -7,10 +7,14 @@ import { DynamicFormService, DynamicInputModel } from '@ng-dynamic-forms/core'; import { FormControl, FormGroup } from '@angular/forms'; import { DynamicFormControlModel } from '@ng-dynamic-forms/core/src/model/dynamic-form-control.model'; import { Community } from '../../../core/shared/community.model'; -import { ResourceType } from '../../../core/shared/resource-type'; import { ComColFormComponent } from './comcol-form.component'; import { DSpaceObject } from '../../../core/shared/dspace-object.model'; import { hasValue } from '../../empty.util'; +import { VarDirective } from '../../utils/var.directive'; +import { NotificationsService } from '../../notifications/notifications.service'; +import { NotificationsServiceStub } from '../../testing/notifications-service-stub'; +import { AuthService } from '../../../core/auth/auth.service'; +import { AuthServiceMock } from '../../mocks/mock-auth.service'; describe('ComColFormComponent', () => { let comp: ComColFormComponent; @@ -56,10 +60,12 @@ describe('ComColFormComponent', () => { beforeEach(async(() => { TestBed.configureTestingModule({ imports: [TranslateModule.forRoot(), RouterTestingModule], - declarations: [ComColFormComponent], + declarations: [ComColFormComponent, VarDirective], providers: [ { provide: Location, useValue: locationStub }, - { provide: DynamicFormService, useValue: formServiceStub } + { provide: DynamicFormService, useValue: formServiceStub }, + { provide: NotificationsService, useValue: new NotificationsServiceStub() }, + { provide: AuthService, useValue: new AuthServiceMock() } ], schemas: [NO_ERRORS_SCHEMA] }).compileComponents(); @@ -70,6 +76,10 @@ describe('ComColFormComponent', () => { comp = fixture.componentInstance; comp.formModel = []; comp.dso = new Community(); + (comp as any).type = Community.type; + comp.uploaderComponent = Object.assign({ + uploader: {} + }); fixture.detectChanges(); location = (comp as any).location; }); @@ -94,18 +104,21 @@ describe('ComColFormComponent', () => { comp.onSubmit(); expect(comp.submitForm.emit).toHaveBeenCalledWith( - Object.assign( - {}, - new Community(), - { - metadata: { - ...newTitleMD, - ...randomMD, - ...abstractMD + { + dso: Object.assign( + {}, + new Community(), + { + metadata: { + ...newTitleMD, + ...randomMD, + ...abstractMD + }, + type: Community.type }, - type: Community.type - }, - ) + ), + uploader: {} + } ); }) }); diff --git a/src/app/shared/comcol-forms/create-comcol-page/create-comcol-page.component.spec.ts b/src/app/shared/comcol-forms/create-comcol-page/create-comcol-page.component.spec.ts index 6ad2e5b5e1..bc468fada1 100644 --- a/src/app/shared/comcol-forms/create-comcol-page/create-comcol-page.component.spec.ts +++ b/src/app/shared/comcol-forms/create-comcol-page/create-comcol-page.component.spec.ts @@ -16,6 +16,7 @@ import { createFailedRemoteDataObject$, createSuccessfulRemoteDataObject$ } from '../../testing/utils'; +import { ComColDataService } from '../../../core/data/comcol-data.service'; describe('CreateComColPageComponent', () => { let comp: CreateComColPageComponent; @@ -74,7 +75,7 @@ describe('CreateComColPageComponent', () => { TestBed.configureTestingModule({ imports: [TranslateModule.forRoot(), SharedModule, CommonModule, RouterTestingModule], providers: [ - { provide: DataService, useValue: communityDataServiceStub }, + { provide: ComColDataService, useValue: communityDataServiceStub }, { provide: CommunityDataService, useValue: communityDataServiceStub }, { provide: RouteService, useValue: routeServiceStub }, { provide: Router, useValue: routerStub }, @@ -96,12 +97,21 @@ describe('CreateComColPageComponent', () => { describe('onSubmit', () => { let data; beforeEach(() => { - data = Object.assign(new Community(), { - metadata: [{ - key: 'dc.title', - value: 'test' - }] - }); + data = { + dso: Object.assign(new Community(), { + metadata: [{ + key: 'dc.title', + value: 'test' + }] + }), + uploader: { + options: { + url: '' + }, + queue: [], + uploadAll: {} + } + }; }); it('should navigate when successful', () => { spyOn(router, 'navigate'); diff --git a/src/app/shared/comcol-forms/edit-comcol-page/edit-comcol-page.component.spec.ts b/src/app/shared/comcol-forms/edit-comcol-page/edit-comcol-page.component.spec.ts index 03f751599f..d9fb59fe9e 100644 --- a/src/app/shared/comcol-forms/edit-comcol-page/edit-comcol-page.component.spec.ts +++ b/src/app/shared/comcol-forms/edit-comcol-page/edit-comcol-page.component.spec.ts @@ -15,6 +15,7 @@ import { createFailedRemoteDataObject$, createSuccessfulRemoteDataObject$ } from '../../testing/utils'; +import { ComColDataService } from '../../../core/data/comcol-data.service'; describe('EditComColPageComponent', () => { let comp: EditComColPageComponent; @@ -65,7 +66,7 @@ describe('EditComColPageComponent', () => { TestBed.configureTestingModule({ imports: [TranslateModule.forRoot(), SharedModule, CommonModule, RouterTestingModule], providers: [ - { provide: DataService, useValue: communityDataServiceStub }, + { provide: ComColDataService, useValue: communityDataServiceStub }, { provide: Router, useValue: routerStub }, { provide: ActivatedRoute, useValue: routeStub }, ], @@ -84,12 +85,21 @@ describe('EditComColPageComponent', () => { describe('onSubmit', () => { let data; beforeEach(() => { - data = Object.assign(new Community(), { - metadata: [{ - key: 'dc.title', - value: 'test' - }] - }); + data = { + dso: Object.assign(new Community(), { + metadata: [{ + key: 'dc.title', + value: 'test' + }] + }), + uploader: { + options: { + url: '' + }, + queue: [], + uploadAll: {} + } + } }); it('should navigate when successful', () => { spyOn(router, 'navigate'); diff --git a/src/app/shared/mocks/mock-auth.service.ts b/src/app/shared/mocks/mock-auth.service.ts index 6258e4aa21..a168ffd8e5 100644 --- a/src/app/shared/mocks/mock-auth.service.ts +++ b/src/app/shared/mocks/mock-auth.service.ts @@ -3,4 +3,7 @@ export class AuthServiceMock { public checksAuthenticationToken() { return } + public buildAuthHeader() { + return 'auth-header'; + } } From 8a475f2523e482dc80c9a96ec11c3d5d3c5c73fa Mon Sep 17 00:00:00 2001 From: Kristof De Langhe Date: Wed, 2 Oct 2019 13:04:15 +0200 Subject: [PATCH 10/26] 65240: comcol form logo tests --- .../comcol-form/comcol-form.component.spec.ts | 217 ++++++++++++++---- .../create-comcol-page.component.spec.ts | 113 ++++++--- .../edit-comcol-page.component.spec.ts | 125 +++++++--- 3 files changed, 344 insertions(+), 111 deletions(-) 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 c896614ca9..455e2ef4e0 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 @@ -15,6 +15,11 @@ import { NotificationsService } from '../../notifications/notifications.service' import { NotificationsServiceStub } from '../../testing/notifications-service-stub'; import { AuthService } from '../../../core/auth/auth.service'; import { AuthServiceMock } from '../../mocks/mock-auth.service'; +import { of as observableOf } from 'rxjs'; +import { RemoteData } from '../../../core/data/remote-data'; +import { RestRequestMethod } from '../../../core/data/rest-request-method'; +import { ErrorResponse, RestResponse } from '../../../core/cache/response.models'; +import { RequestError } from '../../../core/data/request.models'; describe('ComColFormComponent', () => { let comp: ComColFormComponent; @@ -53,6 +58,13 @@ describe('ComColFormComponent', () => { }) ]; + const logoEndpoint = 'rest/api/logo/endpoint'; + const dsoService = Object.assign({ + getLogoEndpoint: () => observableOf(logoEndpoint), + deleteLogo: () => observableOf({}) + }); + const notificationsService = new NotificationsServiceStub(); + /* tslint:disable:no-empty */ const locationStub = jasmine.createSpyObj('location', ['back']); /* tslint:enable:no-empty */ @@ -64,69 +76,174 @@ describe('ComColFormComponent', () => { providers: [ { provide: Location, useValue: locationStub }, { provide: DynamicFormService, useValue: formServiceStub }, - { provide: NotificationsService, useValue: new NotificationsServiceStub() }, + { provide: NotificationsService, useValue: notificationsService }, { provide: AuthService, useValue: new AuthServiceMock() } ], schemas: [NO_ERRORS_SCHEMA] }).compileComponents(); })); - beforeEach(() => { + describe('when the dso doesn\'t contain an ID (newly created)', () => { + beforeEach(() => { + initComponent(new Community()); + }); + + it('should initialize the uploadFilesOptions with a placeholder url', () => { + expect(comp.uploadFilesOptions.url.length).toBeGreaterThan(0); + }); + + describe('onSubmit', () => { + beforeEach(() => { + spyOn(comp.submitForm, 'emit'); + comp.formModel = formModel; + }); + + it('should emit the new version of the community', () => { + comp.dso = Object.assign( + new Community(), + { + metadata: { + ...titleMD, + ...randomMD + } + } + ); + + comp.onSubmit(); + + expect(comp.submitForm.emit).toHaveBeenCalledWith( + { + dso: Object.assign( + {}, + new Community(), + { + metadata: { + ...newTitleMD, + ...randomMD, + ...abstractMD + }, + type: Community.type + }, + ), + uploader: {} + } + ); + }) + }); + + describe('onCancel', () => { + it('should call the back method on the Location service', () => { + comp.onCancel(); + expect(locationStub.back).toHaveBeenCalled(); + }); + }); + + describe('onCompleteItem', () => { + beforeEach(() => { + spyOn(comp.finishUpload, 'emit'); + comp.onCompleteItem(); + }); + + it('should show a success notification', () => { + expect(notificationsService.success).toHaveBeenCalled(); + }); + + it('should emit finishUpload', () => { + expect(comp.finishUpload.emit).toHaveBeenCalled(); + }); + }); + + describe('onUploadError', () => { + beforeEach(() => { + spyOn(comp.finishUpload, 'emit'); + comp.onUploadError(); + }); + + it('should show an error notification', () => { + expect(notificationsService.error).toHaveBeenCalled(); + }); + + it('should emit finishUpload', () => { + expect(comp.finishUpload.emit).toHaveBeenCalled(); + }); + }); + }); + + describe('when the dso contains an ID (being edited)', () => { + describe('and the dso doesn\'t contain a logo', () => { + beforeEach(() => { + initComponent(Object.assign(new Community(), { + id: 'community-id', + logo: observableOf(new RemoteData(false, false, true, null, undefined)) + })); + }); + + it('should initialize the uploadFilesOptions with the logo\'s endpoint url', () => { + expect(comp.uploadFilesOptions.url).toEqual(logoEndpoint); + }); + + it('should initialize the uploadFilesOptions with a POST method', () => { + expect(comp.uploadFilesOptions.method).toEqual(RestRequestMethod.POST); + }); + }); + + describe('and the dso contains a logo', () => { + beforeEach(() => { + initComponent(Object.assign(new Community(), { + id: 'community-id', + logo: observableOf(new RemoteData(false, false, true, null, {})) + })); + }); + + it('should initialize the uploadFilesOptions with the logo\'s endpoint url', () => { + expect(comp.uploadFilesOptions.url).toEqual(logoEndpoint); + }); + + it('should initialize the uploadFilesOptions with a PUT method', () => { + expect(comp.uploadFilesOptions.method).toEqual(RestRequestMethod.PUT); + }); + + describe('deleteLogo', () => { + describe('when dsoService.deleteLogo returns a successful response', () => { + const response = new RestResponse(true, 200, 'OK'); + + beforeEach(() => { + spyOn(dsoService, 'deleteLogo').and.returnValue(observableOf(response)); + comp.deleteLogo(); + }); + + it('should display a success notification', () => { + expect(notificationsService.success).toHaveBeenCalled(); + }); + }); + + describe('when dsoService.deleteLogo returns an error response', () => { + const response = new ErrorResponse(new RequestError('errorMessage')); + + beforeEach(() => { + spyOn(dsoService, 'deleteLogo').and.returnValue(observableOf(response)); + comp.deleteLogo(); + }); + + it('should display an error notification', () => { + expect(notificationsService.error).toHaveBeenCalled(); + }); + }); + }); + }); + }); + + function initComponent(dso: Community) { fixture = TestBed.createComponent(ComColFormComponent); comp = fixture.componentInstance; comp.formModel = []; - comp.dso = new Community(); + comp.dso = dso; (comp as any).type = Community.type; comp.uploaderComponent = Object.assign({ uploader: {} }); + (comp as any).dsoService = dsoService; fixture.detectChanges(); location = (comp as any).location; - }); - - describe('onSubmit', () => { - beforeEach(() => { - spyOn(comp.submitForm, 'emit'); - comp.formModel = formModel; - }); - - it('should emit the new version of the community', () => { - comp.dso = Object.assign( - new Community(), - { - metadata: { - ...titleMD, - ...randomMD - } - } - ); - - comp.onSubmit(); - - expect(comp.submitForm.emit).toHaveBeenCalledWith( - { - dso: Object.assign( - {}, - new Community(), - { - metadata: { - ...newTitleMD, - ...randomMD, - ...abstractMD - }, - type: Community.type - }, - ), - uploader: {} - } - ); - }) - }); - - describe('onCancel', () => { - it('should call the back method on the Location service', () => { - comp.onCancel(); - expect(locationStub.back).toHaveBeenCalled(); - }); - }); + } }); diff --git a/src/app/shared/comcol-forms/create-comcol-page/create-comcol-page.component.spec.ts b/src/app/shared/comcol-forms/create-comcol-page/create-comcol-page.component.spec.ts index bc468fada1..99aac6757e 100644 --- a/src/app/shared/comcol-forms/create-comcol-page/create-comcol-page.component.spec.ts +++ b/src/app/shared/comcol-forms/create-comcol-page/create-comcol-page.component.spec.ts @@ -11,7 +11,6 @@ import { RouterTestingModule } from '@angular/router/testing'; import { NO_ERRORS_SCHEMA } from '@angular/core'; import { DSpaceObject } from '../../../core/shared/dspace-object.model'; import { CreateComColPageComponent } from './create-comcol-page.component'; -import { DataService } from '../../../core/data/data.service'; import { createFailedRemoteDataObject$, createSuccessfulRemoteDataObject$ @@ -32,6 +31,8 @@ describe('CreateComColPageComponent', () => { let routeServiceStub; let routerStub; + const logoEndpoint = 'rest/api/logo/endpoint'; + function initializeVars() { community = Object.assign(new Community(), { uuid: 'a20da287-e174-466a-9926-f66b9300d347', @@ -57,8 +58,8 @@ describe('CreateComColPageComponent', () => { value: community.name }] })), - create: (com, uuid?) => createSuccessfulRemoteDataObject$(newCommunity) - + create: (com, uuid?) => createSuccessfulRemoteDataObject$(newCommunity), + getLogoEndpoint: () => observableOf(logoEndpoint) }; routeServiceStub = { @@ -96,36 +97,86 @@ describe('CreateComColPageComponent', () => { describe('onSubmit', () => { let data; - beforeEach(() => { - data = { - dso: Object.assign(new Community(), { - metadata: [{ - key: 'dc.title', - value: 'test' - }] - }), - uploader: { - options: { - url: '' - }, - queue: [], - uploadAll: {} - } - }; - }); - it('should navigate when successful', () => { - spyOn(router, 'navigate'); - comp.onSubmit(data); - fixture.detectChanges(); - expect(router.navigate).toHaveBeenCalled(); + + describe('with an empty queue in the uploader', () => { + beforeEach(() => { + data = { + dso: Object.assign(new Community(), { + metadata: [{ + key: 'dc.title', + value: 'test' + }] + }), + uploader: { + options: { + url: '' + }, + queue: [], + /* tslint:disable:no-empty */ + uploadAll: () => {} + /* tslint:enable:no-empty */ + } + }; + }); + + it('should navigate when successful', () => { + spyOn(router, 'navigate'); + comp.onSubmit(data); + fixture.detectChanges(); + expect(router.navigate).toHaveBeenCalled(); + }); + + it('should not navigate on failure', () => { + spyOn(router, 'navigate'); + spyOn(dsoDataService, 'create').and.returnValue(createFailedRemoteDataObject$(newCommunity)); + comp.onSubmit(data); + fixture.detectChanges(); + expect(router.navigate).not.toHaveBeenCalled(); + }); }); - it('should not navigate on failure', () => { - spyOn(router, 'navigate'); - spyOn(dsoDataService, 'create').and.returnValue(createFailedRemoteDataObject$(newCommunity)); - comp.onSubmit(data); - fixture.detectChanges(); - expect(router.navigate).not.toHaveBeenCalled(); + describe('with at least one item in the uploader\'s queue', () => { + beforeEach(() => { + data = { + dso: Object.assign(new Community(), { + metadata: [{ + key: 'dc.title', + value: 'test' + }] + }), + uploader: { + options: { + url: '' + }, + queue: [ + {} + ], + /* tslint:disable:no-empty */ + uploadAll: () => {} + /* tslint:enable:no-empty */ + } + }; + }); + + it('should not navigate', () => { + spyOn(router, 'navigate'); + comp.onSubmit(data); + fixture.detectChanges(); + expect(router.navigate).not.toHaveBeenCalled(); + }); + + it('should set the uploader\'s url to the logo\'s endpoint', () => { + comp.onSubmit(data); + fixture.detectChanges(); + expect(data.uploader.options.url).toEqual(logoEndpoint); + }); + + it('should call the uploader\'s uploadAll', () => { + spyOn(data.uploader, 'uploadAll'); + comp.onSubmit(data); + fixture.detectChanges(); + expect(data.uploader.uploadAll).toHaveBeenCalled(); + }); }); }); }); diff --git a/src/app/shared/comcol-forms/edit-comcol-page/edit-comcol-page.component.spec.ts b/src/app/shared/comcol-forms/edit-comcol-page/edit-comcol-page.component.spec.ts index d9fb59fe9e..2a52049df5 100644 --- a/src/app/shared/comcol-forms/edit-comcol-page/edit-comcol-page.component.spec.ts +++ b/src/app/shared/comcol-forms/edit-comcol-page/edit-comcol-page.component.spec.ts @@ -10,12 +10,12 @@ import { RouterTestingModule } from '@angular/router/testing'; import { NO_ERRORS_SCHEMA } from '@angular/core'; import { DSpaceObject } from '../../../core/shared/dspace-object.model'; import { EditComColPageComponent } from './edit-comcol-page.component'; -import { DataService } from '../../../core/data/data.service'; import { createFailedRemoteDataObject$, createSuccessfulRemoteDataObject$ } from '../../testing/utils'; import { ComColDataService } from '../../../core/data/comcol-data.service'; +import { RemoteData } from '../../../core/data/remote-data'; describe('EditComColPageComponent', () => { let comp: EditComColPageComponent; @@ -29,6 +29,8 @@ describe('EditComColPageComponent', () => { let routerStub; let routeStub; + const logoEndpoint = 'rest/api/logo/endpoint'; + function initializeVars() { community = Object.assign(new Community(), { uuid: 'a20da287-e174-466a-9926-f66b9300d347', @@ -47,8 +49,8 @@ describe('EditComColPageComponent', () => { }); communityDataServiceStub = { - update: (com, uuid?) => createSuccessfulRemoteDataObject$(newCommunity) - + update: (com, uuid?) => createSuccessfulRemoteDataObject$(newCommunity), + getLogoEndpoint: () => observableOf(logoEndpoint) }; routerStub = { @@ -56,7 +58,9 @@ describe('EditComColPageComponent', () => { }; routeStub = { - data: observableOf(community) + data: observableOf({ + dso: new RemoteData(false, false, true, null, community) + }) }; } @@ -84,36 +88,97 @@ describe('EditComColPageComponent', () => { describe('onSubmit', () => { let data; - beforeEach(() => { - data = { - dso: Object.assign(new Community(), { - metadata: [{ - key: 'dc.title', - value: 'test' - }] - }), - uploader: { - options: { - url: '' - }, - queue: [], - uploadAll: {} + + describe('with an empty queue in the uploader', () => { + beforeEach(() => { + data = { + dso: Object.assign(new Community(), { + metadata: [{ + key: 'dc.title', + value: 'test' + }] + }), + uploader: { + options: { + url: '' + }, + queue: [], + /* tslint:disable:no-empty */ + uploadAll: () => {} + /* tslint:enable:no-empty */ + } } - } - }); - it('should navigate when successful', () => { - spyOn(router, 'navigate'); - comp.onSubmit(data); - fixture.detectChanges(); - expect(router.navigate).toHaveBeenCalled(); + }); + + it('should navigate when successful', () => { + spyOn(router, 'navigate'); + comp.onSubmit(data); + fixture.detectChanges(); + expect(router.navigate).toHaveBeenCalled(); + }); + + it('should not navigate on failure', () => { + spyOn(router, 'navigate'); + spyOn(dsoDataService, 'update').and.returnValue(createFailedRemoteDataObject$(newCommunity)); + comp.onSubmit(data); + fixture.detectChanges(); + expect(router.navigate).not.toHaveBeenCalled(); + }); }); - it('should not navigate on failure', () => { + describe('with at least one item in the uploader\'s queue', () => { + beforeEach(() => { + data = { + dso: Object.assign(new Community(), { + metadata: [{ + key: 'dc.title', + value: 'test' + }] + }), + uploader: { + options: { + url: '' + }, + queue: [ + {} + ], + /* tslint:disable:no-empty */ + uploadAll: () => {} + /* tslint:enable:no-empty */ + } + } + }); + + it('should not navigate', () => { + spyOn(router, 'navigate'); + comp.onSubmit(data); + fixture.detectChanges(); + expect(router.navigate).not.toHaveBeenCalled(); + }); + + it('should set the uploader\'s url to the logo\'s endpoint', () => { + comp.onSubmit(data); + fixture.detectChanges(); + expect(data.uploader.options.url).toEqual(logoEndpoint); + }); + + it('should call the uploader\'s uploadAll', () => { + spyOn(data.uploader, 'uploadAll'); + comp.onSubmit(data); + fixture.detectChanges(); + expect(data.uploader.uploadAll).toHaveBeenCalled(); + }); + }); + }); + + describe('navigateToHomePage', () => { + beforeEach(() => { spyOn(router, 'navigate'); - spyOn(dsoDataService, 'update').and.returnValue(createFailedRemoteDataObject$(newCommunity)); - comp.onSubmit(data); - fixture.detectChanges(); - expect(router.navigate).not.toHaveBeenCalled(); + comp.navigateToHomePage(); + }); + + it('should navigate', () => { + expect(router.navigate).toHaveBeenCalled(); }); }); }); From 37a18fdaa7d5230daa0e063e2f0b02a0d4a71066 Mon Sep 17 00:00:00 2001 From: Kristof De Langhe Date: Wed, 2 Oct 2019 13:40:06 +0200 Subject: [PATCH 11/26] 65240: Success notification on submitting comcol form --- resources/i18n/en.json5 | 4 ++++ .../create-collection-page.component.spec.ts | 3 +++ .../create-collection-page.component.ts | 9 +++++++-- .../edit-collection-page.component.spec.ts | 3 +++ .../edit-collection-page.component.ts | 9 +++++++-- .../create-community-page.component.spec.ts | 3 +++ .../create-community-page.component.ts | 9 +++++++-- .../edit-community-page.component.spec.ts | 3 +++ .../edit-community-page.component.ts | 9 +++++++-- .../create-comcol-page.component.spec.ts | 4 ++++ .../create-comcol-page.component.ts | 15 +++++++++++++-- .../edit-comcol-page.component.spec.ts | 4 ++++ .../edit-comcol-page.component.ts | 13 ++++++++++++- 13 files changed, 77 insertions(+), 11 deletions(-) diff --git a/resources/i18n/en.json5 b/resources/i18n/en.json5 index cf155c0841..bf97bb4b07 100644 --- a/resources/i18n/en.json5 +++ b/resources/i18n/en.json5 @@ -121,6 +121,7 @@ "chips.remove": "Remove chip", "collection.create.head": "Create a Collection", + "collection.create.notifications.success": "Successfully created the Collection", "collection.create.sub-head": "Create a Collection for Community {{ parent }}", "collection.delete.cancel": "Cancel", "collection.delete.confirm": "Confirm", @@ -137,6 +138,7 @@ "collection.edit.logo.notifications.delete.success.content": "Successfully deleted the collection's logo", "collection.edit.logo.notifications.delete.error.title": "Error deleting logo", "collection.edit.logo.upload": "Drop a Collection Logo to upload", + "collection.edit.notifications.success": "Successfully edited the Collection", "collection.form.abstract": "Short Description", "collection.form.description": "Introductory text (HTML)", "collection.form.errors.title.required": "Please enter a collection name", @@ -151,6 +153,7 @@ "collection.page.news": "News", "community.create.head": "Create a Community", + "community.create.notifications.success": "Successfully created the Community", "community.create.sub-head": "Create a Sub-Community for Community {{ parent }}", "community.delete.cancel": "Cancel", "community.delete.confirm": "Confirm", @@ -167,6 +170,7 @@ "community.edit.logo.notifications.delete.success.content": "Successfully deleted the community's logo", "community.edit.logo.notifications.delete.error.title": "Error deleting logo", "community.edit.logo.upload": "Drop a Community Logo to upload", + "community.edit.notifications.success": "Successfully edited the Community", "community.form.abstract": "Short Description", "community.form.description": "Introductory text (HTML)", "community.form.errors.title.required": "Please enter a community name", diff --git a/src/app/+collection-page/create-collection-page/create-collection-page.component.spec.ts b/src/app/+collection-page/create-collection-page/create-collection-page.component.spec.ts index e223b11c65..869a89d5e0 100644 --- a/src/app/+collection-page/create-collection-page/create-collection-page.component.spec.ts +++ b/src/app/+collection-page/create-collection-page/create-collection-page.component.spec.ts @@ -10,6 +10,8 @@ import { CollectionDataService } from '../../core/data/collection-data.service'; import { of as observableOf } from 'rxjs'; import { CommunityDataService } from '../../core/data/community-data.service'; import { CreateCollectionPageComponent } from './create-collection-page.component'; +import { NotificationsService } from '../../shared/notifications/notifications.service'; +import { NotificationsServiceStub } from '../../shared/testing/notifications-service-stub'; describe('CreateCollectionPageComponent', () => { let comp: CreateCollectionPageComponent; @@ -27,6 +29,7 @@ describe('CreateCollectionPageComponent', () => { }, { provide: RouteService, useValue: { getQueryParameterValue: () => observableOf('1234') } }, { provide: Router, useValue: {} }, + { provide: NotificationsService, useValue: new NotificationsServiceStub() } ], schemas: [NO_ERRORS_SCHEMA] }).compileComponents(); diff --git a/src/app/+collection-page/create-collection-page/create-collection-page.component.ts b/src/app/+collection-page/create-collection-page/create-collection-page.component.ts index 2cab36d285..ae31b94c3d 100644 --- a/src/app/+collection-page/create-collection-page/create-collection-page.component.ts +++ b/src/app/+collection-page/create-collection-page/create-collection-page.component.ts @@ -5,6 +5,8 @@ import { Router } from '@angular/router'; import { CreateComColPageComponent } from '../../shared/comcol-forms/create-comcol-page/create-comcol-page.component'; import { Collection } from '../../core/shared/collection.model'; import { CollectionDataService } from '../../core/data/collection-data.service'; +import { NotificationsService } from '../../shared/notifications/notifications.service'; +import { TranslateService } from '@ngx-translate/core'; /** * Component that represents the page where a user can create a new Collection @@ -16,13 +18,16 @@ import { CollectionDataService } from '../../core/data/collection-data.service'; }) export class CreateCollectionPageComponent extends CreateComColPageComponent { protected frontendURL = '/collections/'; + protected type = Collection.type; public constructor( protected communityDataService: CommunityDataService, protected collectionDataService: CollectionDataService, protected routeService: RouteService, - protected router: Router + protected router: Router, + protected notificationsService: NotificationsService, + protected translate: TranslateService ) { - super(collectionDataService, communityDataService, routeService, router); + super(collectionDataService, communityDataService, routeService, router, notificationsService, translate); } } 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 193cb293e4..8f82c30ff4 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 @@ -8,6 +8,8 @@ import { EditCollectionPageComponent } from './edit-collection-page.component'; import { SharedModule } from '../../shared/shared.module'; import { CollectionDataService } from '../../core/data/collection-data.service'; import { of as observableOf } from 'rxjs'; +import { NotificationsService } from '../../shared/notifications/notifications.service'; +import { NotificationsServiceStub } from '../../shared/testing/notifications-service-stub'; describe('EditCollectionPageComponent', () => { let comp: EditCollectionPageComponent; @@ -20,6 +22,7 @@ describe('EditCollectionPageComponent', () => { providers: [ { provide: CollectionDataService, useValue: {} }, { provide: ActivatedRoute, useValue: { data: observableOf({ dso: { payload: {} } }) } }, + { provide: NotificationsService, useValue: new NotificationsServiceStub() } ], schemas: [NO_ERRORS_SCHEMA] }).compileComponents(); diff --git a/src/app/+collection-page/edit-collection-page/edit-collection-page.component.ts b/src/app/+collection-page/edit-collection-page/edit-collection-page.component.ts index ba70bd26c6..310fbb1427 100644 --- a/src/app/+collection-page/edit-collection-page/edit-collection-page.component.ts +++ b/src/app/+collection-page/edit-collection-page/edit-collection-page.component.ts @@ -3,6 +3,8 @@ import { ActivatedRoute, Router } from '@angular/router'; import { EditComColPageComponent } from '../../shared/comcol-forms/edit-comcol-page/edit-comcol-page.component'; import { Collection } from '../../core/shared/collection.model'; import { CollectionDataService } from '../../core/data/collection-data.service'; +import { NotificationsService } from '../../shared/notifications/notifications.service'; +import { TranslateService } from '@ngx-translate/core'; /** * Component that represents the page where a user can edit an existing Collection @@ -14,12 +16,15 @@ import { CollectionDataService } from '../../core/data/collection-data.service'; }) export class EditCollectionPageComponent extends EditComColPageComponent { protected frontendURL = '/collections/'; + protected type = Collection.type; public constructor( protected collectionDataService: CollectionDataService, protected router: Router, - protected route: ActivatedRoute + protected route: ActivatedRoute, + protected notificationsService: NotificationsService, + protected translate: TranslateService ) { - super(collectionDataService, router, route); + super(collectionDataService, router, route, notificationsService, translate); } } diff --git a/src/app/+community-page/create-community-page/create-community-page.component.spec.ts b/src/app/+community-page/create-community-page/create-community-page.component.spec.ts index dead5a5c3b..d0de8ec71c 100644 --- a/src/app/+community-page/create-community-page/create-community-page.component.spec.ts +++ b/src/app/+community-page/create-community-page/create-community-page.component.spec.ts @@ -10,6 +10,8 @@ import { CollectionDataService } from '../../core/data/collection-data.service'; import { of as observableOf } from 'rxjs'; import { CommunityDataService } from '../../core/data/community-data.service'; import { CreateCommunityPageComponent } from './create-community-page.component'; +import { NotificationsService } from '../../shared/notifications/notifications.service'; +import { NotificationsServiceStub } from '../../shared/testing/notifications-service-stub'; describe('CreateCommunityPageComponent', () => { let comp: CreateCommunityPageComponent; @@ -23,6 +25,7 @@ describe('CreateCommunityPageComponent', () => { { provide: CommunityDataService, useValue: { findById: () => observableOf({}) } }, { provide: RouteService, useValue: { getQueryParameterValue: () => observableOf('1234') } }, { provide: Router, useValue: {} }, + { provide: NotificationsService, useValue: new NotificationsServiceStub() } ], schemas: [NO_ERRORS_SCHEMA] }).compileComponents(); diff --git a/src/app/+community-page/create-community-page/create-community-page.component.ts b/src/app/+community-page/create-community-page/create-community-page.component.ts index fd5f18442a..30a2acbb0d 100644 --- a/src/app/+community-page/create-community-page/create-community-page.component.ts +++ b/src/app/+community-page/create-community-page/create-community-page.component.ts @@ -4,6 +4,8 @@ import { CommunityDataService } from '../../core/data/community-data.service'; import { RouteService } from '../../core/services/route.service'; import { Router } from '@angular/router'; import { CreateComColPageComponent } from '../../shared/comcol-forms/create-comcol-page/create-comcol-page.component'; +import { NotificationsService } from '../../shared/notifications/notifications.service'; +import { TranslateService } from '@ngx-translate/core'; /** * Component that represents the page where a user can create a new Community @@ -15,12 +17,15 @@ import { CreateComColPageComponent } from '../../shared/comcol-forms/create-comc }) export class CreateCommunityPageComponent extends CreateComColPageComponent { protected frontendURL = '/communities/'; + protected type = Community.type; public constructor( protected communityDataService: CommunityDataService, protected routeService: RouteService, - protected router: Router + protected router: Router, + protected notificationsService: NotificationsService, + protected translate: TranslateService ) { - super(communityDataService, communityDataService, routeService, router); + super(communityDataService, communityDataService, routeService, router, notificationsService, translate); } } 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 54f2133ce7..86b1647c90 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 @@ -8,6 +8,8 @@ import { SharedModule } from '../../shared/shared.module'; import { of as observableOf } from 'rxjs'; import { EditCommunityPageComponent } from './edit-community-page.component'; import { CommunityDataService } from '../../core/data/community-data.service'; +import { NotificationsService } from '../../shared/notifications/notifications.service'; +import { NotificationsServiceStub } from '../../shared/testing/notifications-service-stub'; describe('EditCommunityPageComponent', () => { let comp: EditCommunityPageComponent; @@ -20,6 +22,7 @@ describe('EditCommunityPageComponent', () => { providers: [ { provide: CommunityDataService, useValue: {} }, { provide: ActivatedRoute, useValue: { data: observableOf({ dso: { payload: {} } }) } }, + { provide: NotificationsService, useValue: new NotificationsServiceStub() } ], schemas: [NO_ERRORS_SCHEMA] }).compileComponents(); diff --git a/src/app/+community-page/edit-community-page/edit-community-page.component.ts b/src/app/+community-page/edit-community-page/edit-community-page.component.ts index 9f49ac49dd..c9eea974f7 100644 --- a/src/app/+community-page/edit-community-page/edit-community-page.component.ts +++ b/src/app/+community-page/edit-community-page/edit-community-page.component.ts @@ -3,6 +3,8 @@ import { Community } from '../../core/shared/community.model'; import { CommunityDataService } from '../../core/data/community-data.service'; import { ActivatedRoute, Router } from '@angular/router'; import { EditComColPageComponent } from '../../shared/comcol-forms/edit-comcol-page/edit-comcol-page.component'; +import { NotificationsService } from '../../shared/notifications/notifications.service'; +import { TranslateService } from '@ngx-translate/core'; /** * Component that represents the page where a user can edit an existing Community @@ -14,12 +16,15 @@ import { EditComColPageComponent } from '../../shared/comcol-forms/edit-comcol-p }) export class EditCommunityPageComponent extends EditComColPageComponent { protected frontendURL = '/communities/'; + protected type = Community.type; public constructor( protected communityDataService: CommunityDataService, protected router: Router, - protected route: ActivatedRoute + protected route: ActivatedRoute, + protected notificationsService: NotificationsService, + protected translate: TranslateService ) { - super(communityDataService, router, route); + super(communityDataService, router, route, notificationsService, translate); } } diff --git a/src/app/shared/comcol-forms/create-comcol-page/create-comcol-page.component.spec.ts b/src/app/shared/comcol-forms/create-comcol-page/create-comcol-page.component.spec.ts index 99aac6757e..717979891f 100644 --- a/src/app/shared/comcol-forms/create-comcol-page/create-comcol-page.component.spec.ts +++ b/src/app/shared/comcol-forms/create-comcol-page/create-comcol-page.component.spec.ts @@ -16,6 +16,8 @@ import { createSuccessfulRemoteDataObject$ } from '../../testing/utils'; import { ComColDataService } from '../../../core/data/comcol-data.service'; +import { NotificationsService } from '../../notifications/notifications.service'; +import { NotificationsServiceStub } from '../../testing/notifications-service-stub'; describe('CreateComColPageComponent', () => { let comp: CreateComColPageComponent; @@ -80,6 +82,7 @@ describe('CreateComColPageComponent', () => { { provide: CommunityDataService, useValue: communityDataServiceStub }, { provide: RouteService, useValue: routeServiceStub }, { provide: Router, useValue: routerStub }, + { provide: NotificationsService, useValue: new NotificationsServiceStub() } ], schemas: [NO_ERRORS_SCHEMA] }).compileComponents(); @@ -88,6 +91,7 @@ describe('CreateComColPageComponent', () => { beforeEach(() => { fixture = TestBed.createComponent(CreateComColPageComponent); comp = fixture.componentInstance; + (comp as any).type = Community.type; fixture.detectChanges(); dsoDataService = (comp as any).dsoDataService; communityDataService = (comp as any).communityDataService; 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 baa05ac5e7..7b23c59498 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 @@ -3,7 +3,7 @@ import { Community } from '../../../core/shared/community.model'; import { CommunityDataService } from '../../../core/data/community-data.service'; import { Observable } from 'rxjs'; import { RouteService } from '../../../core/services/route.service'; -import { Router } from '@angular/router'; +import { ActivatedRoute, Router } from '@angular/router'; import { RemoteData } from '../../../core/data/remote-data'; import { hasValue, isNotEmpty, isNotUndefined } from '../../empty.util'; import { take } from 'rxjs/operators'; @@ -11,6 +11,9 @@ import { getSucceededRemoteData } from '../../../core/shared/operators'; import { DSpaceObject } from '../../../core/shared/dspace-object.model'; import { DataService } from '../../../core/data/data.service'; import { ComColDataService } from '../../../core/data/comcol-data.service'; +import { NotificationsService } from '../../notifications/notifications.service'; +import { TranslateService } from '@ngx-translate/core'; +import { ResourceType } from '../../../core/shared/resource-type'; /** * Component representing the create page for communities and collections @@ -40,11 +43,18 @@ export class CreateComColPageComponent implements */ private newUUID: string; + /** + * The type of the dso + */ + protected type: ResourceType; + public constructor( protected dsoDataService: ComColDataService, protected parentDataService: CommunityDataService, protected routeService: RouteService, - protected router: Router + protected router: Router, + protected notificationsService: NotificationsService, + protected translate: TranslateService ) { } @@ -80,6 +90,7 @@ export class CreateComColPageComponent implements } else { this.navigateToNewPage(); } + this.notificationsService.success(null, this.translate.get(this.type.value + '.create.notifications.success')); } }); }); diff --git a/src/app/shared/comcol-forms/edit-comcol-page/edit-comcol-page.component.spec.ts b/src/app/shared/comcol-forms/edit-comcol-page/edit-comcol-page.component.spec.ts index 2a52049df5..f2b45e8ed4 100644 --- a/src/app/shared/comcol-forms/edit-comcol-page/edit-comcol-page.component.spec.ts +++ b/src/app/shared/comcol-forms/edit-comcol-page/edit-comcol-page.component.spec.ts @@ -16,6 +16,8 @@ import { } from '../../testing/utils'; import { ComColDataService } from '../../../core/data/comcol-data.service'; import { RemoteData } from '../../../core/data/remote-data'; +import { NotificationsService } from '../../notifications/notifications.service'; +import { NotificationsServiceStub } from '../../testing/notifications-service-stub'; describe('EditComColPageComponent', () => { let comp: EditComColPageComponent; @@ -73,6 +75,7 @@ describe('EditComColPageComponent', () => { { provide: ComColDataService, useValue: communityDataServiceStub }, { provide: Router, useValue: routerStub }, { provide: ActivatedRoute, useValue: routeStub }, + { provide: NotificationsService, useValue: new NotificationsServiceStub() } ], schemas: [NO_ERRORS_SCHEMA] }).compileComponents(); @@ -81,6 +84,7 @@ describe('EditComColPageComponent', () => { beforeEach(() => { fixture = TestBed.createComponent(EditComColPageComponent); comp = fixture.componentInstance; + (comp as any).type = Community.type; fixture.detectChanges(); dsoDataService = (comp as any).dsoDataService; router = (comp as any).router; 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 ec4a7fd745..19ba578cd6 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 @@ -8,6 +8,9 @@ import { getSucceededRemoteData } from '../../../core/shared/operators'; import { DataService } from '../../../core/data/data.service'; import { DSpaceObject } from '../../../core/shared/dspace-object.model'; import { ComColDataService } from '../../../core/data/comcol-data.service'; +import { NotificationsService } from '../../notifications/notifications.service'; +import { TranslateService } from '@ngx-translate/core'; +import { ResourceType } from '../../../core/shared/resource-type'; /** * Component representing the edit page for communities and collections @@ -26,10 +29,17 @@ export class EditComColPageComponent implements On */ public dsoRD$: Observable>; + /** + * The type of the dso + */ + protected type: ResourceType; + public constructor( protected dsoDataService: ComColDataService, protected router: Router, - protected route: ActivatedRoute + protected route: ActivatedRoute, + protected notificationsService: NotificationsService, + protected translate: TranslateService ) { } @@ -58,6 +68,7 @@ export class EditComColPageComponent implements On } else { this.router.navigate([this.frontendURL + newUUID]); } + this.notificationsService.success(null, this.translate.get(this.type.value + '.edit.notifications.success')); } }); } From e10a5bb8f81e5a780de51650d152dd8f8b8bae30 Mon Sep 17 00:00:00 2001 From: Kristof De Langhe Date: Thu, 3 Oct 2019 14:39:46 +0200 Subject: [PATCH 12/26] 63669: Hide return button for metadata edit on com/col --- .../edit-collection-page.routing.module.ts | 5 ++++- .../edit-comcol-page/edit-comcol-page.component.html | 2 +- .../edit-comcol-page/edit-comcol-page.component.ts | 7 +++++++ 3 files changed, 12 insertions(+), 2 deletions(-) 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 a3eab30d73..fcfced9d81 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 @@ -28,7 +28,10 @@ import { CollectionCurateComponent } from './collection-curate/collection-curate { path: 'metadata', component: CollectionMetadataComponent, - data: { title: 'collection.edit.tabs.metadata.title' } + data: { + title: 'collection.edit.tabs.metadata.title', + hideReturnButton: true + } }, { path: 'roles', 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 964fea35e3..aa6290ea9f 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 @@ -16,7 +16,7 @@
- {{ type + '.edit.return' | translate }} + {{ type + '.edit.return' | 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 9face94abd..b1b37f265e 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 @@ -36,12 +36,19 @@ export class EditComColPageComponent implements On */ public dsoRD$: Observable>; + /** + * Hide the default return button? + */ + public hideReturnButton: boolean; + public constructor( 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; }); } From ac68893f6e2c7c667b040ae56518734bcc10fe56 Mon Sep 17 00:00:00 2001 From: Kristof De Langhe Date: Fri, 4 Oct 2019 15:47:52 +0200 Subject: [PATCH 13/26] 63669: Test fix --- .../edit-comcol-page/edit-comcol-page.component.spec.ts | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/app/shared/comcol-forms/edit-comcol-page/edit-comcol-page.component.spec.ts b/src/app/shared/comcol-forms/edit-comcol-page/edit-comcol-page.component.spec.ts index 8d1023e66d..d1b87db7ae 100644 --- a/src/app/shared/comcol-forms/edit-comcol-page/edit-comcol-page.component.spec.ts +++ b/src/app/shared/comcol-forms/edit-comcol-page/edit-comcol-page.component.spec.ts @@ -39,7 +39,14 @@ describe('EditComColPageComponent', () => { dso: community }), routeConfig: { - children: [] + children: [ + { + path: 'mockUrl', + data: { + hideReturnButton: false + } + } + ] }, snapshot: { firstChild: { From c9ea9904839544c2bffc62b3964be92a6b6336e5 Mon Sep 17 00:00:00 2001 From: Kristof De Langhe Date: Mon, 7 Oct 2019 13:43:26 +0200 Subject: [PATCH 14/26] 63669: Hide return button on community metadata edit --- .../edit-community-page.routing.module.ts | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) 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 527b3c018f..1182db2de1 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 @@ -27,7 +27,10 @@ import { CommunityCurateComponent } from './community-curate/community-curate.co { path: 'metadata', component: CommunityMetadataComponent, - data: { title: 'community.edit.tabs.metadata.title' } + data: { + title: 'community.edit.tabs.metadata.title', + hideReturnButton: true + } }, { path: 'roles', From bfb2ef021a47c8c94ca2ddb8c75f9511ad96be14 Mon Sep 17 00:00:00 2001 From: Kristof De Langhe Date: Mon, 7 Oct 2019 14:05:54 +0200 Subject: [PATCH 15/26] 65240: AoT build error fixes --- .../collection-form/collection-form.component.ts | 3 +-- .../edit-collection-page.component.ts | 2 +- .../community-form/community-form.component.ts | 2 +- .../edit-community-page/edit-community-page.component.ts | 2 +- .../comcol-forms/comcol-form/comcol-form.component.ts | 4 ++-- .../edit-comcol-page/edit-comcol-page.component.ts | 2 +- src/app/shared/uploader/uploader.component.spec.ts | 4 ++-- .../submission-upload-files.component.spec.ts | 9 +++++---- 8 files changed, 14 insertions(+), 14 deletions(-) diff --git a/src/app/+collection-page/collection-form/collection-form.component.ts b/src/app/+collection-page/collection-form/collection-form.component.ts index d91d9fc1fb..a1d6a08290 100644 --- a/src/app/+collection-page/collection-form/collection-form.component.ts +++ b/src/app/+collection-page/collection-form/collection-form.component.ts @@ -3,7 +3,6 @@ import { DynamicFormService, DynamicInputModel, DynamicTextAreaModel } from '@ng import { DynamicFormControlModel } from '@ng-dynamic-forms/core/src/model/dynamic-form-control.model'; import { Collection } from '../../core/shared/collection.model'; import { ComColFormComponent } from '../../shared/comcol-forms/comcol-form/comcol-form.component'; -import { NormalizedCollection } from '../../core/cache/models/normalized-collection.model'; import { Location } from '@angular/common'; import { TranslateService } from '@ngx-translate/core'; import { NotificationsService } from '../../shared/notifications/notifications.service'; @@ -27,7 +26,7 @@ export class CollectionFormComponent extends ComColFormComponent { /** * @type {Collection.type} This is a collection-type form */ - protected type = Collection.type; + type = Collection.type; /** * The dynamic form fields used for creating/editing a collection diff --git a/src/app/+collection-page/edit-collection-page/edit-collection-page.component.ts b/src/app/+collection-page/edit-collection-page/edit-collection-page.component.ts index 21671fe112..209ce5149a 100644 --- a/src/app/+collection-page/edit-collection-page/edit-collection-page.component.ts +++ b/src/app/+collection-page/edit-collection-page/edit-collection-page.component.ts @@ -12,7 +12,7 @@ import { getCollectionPageRoute } from '../collection-page-routing.module'; templateUrl: '../../shared/comcol-forms/edit-comcol-page/edit-comcol-page.component.html' }) export class EditCollectionPageComponent extends EditComColPageComponent { - protected type = 'collection'; + type = 'collection'; public constructor( protected router: Router, 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 fc1e77c445..8e4f98c14e 100644 --- a/src/app/+community-page/community-form/community-form.component.ts +++ b/src/app/+community-page/community-form/community-form.component.ts @@ -27,7 +27,7 @@ export class CommunityFormComponent extends ComColFormComponent { /** * @type {Community.type} This is a community-type form */ - protected type = Community.type; + type = Community.type; /** * The dynamic form fields used for creating/editing a community diff --git a/src/app/+community-page/edit-community-page/edit-community-page.component.ts b/src/app/+community-page/edit-community-page/edit-community-page.component.ts index a8d4d32b7d..c0adfe0ff1 100644 --- a/src/app/+community-page/edit-community-page/edit-community-page.component.ts +++ b/src/app/+community-page/edit-community-page/edit-community-page.component.ts @@ -12,7 +12,7 @@ import { getCommunityPageRoute } from '../community-page-routing.module'; templateUrl: '../../shared/comcol-forms/edit-comcol-page/edit-comcol-page.component.html' }) export class EditCommunityPageComponent extends EditComColPageComponent { - protected type = 'community'; + type = 'community'; public constructor( protected router: Router, 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 6e8b04e589..1fdaac33dd 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 @@ -47,7 +47,7 @@ export class ComColFormComponent implements OnInit, OnDe /** * Type of DSpaceObject that the form represents */ - protected type: ResourceType; + type: ResourceType; /** * @type {string} Key prefix used to generate form labels @@ -95,7 +95,7 @@ export class ComColFormComponent implements OnInit, OnDe * Observable keeping track whether or not the uploader has finished initializing * Used to start rendering the uploader component */ - private initializedUploaderOptions = new BehaviorSubject(false); + initializedUploaderOptions = new BehaviorSubject(false); /** * Array to track all subscriptions and unsubscribe them onDestroy 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 b1b37f265e..0f9d4c55b4 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 @@ -19,7 +19,7 @@ export class EditComColPageComponent implements On /** * The type of DSpaceObject (used to create i18n messages) */ - protected type: string; + public type: string; /** * The current page outlet string diff --git a/src/app/shared/uploader/uploader.component.spec.ts b/src/app/shared/uploader/uploader.component.spec.ts index a36bd7241b..dcdac911bf 100644 --- a/src/app/shared/uploader/uploader.component.spec.ts +++ b/src/app/shared/uploader/uploader.component.spec.ts @@ -64,12 +64,12 @@ describe('Chips component', () => { template: `` }) class TestComponent { - public uploadFilesOptions: UploaderOptions = { + public uploadFilesOptions: UploaderOptions = Object.assign(new UploaderOptions(), { url: 'http://test', authToken: null, disableMultipart: false, itemAlias: null - }; + }); /* tslint:disable:no-empty */ public onBeforeUpload = () => { diff --git a/src/app/submission/form/submission-upload-files/submission-upload-files.component.spec.ts b/src/app/submission/form/submission-upload-files/submission-upload-files.component.spec.ts index 60a572df54..34d291f0e4 100644 --- a/src/app/submission/form/submission-upload-files/submission-upload-files.component.spec.ts +++ b/src/app/submission/form/submission-upload-files/submission-upload-files.component.spec.ts @@ -28,6 +28,7 @@ import { SubmissionJsonPatchOperationsServiceStub } from '../../../shared/testin import { SubmissionJsonPatchOperationsService } from '../../../core/submission/submission-json-patch-operations.service'; import { SharedModule } from '../../../shared/shared.module'; import { createTestComponent } from '../../../shared/testing/utils'; +import { UploaderOptions } from '../../../shared/uploader/uploader-options.model'; describe('SubmissionUploadFilesComponent Component', () => { @@ -112,12 +113,12 @@ describe('SubmissionUploadFilesComponent Component', () => { comp.submissionId = submissionId; comp.collectionId = collectionId; comp.sectionId = 'upload'; - comp.uploadFilesOptions = { + comp.uploadFilesOptions = Object.assign(new UploaderOptions(),{ url: '', authToken: null, disableMultipart: false, itemAlias: null - }; + }); }); @@ -208,11 +209,11 @@ class TestComponent { submissionId = mockSubmissionId; collectionId = mockSubmissionCollectionId; sectionId = 'upload'; - uploadFilesOptions = { + uploadFilesOptions = Object.assign(new UploaderOptions(), { url: '', authToken: null, disableMultipart: false, itemAlias: null - }; + }); } From c7bb6ab17c777a52a9d3614573fc878810bf33cf Mon Sep 17 00:00:00 2001 From: Kristof De Langhe Date: Thu, 17 Oct 2019 17:59:18 +0200 Subject: [PATCH 16/26] 65240: ComCol logo delete on bitstreams endpoint + caching issue fixes when editing logos --- .../collection-form.component.ts | 8 +++- .../community-form.component.ts | 8 +++- src/app/core/data/comcol-data.service.ts | 41 ++++++++++++++----- .../comcol-form/comcol-form.component.html | 40 +++++++++++------- .../comcol-form/comcol-form.component.ts | 21 ++++++++-- 5 files changed, 85 insertions(+), 33 deletions(-) diff --git a/src/app/+collection-page/collection-form/collection-form.component.ts b/src/app/+collection-page/collection-form/collection-form.component.ts index a1d6a08290..76ba549f14 100644 --- a/src/app/+collection-page/collection-form/collection-form.component.ts +++ b/src/app/+collection-page/collection-form/collection-form.component.ts @@ -8,6 +8,8 @@ import { TranslateService } from '@ngx-translate/core'; import { NotificationsService } from '../../shared/notifications/notifications.service'; import { CommunityDataService } from '../../core/data/community-data.service'; import { AuthService } from '../../core/auth/auth.service'; +import { RequestService } from '../../core/data/request.service'; +import { ObjectCacheService } from '../../core/cache/object-cache.service'; /** * Form used for creating and editing collections @@ -75,7 +77,9 @@ export class CollectionFormComponent extends ComColFormComponent { protected translate: TranslateService, protected notificationsService: NotificationsService, protected authService: AuthService, - protected dsoService: CommunityDataService) { - super(location, formService, translate, notificationsService, authService); + protected dsoService: CommunityDataService, + protected requestService: RequestService, + protected objectCache: ObjectCacheService) { + super(location, formService, translate, notificationsService, authService, requestService, objectCache); } } 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 8e4f98c14e..1f081bd81b 100644 --- a/src/app/+community-page/community-form/community-form.component.ts +++ b/src/app/+community-page/community-form/community-form.component.ts @@ -9,6 +9,8 @@ import { TranslateService } from '@ngx-translate/core'; import { NotificationsService } from '../../shared/notifications/notifications.service'; import { CommunityDataService } from '../../core/data/community-data.service'; import { AuthService } from '../../core/auth/auth.service'; +import { RequestService } from '../../core/data/request.service'; +import { ObjectCacheService } from '../../core/cache/object-cache.service'; /** * Form used for creating and editing communities @@ -68,7 +70,9 @@ export class CommunityFormComponent extends ComColFormComponent { protected translate: TranslateService, protected notificationsService: NotificationsService, protected authService: AuthService, - protected dsoService: CommunityDataService) { - super(location, formService, translate, notificationsService, authService); + protected dsoService: CommunityDataService, + protected requestService: RequestService, + protected objectCache: ObjectCacheService) { + super(location, formService, translate, notificationsService, authService, requestService, objectCache); } } diff --git a/src/app/core/data/comcol-data.service.ts b/src/app/core/data/comcol-data.service.ts index ba17d04d76..60bd837163 100644 --- a/src/app/core/data/comcol-data.service.ts +++ b/src/app/core/data/comcol-data.service.ts @@ -1,6 +1,6 @@ import { distinctUntilChanged, filter, map, mergeMap, share, switchMap, take, tap } from 'rxjs/operators'; -import { merge as observableMerge, Observable, throwError as observableThrowError } from 'rxjs'; -import { isEmpty, isNotEmpty } from '../../shared/empty.util'; +import { merge as observableMerge, Observable, throwError as observableThrowError, combineLatest as observableCombineLatest } from 'rxjs'; +import { hasValue, isEmpty, isNotEmpty } from '../../shared/empty.util'; import { NormalizedCommunity } from '../cache/models/normalized-community.model'; import { ObjectCacheService } from '../cache/object-cache.service'; import { CommunityDataService } from './community-data.service'; @@ -8,15 +8,27 @@ import { CommunityDataService } from './community-data.service'; import { DataService } from './data.service'; import { DeleteRequest, FindAllOptions, FindByIDRequest, RestRequest } from './request.models'; import { HALEndpointService } from '../shared/hal-endpoint.service'; -import { configureRequest, getResponseFromEntry } from '../shared/operators'; +import { + configureRequest, + getRemoteDataPayload, + getResponseFromEntry, + getSucceededRemoteData +} from '../shared/operators'; import { CacheableObject } from '../cache/object-cache.reducer'; import { RestResponse } from '../cache/response.models'; +import { Bitstream } from '../shared/bitstream.model'; +import { DSpaceObject } from '../shared/dspace-object.model'; export abstract class ComColDataService extends DataService { protected abstract cds: CommunityDataService; protected abstract objectCache: ObjectCacheService; protected abstract halService: HALEndpointService; + /** + * Linkpath of endpoint to delete the logo + */ + protected logoDeleteLinkpath = 'bitstreams'; + /** * Get the scoped endpoint URL by fetching the object with * the given scopeID and returning its HAL link with this @@ -71,14 +83,21 @@ export abstract class ComColDataService extends DataS /** * Delete the logo from the community or collection - * @param id The community or collection's ID + * @param dso The object to delete the logo from */ - public deleteLogo(id: string): Observable { - return this.getLogoEndpoint(id).pipe( - map((href: string) => new DeleteRequest(this.requestService.generateRequestId(), href)), - configureRequest(this.requestService), - switchMap((restRequest: RestRequest) => this.requestService.getByUUID(restRequest.uuid)), - getResponseFromEntry() - ); + public deleteLogo(dso: DSpaceObject): Observable { + const logo$ = (dso as any).logo; + if (hasValue(logo$)) { + return observableCombineLatest( + logo$.pipe(getSucceededRemoteData(), getRemoteDataPayload(), take(1)), + this.halService.getEndpoint(this.logoDeleteLinkpath) + ).pipe( + map(([logo, href]: [Bitstream, string]) => `${href}/${logo.id}`), + map((href: string) => new DeleteRequest(this.requestService.generateRequestId(), href)), + configureRequest(this.requestService), + switchMap((restRequest: RestRequest) => this.requestService.getByUUID(restRequest.uuid)), + getResponseFromEntry() + ); + } } } 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 b65e6e8f80..fafe796107 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 @@ -1,20 +1,30 @@
- - - -
- +
+
+
- - + +
+ +
+
+
+ +
+
+
+ +
+
+
implements OnInit, OnDe * @type {UploaderOptions} */ uploadFilesOptions: UploaderOptions = Object.assign(new UploaderOptions(), { - disableMultipart: true, autoUpload: false }); @@ -112,7 +114,9 @@ export class ComColFormComponent implements OnInit, OnDe protected formService: DynamicFormService, protected translate: TranslateService, protected notificationsService: NotificationsService, - protected authService: AuthService) { + protected authService: AuthService, + protected requestService: RequestService, + protected objectCache: ObjectCacheService) { } ngOnInit(): void { @@ -204,7 +208,7 @@ export class ComColFormComponent implements OnInit, OnDe */ deleteLogo() { if (hasValue(this.dso.id)) { - this.dsoService.deleteLogo(this.dso.id).subscribe((response: RestResponse) => { + this.dsoService.deleteLogo(this.dso).subscribe((response: RestResponse) => { if (response.isSuccessful) { this.notificationsService.success( this.translate.get(this.type.value + '.edit.logo.notifications.delete.success.title'), @@ -217,14 +221,25 @@ export class ComColFormComponent implements OnInit, OnDe errorResponse.errorMessage ); } + this.refreshCache(); }); } } + /** + * Refresh the object's cache to ensure the latest version + */ + private refreshCache() { + (this.dso as any).logo = undefined; + this.requestService.removeByHrefSubstring(this.dso.self); + this.objectCache.remove(this.dso.self); + } + /** * The request was successful, display a success notification */ public onCompleteItem() { + this.refreshCache(); this.notificationsService.success(null, this.translate.get(this.type.value + '.edit.logo.notifications.add.success')); this.finishUpload.emit(); } From 1fafc3a5d54bcfee13e831e48309f5d1a24fc359 Mon Sep 17 00:00:00 2001 From: Kristof De Langhe Date: Fri, 18 Oct 2019 10:35:25 +0200 Subject: [PATCH 17/26] 65240: Additional tests --- .../comcol-form/comcol-form.component.spec.ts | 28 ++++++++++++++++++- 1 file changed, 27 insertions(+), 1 deletion(-) 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 455e2ef4e0..0a7c55a118 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 @@ -20,6 +20,8 @@ import { RemoteData } from '../../../core/data/remote-data'; import { RestRequestMethod } from '../../../core/data/rest-request-method'; import { ErrorResponse, RestResponse } from '../../../core/cache/response.models'; import { RequestError } from '../../../core/data/request.models'; +import { RequestService } from '../../../core/data/request.service'; +import { ObjectCacheService } from '../../../core/cache/object-cache.service'; describe('ComColFormComponent', () => { let comp: ComColFormComponent; @@ -69,6 +71,13 @@ describe('ComColFormComponent', () => { const locationStub = jasmine.createSpyObj('location', ['back']); /* tslint:enable:no-empty */ + const requestServiceStub = jasmine.createSpyObj({ + removeByHrefSubstring: {} + }); + const objectCacheStub = jasmine.createSpyObj({ + remove: {} + }); + beforeEach(async(() => { TestBed.configureTestingModule({ imports: [TranslateModule.forRoot(), RouterTestingModule], @@ -77,7 +86,9 @@ describe('ComColFormComponent', () => { { provide: Location, useValue: locationStub }, { provide: DynamicFormService, useValue: formServiceStub }, { provide: NotificationsService, useValue: notificationsService }, - { provide: AuthService, useValue: new AuthServiceMock() } + { provide: AuthService, useValue: new AuthServiceMock() }, + { provide: RequestService, useValue: requestServiceStub }, + { provide: ObjectCacheService, useValue: objectCacheStub } ], schemas: [NO_ERRORS_SCHEMA] }).compileComponents(); @@ -151,6 +162,11 @@ describe('ComColFormComponent', () => { it('should emit finishUpload', () => { expect(comp.finishUpload.emit).toHaveBeenCalled(); }); + + it('should remove the object\'s cache', () => { + expect(requestServiceStub.removeByHrefSubstring).toHaveBeenCalled(); + expect(objectCacheStub.remove).toHaveBeenCalled(); + }); }); describe('onUploadError', () => { @@ -215,6 +231,11 @@ describe('ComColFormComponent', () => { it('should display a success notification', () => { expect(notificationsService.success).toHaveBeenCalled(); }); + + it('should remove the object\'s cache', () => { + expect(requestServiceStub.removeByHrefSubstring).toHaveBeenCalled(); + expect(objectCacheStub.remove).toHaveBeenCalled(); + }); }); describe('when dsoService.deleteLogo returns an error response', () => { @@ -228,6 +249,11 @@ describe('ComColFormComponent', () => { it('should display an error notification', () => { expect(notificationsService.error).toHaveBeenCalled(); }); + + it('should remove the object\'s cache', () => { + expect(requestServiceStub.removeByHrefSubstring).toHaveBeenCalled(); + expect(objectCacheStub.remove).toHaveBeenCalled(); + }); }); }); }); From 19a2ae6ecc25a6a8daa644c147c3a6c2a75fa56f Mon Sep 17 00:00:00 2001 From: Kristof De Langhe Date: Wed, 23 Oct 2019 10:59:14 +0200 Subject: [PATCH 18/26] 65240: ComCol logo caching issue fix --- .../comcol-forms/comcol-form/comcol-form.component.ts | 5 ++--- .../comcol-metadata/comcol-metadata.component.ts | 8 ++++---- 2 files changed, 6 insertions(+), 7 deletions(-) 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 eca3e16cc3..8a41efeef7 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 @@ -182,7 +182,7 @@ export class ComColFormComponent implements OnInit, OnDe }); this.submitForm.emit({ dso: updatedDSO, - uploader: this.uploaderComponent.uploader + uploader: hasValue(this.uploaderComponent) ? this.uploaderComponent.uploader : undefined }); } @@ -221,7 +221,7 @@ export class ComColFormComponent implements OnInit, OnDe errorResponse.errorMessage ); } - this.refreshCache(); + (this.dso as any).logo = undefined; }); } } @@ -230,7 +230,6 @@ export class ComColFormComponent implements OnInit, OnDe * Refresh the object's cache to ensure the latest version */ private refreshCache() { - (this.dso as any).logo = undefined; this.requestService.removeByHrefSubstring(this.dso.self); this.objectCache.remove(this.dso.self); } diff --git a/src/app/shared/comcol-forms/edit-comcol-page/comcol-metadata/comcol-metadata.component.ts b/src/app/shared/comcol-forms/edit-comcol-page/comcol-metadata/comcol-metadata.component.ts index 2e4f4b745c..fbea6e03d1 100644 --- a/src/app/shared/comcol-forms/edit-comcol-page/comcol-metadata/comcol-metadata.component.ts +++ b/src/app/shared/comcol-forms/edit-comcol-page/comcol-metadata/comcol-metadata.component.ts @@ -5,7 +5,7 @@ import { RemoteData } from '../../../../core/data/remote-data'; import { ActivatedRoute, Router } from '@angular/router'; import { first, map, take } from 'rxjs/operators'; import { getSucceededRemoteData } from '../../../../core/shared/operators'; -import { isNotUndefined } from '../../../empty.util'; +import { hasValue, isNotUndefined } from '../../../empty.util'; import { DataService } from '../../../../core/data/data.service'; import { ResourceType } from '../../../../core/shared/resource-type'; import { ComColDataService } from '../../../../core/data/comcol-data.service'; @@ -57,14 +57,14 @@ export class ComcolMetadataComponent implements On .subscribe((dsoRD: RemoteData) => { if (isNotUndefined(dsoRD)) { const newUUID = dsoRD.payload.uuid; - if (uploader.queue.length > 0) { + if (hasValue(uploader) && uploader.queue.length > 0) { this.dsoDataService.getLogoEndpoint(newUUID).pipe(take(1)).subscribe((href: string) => { uploader.options.url = href; uploader.uploadAll(); }); } else { - this.router.navigate([this.frontendURL + newUUID]); - } + this.router.navigate([this.frontendURL + newUUID]); + } this.notificationsService.success(null, this.translate.get(this.type.value + '.edit.notifications.success')); } }); From 896e19990ba3344e2c2a3df3b294a765955c3acf Mon Sep 17 00:00:00 2001 From: Kristof De Langhe Date: Wed, 23 Oct 2019 13:37:13 +0200 Subject: [PATCH 19/26] 65240: Removed old test cases --- .../comcol-form/comcol-form.component.spec.ts | 10 ---------- 1 file changed, 10 deletions(-) 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 0a7c55a118..51faa20280 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 @@ -231,11 +231,6 @@ describe('ComColFormComponent', () => { it('should display a success notification', () => { expect(notificationsService.success).toHaveBeenCalled(); }); - - it('should remove the object\'s cache', () => { - expect(requestServiceStub.removeByHrefSubstring).toHaveBeenCalled(); - expect(objectCacheStub.remove).toHaveBeenCalled(); - }); }); describe('when dsoService.deleteLogo returns an error response', () => { @@ -249,11 +244,6 @@ describe('ComColFormComponent', () => { it('should display an error notification', () => { expect(notificationsService.error).toHaveBeenCalled(); }); - - it('should remove the object\'s cache', () => { - expect(requestServiceStub.removeByHrefSubstring).toHaveBeenCalled(); - expect(objectCacheStub.remove).toHaveBeenCalled(); - }); }); }); }); From 89f4d660126141bb17000e17a0ea0440b9ac00cf Mon Sep 17 00:00:00 2001 From: Kristof De Langhe Date: Fri, 25 Oct 2019 11:37:43 +0200 Subject: [PATCH 20/26] 65240: Switch to POST requests after logo has been deleted --- src/app/shared/comcol-forms/comcol-form/comcol-form.component.ts | 1 + 1 file changed, 1 insertion(+) 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 8a41efeef7..c80a2e4506 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 @@ -222,6 +222,7 @@ export class ComColFormComponent implements OnInit, OnDe ); } (this.dso as any).logo = undefined; + this.uploadFilesOptions.method = RestRequestMethod.POST; }); } } From 792455f00751d27721f89cd9b8690c804f8eebf4 Mon Sep 17 00:00:00 2001 From: Kristof De Langhe Date: Tue, 12 Nov 2019 14:21:33 +0100 Subject: [PATCH 21/26] 65240: Uploader alignment fix --- resources/i18n/en.json5 | 2 +- src/app/shared/uploader/uploader.component.html | 11 +++++------ 2 files changed, 6 insertions(+), 7 deletions(-) diff --git a/resources/i18n/en.json5 b/resources/i18n/en.json5 index 9e31e31ddb..c4312c0d8f 100644 --- a/resources/i18n/en.json5 +++ b/resources/i18n/en.json5 @@ -819,7 +819,7 @@ "uploader.browse": "browse", "uploader.drag-message": "Drag & Drop your files here", - "uploader.or": ", or", + "uploader.or": ", or ", "uploader.processing": "Processing", "uploader.queue-length": "Queue length", } diff --git a/src/app/shared/uploader/uploader.component.html b/src/app/shared/uploader/uploader.component.html index a3181be21c..36078fbeb4 100644 --- a/src/app/shared/uploader/uploader.component.html +++ b/src/app/shared/uploader/uploader.component.html @@ -19,12 +19,11 @@ (fileOver)="fileOverBase($event)" class="well ds-base-drop-zone mt-1 mb-3 text-muted">

- {{dropMsg | translate}} {{'uploader.or' | translate}} - - + {{dropMsg | translate}} {{'uploader.or' | translate}} +

From 166aab606d412129a88476f86bd27bd6127e9a91 Mon Sep 17 00:00:00 2001 From: Kristof De Langhe Date: Tue, 12 Nov 2019 14:54:16 +0100 Subject: [PATCH 22/26] 65240: logo under browse --- .../collection-page.component.html | 14 ++++++++------ .../+community-page/community-page.component.html | 7 ++++--- 2 files changed, 12 insertions(+), 9 deletions(-) diff --git a/src/app/+collection-page/collection-page.component.html b/src/app/+collection-page/collection-page.component.html index 436cd351a0..a8a9a9fdd5 100644 --- a/src/app/+collection-page/collection-page.component.html +++ b/src/app/+collection-page/collection-page.component.html @@ -3,12 +3,7 @@ *ngVar="(collectionRD$ | async) as collectionRD">
-
- - - [alternateText]="'Collection Logo'"> - +
@@ -38,6 +33,13 @@ [contentType]="collection.type"> + + + +

{{'collection.page.browse.recent.head' | translate}}

diff --git a/src/app/+community-page/community-page.component.html b/src/app/+community-page/community-page.component.html index 05d0bd1d0e..87c64b79b7 100644 --- a/src/app/+community-page/community-page.component.html +++ b/src/app/+community-page/community-page.component.html @@ -2,9 +2,6 @@
- - - @@ -25,6 +22,10 @@ + + + + From 64978f2cfee26e8b11d8e59fe4584c15b5714bb9 Mon Sep 17 00:00:00 2001 From: Kristof De Langhe Date: Mon, 18 Nov 2019 16:28:51 +0100 Subject: [PATCH 23/26] 65240: Marking logo for deletion and request on form submit --- .../create-collection-page.component.html | 2 +- .../collection-metadata.component.html | 2 +- .../create-community-page.component.html | 2 +- .../community-metadata.component.html | 2 +- .../comcol-form/comcol-form.component.html | 23 ++++-- .../comcol-form/comcol-form.component.spec.ts | 81 ++++++++++++++++--- .../comcol-form/comcol-form.component.ts | 67 +++++++++------ .../comcol-metadata.component.ts | 3 +- 8 files changed, 133 insertions(+), 49 deletions(-) diff --git a/src/app/+collection-page/create-collection-page/create-collection-page.component.html b/src/app/+collection-page/create-collection-page/create-collection-page.component.html index dc5c5b186a..800d285846 100644 --- a/src/app/+collection-page/create-collection-page/create-collection-page.component.html +++ b/src/app/+collection-page/create-collection-page/create-collection-page.component.html @@ -4,5 +4,5 @@

{{'collection.create.sub-head' | translate:{ parent: (parentRD$| async)?.payload.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 dbfeab98ad..6f3a63790d 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 @@ -1,6 +1,6 @@ + (finish)="navigateToHomePage()"> {{'collection.edit.delete' | translate}} 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 c1b0cf5971..4f75771f6d 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,5 @@
- +
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 71c37f5697..6b441dbabd 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,6 @@ + (finish)="navigateToHomePage()"> {{'community.edit.delete' | translate}} 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 fafe796107..09f7e459e4 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 @@ -4,14 +4,21 @@
-
- -
-
-
- +
+
+
+ +
+
+
+ + +
+
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 51faa20280..7beafa510b 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 @@ -22,8 +22,9 @@ import { ErrorResponse, RestResponse } from '../../../core/cache/response.models import { RequestError } from '../../../core/data/request.models'; import { RequestService } from '../../../core/data/request.service'; import { ObjectCacheService } from '../../../core/cache/object-cache.service'; +import { By } from '@angular/platform-browser'; -describe('ComColFormComponent', () => { +fdescribe('ComColFormComponent', () => { let comp: ComColFormComponent; let fixture: ComponentFixture>; let location: Location; @@ -136,7 +137,8 @@ describe('ComColFormComponent', () => { type: Community.type }, ), - uploader: {} + uploader: {}, + deleteLogo: false } ); }) @@ -151,7 +153,7 @@ describe('ComColFormComponent', () => { describe('onCompleteItem', () => { beforeEach(() => { - spyOn(comp.finishUpload, 'emit'); + spyOn(comp.finish, 'emit'); comp.onCompleteItem(); }); @@ -159,8 +161,8 @@ describe('ComColFormComponent', () => { expect(notificationsService.success).toHaveBeenCalled(); }); - it('should emit finishUpload', () => { - expect(comp.finishUpload.emit).toHaveBeenCalled(); + it('should emit finish', () => { + expect(comp.finish.emit).toHaveBeenCalled(); }); it('should remove the object\'s cache', () => { @@ -171,7 +173,7 @@ describe('ComColFormComponent', () => { describe('onUploadError', () => { beforeEach(() => { - spyOn(comp.finishUpload, 'emit'); + spyOn(comp.finish, 'emit'); comp.onUploadError(); }); @@ -179,8 +181,8 @@ describe('ComColFormComponent', () => { expect(notificationsService.error).toHaveBeenCalled(); }); - it('should emit finishUpload', () => { - expect(comp.finishUpload.emit).toHaveBeenCalled(); + it('should emit finish', () => { + expect(comp.finish.emit).toHaveBeenCalled(); }); }); }); @@ -219,13 +221,17 @@ describe('ComColFormComponent', () => { expect(comp.uploadFilesOptions.method).toEqual(RestRequestMethod.PUT); }); - describe('deleteLogo', () => { + describe('submit with logo marked for deletion', () => { + beforeEach(() => { + comp.markLogoForDeletion = true; + }); + describe('when dsoService.deleteLogo returns a successful response', () => { const response = new RestResponse(true, 200, 'OK'); beforeEach(() => { spyOn(dsoService, 'deleteLogo').and.returnValue(observableOf(response)); - comp.deleteLogo(); + comp.onSubmit(); }); it('should display a success notification', () => { @@ -238,7 +244,7 @@ describe('ComColFormComponent', () => { beforeEach(() => { spyOn(dsoService, 'deleteLogo').and.returnValue(observableOf(response)); - comp.deleteLogo(); + comp.onSubmit(); }); it('should display an error notification', () => { @@ -246,6 +252,59 @@ describe('ComColFormComponent', () => { }); }); }); + + describe('deleteLogo', () => { + beforeEach(() => { + comp.deleteLogo(); + fixture.detectChanges(); + }); + + it('should set markLogoForDeletion to true', () => { + expect(comp.markLogoForDeletion).toEqual(true); + }); + + it('should mark the logo section with a danger alert', () => { + const logoSection = fixture.debugElement.query(By.css('#logo-section.alert-danger')); + expect(logoSection).toBeTruthy(); + }); + + it('should hide the delete button', () => { + const button = fixture.debugElement.query(By.css('#logo-section .btn-danger')); + expect(button).not.toBeTruthy(); + }); + + it('should show the undo button', () => { + const button = fixture.debugElement.query(By.css('#logo-section .btn-warning')); + expect(button).toBeTruthy(); + }); + }); + + describe('undoDeleteLogo', () => { + beforeEach(() => { + comp.markLogoForDeletion = true; + comp.undoDeleteLogo(); + fixture.detectChanges(); + }); + + it('should set markLogoForDeletion to false', () => { + expect(comp.markLogoForDeletion).toEqual(false); + }); + + it('should disable the danger alert on the logo section', () => { + const logoSection = fixture.debugElement.query(By.css('#logo-section.alert-danger')); + expect(logoSection).not.toBeTruthy(); + }); + + it('should show the delete button', () => { + const button = fixture.debugElement.query(By.css('#logo-section .btn-danger')); + expect(button).toBeTruthy(); + }); + + it('should hide the undo button', () => { + const button = fixture.debugElement.query(By.css('#logo-section .btn-warning')); + expect(button).not.toBeTruthy(); + }); + }); }); }); 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 c80a2e4506..d1ad0b8153 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 @@ -25,7 +25,6 @@ import { combineLatest as observableCombineLatest } from 'rxjs'; import { RestRequestMethod } from '../../../core/data/rest-request-method'; import { RequestService } from '../../../core/data/request.service'; import { ObjectCacheService } from '../../../core/cache/object-cache.service'; -import { take } from 'rxjs/operators'; /** * A form for creating and editing Communities or Collections @@ -85,13 +84,14 @@ export class ComColFormComponent implements OnInit, OnDe */ @Output() submitForm: EventEmitter<{ dso: T, - uploader: FileUploader + uploader: FileUploader, + deleteLogo: boolean }> = new EventEmitter(); /** - * Fires an event when the logo has finished uploading (with or without errors) + * Fires an event when the logo has finished uploading (with or without errors) or was removed */ - @Output() finishUpload: EventEmitter = new EventEmitter(); + @Output() finish: EventEmitter = new EventEmitter(); /** * Observable keeping track whether or not the uploader has finished initializing @@ -99,6 +99,11 @@ export class ComColFormComponent implements OnInit, OnDe */ initializedUploaderOptions = new BehaviorSubject(false); + /** + * Is the logo marked to be deleted? + */ + markLogoForDeletion = false; + /** * Array to track all subscriptions and unsubscribe them onDestroy * @type {Array} @@ -160,6 +165,26 @@ export class ComColFormComponent implements OnInit, OnDe * Checks which new fields were added and sends the updated version of the DSO to the parent component */ onSubmit() { + if (this.markLogoForDeletion && hasValue(this.dso.id)) { + this.dsoService.deleteLogo(this.dso).subscribe((response: RestResponse) => { + if (response.isSuccessful) { + this.notificationsService.success( + this.translate.get(this.type.value + '.edit.logo.notifications.delete.success.title'), + this.translate.get(this.type.value + '.edit.logo.notifications.delete.success.content') + ); + } else { + const errorResponse = response as ErrorResponse; + this.notificationsService.error( + this.translate.get(this.type.value + '.edit.logo.notifications.delete.error.title'), + errorResponse.errorMessage + ); + } + (this.dso as any).logo = undefined; + this.uploadFilesOptions.method = RestRequestMethod.POST; + this.finish.emit(); + }); + } + const formMetadata = new Object() as MetadataMap; this.formModel.forEach((fieldModel: DynamicInputModel) => { const value: MetadataValue = { @@ -182,7 +207,8 @@ export class ComColFormComponent implements OnInit, OnDe }); this.submitForm.emit({ dso: updatedDSO, - uploader: hasValue(this.uploaderComponent) ? this.uploaderComponent.uploader : undefined + uploader: hasValue(this.uploaderComponent) ? this.uploaderComponent.uploader : undefined, + deleteLogo: this.markLogoForDeletion }); } @@ -204,27 +230,18 @@ export class ComColFormComponent implements OnInit, OnDe } /** + * Mark the logo to be deleted * Send out a delete request to remove the logo from the community/collection and display notifications */ deleteLogo() { - if (hasValue(this.dso.id)) { - this.dsoService.deleteLogo(this.dso).subscribe((response: RestResponse) => { - if (response.isSuccessful) { - this.notificationsService.success( - this.translate.get(this.type.value + '.edit.logo.notifications.delete.success.title'), - this.translate.get(this.type.value + '.edit.logo.notifications.delete.success.content') - ); - } else { - const errorResponse = response as ErrorResponse; - this.notificationsService.error( - this.translate.get(this.type.value + '.edit.logo.notifications.delete.error.title'), - errorResponse.errorMessage - ); - } - (this.dso as any).logo = undefined; - this.uploadFilesOptions.method = RestRequestMethod.POST; - }); - } + this.markLogoForDeletion = true; + } + + /** + * Undo marking the logo to be deleted + */ + undoDeleteLogo() { + this.markLogoForDeletion = false; } /** @@ -241,7 +258,7 @@ export class ComColFormComponent implements OnInit, OnDe public onCompleteItem() { this.refreshCache(); this.notificationsService.success(null, this.translate.get(this.type.value + '.edit.logo.notifications.add.success')); - this.finishUpload.emit(); + this.finish.emit(); } /** @@ -249,7 +266,7 @@ export class ComColFormComponent implements OnInit, OnDe */ public onUploadError() { this.notificationsService.error(null, this.translate.get(this.type.value + '.edit.logo.notifications.add.error')); - this.finishUpload.emit(); + this.finish.emit(); } /** diff --git a/src/app/shared/comcol-forms/edit-comcol-page/comcol-metadata/comcol-metadata.component.ts b/src/app/shared/comcol-forms/edit-comcol-page/comcol-metadata/comcol-metadata.component.ts index fbea6e03d1..1031fead10 100644 --- a/src/app/shared/comcol-forms/edit-comcol-page/comcol-metadata/comcol-metadata.component.ts +++ b/src/app/shared/comcol-forms/edit-comcol-page/comcol-metadata/comcol-metadata.component.ts @@ -51,6 +51,7 @@ export class ComcolMetadataComponent implements On onSubmit(event) { const dso = event.dso; const uploader = event.uploader; + const deleteLogo = event.deleteLogo; this.dsoDataService.update(dso) .pipe(getSucceededRemoteData()) @@ -62,7 +63,7 @@ export class ComcolMetadataComponent implements On uploader.options.url = href; uploader.uploadAll(); }); - } else { + } else if (!deleteLogo) { this.router.navigate([this.frontendURL + newUUID]); } this.notificationsService.success(null, this.translate.get(this.type.value + '.edit.notifications.success')); From c7b37663997f5f04c47d658c8c81767d8201c091 Mon Sep 17 00:00:00 2001 From: Kristof De Langhe Date: Mon, 18 Nov 2019 17:36:56 +0100 Subject: [PATCH 24/26] 65240: fdescribe to describe --- .../comcol-forms/comcol-form/comcol-form.component.spec.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 7beafa510b..42e2c4ccb5 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 @@ -24,7 +24,7 @@ import { RequestService } from '../../../core/data/request.service'; import { ObjectCacheService } from '../../../core/cache/object-cache.service'; import { By } from '@angular/platform-browser'; -fdescribe('ComColFormComponent', () => { +describe('ComColFormComponent', () => { let comp: ComColFormComponent; let fixture: ComponentFixture>; let location: Location; From 7755228b59e279ed52e942ccfadf0a06f1f7e2d0 Mon Sep 17 00:00:00 2001 From: Kristof De Langhe Date: Thu, 28 Nov 2019 11:51:07 +0100 Subject: [PATCH 25/26] 65240: Refresh object cache after removing com/col logo --- src/app/shared/comcol-forms/comcol-form/comcol-form.component.ts | 1 + 1 file changed, 1 insertion(+) 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 d1ad0b8153..4db744e7d5 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 @@ -181,6 +181,7 @@ export class ComColFormComponent implements OnInit, OnDe } (this.dso as any).logo = undefined; this.uploadFilesOptions.method = RestRequestMethod.POST; + this.refreshCache(); this.finish.emit(); }); } From 9df5a508f1511b683ff675a53fbf6549eb98a4d1 Mon Sep 17 00:00:00 2001 From: Philip Vissenaekens Date: Thu, 12 Dec 2019 13:11:54 +0100 Subject: [PATCH 26/26] 65240: Community and Collection logo layout --- .../collection-page.component.html | 21 +++++++------------ .../community-page.component.html | 8 +++---- src/app/core/data/comcol-data.service.ts | 11 +++------- 3 files changed, 14 insertions(+), 26 deletions(-) diff --git a/src/app/+collection-page/collection-page.component.html b/src/app/+collection-page/collection-page.component.html index 1cd0318bd5..98552ed40b 100644 --- a/src/app/+collection-page/collection-page.component.html +++ b/src/app/+collection-page/collection-page.component.html @@ -5,15 +5,17 @@
- - - [alternateText]="'Collection Logo'"> - - + + + + + - - - -

{{'collection.page.browse.recent.head' | translate}}

diff --git a/src/app/+community-page/community-page.component.html b/src/app/+community-page/community-page.component.html index ed9d527067..dfd1ce93d9 100644 --- a/src/app/+community-page/community-page.component.html +++ b/src/app/+community-page/community-page.component.html @@ -3,9 +3,11 @@
- + + + @@ -23,10 +25,6 @@ - - - - diff --git a/src/app/core/data/comcol-data.service.ts b/src/app/core/data/comcol-data.service.ts index 63f8e9ef44..2ce0362a4e 100644 --- a/src/app/core/data/comcol-data.service.ts +++ b/src/app/core/data/comcol-data.service.ts @@ -1,24 +1,19 @@ import { distinctUntilChanged, - filter, first, - map, - mergeMap, - share, - switchMap, + filter, first,map, mergeMap, share, switchMap, take, tap } from 'rxjs/operators'; -import { merge as observableMerge, Observable, throwError as observableThrowError } from 'rxjs'; +import { merge as observableMerge, Observable, throwError as observableThrowError, combineLatest as observableCombineLatest } from 'rxjs'; import { hasValue, isEmpty, isNotEmpty } from '../../shared/empty.util'; import { NormalizedCommunity } from '../cache/models/normalized-community.model'; import { ObjectCacheService } from '../cache/object-cache.service'; import { CommunityDataService } from './community-data.service'; import { DataService } from './data.service'; -import { DeleteRequest, FindAllOptions, FindByIDRequest, RestRequest } from './request.models'; +import { DeleteRequest, FindListOptions, FindByIDRequest, RestRequest } from './request.models'; import { PaginatedList } from './paginated-list'; import { RemoteData } from './remote-data'; -import { FindListOptions, FindByIDRequest } from './request.models'; import { HALEndpointService } from '../shared/hal-endpoint.service'; import { configureRequest,