From ec96962a87a5ff3d530d4aa435b50ca4aa3d325f Mon Sep 17 00:00:00 2001 From: Kristof De Langhe Date: Mon, 8 Oct 2018 17:50:52 +0200 Subject: [PATCH 01/21] 55946: Start of Edit Item Page Conflicts: resources/i18n/en.json --- resources/i18n/en.json | 61 +++++++++++++++++++ .../edit-item-page.component.html | 52 ++++++++++++++++ .../edit-item-page.component.scss | 0 .../edit-item-page.component.spec.ts | 0 .../edit-item-page.component.ts | 55 +++++++++++++++++ .../+item-page/item-page-routing.module.ts | 10 +++ src/app/+item-page/item-page.module.ts | 4 +- 7 files changed, 181 insertions(+), 1 deletion(-) create mode 100644 src/app/+item-page/edit-item-page/edit-item-page.component.html create mode 100644 src/app/+item-page/edit-item-page/edit-item-page.component.scss create mode 100644 src/app/+item-page/edit-item-page/edit-item-page.component.spec.ts create mode 100644 src/app/+item-page/edit-item-page/edit-item-page.component.ts diff --git a/resources/i18n/en.json b/resources/i18n/en.json index b6a23068d7..deebe09760 100644 --- a/resources/i18n/en.json +++ b/resources/i18n/en.json @@ -43,6 +43,67 @@ "simple": "Simple item page", "full": "Full item page" } + }, + "select": { + "table": { + "collection": "Collection", + "author": "Author", + "title": "Title" + }, + "confirm": "Confirm selected" + }, + "edit": { + "head": "Edit Item", + "tabs": { + "status": { + "head": "Item Status", + "description": "Welcome to the item management page. From here you can withdraw, reinstate, move or delete the item. You may also update or add new metadata / bitstreams on the other tabs.", + "labels": { + "id": "Item Internal ID", + "handle": "Handle", + "lastModified": "Last Modified", + "itemPage": "Item Page" + }, + "buttons": { + "authorizations": { + "label": "Edit item's authorization policies", + "button": "Authorizations..." + }, + "withdraw": { + "label": "Withdraw item from the repository", + "button": "Withdraw..." + }, + "move": { + "label": "Move item to another collection", + "button": "Move..." + }, + "private": { + "label": "Make item private", + "button": "Make it private..." + }, + "delete": { + "label": "Completely expunge item", + "button": "Permanently delete" + }, + "mapped-collections": { + "label": "Manage mapped collections", + "button": "Mapped collections" + } + } + }, + "bitstreams": { + "head": "Item Bitstreams" + }, + "metadata": { + "head": "Item Metadata" + }, + "view": { + "head": "View Item" + }, + "curate": { + "head": "Curate" + } + } } }, "nav": { diff --git a/src/app/+item-page/edit-item-page/edit-item-page.component.html b/src/app/+item-page/edit-item-page/edit-item-page.component.html new file mode 100644 index 0000000000..ca15e83ab9 --- /dev/null +++ b/src/app/+item-page/edit-item-page/edit-item-page.component.html @@ -0,0 +1,52 @@ +
+
+
+

{{'item.edit.head' | translate}}

+
+ + + +

{{'item.edit.tabs.status.description' | translate}}

+
+
+
+ {{'item.edit.tabs.status.labels.' + statusKey | translate}}: +
+
+ {{(statusData$ | async)[statusKey]}} +
+
+
+ {{'item.edit.tabs.status.labels.itemPage' | translate}}: +
+ +
+
+
+ + + + + + + + + + + + + + + + + + + + +
+
+
+
+
diff --git a/src/app/+item-page/edit-item-page/edit-item-page.component.scss b/src/app/+item-page/edit-item-page/edit-item-page.component.scss new file mode 100644 index 0000000000..e69de29bb2 diff --git a/src/app/+item-page/edit-item-page/edit-item-page.component.spec.ts b/src/app/+item-page/edit-item-page/edit-item-page.component.spec.ts new file mode 100644 index 0000000000..e69de29bb2 diff --git a/src/app/+item-page/edit-item-page/edit-item-page.component.ts b/src/app/+item-page/edit-item-page/edit-item-page.component.ts new file mode 100644 index 0000000000..eb017669fc --- /dev/null +++ b/src/app/+item-page/edit-item-page/edit-item-page.component.ts @@ -0,0 +1,55 @@ +import { fadeIn, fadeInOut } from '../../shared/animations/fade'; +import { ChangeDetectionStrategy, Component, OnInit } from '@angular/core'; +import { ItemDataService } from '../../core/data/item-data.service'; +import { ActivatedRoute, Router } from '@angular/router'; +import { Observable } from 'rxjs/Observable'; +import { RemoteData } from '../../core/data/remote-data'; +import { Item } from '../../core/shared/item.model'; +import { getSucceededRemoteData } from '../../core/shared/operators'; +import { map } from 'rxjs/operators'; + +@Component({ + selector: 'ds-edit-item-page', + styleUrls: ['./edit-item-page.component.scss'], + templateUrl: './edit-item-page.component.html', + changeDetection: ChangeDetectionStrategy.OnPush, + animations: [ + fadeIn, + fadeInOut + ] +}) +/** + * Page component for editing an item + */ +export class EditItemPageComponent implements OnInit { + + objectKeys = Object.keys; + + /** + * The item to edit + */ + itemRD$: Observable>; + statusData$: Observable; + + constructor(private route: ActivatedRoute, + private router: Router) { + } + + ngOnInit(): void { + this.itemRD$ = this.route.data.map((data) => data.item); + this.statusData$ = this.itemRD$.pipe( + getSucceededRemoteData(), + map((itemRD: RemoteData) => itemRD.payload), + map((item: Item) => Object.assign({ + id: item.id, + handle: item.handle, + lastModified: item.lastModified + })) + ) + } + + getItemPage(): string { + return this.router.url.substr(0, this.router.url.lastIndexOf('/')); + } + +} diff --git a/src/app/+item-page/item-page-routing.module.ts b/src/app/+item-page/item-page-routing.module.ts index 96158b867e..0105c947e9 100644 --- a/src/app/+item-page/item-page-routing.module.ts +++ b/src/app/+item-page/item-page-routing.module.ts @@ -4,6 +4,8 @@ import { RouterModule } from '@angular/router'; import { ItemPageComponent } from './simple/item-page.component'; import { FullItemPageComponent } from './full/full-item-page.component'; import { ItemPageResolver } from './item-page.resolver'; +import { AuthenticatedGuard } from '../core/auth/authenticated.guard'; +import { EditItemPageComponent } from './edit-item-page/edit-item-page.component'; @NgModule({ imports: [ @@ -22,6 +24,14 @@ import { ItemPageResolver } from './item-page.resolver'; resolve: { item: ItemPageResolver } + }, + { + path: ':id/edit', + component: EditItemPageComponent, + resolve: { + item: ItemPageResolver + }, + canActivate: [AuthenticatedGuard] } ]) ], diff --git a/src/app/+item-page/item-page.module.ts b/src/app/+item-page/item-page.module.ts index bd801923e3..45251bb1d8 100644 --- a/src/app/+item-page/item-page.module.ts +++ b/src/app/+item-page/item-page.module.ts @@ -18,6 +18,7 @@ import { FileSectionComponent } from './simple/field-components/file-section/fil import { CollectionsComponent } from './field-components/collections/collections.component'; import { FullItemPageComponent } from './full/full-item-page.component'; import { FullFileSectionComponent } from './full/field-components/file-section/full-file-section.component'; +import { EditItemPageComponent } from './edit-item-page/edit-item-page.component'; @NgModule({ imports: [ @@ -39,7 +40,8 @@ import { FullFileSectionComponent } from './full/field-components/file-section/f ItemPageSpecificFieldComponent, FileSectionComponent, CollectionsComponent, - FullFileSectionComponent + FullFileSectionComponent, + EditItemPageComponent ] }) export class ItemPageModule { From 05a4918ef0a15ba27c5a80c87767b88f7ed3352f Mon Sep 17 00:00:00 2001 From: Kristof De Langhe Date: Tue, 9 Oct 2018 11:51:52 +0200 Subject: [PATCH 02/21] 55946: Finished edit-item-page and start of collection mapper --- resources/i18n/en.json | 2 +- .../edit-item-page.component.html | 18 +--- .../edit-item-page.component.ts | 24 +----- .../edit-item-page/edit-item-page.module.ts | 23 ++++++ .../edit-item-page.routing.module.ts | 32 ++++++++ .../item-collection-mapper.component.html | 7 ++ .../item-collection-mapper.component.scss | 0 .../item-collection-mapper.component.spec.ts | 0 .../item-collection-mapper.component.ts | 19 +++++ .../item-status/item-status.component.html | 30 +++++++ .../item-status/item-status.component.scss | 0 .../item-status/item-status.component.spec.ts | 0 .../item-status/item-status.component.ts | 82 +++++++++++++++++++ .../+item-page/item-page-routing.module.ts | 6 +- src/app/+item-page/item-page.module.ts | 6 +- 15 files changed, 201 insertions(+), 48 deletions(-) create mode 100644 src/app/+item-page/edit-item-page/edit-item-page.module.ts create mode 100644 src/app/+item-page/edit-item-page/edit-item-page.routing.module.ts create mode 100644 src/app/+item-page/edit-item-page/item-collection-mapper/item-collection-mapper.component.html create mode 100644 src/app/+item-page/edit-item-page/item-collection-mapper/item-collection-mapper.component.scss create mode 100644 src/app/+item-page/edit-item-page/item-collection-mapper/item-collection-mapper.component.spec.ts create mode 100644 src/app/+item-page/edit-item-page/item-collection-mapper/item-collection-mapper.component.ts create mode 100644 src/app/+item-page/edit-item-page/item-status/item-status.component.html create mode 100644 src/app/+item-page/edit-item-page/item-status/item-status.component.scss create mode 100644 src/app/+item-page/edit-item-page/item-status/item-status.component.spec.ts create mode 100644 src/app/+item-page/edit-item-page/item-status/item-status.component.ts diff --git a/resources/i18n/en.json b/resources/i18n/en.json index deebe09760..5cd54869d2 100644 --- a/resources/i18n/en.json +++ b/resources/i18n/en.json @@ -85,7 +85,7 @@ "label": "Completely expunge item", "button": "Permanently delete" }, - "mapped-collections": { + "mappedCollections": { "label": "Manage mapped collections", "button": "Mapped collections" } diff --git a/src/app/+item-page/edit-item-page/edit-item-page.component.html b/src/app/+item-page/edit-item-page/edit-item-page.component.html index ca15e83ab9..001b484c2c 100644 --- a/src/app/+item-page/edit-item-page/edit-item-page.component.html +++ b/src/app/+item-page/edit-item-page/edit-item-page.component.html @@ -6,23 +6,7 @@ -

{{'item.edit.tabs.status.description' | translate}}

-
-
-
- {{'item.edit.tabs.status.labels.' + statusKey | translate}}: -
-
- {{(statusData$ | async)[statusKey]}} -
-
-
- {{'item.edit.tabs.status.labels.itemPage' | translate}}: -
- -
+
diff --git a/src/app/+item-page/edit-item-page/edit-item-page.component.ts b/src/app/+item-page/edit-item-page/edit-item-page.component.ts index eb017669fc..7702fc94e8 100644 --- a/src/app/+item-page/edit-item-page/edit-item-page.component.ts +++ b/src/app/+item-page/edit-item-page/edit-item-page.component.ts @@ -1,12 +1,9 @@ import { fadeIn, fadeInOut } from '../../shared/animations/fade'; import { ChangeDetectionStrategy, Component, OnInit } from '@angular/core'; -import { ItemDataService } from '../../core/data/item-data.service'; -import { ActivatedRoute, Router } from '@angular/router'; +import { ActivatedRoute } from '@angular/router'; import { Observable } from 'rxjs/Observable'; import { RemoteData } from '../../core/data/remote-data'; import { Item } from '../../core/shared/item.model'; -import { getSucceededRemoteData } from '../../core/shared/operators'; -import { map } from 'rxjs/operators'; @Component({ selector: 'ds-edit-item-page', @@ -23,33 +20,16 @@ import { map } from 'rxjs/operators'; */ export class EditItemPageComponent implements OnInit { - objectKeys = Object.keys; - /** * The item to edit */ itemRD$: Observable>; - statusData$: Observable; - constructor(private route: ActivatedRoute, - private router: Router) { + constructor(private route: ActivatedRoute) { } ngOnInit(): void { this.itemRD$ = this.route.data.map((data) => data.item); - this.statusData$ = this.itemRD$.pipe( - getSucceededRemoteData(), - map((itemRD: RemoteData) => itemRD.payload), - map((item: Item) => Object.assign({ - id: item.id, - handle: item.handle, - lastModified: item.lastModified - })) - ) - } - - getItemPage(): string { - return this.router.url.substr(0, this.router.url.lastIndexOf('/')); } } diff --git a/src/app/+item-page/edit-item-page/edit-item-page.module.ts b/src/app/+item-page/edit-item-page/edit-item-page.module.ts new file mode 100644 index 0000000000..70f6fc7d3b --- /dev/null +++ b/src/app/+item-page/edit-item-page/edit-item-page.module.ts @@ -0,0 +1,23 @@ +import { NgModule } from '@angular/core'; +import { CommonModule } from '@angular/common'; +import { SharedModule } from '../../shared/shared.module'; +import { EditItemPageRoutingModule } from './edit-item-page.routing.module'; +import { EditItemPageComponent } from './edit-item-page.component'; +import { ItemCollectionMapperComponent } from './item-collection-mapper/item-collection-mapper.component'; +import { ItemStatusComponent } from './item-status/item-status.component'; + +@NgModule({ + imports: [ + CommonModule, + SharedModule, + EditItemPageRoutingModule + ], + declarations: [ + EditItemPageComponent, + ItemStatusComponent, + ItemCollectionMapperComponent + ] +}) +export class EditItemPageModule { + +} diff --git a/src/app/+item-page/edit-item-page/edit-item-page.routing.module.ts b/src/app/+item-page/edit-item-page/edit-item-page.routing.module.ts new file mode 100644 index 0000000000..f2209cddcc --- /dev/null +++ b/src/app/+item-page/edit-item-page/edit-item-page.routing.module.ts @@ -0,0 +1,32 @@ +import { ItemPageResolver } from '../item-page.resolver'; +import { NgModule } from '@angular/core'; +import { RouterModule } from '@angular/router'; +import { EditItemPageComponent } from './edit-item-page.component'; +import { ItemCollectionMapperComponent } from './item-collection-mapper/item-collection-mapper.component'; + +@NgModule({ + imports: [ + RouterModule.forChild([ + { + path: '', + component: EditItemPageComponent, + resolve: { + item: ItemPageResolver + } + }, + { + path: 'map', + component: ItemCollectionMapperComponent, + resolve: { + item: ItemPageResolver + } + } + ]) + ], + providers: [ + ItemPageResolver, + ] +}) +export class EditItemPageRoutingModule { + +} diff --git a/src/app/+item-page/edit-item-page/item-collection-mapper/item-collection-mapper.component.html b/src/app/+item-page/edit-item-page/item-collection-mapper/item-collection-mapper.component.html new file mode 100644 index 0000000000..3fb829fe8b --- /dev/null +++ b/src/app/+item-page/edit-item-page/item-collection-mapper/item-collection-mapper.component.html @@ -0,0 +1,7 @@ +
+
+
+

It works!

+
+
+
diff --git a/src/app/+item-page/edit-item-page/item-collection-mapper/item-collection-mapper.component.scss b/src/app/+item-page/edit-item-page/item-collection-mapper/item-collection-mapper.component.scss new file mode 100644 index 0000000000..e69de29bb2 diff --git a/src/app/+item-page/edit-item-page/item-collection-mapper/item-collection-mapper.component.spec.ts b/src/app/+item-page/edit-item-page/item-collection-mapper/item-collection-mapper.component.spec.ts new file mode 100644 index 0000000000..e69de29bb2 diff --git a/src/app/+item-page/edit-item-page/item-collection-mapper/item-collection-mapper.component.ts b/src/app/+item-page/edit-item-page/item-collection-mapper/item-collection-mapper.component.ts new file mode 100644 index 0000000000..592e3bd26c --- /dev/null +++ b/src/app/+item-page/edit-item-page/item-collection-mapper/item-collection-mapper.component.ts @@ -0,0 +1,19 @@ +import { ChangeDetectionStrategy, Component } from '@angular/core'; +import { fadeIn, fadeInOut } from '../../../shared/animations/fade'; + +@Component({ + selector: 'ds-item-collection-mapper', + styleUrls: ['./item-collection-mapper.component.scss'], + templateUrl: './item-collection-mapper.component.html', + changeDetection: ChangeDetectionStrategy.OnPush, + animations: [ + fadeIn, + fadeInOut + ] +}) +/** + * Component for mapping collections to an item + */ +export class ItemCollectionMapperComponent { + +} diff --git a/src/app/+item-page/edit-item-page/item-status/item-status.component.html b/src/app/+item-page/edit-item-page/item-status/item-status.component.html new file mode 100644 index 0000000000..0a93e7659d --- /dev/null +++ b/src/app/+item-page/edit-item-page/item-status/item-status.component.html @@ -0,0 +1,30 @@ +

{{'item.edit.tabs.status.description' | translate}}

+
+
+
+ {{'item.edit.tabs.status.labels.' + statusKey | translate}}: +
+
+ {{statusData[statusKey]}} +
+
+
+ {{'item.edit.tabs.status.labels.itemPage' | translate}}: +
+ + +
+
+ + {{'item.edit.tabs.status.buttons.' + actionKey + '.label' | translate}} + +
+ +
+
diff --git a/src/app/+item-page/edit-item-page/item-status/item-status.component.scss b/src/app/+item-page/edit-item-page/item-status/item-status.component.scss new file mode 100644 index 0000000000..e69de29bb2 diff --git a/src/app/+item-page/edit-item-page/item-status/item-status.component.spec.ts b/src/app/+item-page/edit-item-page/item-status/item-status.component.spec.ts new file mode 100644 index 0000000000..e69de29bb2 diff --git a/src/app/+item-page/edit-item-page/item-status/item-status.component.ts b/src/app/+item-page/edit-item-page/item-status/item-status.component.ts new file mode 100644 index 0000000000..715614c1d9 --- /dev/null +++ b/src/app/+item-page/edit-item-page/item-status/item-status.component.ts @@ -0,0 +1,82 @@ +import { ChangeDetectionStrategy, Component, Input, OnInit } from '@angular/core'; +import { fadeIn, fadeInOut } from '../../../shared/animations/fade'; +import { Item } from '../../../core/shared/item.model'; +import { Router } from '@angular/router'; + +@Component({ + selector: 'ds-item-status', + styleUrls: ['./item-status.component.scss'], + templateUrl: './item-status.component.html', + changeDetection: ChangeDetectionStrategy.OnPush, + animations: [ + fadeIn, + fadeInOut + ] +}) +/** + * Component for displaying an item's status + */ +export class ItemStatusComponent implements OnInit { + + /** + * The item to display the status for + */ + @Input() item: Item; + + /** + * The data to show in the status + */ + statusData: any; + /** + * The keys of the data (to loop over) + */ + statusDataKeys; + + /** + * The possible actions that can be performed on the item + * key: id value: url to action's component + */ + actions: any; + /** + * The keys of the actions (to loop over) + */ + actionsKeys; + + constructor(private router: Router) { + } + + ngOnInit(): void { + this.statusData = Object.assign({ + id: this.item.id, + handle: this.item.handle, + lastModified: this.item.lastModified + }); + this.statusDataKeys = Object.keys(this.statusData); + + this.actions = Object.assign({ + mappedCollections: this.getCurrentUrl() + '/map' + }); + this.actionsKeys = Object.keys(this.actions); + } + + /** + * Get the url to the simple item page + * @returns {string} url + */ + getItemPage(): string { + return this.router.url.substr(0, this.router.url.lastIndexOf('/')); + } + + /** + * Get the current url without query params + * @returns {string} url + */ + getCurrentUrl(): string { + if (this.router.url.indexOf('?') > -1) { + return this.router.url.substr(0, this.router.url.indexOf('?')); + } else { + return this.router.url; + } + } + +} diff --git a/src/app/+item-page/item-page-routing.module.ts b/src/app/+item-page/item-page-routing.module.ts index 0105c947e9..be31b0a82d 100644 --- a/src/app/+item-page/item-page-routing.module.ts +++ b/src/app/+item-page/item-page-routing.module.ts @@ -5,7 +5,6 @@ import { ItemPageComponent } from './simple/item-page.component'; import { FullItemPageComponent } from './full/full-item-page.component'; import { ItemPageResolver } from './item-page.resolver'; import { AuthenticatedGuard } from '../core/auth/authenticated.guard'; -import { EditItemPageComponent } from './edit-item-page/edit-item-page.component'; @NgModule({ imports: [ @@ -27,10 +26,7 @@ import { EditItemPageComponent } from './edit-item-page/edit-item-page.component }, { path: ':id/edit', - component: EditItemPageComponent, - resolve: { - item: ItemPageResolver - }, + loadChildren: './edit-item-page/edit-item-page.module#EditItemPageModule', canActivate: [AuthenticatedGuard] } ]) diff --git a/src/app/+item-page/item-page.module.ts b/src/app/+item-page/item-page.module.ts index 45251bb1d8..d383189a9c 100644 --- a/src/app/+item-page/item-page.module.ts +++ b/src/app/+item-page/item-page.module.ts @@ -18,12 +18,13 @@ import { FileSectionComponent } from './simple/field-components/file-section/fil import { CollectionsComponent } from './field-components/collections/collections.component'; import { FullItemPageComponent } from './full/full-item-page.component'; import { FullFileSectionComponent } from './full/field-components/file-section/full-file-section.component'; -import { EditItemPageComponent } from './edit-item-page/edit-item-page.component'; +import { EditItemPageModule } from './edit-item-page/edit-item-page.module'; @NgModule({ imports: [ CommonModule, SharedModule, + EditItemPageModule, ItemPageRoutingModule ], declarations: [ @@ -40,8 +41,7 @@ import { EditItemPageComponent } from './edit-item-page/edit-item-page.component ItemPageSpecificFieldComponent, FileSectionComponent, CollectionsComponent, - FullFileSectionComponent, - EditItemPageComponent + FullFileSectionComponent ] }) export class ItemPageModule { From fb0e1d81e4f461c8eac754831877d2494cb74ac7 Mon Sep 17 00:00:00 2001 From: Kristof De Langhe Date: Tue, 9 Oct 2018 14:30:40 +0200 Subject: [PATCH 03/21] 55946: Edit item page cleanup --- .../edit-item-page/edit-item-page.module.ts | 4 +--- .../edit-item-page.routing.module.ts | 8 -------- .../item-collection-mapper.component.html | 7 ------- .../item-collection-mapper.component.scss | 0 .../item-collection-mapper.component.spec.ts | 0 .../item-collection-mapper.component.ts | 19 ------------------- .../item-status/item-status.component.ts | 8 +++++++- 7 files changed, 8 insertions(+), 38 deletions(-) delete mode 100644 src/app/+item-page/edit-item-page/item-collection-mapper/item-collection-mapper.component.html delete mode 100644 src/app/+item-page/edit-item-page/item-collection-mapper/item-collection-mapper.component.scss delete mode 100644 src/app/+item-page/edit-item-page/item-collection-mapper/item-collection-mapper.component.spec.ts delete mode 100644 src/app/+item-page/edit-item-page/item-collection-mapper/item-collection-mapper.component.ts diff --git a/src/app/+item-page/edit-item-page/edit-item-page.module.ts b/src/app/+item-page/edit-item-page/edit-item-page.module.ts index 70f6fc7d3b..e7016eb05d 100644 --- a/src/app/+item-page/edit-item-page/edit-item-page.module.ts +++ b/src/app/+item-page/edit-item-page/edit-item-page.module.ts @@ -3,7 +3,6 @@ import { CommonModule } from '@angular/common'; import { SharedModule } from '../../shared/shared.module'; import { EditItemPageRoutingModule } from './edit-item-page.routing.module'; import { EditItemPageComponent } from './edit-item-page.component'; -import { ItemCollectionMapperComponent } from './item-collection-mapper/item-collection-mapper.component'; import { ItemStatusComponent } from './item-status/item-status.component'; @NgModule({ @@ -14,8 +13,7 @@ import { ItemStatusComponent } from './item-status/item-status.component'; ], declarations: [ EditItemPageComponent, - ItemStatusComponent, - ItemCollectionMapperComponent + ItemStatusComponent ] }) export class EditItemPageModule { diff --git a/src/app/+item-page/edit-item-page/edit-item-page.routing.module.ts b/src/app/+item-page/edit-item-page/edit-item-page.routing.module.ts index f2209cddcc..46e8dab609 100644 --- a/src/app/+item-page/edit-item-page/edit-item-page.routing.module.ts +++ b/src/app/+item-page/edit-item-page/edit-item-page.routing.module.ts @@ -2,7 +2,6 @@ import { ItemPageResolver } from '../item-page.resolver'; import { NgModule } from '@angular/core'; import { RouterModule } from '@angular/router'; import { EditItemPageComponent } from './edit-item-page.component'; -import { ItemCollectionMapperComponent } from './item-collection-mapper/item-collection-mapper.component'; @NgModule({ imports: [ @@ -13,13 +12,6 @@ import { ItemCollectionMapperComponent } from './item-collection-mapper/item-col resolve: { item: ItemPageResolver } - }, - { - path: 'map', - component: ItemCollectionMapperComponent, - resolve: { - item: ItemPageResolver - } } ]) ], diff --git a/src/app/+item-page/edit-item-page/item-collection-mapper/item-collection-mapper.component.html b/src/app/+item-page/edit-item-page/item-collection-mapper/item-collection-mapper.component.html deleted file mode 100644 index 3fb829fe8b..0000000000 --- a/src/app/+item-page/edit-item-page/item-collection-mapper/item-collection-mapper.component.html +++ /dev/null @@ -1,7 +0,0 @@ -
-
-
-

It works!

-
-
-
diff --git a/src/app/+item-page/edit-item-page/item-collection-mapper/item-collection-mapper.component.scss b/src/app/+item-page/edit-item-page/item-collection-mapper/item-collection-mapper.component.scss deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/src/app/+item-page/edit-item-page/item-collection-mapper/item-collection-mapper.component.spec.ts b/src/app/+item-page/edit-item-page/item-collection-mapper/item-collection-mapper.component.spec.ts deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/src/app/+item-page/edit-item-page/item-collection-mapper/item-collection-mapper.component.ts b/src/app/+item-page/edit-item-page/item-collection-mapper/item-collection-mapper.component.ts deleted file mode 100644 index 592e3bd26c..0000000000 --- a/src/app/+item-page/edit-item-page/item-collection-mapper/item-collection-mapper.component.ts +++ /dev/null @@ -1,19 +0,0 @@ -import { ChangeDetectionStrategy, Component } from '@angular/core'; -import { fadeIn, fadeInOut } from '../../../shared/animations/fade'; - -@Component({ - selector: 'ds-item-collection-mapper', - styleUrls: ['./item-collection-mapper.component.scss'], - templateUrl: './item-collection-mapper.component.html', - changeDetection: ChangeDetectionStrategy.OnPush, - animations: [ - fadeIn, - fadeInOut - ] -}) -/** - * Component for mapping collections to an item - */ -export class ItemCollectionMapperComponent { - -} diff --git a/src/app/+item-page/edit-item-page/item-status/item-status.component.ts b/src/app/+item-page/edit-item-page/item-status/item-status.component.ts index 715614c1d9..8d68a9e961 100644 --- a/src/app/+item-page/edit-item-page/item-status/item-status.component.ts +++ b/src/app/+item-page/edit-item-page/item-status/item-status.component.ts @@ -53,8 +53,14 @@ export class ItemStatusComponent implements OnInit { }); this.statusDataKeys = Object.keys(this.statusData); + /* + The key is used to build messages + i18n example: 'item.edit.tabs.status.buttons..label' + The value is supposed to be a href for the button + */ this.actions = Object.assign({ - mappedCollections: this.getCurrentUrl() + '/map' + // TODO: Create mapping component on item level + mappedCollections: this.getCurrentUrl() + '/' }); this.actionsKeys = Object.keys(this.actions); } From 7d9afeefea78ee1cbe60a2ba74a687cf6014658f Mon Sep 17 00:00:00 2001 From: Kristof De Langhe Date: Tue, 9 Oct 2018 15:32:55 +0200 Subject: [PATCH 04/21] 55946: Removed unnecessary files and created tests --- .../edit-item-page.component.scss | 0 .../edit-item-page.component.spec.ts | 0 .../edit-item-page.component.ts | 1 - .../item-status/item-status.component.html | 12 ++-- .../item-status/item-status.component.scss | 0 .../item-status/item-status.component.spec.ts | 67 +++++++++++++++++++ .../item-status/item-status.component.ts | 1 - 7 files changed, 73 insertions(+), 8 deletions(-) delete mode 100644 src/app/+item-page/edit-item-page/edit-item-page.component.scss delete mode 100644 src/app/+item-page/edit-item-page/edit-item-page.component.spec.ts delete mode 100644 src/app/+item-page/edit-item-page/item-status/item-status.component.scss diff --git a/src/app/+item-page/edit-item-page/edit-item-page.component.scss b/src/app/+item-page/edit-item-page/edit-item-page.component.scss deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/src/app/+item-page/edit-item-page/edit-item-page.component.spec.ts b/src/app/+item-page/edit-item-page/edit-item-page.component.spec.ts deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/src/app/+item-page/edit-item-page/edit-item-page.component.ts b/src/app/+item-page/edit-item-page/edit-item-page.component.ts index 7702fc94e8..8bcf53f140 100644 --- a/src/app/+item-page/edit-item-page/edit-item-page.component.ts +++ b/src/app/+item-page/edit-item-page/edit-item-page.component.ts @@ -7,7 +7,6 @@ import { Item } from '../../core/shared/item.model'; @Component({ selector: 'ds-edit-item-page', - styleUrls: ['./edit-item-page.component.scss'], templateUrl: './edit-item-page.component.html', changeDetection: ChangeDetectionStrategy.OnPush, animations: [ diff --git a/src/app/+item-page/edit-item-page/item-status/item-status.component.html b/src/app/+item-page/edit-item-page/item-status/item-status.component.html index 0a93e7659d..78ab9174eb 100644 --- a/src/app/+item-page/edit-item-page/item-status/item-status.component.html +++ b/src/app/+item-page/edit-item-page/item-status/item-status.component.html @@ -1,27 +1,27 @@

{{'item.edit.tabs.status.description' | translate}}

-
+
{{'item.edit.tabs.status.labels.' + statusKey | translate}}:
-
+
{{statusData[statusKey]}}
-
+
{{'item.edit.tabs.status.labels.itemPage' | translate}}:
-
+
-
+
{{'item.edit.tabs.status.buttons.' + actionKey + '.label' | translate}}
-
+
{{'item.edit.tabs.status.buttons.' + actionKey + '.button' | translate}} diff --git a/src/app/+item-page/edit-item-page/item-status/item-status.component.scss b/src/app/+item-page/edit-item-page/item-status/item-status.component.scss deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/src/app/+item-page/edit-item-page/item-status/item-status.component.spec.ts b/src/app/+item-page/edit-item-page/item-status/item-status.component.spec.ts index e69de29bb2..2df4b977cb 100644 --- a/src/app/+item-page/edit-item-page/item-status/item-status.component.spec.ts +++ b/src/app/+item-page/edit-item-page/item-status/item-status.component.spec.ts @@ -0,0 +1,67 @@ +import { ItemStatusComponent } from './item-status.component'; +import { async, ComponentFixture, TestBed } from '@angular/core/testing'; +import { TranslateModule } from '@ngx-translate/core'; +import { NgbModule } from '@ng-bootstrap/ng-bootstrap'; +import { CommonModule } from '@angular/common'; +import { HostWindowServiceStub } from '../../../shared/testing/host-window-service-stub'; +import { HostWindowService } from '../../../shared/host-window.service'; +import { RouterTestingModule } from '@angular/router/testing'; +import { Router } from '@angular/router'; +import { RouterStub } from '../../../shared/testing/router-stub'; +import { Item } from '../../../core/shared/item.model'; +import { By } from '@angular/platform-browser'; + +describe('ItemStatusComponent', () => { + let comp: ItemStatusComponent; + let fixture: ComponentFixture; + + const mockItem = Object.assign(new Item(), { + id: 'fake-id', + handle: 'fake/handle', + lastModified: '2018' + }); + + const itemPageUrl = `fake-url/${mockItem.id}`; + const routerStub = Object.assign(new RouterStub(), { + url: `${itemPageUrl}/edit` + }); + + beforeEach(async(() => { + TestBed.configureTestingModule({ + imports: [CommonModule, RouterTestingModule.withRoutes([]), TranslateModule.forRoot(), NgbModule.forRoot()], + declarations: [ItemStatusComponent], + providers: [ + { provide: Router, useValue: routerStub }, + { provide: HostWindowService, useValue: new HostWindowServiceStub(0) } + ] + }).compileComponents(); + })); + + beforeEach(() => { + fixture = TestBed.createComponent(ItemStatusComponent); + comp = fixture.componentInstance; + comp.item = mockItem; + fixture.detectChanges(); + }); + + it('should display the item\'s internal id', () => { + const statusId: HTMLElement = fixture.debugElement.query(By.css('.status-data#status-id')).nativeElement; + expect(statusId.textContent).toContain(mockItem.id); + }); + + it('should display the item\'s handle', () => { + const statusHandle: HTMLElement = fixture.debugElement.query(By.css('.status-data#status-handle')).nativeElement; + expect(statusHandle.textContent).toContain(mockItem.handle); + }); + + it('should display the item\'s last modified date', () => { + const statusLastModified: HTMLElement = fixture.debugElement.query(By.css('.status-data#status-lastModified')).nativeElement; + expect(statusLastModified.textContent).toContain(mockItem.lastModified); + }); + + it('should display the item\'s page url', () => { + const statusItemPage: HTMLElement = fixture.debugElement.query(By.css('.status-data#status-itemPage')).nativeElement; + expect(statusItemPage.textContent).toContain(itemPageUrl); + }); + +}); diff --git a/src/app/+item-page/edit-item-page/item-status/item-status.component.ts b/src/app/+item-page/edit-item-page/item-status/item-status.component.ts index 8d68a9e961..bc9dda61ec 100644 --- a/src/app/+item-page/edit-item-page/item-status/item-status.component.ts +++ b/src/app/+item-page/edit-item-page/item-status/item-status.component.ts @@ -5,7 +5,6 @@ import { Router } from '@angular/router'; @Component({ selector: 'ds-item-status', - styleUrls: ['./item-status.component.scss'], templateUrl: './item-status.component.html', changeDetection: ChangeDetectionStrategy.OnPush, animations: [ From 8570ff25784f2ccf93913f6e7a4954621de50e8c Mon Sep 17 00:00:00 2001 From: Yana De Pauw Date: Thu, 25 Oct 2018 18:13:49 +0200 Subject: [PATCH 05/21] 55990: Item move component --- .../item-move/item-move.component.html | 51 +++++++++++++++++++ .../item-move/item-move.component.ts | 0 .../item-operation.component.html | 10 ++++ .../item-operation.component.ts | 0 .../item-operation/itemOperation.model.ts | 0 5 files changed, 61 insertions(+) create mode 100644 src/app/+item-page/edit-item-page/item-move/item-move.component.html create mode 100644 src/app/+item-page/edit-item-page/item-move/item-move.component.ts create mode 100644 src/app/+item-page/edit-item-page/item-operation/item-operation.component.html create mode 100644 src/app/+item-page/edit-item-page/item-operation/item-operation.component.ts create mode 100644 src/app/+item-page/edit-item-page/item-operation/itemOperation.model.ts diff --git a/src/app/+item-page/edit-item-page/item-move/item-move.component.html b/src/app/+item-page/edit-item-page/item-move/item-move.component.html new file mode 100644 index 0000000000..a060aa0fed --- /dev/null +++ b/src/app/+item-page/edit-item-page/item-move/item-move.component.html @@ -0,0 +1,51 @@ +import {Component, OnInit} from '@angular/core'; +import {Collection} from '../../../core/shared/collection.model'; +import {RemoteData} from '../../../core/data/remote-data'; +import {Item} from '../../../core/shared/item.model'; +import {getSucceededRemoteData} from '../../../core/shared/operators'; +import {Observable} from 'rxjs'; +import {PaginatedList} from '../../../core/data/paginated-list'; +import {TranslateService} from '@ngx-translate/core'; +import {NotificationsService} from '../../../shared/notifications/notifications.service'; +import {SearchService} from '../../../+search-page/search-service/search.service'; +import {SearchConfigurationService} from '../../../+search-page/search-service/search-configuration.service'; +import {ActivatedRoute, Router} from '@angular/router'; +import {CollectionDataService} from '../../../core/data/collection-data.service'; + +@Component({ + selector: 'ds-item-move', + templateUrl: './item-move.component.html' +}) +export class ItemMoveComponent implements OnInit { + inheritPolicies: boolean; + + itemRD$: Observable>; + + /** + * List of collections to show under the "Browse" tab + * Collections that are mapped to the item + */ + itemCollectionsRD$: Observable>>; + + constructor(private route: ActivatedRoute, + private router: Router, + private searchConfigService: SearchConfigurationService, + private searchService: SearchService, + private notificationsService: NotificationsService, + private collectionDataService: CollectionDataService, + private translateService: TranslateService) { + } + + ngOnInit(): void { + this.itemRD$ = this.route.data.map((data) => data.item).pipe(getSucceededRemoteData()) as Observable>; + this.loadCollectionLists(); + } + + /** + * Load all available collections to move the item to. + * TODO: When the API support it, only fetch collections where user has ADD rights to. + */ + loadCollectionLists() { + this.itemCollectionsRD$ = this.collectionDataService.findAll(); + } +} diff --git a/src/app/+item-page/edit-item-page/item-move/item-move.component.ts b/src/app/+item-page/edit-item-page/item-move/item-move.component.ts new file mode 100644 index 0000000000..e69de29bb2 diff --git a/src/app/+item-page/edit-item-page/item-operation/item-operation.component.html b/src/app/+item-page/edit-item-page/item-operation/item-operation.component.html new file mode 100644 index 0000000000..59b625d8c0 --- /dev/null +++ b/src/app/+item-page/edit-item-page/item-operation/item-operation.component.html @@ -0,0 +1,10 @@ +import {Component} from '@angular/core'; + +@Component({ + selector: 'ds-item-operation', + templateUrl: './ds-item-operation.html' +}) + +export class ItemOperationComponent { + +} diff --git a/src/app/+item-page/edit-item-page/item-operation/item-operation.component.ts b/src/app/+item-page/edit-item-page/item-operation/item-operation.component.ts new file mode 100644 index 0000000000..e69de29bb2 diff --git a/src/app/+item-page/edit-item-page/item-operation/itemOperation.model.ts b/src/app/+item-page/edit-item-page/item-operation/itemOperation.model.ts new file mode 100644 index 0000000000..e69de29bb2 From d26bba8e14847294d2453f575aab1aba0eb54c61 Mon Sep 17 00:00:00 2001 From: Yana De Pauw Date: Thu, 25 Oct 2018 18:14:22 +0200 Subject: [PATCH 06/21] 5590: Item move component --- resources/i18n/en.json | 10 ++ .../edit-item-page/edit-item-page.module.ts | 8 +- .../edit-item-page.routing.module.ts | 24 +++- .../item-move/item-move.component.html | 90 +++++++------- .../item-move/item-move.component.ts | 111 ++++++++++++++++++ .../item-operation.component.html | 25 ++-- .../item-operation.component.ts | 13 ++ .../item-operation/itemOperation.model.ts | 12 ++ .../item-status/item-status.component.html | 13 +- .../item-status/item-status.component.ts | 12 +- .../+item-page/item-page-routing.module.ts | 25 ++-- src/app/+search-page/search-page.module.ts | 80 +++++++------ src/app/app-routing.module.ts | 6 +- src/app/core/data/item-data.service.ts | 53 ++++++--- .../input-suggestions.component.ts | 9 ++ 15 files changed, 351 insertions(+), 140 deletions(-) diff --git a/resources/i18n/en.json b/resources/i18n/en.json index 5cd54869d2..2d20f21d17 100644 --- a/resources/i18n/en.json +++ b/resources/i18n/en.json @@ -103,6 +103,16 @@ "curate": { "head": "Curate" } + }, + "move": { + "head":"Move item: {{id}}", + "description": "Select the collection you wish to move this item to. To narrow down the list of displayed collections, you can enter a search query in the box.", + "inheritpolicies": { + "description": "Inherit the default policies of the destination collection", + "checkbox": "Inherit policies" + }, + "move": "Move", + "cancel": "Cancel" } } }, diff --git a/src/app/+item-page/edit-item-page/edit-item-page.module.ts b/src/app/+item-page/edit-item-page/edit-item-page.module.ts index e7016eb05d..09a5e1d588 100644 --- a/src/app/+item-page/edit-item-page/edit-item-page.module.ts +++ b/src/app/+item-page/edit-item-page/edit-item-page.module.ts @@ -4,15 +4,21 @@ import { SharedModule } from '../../shared/shared.module'; import { EditItemPageRoutingModule } from './edit-item-page.routing.module'; import { EditItemPageComponent } from './edit-item-page.component'; import { ItemStatusComponent } from './item-status/item-status.component'; +import {ItemOperationComponent} from './item-operation/item-operation.component'; +import {ItemMoveComponent} from './item-move/item-move.component'; +import {SearchPageModule} from '../../+search-page/search-page.module'; @NgModule({ imports: [ CommonModule, SharedModule, - EditItemPageRoutingModule + EditItemPageRoutingModule, + SearchPageModule.forRoot(), ], declarations: [ EditItemPageComponent, + ItemOperationComponent, + ItemMoveComponent, ItemStatusComponent ] }) diff --git a/src/app/+item-page/edit-item-page/edit-item-page.routing.module.ts b/src/app/+item-page/edit-item-page/edit-item-page.routing.module.ts index 46e8dab609..e9b0643cc1 100644 --- a/src/app/+item-page/edit-item-page/edit-item-page.routing.module.ts +++ b/src/app/+item-page/edit-item-page/edit-item-page.routing.module.ts @@ -1,7 +1,16 @@ -import { ItemPageResolver } from '../item-page.resolver'; -import { NgModule } from '@angular/core'; -import { RouterModule } from '@angular/router'; -import { EditItemPageComponent } from './edit-item-page.component'; +import {ItemPageResolver} from '../item-page.resolver'; +import {NgModule} from '@angular/core'; +import {RouterModule} from '@angular/router'; +import {EditItemPageComponent} from './edit-item-page.component'; +import {ItemMoveComponent} from './item-move/item-move.component'; +import {URLCombiner} from '../../core/url-combiner/url-combiner'; +import {getItemEditPath} from '../item-page-routing.module'; + +const ITEM_EDIT_MOVE_PATH = 'move'; + +export function getItemEditMovePath(id: string) { + return new URLCombiner(getItemEditPath(id), ITEM_EDIT_MOVE_PATH); +} @NgModule({ imports: [ @@ -12,6 +21,13 @@ import { EditItemPageComponent } from './edit-item-page.component'; resolve: { item: ItemPageResolver } + }, + { + path: ITEM_EDIT_MOVE_PATH, + component: ItemMoveComponent, + resolve: { + item: ItemPageResolver + } } ]) ], diff --git a/src/app/+item-page/edit-item-page/item-move/item-move.component.html b/src/app/+item-page/edit-item-page/item-move/item-move.component.html index a060aa0fed..fe27ed36a5 100644 --- a/src/app/+item-page/edit-item-page/item-move/item-move.component.html +++ b/src/app/+item-page/edit-item-page/item-move/item-move.component.html @@ -1,51 +1,41 @@ -import {Component, OnInit} from '@angular/core'; -import {Collection} from '../../../core/shared/collection.model'; -import {RemoteData} from '../../../core/data/remote-data'; -import {Item} from '../../../core/shared/item.model'; -import {getSucceededRemoteData} from '../../../core/shared/operators'; -import {Observable} from 'rxjs'; -import {PaginatedList} from '../../../core/data/paginated-list'; -import {TranslateService} from '@ngx-translate/core'; -import {NotificationsService} from '../../../shared/notifications/notifications.service'; -import {SearchService} from '../../../+search-page/search-service/search.service'; -import {SearchConfigurationService} from '../../../+search-page/search-service/search-configuration.service'; -import {ActivatedRoute, Router} from '@angular/router'; -import {CollectionDataService} from '../../../core/data/collection-data.service'; +
+
+
+

{{'item.edit.move.head' | translate: { id: (itemRD$ | async)?.payload?.id} }}

+

{{'item.edit.move.description' | translate}}

+
+
+ + +
+
+
+
+

+ + +

+

+ {{'item.edit.move.inheritpolicies.description' | translate}} +

+
+
-@Component({ - selector: 'ds-item-move', - templateUrl: './item-move.component.html' -}) -export class ItemMoveComponent implements OnInit { - inheritPolicies: boolean; - - itemRD$: Observable>; - - /** - * List of collections to show under the "Browse" tab - * Collections that are mapped to the item - */ - itemCollectionsRD$: Observable>>; - - constructor(private route: ActivatedRoute, - private router: Router, - private searchConfigService: SearchConfigurationService, - private searchService: SearchService, - private notificationsService: NotificationsService, - private collectionDataService: CollectionDataService, - private translateService: TranslateService) { - } - - ngOnInit(): void { - this.itemRD$ = this.route.data.map((data) => data.item).pipe(getSucceededRemoteData()) as Observable>; - this.loadCollectionLists(); - } - - /** - * Load all available collections to move the item to. - * TODO: When the API support it, only fetch collections where user has ADD rights to. - */ - loadCollectionLists() { - this.itemCollectionsRD$ = this.collectionDataService.findAll(); - } -} + + +
+
+
diff --git a/src/app/+item-page/edit-item-page/item-move/item-move.component.ts b/src/app/+item-page/edit-item-page/item-move/item-move.component.ts index e69de29bb2..e0819257c2 100644 --- a/src/app/+item-page/edit-item-page/item-move/item-move.component.ts +++ b/src/app/+item-page/edit-item-page/item-move/item-move.component.ts @@ -0,0 +1,111 @@ +import {Component, OnInit} from '@angular/core'; +import {SearchService} from '../../../+search-page/search-service/search.service'; +import {Observable} from 'rxjs/Observable'; +import {map} from 'rxjs/operators'; +import {DSpaceObjectType} from '../../../core/shared/dspace-object-type.model'; +import {SearchOptions} from '../../../+search-page/search-options.model'; +import {RemoteData} from '../../../core/data/remote-data'; +import {DSpaceObject} from '../../../core/shared/dspace-object.model'; +import {PaginatedList} from '../../../core/data/paginated-list'; +import {SearchResult} from '../../../+search-page/search-result.model'; +import {PaginatedSearchOptions} from '../../../+search-page/paginated-search-options.model'; +import {Item} from '../../../core/shared/item.model'; +import {ActivatedRoute, Router} from '@angular/router'; +import {NotificationsService} from '../../../shared/notifications/notifications.service'; +import {CollectionDataService} from '../../../core/data/collection-data.service'; +import {SearchConfigurationService} from '../../../+search-page/search-service/search-configuration.service'; +import {TranslateService} from '@ngx-translate/core'; +import {getSucceededRemoteData} from '../../../core/shared/operators'; +import {ItemDataService} from '../../../core/data/item-data.service'; +import {RestResponse} from '../../../core/cache/response-cache.models'; +import {getItemEditPath} from '../../item-page-routing.module'; + +@Component({ + selector: 'ds-item-move', + templateUrl: './item-move.component.html' +}) +export class ItemMoveComponent implements OnInit { + + inheritPolicies = false; + itemRD$: Observable>; + /** + * Search options + */ + searchOptions$: Observable; + filterSearchResults: Observable = Observable.of([]); + selectedCollection: string; + + selectedCollectionId: string; + itemId: string; + + constructor(private route: ActivatedRoute, + private router: Router, + private notificationsService: NotificationsService, + private collectionDataService: CollectionDataService, + private itemDataService: ItemDataService, + private searchConfigService: SearchConfigurationService, + private searchService: SearchService, + private translateService: TranslateService) { + } + + ngOnInit(): void { + this.itemRD$ = this.route.data.map((data) => data.item).pipe(getSucceededRemoteData()) as Observable>; + this.itemRD$.first().subscribe((rd) => { + this.itemId = rd.payload.id; + } + ); + this.searchOptions$ = this.searchConfigService.paginatedSearchOptions; + this.loadSuggestions(''); + } + + findSuggestions(query): void { + this.loadSuggestions(query); + } + + /** + * Load all available collections to move the item to. + * TODO: When the API support it, only fetch collections where user has ADD rights to. + */ + loadSuggestions(query): void { + this.filterSearchResults = this.searchService.search(new SearchOptions({ + dsoType: DSpaceObjectType.COLLECTION, + query: query + })).first().pipe( + map((rd: RemoteData>>) => { + return rd.payload.page.map((searchResult) => { + return { + displayValue: searchResult.dspaceObject.name, + value: {name: searchResult.dspaceObject.name, id: searchResult.dspaceObject.uuid} + }; + }); + }) + ); + + } + + onClick(data: any): void { + this.selectedCollection = data.name; + this.selectedCollectionId = data.id; + } + + /** + * @returns {string} the current URL + */ + getCurrentUrl() { + return this.router.url; + } + + moveCollection() { + this.itemDataService.moveToCollection(this.itemId, this.selectedCollectionId).first().subscribe( + (response: RestResponse) => { + this.router.navigate([getItemEditPath(this.itemId)]); + if (response.isSuccessful) { + this.notificationsService.success(this.translateService.get('item.move.success')); + } else { + this.notificationsService.error(this.translateService.get('item.move.error')); + } + } + ); + + } +} diff --git a/src/app/+item-page/edit-item-page/item-operation/item-operation.component.html b/src/app/+item-page/edit-item-page/item-operation/item-operation.component.html index 59b625d8c0..4623195437 100644 --- a/src/app/+item-page/edit-item-page/item-operation/item-operation.component.html +++ b/src/app/+item-page/edit-item-page/item-operation/item-operation.component.html @@ -1,10 +1,15 @@ -import {Component} from '@angular/core'; - -@Component({ - selector: 'ds-item-operation', - templateUrl: './ds-item-operation.html' -}) - -export class ItemOperationComponent { - -} +
+ + {{'item.edit.tabs.status.buttons.' + operation.operationKey + '.label' | translate}} + +
+ +
+ + {{'item.edit.tabs.status.buttons.' + operation.operationKey + '.button' | translate}} + +
\ No newline at end of file diff --git a/src/app/+item-page/edit-item-page/item-operation/item-operation.component.ts b/src/app/+item-page/edit-item-page/item-operation/item-operation.component.ts index e69de29bb2..951d66cbd8 100644 --- a/src/app/+item-page/edit-item-page/item-operation/item-operation.component.ts +++ b/src/app/+item-page/edit-item-page/item-operation/item-operation.component.ts @@ -0,0 +1,13 @@ +import {Component, Input} from '@angular/core'; +import {ItemOperation} from './itemOperation.model'; + +@Component({ + selector: 'ds-item-operation', + templateUrl: './item-operation.component.html' +}) + +export class ItemOperationComponent { + + @Input() operation: ItemOperation; + +} diff --git a/src/app/+item-page/edit-item-page/item-operation/itemOperation.model.ts b/src/app/+item-page/edit-item-page/item-operation/itemOperation.model.ts index e69de29bb2..6a54744fcb 100644 --- a/src/app/+item-page/edit-item-page/item-operation/itemOperation.model.ts +++ b/src/app/+item-page/edit-item-page/item-operation/itemOperation.model.ts @@ -0,0 +1,12 @@ +export class ItemOperation { + + operationKey: string; + operationUrl: string; + disabled: boolean; + + constructor(operationKey: string, operationUrl: string) { + this.operationKey = operationKey; + this.operationUrl = operationUrl; + } + +} diff --git a/src/app/+item-page/edit-item-page/item-status/item-status.component.html b/src/app/+item-page/edit-item-page/item-status/item-status.component.html index 78ab9174eb..0f7d9a5607 100644 --- a/src/app/+item-page/edit-item-page/item-status/item-status.component.html +++ b/src/app/+item-page/edit-item-page/item-status/item-status.component.html @@ -15,16 +15,7 @@ {{getItemPage()}}
-
-
- - {{'item.edit.tabs.status.buttons.' + actionKey + '.label' | translate}} - -
- +
+
diff --git a/src/app/+item-page/edit-item-page/item-status/item-status.component.ts b/src/app/+item-page/edit-item-page/item-status/item-status.component.ts index bc9dda61ec..e92ae10b55 100644 --- a/src/app/+item-page/edit-item-page/item-status/item-status.component.ts +++ b/src/app/+item-page/edit-item-page/item-status/item-status.component.ts @@ -2,6 +2,7 @@ import { ChangeDetectionStrategy, Component, Input, OnInit } from '@angular/core import { fadeIn, fadeInOut } from '../../../shared/animations/fade'; import { Item } from '../../../core/shared/item.model'; import { Router } from '@angular/router'; +import {ItemOperation} from '../item-operation/itemOperation.model'; @Component({ selector: 'ds-item-status', @@ -35,7 +36,7 @@ export class ItemStatusComponent implements OnInit { * The possible actions that can be performed on the item * key: id value: url to action's component */ - actions: any; + operations: ItemOperation[]; /** * The keys of the actions (to loop over) */ @@ -57,11 +58,10 @@ export class ItemStatusComponent implements OnInit { i18n example: 'item.edit.tabs.status.buttons..label' The value is supposed to be a href for the button */ - this.actions = Object.assign({ - // TODO: Create mapping component on item level - mappedCollections: this.getCurrentUrl() + '/' - }); - this.actionsKeys = Object.keys(this.actions); + this.operations = [ + new ItemOperation('mappedCollections',this.getCurrentUrl() + '/'), + new ItemOperation('move', this.getCurrentUrl() + '/move'), + ] } /** diff --git a/src/app/+item-page/item-page-routing.module.ts b/src/app/+item-page/item-page-routing.module.ts index be31b0a82d..a155d00cc0 100644 --- a/src/app/+item-page/item-page-routing.module.ts +++ b/src/app/+item-page/item-page-routing.module.ts @@ -1,10 +1,21 @@ -import { NgModule } from '@angular/core'; -import { RouterModule } from '@angular/router'; +import {NgModule} from '@angular/core'; +import {RouterModule} from '@angular/router'; -import { ItemPageComponent } from './simple/item-page.component'; -import { FullItemPageComponent } from './full/full-item-page.component'; -import { ItemPageResolver } from './item-page.resolver'; -import { AuthenticatedGuard } from '../core/auth/authenticated.guard'; +import {ItemPageComponent} from './simple/item-page.component'; +import {FullItemPageComponent} from './full/full-item-page.component'; +import {ItemPageResolver} from './item-page.resolver'; +import {AuthenticatedGuard} from '../core/auth/authenticated.guard'; +import {URLCombiner} from '../core/url-combiner/url-combiner'; +import {getItemModulePath} from '../app-routing.module'; + +export function getItemPageRoute(itemId: string) { + return new URLCombiner(getItemModulePath(), itemId).toString(); +} +export function getItemEditPath(id: string) { + return new URLCombiner(getItemModulePath(),ITEM_EDIT_PATH.replace(/:id/, id)).toString() +} + +const ITEM_EDIT_PATH = ':id/edit'; @NgModule({ imports: [ @@ -25,7 +36,7 @@ import { AuthenticatedGuard } from '../core/auth/authenticated.guard'; } }, { - path: ':id/edit', + path: ITEM_EDIT_PATH, loadChildren: './edit-item-page/edit-item-page.module#EditItemPageModule', canActivate: [AuthenticatedGuard] } diff --git a/src/app/+search-page/search-page.module.ts b/src/app/+search-page/search-page.module.ts index 0c8a4ee306..a231d8da5a 100644 --- a/src/app/+search-page/search-page.module.ts +++ b/src/app/+search-page/search-page.module.ts @@ -1,38 +1,45 @@ -import { NgModule } from '@angular/core'; -import { CommonModule } from '@angular/common'; -import { CoreModule } from '../core/core.module'; -import { SharedModule } from '../shared/shared.module'; -import { SearchPageRoutingModule } from './search-page-routing.module'; -import { SearchPageComponent } from './search-page.component'; -import { SearchResultsComponent } from './search-results/search-results.component'; -import { ItemSearchResultListElementComponent } from '../shared/object-list/search-result-list-element/item-search-result/item-search-result-list-element.component'; -import { CollectionSearchResultListElementComponent } from '../shared/object-list/search-result-list-element/collection-search-result/collection-search-result-list-element.component'; -import { CommunitySearchResultListElementComponent } from '../shared/object-list/search-result-list-element/community-search-result/community-search-result-list-element.component'; -import { ItemSearchResultGridElementComponent } from '../shared/object-grid/search-result-grid-element/item-search-result/item-search-result-grid-element.component'; -import { CommunitySearchResultGridElementComponent } from '../shared/object-grid/search-result-grid-element/community-search-result/community-search-result-grid-element.component' -import { CollectionSearchResultGridElementComponent } from '../shared/object-grid/search-result-grid-element/collection-search-result/collection-search-result-grid-element.component'; -import { SearchService } from './search-service/search.service'; -import { SearchSidebarComponent } from './search-sidebar/search-sidebar.component'; -import { SearchSidebarService } from './search-sidebar/search-sidebar.service'; -import { SearchSidebarEffects } from './search-sidebar/search-sidebar.effects'; -import { SearchSettingsComponent } from './search-settings/search-settings.component'; -import { EffectsModule } from '@ngrx/effects'; -import { SearchFiltersComponent } from './search-filters/search-filters.component'; -import { SearchFilterComponent } from './search-filters/search-filter/search-filter.component'; -import { SearchFacetFilterComponent } from './search-filters/search-filter/search-facet-filter/search-facet-filter.component'; -import { SearchFilterService } from './search-filters/search-filter/search-filter.service'; -import { SearchLabelsComponent } from './search-labels/search-labels.component'; -import { SearchRangeFilterComponent } from './search-filters/search-filter/search-range-filter/search-range-filter.component'; -import { SearchTextFilterComponent } from './search-filters/search-filter/search-text-filter/search-text-filter.component'; -import { SearchFacetFilterWrapperComponent } from './search-filters/search-filter/search-facet-filter-wrapper/search-facet-filter-wrapper.component'; -import { SearchBooleanFilterComponent } from './search-filters/search-filter/search-boolean-filter/search-boolean-filter.component'; -import { SearchHierarchyFilterComponent } from './search-filters/search-filter/search-hierarchy-filter/search-hierarchy-filter.component'; -import { SearchConfigurationService } from './search-service/search-configuration.service'; +import {ModuleWithProviders, NgModule} from '@angular/core'; +import {CommonModule} from '@angular/common'; +import {CoreModule} from '../core/core.module'; +import {SharedModule} from '../shared/shared.module'; +import {SearchPageRoutingModule} from './search-page-routing.module'; +import {SearchPageComponent} from './search-page.component'; +import {SearchResultsComponent} from './search-results/search-results.component'; +import {ItemSearchResultListElementComponent} from '../shared/object-list/search-result-list-element/item-search-result/item-search-result-list-element.component'; +import {CollectionSearchResultListElementComponent} from '../shared/object-list/search-result-list-element/collection-search-result/collection-search-result-list-element.component'; +import {CommunitySearchResultListElementComponent} from '../shared/object-list/search-result-list-element/community-search-result/community-search-result-list-element.component'; +import {ItemSearchResultGridElementComponent} from '../shared/object-grid/search-result-grid-element/item-search-result/item-search-result-grid-element.component'; +import {CommunitySearchResultGridElementComponent} from '../shared/object-grid/search-result-grid-element/community-search-result/community-search-result-grid-element.component'; +import {CollectionSearchResultGridElementComponent} from '../shared/object-grid/search-result-grid-element/collection-search-result/collection-search-result-grid-element.component'; +import {SearchService} from './search-service/search.service'; +import {SearchSidebarComponent} from './search-sidebar/search-sidebar.component'; +import {SearchSidebarService} from './search-sidebar/search-sidebar.service'; +import {SearchSidebarEffects} from './search-sidebar/search-sidebar.effects'; +import {SearchSettingsComponent} from './search-settings/search-settings.component'; +import {EffectsModule} from '@ngrx/effects'; +import {SearchFiltersComponent} from './search-filters/search-filters.component'; +import {SearchFilterComponent} from './search-filters/search-filter/search-filter.component'; +import {SearchFacetFilterComponent} from './search-filters/search-filter/search-facet-filter/search-facet-filter.component'; +import {SearchFilterService} from './search-filters/search-filter/search-filter.service'; +import {SearchLabelsComponent} from './search-labels/search-labels.component'; +import {SearchRangeFilterComponent} from './search-filters/search-filter/search-range-filter/search-range-filter.component'; +import {SearchTextFilterComponent} from './search-filters/search-filter/search-text-filter/search-text-filter.component'; +import {SearchFacetFilterWrapperComponent} from './search-filters/search-filter/search-facet-filter-wrapper/search-facet-filter-wrapper.component'; +import {SearchBooleanFilterComponent} from './search-filters/search-filter/search-boolean-filter/search-boolean-filter.component'; +import {SearchHierarchyFilterComponent} from './search-filters/search-filter/search-hierarchy-filter/search-hierarchy-filter.component'; +import {SearchConfigurationService} from './search-service/search-configuration.service'; const effects = [ SearchSidebarEffects ]; +const PROVIDERS = [ + SearchService, + SearchSidebarService, + SearchFilterService, + SearchConfigurationService +]; + @NgModule({ imports: [ SearchPageRoutingModule, @@ -65,10 +72,7 @@ const effects = [ SearchBooleanFilterComponent, ], providers: [ - SearchService, - SearchSidebarService, - SearchFilterService, - SearchConfigurationService + ...PROVIDERS ], entryComponents: [ ItemSearchResultListElementComponent, @@ -89,4 +93,12 @@ const effects = [ * This module handles all components and pipes that are necessary for the search page */ export class SearchPageModule { + static forRoot(): ModuleWithProviders { + return { + ngModule: CoreModule, + providers: [ + ...PROVIDERS + ] + }; + } } diff --git a/src/app/app-routing.module.ts b/src/app/app-routing.module.ts index 7de83651ff..e7ea10598d 100644 --- a/src/app/app-routing.module.ts +++ b/src/app/app-routing.module.ts @@ -3,6 +3,10 @@ import { RouterModule } from '@angular/router'; import { PageNotFoundComponent } from './pagenotfound/pagenotfound.component'; +const ITEM_MODULE_PATH = 'items'; +export function getItemModulePath() { + return `/${ITEM_MODULE_PATH}`; +} @NgModule({ imports: [ RouterModule.forRoot([ @@ -10,7 +14,7 @@ import { PageNotFoundComponent } from './pagenotfound/pagenotfound.component'; { path: 'home', loadChildren: './+home-page/home-page.module#HomePageModule' }, { path: 'communities', loadChildren: './+community-page/community-page.module#CommunityPageModule' }, { path: 'collections', loadChildren: './+collection-page/collection-page.module#CollectionPageModule' }, - { path: 'items', loadChildren: './+item-page/item-page.module#ItemPageModule' }, + { path: ITEM_MODULE_PATH, loadChildren: './+item-page/item-page.module#ItemPageModule' }, { path: 'search', loadChildren: './+search-page/search-page.module#SearchPageModule' }, { path: 'browse', loadChildren: './+browse-by/browse-by.module#BrowseByModule' }, { path: 'admin', loadChildren: './+admin/admin.module#AdminModule' }, diff --git a/src/app/core/data/item-data.service.ts b/src/app/core/data/item-data.service.ts index f984dceb12..90311a6f82 100644 --- a/src/app/core/data/item-data.service.ts +++ b/src/app/core/data/item-data.service.ts @@ -1,21 +1,24 @@ -import { Inject, Injectable } from '@angular/core'; +import {Injectable} from '@angular/core'; -import { Store } from '@ngrx/store'; -import { Observable } from 'rxjs/Observable'; -import { GLOBAL_CONFIG, GlobalConfig } from '../../../config'; -import { isEmpty, isNotEmpty } from '../../shared/empty.util'; -import { BrowseService } from '../browse/browse.service'; -import { RemoteDataBuildService } from '../cache/builders/remote-data-build.service'; -import { NormalizedItem } from '../cache/models/normalized-item.model'; -import { ResponseCacheService } from '../cache/response-cache.service'; -import { CoreState } from '../core.reducers'; -import { Item } from '../shared/item.model'; -import { URLCombiner } from '../url-combiner/url-combiner'; +import {Store} from '@ngrx/store'; +import {Observable} from 'rxjs/Observable'; +import {isNotEmpty, isNotEmptyOperator} from '../../shared/empty.util'; +import {BrowseService} from '../browse/browse.service'; +import {RemoteDataBuildService} from '../cache/builders/remote-data-build.service'; +import {NormalizedItem} from '../cache/models/normalized-item.model'; +import {ResponseCacheService} from '../cache/response-cache.service'; +import {CoreState} from '../core.reducers'; +import {Item} from '../shared/item.model'; +import {URLCombiner} from '../url-combiner/url-combiner'; -import { DataService } from './data.service'; -import { RequestService } from './request.service'; -import { HALEndpointService } from '../shared/hal-endpoint.service'; -import { FindAllOptions } from './request.models'; +import {DataService} from './data.service'; +import {RequestService} from './request.service'; +import {HALEndpointService} from '../shared/hal-endpoint.service'; +import {FindAllOptions, PostRequest, RestRequest} from './request.models'; +import {distinctUntilChanged, map} from 'rxjs/operators'; +import {RestResponse} from '../cache/response-cache.models'; +import {configureRequest, getResponseFromSelflink} from '../shared/operators'; +import {ResponseCacheEntry} from '../cache/response-cache.reducer'; @Injectable() export class ItemDataService extends DataService { @@ -48,4 +51,22 @@ export class ItemDataService extends DataService { .distinctUntilChanged(); } + public getMoveItemEndpoint(itemId: string, collectionId?: string): Observable { + return this.halService.getEndpoint(this.linkPath).pipe( + map((endpoint: string) => this.getFindByIDHref(endpoint, itemId)), + map((endpoint: string) => `${endpoint}/owningCollection/move/${collectionId ? `/${collectionId}` : ''}`) + ); + } + + public moveToCollection(itemId: string, collectionId: string): Observable { + return this.getMoveItemEndpoint(itemId, collectionId).pipe( + // isNotEmptyOperator(), + distinctUntilChanged(), + map((endpointURL: string) => new PostRequest(this.requestService.generateRequestId(), endpointURL)), + configureRequest(this.requestService), + map((request: RestRequest) => request.href), + getResponseFromSelflink(this.responseCache), + map((responseCacheEntry: ResponseCacheEntry) => responseCacheEntry.response) + ); + } } diff --git a/src/app/shared/input-suggestions/input-suggestions.component.ts b/src/app/shared/input-suggestions/input-suggestions.component.ts index eb28583eaa..ae15a805e9 100644 --- a/src/app/shared/input-suggestions/input-suggestions.component.ts +++ b/src/app/shared/input-suggestions/input-suggestions.component.ts @@ -159,6 +159,15 @@ export class InputSuggestionsComponent { this.show.next(false); } + /** + * Changes the show variable so the suggestion dropdown opens + */ + open() { + if (!this.blockReopen) { + this.show.next(true); + } + } + /** * For usage of the isNotEmpty function in the template */ From 4411c312e5861b4e3702e6325a34dfd306f692c7 Mon Sep 17 00:00:00 2001 From: Yana De Pauw Date: Mon, 26 Nov 2018 16:28:39 +0100 Subject: [PATCH 07/21] 55990: Add move item component --- .../item-move/item-move.component.html | 2 +- .../item-move/item-move.component.spec.ts | 179 ++++++++++++++++++ .../item-move/item-move.component.ts | 28 +-- .../item-operation.component.spec.ts | 44 +++++ .../item-operation.component.ts | 4 +- .../item-operation/itemOperation.model.ts | 9 + .../item-status/item-status.component.spec.ts | 3 +- .../search-hierarchy-filter.component.html | 2 +- .../search-text-filter.component.html | 2 +- 9 files changed, 256 insertions(+), 17 deletions(-) create mode 100644 src/app/+item-page/edit-item-page/item-move/item-move.component.spec.ts create mode 100644 src/app/+item-page/edit-item-page/item-operation/item-operation.component.spec.ts diff --git a/src/app/+item-page/edit-item-page/item-move/item-move.component.html b/src/app/+item-page/edit-item-page/item-move/item-move.component.html index fe27ed36a5..0c97628d4c 100644 --- a/src/app/+item-page/edit-item-page/item-move/item-move.component.html +++ b/src/app/+item-page/edit-item-page/item-move/item-move.component.html @@ -6,7 +6,7 @@
; + +const mockItem = Object.assign(new Item(), { + id: 'fake-id', + handle: 'fake/handle', + lastModified: '2018' +}); + +const itemPageUrl = `fake-url/${mockItem.id}`; +const routerStub = Object.assign(new RouterStub(), { + url: `${itemPageUrl}/edit` +}); + +const mockItemDataService = jasmine.createSpyObj({ + moveToCollection: Observable.of(new RestResponse(true, '200')) +}); + +const mockItemDataServiceFail = jasmine.createSpyObj({ + moveToCollection: Observable.of(new RestResponse(false, '500')) +}); + +const routeStub = { + data: Observable.of({ + item: new RemoteData(false, false, true, null, { + id: 'item1' + }) + }) +}; + +const mockSearchService = { + search: () => { + return Observable.of(new RemoteData(false, false, true, null, + new PaginatedList(null, [ + { + dspaceObject: { + name: 'Test collection 1', + uuid: 'collection1' + }, hitHighlights: {} + }, { + dspaceObject: { + name: 'Test collection 2', + uuid: 'collection2' + }, hitHighlights: {} + } + ]))); + } +}; + +const notificationsServiceStub = new NotificationsServiceStub(); + +describe('ItemMoveComponent', () => { + beforeEach(async(() => { + TestBed.configureTestingModule({ + imports: [CommonModule, FormsModule, RouterTestingModule.withRoutes([]), TranslateModule.forRoot(), NgbModule.forRoot()], + declarations: [ItemMoveComponent], + providers: [ + {provide: ActivatedRoute, useValue: routeStub}, + {provide: Router, useValue: routerStub}, + {provide: ItemDataService, useValue: mockItemDataService}, + {provide: NotificationsService, useValue: notificationsServiceStub}, + {provide: SearchService, useValue: mockSearchService}, + ], schemas: [ + CUSTOM_ELEMENTS_SCHEMA + ] + }).compileComponents(); + })); + + beforeEach(() => { + fixture = TestBed.createComponent(ItemMoveComponent); + comp = fixture.componentInstance; + fixture.detectChanges(); + }); + it('should load suggestions', () => { + const expected = [ + { + displayValue: 'Test collection 1', + value: { + name: 'Test collection 1', + id: 'collection1', + } + }, + { + displayValue: 'Test collection 2', + value: { + name: 'Test collection 2', + id: 'collection2', + } + } + ]; + + comp.CollectionSearchResults.subscribe((value) => { + expect(value).toEqual(expected); + } + ); + }); + it('should get current url ', () => { + expect(comp.getCurrentUrl()).toEqual('fake-url/fake-id/edit'); + }); + it('should on click select the correct collection name and id', () => { + const data = { + name: 'Test collection 1', + id: 'collection1', + }; + comp.onClick(data); + + expect(comp.selectedCollection).toEqual('Test collection 1'); + expect(comp.selectedCollectionId).toEqual('collection1'); + }); + describe('moveCollection', () => { + it('should call itemDataService.moveToCollection', () => { + comp.itemId = 'item-id'; + comp.selectedCollectionId = 'selected-collection-id'; + comp.moveCollection(); + + expect(mockItemDataService.moveToCollection).toHaveBeenCalledWith('item-id', 'selected-collection-id'); + }); + it('should call notificationsService success message on success', () => { + spyOn(notificationsServiceStub, 'success'); + + comp.moveCollection(); + + expect(notificationsServiceStub.success).toHaveBeenCalled(); + }); + }); +}); + +describe('ItemMoveComponent fail', () => { + beforeEach(async(() => { + TestBed.configureTestingModule({ + imports: [CommonModule, FormsModule, RouterTestingModule.withRoutes([]), TranslateModule.forRoot(), NgbModule.forRoot()], + declarations: [ItemMoveComponent], + providers: [ + {provide: ActivatedRoute, useValue: routeStub}, + {provide: Router, useValue: routerStub}, + {provide: ItemDataService, useValue: mockItemDataServiceFail}, + {provide: NotificationsService, useValue: notificationsServiceStub}, + {provide: SearchService, useValue: mockSearchService}, + ], schemas: [ + CUSTOM_ELEMENTS_SCHEMA + ] + }).compileComponents(); + })); + + beforeEach(() => { + fixture = TestBed.createComponent(ItemMoveComponent); + comp = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should call notificationsService error message on fail', () => { + spyOn(notificationsServiceStub, 'error'); + + comp.moveCollection(); + + expect(notificationsServiceStub.error).toHaveBeenCalled(); + }); +}); diff --git a/src/app/+item-page/edit-item-page/item-move/item-move.component.ts b/src/app/+item-page/edit-item-page/item-move/item-move.component.ts index e0819257c2..338d4b96a3 100644 --- a/src/app/+item-page/edit-item-page/item-move/item-move.component.ts +++ b/src/app/+item-page/edit-item-page/item-move/item-move.component.ts @@ -8,12 +8,9 @@ import {RemoteData} from '../../../core/data/remote-data'; import {DSpaceObject} from '../../../core/shared/dspace-object.model'; import {PaginatedList} from '../../../core/data/paginated-list'; import {SearchResult} from '../../../+search-page/search-result.model'; -import {PaginatedSearchOptions} from '../../../+search-page/paginated-search-options.model'; import {Item} from '../../../core/shared/item.model'; import {ActivatedRoute, Router} from '@angular/router'; import {NotificationsService} from '../../../shared/notifications/notifications.service'; -import {CollectionDataService} from '../../../core/data/collection-data.service'; -import {SearchConfigurationService} from '../../../+search-page/search-service/search-configuration.service'; import {TranslateService} from '@ngx-translate/core'; import {getSucceededRemoteData} from '../../../core/shared/operators'; import {ItemDataService} from '../../../core/data/item-data.service'; @@ -24,15 +21,14 @@ import {getItemEditPath} from '../../item-page-routing.module'; selector: 'ds-item-move', templateUrl: './item-move.component.html' }) +/** + * Component that handles the moving of an item to a different collection + */ export class ItemMoveComponent implements OnInit { inheritPolicies = false; itemRD$: Observable>; - /** - * Search options - */ - searchOptions$: Observable; - filterSearchResults: Observable = Observable.of([]); + CollectionSearchResults: Observable = Observable.of([]); selectedCollection: string; selectedCollectionId: string; @@ -41,9 +37,7 @@ export class ItemMoveComponent implements OnInit { constructor(private route: ActivatedRoute, private router: Router, private notificationsService: NotificationsService, - private collectionDataService: CollectionDataService, private itemDataService: ItemDataService, - private searchConfigService: SearchConfigurationService, private searchService: SearchService, private translateService: TranslateService) { } @@ -54,10 +48,13 @@ export class ItemMoveComponent implements OnInit { this.itemId = rd.payload.id; } ); - this.searchOptions$ = this.searchConfigService.paginatedSearchOptions; this.loadSuggestions(''); } + /** + * Find suggestions based on entered query + * @param query - Search query + */ findSuggestions(query): void { this.loadSuggestions(query); } @@ -67,7 +64,7 @@ export class ItemMoveComponent implements OnInit { * TODO: When the API support it, only fetch collections where user has ADD rights to. */ loadSuggestions(query): void { - this.filterSearchResults = this.searchService.search(new SearchOptions({ + this.CollectionSearchResults = this.searchService.search(new SearchOptions({ dsoType: DSpaceObjectType.COLLECTION, query: query })).first().pipe( @@ -83,6 +80,10 @@ export class ItemMoveComponent implements OnInit { } + /** + * Set the collection name and id based on the selected value + * @param data - obtained from the ds-input-suggestions component + */ onClick(data: any): void { this.selectedCollection = data.name; this.selectedCollectionId = data.id; @@ -95,6 +96,9 @@ export class ItemMoveComponent implements OnInit { return this.router.url; } + /** + * Moves the item to a new collection based on the selected collection + */ moveCollection() { this.itemDataService.moveToCollection(this.itemId, this.selectedCollectionId).first().subscribe( (response: RestResponse) => { diff --git a/src/app/+item-page/edit-item-page/item-operation/item-operation.component.spec.ts b/src/app/+item-page/edit-item-page/item-operation/item-operation.component.spec.ts new file mode 100644 index 0000000000..092f3af0ac --- /dev/null +++ b/src/app/+item-page/edit-item-page/item-operation/item-operation.component.spec.ts @@ -0,0 +1,44 @@ +import {ItemOperation} from './itemOperation.model'; +import {async, TestBed} from '@angular/core/testing'; +import {ItemOperationComponent} from './item-operation.component'; +import {TranslateModule} from '@ngx-translate/core'; +import {By} from '@angular/platform-browser'; + +describe('ItemOperationComponent', () => { + const itemOperation: ItemOperation = new ItemOperation('key1', 'url1'); + + let fixture; + let comp; + + beforeEach(async(() => { + TestBed.configureTestingModule({ + imports: [TranslateModule.forRoot()], + declarations: [ItemOperationComponent] + }).compileComponents(); + })); + + beforeEach(() => { + + fixture = TestBed.createComponent(ItemOperationComponent); + comp = fixture.componentInstance; + comp.operation = itemOperation; + fixture.detectChanges(); + }); + + it('should render operation row', () => { + const span = fixture.debugElement.query(By.css('span')).nativeElement; + expect(span.textContent).toContain('item.edit.tabs.status.buttons.key1.label'); + const link = fixture.debugElement.query(By.css('a')).nativeElement; + expect(link.href).toContain('url1'); + expect(link.textContent).toContain('item.edit.tabs.status.buttons.key1.button'); + }); + it('should render disabled operation row', () => { + itemOperation.setDisabled(true); + fixture.detectChanges(); + + const span = fixture.debugElement.query(By.css('span')).nativeElement; + expect(span.textContent).toContain('item.edit.tabs.status.buttons.key1.label'); + const span2 = fixture.debugElement.query(By.css('span.btn-danger')).nativeElement; + expect(span2.textContent).toContain('item.edit.tabs.status.buttons.key1.button'); + }); +}); diff --git a/src/app/+item-page/edit-item-page/item-operation/item-operation.component.ts b/src/app/+item-page/edit-item-page/item-operation/item-operation.component.ts index 951d66cbd8..76d056df95 100644 --- a/src/app/+item-page/edit-item-page/item-operation/item-operation.component.ts +++ b/src/app/+item-page/edit-item-page/item-operation/item-operation.component.ts @@ -5,7 +5,9 @@ import {ItemOperation} from './itemOperation.model'; selector: 'ds-item-operation', templateUrl: './item-operation.component.html' }) - +/** + * Operation that can be performed on an item + */ export class ItemOperationComponent { @Input() operation: ItemOperation; diff --git a/src/app/+item-page/edit-item-page/item-operation/itemOperation.model.ts b/src/app/+item-page/edit-item-page/item-operation/itemOperation.model.ts index 6a54744fcb..0104dfbdb3 100644 --- a/src/app/+item-page/edit-item-page/item-operation/itemOperation.model.ts +++ b/src/app/+item-page/edit-item-page/item-operation/itemOperation.model.ts @@ -7,6 +7,15 @@ export class ItemOperation { constructor(operationKey: string, operationUrl: string) { this.operationKey = operationKey; this.operationUrl = operationUrl; + this.setDisabled(false); + } + + /** + * Set whether this operation should be disabled + * @param disabled + */ + setDisabled(disabled: boolean): void { + this.disabled = disabled; } } diff --git a/src/app/+item-page/edit-item-page/item-status/item-status.component.spec.ts b/src/app/+item-page/edit-item-page/item-status/item-status.component.spec.ts index 2df4b977cb..319d4c47ae 100644 --- a/src/app/+item-page/edit-item-page/item-status/item-status.component.spec.ts +++ b/src/app/+item-page/edit-item-page/item-status/item-status.component.spec.ts @@ -10,6 +10,7 @@ import { Router } from '@angular/router'; import { RouterStub } from '../../../shared/testing/router-stub'; import { Item } from '../../../core/shared/item.model'; import { By } from '@angular/platform-browser'; +import {CUSTOM_ELEMENTS_SCHEMA} from '@angular/core'; describe('ItemStatusComponent', () => { let comp: ItemStatusComponent; @@ -33,7 +34,7 @@ describe('ItemStatusComponent', () => { providers: [ { provide: Router, useValue: routerStub }, { provide: HostWindowService, useValue: new HostWindowServiceStub(0) } - ] + ], schemas: [CUSTOM_ELEMENTS_SCHEMA] }).compileComponents(); })); diff --git a/src/app/+search-page/search-filters/search-filter/search-hierarchy-filter/search-hierarchy-filter.component.html b/src/app/+search-page/search-filters/search-filter/search-hierarchy-filter/search-hierarchy-filter.component.html index 812f543716..962d09e6c4 100644 --- a/src/app/+search-page/search-filters/search-filter/search-hierarchy-filter/search-hierarchy-filter.component.html +++ b/src/app/+search-page/search-filters/search-filter/search-hierarchy-filter/search-hierarchy-filter.component.html @@ -30,7 +30,7 @@ | translate}}
-
- Date: Tue, 27 Nov 2018 14:38:19 +0100 Subject: [PATCH 08/21] 55990: Fix param name --- .../edit-item-page/item-move/item-move.component.html | 2 +- .../edit-item-page/item-move/item-move.component.spec.ts | 2 +- .../edit-item-page/item-move/item-move.component.ts | 4 ++-- .../search-hierarchy-filter.component.html | 2 +- .../search-text-filter/search-text-filter.component.html | 2 +- 5 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/app/+item-page/edit-item-page/item-move/item-move.component.html b/src/app/+item-page/edit-item-page/item-move/item-move.component.html index 0c97628d4c..0a8e4b68b5 100644 --- a/src/app/+item-page/edit-item-page/item-move/item-move.component.html +++ b/src/app/+item-page/edit-item-page/item-move/item-move.component.html @@ -6,7 +6,7 @@
{ } ]; - comp.CollectionSearchResults.subscribe((value) => { + comp.collectionSearchResults.subscribe((value) => { expect(value).toEqual(expected); } ); diff --git a/src/app/+item-page/edit-item-page/item-move/item-move.component.ts b/src/app/+item-page/edit-item-page/item-move/item-move.component.ts index 338d4b96a3..359c04c8e7 100644 --- a/src/app/+item-page/edit-item-page/item-move/item-move.component.ts +++ b/src/app/+item-page/edit-item-page/item-move/item-move.component.ts @@ -28,7 +28,7 @@ export class ItemMoveComponent implements OnInit { inheritPolicies = false; itemRD$: Observable>; - CollectionSearchResults: Observable = Observable.of([]); + collectionSearchResults: Observable = Observable.of([]); selectedCollection: string; selectedCollectionId: string; @@ -64,7 +64,7 @@ export class ItemMoveComponent implements OnInit { * TODO: When the API support it, only fetch collections where user has ADD rights to. */ loadSuggestions(query): void { - this.CollectionSearchResults = this.searchService.search(new SearchOptions({ + this.collectionSearchResults = this.searchService.search(new SearchOptions({ dsoType: DSpaceObjectType.COLLECTION, query: query })).first().pipe( diff --git a/src/app/+search-page/search-filters/search-filter/search-hierarchy-filter/search-hierarchy-filter.component.html b/src/app/+search-page/search-filters/search-filter/search-hierarchy-filter/search-hierarchy-filter.component.html index 962d09e6c4..812f543716 100644 --- a/src/app/+search-page/search-filters/search-filter/search-hierarchy-filter/search-hierarchy-filter.component.html +++ b/src/app/+search-page/search-filters/search-filter/search-hierarchy-filter/search-hierarchy-filter.component.html @@ -30,7 +30,7 @@ | translate}}
-
- Date: Thu, 29 Nov 2018 11:39:57 +0100 Subject: [PATCH 09/21] 55990: Move item component - fix message --- resources/i18n/en.json | 1 + .../edit-item-page/item-move/item-move.component.html | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/resources/i18n/en.json b/resources/i18n/en.json index 395838c289..3cdf0bc180 100644 --- a/resources/i18n/en.json +++ b/resources/i18n/en.json @@ -107,6 +107,7 @@ "move": { "head":"Move item: {{id}}", "description": "Select the collection you wish to move this item to. To narrow down the list of displayed collections, you can enter a search query in the box.", + "search.placeholder": "Enter a search query to look for collections", "inheritpolicies": { "description": "Inherit the default policies of the destination collection", "checkbox": "Inherit policies" diff --git a/src/app/+item-page/edit-item-page/item-move/item-move.component.html b/src/app/+item-page/edit-item-page/item-move/item-move.component.html index 0a8e4b68b5..b3627e65bb 100644 --- a/src/app/+item-page/edit-item-page/item-move/item-move.component.html +++ b/src/app/+item-page/edit-item-page/item-move/item-move.component.html @@ -7,7 +7,7 @@
Date: Fri, 30 Nov 2018 11:18:57 +0100 Subject: [PATCH 10/21] 55990: Item move - tweaks --- resources/i18n/en.json | 4 +++- .../edit-item-page/item-move/item-move.component.html | 4 ++-- .../edit-item-page/item-move/item-move.component.ts | 4 ++-- 3 files changed, 7 insertions(+), 5 deletions(-) diff --git a/resources/i18n/en.json b/resources/i18n/en.json index 3cdf0bc180..cf87e423a7 100644 --- a/resources/i18n/en.json +++ b/resources/i18n/en.json @@ -113,7 +113,9 @@ "checkbox": "Inherit policies" }, "move": "Move", - "cancel": "Cancel" + "cancel": "Cancel", + "success": "The item has been moved succesfully", + "error": "An error occured when attempting to move the item" } } }, diff --git a/src/app/+item-page/edit-item-page/item-move/item-move.component.html b/src/app/+item-page/edit-item-page/item-move/item-move.component.html index b3627e65bb..063028c719 100644 --- a/src/app/+item-page/edit-item-page/item-move/item-move.component.html +++ b/src/app/+item-page/edit-item-page/item-move/item-move.component.html @@ -1,7 +1,7 @@
-

{{'item.edit.move.head' | translate: { id: (itemRD$ | async)?.payload?.id} }}

+

{{'item.edit.move.head' | translate: { id: (itemRD$ | async)?.payload?.handle} }}

{{'item.edit.move.description' | translate}}

@@ -33,7 +33,7 @@ -
diff --git a/src/app/+item-page/edit-item-page/item-move/item-move.component.ts b/src/app/+item-page/edit-item-page/item-move/item-move.component.ts index 359c04c8e7..07894c4504 100644 --- a/src/app/+item-page/edit-item-page/item-move/item-move.component.ts +++ b/src/app/+item-page/edit-item-page/item-move/item-move.component.ts @@ -104,9 +104,9 @@ export class ItemMoveComponent implements OnInit { (response: RestResponse) => { this.router.navigate([getItemEditPath(this.itemId)]); if (response.isSuccessful) { - this.notificationsService.success(this.translateService.get('item.move.success')); + this.notificationsService.success(this.translateService.get('item.edit.move.success')); } else { - this.notificationsService.error(this.translateService.get('item.move.error')); + this.notificationsService.error(this.translateService.get('item.edit.move.error')); } } ); From a698b56ae804ab3a51726c1a4170942da4d561cb Mon Sep 17 00:00:00 2001 From: Yana De Pauw Date: Thu, 6 Dec 2018 10:42:37 +0100 Subject: [PATCH 11/21] 55990: Fix issues to move item component after master merge --- .../edit-item-page.component.ts | 11 +++++----- .../item-move/item-move.component.spec.ts | 13 ++++++------ .../item-move/item-move.component.ts | 21 ++++++++++++------- .../item-operation.component.spec.ts | 8 +++---- src/app/core/data/item-data.service.ts | 7 +++---- 5 files changed, 32 insertions(+), 28 deletions(-) diff --git a/src/app/+item-page/edit-item-page/edit-item-page.component.ts b/src/app/+item-page/edit-item-page/edit-item-page.component.ts index 8bcf53f140..de40239b3e 100644 --- a/src/app/+item-page/edit-item-page/edit-item-page.component.ts +++ b/src/app/+item-page/edit-item-page/edit-item-page.component.ts @@ -1,9 +1,10 @@ -import { fadeIn, fadeInOut } from '../../shared/animations/fade'; import { ChangeDetectionStrategy, Component, OnInit } from '@angular/core'; import { ActivatedRoute } from '@angular/router'; -import { Observable } from 'rxjs/Observable'; -import { RemoteData } from '../../core/data/remote-data'; -import { Item } from '../../core/shared/item.model'; +import {fadeIn, fadeInOut} from '../../shared/animations/fade'; +import {Observable} from 'rxjs'; +import {RemoteData} from '../../core/data/remote-data'; +import {Item} from '../../core/shared/item.model'; +import {map} from 'rxjs/operators'; @Component({ selector: 'ds-edit-item-page', @@ -28,7 +29,7 @@ export class EditItemPageComponent implements OnInit { } ngOnInit(): void { - this.itemRD$ = this.route.data.map((data) => data.item); + this.itemRD$ = this.route.data.pipe(map((data) => data.item)); } } diff --git a/src/app/+item-page/edit-item-page/item-move/item-move.component.spec.ts b/src/app/+item-page/edit-item-page/item-move/item-move.component.spec.ts index c61a9ed0d3..eaf8e15fa4 100644 --- a/src/app/+item-page/edit-item-page/item-move/item-move.component.spec.ts +++ b/src/app/+item-page/edit-item-page/item-move/item-move.component.spec.ts @@ -10,14 +10,13 @@ import {ItemMoveComponent} from './item-move.component'; import {NotificationsServiceStub} from '../../../shared/testing/notifications-service-stub'; import {NotificationsService} from '../../../shared/notifications/notifications.service'; import {SearchService} from '../../../+search-page/search-service/search.service'; -import {Observable} from 'rxjs/Observable'; -import 'rxjs/add/observable/of'; -import {CUSTOM_ELEMENTS_SCHEMA} from '@angular/core'; +import {of as observableOf} from 'rxjs'; import {FormsModule} from '@angular/forms'; import {ItemDataService} from '../../../core/data/item-data.service'; import {RestResponse} from '../../../core/cache/response-cache.models'; import {RemoteData} from '../../../core/data/remote-data'; import {PaginatedList} from '../../../core/data/paginated-list'; +import {CUSTOM_ELEMENTS_SCHEMA} from '@angular/core'; let comp: ItemMoveComponent; let fixture: ComponentFixture; @@ -34,15 +33,15 @@ const routerStub = Object.assign(new RouterStub(), { }); const mockItemDataService = jasmine.createSpyObj({ - moveToCollection: Observable.of(new RestResponse(true, '200')) + moveToCollection: observableOf(new RestResponse(true, '200')) }); const mockItemDataServiceFail = jasmine.createSpyObj({ - moveToCollection: Observable.of(new RestResponse(false, '500')) + moveToCollection: observableOf(new RestResponse(false, '500')) }); const routeStub = { - data: Observable.of({ + data: observableOf({ item: new RemoteData(false, false, true, null, { id: 'item1' }) @@ -51,7 +50,7 @@ const routeStub = { const mockSearchService = { search: () => { - return Observable.of(new RemoteData(false, false, true, null, + return observableOf(new RemoteData(false, false, true, null, new PaginatedList(null, [ { dspaceObject: { diff --git a/src/app/+item-page/edit-item-page/item-move/item-move.component.ts b/src/app/+item-page/edit-item-page/item-move/item-move.component.ts index 07894c4504..9147ae2238 100644 --- a/src/app/+item-page/edit-item-page/item-move/item-move.component.ts +++ b/src/app/+item-page/edit-item-page/item-move/item-move.component.ts @@ -1,7 +1,6 @@ import {Component, OnInit} from '@angular/core'; import {SearchService} from '../../../+search-page/search-service/search.service'; -import {Observable} from 'rxjs/Observable'; -import {map} from 'rxjs/operators'; +import {first, map} from 'rxjs/operators'; import {DSpaceObjectType} from '../../../core/shared/dspace-object-type.model'; import {SearchOptions} from '../../../+search-page/search-options.model'; import {RemoteData} from '../../../core/data/remote-data'; @@ -16,6 +15,8 @@ import {getSucceededRemoteData} from '../../../core/shared/operators'; import {ItemDataService} from '../../../core/data/item-data.service'; import {RestResponse} from '../../../core/cache/response-cache.models'; import {getItemEditPath} from '../../item-page-routing.module'; +import {Observable} from 'rxjs'; +import {of as observableOf} from 'rxjs'; @Component({ selector: 'ds-item-move', @@ -25,10 +26,13 @@ import {getItemEditPath} from '../../item-page-routing.module'; * Component that handles the moving of an item to a different collection */ export class ItemMoveComponent implements OnInit { - + /** + * TODO: There is currently no backend support to change the owningCollection and inherit policies, + * TODO: when this is added, the inherit policies option should be used. + */ inheritPolicies = false; itemRD$: Observable>; - collectionSearchResults: Observable = Observable.of([]); + collectionSearchResults: Observable = observableOf([]); selectedCollection: string; selectedCollectionId: string; @@ -43,8 +47,8 @@ export class ItemMoveComponent implements OnInit { } ngOnInit(): void { - this.itemRD$ = this.route.data.map((data) => data.item).pipe(getSucceededRemoteData()) as Observable>; - this.itemRD$.first().subscribe((rd) => { + this.itemRD$ = this.route.data.pipe(map((data) => data.item),getSucceededRemoteData()) as Observable>; + this.itemRD$.subscribe((rd) => { this.itemId = rd.payload.id; } ); @@ -67,7 +71,8 @@ export class ItemMoveComponent implements OnInit { this.collectionSearchResults = this.searchService.search(new SearchOptions({ dsoType: DSpaceObjectType.COLLECTION, query: query - })).first().pipe( + })).pipe( + first(), map((rd: RemoteData>>) => { return rd.payload.page.map((searchResult) => { return { @@ -100,7 +105,7 @@ export class ItemMoveComponent implements OnInit { * Moves the item to a new collection based on the selected collection */ moveCollection() { - this.itemDataService.moveToCollection(this.itemId, this.selectedCollectionId).first().subscribe( + this.itemDataService.moveToCollection(this.itemId, this.selectedCollectionId).pipe(first()).subscribe( (response: RestResponse) => { this.router.navigate([getItemEditPath(this.itemId)]); if (response.isSuccessful) { diff --git a/src/app/+item-page/edit-item-page/item-operation/item-operation.component.spec.ts b/src/app/+item-page/edit-item-page/item-operation/item-operation.component.spec.ts index 092f3af0ac..15feb5aeda 100644 --- a/src/app/+item-page/edit-item-page/item-operation/item-operation.component.spec.ts +++ b/src/app/+item-page/edit-item-page/item-operation/item-operation.component.spec.ts @@ -4,11 +4,11 @@ import {ItemOperationComponent} from './item-operation.component'; import {TranslateModule} from '@ngx-translate/core'; import {By} from '@angular/platform-browser'; -describe('ItemOperationComponent', () => { - const itemOperation: ItemOperation = new ItemOperation('key1', 'url1'); +const itemOperation: ItemOperation = new ItemOperation('key1', 'url1'); - let fixture; - let comp; +let fixture; +let comp; +describe('ItemOperationComponent', () => { beforeEach(async(() => { TestBed.configureTestingModule({ diff --git a/src/app/core/data/item-data.service.ts b/src/app/core/data/item-data.service.ts index d6c76bff2b..84eca23507 100644 --- a/src/app/core/data/item-data.service.ts +++ b/src/app/core/data/item-data.service.ts @@ -1,7 +1,6 @@ import {Injectable} from '@angular/core'; - import {distinctUntilChanged, map, filter} from 'rxjs/operators'; -import { Injectable } from '@angular/core';import {Store} from '@ngrx/store'; +import {Store} from '@ngrx/store'; import {Observable} from 'rxjs'; import {isNotEmpty, isNotEmptyOperator} from '../../shared/empty.util'; import {BrowseService} from '../browse/browse.service'; @@ -15,7 +14,7 @@ import {URLCombiner} from '../url-combiner/url-combiner'; import {DataService} from './data.service'; import {RequestService} from './request.service'; import {HALEndpointService} from '../shared/hal-endpoint.service'; -import {FindAllOptions, PostRequest, RestRequest} from './request.models'; +import {FindAllOptions, PostRequest, PutRequest, RestRequest} from './request.models'; import {RestResponse} from '../cache/response-cache.models'; import {configureRequest, getResponseFromSelflink} from '../shared/operators'; import {ResponseCacheEntry} from '../cache/response-cache.reducer'; @@ -62,7 +61,7 @@ export class ItemDataService extends DataService { return this.getMoveItemEndpoint(itemId, collectionId).pipe( // isNotEmptyOperator(), distinctUntilChanged(), - map((endpointURL: string) => new PostRequest(this.requestService.generateRequestId(), endpointURL)), + map((endpointURL: string) => new PutRequest(this.requestService.generateRequestId(), endpointURL)), configureRequest(this.requestService), map((request: RestRequest) => request.href), getResponseFromSelflink(this.responseCache), From e2420c56d38cb3d34d8738985acb991d9dc9dd73 Mon Sep 17 00:00:00 2001 From: Yana De Pauw Date: Thu, 6 Dec 2018 15:59:45 +0100 Subject: [PATCH 12/21] Fix item opertation test issue --- .../item-operation/item-operation.component.spec.ts | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/app/+item-page/edit-item-page/item-operation/item-operation.component.spec.ts b/src/app/+item-page/edit-item-page/item-operation/item-operation.component.spec.ts index 15feb5aeda..54d5a8fe4a 100644 --- a/src/app/+item-page/edit-item-page/item-operation/item-operation.component.spec.ts +++ b/src/app/+item-page/edit-item-page/item-operation/item-operation.component.spec.ts @@ -4,11 +4,11 @@ import {ItemOperationComponent} from './item-operation.component'; import {TranslateModule} from '@ngx-translate/core'; import {By} from '@angular/platform-browser'; -const itemOperation: ItemOperation = new ItemOperation('key1', 'url1'); - -let fixture; -let comp; describe('ItemOperationComponent', () => { + let itemOperation: ItemOperation; + + let fixture; + let comp; beforeEach(async(() => { TestBed.configureTestingModule({ @@ -19,6 +19,8 @@ describe('ItemOperationComponent', () => { beforeEach(() => { + itemOperation = new ItemOperation('key1', 'url1'); + fixture = TestBed.createComponent(ItemOperationComponent); comp = fixture.componentInstance; comp.operation = itemOperation; From 1e6226205083dcc02c50b2320c4d77be9c0f5933 Mon Sep 17 00:00:00 2001 From: Yana De Pauw Date: Wed, 19 Dec 2018 13:20:42 +0100 Subject: [PATCH 13/21] Remove unrelated ItemOperation --- .../edit-item-page/item-status/item-status.component.ts | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/app/+item-page/edit-item-page/item-status/item-status.component.ts b/src/app/+item-page/edit-item-page/item-status/item-status.component.ts index e92ae10b55..70f7c737f6 100644 --- a/src/app/+item-page/edit-item-page/item-status/item-status.component.ts +++ b/src/app/+item-page/edit-item-page/item-status/item-status.component.ts @@ -59,8 +59,7 @@ export class ItemStatusComponent implements OnInit { The value is supposed to be a href for the button */ this.operations = [ - new ItemOperation('mappedCollections',this.getCurrentUrl() + '/'), - new ItemOperation('move', this.getCurrentUrl() + '/move'), + new ItemOperation('move', this.getCurrentUrl() + '/move') ] } From 395a78c360aa927b515ebf61d2f80083340cac4e Mon Sep 17 00:00:00 2001 From: Yana De Pauw Date: Tue, 28 May 2019 13:14:59 +0200 Subject: [PATCH 14/21] 62571: Update item move method --- .../item-move/item-move.component.ts | 5 ++++- src/app/core/data/item-data.service.ts | 22 ++++++++++++------- 2 files changed, 18 insertions(+), 9 deletions(-) diff --git a/src/app/+item-page/edit-item-page/item-move/item-move.component.ts b/src/app/+item-page/edit-item-page/item-move/item-move.component.ts index 7eb0e4c10e..4f6f9bbe08 100644 --- a/src/app/+item-page/edit-item-page/item-move/item-move.component.ts +++ b/src/app/+item-page/edit-item-page/item-move/item-move.component.ts @@ -17,6 +17,7 @@ import {getItemEditPath} from '../../item-page-routing.module'; import {Observable} from 'rxjs'; import {of as observableOf} from 'rxjs'; import { RestResponse } from '../../../core/cache/response.models'; +import { Collection } from '../../../core/shared/collection.model'; @Component({ selector: 'ds-item-move', @@ -34,6 +35,7 @@ export class ItemMoveComponent implements OnInit { itemRD$: Observable>; collectionSearchResults: Observable = observableOf([]); selectedCollection: string; + selectedCollectionObject: Collection; selectedCollectionId: string; itemId: string; @@ -92,6 +94,7 @@ export class ItemMoveComponent implements OnInit { onClick(data: any): void { this.selectedCollection = data.name; this.selectedCollectionId = data.id; + this.selectedCollectionObject = data; } /** @@ -105,7 +108,7 @@ export class ItemMoveComponent implements OnInit { * Moves the item to a new collection based on the selected collection */ moveCollection() { - this.itemDataService.moveToCollection(this.itemId, this.selectedCollectionId).pipe(first()).subscribe( + this.itemDataService.moveToCollection(this.itemId, this.selectedCollectionObject).pipe(first()).subscribe( (response: RestResponse) => { this.router.navigate([getItemEditPath(this.itemId)]); if (response.isSuccessful) { diff --git a/src/app/core/data/item-data.service.ts b/src/app/core/data/item-data.service.ts index 1e6f3e50de..9d686d98d1 100644 --- a/src/app/core/data/item-data.service.ts +++ b/src/app/core/data/item-data.service.ts @@ -12,15 +12,17 @@ import { URLCombiner } from '../url-combiner/url-combiner'; import { DataService } from './data.service'; import { RequestService } from './request.service'; import { HALEndpointService } from '../shared/hal-endpoint.service'; -import { DeleteByIDRequest, FindAllOptions, PatchRequest, PutRequest, RestRequest } from './request.models'; +import { FindAllOptions, PatchRequest, PutRequest, RestRequest } from './request.models'; import { ObjectCacheService } from '../cache/object-cache.service'; import { NotificationsService } from '../../shared/notifications/notifications.service'; import { DSOChangeAnalyzer } from './dso-change-analyzer.service'; -import { HttpClient } from '@angular/common/http'; +import { HttpClient, HttpHeaders } from '@angular/common/http'; import { NormalizedObjectBuildService } from '../cache/builders/normalized-object-build.service'; import { configureRequest, getRequestFromRequestHref } from '../shared/operators'; import { RequestEntry } from './request.reducer'; import { RestResponse } from '../cache/response.models'; +import { HttpOptions } from '../dspace-rest-v2/dspace-rest-v2.service'; +import { Collection } from '../shared/collection.model'; @Injectable() export class ItemDataService extends DataService { @@ -120,22 +122,26 @@ export class ItemDataService extends DataService { ); } - public getMoveItemEndpoint(itemId: string, collectionId?: string): Observable { + public getMoveItemEndpoint(itemId: string): Observable { return this.halService.getEndpoint(this.linkPath).pipe( map((endpoint: string) => this.getIDHref(endpoint, itemId)), - map((endpoint: string) => `${endpoint}/owningCollection/move/${collectionId ? `/${collectionId}` : ''}`) + map((endpoint: string) => `${endpoint}/owningCollection`) ); } - public moveToCollection(itemId: string, collectionId: string): Observable { - const requestId = this.requestService.generateRequestId(); + public moveToCollection(itemId: string, collection: Collection): Observable { + const options: HttpOptions = Object.create({}); + let headers = new HttpHeaders(); + headers = headers.append('Content-Type', 'text/uri-list'); + options.headers = headers; - const hrefObs = this.getMoveItemEndpoint(itemId, collectionId); + const requestId = this.requestService.generateRequestId(); + const hrefObs = this.getMoveItemEndpoint(itemId); hrefObs.pipe( find((href: string) => hasValue(href)), map((href: string) => { - const request = new PutRequest(requestId, href); + const request = new PutRequest(requestId, href, collection.self, options); this.requestService.configure(request); }) ).subscribe(); From 74bf69f984688a8195e4a5f3b19472e537843763 Mon Sep 17 00:00:00 2001 From: Yana De Pauw Date: Tue, 28 May 2019 15:47:42 +0200 Subject: [PATCH 15/21] 62571: Move item update and test fixes --- .../edit-item-page/edit-item-page.module.ts | 2 + .../item-move/item-move.component.spec.ts | 78 ++++++++++--------- .../item-move/item-move.component.ts | 8 +- 3 files changed, 47 insertions(+), 41 deletions(-) diff --git a/src/app/+item-page/edit-item-page/edit-item-page.module.ts b/src/app/+item-page/edit-item-page/edit-item-page.module.ts index e2f63ac5fc..de672c9ea7 100644 --- a/src/app/+item-page/edit-item-page/edit-item-page.module.ts +++ b/src/app/+item-page/edit-item-page/edit-item-page.module.ts @@ -15,6 +15,7 @@ import { ItemMetadataComponent } from './item-metadata/item-metadata.component'; import { EditInPlaceFieldComponent } from './item-metadata/edit-in-place-field/edit-in-place-field.component'; import { ItemBitstreamsComponent } from './item-bitstreams/item-bitstreams.component'; import { ItemMoveComponent } from './item-move/item-move.component'; +import { EditItemPageRoutingModule } from './edit-item-page.routing.module'; /** * Module that contains all components related to the Edit Item page administrator functionality @@ -23,6 +24,7 @@ import { ItemMoveComponent } from './item-move/item-move.component'; imports: [ CommonModule, SharedModule, + EditItemPageRoutingModule ], declarations: [ EditItemPageComponent, diff --git a/src/app/+item-page/edit-item-page/item-move/item-move.component.spec.ts b/src/app/+item-page/edit-item-page/item-move/item-move.component.spec.ts index 8f95441bad..3d947fdabe 100644 --- a/src/app/+item-page/edit-item-page/item-move/item-move.component.spec.ts +++ b/src/app/+item-page/edit-item-page/item-move/item-move.component.spec.ts @@ -1,22 +1,23 @@ -import {async, ComponentFixture, TestBed} from '@angular/core/testing'; -import {Item} from '../../../core/shared/item.model'; -import {RouterStub} from '../../../shared/testing/router-stub'; -import {CommonModule} from '@angular/common'; -import {RouterTestingModule} from '@angular/router/testing'; -import {TranslateModule} from '@ngx-translate/core'; -import {NgbModule} from '@ng-bootstrap/ng-bootstrap'; -import {ActivatedRoute, Router} from '@angular/router'; -import {ItemMoveComponent} from './item-move.component'; -import {NotificationsServiceStub} from '../../../shared/testing/notifications-service-stub'; -import {NotificationsService} from '../../../shared/notifications/notifications.service'; -import {SearchService} from '../../../+search-page/search-service/search.service'; -import {of as observableOf} from 'rxjs'; -import {FormsModule} from '@angular/forms'; -import {ItemDataService} from '../../../core/data/item-data.service'; -import {RemoteData} from '../../../core/data/remote-data'; -import {PaginatedList} from '../../../core/data/paginated-list'; -import {CUSTOM_ELEMENTS_SCHEMA} from '@angular/core'; +import { async, ComponentFixture, TestBed } from '@angular/core/testing'; +import { Item } from '../../../core/shared/item.model'; +import { RouterStub } from '../../../shared/testing/router-stub'; +import { CommonModule } from '@angular/common'; +import { RouterTestingModule } from '@angular/router/testing'; +import { TranslateModule } from '@ngx-translate/core'; +import { NgbModule } from '@ng-bootstrap/ng-bootstrap'; +import { ActivatedRoute, Router } from '@angular/router'; +import { ItemMoveComponent } from './item-move.component'; +import { NotificationsServiceStub } from '../../../shared/testing/notifications-service-stub'; +import { NotificationsService } from '../../../shared/notifications/notifications.service'; +import { SearchService } from '../../../+search-page/search-service/search.service'; +import { of as observableOf } from 'rxjs'; +import { FormsModule } from '@angular/forms'; +import { ItemDataService } from '../../../core/data/item-data.service'; +import { RemoteData } from '../../../core/data/remote-data'; +import { PaginatedList } from '../../../core/data/paginated-list'; +import { CUSTOM_ELEMENTS_SCHEMA } from '@angular/core'; import { RestResponse } from '../../../core/cache/response.models'; +import { Collection } from '../../../core/shared/collection.model'; describe('ItemMoveComponent', () => { let comp: ItemMoveComponent; @@ -49,20 +50,28 @@ describe('ItemMoveComponent', () => { }) }; + const collection1 = Object.assign(new Collection(),{ + uuid: 'collection-uuid-1', + name: 'Test collection 1', + self: 'self-link-1', + }); + + const collection2 = Object.assign(new Collection(),{ + uuid: 'collection-uuid-2', + name: 'Test collection 2', + self: 'self-link-2', + }); + const mockSearchService = { search: () => { return observableOf(new RemoteData(false, false, true, null, new PaginatedList(null, [ { - dspaceObject: { - name: 'Test collection 1', - uuid: 'collection1' - }, hitHighlights: {} + indexableObject: collection1, + hitHighlights: {} }, { - dspaceObject: { - name: 'Test collection 2', - uuid: 'collection2' - }, hitHighlights: {} + indexableObject: collection2, + hitHighlights: {} } ]))); } @@ -98,14 +107,14 @@ describe('ItemMoveComponent', () => { displayValue: 'Test collection 1', value: { name: 'Test collection 1', - id: 'collection1', + object: collection1, } }, { displayValue: 'Test collection 2', value: { name: 'Test collection 2', - id: 'collection2', + object: collection2, } } ]; @@ -121,24 +130,23 @@ describe('ItemMoveComponent', () => { it('should on click select the correct collection name and id', () => { const data = { name: 'Test collection 1', - id: 'collection1', + object: collection1, }; comp.onClick(data); expect(comp.selectedCollection).toEqual('Test collection 1'); - expect(comp.selectedCollectionId).toEqual('collection1'); + expect(comp.selectedCollectionObject).toEqual(collection1); }); describe('moveCollection', () => { it('should call itemDataService.moveToCollection', () => { comp.itemId = 'item-id'; - comp.selectedCollectionId = 'selected-collection-id'; + comp.selectedCollection = 'selected-collection-id'; + comp.selectedCollectionObject = collection1; comp.moveCollection(); - expect(mockItemDataService.moveToCollection).toHaveBeenCalledWith('item-id', 'selected-collection-id'); + expect(mockItemDataService.moveToCollection).toHaveBeenCalledWith('item-id', collection1); }); it('should call notificationsService success message on success', () => { - // spyOn(notificationsServiceStub, 'success'); - comp.moveCollection(); expect(notificationsServiceStub.success).toHaveBeenCalled(); @@ -170,8 +178,6 @@ describe('ItemMoveComponent', () => { }); it('should call notificationsService error message on fail', () => { - // spyOn(notificationsServiceStub, 'error'); - comp.moveCollection(); expect(notificationsServiceStub.error).toHaveBeenCalled(); diff --git a/src/app/+item-page/edit-item-page/item-move/item-move.component.ts b/src/app/+item-page/edit-item-page/item-move/item-move.component.ts index 4f6f9bbe08..4cca0cd3a4 100644 --- a/src/app/+item-page/edit-item-page/item-move/item-move.component.ts +++ b/src/app/+item-page/edit-item-page/item-move/item-move.component.ts @@ -37,7 +37,6 @@ export class ItemMoveComponent implements OnInit { selectedCollection: string; selectedCollectionObject: Collection; - selectedCollectionId: string; itemId: string; constructor(private route: ActivatedRoute, @@ -78,8 +77,8 @@ export class ItemMoveComponent implements OnInit { map((rd: RemoteData>>) => { return rd.payload.page.map((searchResult) => { return { - displayValue: searchResult.dspaceObject.name, - value: {name: searchResult.dspaceObject.name, id: searchResult.dspaceObject.uuid} + displayValue: searchResult.indexableObject.name, + value: {name: searchResult.indexableObject.name, object: searchResult.indexableObject} }; }); }) @@ -93,8 +92,7 @@ export class ItemMoveComponent implements OnInit { */ onClick(data: any): void { this.selectedCollection = data.name; - this.selectedCollectionId = data.id; - this.selectedCollectionObject = data; + this.selectedCollectionObject = data.object; } /** From a419e64cef6f1e72448ef8d6130acd7466865f42 Mon Sep 17 00:00:00 2001 From: Philip Vissenaekens Date: Tue, 28 May 2019 17:13:18 +0200 Subject: [PATCH 16/21] 62571: removed duplicate line --- .../item-operation/item-operation.component.spec.ts | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/app/+item-page/edit-item-page/item-operation/item-operation.component.spec.ts b/src/app/+item-page/edit-item-page/item-operation/item-operation.component.spec.ts index 9b0c516083..1901bf5fb4 100644 --- a/src/app/+item-page/edit-item-page/item-operation/item-operation.component.spec.ts +++ b/src/app/+item-page/edit-item-page/item-operation/item-operation.component.spec.ts @@ -20,8 +20,6 @@ describe('ItemOperationComponent', () => { beforeEach(() => { itemOperation = new ItemOperation('key1', 'url1'); - itemOperation = new ItemOperation('key1', 'url1'); - fixture = TestBed.createComponent(ItemOperationComponent); comp = fixture.componentInstance; comp.operation = itemOperation; From 5c101d116a8db8ac40da236723744deb1e229508 Mon Sep 17 00:00:00 2001 From: Yana De Pauw Date: Thu, 8 Aug 2019 15:43:29 +0200 Subject: [PATCH 17/21] 63838: Refactor input suggestions to support DSpaceObjects as suggestions --- .../edit-item-page/edit-item-page.module.ts | 2 +- .../edit-item-page.routing.module.ts | 1 + .../edit-in-place-field.component.html | 4 +- .../edit-in-place-field.component.spec.ts | 2 +- .../edit-in-place-field.component.ts | 2 +- .../search-authority-filter.component.html | 4 +- .../search-facet-filter.component.ts | 2 +- .../search-hierarchy-filter.component.html | 4 +- .../search-text-filter.component.html | 4 +- .../dso-input-suggestions.component.html | 23 ++++++ .../dso-input-suggestions.component.spec.ts | 71 +++++++++++++++++++ .../dso-input-suggestions.component.ts | 47 ++++++++++++ .../filter-input-suggestions.component.html | 22 ++++++ ...filter-input-suggestions.component.spec.ts | 57 +++++++++++++++ .../filter-input-suggestions.component.ts | 44 ++++++++++++ .../input-suggestions.component.ts | 31 ++------ src/app/shared/shared.module.ts | 6 +- 17 files changed, 289 insertions(+), 37 deletions(-) create mode 100644 src/app/shared/input-suggestions/dso-input-suggestions/dso-input-suggestions.component.html create mode 100644 src/app/shared/input-suggestions/dso-input-suggestions/dso-input-suggestions.component.spec.ts create mode 100644 src/app/shared/input-suggestions/dso-input-suggestions/dso-input-suggestions.component.ts create mode 100644 src/app/shared/input-suggestions/filter-suggestions/filter-input-suggestions.component.html create mode 100644 src/app/shared/input-suggestions/filter-suggestions/filter-input-suggestions.component.spec.ts create mode 100644 src/app/shared/input-suggestions/filter-suggestions/filter-input-suggestions.component.ts diff --git a/src/app/+item-page/edit-item-page/edit-item-page.module.ts b/src/app/+item-page/edit-item-page/edit-item-page.module.ts index de672c9ea7..a82c1976c8 100644 --- a/src/app/+item-page/edit-item-page/edit-item-page.module.ts +++ b/src/app/+item-page/edit-item-page/edit-item-page.module.ts @@ -40,7 +40,7 @@ import { EditItemPageRoutingModule } from './edit-item-page.routing.module'; ItemMetadataComponent, ItemBitstreamsComponent, EditInPlaceFieldComponent, - ItemMoveComponent + ItemMoveComponent, ] }) export class EditItemPageModule { diff --git a/src/app/+item-page/edit-item-page/edit-item-page.routing.module.ts b/src/app/+item-page/edit-item-page/edit-item-page.routing.module.ts index c82025cf34..781b5ea933 100644 --- a/src/app/+item-page/edit-item-page/edit-item-page.routing.module.ts +++ b/src/app/+item-page/edit-item-page/edit-item-page.routing.module.ts @@ -111,6 +111,7 @@ export function getItemEditMovePath(id: string) { { path: ITEM_EDIT_MOVE_PATH, component: ItemMoveComponent, + data: {title: 'item.edit.move.title'}, resolve: { item: ItemPageResolver } diff --git a/src/app/+item-page/edit-item-page/item-metadata/edit-in-place-field/edit-in-place-field.component.html b/src/app/+item-page/edit-item-page/item-metadata/edit-in-place-field/edit-in-place-field.component.html index e9c5de95ca..e8ffc28920 100644 --- a/src/app/+item-page/edit-item-page/item-metadata/edit-in-place-field/edit-in-place-field.component.html +++ b/src/app/+item-page/edit-item-page/item-metadata/edit-in-place-field/edit-in-place-field.component.html @@ -4,7 +4,7 @@ {{metadata?.key?.split('.').join('.​')}}
- + >
{{"item.edit.metadata.metadatafield.invalid" | translate}} diff --git a/src/app/+item-page/edit-item-page/item-metadata/edit-in-place-field/edit-in-place-field.component.spec.ts b/src/app/+item-page/edit-item-page/item-metadata/edit-in-place-field/edit-in-place-field.component.spec.ts index 09363b9964..7182f90108 100644 --- a/src/app/+item-page/edit-item-page/item-metadata/edit-in-place-field/edit-in-place-field.component.spec.ts +++ b/src/app/+item-page/edit-item-page/item-metadata/edit-in-place-field/edit-in-place-field.component.spec.ts @@ -11,12 +11,12 @@ import { By } from '@angular/platform-browser'; import { FormsModule } from '@angular/forms'; import { SharedModule } from '../../../../shared/shared.module'; import { getTestScheduler } from 'jasmine-marbles'; -import { InputSuggestion } from '../../../../shared/input-suggestions/input-suggestions.model'; import { TestScheduler } from 'rxjs/testing'; import { MetadataSchema } from '../../../../core/metadata/metadataschema.model'; import { FieldChangeType } from '../../../../core/data/object-updates/object-updates.actions'; import { TranslateModule } from '@ngx-translate/core'; import { MetadatumViewModel } from '../../../../core/shared/metadata.models'; +import { InputSuggestion } from '../../../../shared/input-suggestions/input-suggestions.model'; let comp: EditInPlaceFieldComponent; let fixture: ComponentFixture; diff --git a/src/app/+item-page/edit-item-page/item-metadata/edit-in-place-field/edit-in-place-field.component.ts b/src/app/+item-page/edit-item-page/item-metadata/edit-in-place-field/edit-in-place-field.component.ts index 0b9bc62c55..facfd25008 100644 --- a/src/app/+item-page/edit-item-page/item-metadata/edit-in-place-field/edit-in-place-field.component.ts +++ b/src/app/+item-page/edit-item-page/item-metadata/edit-in-place-field/edit-in-place-field.component.ts @@ -5,12 +5,12 @@ import { cloneDeep } from 'lodash'; import { BehaviorSubject, Observable, of as observableOf } from 'rxjs'; import { map, take } from 'rxjs/operators'; import { MetadataField } from '../../../../core/metadata/metadatafield.model'; -import { InputSuggestion } from '../../../../shared/input-suggestions/input-suggestions.model'; import { FieldChangeType } from '../../../../core/data/object-updates/object-updates.actions'; import { FieldUpdate } from '../../../../core/data/object-updates/object-updates.reducer'; import { ObjectUpdatesService } from '../../../../core/data/object-updates/object-updates.service'; import { NgModel } from '@angular/forms'; import { MetadatumViewModel } from '../../../../core/shared/metadata.models'; +import { InputSuggestion } from '../../../../shared/input-suggestions/input-suggestions.model'; @Component({ // tslint:disable-next-line:component-selector diff --git a/src/app/+search-page/search-filters/search-filter/search-authority-filter/search-authority-filter.component.html b/src/app/+search-page/search-filters/search-filter/search-authority-filter/search-authority-filter.component.html index 76cdc6c8f5..f2b2aad7aa 100644 --- a/src/app/+search-page/search-filters/search-filter/search-authority-filter/search-authority-filter.component.html +++ b/src/app/+search-page/search-filters/search-filter/search-authority-filter/search-authority-filter.component.html @@ -15,7 +15,7 @@ | translate}}
- + ngDefaultControl>
diff --git a/src/app/+search-page/search-filters/search-filter/search-facet-filter/search-facet-filter.component.ts b/src/app/+search-page/search-filters/search-filter/search-facet-filter/search-facet-filter.component.ts index 772240eb0b..6402d07f9b 100644 --- a/src/app/+search-page/search-filters/search-filter/search-facet-filter/search-facet-filter.component.ts +++ b/src/app/+search-page/search-filters/search-filter/search-facet-filter/search-facet-filter.component.ts @@ -21,9 +21,9 @@ import { SearchService } from '../../../search-service/search.service'; import { FILTER_CONFIG, IN_PLACE_SEARCH, SearchFilterService } from '../search-filter.service'; import { SearchConfigurationService } from '../../../search-service/search-configuration.service'; import { getSucceededRemoteData } from '../../../../core/shared/operators'; -import { InputSuggestion } from '../../../../shared/input-suggestions/input-suggestions.model'; import { SearchOptions } from '../../../search-options.model'; import { SEARCH_CONFIG_SERVICE } from '../../../../+my-dspace-page/my-dspace-page.component'; +import { InputSuggestion } from '../../../../shared/input-suggestions/input-suggestions.model'; @Component({ selector: 'ds-search-facet-filter', diff --git a/src/app/+search-page/search-filters/search-filter/search-hierarchy-filter/search-hierarchy-filter.component.html b/src/app/+search-page/search-filters/search-filter/search-hierarchy-filter/search-hierarchy-filter.component.html index ac2a72f4b6..027f162a0a 100644 --- a/src/app/+search-page/search-filters/search-filter/search-hierarchy-filter/search-hierarchy-filter.component.html +++ b/src/app/+search-page/search-filters/search-filter/search-hierarchy-filter/search-hierarchy-filter.component.html @@ -15,7 +15,7 @@ | translate}}
- + >
diff --git a/src/app/+search-page/search-filters/search-filter/search-text-filter/search-text-filter.component.html b/src/app/+search-page/search-filters/search-filter/search-text-filter/search-text-filter.component.html index a4f4fb5ee8..5241c6c0bd 100644 --- a/src/app/+search-page/search-filters/search-filter/search-text-filter/search-text-filter.component.html +++ b/src/app/+search-page/search-filters/search-filter/search-text-filter/search-text-filter.component.html @@ -15,7 +15,7 @@ | translate}}
- + ngDefaultControl> diff --git a/src/app/shared/input-suggestions/dso-input-suggestions/dso-input-suggestions.component.html b/src/app/shared/input-suggestions/dso-input-suggestions/dso-input-suggestions.component.html new file mode 100644 index 0000000000..016ff8c06c --- /dev/null +++ b/src/app/shared/input-suggestions/dso-input-suggestions/dso-input-suggestions.component.html @@ -0,0 +1,23 @@ +
+ + + +
+ diff --git a/src/app/shared/input-suggestions/dso-input-suggestions/dso-input-suggestions.component.spec.ts b/src/app/shared/input-suggestions/dso-input-suggestions/dso-input-suggestions.component.spec.ts new file mode 100644 index 0000000000..2e343a6834 --- /dev/null +++ b/src/app/shared/input-suggestions/dso-input-suggestions/dso-input-suggestions.component.spec.ts @@ -0,0 +1,71 @@ +import { ChangeDetectionStrategy, DebugElement, NO_ERRORS_SCHEMA } from '@angular/core'; + +import { TranslateModule } from '@ngx-translate/core'; +import { By } from '@angular/platform-browser'; +import { async, ComponentFixture, TestBed } from '@angular/core/testing'; +import { FormsModule } from '@angular/forms'; +import { NoopAnimationsModule } from '@angular/platform-browser/animations'; +import { RouterTestingModule } from '@angular/router/testing'; +import { DsoInputSuggestionsComponent } from './dso-input-suggestions.component'; +import { DSpaceObject } from '../../../core/shared/dspace-object.model'; + +describe('DsoInputSuggestionsComponent', () => { + + let comp: DsoInputSuggestionsComponent; + let fixture: ComponentFixture; + let de: DebugElement; + let el: HTMLElement; + + const dso1 = { + uuid: 'test-uuid-1', + name: 'test-name-1' + } as DSpaceObject; + + const dso2 = { + uuid: 'test-uuid-2', + name: 'test-name-2' + } as DSpaceObject; + + const dso3 = { + uuid: 'test-uuid-3', + name: 'test-name-3' + } as DSpaceObject; + + const suggestions = [dso1, dso2, dso3]; + + beforeEach(async(() => { + TestBed.configureTestingModule({ + imports: [TranslateModule.forRoot(), RouterTestingModule.withRoutes([]), NoopAnimationsModule, FormsModule], + declarations: [DsoInputSuggestionsComponent], + providers: [], + schemas: [NO_ERRORS_SCHEMA] + }).overrideComponent(DsoInputSuggestionsComponent, { + set: {changeDetection: ChangeDetectionStrategy.Default} + }).compileComponents(); + })); + + beforeEach(() => { + fixture = TestBed.createComponent(DsoInputSuggestionsComponent); + + comp = fixture.componentInstance; // LoadingComponent test instance + comp.suggestions = suggestions; + // query for the message