From bc305e2aa6aec5b822007484431cce9313ca2f1d Mon Sep 17 00:00:00 2001 From: lotte Date: Wed, 20 Feb 2019 16:21:03 +0100 Subject: [PATCH 01/17] 60113: context sensitive popup started from submission branch --- .../admin-sidebar/admin-sidebar.component.ts | 17 ++- src/app/+admin/admin.module.ts | 4 +- .../builders/remote-data-build.service.ts | 21 ++- ...tion-selector-modal-wrapper.component.html | 6 + ...ection-selector-modal-wrapper.component.ts | 10 ++ .../collection-selector.component.html | 26 ++++ .../collection-selector.component.ts | 125 ++++++++++++++++++ src/app/shared/menu/initial-menus-state.ts | 2 +- .../menu/menu-item/models/onclick.model.ts | 11 ++ .../onclick-menu-item.component.html | 1 + .../menu-item/onclick-menu-item.component.ts | 20 +++ src/app/shared/menu/menu.module.ts | 7 +- src/app/shared/shared.module.ts | 8 +- 13 files changed, 246 insertions(+), 12 deletions(-) create mode 100644 src/app/shared/dso-selector/collection-selector-modal-wrapper/collection-selector-modal-wrapper.component.html create mode 100644 src/app/shared/dso-selector/collection-selector-modal-wrapper/collection-selector-modal-wrapper.component.ts create mode 100644 src/app/shared/dso-selector/collection-selector/collection-selector.component.html create mode 100644 src/app/shared/dso-selector/collection-selector/collection-selector.component.ts create mode 100644 src/app/shared/menu/menu-item/models/onclick.model.ts create mode 100644 src/app/shared/menu/menu-item/onclick-menu-item.component.html create mode 100644 src/app/shared/menu/menu-item/onclick-menu-item.component.ts diff --git a/src/app/+admin/admin-sidebar/admin-sidebar.component.ts b/src/app/+admin/admin-sidebar/admin-sidebar.component.ts index eb48f64d4d..f3d417b93d 100644 --- a/src/app/+admin/admin-sidebar/admin-sidebar.component.ts +++ b/src/app/+admin/admin-sidebar/admin-sidebar.component.ts @@ -1,6 +1,6 @@ import { Component, Injector, OnInit } from '@angular/core'; import { Observable } from 'rxjs/internal/Observable'; -import { slide, slideHorizontal, slideSidebar } from '../../shared/animations/slide'; +import { slideHorizontal, slideSidebar } from '../../shared/animations/slide'; import { CSSVariableService } from '../../shared/sass-helper/sass-helper.service'; import { MenuService } from '../../shared/menu/menu.service'; import { MenuID, MenuItemType } from '../../shared/menu/initial-menus-state'; @@ -10,6 +10,9 @@ import { LinkMenuItemModel } from '../../shared/menu/menu-item/models/link.model import { AuthService } from '../../core/auth/auth.service'; import { first, map } from 'rxjs/operators'; import { combineLatest as combineLatestObservable } from 'rxjs'; +import { NgbModal } from '@ng-bootstrap/ng-bootstrap'; +import { OnClickMenuItemModel } from '../../shared/menu/menu-item/models/onclick.model'; +import { CollectionSelectorModalWrapperComponent } from '../../shared/dso-selector/collection-selector-modal-wrapper/collection-selector-modal-wrapper.component'; /** * Component representing the admin sidebar @@ -52,7 +55,8 @@ export class AdminSidebarComponent extends MenuComponent implements OnInit { constructor(protected menuService: MenuService, protected injector: Injector, private variableService: CSSVariableService, - private authService: AuthService + private authService: AuthService, + private modalService: NgbModal ) { super(menuService, injector); } @@ -104,10 +108,13 @@ export class AdminSidebarComponent extends MenuComponent implements OnInit { active: false, visible: true, model: { - type: MenuItemType.LINK, + type: MenuItemType.ONCLICK, text: 'menu.section.new_community', - link: '/communities/submission' - } as LinkMenuItemModel, + function: () => { + const modal = this.modalService.open(CollectionSelectorModalWrapperComponent); + modal.componentInstance.currentCollectionID = 'c069b0c2-dc6a-40de-92c3-6803cd66023e'; + } + } as OnClickMenuItemModel, }, { id: 'new_collection', diff --git a/src/app/+admin/admin.module.ts b/src/app/+admin/admin.module.ts index 41d00223ab..1495d0fd8c 100644 --- a/src/app/+admin/admin.module.ts +++ b/src/app/+admin/admin.module.ts @@ -1,12 +1,14 @@ import { NgModule } from '@angular/core'; import { AdminRegistriesModule } from './admin-registries/admin-registries.module'; import { AdminRoutingModule } from './admin-routing.module'; +import { SharedModule } from '../shared/shared.module'; @NgModule({ imports: [ AdminRegistriesModule, AdminRoutingModule, - ] + SharedModule, + ], }) export class AdminModule { diff --git a/src/app/core/cache/builders/remote-data-build.service.ts b/src/app/core/cache/builders/remote-data-build.service.ts index 7cfbcdd252..697d98fc68 100644 --- a/src/app/core/cache/builders/remote-data-build.service.ts +++ b/src/app/core/cache/builders/remote-data-build.service.ts @@ -5,8 +5,14 @@ import { race as observableRace } from 'rxjs'; import { Injectable } from '@angular/core'; -import { distinctUntilChanged, flatMap, map, startWith, switchMap } from 'rxjs/operators'; -import { hasValue, hasValueOperator, isEmpty, isNotEmpty } from '../../../shared/empty.util'; +import { distinctUntilChanged, flatMap, map, startWith, switchMap, tap } from 'rxjs/operators'; +import { + hasValue, + hasValueOperator, + isEmpty, + isNotEmpty, + isNotUndefined +} from '../../../shared/empty.util'; import { PaginatedList } from '../../data/paginated-list'; import { RemoteData } from '../../data/remote-data'; import { RemoteDataError } from '../../data/remote-data-error'; @@ -113,8 +119,19 @@ export class RemoteDataBuildService { } const requestEntry$ = href$.pipe(getRequestFromRequestHref(this.requestService)); + requestEntry$.subscribe((t) => { + console.log('requestEntry$', t) + }); const tDomainList$ = requestEntry$.pipe( getResourceLinksFromResponse(), + tap((resourceUUIDs: string[]) => { + const g = (href$ as Observable) + + g.subscribe((t) => { + console.log('href', t) + }); + console.log(resourceUUIDs); + }), flatMap((resourceUUIDs: string[]) => { return this.objectCache.getList(resourceUUIDs).pipe( map((normList: Array>) => { diff --git a/src/app/shared/dso-selector/collection-selector-modal-wrapper/collection-selector-modal-wrapper.component.html b/src/app/shared/dso-selector/collection-selector-modal-wrapper/collection-selector-modal-wrapper.component.html new file mode 100644 index 0000000000..7fadd477f4 --- /dev/null +++ b/src/app/shared/dso-selector/collection-selector-modal-wrapper/collection-selector-modal-wrapper.component.html @@ -0,0 +1,6 @@ +
+ + +
\ No newline at end of file diff --git a/src/app/shared/dso-selector/collection-selector-modal-wrapper/collection-selector-modal-wrapper.component.ts b/src/app/shared/dso-selector/collection-selector-modal-wrapper/collection-selector-modal-wrapper.component.ts new file mode 100644 index 0000000000..c60d6f2938 --- /dev/null +++ b/src/app/shared/dso-selector/collection-selector-modal-wrapper/collection-selector-modal-wrapper.component.ts @@ -0,0 +1,10 @@ +import { Component, Input } from '@angular/core'; + +@Component({ + selector: 'ds-collection-selector-modal-wrapper', + // styleUrls: ['./collection-selector.component.scss'], + templateUrl: './collection-selector-modal-wrapper.component.html', +}) +export class CollectionSelectorModalWrapperComponent { + @Input() currentCollectionID: string; +} diff --git a/src/app/shared/dso-selector/collection-selector/collection-selector.component.html b/src/app/shared/dso-selector/collection-selector/collection-selector.component.html new file mode 100644 index 0000000000..e137f5e119 --- /dev/null +++ b/src/app/shared/dso-selector/collection-selector/collection-selector.component.html @@ -0,0 +1,26 @@ +
+ +
+ +
+ + +
\ No newline at end of file diff --git a/src/app/shared/dso-selector/collection-selector/collection-selector.component.ts b/src/app/shared/dso-selector/collection-selector/collection-selector.component.ts new file mode 100644 index 0000000000..6b9625c8a6 --- /dev/null +++ b/src/app/shared/dso-selector/collection-selector/collection-selector.component.ts @@ -0,0 +1,125 @@ +import { Component, Input, OnChanges, SimpleChanges } from '@angular/core'; +import { FormControl } from '@angular/forms'; + +import { BehaviorSubject, combineLatest, Observable, Subscription } from 'rxjs'; +import { + debounceTime, + distinctUntilChanged, + filter, + find, + flatMap, + map, + mergeMap, + reduce, + startWith +} from 'rxjs/operators'; + +import { Collection } from '../../../core/shared/collection.model'; +import { CommunityDataService } from '../../../core/data/community-data.service'; +import { Community } from '../../../core/shared/community.model'; +import { hasValue, isEmpty, isNotEmpty } from '../../../shared/empty.util'; +import { RemoteData } from '../../../core/data/remote-data'; +import { PaginatedList } from '../../../core/data/paginated-list'; +import { getSucceededRemoteData } from '../../../core/shared/operators'; + +interface CollectionListEntryItem { + id: string; + name: string; +} + +interface CollectionListEntry { + communities: CollectionListEntryItem[], + collection: CollectionListEntryItem +} + +@Component({ + selector: 'ds-collection-selector', + // styleUrls: ['./collection-selector.component.scss'], + templateUrl: './collection-selector.component.html' +}) +export class CollectionSelectorComponent implements OnChanges { + @Input() currentCollectionId: string; + + public disabled$ = new BehaviorSubject(true); + public model: any; + public searchField: FormControl = new FormControl(); + public searchListCollection$: Observable; + public selectedCollectionId: string; + public selectedCollectionName$: Observable; + + private subs: Subscription[] = []; + + constructor(private communityDataService: CommunityDataService) { + } + + ngOnChanges(changes: SimpleChanges) { + if (hasValue(changes.currentCollectionId) + && hasValue(changes.currentCollectionId.currentValue)) { + this.selectedCollectionId = this.currentCollectionId; + + // @TODO replace with search/top browse endpoint + // @TODO implement community/subcommunity hierarchy + const communities$ = this.communityDataService.findAll().pipe( + find((communities: RemoteData>) => isNotEmpty(communities.payload)), + mergeMap((communities: RemoteData>) => communities.payload.page)); + communities$.subscribe((t) => {console.log('communities', t)}); + // const listCollection$ = communities$.pipe( + // flatMap((communityData: Community) => { + // return communityData.collections.pipe( + // getSucceededRemoteData(), + // mergeMap((collections: RemoteData>) => collections.payload.page), + // filter((collectionData: Collection) => isNotEmpty(collectionData)), + // map((collectionData: Collection) => ({ + // communities: [{ id: communityData.id, name: communityData.name }], + // collection: { id: collectionData.id, name: collectionData.name } + // })) + // ); + // }), + // reduce((acc: any, value: any) => [...acc, ...value], []), + // startWith([]) + // ); + // + // this.selectedCollectionName$ = communities$.pipe( + // flatMap((communityData: Community) => { + // return communityData.collections.pipe( + // getSucceededRemoteData(), + // mergeMap((collections: RemoteData>) => collections.payload.page), + // filter((collectionData: Collection) => isNotEmpty(collectionData)), + // filter((collectionData: Collection) => collectionData.id === this.selectedCollectionId), + // map((collectionData: Collection) => collectionData.name) + // ); + // }), + // startWith('') + // ); + // + // const searchTerm$ = this.searchField.valueChanges.pipe( + // debounceTime(200), + // distinctUntilChanged(), + // startWith('') + // ); + // + // this.searchListCollection$ = combineLatest(searchTerm$, listCollection$).pipe( + // map(([searchTerm, listCollection]) => { + // this.disabled$.next(isEmpty(listCollection)); + // if (isEmpty(searchTerm)) { + // return listCollection; + // } else { + // return listCollection.filter((v) => v.collection.name.toLowerCase().indexOf(searchTerm.toLowerCase()) > -1).slice(0, 5) + // } + // })); + } + } + + ngOnDestroy(): void { + this.subs.filter((sub) => hasValue(sub)).forEach((sub) => sub.unsubscribe()); + } + + onSelect(event) { + this.searchField.reset(); + this.disabled$.next(true); + } + + onClose() { + this.searchField.reset(); + } +} diff --git a/src/app/shared/menu/initial-menus-state.ts b/src/app/shared/menu/initial-menus-state.ts index 7f3482f41f..7b900540b6 100644 --- a/src/app/shared/menu/initial-menus-state.ts +++ b/src/app/shared/menu/initial-menus-state.ts @@ -12,7 +12,7 @@ export enum MenuID { * List of possible MenuItemTypes */ export enum MenuItemType { - TEXT, LINK, ALTMETRIC, SEARCH + TEXT, LINK, ALTMETRIC, SEARCH, ONCLICK } /** diff --git a/src/app/shared/menu/menu-item/models/onclick.model.ts b/src/app/shared/menu/menu-item/models/onclick.model.ts new file mode 100644 index 0000000000..4cef3084f9 --- /dev/null +++ b/src/app/shared/menu/menu-item/models/onclick.model.ts @@ -0,0 +1,11 @@ +import { MenuItemModel } from './menu-item.model'; +import { MenuItemType } from '../../initial-menus-state'; + +/** + * Model representing an OnClick Menu Section + */ +export class OnClickMenuItemModel implements MenuItemModel { + type = MenuItemType.ONCLICK; + text: string; + function: () => {}; +} diff --git a/src/app/shared/menu/menu-item/onclick-menu-item.component.html b/src/app/shared/menu/menu-item/onclick-menu-item.component.html new file mode 100644 index 0000000000..0790ef7479 --- /dev/null +++ b/src/app/shared/menu/menu-item/onclick-menu-item.component.html @@ -0,0 +1 @@ +{{item.text | translate}} \ No newline at end of file diff --git a/src/app/shared/menu/menu-item/onclick-menu-item.component.ts b/src/app/shared/menu/menu-item/onclick-menu-item.component.ts new file mode 100644 index 0000000000..14fd5d8ffd --- /dev/null +++ b/src/app/shared/menu/menu-item/onclick-menu-item.component.ts @@ -0,0 +1,20 @@ +import { Component, Inject } from '@angular/core'; +import { MenuItemType } from '../initial-menus-state'; +import { rendersMenuItemForType } from '../menu-item.decorator'; +import { GLOBAL_CONFIG, GlobalConfig } from '../../../../config'; +import { OnClickMenuItemModel } from './models/onclick.model'; + +/** + * Component that renders a menu section of type LINK + */ +@Component({ + selector: 'ds-onclick-menu-item', + templateUrl: './onclick-menu-item.component.html' +}) +@rendersMenuItemForType(MenuItemType.ONCLICK) +export class OnClickMenuItemComponent { + item: OnClickMenuItemModel; + constructor(@Inject('itemModelProvider') item: OnClickMenuItemModel, @Inject(GLOBAL_CONFIG) private EnvConfig: GlobalConfig) { + this.item = item; + } +} diff --git a/src/app/shared/menu/menu.module.ts b/src/app/shared/menu/menu.module.ts index 736da5c267..7e900d18e6 100644 --- a/src/app/shared/menu/menu.module.ts +++ b/src/app/shared/menu/menu.module.ts @@ -5,17 +5,20 @@ import { TranslateModule } from '@ngx-translate/core'; import { RouterModule } from '@angular/router'; import { LinkMenuItemComponent } from './menu-item/link-menu-item.component'; import { TextMenuItemComponent } from './menu-item/text-menu-item.component'; +import { OnClickMenuItemComponent } from './menu-item/onclick-menu-item.component'; const COMPONENTS = [ MenuSectionComponent, MenuComponent, LinkMenuItemComponent, - TextMenuItemComponent + TextMenuItemComponent, + OnClickMenuItemComponent ]; const ENTRY_COMPONENTS = [ LinkMenuItemComponent, - TextMenuItemComponent + TextMenuItemComponent, + OnClickMenuItemComponent ]; const MODULES = [ diff --git a/src/app/shared/shared.module.ts b/src/app/shared/shared.module.ts index 5ae3e517e3..da45faee9f 100644 --- a/src/app/shared/shared.module.ts +++ b/src/app/shared/shared.module.ts @@ -91,6 +91,8 @@ import { CreateComColPageComponent } from './comcol-forms/create-comcol-page/cre import { EditComColPageComponent } from './comcol-forms/edit-comcol-page/edit-comcol-page.component'; import { DeleteComColPageComponent } from './comcol-forms/delete-comcol-page/delete-comcol-page.component'; import { LangSwitchComponent } from './lang-switch/lang-switch.component'; +import { CollectionSelectorComponent } from './dso-selector/collection-selector/collection-selector.component'; +import { CollectionSelectorModalWrapperComponent } from './dso-selector/collection-selector-modal-wrapper/collection-selector-modal-wrapper.component'; import { ObjectValuesPipe } from './utils/object-values-pipe'; import { InListValidator } from './utils/in-list-validator.directive'; import { AutoFocusDirective } from './utils/auto-focus.directive'; @@ -177,6 +179,8 @@ const COMPONENTS = [ TruncatablePartComponent, BrowseByComponent, InputSuggestionsComponent, + CollectionSelectorComponent, + CollectionSelectorModalWrapperComponent ]; const ENTRY_COMPONENTS = [ @@ -189,7 +193,9 @@ const ENTRY_COMPONENTS = [ CollectionGridElementComponent, CommunityGridElementComponent, SearchResultGridElementComponent, - BrowseEntryListElementComponent + BrowseEntryListElementComponent, + CollectionSelectorComponent, + CollectionSelectorModalWrapperComponent ]; const PROVIDERS = [ From 61a5620efe761ec79027f7ee625a820c301553f0 Mon Sep 17 00:00:00 2001 From: lotte Date: Fri, 1 Mar 2019 16:41:38 +0100 Subject: [PATCH 02/17] refactored lookup --- config/environment.default.js | 5 +- .../admin-sidebar/admin-sidebar.component.ts | 21 +-- .../collection-page.module.ts | 1 - src/app/+search-page/search-page.module.ts | 1 - .../builders/remote-data-build.service.ts | 11 -- src/app/core/core.module.ts | 2 + src/app/core/data/request.models.ts | 9 +- ...tion-selector-modal-wrapper.component.html | 4 +- ...ection-selector-modal-wrapper.component.ts | 16 ++- .../collection-selector.component.html | 26 ---- .../collection-selector.component.ts | 125 ------------------ ...nity-selector-modal-wrapper.component.html | 7 + ...munity-selector-modal-wrapper.component.ts | 20 +++ .../dso-selector/dso-selector.component.html | 27 ++++ .../dso-selector/dso-selector.component.ts | 94 +++++++++++++ ...item-selector-modal-wrapper.component.html | 6 + .../item-selector-modal-wrapper.component.ts | 21 +++ src/app/shared/shared.module.ts | 16 ++- 18 files changed, 223 insertions(+), 189 deletions(-) delete mode 100644 src/app/shared/dso-selector/collection-selector/collection-selector.component.html delete mode 100644 src/app/shared/dso-selector/collection-selector/collection-selector.component.ts create mode 100644 src/app/shared/dso-selector/community-selector-modal-wrapper/community-selector-modal-wrapper.component.html create mode 100644 src/app/shared/dso-selector/community-selector-modal-wrapper/community-selector-modal-wrapper.component.ts create mode 100644 src/app/shared/dso-selector/dso-selector/dso-selector.component.html create mode 100644 src/app/shared/dso-selector/dso-selector/dso-selector.component.ts create mode 100644 src/app/shared/dso-selector/item-selector-modal-wrapper/item-selector-modal-wrapper.component.html create mode 100644 src/app/shared/dso-selector/item-selector-modal-wrapper/item-selector-modal-wrapper.component.ts diff --git a/config/environment.default.js b/config/environment.default.js index b8eae1ccff..b493d0473a 100644 --- a/config/environment.default.js +++ b/config/environment.default.js @@ -10,10 +10,9 @@ module.exports = { // The REST API server settings. rest: { ssl: true, - host: 'dspace7.4science.it', + host: 'dspace7-internal.atmire.com', port: 443, - // NOTE: Space is capitalized because 'namespace' is a reserved string in TypeScript - nameSpace: '/dspace-spring-rest/api' + nameSpace: '/rest/api' }, // Caching settings cache: { diff --git a/src/app/+admin/admin-sidebar/admin-sidebar.component.ts b/src/app/+admin/admin-sidebar/admin-sidebar.component.ts index f3d417b93d..22cb1f5825 100644 --- a/src/app/+admin/admin-sidebar/admin-sidebar.component.ts +++ b/src/app/+admin/admin-sidebar/admin-sidebar.component.ts @@ -13,6 +13,8 @@ import { combineLatest as combineLatestObservable } from 'rxjs'; import { NgbModal } from '@ng-bootstrap/ng-bootstrap'; import { OnClickMenuItemModel } from '../../shared/menu/menu-item/models/onclick.model'; import { CollectionSelectorModalWrapperComponent } from '../../shared/dso-selector/collection-selector-modal-wrapper/collection-selector-modal-wrapper.component'; +import { ItemSelectorModalWrapperComponent } from '../../shared/dso-selector/item-selector-modal-wrapper/item-selector-modal-wrapper.component'; +import { CommunitySelectorModalWrapperComponent } from '../../shared/dso-selector/community-selector-modal-wrapper/community-selector-modal-wrapper.component'; /** * Component representing the admin sidebar @@ -111,8 +113,7 @@ export class AdminSidebarComponent extends MenuComponent implements OnInit { type: MenuItemType.ONCLICK, text: 'menu.section.new_community', function: () => { - const modal = this.modalService.open(CollectionSelectorModalWrapperComponent); - modal.componentInstance.currentCollectionID = 'c069b0c2-dc6a-40de-92c3-6803cd66023e'; + this.modalService.open(CommunitySelectorModalWrapperComponent); } } as OnClickMenuItemModel, }, @@ -122,10 +123,12 @@ export class AdminSidebarComponent extends MenuComponent implements OnInit { active: false, visible: true, model: { - type: MenuItemType.LINK, + type: MenuItemType.ONCLICK, text: 'menu.section.new_collection', - link: '/collections/submission' - } as LinkMenuItemModel, + function: () => { + this.modalService.open(CollectionSelectorModalWrapperComponent); + } + } as OnClickMenuItemModel, }, { id: 'new_item', @@ -133,10 +136,12 @@ export class AdminSidebarComponent extends MenuComponent implements OnInit { active: false, visible: true, model: { - type: MenuItemType.LINK, + type: MenuItemType.ONCLICK, text: 'menu.section.new_item', - link: '/items/submission' - } as LinkMenuItemModel, + function: () => { + this.modalService.open(ItemSelectorModalWrapperComponent); + } + } as OnClickMenuItemModel, }, { id: 'new_item_version', diff --git a/src/app/+collection-page/collection-page.module.ts b/src/app/+collection-page/collection-page.module.ts index 8424cc02a4..f0e4138d2d 100644 --- a/src/app/+collection-page/collection-page.module.ts +++ b/src/app/+collection-page/collection-page.module.ts @@ -15,7 +15,6 @@ import { DeleteCollectionPageComponent } from './delete-collection-page/delete-c imports: [ CommonModule, SharedModule, - SearchPageModule, CollectionPageRoutingModule ], declarations: [ diff --git a/src/app/+search-page/search-page.module.ts b/src/app/+search-page/search-page.module.ts index 0c8a4ee306..5fa1fadfae 100644 --- a/src/app/+search-page/search-page.module.ts +++ b/src/app/+search-page/search-page.module.ts @@ -65,7 +65,6 @@ const effects = [ SearchBooleanFilterComponent, ], providers: [ - SearchService, SearchSidebarService, SearchFilterService, SearchConfigurationService diff --git a/src/app/core/cache/builders/remote-data-build.service.ts b/src/app/core/cache/builders/remote-data-build.service.ts index 697d98fc68..a59039c226 100644 --- a/src/app/core/cache/builders/remote-data-build.service.ts +++ b/src/app/core/cache/builders/remote-data-build.service.ts @@ -119,19 +119,8 @@ export class RemoteDataBuildService { } const requestEntry$ = href$.pipe(getRequestFromRequestHref(this.requestService)); - requestEntry$.subscribe((t) => { - console.log('requestEntry$', t) - }); const tDomainList$ = requestEntry$.pipe( getResourceLinksFromResponse(), - tap((resourceUUIDs: string[]) => { - const g = (href$ as Observable) - - g.subscribe((t) => { - console.log('href', t) - }); - console.log(resourceUUIDs); - }), flatMap((resourceUUIDs: string[]) => { return this.objectCache.getList(resourceUUIDs).pipe( map((normList: Array>) => { diff --git a/src/app/core/core.module.ts b/src/app/core/core.module.ts index 357f552074..82a25d6d4f 100644 --- a/src/app/core/core.module.ts +++ b/src/app/core/core.module.ts @@ -69,6 +69,7 @@ import { NormalizedObjectBuildService } from './cache/builders/normalized-object import { DSOChangeAnalyzer } from './data/dso-change-analyzer.service'; import { ObjectUpdatesService } from './data/object-updates/object-updates.service'; import { DefaultChangeAnalyzer } from './data/default-change-analyzer.service'; +import { SearchService } from '../+search-page/search-service/search.service'; const IMPORTS = [ CommonModule, @@ -138,6 +139,7 @@ const PROVIDERS = [ CSSVariableService, MenuService, ObjectUpdatesService, + SearchService, // register AuthInterceptor as HttpInterceptor { provide: HTTP_INTERCEPTORS, diff --git a/src/app/core/data/request.models.ts b/src/app/core/data/request.models.ts index 18820dbd43..951dbacff6 100644 --- a/src/app/core/data/request.models.ts +++ b/src/app/core/data/request.models.ts @@ -14,6 +14,7 @@ import { BrowseItemsResponseParsingService } from './browse-items-response-parsi import { RegistryMetadataschemasResponseParsingService } from './registry-metadataschemas-response-parsing.service'; import { MetadataschemaParsingService } from './metadataschema-parsing.service'; import { MetadatafieldParsingService } from './metadatafield-parsing.service'; +import { URLCombiner } from '../url-combiner/url-combiner'; /* tslint:disable:max-classes-per-file */ @@ -146,11 +147,11 @@ export class FindAllRequest extends GetRequest { export class EndpointMapRequest extends GetRequest { constructor( - public uuid: string, - public href: string, - public body?: any + uuid: string, + href: string, + body?: any ) { - super(uuid, href, body); + super(uuid, new URLCombiner(href, '?endpointMap').toString(), body); } getResponseParser(): GenericConstructor { diff --git a/src/app/shared/dso-selector/collection-selector-modal-wrapper/collection-selector-modal-wrapper.component.html b/src/app/shared/dso-selector/collection-selector-modal-wrapper/collection-selector-modal-wrapper.component.html index 7fadd477f4..f3bf405651 100644 --- a/src/app/shared/dso-selector/collection-selector-modal-wrapper/collection-selector-modal-wrapper.component.html +++ b/src/app/shared/dso-selector/collection-selector-modal-wrapper/collection-selector-modal-wrapper.component.html @@ -1,6 +1,6 @@
- +
\ No newline at end of file diff --git a/src/app/shared/dso-selector/collection-selector-modal-wrapper/collection-selector-modal-wrapper.component.ts b/src/app/shared/dso-selector/collection-selector-modal-wrapper/collection-selector-modal-wrapper.component.ts index c60d6f2938..cda2284835 100644 --- a/src/app/shared/dso-selector/collection-selector-modal-wrapper/collection-selector-modal-wrapper.component.ts +++ b/src/app/shared/dso-selector/collection-selector-modal-wrapper/collection-selector-modal-wrapper.component.ts @@ -1,10 +1,20 @@ -import { Component, Input } from '@angular/core'; +import { Component, Input, OnInit } from '@angular/core'; +import { ActivatedRoute, Router } from '@angular/router'; +import { Community } from '../../../core/shared/community.model'; +import { RemoteData } from '../../../core/data/remote-data'; @Component({ selector: 'ds-collection-selector-modal-wrapper', // styleUrls: ['./collection-selector.component.scss'], templateUrl: './collection-selector-modal-wrapper.component.html', }) -export class CollectionSelectorModalWrapperComponent { - @Input() currentCollectionID: string; +export class CollectionSelectorModalWrapperComponent implements OnInit { + @Input() communityRD: RemoteData; + + constructor(private route: ActivatedRoute) { + } + + ngOnInit(): void { + this.communityRD = this.route.root.firstChild.firstChild.snapshot.data.community; + } } diff --git a/src/app/shared/dso-selector/collection-selector/collection-selector.component.html b/src/app/shared/dso-selector/collection-selector/collection-selector.component.html deleted file mode 100644 index e137f5e119..0000000000 --- a/src/app/shared/dso-selector/collection-selector/collection-selector.component.html +++ /dev/null @@ -1,26 +0,0 @@ -
- -
- -
- - -
\ No newline at end of file diff --git a/src/app/shared/dso-selector/collection-selector/collection-selector.component.ts b/src/app/shared/dso-selector/collection-selector/collection-selector.component.ts deleted file mode 100644 index 6b9625c8a6..0000000000 --- a/src/app/shared/dso-selector/collection-selector/collection-selector.component.ts +++ /dev/null @@ -1,125 +0,0 @@ -import { Component, Input, OnChanges, SimpleChanges } from '@angular/core'; -import { FormControl } from '@angular/forms'; - -import { BehaviorSubject, combineLatest, Observable, Subscription } from 'rxjs'; -import { - debounceTime, - distinctUntilChanged, - filter, - find, - flatMap, - map, - mergeMap, - reduce, - startWith -} from 'rxjs/operators'; - -import { Collection } from '../../../core/shared/collection.model'; -import { CommunityDataService } from '../../../core/data/community-data.service'; -import { Community } from '../../../core/shared/community.model'; -import { hasValue, isEmpty, isNotEmpty } from '../../../shared/empty.util'; -import { RemoteData } from '../../../core/data/remote-data'; -import { PaginatedList } from '../../../core/data/paginated-list'; -import { getSucceededRemoteData } from '../../../core/shared/operators'; - -interface CollectionListEntryItem { - id: string; - name: string; -} - -interface CollectionListEntry { - communities: CollectionListEntryItem[], - collection: CollectionListEntryItem -} - -@Component({ - selector: 'ds-collection-selector', - // styleUrls: ['./collection-selector.component.scss'], - templateUrl: './collection-selector.component.html' -}) -export class CollectionSelectorComponent implements OnChanges { - @Input() currentCollectionId: string; - - public disabled$ = new BehaviorSubject(true); - public model: any; - public searchField: FormControl = new FormControl(); - public searchListCollection$: Observable; - public selectedCollectionId: string; - public selectedCollectionName$: Observable; - - private subs: Subscription[] = []; - - constructor(private communityDataService: CommunityDataService) { - } - - ngOnChanges(changes: SimpleChanges) { - if (hasValue(changes.currentCollectionId) - && hasValue(changes.currentCollectionId.currentValue)) { - this.selectedCollectionId = this.currentCollectionId; - - // @TODO replace with search/top browse endpoint - // @TODO implement community/subcommunity hierarchy - const communities$ = this.communityDataService.findAll().pipe( - find((communities: RemoteData>) => isNotEmpty(communities.payload)), - mergeMap((communities: RemoteData>) => communities.payload.page)); - communities$.subscribe((t) => {console.log('communities', t)}); - // const listCollection$ = communities$.pipe( - // flatMap((communityData: Community) => { - // return communityData.collections.pipe( - // getSucceededRemoteData(), - // mergeMap((collections: RemoteData>) => collections.payload.page), - // filter((collectionData: Collection) => isNotEmpty(collectionData)), - // map((collectionData: Collection) => ({ - // communities: [{ id: communityData.id, name: communityData.name }], - // collection: { id: collectionData.id, name: collectionData.name } - // })) - // ); - // }), - // reduce((acc: any, value: any) => [...acc, ...value], []), - // startWith([]) - // ); - // - // this.selectedCollectionName$ = communities$.pipe( - // flatMap((communityData: Community) => { - // return communityData.collections.pipe( - // getSucceededRemoteData(), - // mergeMap((collections: RemoteData>) => collections.payload.page), - // filter((collectionData: Collection) => isNotEmpty(collectionData)), - // filter((collectionData: Collection) => collectionData.id === this.selectedCollectionId), - // map((collectionData: Collection) => collectionData.name) - // ); - // }), - // startWith('') - // ); - // - // const searchTerm$ = this.searchField.valueChanges.pipe( - // debounceTime(200), - // distinctUntilChanged(), - // startWith('') - // ); - // - // this.searchListCollection$ = combineLatest(searchTerm$, listCollection$).pipe( - // map(([searchTerm, listCollection]) => { - // this.disabled$.next(isEmpty(listCollection)); - // if (isEmpty(searchTerm)) { - // return listCollection; - // } else { - // return listCollection.filter((v) => v.collection.name.toLowerCase().indexOf(searchTerm.toLowerCase()) > -1).slice(0, 5) - // } - // })); - } - } - - ngOnDestroy(): void { - this.subs.filter((sub) => hasValue(sub)).forEach((sub) => sub.unsubscribe()); - } - - onSelect(event) { - this.searchField.reset(); - this.disabled$.next(true); - } - - onClose() { - this.searchField.reset(); - } -} diff --git a/src/app/shared/dso-selector/community-selector-modal-wrapper/community-selector-modal-wrapper.component.html b/src/app/shared/dso-selector/community-selector-modal-wrapper/community-selector-modal-wrapper.component.html new file mode 100644 index 0000000000..91b97a25a3 --- /dev/null +++ b/src/app/shared/dso-selector/community-selector-modal-wrapper/community-selector-modal-wrapper.component.html @@ -0,0 +1,7 @@ +
+ + +
\ No newline at end of file diff --git a/src/app/shared/dso-selector/community-selector-modal-wrapper/community-selector-modal-wrapper.component.ts b/src/app/shared/dso-selector/community-selector-modal-wrapper/community-selector-modal-wrapper.component.ts new file mode 100644 index 0000000000..8ebee7ea7f --- /dev/null +++ b/src/app/shared/dso-selector/community-selector-modal-wrapper/community-selector-modal-wrapper.component.ts @@ -0,0 +1,20 @@ +import { Component, Input, OnInit } from '@angular/core'; +import { ActivatedRoute, Router } from '@angular/router'; +import { Community } from '../../../core/shared/community.model'; +import { RemoteData } from '../../../core/data/remote-data'; + +@Component({ + selector: 'ds-community-selector-modal-wrapper', + // styleUrls: ['./community-selector.component.scss'], + templateUrl: './community-selector-modal-wrapper.component.html', +}) +export class CommunitySelectorModalWrapperComponent implements OnInit { + @Input() communityRD: RemoteData; + + constructor(private route: ActivatedRoute) { + } + + ngOnInit(): void { + this.communityRD = this.route.root.firstChild.firstChild.snapshot.data.community; + } +} diff --git a/src/app/shared/dso-selector/dso-selector/dso-selector.component.html b/src/app/shared/dso-selector/dso-selector/dso-selector.component.html new file mode 100644 index 0000000000..b15eaf9338 --- /dev/null +++ b/src/app/shared/dso-selector/dso-selector/dso-selector.component.html @@ -0,0 +1,27 @@ +
+ +
+ +{{input.value}} + +
+ + +
\ No newline at end of file diff --git a/src/app/shared/dso-selector/dso-selector/dso-selector.component.ts b/src/app/shared/dso-selector/dso-selector/dso-selector.component.ts new file mode 100644 index 0000000000..04a5792c87 --- /dev/null +++ b/src/app/shared/dso-selector/dso-selector/dso-selector.component.ts @@ -0,0 +1,94 @@ +import { AfterViewInit, Component, Input, OnInit } from '@angular/core'; +import { FormControl } from '@angular/forms'; + +import { Observable } from 'rxjs'; +import { map, switchMap } from 'rxjs/operators'; +import { SearchService } from '../../../+search-page/search-service/search.service'; +import { PaginatedSearchOptions } from '../../../+search-page/paginated-search-options.model'; +import { DSpaceObjectType } from '../../../core/shared/dspace-object-type.model'; +import { RemoteData } from '../../../core/data/remote-data'; +import { PaginatedList } from '../../../core/data/paginated-list'; +import { SearchResult } from '../../../+search-page/search-result.model'; +import { DSpaceObject } from '../../../core/shared/dspace-object.model'; + +interface DSOSelectListEntry { + parents: DSpaceObject[], + dso: DSpaceObject +} + +@Component({ + selector: 'ds-dso-selector', + // styleUrls: ['./dso-selector.component.scss'], + templateUrl: './dso-selector.component.html' +}) +export class DSOSelectorComponent implements OnInit, AfterViewInit { + @Input() currentDSOId: string; + @Input() type: DSpaceObjectType; + + public input: FormControl = new FormControl(); + // private subs: Subscription[] = []; + private defaultPagination = { id: 'dso-selector', currentPage: 1, pageSize: 5 } as any; + listEntries$: Observable; + + constructor(private searchService: SearchService) { + + } + + ngOnInit(): void { + this.listEntries$ = this.input.valueChanges + .pipe( + switchMap((query) => { + return this.searchService.search( + new PaginatedSearchOptions({ + query: query, + dsoType: this.type, + pagination: this.defaultPagination + }) + ) + } + ), + map((searchResultsRD: RemoteData>>) => { + return searchResultsRD.payload.page.map( + (searchResult: SearchResult) => { + let dso = searchResult.dspaceObject; + return { + parents: this.retrieveParentList(dso), + dso + } as DSOSelectListEntry + } + ) + }) + ); + + } + + + retrieveParentList(dso: DSpaceObject, parents: DSpaceObject[] = []) { + return [{name: 'Test Community'} as any]; + // if (hasValue(dso.owner)) { + // dso.owner.pipe( + // first(), + // ).subscribe((parentRD) => { + // const newDSO: DSpaceObject = parentRD.payload; + // parents = [...this.retrieveParentList(newDSO, parents), newDSO]; + // }); + // } + // return parents; + } + + // ngOnDestroy(): void { + // this.subs.filter((sub) => hasValue(sub)).forEach((sub) => sub.unsubscribe()); + // } + + onSelect(event) { + + } + + onClose() { + + } + + ngAfterViewInit(): void { + this.input.setValue(this.currentDSOId); + } +} diff --git a/src/app/shared/dso-selector/item-selector-modal-wrapper/item-selector-modal-wrapper.component.html b/src/app/shared/dso-selector/item-selector-modal-wrapper/item-selector-modal-wrapper.component.html new file mode 100644 index 0000000000..7d100cbece --- /dev/null +++ b/src/app/shared/dso-selector/item-selector-modal-wrapper/item-selector-modal-wrapper.component.html @@ -0,0 +1,6 @@ +
+ + +
\ No newline at end of file diff --git a/src/app/shared/dso-selector/item-selector-modal-wrapper/item-selector-modal-wrapper.component.ts b/src/app/shared/dso-selector/item-selector-modal-wrapper/item-selector-modal-wrapper.component.ts new file mode 100644 index 0000000000..f8d0a14359 --- /dev/null +++ b/src/app/shared/dso-selector/item-selector-modal-wrapper/item-selector-modal-wrapper.component.ts @@ -0,0 +1,21 @@ +import { Component, Input, OnInit } from '@angular/core'; +import { ActivatedRoute, Router } from '@angular/router'; +import { Community } from '../../../core/shared/community.model'; +import { RemoteData } from '../../../core/data/remote-data'; +import { Collection } from '../../../core/shared/collection.model'; + +@Component({ + selector: 'ds-item-selector-modal-wrapper', + // styleUrls: ['./item-selector.component.scss'], + templateUrl: './item-selector-modal-wrapper.component.html', +}) +export class ItemSelectorModalWrapperComponent implements OnInit { + @Input() collectionRD: RemoteData; + + constructor(private route: ActivatedRoute) { + } + + ngOnInit(): void { + this.collectionRD = this.route.root.firstChild.firstChild.snapshot.data.collection; + } +} diff --git a/src/app/shared/shared.module.ts b/src/app/shared/shared.module.ts index da45faee9f..2d69c70591 100644 --- a/src/app/shared/shared.module.ts +++ b/src/app/shared/shared.module.ts @@ -91,12 +91,14 @@ import { CreateComColPageComponent } from './comcol-forms/create-comcol-page/cre import { EditComColPageComponent } from './comcol-forms/edit-comcol-page/edit-comcol-page.component'; import { DeleteComColPageComponent } from './comcol-forms/delete-comcol-page/delete-comcol-page.component'; import { LangSwitchComponent } from './lang-switch/lang-switch.component'; -import { CollectionSelectorComponent } from './dso-selector/collection-selector/collection-selector.component'; import { CollectionSelectorModalWrapperComponent } from './dso-selector/collection-selector-modal-wrapper/collection-selector-modal-wrapper.component'; import { ObjectValuesPipe } from './utils/object-values-pipe'; import { InListValidator } from './utils/in-list-validator.directive'; import { AutoFocusDirective } from './utils/auto-focus.directive'; import { ComcolPageBrowseByComponent } from './comcol-page-browse-by/comcol-page-browse-by.component'; +import { DSOSelectorComponent } from './dso-selector/dso-selector/dso-selector.component'; +import { ItemSelectorModalWrapperComponent } from './dso-selector/item-selector-modal-wrapper/item-selector-modal-wrapper.component'; +import { CommunitySelectorModalWrapperComponent } from './dso-selector/community-selector-modal-wrapper/community-selector-modal-wrapper.component'; const MODULES = [ // Do NOT include UniversalModule, HttpModule, or JsonpModule here @@ -179,8 +181,10 @@ const COMPONENTS = [ TruncatablePartComponent, BrowseByComponent, InputSuggestionsComponent, - CollectionSelectorComponent, - CollectionSelectorModalWrapperComponent + DSOSelectorComponent, + CommunitySelectorModalWrapperComponent, + CollectionSelectorModalWrapperComponent, + ItemSelectorModalWrapperComponent ]; const ENTRY_COMPONENTS = [ @@ -194,8 +198,10 @@ const ENTRY_COMPONENTS = [ CommunityGridElementComponent, SearchResultGridElementComponent, BrowseEntryListElementComponent, - CollectionSelectorComponent, - CollectionSelectorModalWrapperComponent + DSOSelectorComponent, + CommunitySelectorModalWrapperComponent, + CollectionSelectorModalWrapperComponent, + ItemSelectorModalWrapperComponent ]; const PROVIDERS = [ From 9f02f65a0a8c0840520fe6f61a8e9a4304881001 Mon Sep 17 00:00:00 2001 From: lotte Date: Mon, 4 Mar 2019 16:35:04 +0100 Subject: [PATCH 03/17] implemented edit popups and added actions --- .../admin-sidebar/admin-sidebar.component.ts | 40 ++++++++++------- .../collection-page-routing.module.ts | 23 +++++++++- .../community-page-routing.module.ts | 23 +++++++++- src/app/app-routing.module.ts | 12 +++++- ...tion-selector-modal-wrapper.component.html | 6 --- ...ection-selector-modal-wrapper.component.ts | 20 --------- ...nity-selector-modal-wrapper.component.html | 7 --- ...munity-selector-modal-wrapper.component.ts | 20 --------- .../dso-selector/dso-selector.component.html | 4 +- .../dso-selector/dso-selector.component.ts | 34 +++++++++------ ...item-selector-modal-wrapper.component.html | 6 --- .../item-selector-modal-wrapper.component.ts | 21 --------- ...-collection-parent-selector.component.html | 6 +++ ...te-collection-parent-selector.component.ts | 39 +++++++++++++++++ ...e-community-parent-selector.component.html | 7 +++ ...ate-community-parent-selector.component.ts | 43 +++++++++++++++++++ ...create-item-parent-selector.component.html | 6 +++ .../create-item-parent-selector.component.ts | 36 ++++++++++++++++ ...-collection-parent-selector.component.html | 6 +++ ...it-collection-parent-selector.component.ts | 33 ++++++++++++++ ...t-community-parent-selector.component.html | 6 +++ ...dit-community-parent-selector.component.ts | 32 ++++++++++++++ .../edit-item-parent-selector.component.html | 6 +++ .../edit-item-parent-selector.component.ts | 34 +++++++++++++++ .../onclick-menu-item.component.html | 2 +- src/app/shared/shared.module.ts | 27 ++++++++---- 26 files changed, 371 insertions(+), 128 deletions(-) delete mode 100644 src/app/shared/dso-selector/collection-selector-modal-wrapper/collection-selector-modal-wrapper.component.html delete mode 100644 src/app/shared/dso-selector/collection-selector-modal-wrapper/collection-selector-modal-wrapper.component.ts delete mode 100644 src/app/shared/dso-selector/community-selector-modal-wrapper/community-selector-modal-wrapper.component.html delete mode 100644 src/app/shared/dso-selector/community-selector-modal-wrapper/community-selector-modal-wrapper.component.ts delete mode 100644 src/app/shared/dso-selector/item-selector-modal-wrapper/item-selector-modal-wrapper.component.html delete mode 100644 src/app/shared/dso-selector/item-selector-modal-wrapper/item-selector-modal-wrapper.component.ts create mode 100644 src/app/shared/dso-selector/modal-wrappers/create-collection-parent-selector/create-collection-parent-selector.component.html create mode 100644 src/app/shared/dso-selector/modal-wrappers/create-collection-parent-selector/create-collection-parent-selector.component.ts create mode 100644 src/app/shared/dso-selector/modal-wrappers/create-community-parent-selector/create-community-parent-selector.component.html create mode 100644 src/app/shared/dso-selector/modal-wrappers/create-community-parent-selector/create-community-parent-selector.component.ts create mode 100644 src/app/shared/dso-selector/modal-wrappers/create-item-parent-selector/create-item-parent-selector.component.html create mode 100644 src/app/shared/dso-selector/modal-wrappers/create-item-parent-selector/create-item-parent-selector.component.ts create mode 100644 src/app/shared/dso-selector/modal-wrappers/edit-collection-parent-selector/edit-collection-parent-selector.component.html create mode 100644 src/app/shared/dso-selector/modal-wrappers/edit-collection-parent-selector/edit-collection-parent-selector.component.ts create mode 100644 src/app/shared/dso-selector/modal-wrappers/edit-community-parent-selector/edit-community-parent-selector.component.html create mode 100644 src/app/shared/dso-selector/modal-wrappers/edit-community-parent-selector/edit-community-parent-selector.component.ts create mode 100644 src/app/shared/dso-selector/modal-wrappers/edit-item-parent-selector/edit-item-parent-selector.component.html create mode 100644 src/app/shared/dso-selector/modal-wrappers/edit-item-parent-selector/edit-item-parent-selector.component.ts diff --git a/src/app/+admin/admin-sidebar/admin-sidebar.component.ts b/src/app/+admin/admin-sidebar/admin-sidebar.component.ts index 22cb1f5825..8b71bca423 100644 --- a/src/app/+admin/admin-sidebar/admin-sidebar.component.ts +++ b/src/app/+admin/admin-sidebar/admin-sidebar.component.ts @@ -12,9 +12,12 @@ import { first, map } from 'rxjs/operators'; import { combineLatest as combineLatestObservable } from 'rxjs'; import { NgbModal } from '@ng-bootstrap/ng-bootstrap'; import { OnClickMenuItemModel } from '../../shared/menu/menu-item/models/onclick.model'; -import { CollectionSelectorModalWrapperComponent } from '../../shared/dso-selector/collection-selector-modal-wrapper/collection-selector-modal-wrapper.component'; -import { ItemSelectorModalWrapperComponent } from '../../shared/dso-selector/item-selector-modal-wrapper/item-selector-modal-wrapper.component'; -import { CommunitySelectorModalWrapperComponent } from '../../shared/dso-selector/community-selector-modal-wrapper/community-selector-modal-wrapper.component'; +import { CreateCommunityParentSelectorComponent } from '../../shared/dso-selector/modal-wrappers/create-community-parent-selector/create-community-parent-selector.component'; +import { CreateItemParentSelectorComponent } from '../../shared/dso-selector/modal-wrappers/create-item-parent-selector/create-item-parent-selector.component'; +import { CreateCollectionParentSelectorComponent } from '../../shared/dso-selector/modal-wrappers/create-collection-parent-selector/create-collection-parent-selector.component'; +import { EditCollectionParentSelectorComponent } from '../../shared/dso-selector/modal-wrappers/edit-collection-parent-selector/edit-collection-parent-selector.component'; +import { EditItemParentSelectorComponent } from '../../shared/dso-selector/modal-wrappers/edit-item-parent-selector/edit-item-parent-selector.component'; +import { EditCommunityParentSelectorComponent } from '../../shared/dso-selector/modal-wrappers/edit-community-parent-selector/edit-community-parent-selector.component'; /** * Component representing the admin sidebar @@ -113,7 +116,7 @@ export class AdminSidebarComponent extends MenuComponent implements OnInit { type: MenuItemType.ONCLICK, text: 'menu.section.new_community', function: () => { - this.modalService.open(CommunitySelectorModalWrapperComponent); + this.modalService.open(CreateCommunityParentSelectorComponent); } } as OnClickMenuItemModel, }, @@ -126,7 +129,7 @@ export class AdminSidebarComponent extends MenuComponent implements OnInit { type: MenuItemType.ONCLICK, text: 'menu.section.new_collection', function: () => { - this.modalService.open(CollectionSelectorModalWrapperComponent); + this.modalService.open(CreateCollectionParentSelectorComponent); } } as OnClickMenuItemModel, }, @@ -139,7 +142,7 @@ export class AdminSidebarComponent extends MenuComponent implements OnInit { type: MenuItemType.ONCLICK, text: 'menu.section.new_item', function: () => { - this.modalService.open(ItemSelectorModalWrapperComponent); + this.modalService.open(CreateItemParentSelectorComponent); } } as OnClickMenuItemModel, }, @@ -173,10 +176,12 @@ export class AdminSidebarComponent extends MenuComponent implements OnInit { active: false, visible: true, model: { - type: MenuItemType.LINK, + type: MenuItemType.ONCLICK, text: 'menu.section.edit_community', - link: '#' - } as LinkMenuItemModel, + function: () => { + this.modalService.open(EditCommunityParentSelectorComponent); + } + } as OnClickMenuItemModel, }, { id: 'edit_collection', @@ -184,10 +189,12 @@ export class AdminSidebarComponent extends MenuComponent implements OnInit { active: false, visible: true, model: { - type: MenuItemType.LINK, + type: MenuItemType.ONCLICK, text: 'menu.section.edit_collection', - link: '#' - } as LinkMenuItemModel, + function: () => { + this.modalService.open(EditCollectionParentSelectorComponent); + } + } as OnClickMenuItemModel, }, { id: 'edit_item', @@ -195,10 +202,12 @@ export class AdminSidebarComponent extends MenuComponent implements OnInit { active: false, visible: true, model: { - type: MenuItemType.LINK, + type: MenuItemType.ONCLICK, text: 'menu.section.edit_item', - link: '#' - } as LinkMenuItemModel, + function: () => { + this.modalService.open(EditItemParentSelectorComponent); + } + } as OnClickMenuItemModel, }, /* Import */ @@ -235,7 +244,6 @@ export class AdminSidebarComponent extends MenuComponent implements OnInit { link: '#' } as LinkMenuItemModel, }, - /* Export */ { id: 'export', diff --git a/src/app/+collection-page/collection-page-routing.module.ts b/src/app/+collection-page/collection-page-routing.module.ts index ddcf36a0cc..cdbd7650b2 100644 --- a/src/app/+collection-page/collection-page-routing.module.ts +++ b/src/app/+collection-page/collection-page-routing.module.ts @@ -8,17 +8,36 @@ import { AuthenticatedGuard } from '../core/auth/authenticated.guard'; import { EditCollectionPageComponent } from './edit-collection-page/edit-collection-page.component'; import { CreateCollectionPageGuard } from './create-collection-page/create-collection-page.guard'; import { DeleteCollectionPageComponent } from './delete-collection-page/delete-collection-page.component'; +import { URLCombiner } from '../core/url-combiner/url-combiner'; +import { getCollectionModulePath } from '../app-routing.module'; + +export const COLLECTION_PARENT_PARAMETER = 'parent'; + +export function getCollectionPageRoute(collectionId: string) { + return new URLCombiner(getCollectionModulePath(), collectionId).toString(); +} + +export function getCollectionEditPath(id: string) { + return new URLCombiner(getCollectionModulePath(), COLLECTION_EDIT_PATH.replace(/:id/, id)).toString() +} + +export function getCollectionCreatePath() { + return new URLCombiner(getCollectionModulePath(), COLLECTION_CREATE_PATH).toString() +} + +const COLLECTION_CREATE_PATH = 'create'; +const COLLECTION_EDIT_PATH = ':id/edit'; @NgModule({ imports: [ RouterModule.forChild([ { - path: 'create', + path: COLLECTION_CREATE_PATH, component: CreateCollectionPageComponent, canActivate: [AuthenticatedGuard, CreateCollectionPageGuard] }, { - path: ':id/edit', + path: COLLECTION_EDIT_PATH, pathMatch: 'full', component: EditCollectionPageComponent, canActivate: [AuthenticatedGuard], diff --git a/src/app/+community-page/community-page-routing.module.ts b/src/app/+community-page/community-page-routing.module.ts index 02f28f6375..cecd17ec10 100644 --- a/src/app/+community-page/community-page-routing.module.ts +++ b/src/app/+community-page/community-page-routing.module.ts @@ -8,17 +8,36 @@ import { AuthenticatedGuard } from '../core/auth/authenticated.guard'; import { EditCommunityPageComponent } from './edit-community-page/edit-community-page.component'; import { CreateCommunityPageGuard } from './create-community-page/create-community-page.guard'; import { DeleteCommunityPageComponent } from './delete-community-page/delete-community-page.component'; +import { URLCombiner } from '../core/url-combiner/url-combiner'; +import { getCommunityModulePath } from '../app-routing.module'; + +export const COMMUNITY_PARENT_PARAMETER = 'parent'; + +export function getCommunityPageRoute(communityId: string) { + return new URLCombiner(getCommunityModulePath(), communityId).toString(); +} + +export function getCommunityEditPath(id: string) { + return new URLCombiner(getCommunityModulePath(), COMMUNITY_EDIT_PATH.replace(/:id/, id)).toString() +} + +export function getCommunityCreatePath() { + return new URLCombiner(getCommunityModulePath(), COMMUNITY_CREATE_PATH).toString() +} + +const COMMUNITY_CREATE_PATH = 'create'; +const COMMUNITY_EDIT_PATH = ':id/edit'; @NgModule({ imports: [ RouterModule.forChild([ { - path: 'create', + path: COMMUNITY_CREATE_PATH, component: CreateCommunityPageComponent, canActivate: [AuthenticatedGuard, CreateCommunityPageGuard] }, { - path: ':id/edit', + path: COMMUNITY_EDIT_PATH, pathMatch: 'full', component: EditCommunityPageComponent, canActivate: [AuthenticatedGuard], diff --git a/src/app/app-routing.module.ts b/src/app/app-routing.module.ts index 1476aa5dad..1448601067 100644 --- a/src/app/app-routing.module.ts +++ b/src/app/app-routing.module.ts @@ -8,13 +8,21 @@ const ITEM_MODULE_PATH = 'items'; export function getItemModulePath() { return `/${ITEM_MODULE_PATH}`; } +const COLLECTION_MODULE_PATH = 'collections'; +export function getCollectionModulePath() { + return `/${COLLECTION_MODULE_PATH}`; +} +const COMMUNITY_MODULE_PATH = 'communities'; +export function getCommunityModulePath() { + return `/${COMMUNITY_MODULE_PATH}`; +} @NgModule({ imports: [ RouterModule.forRoot([ { path: '', redirectTo: '/home', pathMatch: 'full' }, { 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: COMMUNITY_MODULE_PATH, loadChildren: './+community-page/community-page.module#CommunityPageModule' }, + { path: COLLECTION_MODULE_PATH, loadChildren: './+collection-page/collection-page.module#CollectionPageModule' }, { 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' }, diff --git a/src/app/shared/dso-selector/collection-selector-modal-wrapper/collection-selector-modal-wrapper.component.html b/src/app/shared/dso-selector/collection-selector-modal-wrapper/collection-selector-modal-wrapper.component.html deleted file mode 100644 index f3bf405651..0000000000 --- a/src/app/shared/dso-selector/collection-selector-modal-wrapper/collection-selector-modal-wrapper.component.html +++ /dev/null @@ -1,6 +0,0 @@ -
- - -
\ No newline at end of file diff --git a/src/app/shared/dso-selector/collection-selector-modal-wrapper/collection-selector-modal-wrapper.component.ts b/src/app/shared/dso-selector/collection-selector-modal-wrapper/collection-selector-modal-wrapper.component.ts deleted file mode 100644 index cda2284835..0000000000 --- a/src/app/shared/dso-selector/collection-selector-modal-wrapper/collection-selector-modal-wrapper.component.ts +++ /dev/null @@ -1,20 +0,0 @@ -import { Component, Input, OnInit } from '@angular/core'; -import { ActivatedRoute, Router } from '@angular/router'; -import { Community } from '../../../core/shared/community.model'; -import { RemoteData } from '../../../core/data/remote-data'; - -@Component({ - selector: 'ds-collection-selector-modal-wrapper', - // styleUrls: ['./collection-selector.component.scss'], - templateUrl: './collection-selector-modal-wrapper.component.html', -}) -export class CollectionSelectorModalWrapperComponent implements OnInit { - @Input() communityRD: RemoteData; - - constructor(private route: ActivatedRoute) { - } - - ngOnInit(): void { - this.communityRD = this.route.root.firstChild.firstChild.snapshot.data.community; - } -} diff --git a/src/app/shared/dso-selector/community-selector-modal-wrapper/community-selector-modal-wrapper.component.html b/src/app/shared/dso-selector/community-selector-modal-wrapper/community-selector-modal-wrapper.component.html deleted file mode 100644 index 91b97a25a3..0000000000 --- a/src/app/shared/dso-selector/community-selector-modal-wrapper/community-selector-modal-wrapper.component.html +++ /dev/null @@ -1,7 +0,0 @@ -
- - -
\ No newline at end of file diff --git a/src/app/shared/dso-selector/community-selector-modal-wrapper/community-selector-modal-wrapper.component.ts b/src/app/shared/dso-selector/community-selector-modal-wrapper/community-selector-modal-wrapper.component.ts deleted file mode 100644 index 8ebee7ea7f..0000000000 --- a/src/app/shared/dso-selector/community-selector-modal-wrapper/community-selector-modal-wrapper.component.ts +++ /dev/null @@ -1,20 +0,0 @@ -import { Component, Input, OnInit } from '@angular/core'; -import { ActivatedRoute, Router } from '@angular/router'; -import { Community } from '../../../core/shared/community.model'; -import { RemoteData } from '../../../core/data/remote-data'; - -@Component({ - selector: 'ds-community-selector-modal-wrapper', - // styleUrls: ['./community-selector.component.scss'], - templateUrl: './community-selector-modal-wrapper.component.html', -}) -export class CommunitySelectorModalWrapperComponent implements OnInit { - @Input() communityRD: RemoteData; - - constructor(private route: ActivatedRoute) { - } - - ngOnInit(): void { - this.communityRD = this.route.root.firstChild.firstChild.snapshot.data.community; - } -} diff --git a/src/app/shared/dso-selector/dso-selector/dso-selector.component.html b/src/app/shared/dso-selector/dso-selector/dso-selector.component.html index b15eaf9338..762f736b5d 100644 --- a/src/app/shared/dso-selector/dso-selector/dso-selector.component.html +++ b/src/app/shared/dso-selector/dso-selector/dso-selector.component.html @@ -5,8 +5,6 @@ placeholder="{{ 'submission.sections.general.search-collection' | translate }}" [formControl]="input"> - -{{input.value}}
+ +
+ \ No newline at end of file diff --git a/src/app/shared/dso-selector/modal-wrappers/create-community-parent-selector/create-community-parent-selector.component.ts b/src/app/shared/dso-selector/modal-wrappers/create-community-parent-selector/create-community-parent-selector.component.ts new file mode 100644 index 0000000000..8e1eb4e23f --- /dev/null +++ b/src/app/shared/dso-selector/modal-wrappers/create-community-parent-selector/create-community-parent-selector.component.ts @@ -0,0 +1,43 @@ +import { Component, Input, OnInit } from '@angular/core'; +import { ActivatedRoute, NavigationExtras, Router } from '@angular/router'; +import { Community } from '../../../../core/shared/community.model'; +import { RemoteData } from '../../../../core/data/remote-data'; +import { DSpaceObjectType } from '../../../../core/shared/dspace-object-type.model'; +import { DSpaceObject } from '../../../../core/shared/dspace-object.model'; +import { hasValue } from '../../../empty.util'; +import { NgbActiveModal } from '@ng-bootstrap/ng-bootstrap'; +import { map } from 'rxjs/operators'; +import { Observable } from 'rxjs'; +import { COMMUNITY_PARENT_PARAMETER } from '../../../../+community-page/community-page-routing.module'; + +@Component({ + selector: 'ds-create-community-parent-selector', + // styleUrls: ['./create-community-parent-selector.component.scss'], + templateUrl: './create-community-parent-selector.component.html', +}) +export class CreateCommunityParentSelectorComponent implements OnInit { + @Input() communityRD$: Observable>; + type = DSpaceObjectType.COMMUNITY; + + private createPath = '/communities/create'; + + constructor(private activeModal: NgbActiveModal, private route: ActivatedRoute, private router: Router) { + } + + ngOnInit(): void { + this.communityRD$ = this.route.root.firstChild.firstChild.data.pipe(map(data => data.community)); + } + + createCommunity(dso?: DSpaceObject) { + this.activeModal.close(); + let navigationExtras: NavigationExtras = {}; + if (hasValue(dso)) { + navigationExtras = { + queryParams: { + [COMMUNITY_PARENT_PARAMETER]: dso.uuid, + } + }; + } + this.router.navigate([this.createPath], navigationExtras); + } +} diff --git a/src/app/shared/dso-selector/modal-wrappers/create-item-parent-selector/create-item-parent-selector.component.html b/src/app/shared/dso-selector/modal-wrappers/create-item-parent-selector/create-item-parent-selector.component.html new file mode 100644 index 0000000000..1851fb876b --- /dev/null +++ b/src/app/shared/dso-selector/modal-wrappers/create-item-parent-selector/create-item-parent-selector.component.html @@ -0,0 +1,6 @@ +
+ + +
\ No newline at end of file diff --git a/src/app/shared/dso-selector/modal-wrappers/create-item-parent-selector/create-item-parent-selector.component.ts b/src/app/shared/dso-selector/modal-wrappers/create-item-parent-selector/create-item-parent-selector.component.ts new file mode 100644 index 0000000000..dba3db6959 --- /dev/null +++ b/src/app/shared/dso-selector/modal-wrappers/create-item-parent-selector/create-item-parent-selector.component.ts @@ -0,0 +1,36 @@ +import { Component, Input, OnInit } from '@angular/core'; +import { ActivatedRoute, Router } from '@angular/router'; +import { Community } from '../../../../core/shared/community.model'; +import { RemoteData } from '../../../../core/data/remote-data'; +import { Collection } from '../../../../core/shared/collection.model'; +import { DSpaceObjectType } from '../../../../core/shared/dspace-object-type.model'; +import { DSpaceObject } from '../../../../core/shared/dspace-object.model'; +import { hasValue } from '../../../empty.util'; +import { NgbActiveModal } from '@ng-bootstrap/ng-bootstrap'; +import { map } from 'rxjs/operators'; +import { Observable } from 'rxjs'; + +@Component({ + selector: 'ds-create-item-parent-selector', + // styleUrls: ['./create-item-parent-selector.component.scss'], + templateUrl: './create-item-parent-selector.component.html', +}) +export class CreateItemParentSelectorComponent implements OnInit { + @Input() collectionRD$: Observable>; + type = DSpaceObjectType.COLLECTION; + + constructor(private activeModal: NgbActiveModal, private route: ActivatedRoute) { + } + + ngOnInit(): void { + this.collectionRD$ = this.route.root.firstChild.firstChild.data.pipe(map(data => data.collection)); + } + + createItem(dso: DSpaceObject) { + this.activeModal.close(); + + let path; + // path = this.createPath; + // this.router.navigate([path]); + } +} diff --git a/src/app/shared/dso-selector/modal-wrappers/edit-collection-parent-selector/edit-collection-parent-selector.component.html b/src/app/shared/dso-selector/modal-wrappers/edit-collection-parent-selector/edit-collection-parent-selector.component.html new file mode 100644 index 0000000000..f14110db97 --- /dev/null +++ b/src/app/shared/dso-selector/modal-wrappers/edit-collection-parent-selector/edit-collection-parent-selector.component.html @@ -0,0 +1,6 @@ +
+ + +
\ No newline at end of file diff --git a/src/app/shared/dso-selector/modal-wrappers/edit-collection-parent-selector/edit-collection-parent-selector.component.ts b/src/app/shared/dso-selector/modal-wrappers/edit-collection-parent-selector/edit-collection-parent-selector.component.ts new file mode 100644 index 0000000000..422bd8aee0 --- /dev/null +++ b/src/app/shared/dso-selector/modal-wrappers/edit-collection-parent-selector/edit-collection-parent-selector.component.ts @@ -0,0 +1,33 @@ +import { Component, Input, OnInit } from '@angular/core'; +import { ActivatedRoute, NavigationExtras, Router } from '@angular/router'; +import { Community } from '../../../../core/shared/community.model'; +import { RemoteData } from '../../../../core/data/remote-data'; +import { DSpaceObjectType } from '../../../../core/shared/dspace-object-type.model'; +import { DSpaceObject } from '../../../../core/shared/dspace-object.model'; +import { NgbActiveModal } from '@ng-bootstrap/ng-bootstrap'; +import { Collection } from '../../../../core/shared/collection.model'; +import { Observable } from 'rxjs'; +import { map } from 'rxjs/operators'; +import { getCollectionEditPath } from '../../../../+collection-page/collection-page-routing.module'; + +@Component({ + selector: 'ds-edit-collection-parent-selector', + // styleUrls: ['./edit-collection-parent-selector.component.scss'], + templateUrl: './edit-collection-parent-selector.component.html', +}) +export class EditCollectionParentSelectorComponent implements OnInit { + @Input() collectionRD$: Observable>; + type = DSpaceObjectType.COLLECTION; + + constructor(private activeModal: NgbActiveModal, private route: ActivatedRoute, private router: Router) { + } + + ngOnInit(): void { + this.collectionRD$ = this.route.root.firstChild.firstChild.data.pipe(map(data => data.collection)); + } + + editCollection(dso: DSpaceObject) { + this.activeModal.close(); + this.router.navigate([getCollectionEditPath(dso.uuid)]); + } +} diff --git a/src/app/shared/dso-selector/modal-wrappers/edit-community-parent-selector/edit-community-parent-selector.component.html b/src/app/shared/dso-selector/modal-wrappers/edit-community-parent-selector/edit-community-parent-selector.component.html new file mode 100644 index 0000000000..2cc8c8ae19 --- /dev/null +++ b/src/app/shared/dso-selector/modal-wrappers/edit-community-parent-selector/edit-community-parent-selector.component.html @@ -0,0 +1,6 @@ +
+ + +
\ No newline at end of file diff --git a/src/app/shared/dso-selector/modal-wrappers/edit-community-parent-selector/edit-community-parent-selector.component.ts b/src/app/shared/dso-selector/modal-wrappers/edit-community-parent-selector/edit-community-parent-selector.component.ts new file mode 100644 index 0000000000..e14845bfa4 --- /dev/null +++ b/src/app/shared/dso-selector/modal-wrappers/edit-community-parent-selector/edit-community-parent-selector.component.ts @@ -0,0 +1,32 @@ +import { Component, Input, OnInit } from '@angular/core'; +import { ActivatedRoute, Router } from '@angular/router'; +import { Community } from '../../../../core/shared/community.model'; +import { RemoteData } from '../../../../core/data/remote-data'; +import { DSpaceObjectType } from '../../../../core/shared/dspace-object-type.model'; +import { DSpaceObject } from '../../../../core/shared/dspace-object.model'; +import { NgbActiveModal } from '@ng-bootstrap/ng-bootstrap'; +import { Observable } from 'rxjs'; +import { map } from 'rxjs/operators'; +import { getCommunityEditPath } from '../../../../+community-page/community-page-routing.module'; + +@Component({ + selector: 'ds-edit-community-parent-selector', + // styleUrls: ['./edit-community-parent-selector.component.scss'], + templateUrl: './edit-community-parent-selector.component.html', +}) +export class EditCommunityParentSelectorComponent implements OnInit { + @Input() communityRD$: Observable>; + type = DSpaceObjectType.COMMUNITY; + + constructor(private activeModal: NgbActiveModal, private route: ActivatedRoute, private router: Router) { + } + + ngOnInit(): void { + this.communityRD$ = this.route.root.firstChild.firstChild.data.pipe(map(data => data.collection)); + } + + editCommunity(dso: DSpaceObject) { + this.activeModal.close(); + this.router.navigate([getCommunityEditPath(dso.uuid)]); + } +} diff --git a/src/app/shared/dso-selector/modal-wrappers/edit-item-parent-selector/edit-item-parent-selector.component.html b/src/app/shared/dso-selector/modal-wrappers/edit-item-parent-selector/edit-item-parent-selector.component.html new file mode 100644 index 0000000000..6bc59b96bd --- /dev/null +++ b/src/app/shared/dso-selector/modal-wrappers/edit-item-parent-selector/edit-item-parent-selector.component.html @@ -0,0 +1,6 @@ +
+ + +
\ No newline at end of file diff --git a/src/app/shared/dso-selector/modal-wrappers/edit-item-parent-selector/edit-item-parent-selector.component.ts b/src/app/shared/dso-selector/modal-wrappers/edit-item-parent-selector/edit-item-parent-selector.component.ts new file mode 100644 index 0000000000..0a3963d6ae --- /dev/null +++ b/src/app/shared/dso-selector/modal-wrappers/edit-item-parent-selector/edit-item-parent-selector.component.ts @@ -0,0 +1,34 @@ +import { Component, Input, OnInit } from '@angular/core'; +import { ActivatedRoute, NavigationExtras, Router } from '@angular/router'; +import { Community } from '../../../../core/shared/community.model'; +import { RemoteData } from '../../../../core/data/remote-data'; +import { DSpaceObjectType } from '../../../../core/shared/dspace-object-type.model'; +import { DSpaceObject } from '../../../../core/shared/dspace-object.model'; +import { NgbActiveModal } from '@ng-bootstrap/ng-bootstrap'; +import { Collection } from '../../../../core/shared/collection.model'; +import { Observable } from 'rxjs'; +import { map } from 'rxjs/operators'; +import { Item } from '../../../../core/shared/item.model'; +import { getItemEditPath } from '../../../../+item-page/item-page-routing.module'; + +@Component({ + selector: 'ds-edit-item-parent-selector', + // styleUrls: ['./edit-item-parent-selector.component.scss'], + templateUrl: './edit-item-parent-selector.component.html', +}) +export class EditItemParentSelectorComponent implements OnInit { + @Input() itemRD$: Observable>; + type = DSpaceObjectType.ITEM; + + constructor(private activeModal: NgbActiveModal, private route: ActivatedRoute, private router: Router) { + } + + ngOnInit(): void { + this.itemRD$ = this.route.root.firstChild.firstChild.data.pipe(map(data => data.item)); + } + + editItem(dso: DSpaceObject) { + this.activeModal.close(); + this.router.navigate([getItemEditPath(dso.uuid)]); + } +} diff --git a/src/app/shared/menu/menu-item/onclick-menu-item.component.html b/src/app/shared/menu/menu-item/onclick-menu-item.component.html index 0790ef7479..96c9049ab3 100644 --- a/src/app/shared/menu/menu-item/onclick-menu-item.component.html +++ b/src/app/shared/menu/menu-item/onclick-menu-item.component.html @@ -1 +1 @@ -{{item.text | translate}} \ No newline at end of file +{{item.text | translate}} \ No newline at end of file diff --git a/src/app/shared/shared.module.ts b/src/app/shared/shared.module.ts index 2d69c70591..3ee20d435d 100644 --- a/src/app/shared/shared.module.ts +++ b/src/app/shared/shared.module.ts @@ -91,14 +91,17 @@ import { CreateComColPageComponent } from './comcol-forms/create-comcol-page/cre import { EditComColPageComponent } from './comcol-forms/edit-comcol-page/edit-comcol-page.component'; import { DeleteComColPageComponent } from './comcol-forms/delete-comcol-page/delete-comcol-page.component'; import { LangSwitchComponent } from './lang-switch/lang-switch.component'; -import { CollectionSelectorModalWrapperComponent } from './dso-selector/collection-selector-modal-wrapper/collection-selector-modal-wrapper.component'; import { ObjectValuesPipe } from './utils/object-values-pipe'; import { InListValidator } from './utils/in-list-validator.directive'; import { AutoFocusDirective } from './utils/auto-focus.directive'; import { ComcolPageBrowseByComponent } from './comcol-page-browse-by/comcol-page-browse-by.component'; import { DSOSelectorComponent } from './dso-selector/dso-selector/dso-selector.component'; -import { ItemSelectorModalWrapperComponent } from './dso-selector/item-selector-modal-wrapper/item-selector-modal-wrapper.component'; -import { CommunitySelectorModalWrapperComponent } from './dso-selector/community-selector-modal-wrapper/community-selector-modal-wrapper.component'; +import { CreateCommunityParentSelectorComponent } from './dso-selector/modal-wrappers/create-community-parent-selector/create-community-parent-selector.component'; +import { CreateItemParentSelectorComponent } from './dso-selector/modal-wrappers/create-item-parent-selector/create-item-parent-selector.component'; +import { CreateCollectionParentSelectorComponent } from './dso-selector/modal-wrappers/create-collection-parent-selector/create-collection-parent-selector.component'; +import { EditCollectionParentSelectorComponent } from './dso-selector/modal-wrappers/edit-collection-parent-selector/edit-collection-parent-selector.component'; +import { EditItemParentSelectorComponent } from './dso-selector/modal-wrappers/edit-item-parent-selector/edit-item-parent-selector.component'; +import { EditCommunityParentSelectorComponent } from './dso-selector/modal-wrappers/edit-community-parent-selector/edit-community-parent-selector.component'; const MODULES = [ // Do NOT include UniversalModule, HttpModule, or JsonpModule here @@ -182,9 +185,12 @@ const COMPONENTS = [ BrowseByComponent, InputSuggestionsComponent, DSOSelectorComponent, - CommunitySelectorModalWrapperComponent, - CollectionSelectorModalWrapperComponent, - ItemSelectorModalWrapperComponent + CreateCommunityParentSelectorComponent, + CreateCollectionParentSelectorComponent, + CreateItemParentSelectorComponent, + EditCommunityParentSelectorComponent, + EditCollectionParentSelectorComponent, + EditItemParentSelectorComponent, ]; const ENTRY_COMPONENTS = [ @@ -199,9 +205,12 @@ const ENTRY_COMPONENTS = [ SearchResultGridElementComponent, BrowseEntryListElementComponent, DSOSelectorComponent, - CommunitySelectorModalWrapperComponent, - CollectionSelectorModalWrapperComponent, - ItemSelectorModalWrapperComponent + CreateCommunityParentSelectorComponent, + CreateCollectionParentSelectorComponent, + CreateItemParentSelectorComponent, + EditCommunityParentSelectorComponent, + EditCollectionParentSelectorComponent, + EditItemParentSelectorComponent, ]; const PROVIDERS = [ From b4d404e1d38745d53ca39ffe252f75771e26d58d Mon Sep 17 00:00:00 2001 From: lotte Date: Tue, 5 Mar 2019 16:22:52 +0100 Subject: [PATCH 04/17] fixed focus and css --- .../dso-selector/dso-selector.component.html | 6 +-- .../dso-selector/dso-selector.component.ts | 48 +++++++++---------- ...-collection-parent-selector.component.html | 9 +++- ...te-collection-parent-selector.component.ts | 6 ++- ...e-community-parent-selector.component.html | 18 +++++-- ...e-community-parent-selector.component.scss | 3 ++ ...ate-community-parent-selector.component.ts | 8 +++- ...create-item-parent-selector.component.html | 6 ++- .../create-item-parent-selector.component.ts | 6 ++- ...-collection-parent-selector.component.html | 6 ++- ...it-collection-parent-selector.component.ts | 6 ++- ...t-community-parent-selector.component.html | 6 ++- ...dit-community-parent-selector.component.ts | 7 ++- .../edit-item-parent-selector.component.html | 6 ++- .../edit-item-parent-selector.component.ts | 6 ++- 15 files changed, 103 insertions(+), 44 deletions(-) create mode 100644 src/app/shared/dso-selector/modal-wrappers/create-community-parent-selector/create-community-parent-selector.component.scss diff --git a/src/app/shared/dso-selector/dso-selector/dso-selector.component.html b/src/app/shared/dso-selector/dso-selector/dso-selector.component.html index 762f736b5d..ceaefc2ac9 100644 --- a/src/app/shared/dso-selector/dso-selector/dso-selector.component.html +++ b/src/app/shared/dso-selector/dso-selector/dso-selector.component.html @@ -6,14 +6,14 @@ [formControl]="input"> -
+
+
\ No newline at end of file diff --git a/src/app/shared/dso-selector/modal-wrappers/create-collection-parent-selector/create-collection-parent-selector.component.ts b/src/app/shared/dso-selector/modal-wrappers/create-collection-parent-selector/create-collection-parent-selector.component.ts index 57e77ce77d..c4bff22c7b 100644 --- a/src/app/shared/dso-selector/modal-wrappers/create-collection-parent-selector/create-collection-parent-selector.component.ts +++ b/src/app/shared/dso-selector/modal-wrappers/create-collection-parent-selector/create-collection-parent-selector.component.ts @@ -28,7 +28,7 @@ export class CreateCollectionParentSelectorComponent implements OnInit { } createCollection(dso: DSpaceObject) { - this.activeModal.close(); + this.close(); let navigationExtras: NavigationExtras = { queryParams: { [COLLECTION_PARENT_PARAMETER]: dso.uuid, @@ -36,4 +36,8 @@ export class CreateCollectionParentSelectorComponent implements OnInit { }; this.router.navigate([this.createPath], navigationExtras); } + + close() { + this.activeModal.close(); + } } diff --git a/src/app/shared/dso-selector/modal-wrappers/create-community-parent-selector/create-community-parent-selector.component.html b/src/app/shared/dso-selector/modal-wrappers/create-community-parent-selector/create-community-parent-selector.component.html index e32d278a44..a50f1a57c6 100644 --- a/src/app/shared/dso-selector/modal-wrappers/create-community-parent-selector/create-community-parent-selector.component.html +++ b/src/app/shared/dso-selector/modal-wrappers/create-community-parent-selector/create-community-parent-selector.component.html @@ -1,7 +1,19 @@
- +
\ No newline at end of file diff --git a/src/app/shared/dso-selector/modal-wrappers/create-community-parent-selector/create-community-parent-selector.component.scss b/src/app/shared/dso-selector/modal-wrappers/create-community-parent-selector/create-community-parent-selector.component.scss new file mode 100644 index 0000000000..0daf4cfa5f --- /dev/null +++ b/src/app/shared/dso-selector/modal-wrappers/create-community-parent-selector/create-community-parent-selector.component.scss @@ -0,0 +1,3 @@ +#create-community-or-separator { + top: 0; +} \ No newline at end of file diff --git a/src/app/shared/dso-selector/modal-wrappers/create-community-parent-selector/create-community-parent-selector.component.ts b/src/app/shared/dso-selector/modal-wrappers/create-community-parent-selector/create-community-parent-selector.component.ts index 8e1eb4e23f..017f933d1f 100644 --- a/src/app/shared/dso-selector/modal-wrappers/create-community-parent-selector/create-community-parent-selector.component.ts +++ b/src/app/shared/dso-selector/modal-wrappers/create-community-parent-selector/create-community-parent-selector.component.ts @@ -12,7 +12,7 @@ import { COMMUNITY_PARENT_PARAMETER } from '../../../../+community-page/communit @Component({ selector: 'ds-create-community-parent-selector', - // styleUrls: ['./create-community-parent-selector.component.scss'], + styleUrls: ['./create-community-parent-selector.component.scss'], templateUrl: './create-community-parent-selector.component.html', }) export class CreateCommunityParentSelectorComponent implements OnInit { @@ -29,7 +29,7 @@ export class CreateCommunityParentSelectorComponent implements OnInit { } createCommunity(dso?: DSpaceObject) { - this.activeModal.close(); + this.close(); let navigationExtras: NavigationExtras = {}; if (hasValue(dso)) { navigationExtras = { @@ -40,4 +40,8 @@ export class CreateCommunityParentSelectorComponent implements OnInit { } this.router.navigate([this.createPath], navigationExtras); } + + close() { + this.activeModal.close(); + } } diff --git a/src/app/shared/dso-selector/modal-wrappers/create-item-parent-selector/create-item-parent-selector.component.html b/src/app/shared/dso-selector/modal-wrappers/create-item-parent-selector/create-item-parent-selector.component.html index 1851fb876b..1009867056 100644 --- a/src/app/shared/dso-selector/modal-wrappers/create-item-parent-selector/create-item-parent-selector.component.html +++ b/src/app/shared/dso-selector/modal-wrappers/create-item-parent-selector/create-item-parent-selector.component.html @@ -1,5 +1,9 @@
- + diff --git a/src/app/shared/dso-selector/modal-wrappers/create-item-parent-selector/create-item-parent-selector.component.ts b/src/app/shared/dso-selector/modal-wrappers/create-item-parent-selector/create-item-parent-selector.component.ts index dba3db6959..44a8d67d04 100644 --- a/src/app/shared/dso-selector/modal-wrappers/create-item-parent-selector/create-item-parent-selector.component.ts +++ b/src/app/shared/dso-selector/modal-wrappers/create-item-parent-selector/create-item-parent-selector.component.ts @@ -27,10 +27,14 @@ export class CreateItemParentSelectorComponent implements OnInit { } createItem(dso: DSpaceObject) { - this.activeModal.close(); + this.close(); let path; // path = this.createPath; // this.router.navigate([path]); } + + close() { + this.activeModal.close(); + } } diff --git a/src/app/shared/dso-selector/modal-wrappers/edit-collection-parent-selector/edit-collection-parent-selector.component.html b/src/app/shared/dso-selector/modal-wrappers/edit-collection-parent-selector/edit-collection-parent-selector.component.html index f14110db97..9d050ef2fc 100644 --- a/src/app/shared/dso-selector/modal-wrappers/edit-collection-parent-selector/edit-collection-parent-selector.component.html +++ b/src/app/shared/dso-selector/modal-wrappers/edit-collection-parent-selector/edit-collection-parent-selector.component.html @@ -1,5 +1,9 @@
- + diff --git a/src/app/shared/dso-selector/modal-wrappers/edit-collection-parent-selector/edit-collection-parent-selector.component.ts b/src/app/shared/dso-selector/modal-wrappers/edit-collection-parent-selector/edit-collection-parent-selector.component.ts index 422bd8aee0..11e1c47f55 100644 --- a/src/app/shared/dso-selector/modal-wrappers/edit-collection-parent-selector/edit-collection-parent-selector.component.ts +++ b/src/app/shared/dso-selector/modal-wrappers/edit-collection-parent-selector/edit-collection-parent-selector.component.ts @@ -27,7 +27,11 @@ export class EditCollectionParentSelectorComponent implements OnInit { } editCollection(dso: DSpaceObject) { - this.activeModal.close(); + this.close(); this.router.navigate([getCollectionEditPath(dso.uuid)]); } + + close() { + this.activeModal.close(); + } } diff --git a/src/app/shared/dso-selector/modal-wrappers/edit-community-parent-selector/edit-community-parent-selector.component.html b/src/app/shared/dso-selector/modal-wrappers/edit-community-parent-selector/edit-community-parent-selector.component.html index 2cc8c8ae19..b75a760f8e 100644 --- a/src/app/shared/dso-selector/modal-wrappers/edit-community-parent-selector/edit-community-parent-selector.component.html +++ b/src/app/shared/dso-selector/modal-wrappers/edit-community-parent-selector/edit-community-parent-selector.component.html @@ -1,5 +1,9 @@
- + diff --git a/src/app/shared/dso-selector/modal-wrappers/edit-community-parent-selector/edit-community-parent-selector.component.ts b/src/app/shared/dso-selector/modal-wrappers/edit-community-parent-selector/edit-community-parent-selector.component.ts index e14845bfa4..8932be26ca 100644 --- a/src/app/shared/dso-selector/modal-wrappers/edit-community-parent-selector/edit-community-parent-selector.component.ts +++ b/src/app/shared/dso-selector/modal-wrappers/edit-community-parent-selector/edit-community-parent-selector.component.ts @@ -26,7 +26,12 @@ export class EditCommunityParentSelectorComponent implements OnInit { } editCommunity(dso: DSpaceObject) { - this.activeModal.close(); + this.close(); this.router.navigate([getCommunityEditPath(dso.uuid)]); } + + + close() { + this.activeModal.close(); + } } diff --git a/src/app/shared/dso-selector/modal-wrappers/edit-item-parent-selector/edit-item-parent-selector.component.html b/src/app/shared/dso-selector/modal-wrappers/edit-item-parent-selector/edit-item-parent-selector.component.html index 6bc59b96bd..a9c508e381 100644 --- a/src/app/shared/dso-selector/modal-wrappers/edit-item-parent-selector/edit-item-parent-selector.component.html +++ b/src/app/shared/dso-selector/modal-wrappers/edit-item-parent-selector/edit-item-parent-selector.component.html @@ -1,5 +1,9 @@
- + diff --git a/src/app/shared/dso-selector/modal-wrappers/edit-item-parent-selector/edit-item-parent-selector.component.ts b/src/app/shared/dso-selector/modal-wrappers/edit-item-parent-selector/edit-item-parent-selector.component.ts index 0a3963d6ae..f71e61a1fa 100644 --- a/src/app/shared/dso-selector/modal-wrappers/edit-item-parent-selector/edit-item-parent-selector.component.ts +++ b/src/app/shared/dso-selector/modal-wrappers/edit-item-parent-selector/edit-item-parent-selector.component.ts @@ -28,7 +28,11 @@ export class EditItemParentSelectorComponent implements OnInit { } editItem(dso: DSpaceObject) { - this.activeModal.close(); + this.close(); this.router.navigate([getItemEditPath(dso.uuid)]); } + + close() { + this.activeModal.close(); + } } From 9abbfa955e3cb6923646f04291089423703a554e Mon Sep 17 00:00:00 2001 From: lotte Date: Wed, 6 Mar 2019 17:03:43 +0100 Subject: [PATCH 05/17] refactored, started tests --- config/environment.default.js | 5 +- resources/i18n/en.json | 26 +++++++ .../admin-sidebar/admin-sidebar.component.ts | 12 +-- src/app/+search-page/search-page.module.ts | 14 ++-- .../dso-selector/dso-selector.component.html | 20 ++--- .../dso-selector.component.spec.ts | 65 +++++++++++++++++ .../dso-selector/dso-selector.component.ts | 73 ++++++++++--------- ...-collection-parent-selector.component.html | 11 --- ...te-collection-parent-selector.component.ts | 39 +++++----- ...e-community-parent-selector.component.html | 10 +-- ...ate-community-parent-selector.component.ts | 34 ++++----- ...create-item-parent-selector.component.html | 10 --- .../create-item-parent-selector.component.ts | 28 +++---- .../dso-selector-modal-wrapper.component.html | 10 +++ .../dso-selector-modal-wrapper.component.ts | 43 +++++++++++ ...-collection-parent-selector.component.html | 10 --- ...it-collection-parent-selector.component.ts | 37 ---------- .../edit-collection-selector.component.ts | 28 +++++++ ...t-community-parent-selector.component.html | 10 --- ...dit-community-parent-selector.component.ts | 37 ---------- .../edit-community-selector.component.ts | 29 ++++++++ .../edit-item-parent-selector.component.html | 10 --- ...ent.ts => edit-item-selector.component.ts} | 30 ++++---- src/app/shared/shared.module.ts | 27 ++++--- src/app/shared/testing/search-service-stub.ts | 4 + 25 files changed, 348 insertions(+), 274 deletions(-) create mode 100644 src/app/shared/dso-selector/dso-selector/dso-selector.component.spec.ts delete mode 100644 src/app/shared/dso-selector/modal-wrappers/create-collection-parent-selector/create-collection-parent-selector.component.html delete mode 100644 src/app/shared/dso-selector/modal-wrappers/create-item-parent-selector/create-item-parent-selector.component.html create mode 100644 src/app/shared/dso-selector/modal-wrappers/dso-selector-modal-wrapper.component.html create mode 100644 src/app/shared/dso-selector/modal-wrappers/dso-selector-modal-wrapper.component.ts delete mode 100644 src/app/shared/dso-selector/modal-wrappers/edit-collection-parent-selector/edit-collection-parent-selector.component.html delete mode 100644 src/app/shared/dso-selector/modal-wrappers/edit-collection-parent-selector/edit-collection-parent-selector.component.ts create mode 100644 src/app/shared/dso-selector/modal-wrappers/edit-collection-parent-selector/edit-collection-selector.component.ts delete mode 100644 src/app/shared/dso-selector/modal-wrappers/edit-community-parent-selector/edit-community-parent-selector.component.html delete mode 100644 src/app/shared/dso-selector/modal-wrappers/edit-community-parent-selector/edit-community-parent-selector.component.ts create mode 100644 src/app/shared/dso-selector/modal-wrappers/edit-community-parent-selector/edit-community-selector.component.ts delete mode 100644 src/app/shared/dso-selector/modal-wrappers/edit-item-parent-selector/edit-item-parent-selector.component.html rename src/app/shared/dso-selector/modal-wrappers/edit-item-parent-selector/{edit-item-parent-selector.component.ts => edit-item-selector.component.ts} (57%) diff --git a/config/environment.default.js b/config/environment.default.js index b493d0473a..b8eae1ccff 100644 --- a/config/environment.default.js +++ b/config/environment.default.js @@ -10,9 +10,10 @@ module.exports = { // The REST API server settings. rest: { ssl: true, - host: 'dspace7-internal.atmire.com', + host: 'dspace7.4science.it', port: 443, - nameSpace: '/rest/api' + // NOTE: Space is capitalized because 'namespace' is a reserved string in TypeScript + nameSpace: '/dspace-spring-rest/api' }, // Caching settings cache: { diff --git a/resources/i18n/en.json b/resources/i18n/en.json index 208e5415a8..38d90e67ea 100644 --- a/resources/i18n/en.json +++ b/resources/i18n/en.json @@ -642,5 +642,31 @@ }, "chips": { "remove": "Remove chip" + }, + "dso-selector": { + "create": { + "community": { + "head": "New community", + "sub-level": "Create a new community in", + "top-level": "Create a new top-level community" + }, + "collection": { + "head": "New collection" + }, + "item": { + "head": "New item" + } + }, + "edit": { + "community": { + "head": "Edit community" + }, + "collection": { + "head": "Edit collection" + }, + "item": { + "head": "Edit item" + } + } } } diff --git a/src/app/+admin/admin-sidebar/admin-sidebar.component.ts b/src/app/+admin/admin-sidebar/admin-sidebar.component.ts index 8b71bca423..e429b57bae 100644 --- a/src/app/+admin/admin-sidebar/admin-sidebar.component.ts +++ b/src/app/+admin/admin-sidebar/admin-sidebar.component.ts @@ -15,9 +15,9 @@ import { OnClickMenuItemModel } from '../../shared/menu/menu-item/models/onclick import { CreateCommunityParentSelectorComponent } from '../../shared/dso-selector/modal-wrappers/create-community-parent-selector/create-community-parent-selector.component'; import { CreateItemParentSelectorComponent } from '../../shared/dso-selector/modal-wrappers/create-item-parent-selector/create-item-parent-selector.component'; import { CreateCollectionParentSelectorComponent } from '../../shared/dso-selector/modal-wrappers/create-collection-parent-selector/create-collection-parent-selector.component'; -import { EditCollectionParentSelectorComponent } from '../../shared/dso-selector/modal-wrappers/edit-collection-parent-selector/edit-collection-parent-selector.component'; -import { EditItemParentSelectorComponent } from '../../shared/dso-selector/modal-wrappers/edit-item-parent-selector/edit-item-parent-selector.component'; -import { EditCommunityParentSelectorComponent } from '../../shared/dso-selector/modal-wrappers/edit-community-parent-selector/edit-community-parent-selector.component'; +import { EditItemSelectorComponent } from '../../shared/dso-selector/modal-wrappers/edit-item-parent-selector/edit-item-selector.component'; +import { EditCommunitySelectorComponent } from '../../shared/dso-selector/modal-wrappers/edit-community-parent-selector/edit-community-selector.component'; +import { EditCollectionSelectorComponent } from '../../shared/dso-selector/modal-wrappers/edit-collection-parent-selector/edit-collection-selector.component'; /** * Component representing the admin sidebar @@ -179,7 +179,7 @@ export class AdminSidebarComponent extends MenuComponent implements OnInit { type: MenuItemType.ONCLICK, text: 'menu.section.edit_community', function: () => { - this.modalService.open(EditCommunityParentSelectorComponent); + this.modalService.open(EditCommunitySelectorComponent); } } as OnClickMenuItemModel, }, @@ -192,7 +192,7 @@ export class AdminSidebarComponent extends MenuComponent implements OnInit { type: MenuItemType.ONCLICK, text: 'menu.section.edit_collection', function: () => { - this.modalService.open(EditCollectionParentSelectorComponent); + this.modalService.open(EditCollectionSelectorComponent); } } as OnClickMenuItemModel, }, @@ -205,7 +205,7 @@ export class AdminSidebarComponent extends MenuComponent implements OnInit { type: MenuItemType.ONCLICK, text: 'menu.section.edit_item', function: () => { - this.modalService.open(EditItemParentSelectorComponent); + this.modalService.open(EditItemSelectorComponent); } } as OnClickMenuItemModel, }, diff --git a/src/app/+search-page/search-page.module.ts b/src/app/+search-page/search-page.module.ts index 5fa1fadfae..4cd0c9428b 100644 --- a/src/app/+search-page/search-page.module.ts +++ b/src/app/+search-page/search-page.module.ts @@ -11,7 +11,6 @@ import { CommunitySearchResultListElementComponent } from '../shared/object-list 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'; @@ -46,13 +45,12 @@ const effects = [ SearchResultsComponent, SearchSidebarComponent, SearchSettingsComponent, - ItemSearchResultListElementComponent, - CollectionSearchResultListElementComponent, - CommunitySearchResultListElementComponent, + // ItemSearchResultListElementComponent, + // CollectionSearchResultListElementComponent, + // CommunitySearchResultListElementComponent, ItemSearchResultGridElementComponent, CollectionSearchResultGridElementComponent, CommunitySearchResultGridElementComponent, - CommunitySearchResultListElementComponent, SearchFiltersComponent, SearchFilterComponent, SearchFacetFilterComponent, @@ -70,9 +68,9 @@ const effects = [ SearchConfigurationService ], entryComponents: [ - ItemSearchResultListElementComponent, - CollectionSearchResultListElementComponent, - CommunitySearchResultListElementComponent, + // ItemSearchResultListElementComponent, + // CollectionSearchResultListElementComponent, + // CommunitySearchResultListElementComponent, ItemSearchResultGridElementComponent, CollectionSearchResultGridElementComponent, CommunitySearchResultGridElementComponent, diff --git a/src/app/shared/dso-selector/dso-selector/dso-selector.component.html b/src/app/shared/dso-selector/dso-selector/dso-selector.component.html index ceaefc2ac9..bc520bfe3b 100644 --- a/src/app/shared/dso-selector/dso-selector/dso-selector.component.html +++ b/src/app/shared/dso-selector/dso-selector/dso-selector.component.html @@ -6,20 +6,14 @@ [formControl]="input">
-
- -
\ No newline at end of file diff --git a/src/app/shared/dso-selector/dso-selector/dso-selector.component.spec.ts b/src/app/shared/dso-selector/dso-selector/dso-selector.component.spec.ts new file mode 100644 index 0000000000..38067f3dc0 --- /dev/null +++ b/src/app/shared/dso-selector/dso-selector/dso-selector.component.spec.ts @@ -0,0 +1,65 @@ +import { async, ComponentFixture, TestBed } from '@angular/core/testing'; +import { TranslateModule } from '@ngx-translate/core'; +import { DebugElement, NO_ERRORS_SCHEMA } from '@angular/core'; +import { DSOSelectorComponent } from './dso-selector.component'; +import { SearchService } from '../../../+search-page/search-service/search.service'; +import { DSpaceObjectType } from '../../../core/shared/dspace-object-type.model'; +import { PaginatedSearchOptions } from '../../../+search-page/paginated-search-options.model'; +import { RemoteData } from '../../../core/data/remote-data'; +import { ItemSearchResult } from '../../object-collection/shared/item-search-result.model'; +import { Item } from '../../../core/shared/item.model'; +import { of as observableOf } from 'rxjs'; +import { PaginatedList } from '../../../core/data/paginated-list'; + +fdescribe('DSOSelectorComponent', () => { + let component: DSOSelectorComponent; + let fixture: ComponentFixture; + let debugElement: DebugElement; + + const currentDSOId = 'test-uuid-ford-sose'; + const type = DSpaceObjectType.ITEM; + const searchResult = new ItemSearchResult(); + const item = new Item(); + item.metadata = { 'dc.title': [{ value: 'Item title', language: undefined }] }; + searchResult.dspaceObject = item; + searchResult.hitHighlights = {}; + const searchService = jasmine.createSpyObj('searchService', { + search: observableOf(new RemoteData(false, false, true, undefined, new PaginatedList(undefined, [searchResult]))) + }); + + beforeEach(async(() => { + TestBed.configureTestingModule({ + imports: [TranslateModule.forRoot()], + declarations: [DSOSelectorComponent], + providers: [ + { provide: SearchService, useValue: searchService }, + ], + schemas: [NO_ERRORS_SCHEMA] + }) + .compileComponents(); + + })); + + beforeEach(() => { + fixture = TestBed.createComponent(DSOSelectorComponent); + component = fixture.componentInstance; + debugElement = fixture.debugElement; + component.currentDSOId = currentDSOId; + component.type = type; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); + + it('should initially call the search method on the SearchService with the given DSO uuid', () => { + const searchOptions = new PaginatedSearchOptions({ + query: currentDSOId, + dsoType: type, + pagination: (component as any).defaultPagination + }); + expect(searchService.search).toHaveBeenCalledWith(searchOptions); + }); + +}); diff --git a/src/app/shared/dso-selector/dso-selector/dso-selector.component.ts b/src/app/shared/dso-selector/dso-selector/dso-selector.component.ts index 6eb5716489..f3164a37e2 100644 --- a/src/app/shared/dso-selector/dso-selector/dso-selector.component.ts +++ b/src/app/shared/dso-selector/dso-selector/dso-selector.component.ts @@ -21,32 +21,60 @@ import { PaginatedList } from '../../../core/data/paginated-list'; import { SearchResult } from '../../../+search-page/search-result.model'; import { DSpaceObject } from '../../../core/shared/dspace-object.model'; -interface DSOSelectListEntry { - parents: DSpaceObject[], - dso: DSpaceObject -} - @Component({ selector: 'ds-dso-selector', // styleUrls: ['./dso-selector.component.scss'], templateUrl: './dso-selector.component.html' }) + +/** + * Component to render a list of DSO's of which one can be selected + * The user can search the list by using the input field + */ export class DSOSelectorComponent implements OnInit, AfterViewInit { + + /** + * The initially selected DSO's uuid + */ @Input() currentDSOId: string; + + /** + * The type of DSpace objects this components shows a list of + */ @Input() type: DSpaceObjectType; + /** + * Emits the selected Object when a user selects it in the list + */ @Output() onSelect: EventEmitter = new EventEmitter(); + /** + * Input form control to query the list + */ public input: FormControl = new FormControl(); - // private subs: Subscription[] = []; + + /** + * Default pagination for this feature + */ private defaultPagination = { id: 'dso-selector', currentPage: 1, pageSize: 5 } as any; - listEntries$: Observable; + + /** + * List with search results of DSpace objects for the current query + */ + listEntries$: Observable>>>; + + /** + * List of element references to all elements + */ @ViewChildren('listEntryElement') listElements: QueryList; constructor(private searchService: SearchService) { - } + /** + * Fills the listEntries$ variable with search results based on the input field's current value + * The search will always start with the initial currentDSOId value + */ ngOnInit(): void { this.listEntries$ = this.input.valueChanges .pipe( @@ -60,21 +88,13 @@ export class DSOSelectorComponent implements OnInit, AfterViewInit { }) ) } - ), - map((searchResultsRD: RemoteData>>) => { - return searchResultsRD.payload.page.map( - (searchResult: SearchResult) => { - let dso = searchResult.dspaceObject; - return { - parents: this.retrieveParentList(dso), - dso - } as DSOSelectListEntry - } - ) - }) + ) ) } + /** + * Make sure to set focus on the first list element when the initial search (with currentDSOId) emits a single value + */ ngAfterViewInit(): void { this.listElements.changes.pipe( take(1) @@ -84,17 +104,4 @@ export class DSOSelectorComponent implements OnInit, AfterViewInit { } }); } - - retrieveParentList(dso: DSpaceObject, parents: DSpaceObject[] = []) { - return [{ name: 'Test Community' } as any]; - // if (hasValue(dso.owner)) { - // dso.owner.pipe( - // first(), - // ).subscribe((parentRD) => { - // const newDSO: DSpaceObject = parentRD.payload; - // parents = [...this.retrieveParentList(newDSO, parents), newDSO]; - // }); - // } - // return parents; - } } diff --git a/src/app/shared/dso-selector/modal-wrappers/create-collection-parent-selector/create-collection-parent-selector.component.html b/src/app/shared/dso-selector/modal-wrappers/create-collection-parent-selector/create-collection-parent-selector.component.html deleted file mode 100644 index 16fd37928f..0000000000 --- a/src/app/shared/dso-selector/modal-wrappers/create-collection-parent-selector/create-collection-parent-selector.component.html +++ /dev/null @@ -1,11 +0,0 @@ -
- - -
\ No newline at end of file diff --git a/src/app/shared/dso-selector/modal-wrappers/create-collection-parent-selector/create-collection-parent-selector.component.ts b/src/app/shared/dso-selector/modal-wrappers/create-collection-parent-selector/create-collection-parent-selector.component.ts index c4bff22c7b..631480c04d 100644 --- a/src/app/shared/dso-selector/modal-wrappers/create-collection-parent-selector/create-collection-parent-selector.component.ts +++ b/src/app/shared/dso-selector/modal-wrappers/create-collection-parent-selector/create-collection-parent-selector.component.ts @@ -5,39 +5,34 @@ import { RemoteData } from '../../../../core/data/remote-data'; import { DSpaceObjectType } from '../../../../core/shared/dspace-object-type.model'; import { DSpaceObject } from '../../../../core/shared/dspace-object.model'; import { NgbActiveModal } from '@ng-bootstrap/ng-bootstrap'; -import { map } from 'rxjs/operators'; -import { Observable } from 'rxjs'; -import { COLLECTION_PARENT_PARAMETER } from '../../../../+collection-page/collection-page-routing.module'; +import { + COLLECTION_PARENT_PARAMETER, + getCollectionCreatePath +} from '../../../../+collection-page/collection-page-routing.module'; +import { + DSOSelectorModalWrapperComponent, + SelectorActionType +} from '../dso-selector-modal-wrapper.component'; @Component({ selector: 'ds-create-collection-parent-selector', - // styleUrls: ['./create-collection-parent-selector.component.scss'], - templateUrl: './create-collection-parent-selector.component.html', + templateUrl: '../dso-selector-modal-wrapper.component.html', }) -export class CreateCollectionParentSelectorComponent implements OnInit { - @Input() communityRD$: Observable>; - type = DSpaceObjectType.COMMUNITY; +export class CreateCollectionParentSelectorComponent extends DSOSelectorModalWrapperComponent implements OnInit { + objectType = DSpaceObjectType.COLLECTION; + selectorType = DSpaceObjectType.COMMUNITY; + action = SelectorActionType.CREATE; - private createPath = '/collections/create'; - - constructor(private activeModal: NgbActiveModal, private route: ActivatedRoute, private router: Router) { + constructor(protected activeModal: NgbActiveModal, protected route: ActivatedRoute, private router: Router) { + super(activeModal, route); } - ngOnInit(): void { - this.communityRD$ = this.route.root.firstChild.firstChild.data.pipe(map(data => data.community)); - } - - createCollection(dso: DSpaceObject) { - this.close(); + navigate(dso: DSpaceObject) { let navigationExtras: NavigationExtras = { queryParams: { [COLLECTION_PARENT_PARAMETER]: dso.uuid, } }; - this.router.navigate([this.createPath], navigationExtras); - } - - close() { - this.activeModal.close(); + this.router.navigate([getCollectionCreatePath()], navigationExtras); } } diff --git a/src/app/shared/dso-selector/modal-wrappers/create-community-parent-selector/create-community-parent-selector.component.html b/src/app/shared/dso-selector/modal-wrappers/create-community-parent-selector/create-community-parent-selector.component.html index a50f1a57c6..e6a0db3b62 100644 --- a/src/app/shared/dso-selector/modal-wrappers/create-community-parent-selector/create-community-parent-selector.component.html +++ b/src/app/shared/dso-selector/modal-wrappers/create-community-parent-selector/create-community-parent-selector.component.html @@ -1,19 +1,19 @@
- \ No newline at end of file diff --git a/src/app/shared/dso-selector/modal-wrappers/create-community-parent-selector/create-community-parent-selector.component.ts b/src/app/shared/dso-selector/modal-wrappers/create-community-parent-selector/create-community-parent-selector.component.ts index 017f933d1f..c3d112a455 100644 --- a/src/app/shared/dso-selector/modal-wrappers/create-community-parent-selector/create-community-parent-selector.component.ts +++ b/src/app/shared/dso-selector/modal-wrappers/create-community-parent-selector/create-community-parent-selector.component.ts @@ -8,28 +8,30 @@ import { hasValue } from '../../../empty.util'; import { NgbActiveModal } from '@ng-bootstrap/ng-bootstrap'; import { map } from 'rxjs/operators'; import { Observable } from 'rxjs'; -import { COMMUNITY_PARENT_PARAMETER } from '../../../../+community-page/community-page-routing.module'; +import { + COMMUNITY_PARENT_PARAMETER, + getCommunityCreatePath +} from '../../../../+community-page/community-page-routing.module'; +import { + DSOSelectorModalWrapperComponent, + SelectorActionType +} from '../dso-selector-modal-wrapper.component'; @Component({ selector: 'ds-create-community-parent-selector', styleUrls: ['./create-community-parent-selector.component.scss'], templateUrl: './create-community-parent-selector.component.html', }) -export class CreateCommunityParentSelectorComponent implements OnInit { - @Input() communityRD$: Observable>; - type = DSpaceObjectType.COMMUNITY; +export class CreateCommunityParentSelectorComponent extends DSOSelectorModalWrapperComponent implements OnInit { + objectType = DSpaceObjectType.COMMUNITY; + selectorType = DSpaceObjectType.COMMUNITY; + action = SelectorActionType.CREATE; - private createPath = '/communities/create'; - - constructor(private activeModal: NgbActiveModal, private route: ActivatedRoute, private router: Router) { + constructor(protected activeModal: NgbActiveModal, protected route: ActivatedRoute, private router: Router) { + super(activeModal, route); } - ngOnInit(): void { - this.communityRD$ = this.route.root.firstChild.firstChild.data.pipe(map(data => data.community)); - } - - createCommunity(dso?: DSpaceObject) { - this.close(); + navigate(dso: DSpaceObject) { let navigationExtras: NavigationExtras = {}; if (hasValue(dso)) { navigationExtras = { @@ -38,10 +40,6 @@ export class CreateCommunityParentSelectorComponent implements OnInit { } }; } - this.router.navigate([this.createPath], navigationExtras); - } - - close() { - this.activeModal.close(); + this.router.navigate([getCommunityCreatePath()], navigationExtras); } } diff --git a/src/app/shared/dso-selector/modal-wrappers/create-item-parent-selector/create-item-parent-selector.component.html b/src/app/shared/dso-selector/modal-wrappers/create-item-parent-selector/create-item-parent-selector.component.html deleted file mode 100644 index 1009867056..0000000000 --- a/src/app/shared/dso-selector/modal-wrappers/create-item-parent-selector/create-item-parent-selector.component.html +++ /dev/null @@ -1,10 +0,0 @@ -
- - -
\ No newline at end of file diff --git a/src/app/shared/dso-selector/modal-wrappers/create-item-parent-selector/create-item-parent-selector.component.ts b/src/app/shared/dso-selector/modal-wrappers/create-item-parent-selector/create-item-parent-selector.component.ts index 44a8d67d04..dac79dddcb 100644 --- a/src/app/shared/dso-selector/modal-wrappers/create-item-parent-selector/create-item-parent-selector.component.ts +++ b/src/app/shared/dso-selector/modal-wrappers/create-item-parent-selector/create-item-parent-selector.component.ts @@ -9,32 +9,28 @@ import { hasValue } from '../../../empty.util'; import { NgbActiveModal } from '@ng-bootstrap/ng-bootstrap'; import { map } from 'rxjs/operators'; import { Observable } from 'rxjs'; +import { + DSOSelectorModalWrapperComponent, + SelectorActionType +} from '../dso-selector-modal-wrapper.component'; @Component({ selector: 'ds-create-item-parent-selector', // styleUrls: ['./create-item-parent-selector.component.scss'], - templateUrl: './create-item-parent-selector.component.html', + templateUrl: '../dso-selector-modal-wrapper.component.html', }) -export class CreateItemParentSelectorComponent implements OnInit { - @Input() collectionRD$: Observable>; - type = DSpaceObjectType.COLLECTION; +export class CreateItemParentSelectorComponent extends DSOSelectorModalWrapperComponent implements OnInit { + objectType = DSpaceObjectType.ITEM; + selectorType = DSpaceObjectType.COLLECTION; + action = SelectorActionType.CREATE; - constructor(private activeModal: NgbActiveModal, private route: ActivatedRoute) { + constructor(protected activeModal: NgbActiveModal, protected route: ActivatedRoute, private router: Router) { + super(activeModal, route); } - ngOnInit(): void { - this.collectionRD$ = this.route.root.firstChild.firstChild.data.pipe(map(data => data.collection)); - } - - createItem(dso: DSpaceObject) { - this.close(); - + navigate(dso: DSpaceObject) { let path; // path = this.createPath; // this.router.navigate([path]); } - - close() { - this.activeModal.close(); - } } diff --git a/src/app/shared/dso-selector/modal-wrappers/dso-selector-modal-wrapper.component.html b/src/app/shared/dso-selector/modal-wrappers/dso-selector-modal-wrapper.component.html new file mode 100644 index 0000000000..88f4a6f917 --- /dev/null +++ b/src/app/shared/dso-selector/modal-wrappers/dso-selector-modal-wrapper.component.html @@ -0,0 +1,10 @@ +
+ + +
\ No newline at end of file diff --git a/src/app/shared/dso-selector/modal-wrappers/dso-selector-modal-wrapper.component.ts b/src/app/shared/dso-selector/modal-wrappers/dso-selector-modal-wrapper.component.ts new file mode 100644 index 0000000000..3d053e9dcb --- /dev/null +++ b/src/app/shared/dso-selector/modal-wrappers/dso-selector-modal-wrapper.component.ts @@ -0,0 +1,43 @@ +import { Component, Input, OnInit } from '@angular/core'; +import { ActivatedRoute } from '@angular/router'; +import { Observable } from 'rxjs'; +import { DSpaceObject } from '../../../core/shared/dspace-object.model'; +import { RemoteData } from '../../../core/data/remote-data'; +import { NgbActiveModal } from '@ng-bootstrap/ng-bootstrap'; +import { map } from 'rxjs/operators'; +import { DSpaceObjectType } from '../../../core/shared/dspace-object-type.model'; + +export enum SelectorActionType { + CREATE = 'create', + EDIT = 'edit' +}; + +@Component({ + selector: 'ds-dso-selector-modal-wrapper', + templateUrl: './dso-selector-modal-wrapper.component.html', +}) +export abstract class DSOSelectorModalWrapperComponent implements OnInit { + @Input() dsoRD$: Observable>; + objectType: DSpaceObjectType; + selectorType: DSpaceObjectType; + action: SelectorActionType; + + constructor(protected activeModal: NgbActiveModal, protected route: ActivatedRoute) { + } + + ngOnInit(): void { + const typeString = this.selectorType.toString().toLowerCase(); + this.dsoRD$ = this.route.root.firstChild.firstChild.data.pipe(map(data => data[typeString])); + } + + selectObject(dso: DSpaceObject) { + this.close(); + this.navigate(dso); + } + + abstract navigate(dso: DSpaceObject); + + close() { + this.activeModal.close(); + } +} diff --git a/src/app/shared/dso-selector/modal-wrappers/edit-collection-parent-selector/edit-collection-parent-selector.component.html b/src/app/shared/dso-selector/modal-wrappers/edit-collection-parent-selector/edit-collection-parent-selector.component.html deleted file mode 100644 index 9d050ef2fc..0000000000 --- a/src/app/shared/dso-selector/modal-wrappers/edit-collection-parent-selector/edit-collection-parent-selector.component.html +++ /dev/null @@ -1,10 +0,0 @@ -
- - -
\ No newline at end of file diff --git a/src/app/shared/dso-selector/modal-wrappers/edit-collection-parent-selector/edit-collection-parent-selector.component.ts b/src/app/shared/dso-selector/modal-wrappers/edit-collection-parent-selector/edit-collection-parent-selector.component.ts deleted file mode 100644 index 11e1c47f55..0000000000 --- a/src/app/shared/dso-selector/modal-wrappers/edit-collection-parent-selector/edit-collection-parent-selector.component.ts +++ /dev/null @@ -1,37 +0,0 @@ -import { Component, Input, OnInit } from '@angular/core'; -import { ActivatedRoute, NavigationExtras, Router } from '@angular/router'; -import { Community } from '../../../../core/shared/community.model'; -import { RemoteData } from '../../../../core/data/remote-data'; -import { DSpaceObjectType } from '../../../../core/shared/dspace-object-type.model'; -import { DSpaceObject } from '../../../../core/shared/dspace-object.model'; -import { NgbActiveModal } from '@ng-bootstrap/ng-bootstrap'; -import { Collection } from '../../../../core/shared/collection.model'; -import { Observable } from 'rxjs'; -import { map } from 'rxjs/operators'; -import { getCollectionEditPath } from '../../../../+collection-page/collection-page-routing.module'; - -@Component({ - selector: 'ds-edit-collection-parent-selector', - // styleUrls: ['./edit-collection-parent-selector.component.scss'], - templateUrl: './edit-collection-parent-selector.component.html', -}) -export class EditCollectionParentSelectorComponent implements OnInit { - @Input() collectionRD$: Observable>; - type = DSpaceObjectType.COLLECTION; - - constructor(private activeModal: NgbActiveModal, private route: ActivatedRoute, private router: Router) { - } - - ngOnInit(): void { - this.collectionRD$ = this.route.root.firstChild.firstChild.data.pipe(map(data => data.collection)); - } - - editCollection(dso: DSpaceObject) { - this.close(); - this.router.navigate([getCollectionEditPath(dso.uuid)]); - } - - close() { - this.activeModal.close(); - } -} diff --git a/src/app/shared/dso-selector/modal-wrappers/edit-collection-parent-selector/edit-collection-selector.component.ts b/src/app/shared/dso-selector/modal-wrappers/edit-collection-parent-selector/edit-collection-selector.component.ts new file mode 100644 index 0000000000..edf3f37f6e --- /dev/null +++ b/src/app/shared/dso-selector/modal-wrappers/edit-collection-parent-selector/edit-collection-selector.component.ts @@ -0,0 +1,28 @@ +import { Component, OnInit } from '@angular/core'; +import { ActivatedRoute, Router } from '@angular/router'; +import { DSpaceObjectType } from '../../../../core/shared/dspace-object-type.model'; +import { DSpaceObject } from '../../../../core/shared/dspace-object.model'; +import { NgbActiveModal } from '@ng-bootstrap/ng-bootstrap'; +import { getCollectionEditPath } from '../../../../+collection-page/collection-page-routing.module'; +import { + DSOSelectorModalWrapperComponent, + SelectorActionType +} from '../dso-selector-modal-wrapper.component'; + +@Component({ + selector: 'ds-edit-collection-selector', + templateUrl: '../dso-selector-modal-wrapper.component.html', +}) +export class EditCollectionSelectorComponent extends DSOSelectorModalWrapperComponent implements OnInit { + objectType = DSpaceObjectType.COLLECTION; + selectorType = DSpaceObjectType.COLLECTION; + action = SelectorActionType.EDIT; + + constructor(protected activeModal: NgbActiveModal, protected route: ActivatedRoute, private router: Router) { + super(activeModal, route); + } + + navigate(dso: DSpaceObject) { + this.router.navigate([getCollectionEditPath(dso.uuid)]); + } +} diff --git a/src/app/shared/dso-selector/modal-wrappers/edit-community-parent-selector/edit-community-parent-selector.component.html b/src/app/shared/dso-selector/modal-wrappers/edit-community-parent-selector/edit-community-parent-selector.component.html deleted file mode 100644 index b75a760f8e..0000000000 --- a/src/app/shared/dso-selector/modal-wrappers/edit-community-parent-selector/edit-community-parent-selector.component.html +++ /dev/null @@ -1,10 +0,0 @@ -
- - -
\ No newline at end of file diff --git a/src/app/shared/dso-selector/modal-wrappers/edit-community-parent-selector/edit-community-parent-selector.component.ts b/src/app/shared/dso-selector/modal-wrappers/edit-community-parent-selector/edit-community-parent-selector.component.ts deleted file mode 100644 index 8932be26ca..0000000000 --- a/src/app/shared/dso-selector/modal-wrappers/edit-community-parent-selector/edit-community-parent-selector.component.ts +++ /dev/null @@ -1,37 +0,0 @@ -import { Component, Input, OnInit } from '@angular/core'; -import { ActivatedRoute, Router } from '@angular/router'; -import { Community } from '../../../../core/shared/community.model'; -import { RemoteData } from '../../../../core/data/remote-data'; -import { DSpaceObjectType } from '../../../../core/shared/dspace-object-type.model'; -import { DSpaceObject } from '../../../../core/shared/dspace-object.model'; -import { NgbActiveModal } from '@ng-bootstrap/ng-bootstrap'; -import { Observable } from 'rxjs'; -import { map } from 'rxjs/operators'; -import { getCommunityEditPath } from '../../../../+community-page/community-page-routing.module'; - -@Component({ - selector: 'ds-edit-community-parent-selector', - // styleUrls: ['./edit-community-parent-selector.component.scss'], - templateUrl: './edit-community-parent-selector.component.html', -}) -export class EditCommunityParentSelectorComponent implements OnInit { - @Input() communityRD$: Observable>; - type = DSpaceObjectType.COMMUNITY; - - constructor(private activeModal: NgbActiveModal, private route: ActivatedRoute, private router: Router) { - } - - ngOnInit(): void { - this.communityRD$ = this.route.root.firstChild.firstChild.data.pipe(map(data => data.collection)); - } - - editCommunity(dso: DSpaceObject) { - this.close(); - this.router.navigate([getCommunityEditPath(dso.uuid)]); - } - - - close() { - this.activeModal.close(); - } -} diff --git a/src/app/shared/dso-selector/modal-wrappers/edit-community-parent-selector/edit-community-selector.component.ts b/src/app/shared/dso-selector/modal-wrappers/edit-community-parent-selector/edit-community-selector.component.ts new file mode 100644 index 0000000000..9af974782a --- /dev/null +++ b/src/app/shared/dso-selector/modal-wrappers/edit-community-parent-selector/edit-community-selector.component.ts @@ -0,0 +1,29 @@ +import { Component, OnInit } from '@angular/core'; +import { ActivatedRoute, Router } from '@angular/router'; +import { DSpaceObjectType } from '../../../../core/shared/dspace-object-type.model'; +import { DSpaceObject } from '../../../../core/shared/dspace-object.model'; +import { NgbActiveModal } from '@ng-bootstrap/ng-bootstrap'; +import { getCommunityEditPath } from '../../../../+community-page/community-page-routing.module'; +import { + DSOSelectorModalWrapperComponent, + SelectorActionType +} from '../dso-selector-modal-wrapper.component'; + +@Component({ + selector: 'ds-edit-community-selector', + templateUrl: '../dso-selector-modal-wrapper.component.html', +}) + +export class EditCommunitySelectorComponent extends DSOSelectorModalWrapperComponent implements OnInit { + objectType = DSpaceObjectType.COMMUNITY; + selectorType = DSpaceObjectType.COMMUNITY; + action = SelectorActionType.EDIT; + + constructor(protected activeModal: NgbActiveModal, protected route: ActivatedRoute, private router: Router) { + super(activeModal, route); + } + + navigate(dso: DSpaceObject) { + this.router.navigate([getCommunityEditPath(dso.uuid)]); + } +} diff --git a/src/app/shared/dso-selector/modal-wrappers/edit-item-parent-selector/edit-item-parent-selector.component.html b/src/app/shared/dso-selector/modal-wrappers/edit-item-parent-selector/edit-item-parent-selector.component.html deleted file mode 100644 index a9c508e381..0000000000 --- a/src/app/shared/dso-selector/modal-wrappers/edit-item-parent-selector/edit-item-parent-selector.component.html +++ /dev/null @@ -1,10 +0,0 @@ -
- - -
\ No newline at end of file diff --git a/src/app/shared/dso-selector/modal-wrappers/edit-item-parent-selector/edit-item-parent-selector.component.ts b/src/app/shared/dso-selector/modal-wrappers/edit-item-parent-selector/edit-item-selector.component.ts similarity index 57% rename from src/app/shared/dso-selector/modal-wrappers/edit-item-parent-selector/edit-item-parent-selector.component.ts rename to src/app/shared/dso-selector/modal-wrappers/edit-item-parent-selector/edit-item-selector.component.ts index f71e61a1fa..ff6ab35bf3 100644 --- a/src/app/shared/dso-selector/modal-wrappers/edit-item-parent-selector/edit-item-parent-selector.component.ts +++ b/src/app/shared/dso-selector/modal-wrappers/edit-item-parent-selector/edit-item-selector.component.ts @@ -10,29 +10,25 @@ import { Observable } from 'rxjs'; import { map } from 'rxjs/operators'; import { Item } from '../../../../core/shared/item.model'; import { getItemEditPath } from '../../../../+item-page/item-page-routing.module'; +import { + DSOSelectorModalWrapperComponent, + SelectorActionType +} from '../dso-selector-modal-wrapper.component'; @Component({ - selector: 'ds-edit-item-parent-selector', - // styleUrls: ['./edit-item-parent-selector.component.scss'], - templateUrl: './edit-item-parent-selector.component.html', + selector: 'ds-edit-item-selector', + templateUrl: '../dso-selector-modal-wrapper.component.html', }) -export class EditItemParentSelectorComponent implements OnInit { - @Input() itemRD$: Observable>; - type = DSpaceObjectType.ITEM; +export class EditItemSelectorComponent extends DSOSelectorModalWrapperComponent implements OnInit { + objectType = DSpaceObjectType.ITEM; + selectorType = DSpaceObjectType.ITEM; + action = SelectorActionType.EDIT; - constructor(private activeModal: NgbActiveModal, private route: ActivatedRoute, private router: Router) { + constructor(protected activeModal: NgbActiveModal, protected route: ActivatedRoute, private router: Router) { + super(activeModal, route); } - ngOnInit(): void { - this.itemRD$ = this.route.root.firstChild.firstChild.data.pipe(map(data => data.item)); - } - - editItem(dso: DSpaceObject) { - this.close(); + navigate(dso: DSpaceObject) { this.router.navigate([getItemEditPath(dso.uuid)]); } - - close() { - this.activeModal.close(); - } } diff --git a/src/app/shared/shared.module.ts b/src/app/shared/shared.module.ts index 3ee20d435d..5d87148a73 100644 --- a/src/app/shared/shared.module.ts +++ b/src/app/shared/shared.module.ts @@ -99,9 +99,12 @@ import { DSOSelectorComponent } from './dso-selector/dso-selector/dso-selector.c import { CreateCommunityParentSelectorComponent } from './dso-selector/modal-wrappers/create-community-parent-selector/create-community-parent-selector.component'; import { CreateItemParentSelectorComponent } from './dso-selector/modal-wrappers/create-item-parent-selector/create-item-parent-selector.component'; import { CreateCollectionParentSelectorComponent } from './dso-selector/modal-wrappers/create-collection-parent-selector/create-collection-parent-selector.component'; -import { EditCollectionParentSelectorComponent } from './dso-selector/modal-wrappers/edit-collection-parent-selector/edit-collection-parent-selector.component'; -import { EditItemParentSelectorComponent } from './dso-selector/modal-wrappers/edit-item-parent-selector/edit-item-parent-selector.component'; -import { EditCommunityParentSelectorComponent } from './dso-selector/modal-wrappers/edit-community-parent-selector/edit-community-parent-selector.component'; +import { CommunitySearchResultListElementComponent } from './object-list/search-result-list-element/community-search-result/community-search-result-list-element.component'; +import { CollectionSearchResultListElementComponent } from './object-list/search-result-list-element/collection-search-result/collection-search-result-list-element.component'; +import { ItemSearchResultListElementComponent } from './object-list/search-result-list-element/item-search-result/item-search-result-list-element.component'; +import { EditItemSelectorComponent } from './dso-selector/modal-wrappers/edit-item-parent-selector/edit-item-selector.component'; +import { EditCommunitySelectorComponent } from './dso-selector/modal-wrappers/edit-community-parent-selector/edit-community-selector.component'; +import { EditCollectionSelectorComponent } from './dso-selector/modal-wrappers/edit-collection-parent-selector/edit-collection-selector.component'; const MODULES = [ // Do NOT include UniversalModule, HttpModule, or JsonpModule here @@ -188,9 +191,12 @@ const COMPONENTS = [ CreateCommunityParentSelectorComponent, CreateCollectionParentSelectorComponent, CreateItemParentSelectorComponent, - EditCommunityParentSelectorComponent, - EditCollectionParentSelectorComponent, - EditItemParentSelectorComponent, + EditCommunitySelectorComponent, + EditCollectionSelectorComponent, + EditItemSelectorComponent, + CommunitySearchResultListElementComponent, + CollectionSearchResultListElementComponent, + ItemSearchResultListElementComponent, ]; const ENTRY_COMPONENTS = [ @@ -199,6 +205,9 @@ const ENTRY_COMPONENTS = [ CollectionListElementComponent, CommunityListElementComponent, SearchResultListElementComponent, + CommunitySearchResultListElementComponent, + CollectionSearchResultListElementComponent, + ItemSearchResultListElementComponent, ItemGridElementComponent, CollectionGridElementComponent, CommunityGridElementComponent, @@ -208,9 +217,9 @@ const ENTRY_COMPONENTS = [ CreateCommunityParentSelectorComponent, CreateCollectionParentSelectorComponent, CreateItemParentSelectorComponent, - EditCommunityParentSelectorComponent, - EditCollectionParentSelectorComponent, - EditItemParentSelectorComponent, + EditCommunitySelectorComponent, + EditCollectionSelectorComponent, + EditItemSelectorComponent, ]; const PROVIDERS = [ diff --git a/src/app/shared/testing/search-service-stub.ts b/src/app/shared/testing/search-service-stub.ts index cbc0611a47..2a46e42ef5 100644 --- a/src/app/shared/testing/search-service-stub.ts +++ b/src/app/shared/testing/search-service-stub.ts @@ -40,4 +40,8 @@ export class SearchServiceStub { getFilterLabels() { return observableOf([]); } + + search() { + return observableOf({}); + } } From 31d24284fb7551e8f9aa2eb15d1c0024c491ea8d Mon Sep 17 00:00:00 2001 From: lotte Date: Thu, 7 Mar 2019 14:17:49 +0100 Subject: [PATCH 06/17] added tests for popups --- .../admin-sidebar.component.spec.ts | 29 +++- .../admin-sidebar/admin-sidebar.component.ts | 6 +- .../dso-selector.component.spec.ts | 5 +- ...llection-parent-selector.component.spec.ts | 65 +++++++++ ...ommunity-parent-selector.component.spec.ts | 65 +++++++++ ...ate-community-parent-selector.component.ts | 6 +- ...ate-item-parent-selector.component.spec.ts | 65 +++++++++ .../create-item-parent-selector.component.ts | 4 +- ...o-selector-modal-wrapper.component.spec.ts | 129 ++++++++++++++++++ .../dso-selector-modal-wrapper.component.ts | 38 +++++- ...edit-collection-selector.component.spec.ts | 65 +++++++++ .../edit-collection-selector.component.ts | 0 .../edit-community-selector.component.spec.ts | 65 +++++++++ .../edit-community-selector.component.ts | 0 .../edit-item-selector.component.spec.ts | 65 +++++++++ .../edit-item-selector.component.ts | 0 .../onclick-menu-item.component.spec.ts | 51 +++++++ .../menu-item/onclick-menu-item.component.ts | 5 +- src/app/shared/shared.module.ts | 7 +- 19 files changed, 639 insertions(+), 31 deletions(-) create mode 100644 src/app/shared/dso-selector/modal-wrappers/create-collection-parent-selector/create-collection-parent-selector.component.spec.ts create mode 100644 src/app/shared/dso-selector/modal-wrappers/create-community-parent-selector/create-community-parent-selector.component.spec.ts create mode 100644 src/app/shared/dso-selector/modal-wrappers/create-item-parent-selector/create-item-parent-selector.component.spec.ts create mode 100644 src/app/shared/dso-selector/modal-wrappers/dso-selector-modal-wrapper.component.spec.ts create mode 100644 src/app/shared/dso-selector/modal-wrappers/edit-collection-selector/edit-collection-selector.component.spec.ts rename src/app/shared/dso-selector/modal-wrappers/{edit-collection-parent-selector => edit-collection-selector}/edit-collection-selector.component.ts (100%) create mode 100644 src/app/shared/dso-selector/modal-wrappers/edit-community-selector/edit-community-selector.component.spec.ts rename src/app/shared/dso-selector/modal-wrappers/{edit-community-parent-selector => edit-community-selector}/edit-community-selector.component.ts (100%) create mode 100644 src/app/shared/dso-selector/modal-wrappers/edit-item-selector/edit-item-selector.component.spec.ts rename src/app/shared/dso-selector/modal-wrappers/{edit-item-parent-selector => edit-item-selector}/edit-item-selector.component.ts (100%) create mode 100644 src/app/shared/menu/menu-item/onclick-menu-item.component.spec.ts diff --git a/src/app/+admin/admin-sidebar/admin-sidebar.component.spec.ts b/src/app/+admin/admin-sidebar/admin-sidebar.component.spec.ts index c99e8adc58..e95949dd94 100644 --- a/src/app/+admin/admin-sidebar/admin-sidebar.component.spec.ts +++ b/src/app/+admin/admin-sidebar/admin-sidebar.component.spec.ts @@ -12,6 +12,7 @@ import { AuthService } from '../../core/auth/auth.service'; import { of as observableOf } from 'rxjs'; import { By } from '@angular/platform-browser'; +import { NgbModal } from '@ng-bootstrap/ng-bootstrap'; describe('AdminSidebarComponent', () => { let comp: AdminSidebarComponent; @@ -26,7 +27,13 @@ describe('AdminSidebarComponent', () => { { provide: Injector, useValue: {} }, { provide: MenuService, useValue: menuService }, { provide: CSSVariableService, useClass: CSSVariableServiceStub }, - { provide: AuthService, useClass: AuthServiceStub } + { provide: AuthService, useClass: AuthServiceStub }, + { + provide: NgbModal, useValue: { + open: () => { + } + } + } ], schemas: [NO_ERRORS_SCHEMA] }).overrideComponent(AdminSidebarComponent, { @@ -96,7 +103,10 @@ describe('AdminSidebarComponent', () => { beforeEach(() => { spyOn(menuService, 'toggleMenu'); const sidebarToggler = fixture.debugElement.query(By.css('#sidebar-collapse-toggle')).query(By.css('a.shortcut-icon')); - sidebarToggler.triggerEventHandler('click', {preventDefault: () => {/**/}}); + sidebarToggler.triggerEventHandler('click', { + preventDefault: () => {/**/ + } + }); }); it('should call toggleMenu on the menuService', () => { @@ -108,7 +118,10 @@ describe('AdminSidebarComponent', () => { beforeEach(() => { spyOn(menuService, 'toggleMenu'); const sidebarToggler = fixture.debugElement.query(By.css('#sidebar-collapse-toggle')).query(By.css('.sidebar-collapsible')).query(By.css('a')); - sidebarToggler.triggerEventHandler('click', {preventDefault: () => {/**/}}); + sidebarToggler.triggerEventHandler('click', { + preventDefault: () => {/**/ + } + }); }); it('should call toggleMenu on the menuService', () => { @@ -120,7 +133,10 @@ describe('AdminSidebarComponent', () => { it('should call expandPreview on the menuService after 100ms', fakeAsync(() => { spyOn(menuService, 'expandMenuPreview'); const sidebarToggler = fixture.debugElement.query(By.css('nav.navbar')); - sidebarToggler.triggerEventHandler('mouseenter', {preventDefault: () => {/**/}}); + sidebarToggler.triggerEventHandler('mouseenter', { + preventDefault: () => {/**/ + } + }); tick(99); expect(menuService.expandMenuPreview).not.toHaveBeenCalled(); tick(1); @@ -132,7 +148,10 @@ describe('AdminSidebarComponent', () => { it('should call collapseMenuPreview on the menuService after 400ms', fakeAsync(() => { spyOn(menuService, 'collapseMenuPreview'); const sidebarToggler = fixture.debugElement.query(By.css('nav.navbar')); - sidebarToggler.triggerEventHandler('mouseleave', {preventDefault: () => {/**/}}); + sidebarToggler.triggerEventHandler('mouseleave', { + preventDefault: () => {/**/ + } + }); tick(399); expect(menuService.collapseMenuPreview).not.toHaveBeenCalled(); tick(1); diff --git a/src/app/+admin/admin-sidebar/admin-sidebar.component.ts b/src/app/+admin/admin-sidebar/admin-sidebar.component.ts index e429b57bae..f148627297 100644 --- a/src/app/+admin/admin-sidebar/admin-sidebar.component.ts +++ b/src/app/+admin/admin-sidebar/admin-sidebar.component.ts @@ -15,9 +15,9 @@ import { OnClickMenuItemModel } from '../../shared/menu/menu-item/models/onclick import { CreateCommunityParentSelectorComponent } from '../../shared/dso-selector/modal-wrappers/create-community-parent-selector/create-community-parent-selector.component'; import { CreateItemParentSelectorComponent } from '../../shared/dso-selector/modal-wrappers/create-item-parent-selector/create-item-parent-selector.component'; import { CreateCollectionParentSelectorComponent } from '../../shared/dso-selector/modal-wrappers/create-collection-parent-selector/create-collection-parent-selector.component'; -import { EditItemSelectorComponent } from '../../shared/dso-selector/modal-wrappers/edit-item-parent-selector/edit-item-selector.component'; -import { EditCommunitySelectorComponent } from '../../shared/dso-selector/modal-wrappers/edit-community-parent-selector/edit-community-selector.component'; -import { EditCollectionSelectorComponent } from '../../shared/dso-selector/modal-wrappers/edit-collection-parent-selector/edit-collection-selector.component'; +import { EditItemSelectorComponent } from '../../shared/dso-selector/modal-wrappers/edit-item-selector/edit-item-selector.component'; +import { EditCommunitySelectorComponent } from '../../shared/dso-selector/modal-wrappers/edit-community-selector/edit-community-selector.component'; +import { EditCollectionSelectorComponent } from '../../shared/dso-selector/modal-wrappers/edit-collection-selector/edit-collection-selector.component'; /** * Component representing the admin sidebar diff --git a/src/app/shared/dso-selector/dso-selector/dso-selector.component.spec.ts b/src/app/shared/dso-selector/dso-selector/dso-selector.component.spec.ts index 38067f3dc0..b7fa0c420e 100644 --- a/src/app/shared/dso-selector/dso-selector/dso-selector.component.spec.ts +++ b/src/app/shared/dso-selector/dso-selector/dso-selector.component.spec.ts @@ -11,7 +11,7 @@ import { Item } from '../../../core/shared/item.model'; import { of as observableOf } from 'rxjs'; import { PaginatedList } from '../../../core/data/paginated-list'; -fdescribe('DSOSelectorComponent', () => { +describe('DSOSelectorComponent', () => { let component: DSOSelectorComponent; let fixture: ComponentFixture; let debugElement: DebugElement; @@ -35,8 +35,7 @@ fdescribe('DSOSelectorComponent', () => { { provide: SearchService, useValue: searchService }, ], schemas: [NO_ERRORS_SCHEMA] - }) - .compileComponents(); + }).compileComponents(); })); diff --git a/src/app/shared/dso-selector/modal-wrappers/create-collection-parent-selector/create-collection-parent-selector.component.spec.ts b/src/app/shared/dso-selector/modal-wrappers/create-collection-parent-selector/create-collection-parent-selector.component.spec.ts new file mode 100644 index 0000000000..5ffbae79be --- /dev/null +++ b/src/app/shared/dso-selector/modal-wrappers/create-collection-parent-selector/create-collection-parent-selector.component.spec.ts @@ -0,0 +1,65 @@ +import { async, ComponentFixture, TestBed } from '@angular/core/testing'; +import { TranslateModule } from '@ngx-translate/core'; +import { DebugElement, NO_ERRORS_SCHEMA } from '@angular/core'; +import { of as observableOf } from 'rxjs'; +import { NgbActiveModal } from '@ng-bootstrap/ng-bootstrap'; +import { ActivatedRoute, Router } from '@angular/router'; +import { RemoteData } from '../../../../core/data/remote-data'; +import { RouterStub } from '../../../testing/router-stub'; +import * as collectionRouter from '../../../../+collection-page/collection-page-routing.module'; +import { Community } from '../../../../core/shared/community.model'; +import { CreateCollectionParentSelectorComponent } from './create-collection-parent-selector.component'; + +describe('CreateCollectionParentSelectorComponent', () => { + let component: CreateCollectionParentSelectorComponent; + let fixture: ComponentFixture; + let debugElement: DebugElement; + + const community = new Community(); + community.uuid = '1234-1234-1234-1234'; + community.metadata = { 'dc.title': [{ value: 'Community title', language: undefined }] }; + const router = new RouterStub(); + const communityRD = new RemoteData(false, false, true, undefined, community); + const modalStub = jasmine.createSpyObj('modalStub', ['close']); + const createPath = 'testCreatePath'; + + beforeEach(async(() => { + TestBed.configureTestingModule({ + imports: [TranslateModule.forRoot()], + declarations: [CreateCollectionParentSelectorComponent], + providers: [ + { provide: NgbActiveModal, useValue: modalStub }, + { + provide: ActivatedRoute, + useValue: { root: { firstChild: { firstChild: { data: observableOf({ community: communityRD }) } } } } + }, + { + provide: Router, useValue: router + } + ], + schemas: [NO_ERRORS_SCHEMA] + }).compileComponents(); + + })); + + beforeEach(() => { + spyOnProperty(collectionRouter, 'getCollectionCreatePath').and.callFake(() => { + return () => createPath; + }); + + fixture = TestBed.createComponent(CreateCollectionParentSelectorComponent); + component = fixture.componentInstance; + debugElement = fixture.debugElement; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); + + it('should call navigate on the router with the correct edit path when navigate is called', () => { + component.navigate(community); + expect(router.navigate).toHaveBeenCalledWith([createPath], { queryParams: { parent: community.uuid } } ); + }); + +}); diff --git a/src/app/shared/dso-selector/modal-wrappers/create-community-parent-selector/create-community-parent-selector.component.spec.ts b/src/app/shared/dso-selector/modal-wrappers/create-community-parent-selector/create-community-parent-selector.component.spec.ts new file mode 100644 index 0000000000..156e8924c8 --- /dev/null +++ b/src/app/shared/dso-selector/modal-wrappers/create-community-parent-selector/create-community-parent-selector.component.spec.ts @@ -0,0 +1,65 @@ +import { async, ComponentFixture, TestBed } from '@angular/core/testing'; +import { TranslateModule } from '@ngx-translate/core'; +import { DebugElement, NO_ERRORS_SCHEMA } from '@angular/core'; +import { of as observableOf } from 'rxjs'; +import { NgbActiveModal } from '@ng-bootstrap/ng-bootstrap'; +import { ActivatedRoute, Router } from '@angular/router'; +import { RemoteData } from '../../../../core/data/remote-data'; +import { RouterStub } from '../../../testing/router-stub'; +import * as communityRouter from '../../../../+community-page/community-page-routing.module'; +import { Community } from '../../../../core/shared/community.model'; +import { CreateCommunityParentSelectorComponent } from './create-community-parent-selector.component'; + +describe('CreateCommunityParentSelectorComponent', () => { + let component: CreateCommunityParentSelectorComponent; + let fixture: ComponentFixture; + let debugElement: DebugElement; + + const community = new Community(); + community.uuid = '1234-1234-1234-1234'; + community.metadata = { 'dc.title': [{ value: 'Community title', language: undefined }] }; + const router = new RouterStub(); + const communityRD = new RemoteData(false, false, true, undefined, community); + const modalStub = jasmine.createSpyObj('modalStub', ['close']); + const createPath = 'testCreatePath'; + + beforeEach(async(() => { + TestBed.configureTestingModule({ + imports: [TranslateModule.forRoot()], + declarations: [CreateCommunityParentSelectorComponent], + providers: [ + { provide: NgbActiveModal, useValue: modalStub }, + { + provide: ActivatedRoute, + useValue: { root: { firstChild: { firstChild: { data: observableOf({ community: communityRD }) } } } } + }, + { + provide: Router, useValue: router + } + ], + schemas: [NO_ERRORS_SCHEMA] + }).compileComponents(); + + })); + + beforeEach(() => { + spyOnProperty(communityRouter, 'getCommunityCreatePath').and.callFake(() => { + return () => createPath; + }); + + fixture = TestBed.createComponent(CreateCommunityParentSelectorComponent); + component = fixture.componentInstance; + debugElement = fixture.debugElement; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); + + it('should call navigate on the router with the correct edit path when navigate is called', () => { + component.navigate(community); + expect(router.navigate).toHaveBeenCalledWith([createPath], { queryParams: { parent: community.uuid } }); + }); + +}); diff --git a/src/app/shared/dso-selector/modal-wrappers/create-community-parent-selector/create-community-parent-selector.component.ts b/src/app/shared/dso-selector/modal-wrappers/create-community-parent-selector/create-community-parent-selector.component.ts index c3d112a455..c8c98503d0 100644 --- a/src/app/shared/dso-selector/modal-wrappers/create-community-parent-selector/create-community-parent-selector.component.ts +++ b/src/app/shared/dso-selector/modal-wrappers/create-community-parent-selector/create-community-parent-selector.component.ts @@ -1,13 +1,9 @@ -import { Component, Input, OnInit } from '@angular/core'; +import { Component, OnInit } from '@angular/core'; import { ActivatedRoute, NavigationExtras, Router } from '@angular/router'; -import { Community } from '../../../../core/shared/community.model'; -import { RemoteData } from '../../../../core/data/remote-data'; import { DSpaceObjectType } from '../../../../core/shared/dspace-object-type.model'; import { DSpaceObject } from '../../../../core/shared/dspace-object.model'; import { hasValue } from '../../../empty.util'; import { NgbActiveModal } from '@ng-bootstrap/ng-bootstrap'; -import { map } from 'rxjs/operators'; -import { Observable } from 'rxjs'; import { COMMUNITY_PARENT_PARAMETER, getCommunityCreatePath diff --git a/src/app/shared/dso-selector/modal-wrappers/create-item-parent-selector/create-item-parent-selector.component.spec.ts b/src/app/shared/dso-selector/modal-wrappers/create-item-parent-selector/create-item-parent-selector.component.spec.ts new file mode 100644 index 0000000000..89204ff2b3 --- /dev/null +++ b/src/app/shared/dso-selector/modal-wrappers/create-item-parent-selector/create-item-parent-selector.component.spec.ts @@ -0,0 +1,65 @@ +import { async, ComponentFixture, TestBed } from '@angular/core/testing'; +import { TranslateModule } from '@ngx-translate/core'; +import { DebugElement, NO_ERRORS_SCHEMA } from '@angular/core'; +import { of as observableOf } from 'rxjs'; +import { NgbActiveModal } from '@ng-bootstrap/ng-bootstrap'; +import { ActivatedRoute, Router } from '@angular/router'; +import { RemoteData } from '../../../../core/data/remote-data'; +import { RouterStub } from '../../../testing/router-stub'; +import { Collection } from '../../../../core/shared/collection.model'; +import { CreateItemParentSelectorComponent } from './create-item-parent-selector.component'; + +describe('CreateItemParentSelectorComponent', () => { + let component: CreateItemParentSelectorComponent; + let fixture: ComponentFixture; + let debugElement: DebugElement; + + const collection = new Collection(); + collection.uuid = '1234-1234-1234-1234'; + collection.metadata = { 'dc.title': [{ value: 'Collection title', language: undefined }] }; + const router = new RouterStub(); + const collectionRD = new RemoteData(false, false, true, undefined, collection); + const modalStub = jasmine.createSpyObj('modalStub', ['close']); + const createPath = 'testCreatePath'; + + beforeEach(async(() => { + TestBed.configureTestingModule({ + imports: [TranslateModule.forRoot()], + declarations: [CreateItemParentSelectorComponent], + providers: [ + { provide: NgbActiveModal, useValue: modalStub }, + { + provide: ActivatedRoute, + useValue: { root: { firstChild: { firstChild: { data: observableOf({ collection: collectionRD }) } } } } + }, + { + provide: Router, useValue: router + } + ], + schemas: [NO_ERRORS_SCHEMA] + }).compileComponents(); + + })); + + beforeEach(() => { + // spyOnProperty(itemRouter, 'getItemCreatePath').and.callFake(() => { + // return () => createPath; + // }); + + fixture = TestBed.createComponent(CreateItemParentSelectorComponent); + component = fixture.componentInstance; + debugElement = fixture.debugElement; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); + + it('should call navigate on the router with the correct create path when navigate is called', () => { + /* TODO when there is a specific submission path */ + // component.navigate(item); + // expect(router.navigate).toHaveBeenCalledWith([createPath]); + }); + +}); diff --git a/src/app/shared/dso-selector/modal-wrappers/create-item-parent-selector/create-item-parent-selector.component.ts b/src/app/shared/dso-selector/modal-wrappers/create-item-parent-selector/create-item-parent-selector.component.ts index dac79dddcb..27610304e5 100644 --- a/src/app/shared/dso-selector/modal-wrappers/create-item-parent-selector/create-item-parent-selector.component.ts +++ b/src/app/shared/dso-selector/modal-wrappers/create-item-parent-selector/create-item-parent-selector.component.ts @@ -29,8 +29,6 @@ export class CreateItemParentSelectorComponent extends DSOSelectorModalWrapperCo } navigate(dso: DSpaceObject) { - let path; - // path = this.createPath; - // this.router.navigate([path]); + //There's no submit path per collection yet... } } diff --git a/src/app/shared/dso-selector/modal-wrappers/dso-selector-modal-wrapper.component.spec.ts b/src/app/shared/dso-selector/modal-wrappers/dso-selector-modal-wrapper.component.spec.ts new file mode 100644 index 0000000000..edc6a512a5 --- /dev/null +++ b/src/app/shared/dso-selector/modal-wrappers/dso-selector-modal-wrapper.component.spec.ts @@ -0,0 +1,129 @@ +import { async, ComponentFixture, TestBed } from '@angular/core/testing'; +import { TranslateModule } from '@ngx-translate/core'; +import { Component, DebugElement, NO_ERRORS_SCHEMA, OnInit } from '@angular/core'; +import { DSpaceObjectType } from '../../../core/shared/dspace-object-type.model'; +import { RemoteData } from '../../../core/data/remote-data'; +import { Item } from '../../../core/shared/item.model'; +import { of as observableOf } from 'rxjs'; +import { + DSOSelectorModalWrapperComponent, + SelectorActionType +} from './dso-selector-modal-wrapper.component'; +import { NgbActiveModal } from '@ng-bootstrap/ng-bootstrap'; +import { ActivatedRoute } from '@angular/router'; +import { DSpaceObject } from '../../../core/shared/dspace-object.model'; +import { first } from 'rxjs/operators'; +import { By } from '@angular/platform-browser'; +import { DSOSelectorComponent } from '../dso-selector/dso-selector.component'; +import { MockComponent } from 'ng-mocks'; + +describe('DSOSelectorModalWrapperComponent', () => { + let component: DSOSelectorModalWrapperComponent; + let fixture: ComponentFixture; + let debugElement: DebugElement; + + const item = new Item(); + item.uuid = '1234-1234-1234-1234'; + item.metadata = { 'dc.title': [{ value: 'Item title', language: undefined }] }; + + const itemRD = new RemoteData(false, false, true, undefined, item); + const modalStub = jasmine.createSpyObj('modalStub', ['close']); + + beforeEach(async(() => { + TestBed.configureTestingModule({ + imports: [TranslateModule.forRoot()], + declarations: [TestComponent, MockComponent(DSOSelectorComponent)], + providers: [ + { provide: NgbActiveModal, useValue: modalStub }, + { + provide: ActivatedRoute, + useValue: { root: { firstChild: { firstChild: { data: observableOf({ item: itemRD }) } } } } + } + ], + schemas: [NO_ERRORS_SCHEMA] + }).compileComponents(); + + })); + + beforeEach(() => { + fixture = TestBed.createComponent(TestComponent); + component = fixture.componentInstance; + debugElement = fixture.debugElement; + fixture.detectChanges(); + component.ngOnInit(); + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); + + it('should initially set the DSO to the activated route\'s item/collection/community', () => { + component.dsoRD$ + .pipe(first()) + .subscribe((a) => { + expect(a).toEqual(itemRD); + }) + }); + + describe('selectObject', () => { + beforeEach(() => { + spyOn(component, 'navigate'); + spyOn(component, 'close'); + component.selectObject(item) + }); + it('should call the close and navigate method on the component with the given DSO', () => { + expect(component.close).toHaveBeenCalled(); + expect(component.navigate).toHaveBeenCalledWith(item); + }); + }); + + describe('close', () => { + beforeEach(() => { + component.close(); + }); + it('should call the close method on the æctive modal', () => { + expect(modalStub.close).toHaveBeenCalled(); + }); + }); + + + describe('when the onSelect method emits on the child component', () => { + beforeEach(() => { + spyOn(component, 'selectObject'); + debugElement.query(By.css('ds-dso-selector')).componentInstance.onSelect.emit(item); + fixture.detectChanges(); + }); + it('should call the selectObject method on the component with the correct object', () => { + expect(component.selectObject).toHaveBeenCalledWith(item); + }); + }); + + describe('when the click method emits on close button', () => { + beforeEach(() => { + spyOn(component, 'close'); + debugElement.query(By.css('button.close')).triggerEventHandler('click', {}); + fixture.detectChanges(); + }); + it('should call the close method on the component', () => { + expect(component.close).toHaveBeenCalled(); + }); + }); +}); + +@Component({ + selector: 'ds-test-cmp', + templateUrl: './dso-selector-modal-wrapper.component.html' +}) +class TestComponent extends DSOSelectorModalWrapperComponent implements OnInit { + objectType = DSpaceObjectType.ITEM; + selectorType = DSpaceObjectType.ITEM; + action = SelectorActionType.EDIT; + + constructor(protected activeModal: NgbActiveModal, protected route: ActivatedRoute) { + super(activeModal, route); + } + + navigate(dso: DSpaceObject) { + } +} diff --git a/src/app/shared/dso-selector/modal-wrappers/dso-selector-modal-wrapper.component.ts b/src/app/shared/dso-selector/modal-wrappers/dso-selector-modal-wrapper.component.ts index 3d053e9dcb..7e6ee889c0 100644 --- a/src/app/shared/dso-selector/modal-wrappers/dso-selector-modal-wrapper.component.ts +++ b/src/app/shared/dso-selector/modal-wrappers/dso-selector-modal-wrapper.component.ts @@ -1,4 +1,4 @@ -import { Component, Input, OnInit } from '@angular/core'; +import { Component, Injectable, Input, OnInit } from '@angular/core'; import { ActivatedRoute } from '@angular/router'; import { Observable } from 'rxjs'; import { DSpaceObject } from '../../../core/shared/dspace-object.model'; @@ -10,33 +10,59 @@ import { DSpaceObjectType } from '../../../core/shared/dspace-object-type.model' export enum SelectorActionType { CREATE = 'create', EDIT = 'edit' -}; +} -@Component({ - selector: 'ds-dso-selector-modal-wrapper', - templateUrl: './dso-selector-modal-wrapper.component.html', -}) +@Injectable() export abstract class DSOSelectorModalWrapperComponent implements OnInit { + /** + * The current page's DSO + */ @Input() dsoRD$: Observable>; + + /** + * The type of the DSO that's being edited or created + */ objectType: DSpaceObjectType; + + /** + * The type of DSO that can be selected from this list + */ selectorType: DSpaceObjectType; + + /** + * The type of action to perform + */ action: SelectorActionType; constructor(protected activeModal: NgbActiveModal, protected route: ActivatedRoute) { } + /** + * Get de current page's DSO based on the selectorType + */ ngOnInit(): void { const typeString = this.selectorType.toString().toLowerCase(); this.dsoRD$ = this.route.root.firstChild.firstChild.data.pipe(map(data => data[typeString])); } + /** + * Method called when an object has been selected + * @param dso The selected DSpaceObject + */ selectObject(dso: DSpaceObject) { this.close(); this.navigate(dso); } + /** + * Navigate to a page based on the DSpaceObject provided + * @param dso The DSpaceObject which can be used to calculate the page to navigate to + */ abstract navigate(dso: DSpaceObject); + /** + * Close the modal + */ close() { this.activeModal.close(); } diff --git a/src/app/shared/dso-selector/modal-wrappers/edit-collection-selector/edit-collection-selector.component.spec.ts b/src/app/shared/dso-selector/modal-wrappers/edit-collection-selector/edit-collection-selector.component.spec.ts new file mode 100644 index 0000000000..6e4cd7b3b6 --- /dev/null +++ b/src/app/shared/dso-selector/modal-wrappers/edit-collection-selector/edit-collection-selector.component.spec.ts @@ -0,0 +1,65 @@ +import { async, ComponentFixture, TestBed } from '@angular/core/testing'; +import { TranslateModule } from '@ngx-translate/core'; +import { DebugElement, NO_ERRORS_SCHEMA } from '@angular/core'; +import { of as observableOf } from 'rxjs'; +import { NgbActiveModal } from '@ng-bootstrap/ng-bootstrap'; +import { ActivatedRoute, Router } from '@angular/router'; +import { RemoteData } from '../../../../core/data/remote-data'; +import { RouterStub } from '../../../testing/router-stub'; +import * as collectionRouter from '../../../../+collection-page/collection-page-routing.module'; +import { EditCollectionSelectorComponent } from './edit-collection-selector.component'; +import { Collection } from '../../../../core/shared/collection.model'; + +describe('EditCollectionSelectorComponent', () => { + let component: EditCollectionSelectorComponent; + let fixture: ComponentFixture; + let debugElement: DebugElement; + + const collection = new Collection(); + collection.uuid = '1234-1234-1234-1234'; + collection.metadata = { 'dc.title': [{ value: 'Collection title', language: undefined }] }; + const router = new RouterStub(); + const collectionRD = new RemoteData(false, false, true, undefined, collection); + const modalStub = jasmine.createSpyObj('modalStub', ['close']); + const editPath = 'testEditPath'; + + beforeEach(async(() => { + TestBed.configureTestingModule({ + imports: [TranslateModule.forRoot()], + declarations: [EditCollectionSelectorComponent], + providers: [ + { provide: NgbActiveModal, useValue: modalStub }, + { + provide: ActivatedRoute, + useValue: { root: { firstChild: { firstChild: { data: observableOf({ collection: collectionRD }) } } } } + }, + { + provide: Router, useValue: router + } + ], + schemas: [NO_ERRORS_SCHEMA] + }).compileComponents(); + + })); + + beforeEach(() => { + spyOnProperty(collectionRouter, 'getCollectionEditPath').and.callFake(() => { + return () => editPath; + }); + + fixture = TestBed.createComponent(EditCollectionSelectorComponent); + component = fixture.componentInstance; + debugElement = fixture.debugElement; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); + + it('should call navigate on the router with the correct edit path when navigate is called', () => { + component.navigate(collection); + expect(router.navigate).toHaveBeenCalledWith([editPath]); + }); + +}); diff --git a/src/app/shared/dso-selector/modal-wrappers/edit-collection-parent-selector/edit-collection-selector.component.ts b/src/app/shared/dso-selector/modal-wrappers/edit-collection-selector/edit-collection-selector.component.ts similarity index 100% rename from src/app/shared/dso-selector/modal-wrappers/edit-collection-parent-selector/edit-collection-selector.component.ts rename to src/app/shared/dso-selector/modal-wrappers/edit-collection-selector/edit-collection-selector.component.ts diff --git a/src/app/shared/dso-selector/modal-wrappers/edit-community-selector/edit-community-selector.component.spec.ts b/src/app/shared/dso-selector/modal-wrappers/edit-community-selector/edit-community-selector.component.spec.ts new file mode 100644 index 0000000000..e66554d1c3 --- /dev/null +++ b/src/app/shared/dso-selector/modal-wrappers/edit-community-selector/edit-community-selector.component.spec.ts @@ -0,0 +1,65 @@ +import { async, ComponentFixture, TestBed } from '@angular/core/testing'; +import { TranslateModule } from '@ngx-translate/core'; +import { DebugElement, NO_ERRORS_SCHEMA } from '@angular/core'; +import { of as observableOf } from 'rxjs'; +import { NgbActiveModal } from '@ng-bootstrap/ng-bootstrap'; +import { ActivatedRoute, Router } from '@angular/router'; +import { RemoteData } from '../../../../core/data/remote-data'; +import { RouterStub } from '../../../testing/router-stub'; +import * as communityRouter from '../../../../+community-page/community-page-routing.module'; +import { EditCommunitySelectorComponent } from './edit-community-selector.component'; +import { Community } from '../../../../core/shared/community.model'; + +describe('EditCommunitySelectorComponent', () => { + let component: EditCommunitySelectorComponent; + let fixture: ComponentFixture; + let debugElement: DebugElement; + + const community = new Community(); + community.uuid = '1234-1234-1234-1234'; + community.metadata = { 'dc.title': [{ value: 'Community title', language: undefined }] }; + const router = new RouterStub(); + const communityRD = new RemoteData(false, false, true, undefined, community); + const modalStub = jasmine.createSpyObj('modalStub', ['close']); + const editPath = 'testEditPath'; + + beforeEach(async(() => { + TestBed.configureTestingModule({ + imports: [TranslateModule.forRoot()], + declarations: [EditCommunitySelectorComponent], + providers: [ + { provide: NgbActiveModal, useValue: modalStub }, + { + provide: ActivatedRoute, + useValue: { root: { firstChild: { firstChild: { data: observableOf({ community: communityRD }) } } } } + }, + { + provide: Router, useValue: router + } + ], + schemas: [NO_ERRORS_SCHEMA] + }).compileComponents(); + + })); + + beforeEach(() => { + spyOnProperty(communityRouter, 'getCommunityEditPath').and.callFake(() => { + return () => editPath; + }); + + fixture = TestBed.createComponent(EditCommunitySelectorComponent); + component = fixture.componentInstance; + debugElement = fixture.debugElement; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); + + it('should call navigate on the router with the correct edit path when navigate is called', () => { + component.navigate(community); + expect(router.navigate).toHaveBeenCalledWith([editPath]); + }); + +}); diff --git a/src/app/shared/dso-selector/modal-wrappers/edit-community-parent-selector/edit-community-selector.component.ts b/src/app/shared/dso-selector/modal-wrappers/edit-community-selector/edit-community-selector.component.ts similarity index 100% rename from src/app/shared/dso-selector/modal-wrappers/edit-community-parent-selector/edit-community-selector.component.ts rename to src/app/shared/dso-selector/modal-wrappers/edit-community-selector/edit-community-selector.component.ts diff --git a/src/app/shared/dso-selector/modal-wrappers/edit-item-selector/edit-item-selector.component.spec.ts b/src/app/shared/dso-selector/modal-wrappers/edit-item-selector/edit-item-selector.component.spec.ts new file mode 100644 index 0000000000..01de6b2de6 --- /dev/null +++ b/src/app/shared/dso-selector/modal-wrappers/edit-item-selector/edit-item-selector.component.spec.ts @@ -0,0 +1,65 @@ +import { async, ComponentFixture, TestBed } from '@angular/core/testing'; +import { TranslateModule } from '@ngx-translate/core'; +import { DebugElement, NO_ERRORS_SCHEMA } from '@angular/core'; +import { of as observableOf } from 'rxjs'; +import { NgbActiveModal } from '@ng-bootstrap/ng-bootstrap'; +import { ActivatedRoute, Router } from '@angular/router'; +import { EditItemSelectorComponent } from './edit-item-selector.component'; +import { Item } from '../../../../core/shared/item.model'; +import { RemoteData } from '../../../../core/data/remote-data'; +import { RouterStub } from '../../../testing/router-stub'; +import * as itemRouter from '../../../../+item-page/item-page-routing.module'; + +describe('EditItemSelectorComponent', () => { + let component: EditItemSelectorComponent; + let fixture: ComponentFixture; + let debugElement: DebugElement; + + const item = new Item(); + item.uuid = '1234-1234-1234-1234'; + item.metadata = { 'dc.title': [{ value: 'Item title', language: undefined }] }; + const router = new RouterStub(); + const itemRD = new RemoteData(false, false, true, undefined, item); + const modalStub = jasmine.createSpyObj('modalStub', ['close']); + const editPath = 'testEditPath'; + + beforeEach(async(() => { + TestBed.configureTestingModule({ + imports: [TranslateModule.forRoot()], + declarations: [EditItemSelectorComponent], + providers: [ + { provide: NgbActiveModal, useValue: modalStub }, + { + provide: ActivatedRoute, + useValue: { root: { firstChild: { firstChild: { data: observableOf({ item: itemRD }) } } } } + }, + { + provide: Router, useValue: router + } + ], + schemas: [NO_ERRORS_SCHEMA] + }).compileComponents(); + + })); + + beforeEach(() => { + spyOnProperty(itemRouter, 'getItemEditPath').and.callFake(() => { + return () => editPath; + }); + + fixture = TestBed.createComponent(EditItemSelectorComponent); + component = fixture.componentInstance; + debugElement = fixture.debugElement; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); + + it('should call navigate on the router with the correct edit path when navigate is called', () => { + component.navigate(item); + expect(router.navigate).toHaveBeenCalledWith([editPath]); + }); + +}); diff --git a/src/app/shared/dso-selector/modal-wrappers/edit-item-parent-selector/edit-item-selector.component.ts b/src/app/shared/dso-selector/modal-wrappers/edit-item-selector/edit-item-selector.component.ts similarity index 100% rename from src/app/shared/dso-selector/modal-wrappers/edit-item-parent-selector/edit-item-selector.component.ts rename to src/app/shared/dso-selector/modal-wrappers/edit-item-selector/edit-item-selector.component.ts diff --git a/src/app/shared/menu/menu-item/onclick-menu-item.component.spec.ts b/src/app/shared/menu/menu-item/onclick-menu-item.component.spec.ts new file mode 100644 index 0000000000..5b085b28e4 --- /dev/null +++ b/src/app/shared/menu/menu-item/onclick-menu-item.component.spec.ts @@ -0,0 +1,51 @@ +import { async, ComponentFixture, TestBed } from '@angular/core/testing'; +import { TextMenuItemComponent } from './text-menu-item.component'; +import { TranslateModule } from '@ngx-translate/core'; +import { DebugElement, NO_ERRORS_SCHEMA } from '@angular/core'; +import { By } from '@angular/platform-browser'; +import { OnClickMenuItemComponent } from './onclick-menu-item.component'; +import { OnClickMenuItemModel } from './models/onclick.model'; + +describe('OnClickMenuItemComponent', () => { + let component: OnClickMenuItemComponent; + let fixture: ComponentFixture; + let debugElement: DebugElement; + const text = 'HELLO'; + const func = () => { + }; + const item = Object.assign(new OnClickMenuItemModel(), { text, function: func }); + + beforeEach(async(() => { + TestBed.configureTestingModule({ + imports: [TranslateModule.forRoot()], + declarations: [OnClickMenuItemComponent], + providers: [ + { provide: 'itemModelProvider', useValue: item }, + ], + schemas: [NO_ERRORS_SCHEMA] + }) + .compileComponents(); + })); + + beforeEach(() => { + spyOn(item, 'function'); + fixture = TestBed.createComponent(OnClickMenuItemComponent); + component = fixture.componentInstance; + debugElement = fixture.debugElement; + fixture.detectChanges(); + }); + + it('should contain the correct text', () => { + expect(component).toBeTruthy(); + }); + + it('should contain the text element', () => { + const textContent = debugElement.query(By.css('a')).nativeElement.textContent; + expect(textContent).toEqual(text); + }); + + it('should contain call the function on the item when clicked', () => { + debugElement.query(By.css('a.nav-link')).triggerEventHandler('click', {}); + expect(item.function).toHaveBeenCalled(); + }); +}); diff --git a/src/app/shared/menu/menu-item/onclick-menu-item.component.ts b/src/app/shared/menu/menu-item/onclick-menu-item.component.ts index 14fd5d8ffd..b981f08764 100644 --- a/src/app/shared/menu/menu-item/onclick-menu-item.component.ts +++ b/src/app/shared/menu/menu-item/onclick-menu-item.component.ts @@ -1,11 +1,10 @@ import { Component, Inject } from '@angular/core'; import { MenuItemType } from '../initial-menus-state'; import { rendersMenuItemForType } from '../menu-item.decorator'; -import { GLOBAL_CONFIG, GlobalConfig } from '../../../../config'; import { OnClickMenuItemModel } from './models/onclick.model'; /** - * Component that renders a menu section of type LINK + * Component that renders a menu section of type ONCLICK */ @Component({ selector: 'ds-onclick-menu-item', @@ -14,7 +13,7 @@ import { OnClickMenuItemModel } from './models/onclick.model'; @rendersMenuItemForType(MenuItemType.ONCLICK) export class OnClickMenuItemComponent { item: OnClickMenuItemModel; - constructor(@Inject('itemModelProvider') item: OnClickMenuItemModel, @Inject(GLOBAL_CONFIG) private EnvConfig: GlobalConfig) { + constructor(@Inject('itemModelProvider') item: OnClickMenuItemModel) { this.item = item; } } diff --git a/src/app/shared/shared.module.ts b/src/app/shared/shared.module.ts index 5d87148a73..e98da96e53 100644 --- a/src/app/shared/shared.module.ts +++ b/src/app/shared/shared.module.ts @@ -102,9 +102,10 @@ import { CreateCollectionParentSelectorComponent } from './dso-selector/modal-wr import { CommunitySearchResultListElementComponent } from './object-list/search-result-list-element/community-search-result/community-search-result-list-element.component'; import { CollectionSearchResultListElementComponent } from './object-list/search-result-list-element/collection-search-result/collection-search-result-list-element.component'; import { ItemSearchResultListElementComponent } from './object-list/search-result-list-element/item-search-result/item-search-result-list-element.component'; -import { EditItemSelectorComponent } from './dso-selector/modal-wrappers/edit-item-parent-selector/edit-item-selector.component'; -import { EditCommunitySelectorComponent } from './dso-selector/modal-wrappers/edit-community-parent-selector/edit-community-selector.component'; -import { EditCollectionSelectorComponent } from './dso-selector/modal-wrappers/edit-collection-parent-selector/edit-collection-selector.component'; +import { EditItemSelectorComponent } from './dso-selector/modal-wrappers/edit-item-selector/edit-item-selector.component'; +import { EditCommunitySelectorComponent } from './dso-selector/modal-wrappers/edit-community-selector/edit-community-selector.component'; +import { EditCollectionSelectorComponent } from './dso-selector/modal-wrappers/edit-collection-selector/edit-collection-selector.component'; +import { DSOSelectorModalWrapperComponent } from './dso-selector/modal-wrappers/dso-selector-modal-wrapper.component'; const MODULES = [ // Do NOT include UniversalModule, HttpModule, or JsonpModule here From c60175ac80140114944d14e729a37c5eb8ec0376 Mon Sep 17 00:00:00 2001 From: lotte Date: Thu, 7 Mar 2019 15:00:30 +0100 Subject: [PATCH 07/17] fixed metadata value issues --- resources/i18n/en.json | 4 +++- .../dso-selector/dso-selector.component.html | 7 ++++--- .../dso-selector/dso-selector.component.spec.ts | 3 ++- ...ate-collection-parent-selector.component.spec.ts | 13 ++++++++++--- ...eate-community-parent-selector.component.spec.ts | 3 ++- .../create-item-parent-selector.component.spec.ts | 3 ++- .../dso-selector-modal-wrapper.component.spec.ts | 8 +++++++- .../edit-collection-selector.component.spec.ts | 3 ++- .../edit-community-selector.component.spec.ts | 3 ++- .../edit-item-selector.component.spec.ts | 3 ++- 10 files changed, 36 insertions(+), 14 deletions(-) diff --git a/resources/i18n/en.json b/resources/i18n/en.json index 38d90e67ea..f563411231 100644 --- a/resources/i18n/en.json +++ b/resources/i18n/en.json @@ -667,6 +667,8 @@ "item": { "head": "Edit item" } - } + }, + "placeholder": "Search for a {{ type }}", + "no-results": "No {{ type }} found" } } diff --git a/src/app/shared/dso-selector/dso-selector/dso-selector.component.html b/src/app/shared/dso-selector/dso-selector/dso-selector.component.html index bc520bfe3b..e9555a6191 100644 --- a/src/app/shared/dso-selector/dso-selector/dso-selector.component.html +++ b/src/app/shared/dso-selector/dso-selector/dso-selector.component.html @@ -2,13 +2,14 @@
-
diff --git a/src/app/shared/dso-selector/dso-selector/dso-selector.component.ts b/src/app/shared/dso-selector/dso-selector/dso-selector.component.ts index f3164a37e2..7bb9bfac28 100644 --- a/src/app/shared/dso-selector/dso-selector/dso-selector.component.ts +++ b/src/app/shared/dso-selector/dso-selector/dso-selector.component.ts @@ -31,7 +31,7 @@ import { DSpaceObject } from '../../../core/shared/dspace-object.model'; * Component to render a list of DSO's of which one can be selected * The user can search the list by using the input field */ -export class DSOSelectorComponent implements OnInit, AfterViewInit { +export class DSOSelectorComponent implements OnInit { /** * The initially selected DSO's uuid @@ -76,6 +76,7 @@ export class DSOSelectorComponent implements OnInit, AfterViewInit { * The search will always start with the initial currentDSOId value */ ngOnInit(): void { + this.input.setValue(this.currentDSOId); this.listEntries$ = this.input.valueChanges .pipe( startWith(this.currentDSOId), @@ -93,15 +94,11 @@ export class DSOSelectorComponent implements OnInit, AfterViewInit { } /** - * Make sure to set focus on the first list element when the initial search (with currentDSOId) emits a single value + * Set focus on the first list element when there is only one result */ - ngAfterViewInit(): void { - this.listElements.changes.pipe( - take(1) - ).subscribe((changes) => { - if (changes.length === 1) { - this.listElements.first.nativeElement.focus(); - } - }); + selectSingleResult(): void { + if (this.listElements.length > 0) { + this.listElements.first.nativeElement.click(); + } } } diff --git a/src/app/shared/dso-selector/modal-wrappers/create-collection-parent-selector/create-collection-parent-selector.component.ts b/src/app/shared/dso-selector/modal-wrappers/create-collection-parent-selector/create-collection-parent-selector.component.ts index 631480c04d..ea2da41849 100644 --- a/src/app/shared/dso-selector/modal-wrappers/create-collection-parent-selector/create-collection-parent-selector.component.ts +++ b/src/app/shared/dso-selector/modal-wrappers/create-collection-parent-selector/create-collection-parent-selector.component.ts @@ -27,6 +27,9 @@ export class CreateCollectionParentSelectorComponent extends DSOSelectorModalWra super(activeModal, route); } + /** + * Navigate to the collection create page + */ navigate(dso: DSpaceObject) { let navigationExtras: NavigationExtras = { queryParams: { diff --git a/src/app/shared/dso-selector/modal-wrappers/create-community-parent-selector/create-community-parent-selector.component.ts b/src/app/shared/dso-selector/modal-wrappers/create-community-parent-selector/create-community-parent-selector.component.ts index c8c98503d0..b8cc28b9fc 100644 --- a/src/app/shared/dso-selector/modal-wrappers/create-community-parent-selector/create-community-parent-selector.component.ts +++ b/src/app/shared/dso-selector/modal-wrappers/create-community-parent-selector/create-community-parent-selector.component.ts @@ -27,6 +27,9 @@ export class CreateCommunityParentSelectorComponent extends DSOSelectorModalWrap super(activeModal, route); } + /** + * Navigate to the community create page + */ navigate(dso: DSpaceObject) { let navigationExtras: NavigationExtras = {}; if (hasValue(dso)) { diff --git a/src/app/shared/dso-selector/modal-wrappers/create-item-parent-selector/create-item-parent-selector.component.ts b/src/app/shared/dso-selector/modal-wrappers/create-item-parent-selector/create-item-parent-selector.component.ts index 27610304e5..dad0a2eb41 100644 --- a/src/app/shared/dso-selector/modal-wrappers/create-item-parent-selector/create-item-parent-selector.component.ts +++ b/src/app/shared/dso-selector/modal-wrappers/create-item-parent-selector/create-item-parent-selector.component.ts @@ -28,6 +28,9 @@ export class CreateItemParentSelectorComponent extends DSOSelectorModalWrapperCo super(activeModal, route); } + /** + * Navigate to the item create page + */ navigate(dso: DSpaceObject) { //There's no submit path per collection yet... } diff --git a/src/app/shared/dso-selector/modal-wrappers/edit-collection-selector/edit-collection-selector.component.ts b/src/app/shared/dso-selector/modal-wrappers/edit-collection-selector/edit-collection-selector.component.ts index edf3f37f6e..dab5b8eea3 100644 --- a/src/app/shared/dso-selector/modal-wrappers/edit-collection-selector/edit-collection-selector.component.ts +++ b/src/app/shared/dso-selector/modal-wrappers/edit-collection-selector/edit-collection-selector.component.ts @@ -22,6 +22,9 @@ export class EditCollectionSelectorComponent extends DSOSelectorModalWrapperComp super(activeModal, route); } + /** + * Navigate to the collection edit page + */ navigate(dso: DSpaceObject) { this.router.navigate([getCollectionEditPath(dso.uuid)]); } diff --git a/src/app/shared/dso-selector/modal-wrappers/edit-community-selector/edit-community-selector.component.ts b/src/app/shared/dso-selector/modal-wrappers/edit-community-selector/edit-community-selector.component.ts index 9af974782a..ce688d17ae 100644 --- a/src/app/shared/dso-selector/modal-wrappers/edit-community-selector/edit-community-selector.component.ts +++ b/src/app/shared/dso-selector/modal-wrappers/edit-community-selector/edit-community-selector.component.ts @@ -23,6 +23,9 @@ export class EditCommunitySelectorComponent extends DSOSelectorModalWrapperCompo super(activeModal, route); } + /** + * Navigate to the community edit page + */ navigate(dso: DSpaceObject) { this.router.navigate([getCommunityEditPath(dso.uuid)]); } diff --git a/src/app/shared/dso-selector/modal-wrappers/edit-item-selector/edit-item-selector.component.ts b/src/app/shared/dso-selector/modal-wrappers/edit-item-selector/edit-item-selector.component.ts index ff6ab35bf3..e14be10435 100644 --- a/src/app/shared/dso-selector/modal-wrappers/edit-item-selector/edit-item-selector.component.ts +++ b/src/app/shared/dso-selector/modal-wrappers/edit-item-selector/edit-item-selector.component.ts @@ -28,6 +28,9 @@ export class EditItemSelectorComponent extends DSOSelectorModalWrapperComponent super(activeModal, route); } + /** + * Navigate to the item edit page + */ navigate(dso: DSpaceObject) { this.router.navigate([getItemEditPath(dso.uuid)]); } diff --git a/src/app/shared/menu/menu-item/onclick-menu-item.component.scss b/src/app/shared/menu/menu-item/onclick-menu-item.component.scss new file mode 100644 index 0000000000..adb670aa6f --- /dev/null +++ b/src/app/shared/menu/menu-item/onclick-menu-item.component.scss @@ -0,0 +1,3 @@ +a { + cursor: pointer; +} \ No newline at end of file diff --git a/src/app/shared/menu/menu-item/onclick-menu-item.component.ts b/src/app/shared/menu/menu-item/onclick-menu-item.component.ts index b981f08764..95b896ed64 100644 --- a/src/app/shared/menu/menu-item/onclick-menu-item.component.ts +++ b/src/app/shared/menu/menu-item/onclick-menu-item.component.ts @@ -8,6 +8,7 @@ import { OnClickMenuItemModel } from './models/onclick.model'; */ @Component({ selector: 'ds-onclick-menu-item', + styleUrls: ['./onclick-menu-item.component.scss'], templateUrl: './onclick-menu-item.component.html' }) @rendersMenuItemForType(MenuItemType.ONCLICK) From ede9f05e92c17d10e0265d696669f655f53ef0ea Mon Sep 17 00:00:00 2001 From: lotte Date: Fri, 8 Mar 2019 08:51:33 +0100 Subject: [PATCH 09/17] fixed documentation --- src/app/+admin/admin-sidebar/admin-sidebar.component.spec.ts | 3 +-- .../create-collection-parent-selector.component.ts | 2 +- .../create-item-parent-selector.component.ts | 2 +- .../dso-selector-modal-wrapper.component.spec.ts | 2 +- .../modal-wrappers/dso-selector-modal-wrapper.component.ts | 2 +- .../shared/menu/menu-item/onclick-menu-item.component.spec.ts | 1 + 6 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/app/+admin/admin-sidebar/admin-sidebar.component.spec.ts b/src/app/+admin/admin-sidebar/admin-sidebar.component.spec.ts index e95949dd94..590caaaccf 100644 --- a/src/app/+admin/admin-sidebar/admin-sidebar.component.spec.ts +++ b/src/app/+admin/admin-sidebar/admin-sidebar.component.spec.ts @@ -30,8 +30,7 @@ describe('AdminSidebarComponent', () => { { provide: AuthService, useClass: AuthServiceStub }, { provide: NgbModal, useValue: { - open: () => { - } + open: () => {/*comment*/} } } ], diff --git a/src/app/shared/dso-selector/modal-wrappers/create-collection-parent-selector/create-collection-parent-selector.component.ts b/src/app/shared/dso-selector/modal-wrappers/create-collection-parent-selector/create-collection-parent-selector.component.ts index ea2da41849..20968456b3 100644 --- a/src/app/shared/dso-selector/modal-wrappers/create-collection-parent-selector/create-collection-parent-selector.component.ts +++ b/src/app/shared/dso-selector/modal-wrappers/create-collection-parent-selector/create-collection-parent-selector.component.ts @@ -31,7 +31,7 @@ export class CreateCollectionParentSelectorComponent extends DSOSelectorModalWra * Navigate to the collection create page */ navigate(dso: DSpaceObject) { - let navigationExtras: NavigationExtras = { + const navigationExtras: NavigationExtras = { queryParams: { [COLLECTION_PARENT_PARAMETER]: dso.uuid, } diff --git a/src/app/shared/dso-selector/modal-wrappers/create-item-parent-selector/create-item-parent-selector.component.ts b/src/app/shared/dso-selector/modal-wrappers/create-item-parent-selector/create-item-parent-selector.component.ts index dad0a2eb41..5dc6e4fe78 100644 --- a/src/app/shared/dso-selector/modal-wrappers/create-item-parent-selector/create-item-parent-selector.component.ts +++ b/src/app/shared/dso-selector/modal-wrappers/create-item-parent-selector/create-item-parent-selector.component.ts @@ -32,6 +32,6 @@ export class CreateItemParentSelectorComponent extends DSOSelectorModalWrapperCo * Navigate to the item create page */ navigate(dso: DSpaceObject) { - //There's no submit path per collection yet... + // There's no submit path per collection yet... } } diff --git a/src/app/shared/dso-selector/modal-wrappers/dso-selector-modal-wrapper.component.spec.ts b/src/app/shared/dso-selector/modal-wrappers/dso-selector-modal-wrapper.component.spec.ts index 2c7ddeb265..ea857f7d62 100644 --- a/src/app/shared/dso-selector/modal-wrappers/dso-selector-modal-wrapper.component.spec.ts +++ b/src/app/shared/dso-selector/modal-wrappers/dso-selector-modal-wrapper.component.spec.ts @@ -93,7 +93,6 @@ describe('DSOSelectorModalWrapperComponent', () => { }); }); - describe('when the onSelect method emits on the child component', () => { beforeEach(() => { spyOn(component, 'selectObject'); @@ -131,5 +130,6 @@ class TestComponent extends DSOSelectorModalWrapperComponent implements OnInit { } navigate(dso: DSpaceObject) { + /* comment */ } } diff --git a/src/app/shared/dso-selector/modal-wrappers/dso-selector-modal-wrapper.component.ts b/src/app/shared/dso-selector/modal-wrappers/dso-selector-modal-wrapper.component.ts index 7e6ee889c0..8414f00830 100644 --- a/src/app/shared/dso-selector/modal-wrappers/dso-selector-modal-wrapper.component.ts +++ b/src/app/shared/dso-selector/modal-wrappers/dso-selector-modal-wrapper.component.ts @@ -42,7 +42,7 @@ export abstract class DSOSelectorModalWrapperComponent implements OnInit { */ ngOnInit(): void { const typeString = this.selectorType.toString().toLowerCase(); - this.dsoRD$ = this.route.root.firstChild.firstChild.data.pipe(map(data => data[typeString])); + this.dsoRD$ = this.route.root.firstChild.firstChild.data.pipe(map((data) => data[typeString])); } /** diff --git a/src/app/shared/menu/menu-item/onclick-menu-item.component.spec.ts b/src/app/shared/menu/menu-item/onclick-menu-item.component.spec.ts index 5b085b28e4..dd031a96e0 100644 --- a/src/app/shared/menu/menu-item/onclick-menu-item.component.spec.ts +++ b/src/app/shared/menu/menu-item/onclick-menu-item.component.spec.ts @@ -12,6 +12,7 @@ describe('OnClickMenuItemComponent', () => { let debugElement: DebugElement; const text = 'HELLO'; const func = () => { + /* comment */ }; const item = Object.assign(new OnClickMenuItemModel(), { text, function: func }); From f1686f3de1b7c8f853a5509573fbd5ab61540ea8 Mon Sep 17 00:00:00 2001 From: lotte Date: Mon, 11 Mar 2019 12:40:29 +0100 Subject: [PATCH 10/17] applied feedback --- src/app/+search-page/search-page.module.ts | 9 +++------ .../create-collection-parent-selector.component.ts | 5 +++++ .../create-community-parent-selector.component.ts | 7 +++++++ .../create-item-parent-selector.component.ts | 5 +++++ .../dso-selector-modal-wrapper.component.ts | 4 ++++ .../edit-collection-selector.component.ts | 5 +++++ .../edit-community-selector.component.ts | 5 +++++ .../edit-item-selector/edit-item-selector.component.ts | 5 +++++ 8 files changed, 39 insertions(+), 6 deletions(-) diff --git a/src/app/+search-page/search-page.module.ts b/src/app/+search-page/search-page.module.ts index 4cd0c9428b..505065e44c 100644 --- a/src/app/+search-page/search-page.module.ts +++ b/src/app/+search-page/search-page.module.ts @@ -45,9 +45,6 @@ const effects = [ SearchResultsComponent, SearchSidebarComponent, SearchSettingsComponent, - // ItemSearchResultListElementComponent, - // CollectionSearchResultListElementComponent, - // CommunitySearchResultListElementComponent, ItemSearchResultGridElementComponent, CollectionSearchResultGridElementComponent, CommunitySearchResultGridElementComponent, @@ -68,9 +65,9 @@ const effects = [ SearchConfigurationService ], entryComponents: [ - // ItemSearchResultListElementComponent, - // CollectionSearchResultListElementComponent, - // CommunitySearchResultListElementComponent, + ItemSearchResultListElementComponent, + CollectionSearchResultListElementComponent, + CommunitySearchResultListElementComponent, ItemSearchResultGridElementComponent, CollectionSearchResultGridElementComponent, CommunitySearchResultGridElementComponent, diff --git a/src/app/shared/dso-selector/modal-wrappers/create-collection-parent-selector/create-collection-parent-selector.component.ts b/src/app/shared/dso-selector/modal-wrappers/create-collection-parent-selector/create-collection-parent-selector.component.ts index 20968456b3..1e129c0dbe 100644 --- a/src/app/shared/dso-selector/modal-wrappers/create-collection-parent-selector/create-collection-parent-selector.component.ts +++ b/src/app/shared/dso-selector/modal-wrappers/create-collection-parent-selector/create-collection-parent-selector.component.ts @@ -14,6 +14,11 @@ import { SelectorActionType } from '../dso-selector-modal-wrapper.component'; +/** + * Component to wrap a list of existing communities inside a modal + * Used to choose a community from to create a new collection in + */ + @Component({ selector: 'ds-create-collection-parent-selector', templateUrl: '../dso-selector-modal-wrapper.component.html', diff --git a/src/app/shared/dso-selector/modal-wrappers/create-community-parent-selector/create-community-parent-selector.component.ts b/src/app/shared/dso-selector/modal-wrappers/create-community-parent-selector/create-community-parent-selector.component.ts index b8cc28b9fc..914dc7582f 100644 --- a/src/app/shared/dso-selector/modal-wrappers/create-community-parent-selector/create-community-parent-selector.component.ts +++ b/src/app/shared/dso-selector/modal-wrappers/create-community-parent-selector/create-community-parent-selector.component.ts @@ -13,6 +13,13 @@ import { SelectorActionType } from '../dso-selector-modal-wrapper.component'; +/** + * Component to wrap a button - for top communities - + * and a list of parent communities - for sub communities + * inside a modal + * Used to create a new community + */ + @Component({ selector: 'ds-create-community-parent-selector', styleUrls: ['./create-community-parent-selector.component.scss'], diff --git a/src/app/shared/dso-selector/modal-wrappers/create-item-parent-selector/create-item-parent-selector.component.ts b/src/app/shared/dso-selector/modal-wrappers/create-item-parent-selector/create-item-parent-selector.component.ts index 5dc6e4fe78..dac5888bf7 100644 --- a/src/app/shared/dso-selector/modal-wrappers/create-item-parent-selector/create-item-parent-selector.component.ts +++ b/src/app/shared/dso-selector/modal-wrappers/create-item-parent-selector/create-item-parent-selector.component.ts @@ -14,6 +14,11 @@ import { SelectorActionType } from '../dso-selector-modal-wrapper.component'; +/** + * Component to wrap a list of existing collections inside a modal + * Used to choose a collection from to create a new item in + */ + @Component({ selector: 'ds-create-item-parent-selector', // styleUrls: ['./create-item-parent-selector.component.scss'], diff --git a/src/app/shared/dso-selector/modal-wrappers/dso-selector-modal-wrapper.component.ts b/src/app/shared/dso-selector/modal-wrappers/dso-selector-modal-wrapper.component.ts index 8414f00830..351a92302c 100644 --- a/src/app/shared/dso-selector/modal-wrappers/dso-selector-modal-wrapper.component.ts +++ b/src/app/shared/dso-selector/modal-wrappers/dso-selector-modal-wrapper.component.ts @@ -12,6 +12,10 @@ export enum SelectorActionType { EDIT = 'edit' } +/** + * Abstract base class that represents a wrapper for modal content used to select a DSpace Object + */ + @Injectable() export abstract class DSOSelectorModalWrapperComponent implements OnInit { /** diff --git a/src/app/shared/dso-selector/modal-wrappers/edit-collection-selector/edit-collection-selector.component.ts b/src/app/shared/dso-selector/modal-wrappers/edit-collection-selector/edit-collection-selector.component.ts index dab5b8eea3..79660b9589 100644 --- a/src/app/shared/dso-selector/modal-wrappers/edit-collection-selector/edit-collection-selector.component.ts +++ b/src/app/shared/dso-selector/modal-wrappers/edit-collection-selector/edit-collection-selector.component.ts @@ -9,6 +9,11 @@ import { SelectorActionType } from '../dso-selector-modal-wrapper.component'; +/** + * Component to wrap a list of existing collections inside a modal + * Used to choose a collection from to edit + */ + @Component({ selector: 'ds-edit-collection-selector', templateUrl: '../dso-selector-modal-wrapper.component.html', diff --git a/src/app/shared/dso-selector/modal-wrappers/edit-community-selector/edit-community-selector.component.ts b/src/app/shared/dso-selector/modal-wrappers/edit-community-selector/edit-community-selector.component.ts index ce688d17ae..6b9efc1ff4 100644 --- a/src/app/shared/dso-selector/modal-wrappers/edit-community-selector/edit-community-selector.component.ts +++ b/src/app/shared/dso-selector/modal-wrappers/edit-community-selector/edit-community-selector.component.ts @@ -9,6 +9,11 @@ import { SelectorActionType } from '../dso-selector-modal-wrapper.component'; +/** + * Component to wrap a list of existing communities inside a modal + * Used to choose a community from to edit + */ + @Component({ selector: 'ds-edit-community-selector', templateUrl: '../dso-selector-modal-wrapper.component.html', diff --git a/src/app/shared/dso-selector/modal-wrappers/edit-item-selector/edit-item-selector.component.ts b/src/app/shared/dso-selector/modal-wrappers/edit-item-selector/edit-item-selector.component.ts index e14be10435..9182df8045 100644 --- a/src/app/shared/dso-selector/modal-wrappers/edit-item-selector/edit-item-selector.component.ts +++ b/src/app/shared/dso-selector/modal-wrappers/edit-item-selector/edit-item-selector.component.ts @@ -15,6 +15,11 @@ import { SelectorActionType } from '../dso-selector-modal-wrapper.component'; +/** + * Component to wrap a list of existing items inside a modal + * Used to choose an item from to edit + */ + @Component({ selector: 'ds-edit-item-selector', templateUrl: '../dso-selector-modal-wrapper.component.html', From 88ae626736d00226413e679a5caf04eaaa16942b Mon Sep 17 00:00:00 2001 From: lotte Date: Wed, 13 Mar 2019 15:51:04 +0100 Subject: [PATCH 11/17] fixed caching --- .../builders/remote-data-build.service.ts | 4 +- .../core/cache/object-cache.service.spec.ts | 6 +- src/app/core/cache/object-cache.service.ts | 14 +-- .../core/cache/server-sync-buffer.effects.ts | 2 +- src/app/core/data/comcol-data.service.spec.ts | 4 +- src/app/core/data/comcol-data.service.ts | 2 +- src/app/core/data/data.service.ts | 2 +- src/app/core/data/request.service.spec.ts | 106 +++++------------ src/app/core/data/request.service.ts | 111 +++++++----------- 9 files changed, 91 insertions(+), 160 deletions(-) diff --git a/src/app/core/cache/builders/remote-data-build.service.ts b/src/app/core/cache/builders/remote-data-build.service.ts index a59039c226..8d40741dc0 100644 --- a/src/app/core/cache/builders/remote-data-build.service.ts +++ b/src/app/core/cache/builders/remote-data-build.service.ts @@ -56,13 +56,13 @@ export class RemoteDataBuildService { const payload$ = observableCombineLatest( href$.pipe( - switchMap((href: string) => this.objectCache.getBySelfLink(href)), + switchMap((href: string) => this.objectCache.getObjectBySelfLink(href)), startWith(undefined)), requestEntry$.pipe( getResourceLinksFromResponse(), switchMap((resourceSelfLinks: string[]) => { if (isNotEmpty(resourceSelfLinks)) { - return this.objectCache.getBySelfLink(resourceSelfLinks[0]); + return this.objectCache.getObjectBySelfLink(resourceSelfLinks[0]); } else { return observableOf(undefined); } diff --git a/src/app/core/cache/object-cache.service.spec.ts b/src/app/core/cache/object-cache.service.spec.ts index af353a38c1..eae7c06be7 100644 --- a/src/app/core/cache/object-cache.service.spec.ts +++ b/src/app/core/cache/object-cache.service.spec.ts @@ -80,7 +80,7 @@ describe('ObjectCacheService', () => { }); // due to the implementation of spyOn above, this subscribe will be synchronous - service.getBySelfLink(selfLink).pipe(first()).subscribe((o) => { + service.getObjectBySelfLink(selfLink).pipe(first()).subscribe((o) => { expect(o.self).toBe(selfLink); // this only works if testObj is an instance of TestClass expect(o instanceof NormalizedItem).toBeTruthy(); @@ -96,7 +96,7 @@ describe('ObjectCacheService', () => { }); let getObsHasFired = false; - const subscription = service.getBySelfLink(selfLink).subscribe((o) => getObsHasFired = true); + const subscription = service.getObjectBySelfLink(selfLink).subscribe((o) => getObsHasFired = true); expect(getObsHasFired).toBe(false); subscription.unsubscribe(); }); @@ -106,7 +106,7 @@ describe('ObjectCacheService', () => { it('should return an observable of the array of cached objects with the specified self link and type', () => { const item = new NormalizedItem(); item.self = selfLink; - spyOn(service, 'getBySelfLink').and.returnValue(observableOf(item)); + spyOn(service, 'getObjectBySelfLink').and.returnValue(observableOf(item)); service.getList([selfLink, selfLink]).pipe(first()).subscribe((arr) => { expect(arr[0].self).toBe(selfLink); diff --git a/src/app/core/cache/object-cache.service.ts b/src/app/core/cache/object-cache.service.ts index d4d52b404f..384df23c22 100644 --- a/src/app/core/cache/object-cache.service.ts +++ b/src/app/core/cache/object-cache.service.ts @@ -78,16 +78,16 @@ export class ObjectCacheService { * @return Observable * An observable of the requested object */ - getByUUID(uuid: string): Observable> { + getObjectByUUID(uuid: string): Observable> { return this.store.pipe( select(selfLinkFromUuidSelector(uuid)), - mergeMap((selfLink: string) => this.getBySelfLink(selfLink) + mergeMap((selfLink: string) => this.getObjectBySelfLink(selfLink) ) ) } - getBySelfLink(selfLink: string): Observable> { - return this.getEntry(selfLink).pipe( + getObjectBySelfLink(selfLink: string): Observable> { + return this.getBySelfLink(selfLink).pipe( map((entry: ObjectCacheEntry) => { if (isNotEmpty(entry.patches)) { const flatPatch: Operation[] = [].concat(...entry.patches.map((patch) => patch.operations)); @@ -105,7 +105,7 @@ export class ObjectCacheService { ); } - private getEntry(selfLink: string): Observable { + getBySelfLink(selfLink: string): Observable { return this.store.pipe( select(entryFromSelfLinkSelector(selfLink)), filter((entry) => this.isValid(entry)), @@ -114,7 +114,7 @@ export class ObjectCacheService { } getRequestUUIDBySelfLink(selfLink: string): Observable { - return this.getEntry(selfLink).pipe( + return this.getBySelfLink(selfLink).pipe( map((entry: ObjectCacheEntry) => entry.requestUUID), distinctUntilChanged()); } @@ -147,7 +147,7 @@ export class ObjectCacheService { */ getList(selfLinks: string[]): Observable>> { return observableCombineLatest( - selfLinks.map((selfLink: string) => this.getBySelfLink(selfLink)) + selfLinks.map((selfLink: string) => this.getObjectBySelfLink(selfLink)) ); } diff --git a/src/app/core/cache/server-sync-buffer.effects.ts b/src/app/core/cache/server-sync-buffer.effects.ts index 0d7392e555..2e11f15540 100644 --- a/src/app/core/cache/server-sync-buffer.effects.ts +++ b/src/app/core/cache/server-sync-buffer.effects.ts @@ -95,7 +95,7 @@ export class ServerSyncBufferEffects { * @returns {Observable} ApplyPatchObjectCacheAction to be dispatched */ private applyPatch(href: string): Observable { - const patchObject = this.objectCache.getBySelfLink(href).pipe(take(1)); + const patchObject = this.objectCache.getObjectBySelfLink(href).pipe(take(1)); return patchObject.pipe( map((object) => { diff --git a/src/app/core/data/comcol-data.service.spec.ts b/src/app/core/data/comcol-data.service.spec.ts index 784075c855..d93600a06a 100644 --- a/src/app/core/data/comcol-data.service.spec.ts +++ b/src/app/core/data/comcol-data.service.spec.ts @@ -94,7 +94,7 @@ describe('ComColDataService', () => { function initMockObjectCacheService(): ObjectCacheService { return jasmine.createSpyObj('objectCache', { - getByUUID: cold('d-', { + getObjectByUUID: cold('d-', { d: { _links: { [LINK_NAME]: scopedEndpoint @@ -159,7 +159,7 @@ describe('ComColDataService', () => { it('should fetch the scope Community from the cache', () => { scheduler.schedule(() => service.getBrowseEndpoint(options).subscribe()); scheduler.flush(); - expect(objectCache.getByUUID).toHaveBeenCalledWith(scopeID); + expect(objectCache.getObjectByUUID).toHaveBeenCalledWith(scopeID); }); it('should return the endpoint to fetch resources within the given scope', () => { diff --git a/src/app/core/data/comcol-data.service.ts b/src/app/core/data/comcol-data.service.ts index 693b8af58b..9d82cc5047 100644 --- a/src/app/core/data/comcol-data.service.ts +++ b/src/app/core/data/comcol-data.service.ts @@ -49,7 +49,7 @@ export abstract class ComColDataService extends DataS ); const successResponses = responses.pipe( filter((response) => response.isSuccessful), - mergeMap(() => this.objectCache.getByUUID(options.scopeID)), + mergeMap(() => this.objectCache.getObjectByUUID(options.scopeID)), map((nc: NormalizedCommunity) => nc._links[linkPath]), filter((href) => isNotEmpty(href)) ); diff --git a/src/app/core/data/data.service.ts b/src/app/core/data/data.service.ts index 42115b6b6c..72af52c4c8 100644 --- a/src/app/core/data/data.service.ts +++ b/src/app/core/data/data.service.ts @@ -139,7 +139,7 @@ export abstract class DataService { * @param {DSpaceObject} object The given object */ update(object: T): Observable> { - const oldVersion$ = this.objectCache.getBySelfLink(object.self); + const oldVersion$ = this.objectCache.getObjectBySelfLink(object.self); return oldVersion$.pipe(take(1), mergeMap((oldVersion: T) => { const operations = this.comparator.diff(oldVersion, object); if (isNotEmpty(operations)) { diff --git a/src/app/core/data/request.service.spec.ts b/src/app/core/data/request.service.spec.ts index b28436f3a8..69d64cf470 100644 --- a/src/app/core/data/request.service.spec.ts +++ b/src/app/core/data/request.service.spec.ts @@ -24,7 +24,7 @@ import { BehaviorSubject } from 'rxjs/internal/BehaviorSubject'; import { MockStore } from '../../shared/testing/mock-store'; import { IndexState } from '../index/index.reducer'; -describe('RequestService', () => { +fdescribe('RequestService', () => { let scheduler: TestScheduler; let service: RequestService; let serviceAsAny: any; @@ -323,6 +323,7 @@ describe('RequestService', () => { describe('in the ObjectCache', () => { beforeEach(() => { (objectCache.hasBySelfLink as any).and.returnValue(true); + spyOn(serviceAsAny, 'hasByHref').and.returnValue(false); }); it('should return true', () => { @@ -332,63 +333,16 @@ describe('RequestService', () => { expect(result).toEqual(expected); }); }); - describe('in the responseCache', () => { + describe('in the request cache', () => { beforeEach(() => { - spyOn(serviceAsAny, 'isReusable').and.returnValue(observableOf(true)); - spyOn(serviceAsAny, 'getByHref').and.returnValue(observableOf(undefined)); + (objectCache.hasBySelfLink as any).and.returnValue(false); + spyOn(serviceAsAny, 'hasByHref').and.returnValue(true); }); + it('should return true', () => { + const result = serviceAsAny.isCachedOrPending(testGetRequest); + const expected = true; - describe('and it\'s a DSOSuccessResponse', () => { - beforeEach(() => { - (serviceAsAny.getByHref as any).and.returnValue(observableOf({ - response: { - isSuccessful: true, - resourceSelfLinks: [ - 'https://rest.api/endpoint/selfLink1', - 'https://rest.api/endpoint/selfLink2' - ] - } - } - )); - }); - - it('should return true if all top level links in the response are cached in the object cache', () => { - (objectCache.hasBySelfLink as any).and.returnValues(false, true, true); - - const result = serviceAsAny.isCachedOrPending(testGetRequest); - const expected = true; - - expect(result).toEqual(expected); - }); - it('should return false if not all top level links in the response are cached in the object cache', () => { - (objectCache.hasBySelfLink as any).and.returnValues(false, true, false); - spyOn(service, 'isPending').and.returnValue(false); - - const result = serviceAsAny.isCachedOrPending(testGetRequest); - const expected = false; - - expect(result).toEqual(expected); - }); - }); - - describe('and it isn\'t a DSOSuccessResponse', () => { - beforeEach(() => { - (objectCache.hasBySelfLink as any).and.returnValue(false); - (service as any).isReusable.and.returnValue(observableOf(true)); - (serviceAsAny.getByHref as any).and.returnValue(observableOf({ - response: { - isSuccessful: true - } - } - )); - }); - - it('should return true', () => { - const result = serviceAsAny.isCachedOrPending(testGetRequest); - const expected = true; - - expect(result).toEqual(expected); - }); + expect(result).toEqual(expected); }); }); }); @@ -462,56 +416,56 @@ describe('RequestService', () => { }); }); - describe('isReusable', () => { - describe('when the given UUID is has no value', () => { - let reusable; + describe('isValid', () => { + describe('when the given UUID has no value', () => { + let valid; beforeEach(() => { const uuid = undefined; - reusable = serviceAsAny.isReusable(uuid); + valid = serviceAsAny.isValid(uuid); }); it('return an observable emitting false', () => { - reusable.subscribe((isReusable) => expect(isReusable).toBe(false)); + valid.subscribe((isValid) => expect(isValid).toBe(false)); }) }); describe('when the given UUID has a value, but no cached entry is found', () => { - let reusable; + let valid; beforeEach(() => { spyOn(service, 'getByUUID').and.returnValue(observableOf(undefined)); const uuid = 'a45bb291-1adb-40d9-b2fc-7ad9080607be'; - reusable = serviceAsAny.isReusable(uuid); + valid = serviceAsAny.isValid(uuid); }); it('return an observable emitting false', () => { - reusable.subscribe((isReusable) => expect(isReusable).toBe(false)); + valid.subscribe((isValid) => expect(isValid).toBe(false)); }) }); describe('when the given UUID has a value, a cached entry is found, but it has no response', () => { - let reusable; + let valid; beforeEach(() => { spyOn(service, 'getByUUID').and.returnValue(observableOf({ response: undefined })); const uuid = '53c9b814-ad8b-4567-9bc1-d9bb6cfba6c8'; - reusable = serviceAsAny.isReusable(uuid); + valid = serviceAsAny.isValid(uuid); }); it('return an observable emitting false', () => { - reusable.subscribe((isReusable) => expect(isReusable).toBe(false)); + valid.subscribe((isValid) => expect(isValid).toBe(false)); }) }); describe('when the given UUID has a value, a cached entry is found, but its response was not successful', () => { - let reusable; + let valid; beforeEach(() => { spyOn(service, 'getByUUID').and.returnValue(observableOf({ response: { isSuccessful: false } })); const uuid = '694c9b32-7b2e-4788-835b-ef3fc2252e6c'; - reusable = serviceAsAny.isReusable(uuid); + valid = serviceAsAny.isValid(uuid); }); it('return an observable emitting false', () => { - reusable.subscribe((isReusable) => expect(isReusable).toBe(false)); + valid.subscribe((isValid) => expect(isValid).toBe(false)); }) }); - describe('when the given UUID has a value, a cached entry is found, its response was successful, but the response is outdated', () => { - let reusable; + fdescribe('when the given UUID has a value, a cached entry is found, its response was successful, but the response is outdated', () => { + let valid; const now = 100000; const timeAdded = 99899; const msToLive = 100; @@ -528,16 +482,16 @@ describe('RequestService', () => { } })); const uuid = 'f9b85788-881c-4994-86b6-bae8dad024d2'; - reusable = serviceAsAny.isReusable(uuid); + valid = serviceAsAny.isValid(uuid); }); it('return an observable emitting false', () => { - reusable.subscribe((isReusable) => expect(isReusable).toBe(false)); + valid.subscribe((isValid) => expect(isValid).toBe(false)); }) }); describe('when the given UUID has a value, a cached entry is found, its response was successful, and the response is not outdated', () => { - let reusable; + let valid; const now = 100000; const timeAdded = 99999; const msToLive = 100; @@ -554,11 +508,11 @@ describe('RequestService', () => { } })); const uuid = 'f9b85788-881c-4994-86b6-bae8dad024d2'; - reusable = serviceAsAny.isReusable(uuid); + valid = serviceAsAny.isValid(uuid); }); it('return an observable emitting true', () => { - reusable.subscribe((isReusable) => expect(isReusable).toBe(true)); + valid.subscribe((isValid) => expect(isValid).toBe(true)); }) }) }) diff --git a/src/app/core/data/request.service.ts b/src/app/core/data/request.service.ts index 93a7a10506..4fd7b84196 100644 --- a/src/app/core/data/request.service.ts +++ b/src/app/core/data/request.service.ts @@ -1,36 +1,25 @@ -import { merge as observableMerge, Observable, of as observableOf } from 'rxjs'; -import { - distinctUntilChanged, - filter, - find, - first, - map, - mergeMap, - reduce, - startWith, - switchMap, - take, - tap -} from 'rxjs/operators'; -import { race as observableRace } from 'rxjs'; +import { Observable, race as observableRace } from 'rxjs'; +import { filter, mergeMap, take } from 'rxjs/operators'; import { Injectable } from '@angular/core'; import { createSelector, MemoizedSelector, select, Store } from '@ngrx/store'; -import { hasNoValue, hasValue, isNotEmpty, isNotUndefined } from '../../shared/empty.util'; +import { hasValue, isNotEmpty } from '../../shared/empty.util'; import { CacheableObject } from '../cache/object-cache.reducer'; import { ObjectCacheService } from '../cache/object-cache.service'; -import { DSOSuccessResponse, RestResponse } from '../cache/response.models'; import { coreSelector, CoreState } from '../core.reducers'; import { IndexName, IndexState } from '../index/index.reducer'; import { pathSelector } from '../shared/selectors'; import { UUIDService } from '../shared/uuid.service'; -import { RequestConfigureAction, RequestExecuteAction, RequestRemoveAction } from './request.actions'; -import { GetRequest, RestRequest } from './request.models'; +import { + RequestConfigureAction, + RequestExecuteAction, + RequestRemoveAction +} from './request.actions'; +import { EndpointMapRequest, GetRequest, RestRequest } from './request.models'; import { RequestEntry } from './request.reducer'; import { CommitSSBAction } from '../cache/server-sync-buffer.actions'; import { RestRequestMethod } from './rest-request-method'; -import { getResponseFromEntry } from '../shared/operators'; import { AddToIndexAction, RemoveFromIndexBySubstringAction } from '../index/index.actions'; @Injectable() @@ -104,7 +93,6 @@ export class RequestService { .subscribe((re: RequestEntry) => { isPending = (hasValue(re) && !re.completed) }); - return isPending; } @@ -183,31 +171,11 @@ export class RequestService { * @param {GetRequest} request The request to check * @returns {boolean} True if the request is cached or still pending */ - private isCachedOrPending(request: GetRequest) { - let isCached = this.objectCache.hasBySelfLink(request.href); - if (isCached) { - const responses: Observable = this.isReusable(request.uuid).pipe( - filter((reusable: boolean) => reusable), - switchMap(() => { - return this.getByHref(request.href).pipe( - getResponseFromEntry(), - take(1) - ); - } - )); + private isCachedOrPending(request: GetRequest): boolean { + const inReqCache = this.hasByHref(request.href); + const inObjCache = this.objectCache.hasBySelfLink(request.href); + const isCached = inReqCache || inObjCache; - const errorResponses = responses.pipe(filter((response) => !response.isSuccessful), map(() => true)); // TODO add a configurable number of retries in case of an error. - const dsoSuccessResponses = responses.pipe( - filter((response) => response.isSuccessful && hasValue((response as DSOSuccessResponse).resourceSelfLinks)), - map((response: DSOSuccessResponse) => response.resourceSelfLinks), - map((resourceSelfLinks: string[]) => resourceSelfLinks - .every((selfLink) => this.objectCache.hasBySelfLink(selfLink)) - )); - - const otherSuccessResponses = responses.pipe(filter((response) => response.isSuccessful && !hasValue((response as DSOSuccessResponse).resourceSelfLinks)), map(() => true)); - - observableMerge(errorResponses, otherSuccessResponses, dsoSuccessResponses).subscribe((c) => isCached = c); - } const isPending = this.isPending(request); return isCached || isPending; } @@ -230,7 +198,7 @@ export class RequestService { */ private trackRequestsOnTheirWayToTheStore(request: GetRequest) { this.requestsOnTheirWayToTheStore = [...this.requestsOnTheirWayToTheStore, request.href]; - this.store.pipe(select(this.entryFromUUIDSelector(request.href)), + this.getByHref(request.href).pipe( filter((re: RequestEntry) => hasValue(re)), take(1) ).subscribe((re: RequestEntry) => { @@ -247,31 +215,40 @@ export class RequestService { } /** - * Check whether a Response should still be cached + * Check whether a cached response should still be valid * - * @param uuid - * the uuid of the entry to check + * @param entry + * the entry to check * @return boolean - * false if the uuid has no value, no entry could be found, the response was nog successful or its time to - * live has exceeded, true otherwise + * false if the uuid has no value, the response was not successful or its time to + * live was exceeded, true otherwise */ - private isReusable(uuid: string): Observable { - if (hasNoValue(uuid)) { - return observableOf(false); + private isValid(entry: RequestEntry): boolean { + if (hasValue(entry) && entry.completed && entry.response.isSuccessful) { + const timeOutdated = entry.response.timeAdded + entry.request.responseMsToLive; + const isOutDated = new Date().getTime() > timeOutdated; + return !isOutDated; } else { - const requestEntry$ = this.getByUUID(uuid); - return requestEntry$.pipe( - filter((entry: RequestEntry) => hasValue(entry) && hasValue(entry.response)), - map((entry: RequestEntry) => { - if (hasValue(entry) && entry.response.isSuccessful) { - const timeOutdated = entry.response.timeAdded + entry.request.responseMsToLive; - const isOutDated = new Date().getTime() > timeOutdated; - return !isOutDated; - } else { - return false; - } - }) - ); + return false; } } + + /** + * Check whether the request with the specified href is cached + * + * @param href + * The link of the request to check + * @return boolean + * true if the request with the specified href is cached, + * false otherwise + */ + hasByHref(href: string): boolean { + let result = false; + this.getByHref(href).pipe( + take(1) + ).subscribe((requestEntry: RequestEntry) => result = this.isValid(requestEntry)); + + return result; + } + } From 4c150988e26ce985378c32b55f785a8812da5f25 Mon Sep 17 00:00:00 2001 From: lotte Date: Wed, 13 Mar 2019 16:28:46 +0100 Subject: [PATCH 12/17] fixed tests after changes to request caching --- .../cache/server-sync-buffer.effects.spec.ts | 2 +- src/app/core/data/data.service.spec.ts | 4 +- src/app/core/data/request.service.spec.ts | 95 +++++++++---------- 3 files changed, 46 insertions(+), 55 deletions(-) diff --git a/src/app/core/cache/server-sync-buffer.effects.spec.ts b/src/app/core/cache/server-sync-buffer.effects.spec.ts index 0a8d50107e..87d8804e9c 100644 --- a/src/app/core/cache/server-sync-buffer.effects.spec.ts +++ b/src/app/core/cache/server-sync-buffer.effects.spec.ts @@ -47,7 +47,7 @@ describe('ServerSyncBufferEffects', () => { { provide: RequestService, useValue: getMockRequestService() }, { provide: ObjectCacheService, useValue: { - getBySelfLink: (link) => { + getObjectBySelfLink: (link) => { const object = new DSpaceObject(); object.self = link; return observableOf(object); diff --git a/src/app/core/data/data.service.spec.ts b/src/app/core/data/data.service.spec.ts index 178a16d4c1..51474f6740 100644 --- a/src/app/core/data/data.service.spec.ts +++ b/src/app/core/data/data.service.spec.ts @@ -67,7 +67,7 @@ describe('DataService', () => { addPatch: () => { /* empty */ }, - getBySelfLink: () => { + getObjectBySelfLink: () => { /* empty */ } } as any; @@ -189,7 +189,7 @@ describe('DataService', () => { dso2.metadata = [{ key: 'dc.title', value: name2 }]; spyOn(service, 'findById').and.returnValues(observableOf(dso)); - spyOn(objectCache, 'getBySelfLink').and.returnValues(observableOf(dso)); + spyOn(objectCache, 'getObjectBySelfLink').and.returnValues(observableOf(dso)); spyOn(objectCache, 'addPatch'); }); diff --git a/src/app/core/data/request.service.spec.ts b/src/app/core/data/request.service.spec.ts index 69d64cf470..1ff55f9871 100644 --- a/src/app/core/data/request.service.spec.ts +++ b/src/app/core/data/request.service.spec.ts @@ -24,7 +24,7 @@ import { BehaviorSubject } from 'rxjs/internal/BehaviorSubject'; import { MockStore } from '../../shared/testing/mock-store'; import { IndexState } from '../index/index.reducer'; -fdescribe('RequestService', () => { +describe('RequestService', () => { let scheduler: TestScheduler; let service: RequestService; let serviceAsAny: any; @@ -42,6 +42,7 @@ fdescribe('RequestService', () => { const testHeadRequest = new HeadRequest(testUUID, testHref); const testPatchRequest = new PatchRequest(testUUID, testHref); let selectSpy; + beforeEach(() => { scheduler = getTestScheduler(); @@ -417,76 +418,65 @@ fdescribe('RequestService', () => { }); describe('isValid', () => { - describe('when the given UUID has no value', () => { + describe('when the given entry has no value', () => { let valid; beforeEach(() => { - const uuid = undefined; - valid = serviceAsAny.isValid(uuid); + const entry = undefined; + valid = serviceAsAny.isValid(entry); }); it('return an observable emitting false', () => { - valid.subscribe((isValid) => expect(isValid).toBe(false)); + expect(valid).toBe(false); }) }); - describe('when the given UUID has a value, but no cached entry is found', () => { + describe('when the given entry has a value, but the request is not completed', () => { let valid; + const requestEntry = { completed: false } ; beforeEach(() => { - spyOn(service, 'getByUUID').and.returnValue(observableOf(undefined)); - const uuid = 'a45bb291-1adb-40d9-b2fc-7ad9080607be'; - valid = serviceAsAny.isValid(uuid); + spyOn(service, 'getByUUID').and.returnValue(observableOf(requestEntry)); + valid = serviceAsAny.isValid(requestEntry); }); it('return an observable emitting false', () => { - valid.subscribe((isValid) => expect(isValid).toBe(false)); + expect(valid).toBe(false); }) }); - describe('when the given UUID has a value, a cached entry is found, but it has no response', () => { + describe('when the given entry has a value, but the response is not successful', () => { let valid; + const requestEntry = { completed: true, response: { isSuccessful: false } }; beforeEach(() => { - spyOn(service, 'getByUUID').and.returnValue(observableOf({ response: undefined })); - const uuid = '53c9b814-ad8b-4567-9bc1-d9bb6cfba6c8'; - valid = serviceAsAny.isValid(uuid); + spyOn(service, 'getByUUID').and.returnValue(observableOf(requestEntry)); + valid = serviceAsAny.isValid(requestEntry); }); it('return an observable emitting false', () => { - valid.subscribe((isValid) => expect(isValid).toBe(false)); + expect(valid).toBe(false); }) }); - describe('when the given UUID has a value, a cached entry is found, but its response was not successful', () => { - let valid; - beforeEach(() => { - spyOn(service, 'getByUUID').and.returnValue(observableOf({ response: { isSuccessful: false } })); - const uuid = '694c9b32-7b2e-4788-835b-ef3fc2252e6c'; - valid = serviceAsAny.isValid(uuid); - }); - it('return an observable emitting false', () => { - valid.subscribe((isValid) => expect(isValid).toBe(false)); - }) - }); - - fdescribe('when the given UUID has a value, a cached entry is found, its response was successful, but the response is outdated', () => { + describe('when the given UUID has a value, its response was successful, but the response is outdated', () => { let valid; const now = 100000; const timeAdded = 99899; const msToLive = 100; + const requestEntry = { + completed: true, + response: { + isSuccessful: true, + timeAdded: timeAdded + }, + request: { + responseMsToLive: msToLive, + } + }; beforeEach(() => { spyOn(Date.prototype, 'getTime').and.returnValue(now); - spyOn(service, 'getByUUID').and.returnValue(observableOf({ - response: { - isSuccessful: true, - timeAdded: timeAdded - }, - request: { - responseMsToLive: msToLive - } - })); - const uuid = 'f9b85788-881c-4994-86b6-bae8dad024d2'; - valid = serviceAsAny.isValid(uuid); + spyOn(service, 'getByUUID').and.returnValue(observableOf(requestEntry)); + valid = serviceAsAny.isValid(requestEntry); }); it('return an observable emitting false', () => { - valid.subscribe((isValid) => expect(isValid).toBe(false)); + expect(valid).toBe(false); }) }); @@ -496,23 +486,24 @@ fdescribe('RequestService', () => { const timeAdded = 99999; const msToLive = 100; + const requestEntry = { + completed: true, + response: { + isSuccessful: true, + timeAdded: timeAdded + }, + request: { + responseMsToLive: msToLive + } + }; beforeEach(() => { spyOn(Date.prototype, 'getTime').and.returnValue(now); - spyOn(service, 'getByUUID').and.returnValue(observableOf({ - response: { - isSuccessful: true, - timeAdded: timeAdded - }, - request: { - responseMsToLive: msToLive - } - })); - const uuid = 'f9b85788-881c-4994-86b6-bae8dad024d2'; - valid = serviceAsAny.isValid(uuid); + spyOn(service, 'getByUUID').and.returnValue(observableOf(requestEntry)); + valid = serviceAsAny.isValid(requestEntry); }); it('return an observable emitting true', () => { - valid.subscribe((isValid) => expect(isValid).toBe(true)); + expect(valid).toBe(true); }) }) }) From 917c00f8fbca40b97840e35fbc42e0c5609ef16a Mon Sep 17 00:00:00 2001 From: lotte Date: Thu, 14 Mar 2019 11:14:59 +0100 Subject: [PATCH 13/17] added missing tests and docs --- src/app/core/cache/object-cache.service.ts | 44 ++++++++++++++++----- src/app/core/data/request.models.ts | 2 +- src/app/core/data/request.service.spec.ts | 46 ++++++++++++++++++---- src/app/core/data/request.service.ts | 10 ++++- 4 files changed, 83 insertions(+), 19 deletions(-) diff --git a/src/app/core/cache/object-cache.service.ts b/src/app/core/cache/object-cache.service.ts index 384df23c22..b4c37df736 100644 --- a/src/app/core/cache/object-cache.service.ts +++ b/src/app/core/cache/object-cache.service.ts @@ -65,18 +65,10 @@ export class ObjectCacheService { /** * Get an observable of the object with the specified UUID * - * The type needs to be specified as well, in order to turn - * the cached plain javascript object in to an instance of - * a class. - * - * e.g. getByUUID('c96588c6-72d3-425d-9d47-fa896255a695', Item) - * * @param uuid * The UUID of the object to get - * @param type - * The type of the object to get - * @return Observable - * An observable of the requested object + * @return Observable> + * An observable of the requested object in normalized form */ getObjectByUUID(uuid: string): Observable> { return this.store.pipe( @@ -86,6 +78,14 @@ export class ObjectCacheService { ) } + /** + * Get an observable of the object with the specified selfLink + * + * @param selfLink + * The selfLink of the object to get + * @return Observable> + * An observable of the requested object in normalized form + */ getObjectBySelfLink(selfLink: string): Observable> { return this.getBySelfLink(selfLink).pipe( map((entry: ObjectCacheEntry) => { @@ -105,6 +105,14 @@ export class ObjectCacheService { ); } + /** + * Get an observable of the object cache entry with the specified selfLink + * + * @param selfLink + * The selfLink of the object to get + * @return Observable + * An observable of the requested object cache entry + */ getBySelfLink(selfLink: string): Observable { return this.store.pipe( select(entryFromSelfLinkSelector(selfLink)), @@ -113,12 +121,28 @@ export class ObjectCacheService { ); } + /** + * Get an observable of the request's uuid with the specified selfLink + * + * @param selfLink + * The selfLink of the object to get + * @return Observable + * An observable of the request's uuid + */ getRequestUUIDBySelfLink(selfLink: string): Observable { return this.getBySelfLink(selfLink).pipe( map((entry: ObjectCacheEntry) => entry.requestUUID), distinctUntilChanged()); } + /** + * Get an observable of the request's uuid with the specified uuid + * + * @param uuid + * The uuid of the object to get + * @return Observable + * An observable of the request's uuid + */ getRequestUUIDByObjectUUID(uuid: string): Observable { return this.store.pipe( select(selfLinkFromUuidSelector(uuid)), diff --git a/src/app/core/data/request.models.ts b/src/app/core/data/request.models.ts index 951dbacff6..11ead7b53c 100644 --- a/src/app/core/data/request.models.ts +++ b/src/app/core/data/request.models.ts @@ -39,7 +39,7 @@ export abstract class RestRequest { } export class GetRequest extends RestRequest { - public responseMsToLive = 60 * 15 * 1000; + public responseMsToLive = 10000; constructor( public uuid: string, diff --git a/src/app/core/data/request.service.spec.ts b/src/app/core/data/request.service.spec.ts index 1ff55f9871..b3d9436d30 100644 --- a/src/app/core/data/request.service.spec.ts +++ b/src/app/core/data/request.service.spec.ts @@ -1,5 +1,5 @@ import { cold, getTestScheduler, hot } from 'jasmine-marbles'; -import { of as observableOf } from 'rxjs'; +import { of as observableOf, EMPTY } from 'rxjs'; import { getMockObjectCacheService } from '../../shared/mocks/mock-object-cache.service'; import { defaultUUID, getMockUUIDService } from '../../shared/mocks/mock-uuid.service'; import { ObjectCacheService } from '../cache/object-cache.service'; @@ -7,6 +7,7 @@ import { CoreState } from '../core.reducers'; import { UUIDService } from '../shared/uuid.service'; import { RequestConfigureAction, RequestExecuteAction } from './request.actions'; import * as ngrx from '@ngrx/store'; +import { ActionsSubject, Store } from '@ngrx/store'; import { DeleteRequest, GetRequest, @@ -18,11 +19,8 @@ import { RestRequest } from './request.models'; import { RequestService } from './request.service'; -import { ActionsSubject, Store } from '@ngrx/store'; import { TestScheduler } from 'rxjs/testing'; import { BehaviorSubject } from 'rxjs/internal/BehaviorSubject'; -import { MockStore } from '../../shared/testing/mock-store'; -import { IndexState } from '../index/index.reducer'; describe('RequestService', () => { let scheduler: TestScheduler; @@ -431,7 +429,7 @@ describe('RequestService', () => { describe('when the given entry has a value, but the request is not completed', () => { let valid; - const requestEntry = { completed: false } ; + const requestEntry = { completed: false }; beforeEach(() => { spyOn(service, 'getByUUID').and.returnValue(observableOf(requestEntry)); valid = serviceAsAny.isValid(requestEntry); @@ -503,8 +501,42 @@ describe('RequestService', () => { }); it('return an observable emitting true', () => { - expect(valid).toBe(true); + expect(valid).toBe(true); }) }) - }) + }); + + describe('hasByHref', () => { + describe('when nothing is returned by getByHref', () => { + beforeEach(() => { + spyOn(service, 'getByHref').and.returnValue(EMPTY); + }); + it('hasByHref should return false', () => { + const result = service.hasByHref(''); + expect(result).toBe(false); + }); + }); + + describe('when isValid returns false', () => { + beforeEach(() => { + spyOn(service, 'getByHref').and.returnValue(observableOf(undefined)); + spyOn(service as any, 'isValid').and.returnValue(false); + }); + it('hasByHref should return false', () => { + const result = service.hasByHref(''); + expect(result).toBe(false); + }); + }); + + describe('when isValid returns true', () => { + beforeEach(() => { + spyOn(service, 'getByHref').and.returnValue(observableOf(undefined)); + spyOn(service as any, 'isValid').and.returnValue(true); + }); + it('hasByHref should return true', () => { + const result = service.hasByHref(''); + expect(result).toBe(true); + }); + }); + }); }); diff --git a/src/app/core/data/request.service.ts b/src/app/core/data/request.service.ts index 4fd7b84196..f129f8becd 100644 --- a/src/app/core/data/request.service.ts +++ b/src/app/core/data/request.service.ts @@ -80,6 +80,9 @@ export class RequestService { return `client/${this.uuidService.generate()}`; } + /** + * Check if a request is currently pending + */ isPending(request: GetRequest): boolean { // first check requests that haven't made it to the store yet if (this.requestsOnTheirWayToTheStore.includes(request.href)) { @@ -96,6 +99,9 @@ export class RequestService { return isPending; } + /** + * Retrieve a RequestEntry based on their uuid + */ getByUUID(uuid: string): Observable { return observableRace( this.store.pipe(select(this.entryFromUUIDSelector(uuid))), @@ -108,6 +114,9 @@ export class RequestService { ); } + /** + * Retrieve a RequestEntry based on their href + */ getByHref(href: string): Observable { return this.store.pipe( select(this.uuidFromHrefSelector(href)), @@ -247,7 +256,6 @@ export class RequestService { this.getByHref(href).pipe( take(1) ).subscribe((requestEntry: RequestEntry) => result = this.isValid(requestEntry)); - return result; } From f160196cf3ae8c7b8095310d17bafa793e15abf1 Mon Sep 17 00:00:00 2001 From: lotte Date: Thu, 14 Mar 2019 11:35:00 +0100 Subject: [PATCH 14/17] reinstated responseMsToLive for get requests --- src/app/core/data/request.models.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/app/core/data/request.models.ts b/src/app/core/data/request.models.ts index 11ead7b53c..951dbacff6 100644 --- a/src/app/core/data/request.models.ts +++ b/src/app/core/data/request.models.ts @@ -39,7 +39,7 @@ export abstract class RestRequest { } export class GetRequest extends RestRequest { - public responseMsToLive = 10000; + public responseMsToLive = 60 * 15 * 1000; constructor( public uuid: string, From 6f55788f37a1b16ccbba3aca5ede247910f3d436 Mon Sep 17 00:00:00 2001 From: lotte Date: Fri, 15 Mar 2019 10:16:35 +0100 Subject: [PATCH 15/17] 61116: bootstrap upgrade --- package.json | 4 ++-- yarn.lock | 12 ++++++------ 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/package.json b/package.json index fd037de3f7..7dba45c6df 100644 --- a/package.json +++ b/package.json @@ -89,7 +89,7 @@ "angular2-text-mask": "9.0.0", "angulartics2": "^6.2.0", "body-parser": "1.18.2", - "bootstrap": "4.1.3", + "bootstrap": "4.3.1", "cerialize": "0.1.18", "compression": "1.7.1", "cookie-parser": "1.4.3", @@ -111,7 +111,7 @@ "ng-mocks": "^6.2.1", "ng2-file-upload": "1.2.1", "ng2-nouislider": "^1.7.11", - "ngx-bootstrap": "^3.0.1", + "ngx-bootstrap": "^3.2.0", "ngx-infinite-scroll": "6.0.1", "ngx-moment": "^3.1.0", "ngx-pagination": "3.0.3", diff --git a/yarn.lock b/yarn.lock index d71d9b9186..d4c5002646 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1207,9 +1207,9 @@ boom@5.x.x: dependencies: hoek "4.x.x" -bootstrap@4.1.3: - version "4.1.3" - resolved "https://registry.yarnpkg.com/bootstrap/-/bootstrap-4.1.3.tgz#0eb371af2c8448e8c210411d0cb824a6409a12be" +bootstrap@4.3.1: + version "4.3.1" + resolved "https://registry.yarnpkg.com/bootstrap/-/bootstrap-4.3.1.tgz#280ca8f610504d99d7b6b4bfc4b68cec601704ac" boxen@^1.2.1: version "1.3.0" @@ -5394,9 +5394,9 @@ ngrx-store-freeze@^0.2.4: dependencies: deep-freeze-strict "^1.1.1" -ngx-bootstrap@^3.0.1: - version "3.0.1" - resolved "https://registry.yarnpkg.com/ngx-bootstrap/-/ngx-bootstrap-3.0.1.tgz#e98d2fc6340f32a9d358cd08e8fda7dcb23bdab3" +ngx-bootstrap@^3.2.0: + version "3.2.0" + resolved "https://registry.yarnpkg.com/ngx-bootstrap/-/ngx-bootstrap-3.2.0.tgz#ece7c48af0bc260462c3f77de14f22d4b3dde149" ngx-infinite-scroll@6.0.1: version "6.0.1" From cc5783082f070e75cc8101957657d80f431374d7 Mon Sep 17 00:00:00 2001 From: Art Lowel Date: Fri, 15 Mar 2019 16:55:22 +0100 Subject: [PATCH 16/17] webpack: replace deprecated LoaderOptionsPlugin with OptimizeCSSAssetsPlugin --- package.json | 2 + webpack/webpack.prod.js | 17 +- webpack/webpack.test.js | 12 - yarn.lock | 756 +++++++++++++++++++++++++++++++++++++++- 4 files changed, 759 insertions(+), 28 deletions(-) diff --git a/package.json b/package.json index 7dba45c6df..0081f6231c 100644 --- a/package.json +++ b/package.json @@ -162,6 +162,7 @@ "copy-webpack-plugin": "^4.4.1", "coveralls": "3.0.0", "css-loader": "1.0.0", + "cssnano": "^4.1.10", "deep-freeze": "0.0.1", "exports-loader": "^0.7.0", "html-webpack-plugin": "^4.0.0-alpha", @@ -187,6 +188,7 @@ "node-sass": "^4.11.0", "nodemon": "^1.15.0", "npm-run-all": "4.1.3", + "optimize-css-assets-webpack-plugin": "^5.0.1", "postcss": "^7.0.2", "postcss-apply": "0.11.0", "postcss-cli": "^6.0.0", diff --git a/webpack/webpack.prod.js b/webpack/webpack.prod.js index 9b15b464e3..35a683bb96 100644 --- a/webpack/webpack.prod.js +++ b/webpack/webpack.prod.js @@ -2,6 +2,8 @@ const webpack = require('webpack'); const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin; const CompressionPlugin = require("compression-webpack-plugin"); const UglifyJsPlugin = require('uglifyjs-webpack-plugin'); +const OptimizeCSSAssetsPlugin = require("optimize-css-assets-webpack-plugin"); +const cssnano = require("cssnano"); const { root @@ -18,12 +20,6 @@ module.exports = { } }), - // Loader options - new webpack.LoaderOptionsPlugin({ - minimize: true, - debug: false - }), - new BundleAnalyzerPlugin({ analyzerMode: 'disabled', // change it to `server` to view bundle stats reportFilename: 'report.html', @@ -64,6 +60,15 @@ module.exports = { }, sourceMap: true } + }), + new OptimizeCSSAssetsPlugin({ + cssProcessor: cssnano, + cssProcessorOptions: { + discardComments: { + removeAll: true, + } + }, + safe: true }) ] }, diff --git a/webpack/webpack.test.js b/webpack/webpack.test.js index b0305728d3..8c6760e377 100644 --- a/webpack/webpack.test.js +++ b/webpack/webpack.test.js @@ -241,18 +241,6 @@ module.exports = function (options) { 'HMR': false, } }), - - /** - * Plugin LoaderOptionsPlugin (experimental) - * - * See: https://gist.github.com/sokra/27b24881210b56bbaff7 - */ - new LoaderOptionsPlugin({ - debug: false, - options: { - - } - }), new ForkTsCheckerWebpackPlugin() ], diff --git a/yarn.lock b/yarn.lock index d4c5002646..7399f373e6 100644 --- a/yarn.lock +++ b/yarn.lock @@ -349,6 +349,11 @@ version "0.0.32" resolved "https://registry.yarnpkg.com/@types/q/-/q-0.0.32.tgz#bd284e57c84f1325da702babfc82a5328190c0c5" +"@types/q@^1.5.1": + version "1.5.2" + resolved "https://registry.yarnpkg.com/@types/q/-/q-1.5.2.tgz#690a1475b84f2a884fd07cd797c00f5f31356ea8" + integrity sha512-ce5d3q03Ex0sy4R14722Rmt6MT07Ua+k4FwDfdcToYJcMKNtRVQvJ6JCAPdAmAnbRb6CsX6aYb9m96NGod9uTw== + "@types/range-parser@*": version "1.2.2" resolved "https://registry.yarnpkg.com/@types/range-parser/-/range-parser-1.2.2.tgz#fa8e1ad1d474688a757140c91de6dace6f4abc8d" @@ -622,6 +627,11 @@ align-text@^0.1.1, align-text@^0.1.3: longest "^1.0.1" repeat-string "^1.5.2" +alphanum-sort@^1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/alphanum-sort/-/alphanum-sort-1.0.2.tgz#97a1119649b211ad33691d9f9f486a8ec9fbe0a3" + integrity sha1-l6ERlkmyEa0zaR2fn0hqjsn74KM= + amdefine@>=0.0.4, amdefine@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/amdefine/-/amdefine-1.0.1.tgz#4a5282ac164729e93619bcfd3ad151f817ce91f5" @@ -1191,7 +1201,7 @@ bonjour@^3.5.0: multicast-dns "^6.0.1" multicast-dns-service-types "^1.1.0" -boolbase@~1.0.0: +boolbase@^1.0.0, boolbase@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/boolbase/-/boolbase-1.0.0.tgz#68dff5fbe60c51eb37725ea9e3ed310dcc1e776e" @@ -1323,6 +1333,15 @@ browserslist@^2.0.0, browserslist@^2.11.3: caniuse-lite "^1.0.30000792" electron-to-chromium "^1.3.30" +browserslist@^4.0.0: + version "4.4.2" + resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.4.2.tgz#6ea8a74d6464bb0bd549105f659b41197d8f0ba2" + integrity sha512-ISS/AIAiHERJ3d45Fz0AVYKkgcy+F/eJHzKEvv1j0wwKGKD9T3BrwKr/5g45L+Y4XIK5PlTqefHciRFcfE1Jxg== + dependencies: + caniuse-lite "^1.0.30000939" + electron-to-chromium "^1.3.113" + node-releases "^1.1.8" + browserslist@^4.0.2: version "4.1.0" resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.1.0.tgz#81cbb8e52dfa09918f93c6e051d779cb7360785d" @@ -1443,10 +1462,29 @@ call-me-maybe@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/call-me-maybe/-/call-me-maybe-1.0.1.tgz#26d208ea89e37b5cbde60250a15f031c16a4d66b" +caller-callsite@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/caller-callsite/-/caller-callsite-2.0.0.tgz#847e0fce0a223750a9a027c54b33731ad3154134" + integrity sha1-hH4PzgoiN1CpoCfFSzNzGtMVQTQ= + dependencies: + callsites "^2.0.0" + +caller-path@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/caller-path/-/caller-path-2.0.0.tgz#468f83044e369ab2010fac5f06ceee15bb2cb1f4" + integrity sha1-Ro+DBE42mrIBD6xfBs7uFbsssfQ= + dependencies: + caller-callsite "^2.0.0" + callsite@1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/callsite/-/callsite-1.0.0.tgz#280398e5d664bd74038b6f0905153e6e8af1bc20" +callsites@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/callsites/-/callsites-2.0.0.tgz#06eb84f00eea413da86affefacbffb36093b3c50" + integrity sha1-BuuE8A7qQT2oav/vrL/7Ngk7PFA= + camel-case@3.0.x: version "3.0.0" resolved "https://registry.yarnpkg.com/camel-case/-/camel-case-3.0.0.tgz#ca3c3688a4e9cf3a4cda777dc4dcbc713249cf73" @@ -1486,10 +1524,25 @@ caniuse-api@^2.0.0: lodash.memoize "^4.1.2" lodash.uniq "^4.5.0" +caniuse-api@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/caniuse-api/-/caniuse-api-3.0.0.tgz#5e4d90e2274961d46291997df599e3ed008ee4c0" + integrity sha512-bsTwuIg/BZZK/vreVTYYbSWoe2F+71P7K5QGEX+pT250DZbfU1MQ5prOKpPR+LL6uWKK3KMwMCAS74QB3Um1uw== + dependencies: + browserslist "^4.0.0" + caniuse-lite "^1.0.0" + lodash.memoize "^4.1.2" + lodash.uniq "^4.5.0" + caniuse-lite@^1.0.0, caniuse-lite@^1.0.30000697, caniuse-lite@^1.0.30000792, caniuse-lite@^1.0.30000805, caniuse-lite@^1.0.30000878: version "1.0.30000883" resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30000883.tgz#597c1eabfb379bd9fbeaa778632762eb574706ac" +caniuse-lite@^1.0.30000939: + version "1.0.30000948" + resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30000948.tgz#793ed7c28fe664856beb92b43fc013fc22b81633" + integrity sha512-Lw4y7oz1X5MOMZm+2IFaSISqVVQvUuD+ZUSfeYK/SlYiMjkHN/eJ2PDfJehW5NA6JjrxYSSnIWfwjeObQMEjFQ== + capture-stack-trace@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/capture-stack-trace/-/capture-stack-trace-1.0.0.tgz#4a6fa07399c26bba47f0b2496b4d0fb408c5550d" @@ -1529,6 +1582,15 @@ chalk@^2.0.0, chalk@^2.0.1, chalk@^2.1.0, chalk@^2.3.0, chalk@^2.4.1: escape-string-regexp "^1.0.5" supports-color "^5.3.0" +chalk@^2.4.2: + version "2.4.2" + resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424" + integrity sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ== + dependencies: + ansi-styles "^3.2.1" + escape-string-regexp "^1.0.5" + supports-color "^5.3.0" + chardet@^0.4.0: version "0.4.2" resolved "https://registry.yarnpkg.com/chardet/-/chardet-0.4.2.tgz#b5473b33dc97c424e5d98dc87d55d4d8a29c8bf2" @@ -1678,6 +1740,15 @@ co@^4.6.0: version "4.6.0" resolved "https://registry.yarnpkg.com/co/-/co-4.6.0.tgz#6ea6bdf3d853ae54ccb8e47bfa0bf3f9031fb184" +coa@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/coa/-/coa-2.0.2.tgz#43f6c21151b4ef2bf57187db0d73de229e3e7ec3" + integrity sha512-q5/jG+YQnSy4nRTV4F7lPepBJZ8qBNJJDBuJdoejDyLXgmL7IEo+Le2JDZudFTFt7mrCqIRaSjws4ygRCTCAXA== + dependencies: + "@types/q" "^1.5.1" + chalk "^2.4.1" + q "^1.1.2" + code-point-at@^1.0.0: version "1.1.0" resolved "https://registry.yarnpkg.com/code-point-at/-/code-point-at-1.1.0.tgz#0d070b4d043a5bea33a2f1a40e2edb3d9a4ccf77" @@ -1749,6 +1820,14 @@ color@^2.0.1: color-convert "^1.9.1" color-string "^1.5.2" +color@^3.0.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/color/-/color-3.1.0.tgz#d8e9fb096732875774c84bf922815df0308d0ffc" + integrity sha512-CwyopLkuRYO5ei2EpzpIh6LqJMt6Mt+jZhO5VI5f/wJLZriXQE32/SSqzmrh+QB+AZT81Cj8yv+7zwToW8ahZg== + dependencies: + color-convert "^1.9.1" + color-string "^1.5.2" + colors@1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/colors/-/colors-1.0.3.tgz#0433f44d809680fdeb60ed260f1b0c262e82a40b" @@ -1981,6 +2060,17 @@ cosmiconfig@^4.0.0: parse-json "^4.0.0" require-from-string "^2.0.1" +cosmiconfig@^5.0.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/cosmiconfig/-/cosmiconfig-5.1.0.tgz#6c5c35e97f37f985061cdf653f114784231185cf" + integrity sha512-kCNPvthka8gvLtzAxQXvWo4FxqRB+ftRZyPZNuab5ngvM9Y7yw7hbEysglptLgpkGX9nAOKTBVkHUAe8xtYR6Q== + dependencies: + import-fresh "^2.0.0" + is-directory "^0.3.1" + js-yaml "^3.9.0" + lodash.get "^4.4.2" + parse-json "^4.0.0" + coveralls@3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/coveralls/-/coveralls-3.0.0.tgz#22ef730330538080d29b8c151dc9146afde88a99" @@ -2106,6 +2196,19 @@ css-color-function@~1.3.3: debug "^3.1.0" rgb "~0.1.0" +css-color-names@0.0.4, css-color-names@^0.0.4: + version "0.0.4" + resolved "https://registry.yarnpkg.com/css-color-names/-/css-color-names-0.0.4.tgz#808adc2e79cf84738069b646cb20ec27beb629e0" + integrity sha1-gIrcLnnPhHOAabZGyyDsJ762KeA= + +css-declaration-sorter@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/css-declaration-sorter/-/css-declaration-sorter-4.0.1.tgz#c198940f63a76d7e36c1e71018b001721054cb22" + integrity sha512-BcxQSKTSEEQUftYpBVnsH4SF05NTuBokb19/sBt6asXGKZ/6VP7PLG1CBCkFDYOnhXhPh0jMhO6xZ71oYHXHBA== + dependencies: + postcss "^7.0.1" + timsort "^0.3.0" + css-loader@1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/css-loader/-/css-loader-1.0.0.tgz#9f46aaa5ca41dbe31860e3b62b8e23c42916bf56" @@ -2123,6 +2226,11 @@ css-loader@1.0.0: postcss-value-parser "^3.3.0" source-list-map "^2.0.0" +css-select-base-adapter@^0.1.1: + version "0.1.1" + resolved "https://registry.yarnpkg.com/css-select-base-adapter/-/css-select-base-adapter-0.1.1.tgz#3b2ff4972cc362ab88561507a95408a1432135d7" + integrity sha512-jQVeeRG70QI08vSTwf1jHxp74JoZsr2XSgETae8/xC8ovSnL2WF87GTLO86Sbwdt2lK4Umg4HnnwMO4YF3Ce7w== + css-select@^1.1.0: version "1.2.0" resolved "https://registry.yarnpkg.com/css-select/-/css-select-1.2.0.tgz#2b3a110539c5355f1cd8d314623e870b121ec858" @@ -2132,6 +2240,16 @@ css-select@^1.1.0: domutils "1.5.1" nth-check "~1.0.1" +css-select@^2.0.0: + version "2.0.2" + resolved "https://registry.yarnpkg.com/css-select/-/css-select-2.0.2.tgz#ab4386cec9e1f668855564b17c3733b43b2a5ede" + integrity sha512-dSpYaDVoWaELjvZ3mS6IKZM/y2PMPa/XYoEfYNZePL4U/XgyxZNroHEHReDx/d+VgXh9VbCTtFqLkFbmeqeaRQ== + dependencies: + boolbase "^1.0.0" + css-what "^2.1.2" + domutils "^1.7.0" + nth-check "^1.0.2" + css-selector-tokenizer@^0.7.0: version "0.7.0" resolved "https://registry.yarnpkg.com/css-selector-tokenizer/-/css-selector-tokenizer-0.7.0.tgz#e6988474ae8c953477bf5e7efecfceccd9cf4c86" @@ -2140,14 +2258,40 @@ css-selector-tokenizer@^0.7.0: fastparse "^1.1.1" regexpu-core "^1.0.0" +css-tree@1.0.0-alpha.28: + version "1.0.0-alpha.28" + resolved "https://registry.yarnpkg.com/css-tree/-/css-tree-1.0.0-alpha.28.tgz#8e8968190d886c9477bc8d61e96f61af3f7ffa7f" + integrity sha512-joNNW1gCp3qFFzj4St6zk+Wh/NBv0vM5YbEreZk0SD4S23S+1xBKb6cLDg2uj4P4k/GUMlIm6cKIDqIG+vdt0w== + dependencies: + mdn-data "~1.1.0" + source-map "^0.5.3" + +css-tree@1.0.0-alpha.29: + version "1.0.0-alpha.29" + resolved "https://registry.yarnpkg.com/css-tree/-/css-tree-1.0.0-alpha.29.tgz#3fa9d4ef3142cbd1c301e7664c1f352bd82f5a39" + integrity sha512-sRNb1XydwkW9IOci6iB2xmy8IGCj6r/fr+JWitvJ2JxQRPzN3T4AGGVWCMlVmVwM1gtgALJRmGIlWv5ppnGGkg== + dependencies: + mdn-data "~1.1.0" + source-map "^0.5.3" + css-unit-converter@^1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/css-unit-converter/-/css-unit-converter-1.1.1.tgz#d9b9281adcfd8ced935bdbaba83786897f64e996" +css-url-regex@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/css-url-regex/-/css-url-regex-1.1.0.tgz#83834230cc9f74c457de59eebd1543feeb83b7ec" + integrity sha1-g4NCMMyfdMRX3lnuvRVD/uuDt+w= + css-what@2.1: version "2.1.0" resolved "https://registry.yarnpkg.com/css-what/-/css-what-2.1.0.tgz#9467d032c38cfaefb9f2d79501253062f87fa1bd" +css-what@^2.1.2: + version "2.1.3" + resolved "https://registry.yarnpkg.com/css-what/-/css-what-2.1.3.tgz#a6d7604573365fe74686c3f311c56513d88285f2" + integrity sha512-a+EPoD+uZiNfh+5fxw2nO9QwFa6nJe2Or35fGY6Ipw1R3R4AGz1d1TEZrCegvw2YTmZ0jXirGYlzxxpYSHwpEg== + css@^2.0.0: version "2.2.3" resolved "https://registry.yarnpkg.com/css/-/css-2.2.3.tgz#f861f4ba61e79bedc962aa548e5780fd95cbc6be" @@ -2167,6 +2311,86 @@ cssesc@^0.1.0: version "0.1.0" resolved "https://registry.yarnpkg.com/cssesc/-/cssesc-0.1.0.tgz#c814903e45623371a0477b40109aaafbeeaddbb4" +cssesc@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/cssesc/-/cssesc-2.0.0.tgz#3b13bd1bb1cb36e1bcb5a4dcd27f54c5dcb35703" + integrity sha512-MsCAG1z9lPdoO/IUMLSBWBSVxVtJ1395VGIQ+Fc2gNdkQ1hNDnQdw3YhA71WJCBW1vdwA0cAnk/DnW6bqoEUYg== + +cssnano-preset-default@^4.0.7: + version "4.0.7" + resolved "https://registry.yarnpkg.com/cssnano-preset-default/-/cssnano-preset-default-4.0.7.tgz#51ec662ccfca0f88b396dcd9679cdb931be17f76" + integrity sha512-x0YHHx2h6p0fCl1zY9L9roD7rnlltugGu7zXSKQx6k2rYw0Hi3IqxcoAGF7u9Q5w1nt7vK0ulxV8Lo+EvllGsA== + dependencies: + css-declaration-sorter "^4.0.1" + cssnano-util-raw-cache "^4.0.1" + postcss "^7.0.0" + postcss-calc "^7.0.1" + postcss-colormin "^4.0.3" + postcss-convert-values "^4.0.1" + postcss-discard-comments "^4.0.2" + postcss-discard-duplicates "^4.0.2" + postcss-discard-empty "^4.0.1" + postcss-discard-overridden "^4.0.1" + postcss-merge-longhand "^4.0.11" + postcss-merge-rules "^4.0.3" + postcss-minify-font-values "^4.0.2" + postcss-minify-gradients "^4.0.2" + postcss-minify-params "^4.0.2" + postcss-minify-selectors "^4.0.2" + postcss-normalize-charset "^4.0.1" + postcss-normalize-display-values "^4.0.2" + postcss-normalize-positions "^4.0.2" + postcss-normalize-repeat-style "^4.0.2" + postcss-normalize-string "^4.0.2" + postcss-normalize-timing-functions "^4.0.2" + postcss-normalize-unicode "^4.0.1" + postcss-normalize-url "^4.0.1" + postcss-normalize-whitespace "^4.0.2" + postcss-ordered-values "^4.1.2" + postcss-reduce-initial "^4.0.3" + postcss-reduce-transforms "^4.0.2" + postcss-svgo "^4.0.2" + postcss-unique-selectors "^4.0.1" + +cssnano-util-get-arguments@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/cssnano-util-get-arguments/-/cssnano-util-get-arguments-4.0.0.tgz#ed3a08299f21d75741b20f3b81f194ed49cc150f" + integrity sha1-7ToIKZ8h11dBsg87gfGU7UnMFQ8= + +cssnano-util-get-match@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/cssnano-util-get-match/-/cssnano-util-get-match-4.0.0.tgz#c0e4ca07f5386bb17ec5e52250b4f5961365156d" + integrity sha1-wOTKB/U4a7F+xeUiULT1lhNlFW0= + +cssnano-util-raw-cache@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/cssnano-util-raw-cache/-/cssnano-util-raw-cache-4.0.1.tgz#b26d5fd5f72a11dfe7a7846fb4c67260f96bf282" + integrity sha512-qLuYtWK2b2Dy55I8ZX3ky1Z16WYsx544Q0UWViebptpwn/xDBmog2TLg4f+DBMg1rJ6JDWtn96WHbOKDWt1WQA== + dependencies: + postcss "^7.0.0" + +cssnano-util-same-parent@^4.0.0: + version "4.0.1" + resolved "https://registry.yarnpkg.com/cssnano-util-same-parent/-/cssnano-util-same-parent-4.0.1.tgz#574082fb2859d2db433855835d9a8456ea18bbf3" + integrity sha512-WcKx5OY+KoSIAxBW6UBBRay1U6vkYheCdjyVNDm85zt5K9mHoGOfsOsqIszfAqrQQFIIKgjh2+FDgIj/zsl21Q== + +cssnano@^4.1.0, cssnano@^4.1.10: + version "4.1.10" + resolved "https://registry.yarnpkg.com/cssnano/-/cssnano-4.1.10.tgz#0ac41f0b13d13d465487e111b778d42da631b8b2" + integrity sha512-5wny+F6H4/8RgNlaqab4ktc3e0/blKutmq8yNlBFXA//nSFFAqAngjNVRzUvCgYROULmZZUoosL/KSoZo5aUaQ== + dependencies: + cosmiconfig "^5.0.0" + cssnano-preset-default "^4.0.7" + is-resolvable "^1.0.0" + postcss "^7.0.0" + +csso@^3.5.1: + version "3.5.1" + resolved "https://registry.yarnpkg.com/csso/-/csso-3.5.1.tgz#7b9eb8be61628973c1b261e169d2f024008e758b" + integrity sha512-vrqULLffYU1Q2tLdJvaCYbONStnfkfimRxXNaGjxMldI0C7JPBC4rB1RyjhfdZ4m1frm8pM9uRPKH3d2knZ8gg== + dependencies: + css-tree "1.0.0-alpha.29" + currently-unhandled@^0.4.1: version "0.4.1" resolved "https://registry.yarnpkg.com/currently-unhandled/-/currently-unhandled-0.4.1.tgz#988df33feab191ef799a61369dd76c17adf957ea" @@ -2261,7 +2485,7 @@ default-gateway@^2.6.0: execa "^0.10.0" ip-regex "^2.1.0" -define-properties@^1.1.2: +define-properties@^1.1.2, define-properties@^1.1.3: version "1.1.3" resolved "https://registry.yarnpkg.com/define-properties/-/define-properties-1.1.3.tgz#cf88da6cbee26fe6db7094f61d870cbd84cee9f1" dependencies: @@ -2451,7 +2675,15 @@ domutils@1.5.1: dom-serializer "0" domelementtype "1" -dot-prop@^4.1.0: +domutils@^1.7.0: + version "1.7.0" + resolved "https://registry.yarnpkg.com/domutils/-/domutils-1.7.0.tgz#56ea341e834e06e6748af7a1cb25da67ea9f8c2a" + integrity sha512-Lgd2XcJ/NjEw+7tFvfKxOzCYKZsdct5lczQ2ZaQY8Djz7pfAD3Gbp8ySJWtreII/vDlMVmxwa6pHmdxIYgttDg== + dependencies: + dom-serializer "0" + domelementtype "1" + +dot-prop@^4.1.0, dot-prop@^4.1.1: version "4.2.0" resolved "https://registry.yarnpkg.com/dot-prop/-/dot-prop-4.2.0.tgz#1f19e0c2e1aa0e32797c49799f2837ac6af69c57" dependencies: @@ -2504,6 +2736,11 @@ ejs@^2.5.7: version "2.6.1" resolved "https://registry.yarnpkg.com/ejs/-/ejs-2.6.1.tgz#498ec0d495655abc6f23cd61868d926464071aa0" +electron-to-chromium@^1.3.113: + version "1.3.116" + resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.116.tgz#1dbfee6a592a0c14ade77dbdfe54fef86387d702" + integrity sha512-NKwKAXzur5vFCZYBHpdWjTMO8QptNLNP80nItkSIgUOapPAo9Uia+RvkCaZJtO7fhQaVElSvBPWEc2ku6cKsPA== + electron-to-chromium@^1.3.30, electron-to-chromium@^1.3.61: version "1.3.62" resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.62.tgz#2e8e2dc070c800ec8ce23ff9dfcceb585d6f9ed8" @@ -2605,6 +2842,18 @@ error-ex@^1.2.0, error-ex@^1.3.1: dependencies: is-arrayish "^0.2.1" +es-abstract@^1.12.0: + version "1.13.0" + resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.13.0.tgz#ac86145fdd5099d8dd49558ccba2eaf9b88e24e9" + integrity sha512-vDZfg/ykNxQVwup/8E1BZhVzFfBxs9NqMzGcvIJrqg5k2/5Za2bWo40dK2J1pgLngZ7c+Shh8lwYtLGyrwPutg== + dependencies: + es-to-primitive "^1.2.0" + function-bind "^1.1.1" + has "^1.0.3" + is-callable "^1.1.4" + is-regex "^1.0.4" + object-keys "^1.0.12" + es-abstract@^1.4.3, es-abstract@^1.5.1: version "1.12.0" resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.12.0.tgz#9dbbdd27c6856f0001421ca18782d786bf8a6165" @@ -2623,6 +2872,15 @@ es-to-primitive@^1.1.1: is-date-object "^1.0.1" is-symbol "^1.0.1" +es-to-primitive@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/es-to-primitive/-/es-to-primitive-1.2.0.tgz#edf72478033456e8dda8ef09e00ad9650707f377" + integrity sha512-qZryBOJjV//LaxLTV6UC//WewneB3LcXOL9NP++ozKVXsIIIpm/2c13UDiD9Jp2eThsecw9m3jPqDwTyobcdbg== + dependencies: + is-callable "^1.1.4" + is-date-object "^1.0.1" + is-symbol "^1.0.2" + es5-ext@^0.10.35, es5-ext@^0.10.9, es5-ext@~0.10.14: version "0.10.46" resolved "https://registry.yarnpkg.com/es5-ext/-/es5-ext-0.10.46.tgz#efd99f67c5a7ec789baa3daa7f79870388f7f572" @@ -3628,7 +3886,7 @@ has-values@^1.0.0: is-number "^3.0.0" kind-of "^4.0.0" -has@^1.0.1: +has@^1.0.0, has@^1.0.1, has@^1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/has/-/has-1.0.3.tgz#722d7cbfc1f6aa8241f16dd814e011e1f41e8796" dependencies: @@ -3668,6 +3926,11 @@ he@1.1.x, he@^1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/he/-/he-1.1.1.tgz#93410fd21b009735151f8868c2f271f3427e23fd" +hex-color-regex@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/hex-color-regex/-/hex-color-regex-1.1.0.tgz#4c06fccb4602fe2602b3c93df82d7e7dbf1a8a8e" + integrity sha512-l9sfDFsuqtOqKDsQdqrMRk0U85RZc0RtOR9yPI7mRVOa4FsR/BVnZ0shmQRM96Ji99kYZP/7hn1cedc1+ApsTQ== + highlight.js@^9.0.0: version "9.12.0" resolved "https://registry.yarnpkg.com/highlight.js/-/highlight.js-9.12.0.tgz#e6d9dbe57cbefe60751f02af336195870c90c01e" @@ -3703,6 +3966,21 @@ hpack.js@^2.1.6: readable-stream "^2.0.1" wbuf "^1.1.0" +hsl-regex@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/hsl-regex/-/hsl-regex-1.0.0.tgz#d49330c789ed819e276a4c0d272dffa30b18fe6e" + integrity sha1-1JMwx4ntgZ4nakwNJy3/owsY/m4= + +hsla-regex@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/hsla-regex/-/hsla-regex-1.0.0.tgz#c1ce7a3168c8c6614033a4b5f7877f3b225f9c38" + integrity sha1-wc56MWjIxmFAM6S194d/OyJfnDg= + +html-comment-regex@^1.1.0: + version "1.1.2" + resolved "https://registry.yarnpkg.com/html-comment-regex/-/html-comment-regex-1.1.2.tgz#97d4688aeb5c81886a364faa0cad1dda14d433a7" + integrity sha512-P+M65QY2JQ5Y0G9KKdlDpo0zK+/OHptU5AaBwUfAIDJZk1MYf32Frm84EcOytfJE0t5JvkAnKlmjsXDnWzCJmQ== + html-entities@^1.2.0: version "1.2.1" resolved "https://registry.yarnpkg.com/html-entities/-/html-entities-1.2.1.tgz#0df29351f0721163515dfb9e5543e5f6eed5162f" @@ -3877,6 +4155,14 @@ import-cwd@^2.0.0: dependencies: import-from "^2.1.0" +import-fresh@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/import-fresh/-/import-fresh-2.0.0.tgz#d81355c15612d386c61f9ddd3922d4304822a546" + integrity sha1-2BNVwVYS04bGH53dOSLUMEgipUY= + dependencies: + caller-path "^2.0.0" + resolve-from "^3.0.0" + import-from@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/import-from/-/import-from-2.1.0.tgz#335db7f2a7affd53aaa471d4b8021dee36b7f3b1" @@ -4015,6 +4301,11 @@ ipaddr.js@^1.5.2: version "1.8.1" resolved "https://registry.yarnpkg.com/ipaddr.js/-/ipaddr.js-1.8.1.tgz#fa4b79fa47fd3def5e3b159825161c0a519c9427" +is-absolute-url@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/is-absolute-url/-/is-absolute-url-2.1.0.tgz#50530dfb84fcc9aa7dbe7852e83a37b93b9f2aa6" + integrity sha1-UFMN+4T8yap9vnhS6Do3uTufKqY= + is-accessor-descriptor@^0.1.6: version "0.1.6" resolved "https://registry.yarnpkg.com/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz#a9e12cb3ae8d876727eeef3843f8a0897b5c98d6" @@ -4051,7 +4342,7 @@ is-builtin-module@^1.0.0: dependencies: builtin-modules "^1.0.0" -is-callable@^1.1.1, is-callable@^1.1.3: +is-callable@^1.1.1, is-callable@^1.1.3, is-callable@^1.1.4: version "1.1.4" resolved "https://registry.yarnpkg.com/is-callable/-/is-callable-1.1.4.tgz#1e1adf219e1eeb684d691f9d6a05ff0d30a24d75" @@ -4061,6 +4352,18 @@ is-ci@^1.0.10: dependencies: ci-info "^1.3.0" +is-color-stop@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/is-color-stop/-/is-color-stop-1.1.0.tgz#cfff471aee4dd5c9e158598fbe12967b5cdad345" + integrity sha1-z/9HGu5N1cnhWFmPvhKWe1za00U= + dependencies: + css-color-names "^0.0.4" + hex-color-regex "^1.1.0" + hsl-regex "^1.0.0" + hsla-regex "^1.0.0" + rgb-regex "^1.0.1" + rgba-regex "^1.0.0" + is-data-descriptor@^0.1.4: version "0.1.4" resolved "https://registry.yarnpkg.com/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz#0b5ee648388e2c860282e793f1856fec3f301b56" @@ -4242,6 +4545,11 @@ is-regex@^1.0.4: dependencies: has "^1.0.1" +is-resolvable@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/is-resolvable/-/is-resolvable-1.1.0.tgz#fb18f87ce1feb925169c9a407c19318a3206ed88" + integrity sha512-qgDYXFSR5WvEfuS5dMj6oTMEbrrSaM0CrFk2Yiq/gXnBvD9pMa2jGXxyhGLfvhZpuMZe18CJpFxAt3CRs42NMg== + is-retry-allowed@^1.0.0: version "1.1.0" resolved "https://registry.yarnpkg.com/is-retry-allowed/-/is-retry-allowed-1.1.0.tgz#11a060568b67339444033d0125a61a20d564fb34" @@ -4250,10 +4558,24 @@ is-stream@^1.0.0, is-stream@^1.0.1, is-stream@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-1.1.0.tgz#12d4a3dd4e68e0b79ceb8dbc84173ae80d91ca44" +is-svg@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/is-svg/-/is-svg-3.0.0.tgz#9321dbd29c212e5ca99c4fa9794c714bcafa2f75" + integrity sha512-gi4iHK53LR2ujhLVVj+37Ykh9GLqYHX6JOVXbLAucaG/Cqw9xwdFOjDM2qeifLs1sF1npXXFvDu0r5HNgCMrzQ== + dependencies: + html-comment-regex "^1.1.0" + is-symbol@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/is-symbol/-/is-symbol-1.0.1.tgz#3cc59f00025194b6ab2e38dbae6689256b660572" +is-symbol@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/is-symbol/-/is-symbol-1.0.2.tgz#a055f6ae57192caee329e7a860118b497a950f38" + integrity sha512-HS8bZ9ox60yCJLH9snBpIwv9pYUAkcuLhSA1oero1UB5y9aiQpRA8y2ex945AOtCZL1lJDeIk3G5LthswI46Lw== + dependencies: + has-symbols "^1.0.0" + is-typedarray@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/is-typedarray/-/is-typedarray-1.0.0.tgz#e479c80858df0c1b11ddda6940f96011fcda4a9a" @@ -4421,6 +4743,14 @@ js-yaml@3.x, js-yaml@^3.6.1, js-yaml@^3.7.0, js-yaml@^3.9.0: argparse "^1.0.7" esprima "^4.0.0" +js-yaml@^3.12.0: + version "3.12.2" + resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.12.2.tgz#ef1d067c5a9d9cb65bd72f285b5d8105c77f14fc" + integrity sha512-QHn/Lh/7HhZ/Twc7vJYQTkjuCa0kaCcDcjK5Zlk2rvnUpy7DxMJ23+Jc2dcyvltwQVg1nygAVlB2oRDFHoRS5Q== + dependencies: + argparse "^1.0.7" + esprima "^4.0.0" + js.clone@0.0.3: version "0.0.3" resolved "https://registry.yarnpkg.com/js.clone/-/js.clone-0.0.3.tgz#f378d2bf501fcf648074fd91893f4718236bb79c" @@ -4662,6 +4992,14 @@ klaw@^1.0.0: optionalDependencies: graceful-fs "^4.1.9" +last-call-webpack-plugin@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/last-call-webpack-plugin/-/last-call-webpack-plugin-3.0.0.tgz#9742df0e10e3cf46e5c0381c2de90d3a7a2d7555" + integrity sha512-7KI2l2GIZa9p2spzPIVZBYyNKkN+e/SQPpnjlTiPhdbDW3F86tdKKELxKpzJ5sgU19wQWsACULZmpTPYHeWO5w== + dependencies: + lodash "^4.17.5" + webpack-sources "^1.1.0" + latest-version@^3.0.0: version "3.1.0" resolved "https://registry.yarnpkg.com/latest-version/-/latest-version-3.1.0.tgz#a205383fea322b33b5ae3b18abee0dc2f356ee15" @@ -4855,6 +5193,11 @@ lodash.escape@^3.0.0: dependencies: lodash._root "^3.0.0" +lodash.get@^4.4.2: + version "4.4.2" + resolved "https://registry.yarnpkg.com/lodash.get/-/lodash.get-4.4.2.tgz#2d177f652fa31e939b4438d5341499dfa3825e99" + integrity sha1-LRd/ZS+jHpObRDjVNBSZ36OCXpk= + lodash.isarguments@^3.0.0: version "3.1.0" resolved "https://registry.yarnpkg.com/lodash.isarguments/-/lodash.isarguments-3.1.0.tgz#2f573d85c6a24289ff00663b491c1d338ff3458a" @@ -5081,6 +5424,11 @@ md5@^2.2.1: crypt "~0.0.1" is-buffer "~1.1.1" +mdn-data@~1.1.0: + version "1.1.4" + resolved "https://registry.yarnpkg.com/mdn-data/-/mdn-data-1.1.4.tgz#50b5d4ffc4575276573c4eedb8780812a8419f01" + integrity sha512-FSYbp3lyKjyj3E7fMl6rYvUdX0FBXaluGqlFoYESWQlyUTq8R+wp0rkFxoYFqZlHCvsUXGjyJmLQSnXToYhOSA== + media-typer@0.3.0: version "0.3.0" resolved "https://registry.yarnpkg.com/media-typer/-/media-typer-0.3.0.tgz#8710d7af0aa626f8fffa1ce00168545263255748" @@ -5280,7 +5628,7 @@ mixin-object@^2.0.1: for-in "^0.1.3" is-extendable "^0.1.1" -mkdirp@0.5.1, mkdirp@0.5.x, "mkdirp@>=0.5 0", mkdirp@^0.5.0, mkdirp@^0.5.1, mkdirp@~0.5.0: +mkdirp@0.5.1, mkdirp@0.5.x, "mkdirp@>=0.5 0", mkdirp@^0.5.0, mkdirp@^0.5.1, mkdirp@~0.5.0, mkdirp@~0.5.1: version "0.5.1" resolved "http://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz#30057438eac6cf7f8c4767f38648d6697d75c903" dependencies: @@ -5501,6 +5849,13 @@ node-releases@^1.0.0-alpha.11: dependencies: semver "^5.3.0" +node-releases@^1.1.8: + version "1.1.10" + resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-1.1.10.tgz#5dbeb6bc7f4e9c85b899e2e7adcc0635c9b2adf7" + integrity sha512-KbUPCpfoBvb3oBkej9+nrU0/7xPlVhmhhUJ1PZqwIP5/1dJkRWKWD3OONjo6M2J7tSCBtDCumLwwqeI+DWWaLQ== + dependencies: + semver "^5.3.0" + node-sass@^4.11.0: version "4.11.0" resolved "https://registry.yarnpkg.com/node-sass/-/node-sass-4.11.0.tgz#183faec398e9cbe93ba43362e2768ca988a6369a" @@ -5578,6 +5933,11 @@ normalize-range@^0.1.2: version "0.1.2" resolved "https://registry.yarnpkg.com/normalize-range/-/normalize-range-0.1.2.tgz#2d10c06bdfd312ea9777695a4d28439456b75942" +normalize-url@^3.0.0: + version "3.3.0" + resolved "https://registry.yarnpkg.com/normalize-url/-/normalize-url-3.3.0.tgz#b2e1c4dc4f7c6d57743df733a4f5978d18650559" + integrity sha512-U+JJi7duF1o+u2pynbp2zXDW2/PADgC30f0GsHZtRh+HOcXHnw137TrNlyxxRvWW5fjKd3bcLHPxofWuCjaeZg== + nouislider@^11.0.0: version "11.1.0" resolved "https://registry.yarnpkg.com/nouislider/-/nouislider-11.1.0.tgz#1768eb5b854917325d41b96f2dc4eb3757d73381" @@ -5649,6 +6009,13 @@ npm-run-path@^2.0.0: gauge "~2.7.3" set-blocking "~2.0.0" +nth-check@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/nth-check/-/nth-check-1.0.2.tgz#b2bd295c37e3dd58a3bf0700376663ba4d9cf05c" + integrity sha512-WeBOdju8SnzPN5vTUJYxYUxLeXpCaVP5i5e0LF8fg7WORF2Wd7wFX/pk0tYZk7s8T+J7VLy0Da6J1+wCT0AtHg== + dependencies: + boolbase "~1.0.0" + nth-check@~1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/nth-check/-/nth-check-1.0.1.tgz#9929acdf628fc2c41098deab82ac580cf149aae4" @@ -5738,6 +6105,16 @@ object.pick@^1.3.0: dependencies: isobject "^3.0.1" +object.values@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/object.values/-/object.values-1.1.0.tgz#bf6810ef5da3e5325790eaaa2be213ea84624da9" + integrity sha512-8mf0nKLAoFX6VlNVdhGj31SVYpaNFtUnuoOXWyFEstsWRgU837AK+JYM0iAxwkSzGRbwn8cbFmgbyxj1j4VbXg== + dependencies: + define-properties "^1.1.3" + es-abstract "^1.12.0" + function-bind "^1.1.1" + has "^1.0.3" + obuf@^1.0.0, obuf@^1.1.1: version "1.1.2" resolved "https://registry.yarnpkg.com/obuf/-/obuf-1.1.2.tgz#09bea3343d41859ebd446292d11c9d4db619084e" @@ -5807,6 +6184,14 @@ optimist@0.6.x, optimist@^0.6.1, optimist@~0.6.0: minimist "~0.0.1" wordwrap "~0.0.2" +optimize-css-assets-webpack-plugin@^5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/optimize-css-assets-webpack-plugin/-/optimize-css-assets-webpack-plugin-5.0.1.tgz#9eb500711d35165b45e7fd60ba2df40cb3eb9159" + integrity sha512-Rqm6sSjWtx9FchdP0uzTQDc7GXDKnwVEGoSxjezPkzMewx7gEWE9IMUYKmigTRC4U3RaNSwYVnUDLuIdtTpm0A== + dependencies: + cssnano "^4.1.0" + last-call-webpack-plugin "^3.0.0" + optionator@^0.8.1: version "0.8.2" resolved "https://registry.yarnpkg.com/optionator/-/optionator-0.8.2.tgz#364c5e409d3f4d6301d6c0b4c05bba50180aeb64" @@ -6172,6 +6557,16 @@ postcss-calc@^6.0.0: postcss-selector-parser "^2.2.2" reduce-css-calc "^2.0.0" +postcss-calc@^7.0.1: + version "7.0.1" + resolved "https://registry.yarnpkg.com/postcss-calc/-/postcss-calc-7.0.1.tgz#36d77bab023b0ecbb9789d84dcb23c4941145436" + integrity sha512-oXqx0m6tb4N3JGdmeMSc/i91KppbYsFZKdH0xMOqK8V1rJlzrKlTdokz8ozUXLVejydRN6u2IddxpcijRj2FqQ== + dependencies: + css-unit-converter "^1.1.1" + postcss "^7.0.5" + postcss-selector-parser "^5.0.0-rc.4" + postcss-value-parser "^3.3.1" + postcss-cli@^6.0.0: version "6.0.0" resolved "https://registry.yarnpkg.com/postcss-cli/-/postcss-cli-6.0.0.tgz#688e3750735a7bc21ea6e2f0e427f5f873c16f0b" @@ -6254,6 +6649,25 @@ postcss-color-rgba-fallback@^3.0.0: postcss-value-parser "^3.3.0" rgb-hex "^2.1.0" +postcss-colormin@^4.0.3: + version "4.0.3" + resolved "https://registry.yarnpkg.com/postcss-colormin/-/postcss-colormin-4.0.3.tgz#ae060bce93ed794ac71264f08132d550956bd381" + integrity sha512-WyQFAdDZpExQh32j0U0feWisZ0dmOtPl44qYmJKkq9xFWY3p+4qnRzCHeNrkeRhwPHz9bQ3mo0/yVkaply0MNw== + dependencies: + browserslist "^4.0.0" + color "^3.0.0" + has "^1.0.0" + postcss "^7.0.0" + postcss-value-parser "^3.0.0" + +postcss-convert-values@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/postcss-convert-values/-/postcss-convert-values-4.0.1.tgz#ca3813ed4da0f812f9d43703584e449ebe189a7f" + integrity sha512-Kisdo1y77KUC0Jmn0OXU/COOJbzM8cImvw1ZFsBgBgMgb1iL23Zs/LXRe3r+EZqM3vGYKdQ2YJVQ5VkJI+zEJQ== + dependencies: + postcss "^7.0.0" + postcss-value-parser "^3.0.0" + postcss-cssnext@3.1.0: version "3.1.0" resolved "https://registry.yarnpkg.com/postcss-cssnext/-/postcss-cssnext-3.1.0.tgz#927dc29341a938254cde38ea60a923b9dfedead9" @@ -6310,6 +6724,34 @@ postcss-custom-selectors@^4.0.1: postcss "^6.0.1" postcss-selector-matches "^3.0.0" +postcss-discard-comments@^4.0.2: + version "4.0.2" + resolved "https://registry.yarnpkg.com/postcss-discard-comments/-/postcss-discard-comments-4.0.2.tgz#1fbabd2c246bff6aaad7997b2b0918f4d7af4033" + integrity sha512-RJutN259iuRf3IW7GZyLM5Sw4GLTOH8FmsXBnv8Ab/Tc2k4SR4qbV4DNbyyY4+Sjo362SyDmW2DQ7lBSChrpkg== + dependencies: + postcss "^7.0.0" + +postcss-discard-duplicates@^4.0.2: + version "4.0.2" + resolved "https://registry.yarnpkg.com/postcss-discard-duplicates/-/postcss-discard-duplicates-4.0.2.tgz#3fe133cd3c82282e550fc9b239176a9207b784eb" + integrity sha512-ZNQfR1gPNAiXZhgENFfEglF93pciw0WxMkJeVmw8eF+JZBbMD7jp6C67GqJAXVZP2BWbOztKfbsdmMp/k8c6oQ== + dependencies: + postcss "^7.0.0" + +postcss-discard-empty@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/postcss-discard-empty/-/postcss-discard-empty-4.0.1.tgz#c8c951e9f73ed9428019458444a02ad90bb9f765" + integrity sha512-B9miTzbznhDjTfjvipfHoqbWKwd0Mj+/fL5s1QOz06wufguil+Xheo4XpOnc4NqKYBCNqqEzgPv2aPBIJLox0w== + dependencies: + postcss "^7.0.0" + +postcss-discard-overridden@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/postcss-discard-overridden/-/postcss-discard-overridden-4.0.1.tgz#652aef8a96726f029f5e3e00146ee7a4e755ff57" + integrity sha512-IYY2bEDD7g1XM1IDEsUT4//iEYCxAmP5oDSFMVU/JVvT7gh+l4fmjciLqGgwjdWpQIdb0Che2VX00QObS5+cTg== + dependencies: + postcss "^7.0.0" + postcss-font-family-system-ui@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/postcss-font-family-system-ui/-/postcss-font-family-system-ui-3.0.0.tgz#675fe7a9e029669f05f8dba2e44c2225ede80623" @@ -6362,10 +6804,72 @@ postcss-media-query-parser@^0.2.3: version "0.2.3" resolved "https://registry.yarnpkg.com/postcss-media-query-parser/-/postcss-media-query-parser-0.2.3.tgz#27b39c6f4d94f81b1a73b8f76351c609e5cef244" +postcss-merge-longhand@^4.0.11: + version "4.0.11" + resolved "https://registry.yarnpkg.com/postcss-merge-longhand/-/postcss-merge-longhand-4.0.11.tgz#62f49a13e4a0ee04e7b98f42bb16062ca2549e24" + integrity sha512-alx/zmoeXvJjp7L4mxEMjh8lxVlDFX1gqWHzaaQewwMZiVhLo42TEClKaeHbRf6J7j82ZOdTJ808RtN0ZOZwvw== + dependencies: + css-color-names "0.0.4" + postcss "^7.0.0" + postcss-value-parser "^3.0.0" + stylehacks "^4.0.0" + +postcss-merge-rules@^4.0.3: + version "4.0.3" + resolved "https://registry.yarnpkg.com/postcss-merge-rules/-/postcss-merge-rules-4.0.3.tgz#362bea4ff5a1f98e4075a713c6cb25aefef9a650" + integrity sha512-U7e3r1SbvYzO0Jr3UT/zKBVgYYyhAz0aitvGIYOYK5CPmkNih+WDSsS5tvPrJ8YMQYlEMvsZIiqmn7HdFUaeEQ== + dependencies: + browserslist "^4.0.0" + caniuse-api "^3.0.0" + cssnano-util-same-parent "^4.0.0" + postcss "^7.0.0" + postcss-selector-parser "^3.0.0" + vendors "^1.0.0" + postcss-message-helpers@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/postcss-message-helpers/-/postcss-message-helpers-2.0.0.tgz#a4f2f4fab6e4fe002f0aed000478cdf52f9ba60e" +postcss-minify-font-values@^4.0.2: + version "4.0.2" + resolved "https://registry.yarnpkg.com/postcss-minify-font-values/-/postcss-minify-font-values-4.0.2.tgz#cd4c344cce474343fac5d82206ab2cbcb8afd5a6" + integrity sha512-j85oO6OnRU9zPf04+PZv1LYIYOprWm6IA6zkXkrJXyRveDEuQggG6tvoy8ir8ZwjLxLuGfNkCZEQG7zan+Hbtg== + dependencies: + postcss "^7.0.0" + postcss-value-parser "^3.0.0" + +postcss-minify-gradients@^4.0.2: + version "4.0.2" + resolved "https://registry.yarnpkg.com/postcss-minify-gradients/-/postcss-minify-gradients-4.0.2.tgz#93b29c2ff5099c535eecda56c4aa6e665a663471" + integrity sha512-qKPfwlONdcf/AndP1U8SJ/uzIJtowHlMaSioKzebAXSG4iJthlWC9iSWznQcX4f66gIWX44RSA841HTHj3wK+Q== + dependencies: + cssnano-util-get-arguments "^4.0.0" + is-color-stop "^1.0.0" + postcss "^7.0.0" + postcss-value-parser "^3.0.0" + +postcss-minify-params@^4.0.2: + version "4.0.2" + resolved "https://registry.yarnpkg.com/postcss-minify-params/-/postcss-minify-params-4.0.2.tgz#6b9cef030c11e35261f95f618c90036d680db874" + integrity sha512-G7eWyzEx0xL4/wiBBJxJOz48zAKV2WG3iZOqVhPet/9geefm/Px5uo1fzlHu+DOjT+m0Mmiz3jkQzVHe6wxAWg== + dependencies: + alphanum-sort "^1.0.0" + browserslist "^4.0.0" + cssnano-util-get-arguments "^4.0.0" + postcss "^7.0.0" + postcss-value-parser "^3.0.0" + uniqs "^2.0.0" + +postcss-minify-selectors@^4.0.2: + version "4.0.2" + resolved "https://registry.yarnpkg.com/postcss-minify-selectors/-/postcss-minify-selectors-4.0.2.tgz#e2e5eb40bfee500d0cd9243500f5f8ea4262fbd8" + integrity sha512-D5S1iViljXBj9kflQo4YutWnJmwm8VvIsU1GeXJGiG9j8CIg9zs4voPMdQDUmIxetUOh60VilsNzCiAFTOqu3g== + dependencies: + alphanum-sort "^1.0.0" + has "^1.0.0" + postcss "^7.0.0" + postcss-selector-parser "^3.0.0" + postcss-modules-extract-imports@^1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/postcss-modules-extract-imports/-/postcss-modules-extract-imports-1.2.0.tgz#66140ecece38ef06bf0d3e355d69bf59d141ea85" @@ -6399,6 +6903,96 @@ postcss-nesting@^4.0.1: dependencies: postcss "^6.0.11" +postcss-normalize-charset@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/postcss-normalize-charset/-/postcss-normalize-charset-4.0.1.tgz#8b35add3aee83a136b0471e0d59be58a50285dd4" + integrity sha512-gMXCrrlWh6G27U0hF3vNvR3w8I1s2wOBILvA87iNXaPvSNo5uZAMYsZG7XjCUf1eVxuPfyL4TJ7++SGZLc9A3g== + dependencies: + postcss "^7.0.0" + +postcss-normalize-display-values@^4.0.2: + version "4.0.2" + resolved "https://registry.yarnpkg.com/postcss-normalize-display-values/-/postcss-normalize-display-values-4.0.2.tgz#0dbe04a4ce9063d4667ed2be476bb830c825935a" + integrity sha512-3F2jcsaMW7+VtRMAqf/3m4cPFhPD3EFRgNs18u+k3lTJJlVe7d0YPO+bnwqo2xg8YiRpDXJI2u8A0wqJxMsQuQ== + dependencies: + cssnano-util-get-match "^4.0.0" + postcss "^7.0.0" + postcss-value-parser "^3.0.0" + +postcss-normalize-positions@^4.0.2: + version "4.0.2" + resolved "https://registry.yarnpkg.com/postcss-normalize-positions/-/postcss-normalize-positions-4.0.2.tgz#05f757f84f260437378368a91f8932d4b102917f" + integrity sha512-Dlf3/9AxpxE+NF1fJxYDeggi5WwV35MXGFnnoccP/9qDtFrTArZ0D0R+iKcg5WsUd8nUYMIl8yXDCtcrT8JrdA== + dependencies: + cssnano-util-get-arguments "^4.0.0" + has "^1.0.0" + postcss "^7.0.0" + postcss-value-parser "^3.0.0" + +postcss-normalize-repeat-style@^4.0.2: + version "4.0.2" + resolved "https://registry.yarnpkg.com/postcss-normalize-repeat-style/-/postcss-normalize-repeat-style-4.0.2.tgz#c4ebbc289f3991a028d44751cbdd11918b17910c" + integrity sha512-qvigdYYMpSuoFs3Is/f5nHdRLJN/ITA7huIoCyqqENJe9PvPmLhNLMu7QTjPdtnVf6OcYYO5SHonx4+fbJE1+Q== + dependencies: + cssnano-util-get-arguments "^4.0.0" + cssnano-util-get-match "^4.0.0" + postcss "^7.0.0" + postcss-value-parser "^3.0.0" + +postcss-normalize-string@^4.0.2: + version "4.0.2" + resolved "https://registry.yarnpkg.com/postcss-normalize-string/-/postcss-normalize-string-4.0.2.tgz#cd44c40ab07a0c7a36dc5e99aace1eca4ec2690c" + integrity sha512-RrERod97Dnwqq49WNz8qo66ps0swYZDSb6rM57kN2J+aoyEAJfZ6bMx0sx/F9TIEX0xthPGCmeyiam/jXif0eA== + dependencies: + has "^1.0.0" + postcss "^7.0.0" + postcss-value-parser "^3.0.0" + +postcss-normalize-timing-functions@^4.0.2: + version "4.0.2" + resolved "https://registry.yarnpkg.com/postcss-normalize-timing-functions/-/postcss-normalize-timing-functions-4.0.2.tgz#8e009ca2a3949cdaf8ad23e6b6ab99cb5e7d28d9" + integrity sha512-acwJY95edP762e++00Ehq9L4sZCEcOPyaHwoaFOhIwWCDfik6YvqsYNxckee65JHLKzuNSSmAdxwD2Cud1Z54A== + dependencies: + cssnano-util-get-match "^4.0.0" + postcss "^7.0.0" + postcss-value-parser "^3.0.0" + +postcss-normalize-unicode@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/postcss-normalize-unicode/-/postcss-normalize-unicode-4.0.1.tgz#841bd48fdcf3019ad4baa7493a3d363b52ae1cfb" + integrity sha512-od18Uq2wCYn+vZ/qCOeutvHjB5jm57ToxRaMeNuf0nWVHaP9Hua56QyMF6fs/4FSUnVIw0CBPsU0K4LnBPwYwg== + dependencies: + browserslist "^4.0.0" + postcss "^7.0.0" + postcss-value-parser "^3.0.0" + +postcss-normalize-url@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/postcss-normalize-url/-/postcss-normalize-url-4.0.1.tgz#10e437f86bc7c7e58f7b9652ed878daaa95faae1" + integrity sha512-p5oVaF4+IHwu7VpMan/SSpmpYxcJMtkGppYf0VbdH5B6hN8YNmVyJLuY9FmLQTzY3fag5ESUUHDqM+heid0UVA== + dependencies: + is-absolute-url "^2.0.0" + normalize-url "^3.0.0" + postcss "^7.0.0" + postcss-value-parser "^3.0.0" + +postcss-normalize-whitespace@^4.0.2: + version "4.0.2" + resolved "https://registry.yarnpkg.com/postcss-normalize-whitespace/-/postcss-normalize-whitespace-4.0.2.tgz#bf1d4070fe4fcea87d1348e825d8cc0c5faa7d82" + integrity sha512-tO8QIgrsI3p95r8fyqKV+ufKlSHh9hMJqACqbv2XknufqEDhDvbguXGBBqxw9nsQoXWf0qOqppziKJKHMD4GtA== + dependencies: + postcss "^7.0.0" + postcss-value-parser "^3.0.0" + +postcss-ordered-values@^4.1.2: + version "4.1.2" + resolved "https://registry.yarnpkg.com/postcss-ordered-values/-/postcss-ordered-values-4.1.2.tgz#0cf75c820ec7d5c4d280189559e0b571ebac0eee" + integrity sha512-2fCObh5UanxvSxeXrtLtlwVThBvHn6MQcu4ksNT2tsaV2Fg76R2CV98W7wNSlX+5/pFwEyaDwKLLoEV7uRybAw== + dependencies: + cssnano-util-get-arguments "^4.0.0" + postcss "^7.0.0" + postcss-value-parser "^3.0.0" + postcss-pseudo-class-any-link@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/postcss-pseudo-class-any-link/-/postcss-pseudo-class-any-link-4.0.0.tgz#9152a0613d3450720513e8892854bae42d0ee68e" @@ -6412,6 +7006,26 @@ postcss-pseudoelements@^5.0.0: dependencies: postcss "^6.0.0" +postcss-reduce-initial@^4.0.3: + version "4.0.3" + resolved "https://registry.yarnpkg.com/postcss-reduce-initial/-/postcss-reduce-initial-4.0.3.tgz#7fd42ebea5e9c814609639e2c2e84ae270ba48df" + integrity sha512-gKWmR5aUulSjbzOfD9AlJiHCGH6AEVLaM0AV+aSioxUDd16qXP1PCh8d1/BGVvpdWn8k/HiK7n6TjeoXN1F7DA== + dependencies: + browserslist "^4.0.0" + caniuse-api "^3.0.0" + has "^1.0.0" + postcss "^7.0.0" + +postcss-reduce-transforms@^4.0.2: + version "4.0.2" + resolved "https://registry.yarnpkg.com/postcss-reduce-transforms/-/postcss-reduce-transforms-4.0.2.tgz#17efa405eacc6e07be3414a5ca2d1074681d4e29" + integrity sha512-EEVig1Q2QJ4ELpJXMZR8Vt5DQx8/mo+dGWSR7vWXqcob2gQLyQGsionYcGKATXvQzMPn6DSN1vTN7yFximdIAg== + dependencies: + cssnano-util-get-match "^4.0.0" + has "^1.0.0" + postcss "^7.0.0" + postcss-value-parser "^3.0.0" + postcss-replace-overflow-wrap@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/postcss-replace-overflow-wrap/-/postcss-replace-overflow-wrap-2.0.0.tgz#794db6faa54f8db100854392a93af45768b4e25b" @@ -6468,6 +7082,24 @@ postcss-selector-parser@^2.2.2, postcss-selector-parser@^2.2.3: indexes-of "^1.0.1" uniq "^1.0.1" +postcss-selector-parser@^3.0.0: + version "3.1.1" + resolved "https://registry.yarnpkg.com/postcss-selector-parser/-/postcss-selector-parser-3.1.1.tgz#4f875f4afb0c96573d5cf4d74011aee250a7e865" + integrity sha1-T4dfSvsMllc9XPTXQBGu4lCn6GU= + dependencies: + dot-prop "^4.1.1" + indexes-of "^1.0.1" + uniq "^1.0.1" + +postcss-selector-parser@^5.0.0-rc.4: + version "5.0.0" + resolved "https://registry.yarnpkg.com/postcss-selector-parser/-/postcss-selector-parser-5.0.0.tgz#249044356697b33b64f1a8f7c80922dddee7195c" + integrity sha512-w+zLE5Jhg6Liz8+rQOWEAwtwkyqpfnmsinXjXg6cY7YIONZZtgvE0v2O0uhQBs0peNomOJwWRKt6JBfTdTd3OQ== + dependencies: + cssesc "^2.0.0" + indexes-of "^1.0.1" + uniq "^1.0.1" + postcss-smart-import@0.7.6: version "0.7.6" resolved "https://registry.yarnpkg.com/postcss-smart-import/-/postcss-smart-import-0.7.6.tgz#259deb84aa28f138458218ecc0e9a84c61ada6a4" @@ -6484,6 +7116,30 @@ postcss-smart-import@0.7.6: resolve "^1.5.0" sugarss "^1.0.1" +postcss-svgo@^4.0.2: + version "4.0.2" + resolved "https://registry.yarnpkg.com/postcss-svgo/-/postcss-svgo-4.0.2.tgz#17b997bc711b333bab143aaed3b8d3d6e3d38258" + integrity sha512-C6wyjo3VwFm0QgBy+Fu7gCYOkCmgmClghO+pjcxvrcBKtiKt0uCF+hvbMO1fyv5BMImRK90SMb+dwUnfbGd+jw== + dependencies: + is-svg "^3.0.0" + postcss "^7.0.0" + postcss-value-parser "^3.0.0" + svgo "^1.0.0" + +postcss-unique-selectors@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/postcss-unique-selectors/-/postcss-unique-selectors-4.0.1.tgz#9446911f3289bfd64c6d680f073c03b1f9ee4bac" + integrity sha512-+JanVaryLo9QwZjKrmJgkI4Fn8SBgRO6WXQBJi7KiAVPlmxikB5Jzc4EvXMT2H0/m0RjrVVm9rGNhZddm/8Spg== + dependencies: + alphanum-sort "^1.0.0" + postcss "^7.0.0" + uniqs "^2.0.0" + +postcss-value-parser@^3.0.0, postcss-value-parser@^3.3.1: + version "3.3.1" + resolved "https://registry.yarnpkg.com/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz#9ff822547e2893213cf1c30efa51ac5fd1ba8281" + integrity sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ== + postcss-value-parser@^3.2.3, postcss-value-parser@^3.3.0: version "3.3.0" resolved "https://registry.yarnpkg.com/postcss-value-parser/-/postcss-value-parser-3.3.0.tgz#87f38f9f18f774a4ab4c8a232f5c5ce8872a9d15" @@ -6512,6 +7168,15 @@ postcss@^7.0.0, postcss@^7.0.2: source-map "^0.6.1" supports-color "^5.4.0" +postcss@^7.0.1, postcss@^7.0.5: + version "7.0.14" + resolved "https://registry.yarnpkg.com/postcss/-/postcss-7.0.14.tgz#4527ed6b1ca0d82c53ce5ec1a2041c2346bbd6e5" + integrity sha512-NsbD6XUUMZvBxtQAJuWDJeeC4QFsmWsfozWxCJPWf3M55K9iu2iMDaKqyoOdTJ1R4usBXuxlVFAIo8rZPQD4Bg== + dependencies: + chalk "^2.4.2" + source-map "^0.6.1" + supports-color "^6.1.0" + prelude-ls@~1.1.2: version "1.1.2" resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.1.2.tgz#21932a549f5e52ffd9a827f570e04be62a97da54" @@ -6671,7 +7336,7 @@ q@1.4.1: version "1.4.1" resolved "https://registry.yarnpkg.com/q/-/q-1.4.1.tgz#55705bcd93c5f3673530c2c2cbc0c2b3addc286e" -q@^1.4.1: +q@^1.1.2, q@^1.4.1: version "1.5.1" resolved "https://registry.yarnpkg.com/q/-/q-1.5.1.tgz#7e32f75b41381291d04611f1bf14109ac00651d7" @@ -7148,10 +7813,20 @@ rgb-hex@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/rgb-hex/-/rgb-hex-2.1.0.tgz#c773c5fe2268a25578d92539a82a7a5ce53beda6" +rgb-regex@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/rgb-regex/-/rgb-regex-1.0.1.tgz#c0e0d6882df0e23be254a475e8edd41915feaeb1" + integrity sha1-wODWiC3w4jviVKR16O3UGRX+rrE= + rgb@~0.1.0: version "0.1.0" resolved "https://registry.yarnpkg.com/rgb/-/rgb-0.1.0.tgz#be27b291e8feffeac1bd99729721bfa40fc037b5" +rgba-regex@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/rgba-regex/-/rgba-regex-1.0.0.tgz#43374e2e2ca0968b0ef1523460b7d730ff22eeb3" + integrity sha1-QzdOLiyglosO8VI0YLfXMP8i7rM= + right-align@^0.1.1: version "0.1.3" resolved "https://registry.yarnpkg.com/right-align/-/right-align-0.1.3.tgz#61339b722fe6a3515689210d24e14c96148613ef" @@ -7287,7 +7962,7 @@ saucelabs@^1.5.0: dependencies: https-proxy-agent "^2.2.1" -sax@>=0.6.0, sax@^1.2.4: +sax@>=0.6.0, sax@^1.2.4, sax@~1.2.4: version "1.2.4" resolved "https://registry.yarnpkg.com/sax/-/sax-1.2.4.tgz#2816234e2378bddc4e5354fab5caa895df7100d9" @@ -7697,7 +8372,7 @@ source-map@^0.4.2, source-map@^0.4.4: dependencies: amdefine ">=0.0.4" -source-map@^0.5.1, source-map@^0.5.6, source-map@^0.5.7, source-map@~0.5.1: +source-map@^0.5.1, source-map@^0.5.3, source-map@^0.5.6, source-map@^0.5.7, source-map@~0.5.1: version "0.5.7" resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.5.7.tgz#8a039d2d1021d22d1ea14c80d8ea468ba2ef3fcc" @@ -7801,6 +8476,11 @@ ssri@^5.2.4: dependencies: safe-buffer "^5.1.1" +stable@^0.1.8: + version "0.1.8" + resolved "https://registry.yarnpkg.com/stable/-/stable-0.1.8.tgz#836eb3c8382fe2936feaf544631017ce7d47a3cf" + integrity sha512-ji9qxRnOVfcuLDySj9qzhGSEFVobyt1kIOSkj1qZzYLzq7Tos/oUUWvotUPQLlrsidqsK6tBH89Bc9kL5zHA6w== + static-extend@^0.1.1: version "0.1.2" resolved "https://registry.yarnpkg.com/static-extend/-/static-extend-0.1.2.tgz#60809c39cbff55337226fd5e0b520f341f1fb5c6" @@ -7949,6 +8629,15 @@ strip-json-comments@^2.0.0, strip-json-comments@~2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-2.0.1.tgz#3c531942e908c2697c0ec344858c286c7ca0a60a" +stylehacks@^4.0.0: + version "4.0.3" + resolved "https://registry.yarnpkg.com/stylehacks/-/stylehacks-4.0.3.tgz#6718fcaf4d1e07d8a1318690881e8d96726a71d5" + integrity sha512-7GlLk9JwlElY4Y6a/rmbH2MhVlTyVmiJd1PfTCqFaIBEGMYNsrO/v3SeGTdhBThLg4Z+NbOk/qFMwCa+J+3p/g== + dependencies: + browserslist "^4.0.0" + postcss "^7.0.0" + postcss-selector-parser "^3.0.0" + sugarss@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/sugarss/-/sugarss-1.0.1.tgz#be826d9003e0f247735f92365dc3fd7f1bae9e44" @@ -7971,6 +8660,33 @@ supports-color@^5.1.0, supports-color@^5.2.0, supports-color@^5.3.0, supports-co dependencies: has-flag "^3.0.0" +supports-color@^6.1.0: + version "6.1.0" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-6.1.0.tgz#0764abc69c63d5ac842dd4867e8d025e880df8f3" + integrity sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ== + dependencies: + has-flag "^3.0.0" + +svgo@^1.0.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/svgo/-/svgo-1.2.0.tgz#305a8fc0f4f9710828c65039bb93d5793225ffc3" + integrity sha512-xBfxJxfk4UeVN8asec9jNxHiv3UAMv/ujwBWGYvQhhMb2u3YTGKkiybPcLFDLq7GLLWE9wa73e0/m8L5nTzQbw== + dependencies: + chalk "^2.4.1" + coa "^2.0.2" + css-select "^2.0.0" + css-select-base-adapter "^0.1.1" + css-tree "1.0.0-alpha.28" + css-url-regex "^1.1.0" + csso "^3.5.1" + js-yaml "^3.12.0" + mkdirp "~0.5.1" + object.values "^1.1.0" + sax "~1.2.4" + stable "^0.1.8" + unquote "~1.1.1" + util.promisify "~1.0.0" + symbol-observable@^1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/symbol-observable/-/symbol-observable-1.2.0.tgz#c22688aed4eab3cdc2dfeacbb561660560a00804" @@ -8073,6 +8789,11 @@ timers-browserify@^2.0.4: dependencies: setimmediate "^1.0.4" +timsort@^0.3.0: + version "0.3.0" + resolved "https://registry.yarnpkg.com/timsort/-/timsort-0.3.0.tgz#405411a8e7e6339fe64db9a234de11dc31e02bd4" + integrity sha1-QFQRqOfmM5/mTbmiNN4R3DHgK9Q= + tmp@0.0.30: version "0.0.30" resolved "https://registry.yarnpkg.com/tmp/-/tmp-0.0.30.tgz#72419d4a8be7d6ce75148fd8b324e593a711c2ed" @@ -8389,6 +9110,11 @@ uniq@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/uniq/-/uniq-1.0.1.tgz#b31c5ae8254844a3a8281541ce2b04b865a734ff" +uniqs@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/uniqs/-/uniqs-2.0.0.tgz#ffede4b36b25290696e6e165d4a59edb998e6b02" + integrity sha1-/+3ks2slKQaW5uFl1KWe25mOawI= + unique-filename@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/unique-filename/-/unique-filename-1.1.0.tgz#d05f2fe4032560871f30e93cbe735eea201514f3" @@ -8422,6 +9148,11 @@ unpipe@1.0.0, unpipe@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/unpipe/-/unpipe-1.0.0.tgz#b2bf4ee8514aae6165b4817829d21b2ef49904ec" +unquote@~1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/unquote/-/unquote-1.1.1.tgz#8fded7324ec6e88a0ff8b905e7c098cdc086d544" + integrity sha1-j97XMk7G6IoP+LkF58CYzcCG1UQ= + unset-value@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/unset-value/-/unset-value-1.0.0.tgz#8376873f7d2335179ffb1e6fc3a8ed0dfc8ab559" @@ -8515,7 +9246,7 @@ util-deprecate@~1.0.1: version "1.0.2" resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf" -util.promisify@1.0.0: +util.promisify@1.0.0, util.promisify@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/util.promisify/-/util.promisify-1.0.0.tgz#440f7165a459c9a16dc145eb8e72f35687097030" dependencies: @@ -8585,6 +9316,11 @@ vary@~1.1.2: version "1.1.2" resolved "https://registry.yarnpkg.com/vary/-/vary-1.1.2.tgz#2299f02c6ded30d4a5961b0b9f74524a18f634fc" +vendors@^1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/vendors/-/vendors-1.0.2.tgz#7fcb5eef9f5623b156bcea89ec37d63676f21801" + integrity sha512-w/hry/368nO21AN9QljsaIhb9ZiZtZARoVH5f3CsFbawdLdayCgKRPup7CggujvySMxx0I91NOyxdVENohprLQ== + verror@1.10.0: version "1.10.0" resolved "https://registry.yarnpkg.com/verror/-/verror-1.10.0.tgz#3a105ca17053af55d6e270c1f8288682e18da400" From 6d64326238745cd43677d445934daf3d8424ba8d Mon Sep 17 00:00:00 2001 From: lotte Date: Tue, 19 Mar 2019 16:22:16 +0100 Subject: [PATCH 17/17] Added debounce, fixed error handling for search results, fixed bug in paginated lists --- .../+search-page/search-service/search.service.ts | 4 ++-- src/app/core/data/paginated-list.ts | 5 ++++- .../dso-selector/dso-selector.component.spec.ts | 14 +++++++++++--- .../dso-selector/dso-selector.component.ts | 9 +++++++-- 4 files changed, 24 insertions(+), 8 deletions(-) diff --git a/src/app/+search-page/search-service/search.service.ts b/src/app/+search-page/search-service/search.service.ts index 275b0b3340..2c0f1f4e55 100644 --- a/src/app/+search-page/search-service/search.service.ts +++ b/src/app/+search-page/search-service/search.service.ts @@ -23,7 +23,7 @@ import { DSpaceObject } from '../../core/shared/dspace-object.model'; import { GenericConstructor } from '../../core/shared/generic-constructor'; import { HALEndpointService } from '../../core/shared/hal-endpoint.service'; import { - configureRequest, + configureRequest, filterSuccessfulResponses, getResponseFromEntry, getSucceededRemoteData } from '../../core/shared/operators'; @@ -104,7 +104,7 @@ export class SearchService implements OnDestroy { // get search results from response cache const sqrObs: Observable = requestEntryObs.pipe( - getResponseFromEntry(), + filterSuccessfulResponses(), map((response: SearchSuccessResponse) => response.results) ); diff --git a/src/app/core/data/paginated-list.ts b/src/app/core/data/paginated-list.ts index 8efdccd75d..faecd231bc 100644 --- a/src/app/core/data/paginated-list.ts +++ b/src/app/core/data/paginated-list.ts @@ -1,5 +1,5 @@ import { PageInfo } from '../shared/page-info.model'; -import { hasValue } from '../../shared/empty.util'; +import { hasNoValue, hasValue } from '../../shared/empty.util'; export class PaginatedList { @@ -22,6 +22,9 @@ export class PaginatedList { if (hasValue(this.pageInfo) && hasValue(this.pageInfo.totalElements)) { return this.pageInfo.totalElements; } + if (hasNoValue(this.page)) { + return 0; + } return this.page.length; } diff --git a/src/app/shared/dso-selector/dso-selector/dso-selector.component.spec.ts b/src/app/shared/dso-selector/dso-selector/dso-selector.component.spec.ts index 0386276be7..04111a4ea6 100644 --- a/src/app/shared/dso-selector/dso-selector/dso-selector.component.spec.ts +++ b/src/app/shared/dso-selector/dso-selector/dso-selector.component.spec.ts @@ -1,4 +1,4 @@ -import { async, ComponentFixture, TestBed } from '@angular/core/testing'; +import { async, ComponentFixture, fakeAsync, TestBed, tick } from '@angular/core/testing'; import { TranslateModule } from '@ngx-translate/core'; import { DebugElement, NO_ERRORS_SCHEMA } from '@angular/core'; import { DSOSelectorComponent } from './dso-selector.component'; @@ -21,7 +21,12 @@ describe('DSOSelectorComponent', () => { const type = DSpaceObjectType.ITEM; const searchResult = new ItemSearchResult(); const item = new Item(); - item.metadata = { 'dc.title': [Object.assign(new MetadataValue(), { value: 'Item title', language: undefined })] }; + item.metadata = { + 'dc.title': [Object.assign(new MetadataValue(), { + value: 'Item title', + language: undefined + })] + }; searchResult.dspaceObject = item; searchResult.hitHighlights = {}; const searchService = jasmine.createSpyObj('searchService', { @@ -46,6 +51,7 @@ describe('DSOSelectorComponent', () => { debugElement = fixture.debugElement; component.currentDSOId = currentDSOId; component.type = type; + fixture.detectChanges(); }); @@ -59,7 +65,9 @@ describe('DSOSelectorComponent', () => { dsoType: type, pagination: (component as any).defaultPagination }); + expect(searchService.search).toHaveBeenCalledWith(searchOptions); }); -}); +}) +; diff --git a/src/app/shared/dso-selector/dso-selector/dso-selector.component.ts b/src/app/shared/dso-selector/dso-selector/dso-selector.component.ts index 7bb9bfac28..04501e4923 100644 --- a/src/app/shared/dso-selector/dso-selector/dso-selector.component.ts +++ b/src/app/shared/dso-selector/dso-selector/dso-selector.component.ts @@ -1,5 +1,4 @@ import { - AfterViewInit, Component, ElementRef, EventEmitter, @@ -12,7 +11,7 @@ import { import { FormControl } from '@angular/forms'; import { Observable } from 'rxjs'; -import { map, startWith, switchMap, take } from 'rxjs/operators'; +import { debounceTime, startWith, switchMap } from 'rxjs/operators'; import { SearchService } from '../../../+search-page/search-service/search.service'; import { PaginatedSearchOptions } from '../../../+search-page/paginated-search-options.model'; import { DSpaceObjectType } from '../../../core/shared/dspace-object-type.model'; @@ -68,6 +67,11 @@ export class DSOSelectorComponent implements OnInit { */ @ViewChildren('listEntryElement') listElements: QueryList; + /** + * Time to wait before sending a search request to the server when a user types something + */ + debounceTime = 500; + constructor(private searchService: SearchService) { } @@ -79,6 +83,7 @@ export class DSOSelectorComponent implements OnInit { this.input.setValue(this.currentDSOId); this.listEntries$ = this.input.valueChanges .pipe( + debounceTime(this.debounceTime), startWith(this.currentDSOId), switchMap((query) => { return this.searchService.search(