From 883a1d8881e43f2394d35193bcd787cfc8315f64 Mon Sep 17 00:00:00 2001 From: Kristof De Langhe Date: Wed, 8 Aug 2018 11:36:42 +0200 Subject: [PATCH 01/48] Issues 252,253: Browse by title and browse by metadata (author) --- resources/i18n/en.json | 7 +- .../browse-by-author-page.component.html | 11 ++ .../browse-by-author-page.component.scss | 0 .../browse-by-author-page.component.spec.ts | 0 .../browse-by-author-page.component.ts | 107 +++++++++++ .../browse-by-title-page.component.html | 11 ++ .../browse-by-title-page.component.scss | 0 .../browse-by-title-page.component.spec.ts | 0 .../browse-by-title-page.component.ts | 85 +++++++++ .../+browse-by/browse-by-routing.module.ts | 16 ++ src/app/+browse-by/browse-by.module.ts | 27 +++ src/app/app-routing.module.ts | 1 + src/app/core/browse/browse.service.ts | 77 ++++++-- src/app/core/core.module.ts | 2 + ...wse-items-response-parsing-service.spec.ts | 168 ++++++++++++++++++ .../browse-items-response-parsing-service.ts | 49 +++++ src/app/core/data/comcol-data.service.spec.ts | 16 +- src/app/core/data/comcol-data.service.ts | 14 +- src/app/core/data/data.service.ts | 13 +- src/app/core/data/item-data.service.spec.ts | 21 ++- src/app/core/data/item-data.service.ts | 17 +- src/app/core/data/request.models.ts | 8 + src/app/core/shared/browse-entry.model.ts | 3 +- src/app/core/shared/dspace-object.model.ts | 5 + src/app/core/shared/operators.ts | 19 +- .../shared/browse-by/browse-by.component.html | 12 ++ .../shared/browse-by/browse-by.component.scss | 0 .../browse-by/browse-by.component.spec.ts | 44 +++++ .../shared/browse-by/browse-by.component.ts | 27 +++ .../object-collection.component.html | 2 +- .../item-grid-element.component.html | 40 +++-- .../browse-entry-list-element.component.html | 3 + .../browse-entry-list-element.component.scss | 1 + ...rowse-entry-list-element.component.spec.ts | 47 +++++ .../browse-entry-list-element.component.ts | 17 ++ .../item-list-element.component.html | 40 +++-- .../metadata-list-element.component.html | 3 + .../metadata-list-element.component.scss | 1 + .../metadata-list-element.component.spec.ts | 48 +++++ .../metadata-list-element.component.ts | 15 ++ src/app/shared/shared.module.ts | 7 + 41 files changed, 898 insertions(+), 86 deletions(-) create mode 100644 src/app/+browse-by/+browse-by-author-page/browse-by-author-page.component.html create mode 100644 src/app/+browse-by/+browse-by-author-page/browse-by-author-page.component.scss create mode 100644 src/app/+browse-by/+browse-by-author-page/browse-by-author-page.component.spec.ts create mode 100644 src/app/+browse-by/+browse-by-author-page/browse-by-author-page.component.ts create mode 100644 src/app/+browse-by/+browse-by-title-page/browse-by-title-page.component.html create mode 100644 src/app/+browse-by/+browse-by-title-page/browse-by-title-page.component.scss create mode 100644 src/app/+browse-by/+browse-by-title-page/browse-by-title-page.component.spec.ts create mode 100644 src/app/+browse-by/+browse-by-title-page/browse-by-title-page.component.ts create mode 100644 src/app/+browse-by/browse-by-routing.module.ts create mode 100644 src/app/+browse-by/browse-by.module.ts create mode 100644 src/app/core/data/browse-items-response-parsing-service.spec.ts create mode 100644 src/app/core/data/browse-items-response-parsing-service.ts create mode 100644 src/app/shared/browse-by/browse-by.component.html create mode 100644 src/app/shared/browse-by/browse-by.component.scss create mode 100644 src/app/shared/browse-by/browse-by.component.spec.ts create mode 100644 src/app/shared/browse-by/browse-by.component.ts create mode 100644 src/app/shared/object-list/browse-entry-list-element/browse-entry-list-element.component.html create mode 100644 src/app/shared/object-list/browse-entry-list-element/browse-entry-list-element.component.scss create mode 100644 src/app/shared/object-list/browse-entry-list-element/browse-entry-list-element.component.spec.ts create mode 100644 src/app/shared/object-list/browse-entry-list-element/browse-entry-list-element.component.ts create mode 100644 src/app/shared/object-list/metadata-list-element/metadata-list-element.component.html create mode 100644 src/app/shared/object-list/metadata-list-element/metadata-list-element.component.scss create mode 100644 src/app/shared/object-list/metadata-list-element/metadata-list-element.component.spec.ts create mode 100644 src/app/shared/object-list/metadata-list-element/metadata-list-element.component.ts diff --git a/resources/i18n/en.json b/resources/i18n/en.json index ba70b87e12..f08213df06 100644 --- a/resources/i18n/en.json +++ b/resources/i18n/en.json @@ -135,6 +135,9 @@ } } }, + "browse": { + "title": "Browsing {{ collection }} by {{ field }} {{ value }}" + }, "admin": { "registries": { "metadata": { @@ -193,7 +196,8 @@ "recent-submissions": "Loading recent submissions...", "item": "Loading item...", "objects": "Loading...", - "search-results": "Loading search results..." + "search-results": "Loading search results...", + "browse-by": "Loading items..." }, "error": { "default": "Error", @@ -205,6 +209,7 @@ "item": "Error fetching item", "objects": "Error fetching objects", "search-results": "Error fetching search results", + "browse-by": "Error fetching items", "validation": { "pattern": "This input is restricted by the current pattern: {{ pattern }}.", "license": { diff --git a/src/app/+browse-by/+browse-by-author-page/browse-by-author-page.component.html b/src/app/+browse-by/+browse-by-author-page/browse-by-author-page.component.html new file mode 100644 index 0000000000..438c318994 --- /dev/null +++ b/src/app/+browse-by/+browse-by-author-page/browse-by-author-page.component.html @@ -0,0 +1,11 @@ +
+
+ + +
+
diff --git a/src/app/+browse-by/+browse-by-author-page/browse-by-author-page.component.scss b/src/app/+browse-by/+browse-by-author-page/browse-by-author-page.component.scss new file mode 100644 index 0000000000..e69de29bb2 diff --git a/src/app/+browse-by/+browse-by-author-page/browse-by-author-page.component.spec.ts b/src/app/+browse-by/+browse-by-author-page/browse-by-author-page.component.spec.ts new file mode 100644 index 0000000000..e69de29bb2 diff --git a/src/app/+browse-by/+browse-by-author-page/browse-by-author-page.component.ts b/src/app/+browse-by/+browse-by-author-page/browse-by-author-page.component.ts new file mode 100644 index 0000000000..1605b4afab --- /dev/null +++ b/src/app/+browse-by/+browse-by-author-page/browse-by-author-page.component.ts @@ -0,0 +1,107 @@ +import { Component, OnInit } from '@angular/core'; +import { RemoteData } from '../../core/data/remote-data'; +import { PaginatedList } from '../../core/data/paginated-list'; +import { ItemDataService } from '../../core/data/item-data.service'; +import { Observable } from 'rxjs/Observable'; +import { PaginationComponentOptions } from '../../shared/pagination/pagination-component-options.model'; +import { SortDirection, SortOptions } from '../../core/cache/models/sort-options.model'; +import { Subscription } from 'rxjs/Subscription'; +import { ActivatedRoute } from '@angular/router'; +import { hasValue, isNotEmpty } from '../../shared/empty.util'; +import { Metadatum } from '../../core/shared/metadatum.model'; +import { BrowseService } from '../../core/browse/browse.service'; +import { BrowseEntry } from '../../core/shared/browse-entry.model'; +import { Item } from '../../core/shared/item.model'; + +@Component({ + selector: 'ds-browse-by-author-page', + styleUrls: ['./browse-by-author-page.component.scss'], + templateUrl: './browse-by-author-page.component.html' +}) +export class BrowseByAuthorPageComponent implements OnInit { + + authors$: Observable>>; + items$: Observable>>; + paginationConfig: PaginationComponentOptions = Object.assign(new PaginationComponentOptions(), { + id: 'browse-by-author-pagination', + currentPage: 1, + pageSize: 20 + }); + sortConfig: SortOptions = new SortOptions('dc.contributor.author', SortDirection.ASC); + subs: Subscription[] = []; + currentUrl: string; + value = ''; + + public constructor(private itemDataService: ItemDataService, private route: ActivatedRoute, private browseService: BrowseService) { + } + + ngOnInit(): void { + this.currentUrl = this.route.snapshot.pathFromRoot + .map((snapshot) => (snapshot.routeConfig) ? snapshot.routeConfig.path : '') + .join('/'); + this.updatePage({ + pagination: this.paginationConfig, + sort: this.sortConfig + }); + this.subs.push( + Observable.combineLatest( + this.route.params, + this.route.queryParams, + (params, queryParams, ) => { + return Object.assign({}, params, queryParams); + }) + .subscribe((params) => { + const page = +params.page || this.paginationConfig.currentPage; + const pageSize = +params.pageSize || this.paginationConfig.pageSize; + const sortDirection = params.sortDirection || this.sortConfig.direction; + const sortField = params.sortField || this.sortConfig.field; + const startsWith = +params.query || params.query || ''; + this.value = +params.value || params.value || ''; + const pagination = Object.assign({}, + this.paginationConfig, + { currentPage: page, pageSize: pageSize } + ); + const sort = Object.assign({}, + this.sortConfig, + { direction: sortDirection, field: sortField } + ); + const searchOptions = { + pagination: pagination, + sort: sort, + startsWith: startsWith + }; + if (isNotEmpty(this.value)) { + this.updatePageWithItems(searchOptions, this.value); + } else { + this.updatePage(searchOptions); + } + })); + } + + /** + * @param searchOptions Options to narrow down your search: + * { pagination: PaginationComponentOptions, + * sort: SortOptions, + * startsWith: string } + */ + updatePage(searchOptions) { + this.authors$ = this.browseService.getBrowseEntriesFor('author', searchOptions); + this.items$ = undefined; + } + + /** + * @param searchOptions Options to narrow down your search: + * { pagination: PaginationComponentOptions, + * sort: SortOptions, + * startsWith: string } + * @param author The author's name for displaying items + */ + updatePageWithItems(searchOptions, author: string) { + this.items$ = this.browseService.getBrowseItemsFor('author', author, searchOptions); + } + + ngOnDestroy(): void { + this.subs.filter((sub) => hasValue(sub)).forEach((sub) => sub.unsubscribe()); + } + +} diff --git a/src/app/+browse-by/+browse-by-title-page/browse-by-title-page.component.html b/src/app/+browse-by/+browse-by-title-page/browse-by-title-page.component.html new file mode 100644 index 0000000000..d37727be36 --- /dev/null +++ b/src/app/+browse-by/+browse-by-title-page/browse-by-title-page.component.html @@ -0,0 +1,11 @@ +
+
+ + +
+
diff --git a/src/app/+browse-by/+browse-by-title-page/browse-by-title-page.component.scss b/src/app/+browse-by/+browse-by-title-page/browse-by-title-page.component.scss new file mode 100644 index 0000000000..e69de29bb2 diff --git a/src/app/+browse-by/+browse-by-title-page/browse-by-title-page.component.spec.ts b/src/app/+browse-by/+browse-by-title-page/browse-by-title-page.component.spec.ts new file mode 100644 index 0000000000..e69de29bb2 diff --git a/src/app/+browse-by/+browse-by-title-page/browse-by-title-page.component.ts b/src/app/+browse-by/+browse-by-title-page/browse-by-title-page.component.ts new file mode 100644 index 0000000000..6483ac8d17 --- /dev/null +++ b/src/app/+browse-by/+browse-by-title-page/browse-by-title-page.component.ts @@ -0,0 +1,85 @@ +import { Component, OnInit } from '@angular/core'; +import { RemoteData } from '../../core/data/remote-data'; +import { DSpaceObject } from '../../core/shared/dspace-object.model'; +import { PaginatedList } from '../../core/data/paginated-list'; +import { ItemDataService } from '../../core/data/item-data.service'; +import { Observable } from 'rxjs/Observable'; +import { PaginationComponentOptions } from '../../shared/pagination/pagination-component-options.model'; +import { SortDirection, SortOptions } from '../../core/cache/models/sort-options.model'; +import { Item } from '../../core/shared/item.model'; +import { Subscription } from 'rxjs/Subscription'; +import { ActivatedRoute, PRIMARY_OUTLET, UrlSegmentGroup } from '@angular/router'; +import { hasValue } from '../../shared/empty.util'; +import { Collection } from '../../core/shared/collection.model'; + +@Component({ + selector: 'ds-browse-by-title-page', + styleUrls: ['./browse-by-title-page.component.scss'], + templateUrl: './browse-by-title-page.component.html' +}) +export class BrowseByTitlePageComponent implements OnInit { + + items$: Observable>>; + paginationConfig: PaginationComponentOptions = Object.assign(new PaginationComponentOptions(), { + id: 'browse-by-title-pagination', + currentPage: 1, + pageSize: 20 + }); + sortConfig: SortOptions = new SortOptions('dc.title', SortDirection.ASC); + subs: Subscription[] = []; + currentUrl: string; + + public constructor(private itemDataService: ItemDataService, private route: ActivatedRoute) { + + } + + ngOnInit(): void { + this.currentUrl = this.route.snapshot.pathFromRoot + .map((snapshot) => (snapshot.routeConfig) ? snapshot.routeConfig.path : '') + .join('/'); + this.updatePage({ + pagination: this.paginationConfig, + sort: this.sortConfig + }); + this.subs.push( + Observable.combineLatest( + this.route.params, + this.route.queryParams, + (params, queryParams, ) => { + return Object.assign({}, params, queryParams); + }) + .subscribe((params) => { + const page = +params.page || this.paginationConfig.currentPage; + const pageSize = +params.pageSize || this.paginationConfig.pageSize; + const sortDirection = +params.page || this.sortConfig.direction; + const startsWith = +params.query || params.query || ''; + const pagination = Object.assign({}, + this.paginationConfig, + { currentPage: page, pageSize: pageSize } + ); + const sort = Object.assign({}, + this.sortConfig, + { direction: sortDirection, field: params.sortField } + ); + this.updatePage({ + pagination: pagination, + sort: sort, + startsWith: startsWith + }); + })); + } + + updatePage(searchOptions) { + this.items$ = this.itemDataService.findAll({ + currentPage: searchOptions.pagination.currentPage, + elementsPerPage: searchOptions.pagination.pageSize, + sort: searchOptions.sort, + startsWith: searchOptions.startsWith + }); + } + + ngOnDestroy(): void { + this.subs.filter((sub) => hasValue(sub)).forEach((sub) => sub.unsubscribe()); + } + +} diff --git a/src/app/+browse-by/browse-by-routing.module.ts b/src/app/+browse-by/browse-by-routing.module.ts new file mode 100644 index 0000000000..630a7c0db5 --- /dev/null +++ b/src/app/+browse-by/browse-by-routing.module.ts @@ -0,0 +1,16 @@ +import { RouterModule } from '@angular/router'; +import { NgModule } from '@angular/core'; +import { BrowseByTitlePageComponent } from './+browse-by-title-page/browse-by-title-page.component'; +import { BrowseByAuthorPageComponent } from './+browse-by-author-page/browse-by-author-page.component'; + +@NgModule({ + imports: [ + RouterModule.forChild([ + { path: 'title', component: BrowseByTitlePageComponent }, + { path: 'author', component: BrowseByAuthorPageComponent } + ]) + ] +}) +export class BrowseByRoutingModule { + +} diff --git a/src/app/+browse-by/browse-by.module.ts b/src/app/+browse-by/browse-by.module.ts new file mode 100644 index 0000000000..51843a13d8 --- /dev/null +++ b/src/app/+browse-by/browse-by.module.ts @@ -0,0 +1,27 @@ +import { NgModule } from '@angular/core'; +import { CommonModule } from '@angular/common'; +import { BrowseByTitlePageComponent } from './+browse-by-title-page/browse-by-title-page.component'; +import { ItemDataService } from '../core/data/item-data.service'; +import { SharedModule } from '../shared/shared.module'; +import { BrowseByRoutingModule } from './browse-by-routing.module'; +import { BrowseByAuthorPageComponent } from './+browse-by-author-page/browse-by-author-page.component'; +import { BrowseService } from '../core/browse/browse.service'; + +@NgModule({ + imports: [ + BrowseByRoutingModule, + CommonModule, + SharedModule + ], + declarations: [ + BrowseByTitlePageComponent, + BrowseByAuthorPageComponent + ], + providers: [ + ItemDataService, + BrowseService + ] +}) +export class BrowseByModule { + +} diff --git a/src/app/app-routing.module.ts b/src/app/app-routing.module.ts index 4bc8c43152..7de83651ff 100644 --- a/src/app/app-routing.module.ts +++ b/src/app/app-routing.module.ts @@ -12,6 +12,7 @@ import { PageNotFoundComponent } from './pagenotfound/pagenotfound.component'; { path: 'collections', loadChildren: './+collection-page/collection-page.module#CollectionPageModule' }, { path: 'items', loadChildren: './+item-page/item-page.module#ItemPageModule' }, { path: 'search', loadChildren: './+search-page/search-page.module#SearchPageModule' }, + { path: 'browse', loadChildren: './+browse-by/browse-by.module#BrowseByModule' }, { path: 'admin', loadChildren: './+admin/admin.module#AdminModule' }, { path: 'login', loadChildren: './+login-page/login-page.module#LoginPageModule' }, { path: 'logout', loadChildren: './+logout-page/logout-page.module#LogoutPageModule' }, diff --git a/src/app/core/browse/browse.service.ts b/src/app/core/browse/browse.service.ts index 836014a110..2e4a0a3508 100644 --- a/src/app/core/browse/browse.service.ts +++ b/src/app/core/browse/browse.service.ts @@ -16,19 +16,27 @@ import { ResponseCacheEntry } from '../cache/response-cache.reducer'; import { ResponseCacheService } from '../cache/response-cache.service'; import { PaginatedList } from '../data/paginated-list'; import { RemoteData } from '../data/remote-data'; -import { BrowseEndpointRequest, BrowseEntriesRequest, RestRequest } from '../data/request.models'; +import { + BrowseEndpointRequest, + BrowseEntriesRequest, + BrowseItemsRequest, + GetRequest, + RestRequest +} from '../data/request.models'; import { RequestService } from '../data/request.service'; import { BrowseDefinition } from '../shared/browse-definition.model'; import { BrowseEntry } from '../shared/browse-entry.model'; import { HALEndpointService } from '../shared/hal-endpoint.service'; import { configureRequest, - filterSuccessfulResponses, + filterSuccessfulResponses, getBrowseDefinitionLinks, getRemoteDataPayload, getRequestFromSelflink, getResponseFromSelflink } from '../shared/operators'; import { URLCombiner } from '../url-combiner/url-combiner'; +import { Item } from '../shared/item.model'; +import { DSpaceObject } from '../shared/dspace-object.model'; @Injectable() export class BrowseService { @@ -71,6 +79,8 @@ export class BrowseService { map((entry: ResponseCacheEntry) => entry.response), map((response: GenericSuccessResponse) => response.payload), ensureArrayHasValue(), + map((definitions: BrowseDefinition[]) => definitions + .map((definition: BrowseDefinition) => Object.assign(new BrowseDefinition(), definition))), distinctUntilChanged() ); @@ -82,17 +92,7 @@ export class BrowseService { sort?: SortOptions; } = {}): Observable>> { const request$ = this.getBrowseDefinitions().pipe( - getRemoteDataPayload(), - map((browseDefinitions: BrowseDefinition[]) => browseDefinitions - .find((def: BrowseDefinition) => def.id === definitionID && def.metadataBrowse === true) - ), - map((def: BrowseDefinition) => { - if (isNotEmpty(def)) { - return def._links; - } else { - throw new Error(`No metadata browse definition could be found for id '${definitionID}'`); - } - }), + getBrowseDefinitionLinks(definitionID), hasValueOperator(), map((_links: any) => _links.entries), hasValueOperator(), @@ -124,6 +124,57 @@ export class BrowseService { filterSuccessfulResponses(), map((entry: ResponseCacheEntry) => entry.response), map((response: GenericSuccessResponse) => new PaginatedList(response.pageInfo, response.payload)), + map((list: PaginatedList) => Object.assign(list, { + page: list.page ? list.page.map((entry: BrowseEntry) => Object.assign(new BrowseEntry(), entry)) : list.page + })), + distinctUntilChanged() + ); + + return this.rdb.toRemoteDataObservable(requestEntry$, responseCache$, payload$); + } + + getBrowseItemsFor(definitionID: string, filterValue: string, options: { + pagination?: PaginationComponentOptions; + sort?: SortOptions; + } = {}): Observable>> { + const request$ = this.getBrowseDefinitions().pipe( + getBrowseDefinitionLinks(definitionID), + hasValueOperator(), + map((_links: any) => _links.items), + hasValueOperator(), + map((href: string) => { + const args = []; + if (isNotEmpty(options.sort)) { + args.push(`sort=${options.sort.field},${options.sort.direction}`); + } + if (isNotEmpty(options.pagination)) { + args.push(`page=${options.pagination.currentPage - 1}`); + args.push(`size=${options.pagination.pageSize}`); + } + if (isNotEmpty(filterValue)) { + args.push(`filterValue=${filterValue}`); + } + if (isNotEmpty(args)) { + href = new URLCombiner(href, `?${args.join('&')}`).toString(); + } + return href; + }), + map((endpointURL: string) => new BrowseItemsRequest(this.requestService.generateRequestId(), endpointURL)), + configureRequest(this.requestService) + ); + + const href$ = request$.pipe(map((request: RestRequest) => request.href)); + + const requestEntry$ = href$.pipe(getRequestFromSelflink(this.requestService)); + const responseCache$ = href$.pipe(getResponseFromSelflink(this.responseCache)); + + const payload$ = responseCache$.pipe( + filterSuccessfulResponses(), + map((entry: ResponseCacheEntry) => entry.response), + map((response: GenericSuccessResponse) => new PaginatedList(response.pageInfo, response.payload)), + map((list: PaginatedList) => Object.assign(list, { + page: list.page ? list.page.map((item: DSpaceObject) => Object.assign(new Item(), item)) : list.page + })), distinctUntilChanged() ); diff --git a/src/app/core/core.module.ts b/src/app/core/core.module.ts index 8536169688..422717e233 100644 --- a/src/app/core/core.module.ts +++ b/src/app/core/core.module.ts @@ -62,6 +62,7 @@ import { RegistryMetadatafieldsResponseParsingService } from './data/registry-me import { RegistryBitstreamformatsResponseParsingService } from './data/registry-bitstreamformats-response-parsing.service'; import { NotificationsService } from '../shared/notifications/notifications.service'; import { UploaderService } from '../shared/uploader/uploader.service'; +import { BrowseItemsResponseParsingService } from './data/browse-items-response-parsing-service'; const IMPORTS = [ CommonModule, @@ -114,6 +115,7 @@ const PROVIDERS = [ ServerResponseService, BrowseResponseParsingService, BrowseEntriesResponseParsingService, + BrowseItemsResponseParsingService, BrowseService, ConfigResponseParsingService, RouteService, diff --git a/src/app/core/data/browse-items-response-parsing-service.spec.ts b/src/app/core/data/browse-items-response-parsing-service.spec.ts new file mode 100644 index 0000000000..6a141c01c4 --- /dev/null +++ b/src/app/core/data/browse-items-response-parsing-service.spec.ts @@ -0,0 +1,168 @@ +import { getMockObjectCacheService } from '../../shared/mocks/mock-object-cache.service'; +import { ErrorResponse, GenericSuccessResponse } from '../cache/response-cache.models'; +import { DSpaceRESTV2Response } from '../dspace-rest-v2/dspace-rest-v2-response.model'; +import { BrowseEntriesResponseParsingService } from './browse-entries-response-parsing.service'; +import { BrowseEntriesRequest, BrowseItemsRequest } from './request.models'; +import { BrowseItemsResponseParsingService } from './browse-items-response-parsing-service'; + +describe('BrowseItemsResponseParsingService', () => { + let service: BrowseItemsResponseParsingService; + + beforeEach(() => { + service = new BrowseItemsResponseParsingService(undefined, getMockObjectCacheService()); + }); + + describe('parse', () => { + const request = new BrowseItemsRequest('client/f5b4ccb8-fbb0-4548-b558-f234d9fdfad6', 'https://rest.api/discover/browses/author/items'); + + const validResponse = { + payload: { + _embedded: { + items: [ + { + id: 'd7b6bc6f-ff6c-444a-a0d3-0cd9b68043e7', + uuid: 'd7b6bc6f-ff6c-444a-a0d3-0cd9b68043e7', + name: 'Development of Local Supply Chain : A Critical Link for Concentrated Solar Power in India', + handle: '10986/17472', + metadata: [ + { + key: 'dc.creator', + value: 'World Bank', + language: null + } + ], + inArchive: true, + discoverable: true, + withdrawn: false, + lastModified: '2018-05-25T09:32:58.005+0000', + type: 'item', + _links: { + bitstreams: { + href: 'https://dspace7-internal.atmire.com/rest/api/core/items/d7b6bc6f-ff6c-444a-a0d3-0cd9b68043e7/bitstreams' + }, + owningCollection: { + href: 'https://dspace7-internal.atmire.com/rest/api/core/items/d7b6bc6f-ff6c-444a-a0d3-0cd9b68043e7/owningCollection' + }, + templateItemOf: { + href: 'https://dspace7-internal.atmire.com/rest/api/core/items/d7b6bc6f-ff6c-444a-a0d3-0cd9b68043e7/templateItemOf' + }, + self: { + href: 'https://dspace7-internal.atmire.com/rest/api/core/items/d7b6bc6f-ff6c-444a-a0d3-0cd9b68043e7' + } + } + }, + { + id: '27c6f976-257c-4ad0-a0ef-c5e34ffe4d5b', + uuid: '27c6f976-257c-4ad0-a0ef-c5e34ffe4d5b', + name: 'Development of Local Supply Chain : The Missing Link for Concentrated Solar Power Projects in India', + handle: '10986/17475', + metadata: [ + { + key: 'dc.creator', + value: 'World Bank', + language: null + } + ], + inArchive: true, + discoverable: true, + withdrawn: false, + lastModified: '2018-05-25T09:33:42.526+0000', + type: 'item', + _links: { + bitstreams: { + href: 'https://dspace7-internal.atmire.com/rest/api/core/items/27c6f976-257c-4ad0-a0ef-c5e34ffe4d5b/bitstreams' + }, + owningCollection: { + href: 'https://dspace7-internal.atmire.com/rest/api/core/items/27c6f976-257c-4ad0-a0ef-c5e34ffe4d5b/owningCollection' + }, + templateItemOf: { + href: 'https://dspace7-internal.atmire.com/rest/api/core/items/27c6f976-257c-4ad0-a0ef-c5e34ffe4d5b/templateItemOf' + }, + self: { + href: 'https://dspace7-internal.atmire.com/rest/api/core/items/27c6f976-257c-4ad0-a0ef-c5e34ffe4d5b' + } + } + } + ] + }, + _links: { + first: { + href: 'https://dspace7-internal.atmire.com/rest/api/discover/browses/author/items?page=0&size=2' + }, + self: { + href: 'https://dspace7-internal.atmire.com/rest/api/discover/browses/author/items' + }, + next: { + href: 'https://dspace7-internal.atmire.com/rest/api/discover/browses/author/items?page=1&size=2' + }, + last: { + href: 'https://dspace7-internal.atmire.com/rest/api/discover/browses/author/items?page=7&size=2' + } + }, + page: { + size: 2, + totalElements: 16, + totalPages: 8, + number: 0 + } + }, + statusCode: '200' + } as DSpaceRESTV2Response; + + const invalidResponseNotAList = { + payload: { + id: 'd7b6bc6f-ff6c-444a-a0d3-0cd9b68043e7', + uuid: 'd7b6bc6f-ff6c-444a-a0d3-0cd9b68043e7', + name: 'Development of Local Supply Chain : A Critical Link for Concentrated Solar Power in India', + handle: '10986/17472', + metadata: [ + { + key: 'dc.creator', + value: 'World Bank', + language: null + } + ], + inArchive: true, + discoverable: true, + withdrawn: false, + lastModified: '2018-05-25T09:32:58.005+0000', + type: 'item', + _links: { + bitstreams: { + href: 'https://dspace7-internal.atmire.com/rest/api/core/items/d7b6bc6f-ff6c-444a-a0d3-0cd9b68043e7/bitstreams' + }, + owningCollection: { + href: 'https://dspace7-internal.atmire.com/rest/api/core/items/d7b6bc6f-ff6c-444a-a0d3-0cd9b68043e7/owningCollection' + }, + templateItemOf: { + href: 'https://dspace7-internal.atmire.com/rest/api/core/items/d7b6bc6f-ff6c-444a-a0d3-0cd9b68043e7/templateItemOf' + }, + self: { + href: 'https://dspace7-internal.atmire.com/rest/api/core/items/d7b6bc6f-ff6c-444a-a0d3-0cd9b68043e7' + } + } + }, + statusCode: '200' + } as DSpaceRESTV2Response; + + const invalidResponseStatusCode = { + payload: {}, statusCode: '500' + } as DSpaceRESTV2Response; + + it('should return a GenericSuccessResponse if data contains a valid browse items response', () => { + const response = service.parse(request, validResponse); + expect(response.constructor).toBe(GenericSuccessResponse); + }); + + it('should return an ErrorResponse if data contains an invalid browse entries response', () => { + const response = service.parse(request, invalidResponseNotAList); + expect(response.constructor).toBe(ErrorResponse); + }); + + it('should return an ErrorResponse if data contains a statuscode other than 200', () => { + const response = service.parse(request, invalidResponseStatusCode); + expect(response.constructor).toBe(ErrorResponse); + }); + + }); +}); diff --git a/src/app/core/data/browse-items-response-parsing-service.ts b/src/app/core/data/browse-items-response-parsing-service.ts new file mode 100644 index 0000000000..840d59b863 --- /dev/null +++ b/src/app/core/data/browse-items-response-parsing-service.ts @@ -0,0 +1,49 @@ +import { Inject, Injectable } from '@angular/core'; +import { GLOBAL_CONFIG } from '../../../config'; +import { GlobalConfig } from '../../../config/global-config.interface'; +import { isNotEmpty } from '../../shared/empty.util'; +import { ObjectCacheService } from '../cache/object-cache.service'; +import { + ErrorResponse, + GenericSuccessResponse, + RestResponse +} from '../cache/response-cache.models'; +import { DSpaceRESTV2Response } from '../dspace-rest-v2/dspace-rest-v2-response.model'; +import { DSpaceRESTv2Serializer } from '../dspace-rest-v2/dspace-rest-v2.serializer'; +import { BaseResponseParsingService } from './base-response-parsing.service'; +import { ResponseParsingService } from './parsing.service'; +import { RestRequest } from './request.models'; +import { Item } from '../shared/item.model'; +import { DSpaceObject } from '../shared/dspace-object.model'; + +@Injectable() +export class BrowseItemsResponseParsingService extends BaseResponseParsingService implements ResponseParsingService { + + protected objectFactory = { + getConstructor: () => DSpaceObject + }; + protected toCache = false; + + constructor( + @Inject(GLOBAL_CONFIG) protected EnvConfig: GlobalConfig, + protected objectCache: ObjectCacheService, + ) { super(); + } + + parse(request: RestRequest, data: DSpaceRESTV2Response): RestResponse { + if (isNotEmpty(data.payload) && isNotEmpty(data.payload._embedded) + && Array.isArray(data.payload._embedded[Object.keys(data.payload._embedded)[0]])) { + const serializer = new DSpaceRESTv2Serializer(DSpaceObject); + const items = serializer.deserializeArray(data.payload._embedded[Object.keys(data.payload._embedded)[0]]); + return new GenericSuccessResponse(items, data.statusCode, this.processPageInfo(data.payload)); + } else { + return new ErrorResponse( + Object.assign( + new Error('Unexpected response from browse endpoint'), + { statusText: data.statusCode } + ) + ); + } + } + +} diff --git a/src/app/core/data/comcol-data.service.spec.ts b/src/app/core/data/comcol-data.service.spec.ts index b5727fb22f..59ae6619d8 100644 --- a/src/app/core/data/comcol-data.service.spec.ts +++ b/src/app/core/data/comcol-data.service.spec.ts @@ -10,7 +10,7 @@ import { ResponseCacheService } from '../cache/response-cache.service'; import { CoreState } from '../core.reducers'; import { ComColDataService } from './comcol-data.service'; import { CommunityDataService } from './community-data.service'; -import { FindByIDRequest } from './request.models'; +import { FindAllOptions, FindByIDRequest } from './request.models'; import { RequestService } from './request.service'; import { NormalizedObject } from '../cache/models/normalized-object.model'; import { HALEndpointService } from '../shared/hal-endpoint.service'; @@ -53,6 +53,10 @@ describe('ComColDataService', () => { const EnvConfig = {} as GlobalConfig; const scopeID = 'd9d30c0c-69b7-4369-8397-ca67c888974d'; + const options = Object.assign(new FindAllOptions(), { + scopeID: scopeID + }); + const communitiesEndpoint = 'https://rest.api/core/communities'; const communityEndpoint = `${communitiesEndpoint}/${scopeID}`; const scopedEndpoint = `${communityEndpoint}/${LINK_NAME}`; @@ -99,7 +103,7 @@ describe('ComColDataService', () => { ); } - describe('getScopedEndpoint', () => { + describe('getBrowseEndpoint', () => { beforeEach(() => { scheduler = getTestScheduler(); }); @@ -113,7 +117,7 @@ describe('ComColDataService', () => { const expected = new FindByIDRequest(requestService.generateRequestId(), communityEndpoint, scopeID); - scheduler.schedule(() => service.getScopedEndpoint(scopeID).subscribe()); + scheduler.schedule(() => service.getBrowseEndpoint(options).subscribe()); scheduler.flush(); expect(requestService.configure).toHaveBeenCalledWith(expected); @@ -129,13 +133,13 @@ describe('ComColDataService', () => { }); it('should fetch the scope Community from the cache', () => { - scheduler.schedule(() => service.getScopedEndpoint(scopeID).subscribe()); + scheduler.schedule(() => service.getBrowseEndpoint(options).subscribe()); scheduler.flush(); expect(objectCache.getByUUID).toHaveBeenCalledWith(scopeID); }); it('should return the endpoint to fetch resources within the given scope', () => { - const result = service.getScopedEndpoint(scopeID); + const result = service.getBrowseEndpoint(options); const expected = cold('--e-', { e: scopedEndpoint }); expect(result).toBeObservable(expected); @@ -152,7 +156,7 @@ describe('ComColDataService', () => { }); it('should throw an error', () => { - const result = service.getScopedEndpoint(scopeID); + const result = service.getBrowseEndpoint(options); const expected = cold('--#-', undefined, new Error(`The Community with scope ${scopeID} couldn't be retrieved`)); expect(result).toBeObservable(expected); diff --git a/src/app/core/data/comcol-data.service.ts b/src/app/core/data/comcol-data.service.ts index 112afa0bc8..bb624eda0f 100644 --- a/src/app/core/data/comcol-data.service.ts +++ b/src/app/core/data/comcol-data.service.ts @@ -8,7 +8,7 @@ import { ResponseCacheEntry } from '../cache/response-cache.reducer'; import { CommunityDataService } from './community-data.service'; import { DataService } from './data.service'; -import { FindByIDRequest } from './request.models'; +import { FindAllOptions, FindByIDRequest } from './request.models'; import { NormalizedObject } from '../cache/models/normalized-object.model'; import { HALEndpointService } from '../shared/hal-endpoint.service'; @@ -27,16 +27,16 @@ export abstract class ComColDataService } * an Observable containing the scoped URL */ - public getScopedEndpoint(scopeID: string): Observable { - if (isEmpty(scopeID)) { + public getBrowseEndpoint(options: FindAllOptions = {}): Observable { + if (isEmpty(options.scopeID)) { return this.halService.getEndpoint(this.linkPath); } else { const scopeCommunityHrefObs = this.cds.getEndpoint() - .flatMap((endpoint: string) => this.cds.getFindByIDHref(endpoint, scopeID)) + .flatMap((endpoint: string) => this.cds.getFindByIDHref(endpoint, options.scopeID)) .filter((href: string) => isNotEmpty(href)) .take(1) .do((href: string) => { - const request = new FindByIDRequest(this.requestService.generateRequestId(), href, scopeID); + const request = new FindByIDRequest(this.requestService.generateRequestId(), href, options.scopeID); this.requestService.configure(request); }); @@ -48,9 +48,9 @@ export abstract class ComColDataService - Observable.throw(new Error(`The Community with scope ${scopeID} couldn't be retrieved`))), + Observable.throw(new Error(`The Community with scope ${options.scopeID} couldn't be retrieved`))), successResponse - .flatMap((response: DSOSuccessResponse) => this.objectCache.getByUUID(scopeID)) + .flatMap((response: DSOSuccessResponse) => this.objectCache.getByUUID(options.scopeID)) .map((nc: NormalizedCommunity) => nc._links[this.linkPath]) .filter((href) => isNotEmpty(href)) ).distinctUntilChanged(); diff --git a/src/app/core/data/data.service.ts b/src/app/core/data/data.service.ts index f532ff05ba..5c01412ba7 100644 --- a/src/app/core/data/data.service.ts +++ b/src/app/core/data/data.service.ts @@ -20,17 +20,13 @@ export abstract class DataService protected abstract linkPath: string; protected abstract halService: HALEndpointService; - public abstract getScopedEndpoint(scope: string): Observable + public abstract getBrowseEndpoint(options: FindAllOptions): Observable - protected getFindAllHref(endpoint, options: FindAllOptions = {}): Observable { + protected getFindAllHref(options: FindAllOptions = {}): Observable { let result: Observable; const args = []; - if (hasValue(options.scopeID)) { - result = this.getScopedEndpoint(options.scopeID).distinctUntilChanged(); - } else { - result = Observable.of(endpoint); - } + result = this.getBrowseEndpoint(options).distinctUntilChanged(); if (hasValue(options.currentPage) && typeof options.currentPage === 'number') { /* TODO: this is a temporary fix for the pagination start index (0 or 1) discrepancy between the rest and the frontend respectively */ @@ -53,8 +49,7 @@ export abstract class DataService } findAll(options: FindAllOptions = {}): Observable>> { - const hrefObs = this.halService.getEndpoint(this.linkPath).filter((href: string) => isNotEmpty(href)) - .flatMap((endpoint: string) => this.getFindAllHref(endpoint, options)); + const hrefObs = this.getFindAllHref(options); hrefObs .filter((href: string) => hasValue(href)) diff --git a/src/app/core/data/item-data.service.spec.ts b/src/app/core/data/item-data.service.spec.ts index 4d0dc8aec3..718fbde2f6 100644 --- a/src/app/core/data/item-data.service.spec.ts +++ b/src/app/core/data/item-data.service.spec.ts @@ -8,6 +8,7 @@ import { CoreState } from '../core.reducers'; import { ItemDataService } from './item-data.service'; import { RequestService } from './request.service'; import { HALEndpointService } from '../shared/hal-endpoint.service'; +import { FindAllOptions } from './request.models'; describe('ItemDataService', () => { let scheduler: TestScheduler; @@ -20,9 +21,19 @@ describe('ItemDataService', () => { const halEndpointService = {} as HALEndpointService; const scopeID = '4af28e99-6a9c-4036-a199-e1b587046d39'; + const startsWith = 'a'; + const options = Object.assign(new FindAllOptions(), { + scopeID: scopeID, + sort: { + field: '', + direction: undefined + }, + startsWith: startsWith + }); + const browsesEndpoint = 'https://rest.api/discover/browses'; const itemBrowseEndpoint = `${browsesEndpoint}/author/items`; - const scopedEndpoint = `${itemBrowseEndpoint}?scope=${scopeID}`; + const scopedEndpoint = `${itemBrowseEndpoint}?scope=${scopeID}&startsWith=${startsWith}`; const serviceEndpoint = `https://rest.api/core/items`; const browseError = new Error('getBrowseURL failed'); @@ -46,16 +57,16 @@ describe('ItemDataService', () => { ); } - describe('getScopedEndpoint', () => { + describe('getBrowseEndpoint', () => { beforeEach(() => { scheduler = getTestScheduler(); }); - it('should return the endpoint to fetch Items within the given scope', () => { + it('should return the endpoint to fetch Items within the given scope and starting with the given string', () => { bs = initMockBrowseService(true); service = initTestService(); - const result = service.getScopedEndpoint(scopeID); + const result = service.getBrowseEndpoint(options); const expected = cold('--b-', { b: scopedEndpoint }); expect(result).toBeObservable(expected); @@ -67,7 +78,7 @@ describe('ItemDataService', () => { service = initTestService(); }); it('should throw an error', () => { - const result = service.getScopedEndpoint(scopeID); + const result = service.getBrowseEndpoint(options); const expected = cold('--#-', undefined, browseError); expect(result).toBeObservable(expected); diff --git a/src/app/core/data/item-data.service.ts b/src/app/core/data/item-data.service.ts index 6b0937d8e4..eb0896efdd 100644 --- a/src/app/core/data/item-data.service.ts +++ b/src/app/core/data/item-data.service.ts @@ -15,6 +15,7 @@ import { URLCombiner } from '../url-combiner/url-combiner'; import { DataService } from './data.service'; import { RequestService } from './request.service'; import { HALEndpointService } from '../shared/hal-endpoint.service'; +import { FindAllOptions } from './request.models'; @Injectable() export class ItemDataService extends DataService { @@ -30,15 +31,15 @@ export class ItemDataService extends DataService { super(); } - public getScopedEndpoint(scopeID: string): Observable { - if (isEmpty(scopeID)) { - return this.halService.getEndpoint(this.linkPath); - } else { - return this.bs.getBrowseURLFor('dc.date.issued', this.linkPath) - .filter((href: string) => isNotEmpty(href)) - .map((href: string) => new URLCombiner(href, `?scope=${scopeID}`).toString()) - .distinctUntilChanged(); + public getBrowseEndpoint(options: FindAllOptions = {}): Observable { + let field = 'dc.date.issued'; + if (options.sort && options.sort.field) { + field = options.sort.field; } + return this.bs.getBrowseURLFor(field, this.linkPath) + .filter((href: string) => isNotEmpty(href)) + .map((href: string) => new URLCombiner(href, `?scope=${options.scopeID}` + (options.startsWith ? `&startsWith=${options.startsWith}` : '')).toString()) + .distinctUntilChanged(); } } diff --git a/src/app/core/data/request.models.ts b/src/app/core/data/request.models.ts index 7015b0b0f1..b87f9cefc8 100644 --- a/src/app/core/data/request.models.ts +++ b/src/app/core/data/request.models.ts @@ -12,6 +12,7 @@ import { AuthResponseParsingService } from '../auth/auth-response-parsing.servic import { HttpOptions } from '../dspace-rest-v2/dspace-rest-v2.service'; import { HttpHeaders } from '@angular/common/http'; import { IntegrationResponseParsingService } from '../integration/integration-response-parsing.service'; +import { BrowseItemsResponseParsingService } from './browse-items-response-parsing-service'; /* tslint:disable:max-classes-per-file */ @@ -141,6 +142,7 @@ export class FindAllOptions { elementsPerPage?: number; currentPage?: number; sort?: SortOptions; + startsWith?: string; } export class FindAllRequest extends GetRequest { @@ -183,6 +185,12 @@ export class BrowseEntriesRequest extends GetRequest { } } +export class BrowseItemsRequest extends GetRequest { + getResponseParser(): GenericConstructor { + return BrowseItemsResponseParsingService; + } +} + export class ConfigRequest extends GetRequest { constructor(uuid: string, href: string) { super(uuid, href); diff --git a/src/app/core/shared/browse-entry.model.ts b/src/app/core/shared/browse-entry.model.ts index fede195a39..932c6946d1 100644 --- a/src/app/core/shared/browse-entry.model.ts +++ b/src/app/core/shared/browse-entry.model.ts @@ -1,6 +1,7 @@ import { autoserialize, autoserializeAs } from 'cerialize'; +import { ListableObject } from '../../shared/object-collection/shared/listable-object.model'; -export class BrowseEntry { +export class BrowseEntry implements ListableObject { @autoserialize type: string; diff --git a/src/app/core/shared/dspace-object.model.ts b/src/app/core/shared/dspace-object.model.ts index 5e62e3e321..042bfc01a0 100644 --- a/src/app/core/shared/dspace-object.model.ts +++ b/src/app/core/shared/dspace-object.model.ts @@ -5,6 +5,7 @@ import { RemoteData } from '../data/remote-data'; import { ResourceType } from './resource-type'; import { ListableObject } from '../../shared/object-collection/shared/listable-object.model'; import { Observable } from 'rxjs/Observable'; +import { autoserialize } from 'cerialize'; /** * An abstract model class for a DSpaceObject. @@ -16,11 +17,13 @@ export class DSpaceObject implements CacheableObject, ListableObject { /** * The human-readable identifier of this DSpaceObject */ + @autoserialize id: string; /** * The universally unique identifier of this DSpaceObject */ + @autoserialize uuid: string; /** @@ -31,11 +34,13 @@ export class DSpaceObject implements CacheableObject, ListableObject { /** * The name for this DSpaceObject */ + @autoserialize name: string; /** * An array containing all metadata of this DSpaceObject */ + @autoserialize metadata: Metadatum[]; /** diff --git a/src/app/core/shared/operators.ts b/src/app/core/shared/operators.ts index c0b9be3fbf..9009473765 100644 --- a/src/app/core/shared/operators.ts +++ b/src/app/core/shared/operators.ts @@ -1,6 +1,6 @@ import { Observable } from 'rxjs/Observable'; import { filter, flatMap, map, tap } from 'rxjs/operators'; -import { hasValueOperator } from '../../shared/empty.util'; +import { hasValueOperator, isNotEmpty } from '../../shared/empty.util'; import { DSOSuccessResponse } from '../cache/response-cache.models'; import { ResponseCacheEntry } from '../cache/response-cache.reducer'; import { ResponseCacheService } from '../cache/response-cache.service'; @@ -8,6 +8,7 @@ import { RemoteData } from '../data/remote-data'; import { RestRequest } from '../data/request.models'; import { RequestEntry } from '../data/request.reducer'; import { RequestService } from '../data/request.service'; +import { BrowseDefinition } from './browse-definition.model'; /** * This file contains custom RxJS operators that can be used in multiple places @@ -45,3 +46,19 @@ export const configureRequest = (requestService: RequestService) => export const getRemoteDataPayload = () => (source: Observable>): Observable => source.pipe(map((remoteData: RemoteData) => remoteData.payload)); + +export const getBrowseDefinitionLinks = (definitionID: string) => + (source: Observable>): Observable => + source.pipe( + getRemoteDataPayload(), + map((browseDefinitions: BrowseDefinition[]) => browseDefinitions + .find((def: BrowseDefinition) => def.id === definitionID && def.metadataBrowse === true) + ), + map((def: BrowseDefinition) => { + if (isNotEmpty(def)) { + return def._links; + } else { + throw new Error(`No metadata browse definition could be found for id '${definitionID}'`); + } + }) + ); diff --git a/src/app/shared/browse-by/browse-by.component.html b/src/app/shared/browse-by/browse-by.component.html new file mode 100644 index 0000000000..f30c5b905c --- /dev/null +++ b/src/app/shared/browse-by/browse-by.component.html @@ -0,0 +1,12 @@ + +

{{title}}

+
+ + +
+ + +
diff --git a/src/app/shared/browse-by/browse-by.component.scss b/src/app/shared/browse-by/browse-by.component.scss new file mode 100644 index 0000000000..e69de29bb2 diff --git a/src/app/shared/browse-by/browse-by.component.spec.ts b/src/app/shared/browse-by/browse-by.component.spec.ts new file mode 100644 index 0000000000..883d61a221 --- /dev/null +++ b/src/app/shared/browse-by/browse-by.component.spec.ts @@ -0,0 +1,44 @@ +import { BrowseByComponent } from './browse-by.component'; +import { async, ComponentFixture, TestBed } from '@angular/core/testing'; +import { TranslateModule } from '@ngx-translate/core'; +import { By } from '@angular/platform-browser'; +import { NO_ERRORS_SCHEMA } from '@angular/core'; +import { Observable } from 'rxjs/Observable'; +import { SharedModule } from '../shared.module'; + +describe('BrowseByComponent', () => { + let comp: BrowseByComponent; + let fixture: ComponentFixture; + + beforeEach(async(() => { + TestBed.configureTestingModule({ + imports: [TranslateModule.forRoot(), SharedModule], + declarations: [], + schemas: [NO_ERRORS_SCHEMA] + }).compileComponents(); + })); + + beforeEach(() => { + fixture = TestBed.createComponent(BrowseByComponent); + comp = fixture.componentInstance; + }); + + it('should display a loading message when objects is empty',() => { + (comp as any).objects = undefined; + fixture.detectChanges(); + expect(fixture.debugElement.query(By.css('ds-loading'))).toBeDefined(); + }); + + it('should display results when objects is not empty', () => { + (comp as any).objects = Observable.of({ + payload: { + page: { + length: 1 + } + } + }); + fixture.detectChanges(); + expect(fixture.debugElement.query(By.css('ds-viewable-collection'))).toBeDefined(); + }); + +}); diff --git a/src/app/shared/browse-by/browse-by.component.ts b/src/app/shared/browse-by/browse-by.component.ts new file mode 100644 index 0000000000..196134224c --- /dev/null +++ b/src/app/shared/browse-by/browse-by.component.ts @@ -0,0 +1,27 @@ +import { Component, Input } from '@angular/core'; +import { RemoteData } from '../../core/data/remote-data'; +import { PaginatedList } from '../../core/data/paginated-list'; +import { PaginationComponentOptions } from '../pagination/pagination-component-options.model'; +import { SortOptions } from '../../core/cache/models/sort-options.model'; +import { fadeIn, fadeInOut } from '../animations/fade'; +import { Observable } from 'rxjs/Observable'; +import { Item } from '../../core/shared/item.model'; +import { ListableObject } from '../object-collection/shared/listable-object.model'; + +@Component({ + selector: 'ds-browse-by', + styleUrls: ['./browse-by.component.scss'], + templateUrl: './browse-by.component.html', + animations: [ + fadeIn, + fadeInOut + ] +}) +export class BrowseByComponent { + @Input() title: string; + @Input() objects$: Observable>>; + @Input() paginationConfig: PaginationComponentOptions; + @Input() sortConfig: SortOptions; + @Input() currentUrl: string; + query: string; +} diff --git a/src/app/shared/object-collection/object-collection.component.html b/src/app/shared/object-collection/object-collection.component.html index c9b1cb92f5..b1d07db876 100644 --- a/src/app/shared/object-collection/object-collection.component.html +++ b/src/app/shared/object-collection/object-collection.component.html @@ -8,7 +8,7 @@ diff --git a/src/app/shared/object-grid/item-grid-element/item-grid-element.component.html b/src/app/shared/object-grid/item-grid-element/item-grid-element.component.html index cc2f2efdb1..ee1b9c4239 100644 --- a/src/app/shared/object-grid/item-grid-element/item-grid-element.component.html +++ b/src/app/shared/object-grid/item-grid-element/item-grid-element.component.html @@ -1,22 +1,28 @@ -
+ +
+ + + + +
+

{{object.findMetadata('dc.title')}}

- - - - -
-

{{object.findMetadata('dc.title')}}

-

- {{authorMd.value}} - ; - - {{object.findMetadata("dc.date.issued")}} -

+ +

+ {{authorMd.value}} + ; + + {{object.findMetadata("dc.date.issued")}} +

+
-

{{object.findMetadata("dc.description.abstract") | dsTruncate:[200] }}

+ +

{{object.findMetadata("dc.description.abstract") }}

+
-
- View +
+ View +
-
+ diff --git a/src/app/shared/object-list/browse-entry-list-element/browse-entry-list-element.component.html b/src/app/shared/object-list/browse-entry-list-element/browse-entry-list-element.component.html new file mode 100644 index 0000000000..9eedb70eab --- /dev/null +++ b/src/app/shared/object-list/browse-entry-list-element/browse-entry-list-element.component.html @@ -0,0 +1,3 @@ + + {{object.value}} + diff --git a/src/app/shared/object-list/browse-entry-list-element/browse-entry-list-element.component.scss b/src/app/shared/object-list/browse-entry-list-element/browse-entry-list-element.component.scss new file mode 100644 index 0000000000..45a533cd01 --- /dev/null +++ b/src/app/shared/object-list/browse-entry-list-element/browse-entry-list-element.component.scss @@ -0,0 +1 @@ +@import '../../../../styles/variables'; diff --git a/src/app/shared/object-list/browse-entry-list-element/browse-entry-list-element.component.spec.ts b/src/app/shared/object-list/browse-entry-list-element/browse-entry-list-element.component.spec.ts new file mode 100644 index 0000000000..de53f2e095 --- /dev/null +++ b/src/app/shared/object-list/browse-entry-list-element/browse-entry-list-element.component.spec.ts @@ -0,0 +1,47 @@ +import { async, ComponentFixture, TestBed } from '@angular/core/testing'; +import { ChangeDetectionStrategy, NO_ERRORS_SCHEMA } from '@angular/core'; +import { By } from '@angular/platform-browser'; +import { TruncatePipe } from '../../utils/truncate.pipe'; +import { Metadatum } from '../../../core/shared/metadatum.model'; +import { BrowseEntryListElementComponent } from './browse-entry-list-element.component'; +import { BrowseEntry } from '../../../core/shared/browse-entry.model'; + +let browseEntryListElementComponent: BrowseEntryListElementComponent; +let fixture: ComponentFixture; + +const mockValue: BrowseEntry = Object.assign(new BrowseEntry(), { + type: 'browseEntry', + value: 'De Langhe Kristof' +}); + +describe('MetadataListElementComponent', () => { + beforeEach(async(() => { + TestBed.configureTestingModule({ + declarations: [ BrowseEntryListElementComponent , TruncatePipe], + providers: [ + { provide: 'objectElementProvider', useValue: {mockValue}} + ], + + schemas: [ NO_ERRORS_SCHEMA ] + }).overrideComponent(BrowseEntryListElementComponent, { + set: { changeDetection: ChangeDetectionStrategy.Default } + }).compileComponents(); + })); + + beforeEach(async(() => { + fixture = TestBed.createComponent(BrowseEntryListElementComponent); + browseEntryListElementComponent = fixture.componentInstance; + })); + + describe('When the metadatum is loaded', () => { + beforeEach(() => { + browseEntryListElementComponent.object = mockValue; + fixture.detectChanges(); + }); + + it('should show the value as a link', () => { + const browseEntryLink = fixture.debugElement.query(By.css('a.lead')); + expect(browseEntryLink.nativeElement.textContent.trim()).toBe(mockValue.value); + }); + }); +}); diff --git a/src/app/shared/object-list/browse-entry-list-element/browse-entry-list-element.component.ts b/src/app/shared/object-list/browse-entry-list-element/browse-entry-list-element.component.ts new file mode 100644 index 0000000000..a5c92e87ae --- /dev/null +++ b/src/app/shared/object-list/browse-entry-list-element/browse-entry-list-element.component.ts @@ -0,0 +1,17 @@ +import { Component, Input, Inject } from '@angular/core'; + +import { AbstractListableElementComponent } from '../../object-collection/shared/object-collection-element/abstract-listable-element.component'; +import { renderElementsFor } from '../../object-collection/shared/dso-element-decorator'; +import { ViewMode } from '../../../+search-page/search-options.model'; +import { BrowseEntry } from '../../../core/shared/browse-entry.model'; +import { ActivatedRoute, Router } from '@angular/router'; +import { ListableObject } from '../../object-collection/shared/listable-object.model'; + +@Component({ + selector: 'ds-browse-entry-list-element', + styleUrls: ['./browse-entry-list-element.component.scss'], + templateUrl: './browse-entry-list-element.component.html' +}) + +@renderElementsFor(BrowseEntry, ViewMode.List) +export class BrowseEntryListElementComponent extends AbstractListableElementComponent {} diff --git a/src/app/shared/object-list/item-list-element/item-list-element.component.html b/src/app/shared/object-list/item-list-element/item-list-element.component.html index b4259c25c2..28b83b4000 100644 --- a/src/app/shared/object-list/item-list-element/item-list-element.component.html +++ b/src/app/shared/object-list/item-list-element/item-list-element.component.html @@ -1,18 +1,24 @@ - - {{object.findMetadata("dc.title")}} - -
- - - {{authorMd.value}} - ; + + + {{object.findMetadata("dc.title")}} + +
+ + + + {{authorMd.value}} + ; + - - ({{object.findMetadata("dc.publisher")}}, {{object.findMetadata("dc.date.issued")}}) - -
- {{object.findMetadata("dc.description.abstract") | dsTruncate:[200] }} -
-
+ ({{object.findMetadata("dc.publisher")}}, {{object.findMetadata("dc.date.issued")}}) +
+ + +
+ {{object.findMetadata("dc.description.abstract")}} +
+
+
+ diff --git a/src/app/shared/object-list/metadata-list-element/metadata-list-element.component.html b/src/app/shared/object-list/metadata-list-element/metadata-list-element.component.html new file mode 100644 index 0000000000..c05c4c10c9 --- /dev/null +++ b/src/app/shared/object-list/metadata-list-element/metadata-list-element.component.html @@ -0,0 +1,3 @@ + + {{object.value}} + diff --git a/src/app/shared/object-list/metadata-list-element/metadata-list-element.component.scss b/src/app/shared/object-list/metadata-list-element/metadata-list-element.component.scss new file mode 100644 index 0000000000..45a533cd01 --- /dev/null +++ b/src/app/shared/object-list/metadata-list-element/metadata-list-element.component.scss @@ -0,0 +1 @@ +@import '../../../../styles/variables'; diff --git a/src/app/shared/object-list/metadata-list-element/metadata-list-element.component.spec.ts b/src/app/shared/object-list/metadata-list-element/metadata-list-element.component.spec.ts new file mode 100644 index 0000000000..8098a6a8c9 --- /dev/null +++ b/src/app/shared/object-list/metadata-list-element/metadata-list-element.component.spec.ts @@ -0,0 +1,48 @@ +import { MetadataListElementComponent } from './metadata-list-element.component'; +import { async, ComponentFixture, TestBed } from '@angular/core/testing'; +import { ChangeDetectionStrategy, NO_ERRORS_SCHEMA } from '@angular/core'; +import { By } from '@angular/platform-browser'; +import { TruncatePipe } from '../../utils/truncate.pipe'; +import { Item } from '../../../core/shared/item.model'; +import { Observable } from 'rxjs/Observable'; +import { Metadatum } from '../../../core/shared/metadatum.model'; + +let metadataListElementComponent: MetadataListElementComponent; +let fixture: ComponentFixture; + +const mockValue: Metadatum = Object.assign(new Metadatum(), { + key: 'dc.contributor.author', + value: 'De Langhe Kristof' +}); + +describe('MetadataListElementComponent', () => { + beforeEach(async(() => { + TestBed.configureTestingModule({ + declarations: [ MetadataListElementComponent , TruncatePipe], + providers: [ + { provide: 'objectElementProvider', useValue: {mockValue}} + ], + + schemas: [ NO_ERRORS_SCHEMA ] + }).overrideComponent(MetadataListElementComponent, { + set: { changeDetection: ChangeDetectionStrategy.Default } + }).compileComponents(); + })); + + beforeEach(async(() => { + fixture = TestBed.createComponent(MetadataListElementComponent); + metadataListElementComponent = fixture.componentInstance; + })); + + describe('When the metadatum is loaded', () => { + beforeEach(() => { + metadataListElementComponent.object = mockValue; + fixture.detectChanges(); + }); + + it('should show the value as a link', () => { + const metadatumLink = fixture.debugElement.query(By.css('a.lead')); + expect(metadatumLink.nativeElement.textContent.trim()).toBe(mockValue.value); + }); + }); +}); diff --git a/src/app/shared/object-list/metadata-list-element/metadata-list-element.component.ts b/src/app/shared/object-list/metadata-list-element/metadata-list-element.component.ts new file mode 100644 index 0000000000..12e140c7bf --- /dev/null +++ b/src/app/shared/object-list/metadata-list-element/metadata-list-element.component.ts @@ -0,0 +1,15 @@ +import { Component, Input, Inject } from '@angular/core'; + +import { AbstractListableElementComponent } from '../../object-collection/shared/object-collection-element/abstract-listable-element.component'; +import { renderElementsFor } from '../../object-collection/shared/dso-element-decorator'; +import { ViewMode } from '../../../+search-page/search-options.model'; +import { Metadatum } from '../../../core/shared/metadatum.model'; + +@Component({ + selector: 'ds-metadata-list-element', + styleUrls: ['./metadata-list-element.component.scss'], + templateUrl: './metadata-list-element.component.html' +}) + +@renderElementsFor(Metadatum, ViewMode.List) +export class MetadataListElementComponent extends AbstractListableElementComponent {} diff --git a/src/app/shared/shared.module.ts b/src/app/shared/shared.module.ts index 57ba7dec4d..223eab4c69 100644 --- a/src/app/shared/shared.module.ts +++ b/src/app/shared/shared.module.ts @@ -72,6 +72,10 @@ import { NumberPickerComponent } from './number-picker/number-picker.component'; import { DsDatePickerComponent } from './form/builder/ds-dynamic-form-ui/models/date-picker/date-picker.component'; import { DsDynamicLookupComponent } from './form/builder/ds-dynamic-form-ui/models/lookup/dynamic-lookup.component'; import { MockAdminGuard } from './mocks/mock-admin-guard.service'; +import { MetadataListElementComponent } from './object-list/metadata-list-element/metadata-list-element.component'; +import { BrowseByModule } from '../+browse-by/browse-by.module'; +import { BrowseByComponent } from './browse-by/browse-by.component'; +import { BrowseEntryListElementComponent } from './object-list/browse-entry-list-element/browse-entry-list-element.component'; const MODULES = [ // Do NOT include UniversalModule, HttpModule, or JsonpModule here @@ -139,11 +143,13 @@ const COMPONENTS = [ ViewModeSwitchComponent, TruncatableComponent, TruncatablePartComponent, + BrowseByComponent ]; const ENTRY_COMPONENTS = [ // put shared entry components (components that are created dynamically) here ItemListElementComponent, + MetadataListElementComponent, CollectionListElementComponent, CommunityListElementComponent, SearchResultListElementComponent, @@ -151,6 +157,7 @@ const ENTRY_COMPONENTS = [ CollectionGridElementComponent, CommunityGridElementComponent, SearchResultGridElementComponent, + BrowseEntryListElementComponent ]; const PROVIDERS = [ From 072507b2932472f3dc8c41fe878d68f282450123 Mon Sep 17 00:00:00 2001 From: Kristof De Langhe Date: Thu, 9 Aug 2018 12:37:09 +0200 Subject: [PATCH 02/48] improved coverage, type docs, removed startsWith option and general refactoring --- .../browse-by-author-page.component.ts | 15 +++--- .../browse-by-title-page.component.ts | 16 +++++-- src/app/core/browse/browse.service.spec.ts | 39 +++++++++++++-- src/app/core/browse/browse.service.ts | 9 ++++ src/app/core/data/item-data.service.spec.ts | 6 +-- src/app/core/data/item-data.service.ts | 2 +- src/app/core/shared/operators.ts | 5 ++ .../shared/browse-by/browse-by.component.ts | 3 ++ .../metadata-list-element.component.html | 3 -- .../metadata-list-element.component.scss | 1 - .../metadata-list-element.component.spec.ts | 48 ------------------- .../metadata-list-element.component.ts | 15 ------ src/app/shared/shared.module.ts | 2 - 13 files changed, 74 insertions(+), 90 deletions(-) delete mode 100644 src/app/shared/object-list/metadata-list-element/metadata-list-element.component.html delete mode 100644 src/app/shared/object-list/metadata-list-element/metadata-list-element.component.scss delete mode 100644 src/app/shared/object-list/metadata-list-element/metadata-list-element.component.spec.ts delete mode 100644 src/app/shared/object-list/metadata-list-element/metadata-list-element.component.ts diff --git a/src/app/+browse-by/+browse-by-author-page/browse-by-author-page.component.ts b/src/app/+browse-by/+browse-by-author-page/browse-by-author-page.component.ts index 1605b4afab..1553889741 100644 --- a/src/app/+browse-by/+browse-by-author-page/browse-by-author-page.component.ts +++ b/src/app/+browse-by/+browse-by-author-page/browse-by-author-page.component.ts @@ -18,6 +18,9 @@ import { Item } from '../../core/shared/item.model'; styleUrls: ['./browse-by-author-page.component.scss'], templateUrl: './browse-by-author-page.component.html' }) +/** + * Component for browsing (items) by author (dc.contributor.author) + */ export class BrowseByAuthorPageComponent implements OnInit { authors$: Observable>>; @@ -55,7 +58,6 @@ export class BrowseByAuthorPageComponent implements OnInit { const pageSize = +params.pageSize || this.paginationConfig.pageSize; const sortDirection = params.sortDirection || this.sortConfig.direction; const sortField = params.sortField || this.sortConfig.field; - const startsWith = +params.query || params.query || ''; this.value = +params.value || params.value || ''; const pagination = Object.assign({}, this.paginationConfig, @@ -67,8 +69,7 @@ export class BrowseByAuthorPageComponent implements OnInit { ); const searchOptions = { pagination: pagination, - sort: sort, - startsWith: startsWith + sort: sort }; if (isNotEmpty(this.value)) { this.updatePageWithItems(searchOptions, this.value); @@ -79,10 +80,10 @@ export class BrowseByAuthorPageComponent implements OnInit { } /** + * Updates the current page with searchOptions * @param searchOptions Options to narrow down your search: * { pagination: PaginationComponentOptions, - * sort: SortOptions, - * startsWith: string } + * sort: SortOptions } */ updatePage(searchOptions) { this.authors$ = this.browseService.getBrowseEntriesFor('author', searchOptions); @@ -90,10 +91,10 @@ export class BrowseByAuthorPageComponent implements OnInit { } /** + * Updates the current page with searchOptions and display items linked to author * @param searchOptions Options to narrow down your search: * { pagination: PaginationComponentOptions, - * sort: SortOptions, - * startsWith: string } + * sort: SortOptions } * @param author The author's name for displaying items */ updatePageWithItems(searchOptions, author: string) { diff --git a/src/app/+browse-by/+browse-by-title-page/browse-by-title-page.component.ts b/src/app/+browse-by/+browse-by-title-page/browse-by-title-page.component.ts index 6483ac8d17..3205091952 100644 --- a/src/app/+browse-by/+browse-by-title-page/browse-by-title-page.component.ts +++ b/src/app/+browse-by/+browse-by-title-page/browse-by-title-page.component.ts @@ -17,6 +17,9 @@ import { Collection } from '../../core/shared/collection.model'; styleUrls: ['./browse-by-title-page.component.scss'], templateUrl: './browse-by-title-page.component.html' }) +/** + * Component for browsing items by title (dc.title) + */ export class BrowseByTitlePageComponent implements OnInit { items$: Observable>>; @@ -52,7 +55,6 @@ export class BrowseByTitlePageComponent implements OnInit { const page = +params.page || this.paginationConfig.currentPage; const pageSize = +params.pageSize || this.paginationConfig.pageSize; const sortDirection = +params.page || this.sortConfig.direction; - const startsWith = +params.query || params.query || ''; const pagination = Object.assign({}, this.paginationConfig, { currentPage: page, pageSize: pageSize } @@ -63,18 +65,22 @@ export class BrowseByTitlePageComponent implements OnInit { ); this.updatePage({ pagination: pagination, - sort: sort, - startsWith: startsWith + sort: sort }); })); } + /** + * Updates the current page with searchOptions + * @param searchOptions Options to narrow down your search: + * { pagination: PaginationComponentOptions, + * sort: SortOptions } + */ updatePage(searchOptions) { this.items$ = this.itemDataService.findAll({ currentPage: searchOptions.pagination.currentPage, elementsPerPage: searchOptions.pagination.pageSize, - sort: searchOptions.sort, - startsWith: searchOptions.startsWith + sort: searchOptions.sort }); } diff --git a/src/app/core/browse/browse.service.spec.ts b/src/app/core/browse/browse.service.spec.ts index 5118ea7ecc..daaca1e5b2 100644 --- a/src/app/core/browse/browse.service.spec.ts +++ b/src/app/core/browse/browse.service.spec.ts @@ -6,7 +6,7 @@ import { getMockResponseCacheService } from '../../shared/mocks/mock-response-ca import { HALEndpointServiceStub } from '../../shared/testing/hal-endpoint-service-stub'; import { RemoteDataBuildService } from '../cache/builders/remote-data-build.service'; import { ResponseCacheService } from '../cache/response-cache.service'; -import { BrowseEndpointRequest, BrowseEntriesRequest } from '../data/request.models'; +import { BrowseEndpointRequest, BrowseEntriesRequest, BrowseItemsRequest } from '../data/request.models'; import { RequestService } from '../data/request.service'; import { BrowseDefinition } from '../shared/browse-definition.model'; import { BrowseService } from './browse.service'; @@ -143,7 +143,9 @@ describe('BrowseService', () => { }); - describe('getBrowseEntriesFor', () => { + describe('getBrowseEntriesFor and getBrowseItemsFor', () => { + const mockAuthorName = 'Donald Smith'; + beforeEach(() => { responseCache = initMockResponseCacheService(true); requestService = getMockRequestService(); @@ -156,7 +158,7 @@ describe('BrowseService', () => { spyOn(rdbService, 'toRemoteDataObservable').and.callThrough(); }); - describe('when called with a valid browse definition id', () => { + describe('when getBrowseEntriesFor is called with a valid browse definition id', () => { it('should configure a new BrowseEntriesRequest', () => { const expected = new BrowseEntriesRequest(requestService.generateRequestId(), browseDefinitions[1]._links.entries); @@ -175,7 +177,26 @@ describe('BrowseService', () => { }); - describe('when called with an invalid browse definition id', () => { + describe('when getBrowseItemsFor is called with a valid browse definition id', () => { + it('should configure a new BrowseItemsRequest', () => { + const expected = new BrowseItemsRequest(requestService.generateRequestId(), browseDefinitions[1]._links.items + '?filterValue=' + mockAuthorName); + + scheduler.schedule(() => service.getBrowseItemsFor(browseDefinitions[1].id, mockAuthorName).subscribe()); + scheduler.flush(); + + expect(requestService.configure).toHaveBeenCalledWith(expected); + }); + + it('should call RemoteDataBuildService to create the RemoteData Observable', () => { + service.getBrowseItemsFor(browseDefinitions[1].id, mockAuthorName); + + expect(rdbService.toRemoteDataObservable).toHaveBeenCalled(); + + }); + + }); + + describe('when getBrowseEntriesFor is called with an invalid browse definition id', () => { it('should throw an Error', () => { const definitionID = 'invalidID'; @@ -184,6 +205,16 @@ describe('BrowseService', () => { expect(service.getBrowseEntriesFor(definitionID)).toBeObservable(expected); }); }); + + describe('when getBrowseItemsFor is called with an invalid browse definition id', () => { + it('should throw an Error', () => { + + const definitionID = 'invalidID'; + const expected = cold('--#-', undefined, new Error(`No metadata browse definition could be found for id '${definitionID}'`)) + + expect(service.getBrowseItemsFor(definitionID, mockAuthorName)).toBeObservable(expected); + }); + }); }); describe('getBrowseURLFor', () => { diff --git a/src/app/core/browse/browse.service.ts b/src/app/core/browse/browse.service.ts index 2e4a0a3508..003f92698c 100644 --- a/src/app/core/browse/browse.service.ts +++ b/src/app/core/browse/browse.service.ts @@ -133,6 +133,15 @@ export class BrowseService { return this.rdb.toRemoteDataObservable(requestEntry$, responseCache$, payload$); } + /** + * Get all items linked to a certain metadata value + * @param {string} definitionID definition ID to define the metadata-field (e.g. author) + * @param {string} filterValue metadata value to filter by (e.g. author's name) + * @param options Options to narrow down your search: + * { pagination: PaginationComponentOptions, + * sort: SortOptions } + * @returns {Observable>>} + */ getBrowseItemsFor(definitionID: string, filterValue: string, options: { pagination?: PaginationComponentOptions; sort?: SortOptions; diff --git a/src/app/core/data/item-data.service.spec.ts b/src/app/core/data/item-data.service.spec.ts index 718fbde2f6..4cf126157a 100644 --- a/src/app/core/data/item-data.service.spec.ts +++ b/src/app/core/data/item-data.service.spec.ts @@ -21,19 +21,17 @@ describe('ItemDataService', () => { const halEndpointService = {} as HALEndpointService; const scopeID = '4af28e99-6a9c-4036-a199-e1b587046d39'; - const startsWith = 'a'; const options = Object.assign(new FindAllOptions(), { scopeID: scopeID, sort: { field: '', direction: undefined - }, - startsWith: startsWith + } }); const browsesEndpoint = 'https://rest.api/discover/browses'; const itemBrowseEndpoint = `${browsesEndpoint}/author/items`; - const scopedEndpoint = `${itemBrowseEndpoint}?scope=${scopeID}&startsWith=${startsWith}`; + const scopedEndpoint = `${itemBrowseEndpoint}?scope=${scopeID}`; const serviceEndpoint = `https://rest.api/core/items`; const browseError = new Error('getBrowseURL failed'); diff --git a/src/app/core/data/item-data.service.ts b/src/app/core/data/item-data.service.ts index eb0896efdd..e86003f308 100644 --- a/src/app/core/data/item-data.service.ts +++ b/src/app/core/data/item-data.service.ts @@ -38,7 +38,7 @@ export class ItemDataService extends DataService { } return this.bs.getBrowseURLFor(field, this.linkPath) .filter((href: string) => isNotEmpty(href)) - .map((href: string) => new URLCombiner(href, `?scope=${options.scopeID}` + (options.startsWith ? `&startsWith=${options.startsWith}` : '')).toString()) + .map((href: string) => new URLCombiner(href, `?scope=${options.scopeID}`).toString()) .distinctUntilChanged(); } diff --git a/src/app/core/shared/operators.ts b/src/app/core/shared/operators.ts index 9009473765..1efc7885c8 100644 --- a/src/app/core/shared/operators.ts +++ b/src/app/core/shared/operators.ts @@ -47,6 +47,11 @@ export const getRemoteDataPayload = () => (source: Observable>): Observable => source.pipe(map((remoteData: RemoteData) => remoteData.payload)); +/** + * Get the browse links from a definition by ID given an array of all definitions + * @param {string} definitionID + * @returns {(source: Observable>) => Observable} + */ export const getBrowseDefinitionLinks = (definitionID: string) => (source: Observable>): Observable => source.pipe( diff --git a/src/app/shared/browse-by/browse-by.component.ts b/src/app/shared/browse-by/browse-by.component.ts index 196134224c..062b41a440 100644 --- a/src/app/shared/browse-by/browse-by.component.ts +++ b/src/app/shared/browse-by/browse-by.component.ts @@ -17,6 +17,9 @@ import { ListableObject } from '../object-collection/shared/listable-object.mode fadeInOut ] }) +/** + * Component to display a browse-by page for any ListableObject + */ export class BrowseByComponent { @Input() title: string; @Input() objects$: Observable>>; diff --git a/src/app/shared/object-list/metadata-list-element/metadata-list-element.component.html b/src/app/shared/object-list/metadata-list-element/metadata-list-element.component.html deleted file mode 100644 index c05c4c10c9..0000000000 --- a/src/app/shared/object-list/metadata-list-element/metadata-list-element.component.html +++ /dev/null @@ -1,3 +0,0 @@ - - {{object.value}} - diff --git a/src/app/shared/object-list/metadata-list-element/metadata-list-element.component.scss b/src/app/shared/object-list/metadata-list-element/metadata-list-element.component.scss deleted file mode 100644 index 45a533cd01..0000000000 --- a/src/app/shared/object-list/metadata-list-element/metadata-list-element.component.scss +++ /dev/null @@ -1 +0,0 @@ -@import '../../../../styles/variables'; diff --git a/src/app/shared/object-list/metadata-list-element/metadata-list-element.component.spec.ts b/src/app/shared/object-list/metadata-list-element/metadata-list-element.component.spec.ts deleted file mode 100644 index 8098a6a8c9..0000000000 --- a/src/app/shared/object-list/metadata-list-element/metadata-list-element.component.spec.ts +++ /dev/null @@ -1,48 +0,0 @@ -import { MetadataListElementComponent } from './metadata-list-element.component'; -import { async, ComponentFixture, TestBed } from '@angular/core/testing'; -import { ChangeDetectionStrategy, NO_ERRORS_SCHEMA } from '@angular/core'; -import { By } from '@angular/platform-browser'; -import { TruncatePipe } from '../../utils/truncate.pipe'; -import { Item } from '../../../core/shared/item.model'; -import { Observable } from 'rxjs/Observable'; -import { Metadatum } from '../../../core/shared/metadatum.model'; - -let metadataListElementComponent: MetadataListElementComponent; -let fixture: ComponentFixture; - -const mockValue: Metadatum = Object.assign(new Metadatum(), { - key: 'dc.contributor.author', - value: 'De Langhe Kristof' -}); - -describe('MetadataListElementComponent', () => { - beforeEach(async(() => { - TestBed.configureTestingModule({ - declarations: [ MetadataListElementComponent , TruncatePipe], - providers: [ - { provide: 'objectElementProvider', useValue: {mockValue}} - ], - - schemas: [ NO_ERRORS_SCHEMA ] - }).overrideComponent(MetadataListElementComponent, { - set: { changeDetection: ChangeDetectionStrategy.Default } - }).compileComponents(); - })); - - beforeEach(async(() => { - fixture = TestBed.createComponent(MetadataListElementComponent); - metadataListElementComponent = fixture.componentInstance; - })); - - describe('When the metadatum is loaded', () => { - beforeEach(() => { - metadataListElementComponent.object = mockValue; - fixture.detectChanges(); - }); - - it('should show the value as a link', () => { - const metadatumLink = fixture.debugElement.query(By.css('a.lead')); - expect(metadatumLink.nativeElement.textContent.trim()).toBe(mockValue.value); - }); - }); -}); diff --git a/src/app/shared/object-list/metadata-list-element/metadata-list-element.component.ts b/src/app/shared/object-list/metadata-list-element/metadata-list-element.component.ts deleted file mode 100644 index 12e140c7bf..0000000000 --- a/src/app/shared/object-list/metadata-list-element/metadata-list-element.component.ts +++ /dev/null @@ -1,15 +0,0 @@ -import { Component, Input, Inject } from '@angular/core'; - -import { AbstractListableElementComponent } from '../../object-collection/shared/object-collection-element/abstract-listable-element.component'; -import { renderElementsFor } from '../../object-collection/shared/dso-element-decorator'; -import { ViewMode } from '../../../+search-page/search-options.model'; -import { Metadatum } from '../../../core/shared/metadatum.model'; - -@Component({ - selector: 'ds-metadata-list-element', - styleUrls: ['./metadata-list-element.component.scss'], - templateUrl: './metadata-list-element.component.html' -}) - -@renderElementsFor(Metadatum, ViewMode.List) -export class MetadataListElementComponent extends AbstractListableElementComponent {} diff --git a/src/app/shared/shared.module.ts b/src/app/shared/shared.module.ts index 223eab4c69..7ae6163bf1 100644 --- a/src/app/shared/shared.module.ts +++ b/src/app/shared/shared.module.ts @@ -72,7 +72,6 @@ import { NumberPickerComponent } from './number-picker/number-picker.component'; import { DsDatePickerComponent } from './form/builder/ds-dynamic-form-ui/models/date-picker/date-picker.component'; import { DsDynamicLookupComponent } from './form/builder/ds-dynamic-form-ui/models/lookup/dynamic-lookup.component'; import { MockAdminGuard } from './mocks/mock-admin-guard.service'; -import { MetadataListElementComponent } from './object-list/metadata-list-element/metadata-list-element.component'; import { BrowseByModule } from '../+browse-by/browse-by.module'; import { BrowseByComponent } from './browse-by/browse-by.component'; import { BrowseEntryListElementComponent } from './object-list/browse-entry-list-element/browse-entry-list-element.component'; @@ -149,7 +148,6 @@ const COMPONENTS = [ const ENTRY_COMPONENTS = [ // put shared entry components (components that are created dynamically) here ItemListElementComponent, - MetadataListElementComponent, CollectionListElementComponent, CommunityListElementComponent, SearchResultListElementComponent, From 375742a000568ee4d6a928ecb8abf512801bcaf7 Mon Sep 17 00:00:00 2001 From: Kristof De Langhe Date: Fri, 10 Aug 2018 13:34:44 +0200 Subject: [PATCH 03/48] count badges next to browse-by-metadata values --- .../browse-entry-list-element.component.html | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/app/shared/object-list/browse-entry-list-element/browse-entry-list-element.component.html b/src/app/shared/object-list/browse-entry-list-element/browse-entry-list-element.component.html index 9eedb70eab..198e79b453 100644 --- a/src/app/shared/object-list/browse-entry-list-element/browse-entry-list-element.component.html +++ b/src/app/shared/object-list/browse-entry-list-element/browse-entry-list-element.component.html @@ -1,3 +1,7 @@ - - {{object.value}} - +
+ + {{object.value}} + +   + {{object.count}} +
From 8548aef2b035a04a3f25175d8b2f0cca6302b5cb Mon Sep 17 00:00:00 2001 From: lotte Date: Thu, 16 Aug 2018 15:39:31 +0200 Subject: [PATCH 04/48] test fixes for browse pages --- src/app/core/data/data.service.spec.ts | 30 +++++++++----------------- 1 file changed, 10 insertions(+), 20 deletions(-) diff --git a/src/app/core/data/data.service.spec.ts b/src/app/core/data/data.service.spec.ts index 8377afe92e..7af06ff62a 100644 --- a/src/app/core/data/data.service.spec.ts +++ b/src/app/core/data/data.service.spec.ts @@ -10,7 +10,7 @@ import { Observable } from 'rxjs/Observable'; import { FindAllOptions } from './request.models'; import { SortOptions, SortDirection } from '../cache/models/sort-options.model'; -const LINK_NAME = 'test' +const endpoint = 'https://rest.api/core'; // tslint:disable:max-classes-per-file class NormalizedTestObject extends NormalizedObject { @@ -28,10 +28,9 @@ class TestService extends DataService { super(); } - public getScopedEndpoint(scope: string): Observable { - throw new Error('getScopedEndpoint is abstract in DataService'); + public getBrowseEndpoint(options: FindAllOptions): Observable { + return Observable.of(endpoint); } - } describe('DataService', () => { @@ -42,7 +41,6 @@ describe('DataService', () => { const halService = {} as HALEndpointService; const rdbService = {} as RemoteDataBuildService; const store = {} as Store; - const endpoint = 'https://rest.api/core'; function initTestService(): TestService { return new TestService( @@ -50,7 +48,7 @@ describe('DataService', () => { requestService, rdbService, store, - LINK_NAME, + endpoint, halService ); } @@ -62,25 +60,17 @@ describe('DataService', () => { it('should return an observable with the endpoint', () => { options = {}; - (service as any).getFindAllHref(endpoint).subscribe((value) => { + (service as any).getFindAllHref(options).subscribe((value) => { expect(value).toBe(endpoint); } ); }); - // getScopedEndpoint is not implemented in abstract DataService - it('should throw error if scopeID provided in options', () => { - options = { scopeID: 'somevalue' }; - - expect(() => { (service as any).getFindAllHref(endpoint, options) }) - .toThrowError('getScopedEndpoint is abstract in DataService'); - }); - it('should include page in href if currentPage provided in options', () => { options = { currentPage: 2 }; const expected = `${endpoint}?page=${options.currentPage - 1}`; - (service as any).getFindAllHref(endpoint, options).subscribe((value) => { + (service as any).getFindAllHref(options).subscribe((value) => { expect(value).toBe(expected); }); }); @@ -89,7 +79,7 @@ describe('DataService', () => { options = { elementsPerPage: 5 }; const expected = `${endpoint}?size=${options.elementsPerPage}`; - (service as any).getFindAllHref(endpoint, options).subscribe((value) => { + (service as any).getFindAllHref(options).subscribe((value) => { expect(value).toBe(expected); }); }); @@ -99,7 +89,7 @@ describe('DataService', () => { options = { sort: sortOptions}; const expected = `${endpoint}?sort=${sortOptions.field},${sortOptions.direction}`; - (service as any).getFindAllHref(endpoint, options).subscribe((value) => { + (service as any).getFindAllHref(options).subscribe((value) => { expect(value).toBe(expected); }); }); @@ -108,7 +98,7 @@ describe('DataService', () => { options = { startsWith: 'ab' }; const expected = `${endpoint}?startsWith=${options.startsWith}`; - (service as any).getFindAllHref(endpoint, options).subscribe((value) => { + (service as any).getFindAllHref(options).subscribe((value) => { expect(value).toBe(expected); }); }); @@ -124,7 +114,7 @@ describe('DataService', () => { const expected = `${endpoint}?page=${options.currentPage - 1}&size=${options.elementsPerPage}` + `&sort=${sortOptions.field},${sortOptions.direction}&startsWith=${options.startsWith}`; - (service as any).getFindAllHref(endpoint, options).subscribe((value) => { + (service as any).getFindAllHref(options).subscribe((value) => { expect(value).toBe(expected); }); }) From 2cbe6a6d91d2ff2fbb2da2543174426e8a120f0a Mon Sep 17 00:00:00 2001 From: lotte Date: Fri, 24 Aug 2018 13:26:43 +0200 Subject: [PATCH 05/48] upgrade to angular6 --- package.json | 110 +- spec-bundle.js | 2 +- .../bitstream-formats.component.spec.ts | 2 +- .../bitstream-formats.component.ts | 2 +- .../metadata-registry.component.spec.ts | 2 +- .../metadata-registry.component.ts | 2 +- .../metadata-schema.component.spec.ts | 2 +- .../metadata-schema.component.ts | 2 +- .../collection-page.component.ts | 12 +- .../collection-page.resolver.ts | 2 +- .../community-page.component.ts | 7 +- .../community-page.resolver.ts | 2 +- ...nity-page-sub-collection-list.component.ts | 2 +- .../top-level-community-list.component.ts | 2 +- .../collections/collections.component.spec.ts | 2 +- .../collections/collections.component.ts | 2 +- .../full-file-section.component.ts | 2 +- .../full/full-item-page.component.ts | 2 +- src/app/+item-page/item-page.resolver.ts | 2 +- .../file-section/file-section.component.ts | 2 +- .../+item-page/simple/item-page.component.ts | 2 +- .../+login-page/login-page.component.spec.ts | 2 +- .../search-facet-filter.component.spec.ts | 2 +- .../search-facet-filter.component.ts | 5 +- .../search-filter.component.spec.ts | 2 +- .../search-filter/search-filter.component.ts | 2 +- .../search-filter.service.spec.ts | 2 +- .../search-filter/search-filter.service.ts | 2 +- .../search-range-filter.component.spec.ts | 2 +- .../search-range-filter.component.ts | 3 +- .../search-text-filter.component.ts | 2 +- .../search-filters.component.spec.ts | 2 +- .../search-filters.component.ts | 2 +- .../search-labels.component.spec.ts | 2 +- .../search-labels/search-labels.component.ts | 2 +- .../search-page.component.spec.ts | 2 +- src/app/+search-page/search-page.component.ts | 4 +- .../search-configuration.service.spec.ts | 2 +- .../search-configuration.service.ts | 4 +- .../search-service/search.service.spec.ts | 2 +- .../search-service/search.service.ts | 2 +- .../search-settings.component.spec.ts | 2 +- .../search-settings.component.ts | 2 +- .../search-sidebar.effects.spec.ts | 2 +- .../search-sidebar.service.spec.ts | 2 +- .../search-sidebar/search-sidebar.service.ts | 2 +- src/app/app.module.ts | 4 - src/app/core/auth/auth-request.service.ts | 4 +- src/app/core/auth/auth.effects.spec.ts | 2 +- src/app/core/auth/auth.effects.ts | 2 +- src/app/core/auth/auth.interceptor.spec.ts | 2 +- src/app/core/auth/auth.interceptor.ts | 9 +- src/app/core/auth/auth.service.spec.ts | 2 +- src/app/core/auth/auth.service.ts | 2 +- src/app/core/auth/authenticated.guard.ts | 2 +- src/app/core/auth/server-auth.service.ts | 2 +- src/app/core/browse/browse.service.spec.ts | 2 +- src/app/core/browse/browse.service.ts | 2 +- .../builders/remote-data-build.service.ts | 2 +- .../core/cache/object-cache.effects.spec.ts | 2 +- .../core/cache/object-cache.service.spec.ts | 2 +- src/app/core/cache/object-cache.service.ts | 2 +- .../core/cache/response-cache.effects.spec.ts | 2 +- .../core/cache/response-cache.service.spec.ts | 2 +- src/app/core/cache/response-cache.service.ts | 2 +- src/app/core/config/config.service.spec.ts | 2 +- src/app/core/config/config.service.ts | 5 +- src/app/core/data/comcol-data.service.spec.ts | 2 +- src/app/core/data/comcol-data.service.ts | 5 +- src/app/core/data/community-data.service.ts | 2 +- src/app/core/data/data.service.spec.ts | 2 +- src/app/core/data/data.service.ts | 2 +- .../core/data/dspace-object-data.service.ts | 2 +- src/app/core/data/item-data.service.spec.ts | 2 +- src/app/core/data/item-data.service.ts | 2 +- src/app/core/data/request.service.spec.ts | 2 +- src/app/core/data/request.service.ts | 2 +- .../dspace-rest-v2/dspace-rest-v2.service.ts | 7 +- .../integration/integration.service.spec.ts | 2 +- .../core/integration/integration.service.ts | 5 +- .../core/metadata/metadata.service.spec.ts | 2 +- src/app/core/metadata/metadata.service.ts | 7 +- .../core/registry/registry.service.spec.ts | 2 +- src/app/core/registry/registry.service.ts | 2 +- src/app/core/shared/bitstream.model.ts | 2 +- src/app/core/shared/bundle.model.ts | 2 +- src/app/core/shared/collection.model.ts | 2 +- src/app/core/shared/community.model.ts | 2 +- src/app/core/shared/dspace-object.model.ts | 2 +- src/app/core/shared/hal-endpoint.service.ts | 2 +- src/app/core/shared/item.model.spec.ts | 2 +- src/app/core/shared/item.model.ts | 2 +- src/app/core/shared/operators.ts | 2 +- src/app/header/header.component.spec.ts | 2 +- src/app/header/header.component.ts | 2 +- src/app/header/header.effects.spec.ts | 2 +- src/app/shared/animations/slide.ts | 2 +- .../auth-nav-menu/auth-nav-menu.component.ts | 2 +- src/app/shared/chips/models/chips.model.ts | 2 +- src/app/shared/empty.util.ts | 2 +- src/app/shared/error/error.component.ts | 2 +- .../models/date-picker/date-picker.model.ts | 2 +- .../models/ds-dynamic-input.model.ts | 2 +- .../models/ds-dynamic-qualdrop.model.ts | 2 +- .../dynamic-group.component.spec.ts | 2 +- .../dynamic-group/dynamic-group.components.ts | 3 +- .../list/dynamic-list-checkbox-group.model.ts | 2 +- .../models/lookup/dynamic-lookup.component.ts | 2 +- .../models/tag/dynamic-tag.component.spec.ts | 2 +- .../models/tag/dynamic-tag.component.ts | 2 +- .../dynamic-typeahead.component.spec.ts | 2 +- .../typeahead/dynamic-typeahead.component.ts | 2 +- src/app/shared/form/form.component.ts | 3 +- src/app/shared/form/form.service.ts | 2 +- src/app/shared/host-window.service.spec.ts | 2 +- src/app/shared/host-window.service.ts | 2 +- .../input-suggestions.component.ts | 2 +- src/app/shared/loading/loading.component.ts | 2 +- src/app/shared/log-in/log-in.component.ts | 6 +- src/app/shared/log-out/log-out.component.ts | 2 +- src/app/shared/mocks/mock-active-router.ts | 2 +- .../shared/mocks/mock-host-window-service.ts | 2 +- src/app/shared/mocks/mock-item.ts | 2 +- .../mocks/mock-remote-data-build.service.ts | 2 +- src/app/shared/mocks/mock-request.service.ts | 2 +- .../mocks/mock-response-cache.service.ts | 2 +- src/app/shared/mocks/mock-store.ts | 2 +- src/app/shared/mocks/mock-translate-loader.ts | 2 +- .../models/notification.model.ts | 2 +- .../notification.component.spec.ts | 2 +- .../notification/notification.component.ts | 2 +- .../notifications-board.component.ts | 2 +- .../notifications.service.spec.ts | 2 +- .../notifications/notifications.service.ts | 2 +- .../object-collection.component.spec.ts | 2 +- .../object-collection.component.ts | 2 +- .../item-grid-element.component.spec.ts | 2 +- .../object-grid/object-grid.component.ts | 3 +- ...arch-result-grid-element.component.spec.ts | 2 +- ...arch-result-grid-element.component.spec.ts | 2 +- ...arch-result-grid-element.component.spec.ts | 2 +- .../search-result-grid-element.component.ts | 2 +- .../wrapper-grid-element.component.spec.ts | 2 +- .../item-list-element.component.spec.ts | 2 +- ...arch-result-list-element.component.spec.ts | 2 +- ...arch-result-list-element.component.spec.ts | 2 +- ...arch-result-list-element.component.spec.ts | 2 +- .../search-result-list-element.component.ts | 2 +- .../pagination/pagination.component.spec.ts | 2 +- .../shared/pagination/pagination.component.ts | 6 +- src/app/shared/services/api.service.ts | 7 +- src/app/shared/services/cookie.service.ts | 3 +- src/app/shared/services/route.service.spec.ts | 2 +- src/app/shared/services/route.service.ts | 2 +- src/app/shared/testing/active-router-stub.ts | 2 +- .../testing/auth-request-service-stub.ts | 2 +- src/app/shared/testing/auth-service-stub.ts | 2 +- .../shared/testing/authority-service-stub.ts | 2 +- .../testing/hal-endpoint-service-stub.ts | 2 +- .../testing/host-window-service-stub.ts | 2 +- src/app/shared/testing/mock-store.ts | 3 +- .../shared/testing/mock-translate-loader.ts | 2 +- .../testing/notifications-service-stub.ts | 2 +- src/app/shared/testing/search-service-stub.ts | 3 +- .../truncatable-part.component.spec.ts | 2 +- .../truncatable/truncatable.component.spec.ts | 2 +- .../truncatable/truncatable.service.spec.ts | 2 +- .../shared/truncatable/truncatable.service.ts | 2 +- src/app/shared/uploader/uploader.component.ts | 2 +- src/app/shared/utils/debounce.directive.ts | 8 +- .../view-mode-switch.component.ts | 2 +- src/app/store.effects.ts | 4 +- src/modules/app/server-app.module.ts | 4 +- src/modules/translate-universal-loader.ts | 2 +- src/server.ts | 2 +- tslint.json | 9 +- webpack.config.js | 5 +- webpack/webpack.common.js | 1 + webpack/webpack.prod.js | 100 +- yarn.lock | 4782 +++++++++-------- 180 files changed, 2987 insertions(+), 2450 deletions(-) diff --git a/package.json b/package.json index 0936b27ea4..47bc7a419c 100644 --- a/package.json +++ b/package.json @@ -23,9 +23,9 @@ "prebuild": "yarn run clean:dist", "prebuild:aot": "yarn run prebuild", "prebuild:prod": "yarn run prebuild", - "build": "webpack --progress", - "build:aot": "webpack --env.aot --env.server && webpack --env.aot --env.client", - "build:prod": "webpack --env.aot --env.server -p && webpack --env.aot --env.client -p", + "build": "webpack --progress --mode development", + "build:aot": "webpack --env.aot --env.server --mode development && webpack --env.aot --env.client --mode development", + "build:prod": "webpack --env.aot --env.server --mode production && webpack --env.aot --env.client --mode production", "postbuild:prod": "yarn run rollup", "rollup": "rollup -c rollup.config.js", "prestart": "yarn run build:prod", @@ -40,15 +40,9 @@ "server": "node dist/server.js", "server:watch": "nodemon dist/server.js", "server:watch:debug": "nodemon --debug dist/server.js", - "webpack:watch": "webpack -w", - "webpack:watch:aot": "webpack -w --env.aot --env.server && webpack -w --env.aot --env.client", - "webpack:watch:prod": "webpack -w --env.aot --env.server -p && webpack -w --env.aot --env.client -p", + "webpack:watch": "webpack -w --mode development", "watch": "yarn run build && npm-run-all -p webpack:watch server:watch", - "watch:aot": "yarn run build:aot && npm-run-all -p webpack:watch:aot server:watch", - "watch:prod": "yarn run build:prod && npm-run-all -p webpack:watch:prod server:watch", "watch:debug": "yarn run build && npm-run-all -p webpack:watch server:watch:debug", - "watch:debug:aot": "yarn run build:aot && npm-run-all -p webpack:watch:aot server:watch:debug", - "watch:debug:prod": "yarn run build:prod && npm-run-all -p webpack:watch:prod server:watch:debug", "predebug": "yarn run build", "predebug:server": "yarn run build", "debug": "node --debug-brk dist/server.js", @@ -69,31 +63,30 @@ "coverage": "http-server -c-1 -o -p 9875 ./coverage" }, "dependencies": { - "@angular/animations": "^5.2.5", - "@angular/common": "^5.2.5", - "@angular/core": "^5.2.5", - "@angular/forms": "^5.2.5", - "@angular/http": "^5.2.5", - "@angular/platform-browser": "^5.2.5", - "@angular/platform-browser-dynamic": "^5.2.5", - "@angular/platform-server": "^5.2.5", - "@angular/router": "^5.2.5", + "@angular/animations": "^6.1.4", + "@angular/common": "^6.1.4", + "@angular/core": "^6.1.4", + "@angular/forms": "^6.1.4", + "@angular/http": "^6.1.4", + "@angular/platform-browser": "^6.1.4", + "@angular/platform-browser-dynamic": "^6.1.4", + "@angular/platform-server": "^6.1.4", + "@angular/router": "^6.1.4", "@angularclass/bootloader": "1.0.1", - "@ng-bootstrap/ng-bootstrap": "^1.0.0", - "@ng-dynamic-forms/core": "5.4.7", - "@ng-dynamic-forms/ui-ng-bootstrap": "5.4.7", - "@ngrx/effects": "^5.1.0", - "@ngrx/router-store": "^5.0.1", - "@ngrx/store": "^5.1.0", - "@nguniversal/express-engine": "5.0.0", - "@ngx-translate/core": "9.1.1", - "@ngx-translate/http-loader": "2.0.1", - "@nicky-lenaers/ngx-scroll-to": "^0.6.0", - "angular-idle-preload": "2.0.4", - "angular2-moment": "^1.9.0", + "@ng-bootstrap/ng-bootstrap": "^2.0.0", + "@ng-dynamic-forms/core": "6.0.9", + "@ng-dynamic-forms/ui-ng-bootstrap": "6.0.9", + "@ngrx/effects": "^6.1.0", + "@ngrx/router-store": "^6.1.0", + "@ngrx/store": "^6.1.0", + "@nguniversal/express-engine": "6.1.0", + "@ngx-translate/core": "10.0.2", + "@ngx-translate/http-loader": "3.0.1", + "@nicky-lenaers/ngx-scroll-to": "^1.0.0", + "angular-idle-preload": "3.0.0", "angular-sortablejs": "^2.5.0", - "angular2-text-mask": "8.0.4", - "angulartics2": "^5.2.0", + "angular2-text-mask": "9.0.0", + "angulartics2": "^6.2.0", "body-parser": "1.18.2", "bootstrap": "4.1.1", "cerialize": "0.1.18", @@ -112,26 +105,27 @@ "methods": "1.1.2", "moment": "^2.22.1", "morgan": "1.9.0", - "ng2-nouislider": "^1.7.11", "ng2-file-upload": "1.2.1", - "ngx-infinite-scroll": "0.8.2", + "ng2-nouislider": "^1.7.11", + "ngx-bootstrap": "^3.0.1", + "ngx-infinite-scroll": "6.0.1", "ngx-pagination": "3.0.3", "nouislider": "^11.0.0", "pem": "1.12.3", "reflect-metadata": "0.1.12", - "rxjs": "5.5.6", + "rxjs": "^6.2.2", "sortablejs": "1.7.0", "text-mask-core": "5.0.1", "ts-md5": "^1.2.4", "uuid": "^3.2.1", "webfontloader": "1.6.28", - "zone.js": "0.8.20" + "zone.js": "^0.8.26" }, "devDependencies": { - "@angular/compiler": "^5.2.5", - "@angular/compiler-cli": "^5.2.5", - "@ngrx/store-devtools": "^5.1.0", - "@ngtools/webpack": "^1.10.0", + "@angular/compiler": "^6.1.4", + "@angular/compiler-cli": "^6.1.4", + "@ngrx/store-devtools": "^6.1.0", + "@ngtools/webpack": "^6.1.5", "@types/acorn": "^4.0.3", "@types/cookie-parser": "1.4.1", "@types/deep-freeze": "0.1.1", @@ -140,6 +134,7 @@ "@types/hammerjs": "2.0.35", "@types/jasmine": "^2.8.6", "@types/js-cookie": "2.1.0", + "@types/lodash": "^4.14.110", "@types/memory-cache": "0.2.0", "@types/mime": "2.0.0", "@types/node": "^9.4.6", @@ -152,18 +147,18 @@ "autoprefixer": "^8.0.0", "awesome-typescript-loader": "3.4.1", "caniuse-lite": "^1.0.30000697", - "codelyzer": "^4.1.0", + "codelyzer": "^4.4.4", "compression-webpack-plugin": "^1.1.6", "copy-webpack-plugin": "^4.4.1", "coveralls": "3.0.0", "css-loader": "0.28.9", "deep-freeze": "0.0.1", "exports-loader": "^0.7.0", - "html-webpack-plugin": "2.30.1", + "html-webpack-plugin": "3.2.0", "imports-loader": "0.7.1", - "istanbul-instrumenter-loader": "3.0.0", - "jasmine-core": "^2.99.1", - "jasmine-marbles": "0.2.0", + "istanbul-instrumenter-loader": "3.0.1", + "jasmine-core": "^3.2.1", + "jasmine-marbles": "0.3.0", "jasmine-spec-reporter": "4.2.1", "json-loader": "0.5.7", "karma": "2.0.0", @@ -178,8 +173,8 @@ "karma-remap-istanbul": "0.6.0", "karma-sourcemap-loader": "0.3.7", "karma-webdriver-launcher": "1.0.5", - "karma-webpack": "2.0.9", - "ngrx-store-freeze": "^0.2.1", + "karma-webpack": "3.0.0", + "ngrx-store-freeze": "^0.2.4", "node-sass": "^4.7.2", "nodemon": "^1.15.0", "npm-run-all": "4.1.2", @@ -201,21 +196,22 @@ "rollup-plugin-node-resolve": "^3.0.3", "rollup-plugin-uglify": "3.0.0", "sass-loader": "6.0.6", - "script-ext-html-webpack-plugin": "1.8.8", + "script-ext-html-webpack-plugin": "2.0.1", "source-map": "0.6.1", "source-map-loader": "0.2.3", - "string-replace-loader": "1.3.0", + "string-replace-loader": "2.1.1", "to-string-loader": "1.1.5", "ts-helpers": "1.1.2", "ts-node": "4.1.0", "tslint": "5.9.1", "typedoc": "^0.9.0", - "typescript": "2.6.2", - "webpack": "^3.11.0", - "webpack-bundle-analyzer": "^2.10.0", - "webpack-dev-middleware": "^2.0.5", - "webpack-dev-server": "2.11.1", - "webpack-merge": "4.1.1", - "webpack-node-externals": "1.6.0" + "typescript": "^2.9.1", + "webpack": "^4.17.1", + "webpack-bundle-analyzer": "^2.13.1", + "webpack-command": "^0.4.1", + "webpack-dev-middleware": "3.2.0", + "webpack-dev-server": "^3.1.5", + "webpack-merge": "4.1.4", + "webpack-node-externals": "1.7.2" } } diff --git a/spec-bundle.js b/spec-bundle.js index b9df9bec5e..aa46c35d14 100644 --- a/spec-bundle.js +++ b/spec-bundle.js @@ -28,7 +28,7 @@ require('zone.js/dist/async-test'); require('zone.js/dist/fake-async-test'); // RxJS -require('rxjs/Rx'); +require('rxjs'); var testing = require('@angular/core/testing'); var browser = require('@angular/platform-browser-dynamic/testing'); diff --git a/src/app/+admin/admin-registries/bitstream-formats/bitstream-formats.component.spec.ts b/src/app/+admin/admin-registries/bitstream-formats/bitstream-formats.component.spec.ts index f720c336e5..681ad65a83 100644 --- a/src/app/+admin/admin-registries/bitstream-formats/bitstream-formats.component.spec.ts +++ b/src/app/+admin/admin-registries/bitstream-formats/bitstream-formats.component.spec.ts @@ -1,7 +1,7 @@ import { BitstreamFormatsComponent } from './bitstream-formats.component'; import { async, ComponentFixture, TestBed } from '@angular/core/testing'; import { RegistryService } from '../../../core/registry/registry.service'; -import { Observable } from 'rxjs/Observable'; +import { Observable } from 'rxjs'; import { RemoteData } from '../../../core/data/remote-data'; import { PaginatedList } from '../../../core/data/paginated-list'; import { CommonModule } from '@angular/common'; diff --git a/src/app/+admin/admin-registries/bitstream-formats/bitstream-formats.component.ts b/src/app/+admin/admin-registries/bitstream-formats/bitstream-formats.component.ts index d6c84ac858..6ba4e8146b 100644 --- a/src/app/+admin/admin-registries/bitstream-formats/bitstream-formats.component.ts +++ b/src/app/+admin/admin-registries/bitstream-formats/bitstream-formats.component.ts @@ -1,6 +1,6 @@ import { Component } from '@angular/core'; import { RegistryService } from '../../../core/registry/registry.service'; -import { Observable } from 'rxjs/Observable'; +import { Observable } from 'rxjs'; import { RemoteData } from '../../../core/data/remote-data'; import { PaginatedList } from '../../../core/data/paginated-list'; import { BitstreamFormat } from '../../../core/registry/mock-bitstream-format.model'; diff --git a/src/app/+admin/admin-registries/metadata-registry/metadata-registry.component.spec.ts b/src/app/+admin/admin-registries/metadata-registry/metadata-registry.component.spec.ts index e3b2e1f2c1..0184bf9245 100644 --- a/src/app/+admin/admin-registries/metadata-registry/metadata-registry.component.spec.ts +++ b/src/app/+admin/admin-registries/metadata-registry/metadata-registry.component.spec.ts @@ -1,6 +1,6 @@ import { MetadataRegistryComponent } from './metadata-registry.component'; import { async, ComponentFixture, TestBed } from '@angular/core/testing'; -import { Observable } from 'rxjs/Observable'; +import { Observable } from 'rxjs'; import { RemoteData } from '../../../core/data/remote-data'; import { PaginatedList } from '../../../core/data/paginated-list'; import { TranslateModule } from '@ngx-translate/core'; diff --git a/src/app/+admin/admin-registries/metadata-registry/metadata-registry.component.ts b/src/app/+admin/admin-registries/metadata-registry/metadata-registry.component.ts index 15dc6b0d80..c2f70eaa9e 100644 --- a/src/app/+admin/admin-registries/metadata-registry/metadata-registry.component.ts +++ b/src/app/+admin/admin-registries/metadata-registry/metadata-registry.component.ts @@ -1,6 +1,6 @@ import { Component } from '@angular/core'; import { RegistryService } from '../../../core/registry/registry.service'; -import { Observable } from 'rxjs/Observable'; +import { Observable } from 'rxjs'; import { RemoteData } from '../../../core/data/remote-data'; import { PaginatedList } from '../../../core/data/paginated-list'; import { MetadataSchema } from '../../../core/metadata/metadataschema.model'; diff --git a/src/app/+admin/admin-registries/metadata-schema/metadata-schema.component.spec.ts b/src/app/+admin/admin-registries/metadata-schema/metadata-schema.component.spec.ts index 7e6064ddff..9a56d9b5b9 100644 --- a/src/app/+admin/admin-registries/metadata-schema/metadata-schema.component.spec.ts +++ b/src/app/+admin/admin-registries/metadata-schema/metadata-schema.component.spec.ts @@ -1,6 +1,6 @@ import { MetadataSchemaComponent } from './metadata-schema.component'; import { async, ComponentFixture, TestBed } from '@angular/core/testing'; -import { Observable } from 'rxjs/Observable'; +import { Observable } from 'rxjs'; import { RemoteData } from '../../../core/data/remote-data'; import { PaginatedList } from '../../../core/data/paginated-list'; import { MetadataSchema } from '../../../core/metadata/metadataschema.model'; diff --git a/src/app/+admin/admin-registries/metadata-schema/metadata-schema.component.ts b/src/app/+admin/admin-registries/metadata-schema/metadata-schema.component.ts index 2f0bfdeddb..b2cc5129ce 100644 --- a/src/app/+admin/admin-registries/metadata-schema/metadata-schema.component.ts +++ b/src/app/+admin/admin-registries/metadata-schema/metadata-schema.component.ts @@ -1,7 +1,7 @@ import { Component, OnInit } from '@angular/core'; import { RegistryService } from '../../../core/registry/registry.service'; import { ActivatedRoute } from '@angular/router'; -import { Observable } from 'rxjs/Observable'; +import { Observable } from 'rxjs'; import { RemoteData } from '../../../core/data/remote-data'; import { PaginatedList } from '../../../core/data/paginated-list'; import { MetadataField } from '../../../core/metadata/metadatafield.model'; diff --git a/src/app/+collection-page/collection-page.component.ts b/src/app/+collection-page/collection-page.component.ts index 89567c4a54..127fd8ce98 100644 --- a/src/app/+collection-page/collection-page.component.ts +++ b/src/app/+collection-page/collection-page.component.ts @@ -1,8 +1,6 @@ import { ChangeDetectionStrategy, Component, OnDestroy, OnInit } from '@angular/core'; import { ActivatedRoute } from '@angular/router'; -import { Observable } from 'rxjs/Observable'; - -import { Subscription } from 'rxjs/Subscription'; +import { Observable , Subscription } from 'rxjs'; import { SortDirection, SortOptions } from '../core/cache/models/sort-options.model'; import { CollectionDataService } from '../core/data/collection-data.service'; import { PaginatedList } from '../core/data/paginated-list'; @@ -56,7 +54,9 @@ export class CollectionPageComponent implements OnInit, OnDestroy { } ngOnInit(): void { - this.collectionRD$ = this.route.data.map((data) => data.collection); + this.collectionRD$ = this.route.data.pipe( + map((data) => data.collection) + ); this.logoRD$ = this.collectionRD$.pipe( map((rd: RemoteData) => rd.payload), filter((collection: Collection) => hasValue(collection)), @@ -75,8 +75,8 @@ export class CollectionPageComponent implements OnInit, OnDestroy { pagination: pagination, sort: this.sortConfig }); - })); - + }) + ); } updatePage(searchOptions) { diff --git a/src/app/+collection-page/collection-page.resolver.ts b/src/app/+collection-page/collection-page.resolver.ts index 3204b8d5c3..82e614caa1 100644 --- a/src/app/+collection-page/collection-page.resolver.ts +++ b/src/app/+collection-page/collection-page.resolver.ts @@ -1,7 +1,7 @@ import { Injectable } from '@angular/core'; import { ActivatedRouteSnapshot, Resolve, RouterStateSnapshot } from '@angular/router'; import { Collection } from '../core/shared/collection.model'; -import { Observable } from 'rxjs/Observable'; +import { Observable } from 'rxjs'; import { CollectionDataService } from '../core/data/collection-data.service'; import { RemoteData } from '../core/data/remote-data'; import { getSucceededRemoteData } from '../core/shared/operators'; diff --git a/src/app/+community-page/community-page.component.ts b/src/app/+community-page/community-page.component.ts index 5fea9b01c9..69738733a8 100644 --- a/src/app/+community-page/community-page.component.ts +++ b/src/app/+community-page/community-page.component.ts @@ -1,7 +1,7 @@ import { ChangeDetectionStrategy, Component, OnDestroy, OnInit } from '@angular/core'; -import { ActivatedRoute, Params } from '@angular/router'; +import { ActivatedRoute } from '@angular/router'; -import { Subscription } from 'rxjs/Subscription'; +import { Subscription , Observable } from 'rxjs'; import { CommunityDataService } from '../core/data/community-data.service'; import { RemoteData } from '../core/data/remote-data'; import { Bitstream } from '../core/shared/bitstream.model'; @@ -12,7 +12,6 @@ import { MetadataService } from '../core/metadata/metadata.service'; import { fadeInOut } from '../shared/animations/fade'; import { hasValue } from '../shared/empty.util'; -import { Observable } from 'rxjs/Observable'; @Component({ selector: 'ds-community-page', @@ -35,7 +34,7 @@ export class CommunityPageComponent implements OnInit, OnDestroy { } ngOnInit(): void { - this.communityRD$ = this.route.data.map((data) => data.community); + this.communityRD$ = this.route.data.pipe((data) => data.community); this.logoRD$ = this.communityRD$ .map((rd: RemoteData) => rd.payload) .filter((community: Community) => hasValue(community)) diff --git a/src/app/+community-page/community-page.resolver.ts b/src/app/+community-page/community-page.resolver.ts index 1b92b19765..e18de17804 100644 --- a/src/app/+community-page/community-page.resolver.ts +++ b/src/app/+community-page/community-page.resolver.ts @@ -1,6 +1,6 @@ import { Injectable } from '@angular/core'; import { ActivatedRouteSnapshot, Resolve, RouterStateSnapshot } from '@angular/router'; -import { Observable } from 'rxjs/Observable'; +import { Observable } from 'rxjs'; import { RemoteData } from '../core/data/remote-data'; import { getSucceededRemoteData } from '../core/shared/operators'; import { Community } from '../core/shared/community.model'; diff --git a/src/app/+community-page/sub-collection-list/community-page-sub-collection-list.component.ts b/src/app/+community-page/sub-collection-list/community-page-sub-collection-list.component.ts index aed2b69a30..b8a5d60002 100644 --- a/src/app/+community-page/sub-collection-list/community-page-sub-collection-list.component.ts +++ b/src/app/+community-page/sub-collection-list/community-page-sub-collection-list.component.ts @@ -1,5 +1,5 @@ import { Component, Input, OnInit } from '@angular/core'; -import { Observable } from 'rxjs/Observable'; +import { Observable } from 'rxjs'; import { RemoteData } from '../../core/data/remote-data'; import { Collection } from '../../core/shared/collection.model'; diff --git a/src/app/+home-page/top-level-community-list/top-level-community-list.component.ts b/src/app/+home-page/top-level-community-list/top-level-community-list.component.ts index 1915a8ce64..8e8c83ce5b 100644 --- a/src/app/+home-page/top-level-community-list/top-level-community-list.component.ts +++ b/src/app/+home-page/top-level-community-list/top-level-community-list.component.ts @@ -1,5 +1,5 @@ import { ChangeDetectionStrategy, Component } from '@angular/core'; -import { Observable } from 'rxjs/Observable'; +import { Observable } from 'rxjs'; import { SortDirection, SortOptions } from '../../core/cache/models/sort-options.model'; import { CommunityDataService } from '../../core/data/community-data.service'; import { PaginatedList } from '../../core/data/paginated-list'; diff --git a/src/app/+item-page/field-components/collections/collections.component.spec.ts b/src/app/+item-page/field-components/collections/collections.component.spec.ts index 871018a9d8..d836c86a8c 100644 --- a/src/app/+item-page/field-components/collections/collections.component.spec.ts +++ b/src/app/+item-page/field-components/collections/collections.component.spec.ts @@ -6,7 +6,7 @@ import { Collection } from '../../../core/shared/collection.model'; import { RemoteDataBuildService } from '../../../core/cache/builders/remote-data-build.service'; import { getMockRemoteDataBuildService } from '../../../shared/mocks/mock-remote-data-build.service'; import { Item } from '../../../core/shared/item.model'; -import { Observable } from 'rxjs/Observable'; +import { Observable } from 'rxjs'; import { RemoteData } from '../../../core/data/remote-data'; import { TranslateModule } from '@ngx-translate/core'; diff --git a/src/app/+item-page/field-components/collections/collections.component.ts b/src/app/+item-page/field-components/collections/collections.component.ts index 83bb0d464d..4665d60caf 100644 --- a/src/app/+item-page/field-components/collections/collections.component.ts +++ b/src/app/+item-page/field-components/collections/collections.component.ts @@ -1,5 +1,5 @@ import { Component, Input, OnInit } from '@angular/core'; -import { Observable } from 'rxjs/Observable'; +import { Observable } from 'rxjs'; import { Collection } from '../../../core/shared/collection.model'; import { Item } from '../../../core/shared/item.model'; diff --git a/src/app/+item-page/full/field-components/file-section/full-file-section.component.ts b/src/app/+item-page/full/field-components/file-section/full-file-section.component.ts index 331e979c8f..5dc5bfdf6c 100644 --- a/src/app/+item-page/full/field-components/file-section/full-file-section.component.ts +++ b/src/app/+item-page/full/field-components/file-section/full-file-section.component.ts @@ -1,5 +1,5 @@ import { Component, Input, OnInit } from '@angular/core'; -import { Observable } from 'rxjs/Observable'; +import { Observable } from 'rxjs'; import { Bitstream } from '../../../../core/shared/bitstream.model'; import { Item } from '../../../../core/shared/item.model'; diff --git a/src/app/+item-page/full/full-item-page.component.ts b/src/app/+item-page/full/full-item-page.component.ts index dafecd748e..4d27b9d8c7 100644 --- a/src/app/+item-page/full/full-item-page.component.ts +++ b/src/app/+item-page/full/full-item-page.component.ts @@ -1,7 +1,7 @@ import { ChangeDetectionStrategy, Component, OnInit } from '@angular/core'; import { ActivatedRoute } from '@angular/router'; -import { Observable } from 'rxjs/Observable'; +import { Observable } from 'rxjs'; import { ItemPageComponent } from '../simple/item-page.component'; import { Metadatum } from '../../core/shared/metadatum.model'; diff --git a/src/app/+item-page/item-page.resolver.ts b/src/app/+item-page/item-page.resolver.ts index 2908a0ce1e..d3e0145488 100644 --- a/src/app/+item-page/item-page.resolver.ts +++ b/src/app/+item-page/item-page.resolver.ts @@ -1,6 +1,6 @@ import { Injectable } from '@angular/core'; import { ActivatedRouteSnapshot, Resolve, RouterStateSnapshot } from '@angular/router'; -import { Observable } from 'rxjs/Observable'; +import { Observable } from 'rxjs'; import { RemoteData } from '../core/data/remote-data'; import { getSucceededRemoteData } from '../core/shared/operators'; import { ItemDataService } from '../core/data/item-data.service'; diff --git a/src/app/+item-page/simple/field-components/file-section/file-section.component.ts b/src/app/+item-page/simple/field-components/file-section/file-section.component.ts index b42e73940f..8c40d123bf 100644 --- a/src/app/+item-page/simple/field-components/file-section/file-section.component.ts +++ b/src/app/+item-page/simple/field-components/file-section/file-section.component.ts @@ -1,5 +1,5 @@ import { Component, Input, OnInit } from '@angular/core'; -import { Observable } from 'rxjs/Observable'; +import { Observable } from 'rxjs'; import { Bitstream } from '../../../../core/shared/bitstream.model'; import { Item } from '../../../../core/shared/item.model'; diff --git a/src/app/+item-page/simple/item-page.component.ts b/src/app/+item-page/simple/item-page.component.ts index 7ff304236d..6f01a30613 100644 --- a/src/app/+item-page/simple/item-page.component.ts +++ b/src/app/+item-page/simple/item-page.component.ts @@ -1,7 +1,7 @@ import { ChangeDetectionStrategy, Component, OnInit } from '@angular/core'; import { ActivatedRoute } from '@angular/router'; -import { Observable } from 'rxjs/Observable'; +import { Observable } from 'rxjs'; import { ItemDataService } from '../../core/data/item-data.service'; import { RemoteData } from '../../core/data/remote-data'; import { Bitstream } from '../../core/shared/bitstream.model'; diff --git a/src/app/+login-page/login-page.component.spec.ts b/src/app/+login-page/login-page.component.spec.ts index 609cf47794..b917a3299b 100644 --- a/src/app/+login-page/login-page.component.spec.ts +++ b/src/app/+login-page/login-page.component.spec.ts @@ -3,7 +3,7 @@ import { async, ComponentFixture, TestBed } from '@angular/core/testing'; import { Store } from '@ngrx/store'; import { TranslateModule } from '@ngx-translate/core'; -import { Observable } from 'rxjs/Observable'; +import { Observable } from 'rxjs'; import 'rxjs/add/observable/of'; import { LoginPageComponent } from './login-page.component'; diff --git a/src/app/+search-page/search-filters/search-filter/search-facet-filter/search-facet-filter.component.spec.ts b/src/app/+search-page/search-filters/search-filter/search-facet-filter/search-facet-filter.component.spec.ts index 49141c2b68..d7aba289c4 100644 --- a/src/app/+search-page/search-filters/search-filter/search-facet-filter/search-facet-filter.component.spec.ts +++ b/src/app/+search-page/search-filters/search-filter/search-facet-filter/search-facet-filter.component.spec.ts @@ -7,7 +7,7 @@ import { SearchFilterConfig } from '../../../search-service/search-filter-config import { FilterType } from '../../../search-service/filter-type.model'; import { FacetValue } from '../../../search-service/facet-value.model'; import { FormsModule } from '@angular/forms'; -import { Observable } from 'rxjs/Observable'; +import { Observable } from 'rxjs'; import { SearchService } from '../../../search-service/search.service'; import { SearchServiceStub } from '../../../../shared/testing/search-service-stub'; import { RemoteData } from '../../../../core/data/remote-data'; diff --git a/src/app/+search-page/search-filters/search-filter/search-facet-filter/search-facet-filter.component.ts b/src/app/+search-page/search-filters/search-filter/search-facet-filter/search-facet-filter.component.ts index e0500b555e..00cf6bdc00 100644 --- a/src/app/+search-page/search-filters/search-filter/search-facet-filter/search-facet-filter.component.ts +++ b/src/app/+search-page/search-filters/search-filter/search-facet-filter/search-facet-filter.component.ts @@ -1,10 +1,7 @@ import { animate, state, style, transition, trigger } from '@angular/animations'; import { Component, Inject, OnDestroy, OnInit } from '@angular/core'; import { Router } from '@angular/router'; -import { BehaviorSubject } from 'rxjs/BehaviorSubject'; -import { Observable } from 'rxjs/Observable'; -import { Subject } from 'rxjs/Subject'; -import { Subscription } from 'rxjs/Subscription'; +import { BehaviorSubject , Observable , Subject , Subscription } from 'rxjs'; import { RemoteDataBuildService } from '../../../../core/cache/builders/remote-data-build.service'; import { PaginatedList } from '../../../../core/data/paginated-list'; import { RemoteData } from '../../../../core/data/remote-data'; diff --git a/src/app/+search-page/search-filters/search-filter/search-filter.component.spec.ts b/src/app/+search-page/search-filters/search-filter/search-filter.component.spec.ts index 78d40b1cf6..1f32ef6c27 100644 --- a/src/app/+search-page/search-filters/search-filter/search-filter.component.spec.ts +++ b/src/app/+search-page/search-filters/search-filter/search-filter.component.spec.ts @@ -3,7 +3,7 @@ import { ChangeDetectionStrategy, NO_ERRORS_SCHEMA } from '@angular/core'; import { async, ComponentFixture, TestBed } from '@angular/core/testing'; import { RouterTestingModule } from '@angular/router/testing'; import { TranslateModule } from '@ngx-translate/core'; -import { Observable } from 'rxjs/Observable'; +import { Observable } from 'rxjs'; import { NoopAnimationsModule } from '@angular/platform-browser/animations'; import { SearchFilterService } from './search-filter.service'; import { SearchService } from '../../search-service/search.service'; diff --git a/src/app/+search-page/search-filters/search-filter/search-filter.component.ts b/src/app/+search-page/search-filters/search-filter/search-filter.component.ts index bd3c9f7a0c..8d20378910 100644 --- a/src/app/+search-page/search-filters/search-filter/search-filter.component.ts +++ b/src/app/+search-page/search-filters/search-filter/search-filter.component.ts @@ -1,7 +1,7 @@ import { Component, Input, OnInit } from '@angular/core'; import { SearchFilterConfig } from '../../search-service/search-filter-config.model'; import { SearchFilterService } from './search-filter.service'; -import { Observable } from 'rxjs/Observable'; +import { Observable } from 'rxjs'; import { slide } from '../../../shared/animations/slide'; import { isNotEmpty } from '../../../shared/empty.util'; diff --git a/src/app/+search-page/search-filters/search-filter/search-filter.service.spec.ts b/src/app/+search-page/search-filters/search-filter/search-filter.service.spec.ts index 6d250f6869..4ee7369706 100644 --- a/src/app/+search-page/search-filters/search-filter/search-filter.service.spec.ts +++ b/src/app/+search-page/search-filters/search-filter/search-filter.service.spec.ts @@ -1,4 +1,4 @@ -import { Observable } from 'rxjs/Observable'; +import { Observable } from 'rxjs'; import { SearchFilterService } from './search-filter.service'; import { Store } from '@ngrx/store'; import { diff --git a/src/app/+search-page/search-filters/search-filter/search-filter.service.ts b/src/app/+search-page/search-filters/search-filter/search-filter.service.ts index 3b7c7b8e86..3f3f14b9e6 100644 --- a/src/app/+search-page/search-filters/search-filter/search-filter.service.ts +++ b/src/app/+search-page/search-filters/search-filter/search-filter.service.ts @@ -2,7 +2,7 @@ import { Injectable, InjectionToken } from '@angular/core'; import { distinctUntilChanged, map } from 'rxjs/operators'; import { SearchFiltersState, SearchFilterState } from './search-filter.reducer'; import { createSelector, MemoizedSelector, Store } from '@ngrx/store'; -import { Observable } from 'rxjs/Observable'; +import { Observable } from 'rxjs'; import { SearchFilterCollapseAction, SearchFilterDecrementPageAction, diff --git a/src/app/+search-page/search-filters/search-filter/search-range-filter/search-range-filter.component.spec.ts b/src/app/+search-page/search-filters/search-filter/search-range-filter/search-range-filter.component.spec.ts index 4e555459d6..ce5d5dd6dd 100644 --- a/src/app/+search-page/search-filters/search-filter/search-range-filter/search-range-filter.component.spec.ts +++ b/src/app/+search-page/search-filters/search-filter/search-range-filter/search-range-filter.component.spec.ts @@ -7,7 +7,7 @@ import { SearchFilterConfig } from '../../../search-service/search-filter-config import { FilterType } from '../../../search-service/filter-type.model'; import { FacetValue } from '../../../search-service/facet-value.model'; import { FormsModule } from '@angular/forms'; -import { Observable } from 'rxjs/Observable'; +import { Observable } from 'rxjs'; import { SearchService } from '../../../search-service/search.service'; import { SearchServiceStub } from '../../../../shared/testing/search-service-stub'; import { RemoteData } from '../../../../core/data/remote-data'; diff --git a/src/app/+search-page/search-filters/search-filter/search-range-filter/search-range-filter.component.ts b/src/app/+search-page/search-filters/search-filter/search-range-filter/search-range-filter.component.ts index 61e07b9b53..0f3832a226 100644 --- a/src/app/+search-page/search-filters/search-filter/search-range-filter/search-range-filter.component.ts +++ b/src/app/+search-page/search-filters/search-filter/search-range-filter/search-range-filter.component.ts @@ -12,10 +12,9 @@ import { FILTER_CONFIG, SearchFilterService } from '../search-filter.service'; import { SearchService } from '../../../search-service/search.service'; import { Router } from '@angular/router'; import * as moment from 'moment'; -import { Observable } from 'rxjs/Observable'; +import { Observable , Subscription } from 'rxjs'; import { RouteService } from '../../../../shared/services/route.service'; import { hasValue } from '../../../../shared/empty.util'; -import { Subscription } from 'rxjs/Subscription'; import { SearchConfigurationService } from '../../../search-service/search-configuration.service'; /** diff --git a/src/app/+search-page/search-filters/search-filter/search-text-filter/search-text-filter.component.ts b/src/app/+search-page/search-filters/search-filter/search-text-filter/search-text-filter.component.ts index 9e603184e8..bb396a6692 100644 --- a/src/app/+search-page/search-filters/search-filter/search-text-filter/search-text-filter.component.ts +++ b/src/app/+search-page/search-filters/search-filter/search-text-filter/search-text-filter.component.ts @@ -1,6 +1,6 @@ import { animate, state, style, transition, trigger } from '@angular/animations'; import { Component, HostBinding, OnInit } from '@angular/core'; -import { Observable } from 'rxjs/Observable'; +import { Observable } from 'rxjs'; import { FilterType } from '../../../search-service/filter-type.model'; import { facetLoad, diff --git a/src/app/+search-page/search-filters/search-filters.component.spec.ts b/src/app/+search-page/search-filters/search-filters.component.spec.ts index 7f0d4ad748..58ff30198e 100644 --- a/src/app/+search-page/search-filters/search-filters.component.spec.ts +++ b/src/app/+search-page/search-filters/search-filters.component.spec.ts @@ -7,7 +7,7 @@ import { NoopAnimationsModule } from '@angular/platform-browser/animations'; import { SearchFilterService } from './search-filter/search-filter.service'; import { SearchFiltersComponent } from './search-filters.component'; import { SearchService } from '../search-service/search.service'; -import { Observable } from 'rxjs/Observable'; +import { Observable } from 'rxjs'; import { SearchConfigurationService } from '../search-service/search-configuration.service'; describe('SearchFiltersComponent', () => { diff --git a/src/app/+search-page/search-filters/search-filters.component.ts b/src/app/+search-page/search-filters/search-filters.component.ts index f4b63c332f..f65c3b4b5b 100644 --- a/src/app/+search-page/search-filters/search-filters.component.ts +++ b/src/app/+search-page/search-filters/search-filters.component.ts @@ -2,7 +2,7 @@ import { Component } from '@angular/core'; import { SearchService } from '../search-service/search.service'; import { RemoteData } from '../../core/data/remote-data'; import { SearchFilterConfig } from '../search-service/search-filter-config.model'; -import { Observable } from 'rxjs/Observable'; +import { Observable } from 'rxjs'; import { SearchConfigurationService } from '../search-service/search-configuration.service'; import { isNotEmpty } from '../../shared/empty.util'; import { SearchFilterService } from './search-filter/search-filter.service'; diff --git a/src/app/+search-page/search-labels/search-labels.component.spec.ts b/src/app/+search-page/search-labels/search-labels.component.spec.ts index bf512ed5db..51ddf81459 100644 --- a/src/app/+search-page/search-labels/search-labels.component.spec.ts +++ b/src/app/+search-page/search-labels/search-labels.component.spec.ts @@ -6,7 +6,7 @@ import { SearchService } from '../search-service/search.service'; import { ChangeDetectionStrategy, NO_ERRORS_SCHEMA } from '@angular/core'; import { FormsModule } from '@angular/forms'; import { SearchServiceStub } from '../../shared/testing/search-service-stub'; -import { Observable } from 'rxjs/Observable'; +import { Observable } from 'rxjs'; import { Params } from '@angular/router'; import { ObjectKeysPipe } from '../../shared/utils/object-keys-pipe'; import { SearchConfigurationService } from '../search-service/search-configuration.service'; diff --git a/src/app/+search-page/search-labels/search-labels.component.ts b/src/app/+search-page/search-labels/search-labels.component.ts index 61482f8d8a..08e07cce3d 100644 --- a/src/app/+search-page/search-labels/search-labels.component.ts +++ b/src/app/+search-page/search-labels/search-labels.component.ts @@ -1,6 +1,6 @@ import { Component } from '@angular/core'; import { SearchService } from '../search-service/search.service'; -import { Observable } from 'rxjs/Observable'; +import { Observable } from 'rxjs'; import { Params } from '@angular/router'; import { map } from 'rxjs/operators'; import { hasValue, isNotEmpty } from '../../shared/empty.util'; diff --git a/src/app/+search-page/search-page.component.spec.ts b/src/app/+search-page/search-page.component.spec.ts index 3ca18ce4c5..05b85a0a00 100644 --- a/src/app/+search-page/search-page.component.spec.ts +++ b/src/app/+search-page/search-page.component.spec.ts @@ -5,7 +5,7 @@ import { RouterTestingModule } from '@angular/router/testing'; import { Store } from '@ngrx/store'; import { TranslateModule } from '@ngx-translate/core'; import { cold, hot } from 'jasmine-marbles'; -import { Observable } from 'rxjs/Observable'; +import { Observable } from 'rxjs'; import 'rxjs/add/observable/of'; import { SortDirection, SortOptions } from '../core/cache/models/sort-options.model'; import { CommunityDataService } from '../core/data/community-data.service'; diff --git a/src/app/+search-page/search-page.component.ts b/src/app/+search-page/search-page.component.ts index da862ee7fc..a305193cf6 100644 --- a/src/app/+search-page/search-page.component.ts +++ b/src/app/+search-page/search-page.component.ts @@ -1,5 +1,5 @@ import { ChangeDetectionStrategy, Component, OnInit } from '@angular/core'; -import { Observable } from 'rxjs/Observable'; +import { Observable , Subscription , BehaviorSubject } from 'rxjs'; import { flatMap, switchMap, } from 'rxjs/operators'; import { PaginatedList } from '../core/data/paginated-list'; import { RemoteData } from '../core/data/remote-data'; @@ -11,9 +11,7 @@ import { SearchFilterService } from './search-filters/search-filter/search-filte import { SearchResult } from './search-result.model'; import { SearchService } from './search-service/search.service'; import { SearchSidebarService } from './search-sidebar/search-sidebar.service'; -import { Subscription } from 'rxjs/Subscription'; import { hasValue } from '../shared/empty.util'; -import { BehaviorSubject } from 'rxjs/BehaviorSubject'; import { SearchConfigurationService } from './search-service/search-configuration.service'; import { getSucceededRemoteData } from '../core/shared/operators'; diff --git a/src/app/+search-page/search-service/search-configuration.service.spec.ts b/src/app/+search-page/search-service/search-configuration.service.spec.ts index 9f2e6d5045..d911df0426 100644 --- a/src/app/+search-page/search-service/search-configuration.service.spec.ts +++ b/src/app/+search-page/search-service/search-configuration.service.spec.ts @@ -3,7 +3,7 @@ import { ActivatedRouteStub } from '../../shared/testing/active-router-stub'; import { PaginationComponentOptions } from '../../shared/pagination/pagination-component-options.model'; import { SortDirection, SortOptions } from '../../core/cache/models/sort-options.model'; import { PaginatedSearchOptions } from '../paginated-search-options.model'; -import { Observable } from 'rxjs/Observable'; +import { Observable } from 'rxjs'; import { SearchFilter } from '../search-filter.model'; describe('SearchConfigurationService', () => { diff --git a/src/app/+search-page/search-service/search-configuration.service.ts b/src/app/+search-page/search-service/search-configuration.service.ts index b4c06e83f3..b509a13274 100644 --- a/src/app/+search-page/search-service/search-configuration.service.ts +++ b/src/app/+search-page/search-service/search-configuration.service.ts @@ -1,15 +1,13 @@ import { SortDirection, SortOptions } from '../../core/cache/models/sort-options.model'; import { PaginationComponentOptions } from '../../shared/pagination/pagination-component-options.model'; import { SearchOptions } from '../search-options.model'; -import { Observable } from 'rxjs/Observable'; +import { Observable , BehaviorSubject , Subscription } from 'rxjs'; import { ActivatedRoute, Params } from '@angular/router'; import { PaginatedSearchOptions } from '../paginated-search-options.model'; import { Injectable, OnDestroy } from '@angular/core'; import { RouteService } from '../../shared/services/route.service'; import { hasNoValue, hasValue, isEmpty, isNotEmpty } from '../../shared/empty.util'; import { RemoteData } from '../../core/data/remote-data'; -import { BehaviorSubject } from 'rxjs/BehaviorSubject'; -import { Subscription } from 'rxjs/Subscription'; import { getSucceededRemoteData } from '../../core/shared/operators'; import { SearchFilter } from '../search-filter.model'; import { DSpaceObjectType } from '../../core/shared/dspace-object-type.model'; diff --git a/src/app/+search-page/search-service/search.service.spec.ts b/src/app/+search-page/search-service/search.service.spec.ts index 85424a3c20..a02d101ac4 100644 --- a/src/app/+search-page/search-service/search.service.spec.ts +++ b/src/app/+search-page/search-service/search.service.spec.ts @@ -12,7 +12,7 @@ import { ResponseCacheService } from '../../core/cache/response-cache.service'; import { ActivatedRouteStub } from '../../shared/testing/active-router-stub'; import { RouterStub } from '../../shared/testing/router-stub'; import { HALEndpointService } from '../../core/shared/hal-endpoint.service'; -import { Observable } from 'rxjs/Observable'; +import { Observable } from 'rxjs'; import { PaginatedSearchOptions } from '../paginated-search-options.model'; import { RemoteData } from '../../core/data/remote-data'; import { ResponseCacheEntry } from '../../core/cache/response-cache.reducer'; diff --git a/src/app/+search-page/search-service/search.service.ts b/src/app/+search-page/search-service/search.service.ts index ac5f7a6169..0d30c7f458 100644 --- a/src/app/+search-page/search-service/search.service.ts +++ b/src/app/+search-page/search-service/search.service.ts @@ -6,7 +6,7 @@ import { Router, UrlSegmentGroup } from '@angular/router'; -import { Observable } from 'rxjs/Observable'; +import { Observable } from 'rxjs'; import { flatMap, map, switchMap } from 'rxjs/operators'; import { RemoteDataBuildService } from '../../core/cache/builders/remote-data-build.service'; import { diff --git a/src/app/+search-page/search-settings/search-settings.component.spec.ts b/src/app/+search-page/search-settings/search-settings.component.spec.ts index 5e6dc9b369..ddd7900b1e 100644 --- a/src/app/+search-page/search-settings/search-settings.component.spec.ts +++ b/src/app/+search-page/search-settings/search-settings.component.spec.ts @@ -1,7 +1,7 @@ import { SearchService } from '../search-service/search.service'; import { async, ComponentFixture, TestBed } from '@angular/core/testing'; import { SearchSettingsComponent } from './search-settings.component'; -import { Observable } from 'rxjs/Observable'; +import { Observable } from 'rxjs'; import { PaginationComponentOptions } from '../../shared/pagination/pagination-component-options.model'; import { SortDirection, SortOptions } from '../../core/cache/models/sort-options.model'; import { TranslateModule } from '@ngx-translate/core'; diff --git a/src/app/+search-page/search-settings/search-settings.component.ts b/src/app/+search-page/search-settings/search-settings.component.ts index 81e2366e39..c6415798ef 100644 --- a/src/app/+search-page/search-settings/search-settings.component.ts +++ b/src/app/+search-page/search-settings/search-settings.component.ts @@ -4,7 +4,7 @@ import { SortDirection, SortOptions } from '../../core/cache/models/sort-options import { ActivatedRoute, NavigationExtras, Router } from '@angular/router'; import { PaginatedSearchOptions } from '../paginated-search-options.model'; import { SearchFilterService } from '../search-filters/search-filter/search-filter.service'; -import { Observable } from 'rxjs/Observable'; +import { Observable } from 'rxjs'; import { SearchConfigurationService } from '../search-service/search-configuration.service'; @Component({ diff --git a/src/app/+search-page/search-sidebar/search-sidebar.effects.spec.ts b/src/app/+search-page/search-sidebar/search-sidebar.effects.spec.ts index 146b1fdcdb..f34f6b72de 100644 --- a/src/app/+search-page/search-sidebar/search-sidebar.effects.spec.ts +++ b/src/app/+search-page/search-sidebar/search-sidebar.effects.spec.ts @@ -1,5 +1,5 @@ import { TestBed } from '@angular/core/testing'; -import { Observable } from 'rxjs/Observable'; +import { Observable } from 'rxjs'; import { provideMockActions } from '@ngrx/effects/testing'; import { cold, hot } from 'jasmine-marbles'; import * as fromRouter from '@ngrx/router-store'; diff --git a/src/app/+search-page/search-sidebar/search-sidebar.service.spec.ts b/src/app/+search-page/search-sidebar/search-sidebar.service.spec.ts index b6439be4df..dcc5f536d9 100644 --- a/src/app/+search-page/search-sidebar/search-sidebar.service.spec.ts +++ b/src/app/+search-page/search-sidebar/search-sidebar.service.spec.ts @@ -2,7 +2,7 @@ import { Store } from '@ngrx/store'; import { SearchSidebarService } from './search-sidebar.service'; import { AppState } from '../../app.reducer'; import { async, inject, TestBed } from '@angular/core/testing'; -import { Observable } from 'rxjs/Observable'; +import { Observable } from 'rxjs'; import 'rxjs/add/observable/of'; import { SearchSidebarCollapseAction, SearchSidebarExpandAction } from './search-sidebar.actions'; import { HostWindowService } from '../../shared/host-window.service'; diff --git a/src/app/+search-page/search-sidebar/search-sidebar.service.ts b/src/app/+search-page/search-sidebar/search-sidebar.service.ts index 8cf9339c5c..c9a7fb57c0 100644 --- a/src/app/+search-page/search-sidebar/search-sidebar.service.ts +++ b/src/app/+search-page/search-sidebar/search-sidebar.service.ts @@ -2,7 +2,7 @@ import { Injectable } from '@angular/core'; import { SearchSidebarState } from './search-sidebar.reducer'; import { createSelector, Store } from '@ngrx/store'; import { SearchSidebarCollapseAction, SearchSidebarExpandAction } from './search-sidebar.actions'; -import { Observable } from 'rxjs/Observable'; +import { Observable } from 'rxjs'; import { AppState } from '../../app.reducer'; import { HostWindowService } from '../../shared/host-window.service'; diff --git a/src/app/app.module.ts b/src/app/app.module.ts index 528c84fd3b..a02997abdd 100755 --- a/src/app/app.module.ts +++ b/src/app/app.module.ts @@ -7,7 +7,6 @@ import { NgbModule } from '@ng-bootstrap/ng-bootstrap'; import { EffectsModule } from '@ngrx/effects'; import { RouterStateSerializer, StoreRouterConnectingModule } from '@ngrx/router-store'; import { META_REDUCERS, MetaReducer, StoreModule } from '@ngrx/store'; -import { StoreDevtoolsModule } from '@ngrx/store-devtools'; import { TranslateModule } from '@ngx-translate/core'; @@ -47,9 +46,6 @@ export function getMetaReducers(config: GlobalConfig): Array response.isSuccessful); return Observable.merge( errorResponse.flatMap((response: ErrorResponse) => - Observable.throw(new Error(response.errorMessage))), + observableThrowError(new Error(response.errorMessage))), successResponse .filter((response: AuthStatusResponse) => isNotEmpty(response)) .map((response: AuthStatusResponse) => response.response) diff --git a/src/app/core/auth/auth.effects.spec.ts b/src/app/core/auth/auth.effects.spec.ts index 3b569e523f..b5b7cd6da9 100644 --- a/src/app/core/auth/auth.effects.spec.ts +++ b/src/app/core/auth/auth.effects.spec.ts @@ -4,7 +4,7 @@ import { provideMockActions } from '@ngrx/effects/testing'; import { Store } from '@ngrx/store'; import { cold, hot } from 'jasmine-marbles'; -import { Observable } from 'rxjs/Observable'; +import { Observable } from 'rxjs'; import 'rxjs/add/observable/of' import { AuthEffects } from './auth.effects'; diff --git a/src/app/core/auth/auth.effects.ts b/src/app/core/auth/auth.effects.ts index e2d6c80b5e..223100056b 100644 --- a/src/app/core/auth/auth.effects.ts +++ b/src/app/core/auth/auth.effects.ts @@ -5,7 +5,7 @@ import { Actions, Effect } from '@ngrx/effects'; import { Action, Store } from '@ngrx/store'; // import rxjs -import { Observable } from 'rxjs/Observable'; +import { Observable } from 'rxjs'; // import services import { AuthService } from './auth.service'; diff --git a/src/app/core/auth/auth.interceptor.spec.ts b/src/app/core/auth/auth.interceptor.spec.ts index 528c2cfab3..e0984bcd3a 100644 --- a/src/app/core/auth/auth.interceptor.spec.ts +++ b/src/app/core/auth/auth.interceptor.spec.ts @@ -4,7 +4,7 @@ import { HTTP_INTERCEPTORS } from '@angular/common/http'; import { Router } from '@angular/router'; import { Store } from '@ngrx/store'; -import { Observable } from 'rxjs/Observable'; +import { Observable } from 'rxjs'; import { AuthInterceptor } from './auth.interceptor'; import { AuthService } from './auth.service'; diff --git a/src/app/core/auth/auth.interceptor.ts b/src/app/core/auth/auth.interceptor.ts index 651e2fd096..95a93fa0c7 100644 --- a/src/app/core/auth/auth.interceptor.ts +++ b/src/app/core/auth/auth.interceptor.ts @@ -1,13 +1,10 @@ + +import {throwError as observableThrowError, Observable } from 'rxjs'; import { Injectable, Injector } from '@angular/core'; import { HttpEvent, HttpInterceptor, HttpHandler, HttpRequest, HttpResponse, HttpErrorResponse, HttpResponseBase } from '@angular/common/http'; - -import { Observable } from 'rxjs/Rx'; -import 'rxjs/add/observable/throw' -import 'rxjs/add/operator/catch'; - import { find } from 'lodash'; import { AppState } from '../../app.reducer'; @@ -146,7 +143,7 @@ export class AuthInterceptor implements HttpInterceptor { } } // Return error response as is. - return Observable.throw(error); + return observableThrowError(error); }) as any; } diff --git a/src/app/core/auth/auth.service.spec.ts b/src/app/core/auth/auth.service.spec.ts index b54f65078e..7e3406dece 100644 --- a/src/app/core/auth/auth.service.spec.ts +++ b/src/app/core/auth/auth.service.spec.ts @@ -3,7 +3,7 @@ import { CommonModule } from '@angular/common'; import { ActivatedRoute, Router } from '@angular/router'; import { Store, StoreModule } from '@ngrx/store'; -import { Observable } from 'rxjs/Observable'; +import { Observable } from 'rxjs'; import { REQUEST } from '@nguniversal/express-engine/tokens'; import 'rxjs/add/observable/of'; diff --git a/src/app/core/auth/auth.service.ts b/src/app/core/auth/auth.service.ts index 2848b54b50..ff1e0df0be 100644 --- a/src/app/core/auth/auth.service.ts +++ b/src/app/core/auth/auth.service.ts @@ -6,7 +6,7 @@ import { REQUEST } from '@nguniversal/express-engine/tokens'; import { RouterReducerState } from '@ngrx/router-store'; import { Store } from '@ngrx/store'; import { CookieAttributes } from 'js-cookie'; -import { Observable } from 'rxjs/Observable'; +import { Observable } from 'rxjs'; import { map, withLatestFrom } from 'rxjs/operators'; import { Eperson } from '../eperson/models/eperson.model'; diff --git a/src/app/core/auth/authenticated.guard.ts b/src/app/core/auth/authenticated.guard.ts index 42c39b403c..66fa34992d 100644 --- a/src/app/core/auth/authenticated.guard.ts +++ b/src/app/core/auth/authenticated.guard.ts @@ -1,7 +1,7 @@ import { Injectable } from '@angular/core'; import { ActivatedRouteSnapshot, CanActivate, CanLoad, Route, Router, RouterStateSnapshot } from '@angular/router'; -import { Observable } from 'rxjs/Observable'; +import { Observable } from 'rxjs'; import { Store } from '@ngrx/store'; // reducers diff --git a/src/app/core/auth/server-auth.service.ts b/src/app/core/auth/server-auth.service.ts index 96ee2e355a..e65452e872 100644 --- a/src/app/core/auth/server-auth.service.ts +++ b/src/app/core/auth/server-auth.service.ts @@ -1,6 +1,6 @@ import { Injectable } from '@angular/core'; -import { Observable } from 'rxjs/Observable'; +import { Observable } from 'rxjs'; import { HttpHeaders } from '@angular/common/http'; import { HttpOptions } from '../dspace-rest-v2/dspace-rest-v2.service'; import { AuthStatus } from './models/auth-status.model'; diff --git a/src/app/core/browse/browse.service.spec.ts b/src/app/core/browse/browse.service.spec.ts index 5118ea7ecc..795a2eb7ff 100644 --- a/src/app/core/browse/browse.service.spec.ts +++ b/src/app/core/browse/browse.service.spec.ts @@ -1,5 +1,5 @@ import { cold, getTestScheduler, hot } from 'jasmine-marbles'; -import { TestScheduler } from 'rxjs/Rx'; +import { TestScheduler } from 'rxjs'; import { getMockRemoteDataBuildService } from '../../shared/mocks/mock-remote-data-build.service'; import { getMockRequestService } from '../../shared/mocks/mock-request.service'; import { getMockResponseCacheService } from '../../shared/mocks/mock-response-cache.service'; diff --git a/src/app/core/browse/browse.service.ts b/src/app/core/browse/browse.service.ts index 836014a110..72e2be481d 100644 --- a/src/app/core/browse/browse.service.ts +++ b/src/app/core/browse/browse.service.ts @@ -1,5 +1,5 @@ import { Injectable } from '@angular/core'; -import { Observable } from 'rxjs/Observable'; +import { Observable } from 'rxjs'; import { distinctUntilChanged, map, startWith } from 'rxjs/operators'; import { ensureArrayHasValue, 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 d934f60e48..9078bb05da 100644 --- a/src/app/core/cache/builders/remote-data-build.service.ts +++ b/src/app/core/cache/builders/remote-data-build.service.ts @@ -1,5 +1,5 @@ import { Injectable } from '@angular/core'; -import { Observable } from 'rxjs/Observable'; +import { Observable } from 'rxjs'; import { distinctUntilChanged, flatMap, map, startWith } from 'rxjs/operators'; import { hasValue, hasValueOperator, isEmpty, isNotEmpty } from '../../../shared/empty.util'; import { PaginatedList } from '../../data/paginated-list'; diff --git a/src/app/core/cache/object-cache.effects.spec.ts b/src/app/core/cache/object-cache.effects.spec.ts index d0a97a18fd..36502be849 100644 --- a/src/app/core/cache/object-cache.effects.spec.ts +++ b/src/app/core/cache/object-cache.effects.spec.ts @@ -1,5 +1,5 @@ import { TestBed } from '@angular/core/testing'; -import { Observable } from 'rxjs/Observable'; +import { Observable } from 'rxjs'; import { provideMockActions } from '@ngrx/effects/testing'; import { cold, hot } from 'jasmine-marbles'; import { ObjectCacheEffects } from './object-cache.effects'; diff --git a/src/app/core/cache/object-cache.service.spec.ts b/src/app/core/cache/object-cache.service.spec.ts index 80a9121544..39afe0c35e 100644 --- a/src/app/core/cache/object-cache.service.spec.ts +++ b/src/app/core/cache/object-cache.service.spec.ts @@ -1,5 +1,5 @@ import { Store } from '@ngrx/store'; -import { Observable } from 'rxjs/Observable'; +import { Observable } from 'rxjs'; import { ObjectCacheService } from './object-cache.service'; import { AddToObjectCacheAction, RemoveFromObjectCacheAction } from './object-cache.actions'; diff --git a/src/app/core/cache/object-cache.service.ts b/src/app/core/cache/object-cache.service.ts index 9344f4d5f0..dbeb02cb0a 100644 --- a/src/app/core/cache/object-cache.service.ts +++ b/src/app/core/cache/object-cache.service.ts @@ -1,7 +1,7 @@ import { Injectable } from '@angular/core'; import { MemoizedSelector, Store } from '@ngrx/store'; -import { Observable } from 'rxjs/Observable'; +import { Observable } from 'rxjs'; import { IndexName } from '../index/index.reducer'; import { ObjectCacheEntry, CacheableObject } from './object-cache.reducer'; diff --git a/src/app/core/cache/response-cache.effects.spec.ts b/src/app/core/cache/response-cache.effects.spec.ts index e58ec536e3..950049bfca 100644 --- a/src/app/core/cache/response-cache.effects.spec.ts +++ b/src/app/core/cache/response-cache.effects.spec.ts @@ -1,5 +1,5 @@ import { TestBed } from '@angular/core/testing'; -import { Observable } from 'rxjs/Observable'; +import { Observable } from 'rxjs'; import { provideMockActions } from '@ngrx/effects/testing'; import { cold, hot } from 'jasmine-marbles'; import { StoreActionTypes } from '../../store.actions'; diff --git a/src/app/core/cache/response-cache.service.spec.ts b/src/app/core/cache/response-cache.service.spec.ts index 77838b6eb6..87db10db1b 100644 --- a/src/app/core/cache/response-cache.service.spec.ts +++ b/src/app/core/cache/response-cache.service.spec.ts @@ -1,7 +1,7 @@ import { Store } from '@ngrx/store'; import { ResponseCacheService } from './response-cache.service'; -import { Observable } from 'rxjs/Observable'; +import { Observable } from 'rxjs'; import { CoreState } from '../core.reducers'; import { RestResponse } from './response-cache.models'; import { ResponseCacheEntry } from './response-cache.reducer'; diff --git a/src/app/core/cache/response-cache.service.ts b/src/app/core/cache/response-cache.service.ts index a0e3740094..19e7711168 100644 --- a/src/app/core/cache/response-cache.service.ts +++ b/src/app/core/cache/response-cache.service.ts @@ -1,7 +1,7 @@ import { Injectable } from '@angular/core'; import { MemoizedSelector, Store } from '@ngrx/store'; -import { Observable } from 'rxjs/Observable'; +import { Observable } from 'rxjs'; import { ResponseCacheEntry } from './response-cache.reducer'; import { hasNoValue } from '../../shared/empty.util'; diff --git a/src/app/core/config/config.service.spec.ts b/src/app/core/config/config.service.spec.ts index 4b05d5c929..75dff4018e 100644 --- a/src/app/core/config/config.service.spec.ts +++ b/src/app/core/config/config.service.spec.ts @@ -1,5 +1,5 @@ import { cold, getTestScheduler, hot } from 'jasmine-marbles'; -import { TestScheduler } from 'rxjs/Rx'; +import { TestScheduler } from 'rxjs'; import { getMockRequestService } from '../../shared/mocks/mock-request.service'; import { ResponseCacheService } from '../cache/response-cache.service'; import { ConfigService } from './config.service'; diff --git a/src/app/core/config/config.service.ts b/src/app/core/config/config.service.ts index bb863ad46f..d1b042afd3 100644 --- a/src/app/core/config/config.service.ts +++ b/src/app/core/config/config.service.ts @@ -1,4 +1,5 @@ -import { Observable } from 'rxjs/Observable'; + +import {throwError as observableThrowError, Observable } from 'rxjs'; import { RequestService } from '../data/request.service'; import { ResponseCacheService } from '../cache/response-cache.service'; @@ -23,7 +24,7 @@ export abstract class ConfigService { .partition((response: RestResponse) => response.isSuccessful); return Observable.merge( errorResponse.flatMap((response: ErrorResponse) => - Observable.throw(new Error(`Couldn't retrieve the config`))), + observableThrowError(new Error(`Couldn't retrieve the config`))), successResponse .filter((response: ConfigSuccessResponse) => isNotEmpty(response) && isNotEmpty(response.configDefinition)) .map((response: ConfigSuccessResponse) => new ConfigData(response.pageInfo, response.configDefinition)) diff --git a/src/app/core/data/comcol-data.service.spec.ts b/src/app/core/data/comcol-data.service.spec.ts index b5727fb22f..99a71e5f0e 100644 --- a/src/app/core/data/comcol-data.service.spec.ts +++ b/src/app/core/data/comcol-data.service.spec.ts @@ -1,6 +1,6 @@ import { Store } from '@ngrx/store'; import { cold, getTestScheduler, hot } from 'jasmine-marbles'; -import { TestScheduler } from 'rxjs/Rx'; +import { TestScheduler } from 'rxjs'; import { GlobalConfig } from '../../../config'; import { getMockRequestService } from '../../shared/mocks/mock-request.service'; import { RemoteDataBuildService } from '../cache/builders/remote-data-build.service'; diff --git a/src/app/core/data/comcol-data.service.ts b/src/app/core/data/comcol-data.service.ts index 112afa0bc8..f2c7a743d5 100644 --- a/src/app/core/data/comcol-data.service.ts +++ b/src/app/core/data/comcol-data.service.ts @@ -1,4 +1,5 @@ -import { Observable } from 'rxjs/Observable'; + +import {throwError as observableThrowError, Observable } from 'rxjs'; import { isEmpty, isNotEmpty } from '../../shared/empty.util'; import { NormalizedCommunity } from '../cache/models/normalized-community.model'; import { CacheableObject } from '../cache/object-cache.reducer'; @@ -48,7 +49,7 @@ export abstract class ComColDataService - Observable.throw(new Error(`The Community with scope ${scopeID} couldn't be retrieved`))), + observableThrowError(new Error(`The Community with scope ${scopeID} couldn't be retrieved`))), successResponse .flatMap((response: DSOSuccessResponse) => this.objectCache.getByUUID(scopeID)) .map((nc: NormalizedCommunity) => nc._links[this.linkPath]) diff --git a/src/app/core/data/community-data.service.ts b/src/app/core/data/community-data.service.ts index 3e31c62d25..206955ea9f 100644 --- a/src/app/core/data/community-data.service.ts +++ b/src/app/core/data/community-data.service.ts @@ -13,7 +13,7 @@ import { HALEndpointService } from '../shared/hal-endpoint.service'; import { FindAllOptions, FindAllRequest } from './request.models'; import { RemoteData } from './remote-data'; import { hasValue, isNotEmpty } from '../../shared/empty.util'; -import { Observable } from 'rxjs/Observable'; +import { Observable } from 'rxjs'; import { PaginatedList } from './paginated-list'; @Injectable() diff --git a/src/app/core/data/data.service.spec.ts b/src/app/core/data/data.service.spec.ts index 8377afe92e..add84818de 100644 --- a/src/app/core/data/data.service.spec.ts +++ b/src/app/core/data/data.service.spec.ts @@ -6,7 +6,7 @@ import { RemoteDataBuildService } from '../cache/builders/remote-data-build.serv import { CoreState } from '../core.reducers'; import { Store } from '@ngrx/store'; import { HALEndpointService } from '../shared/hal-endpoint.service'; -import { Observable } from 'rxjs/Observable'; +import { Observable } from 'rxjs'; import { FindAllOptions } from './request.models'; import { SortOptions, SortDirection } from '../cache/models/sort-options.model'; diff --git a/src/app/core/data/data.service.ts b/src/app/core/data/data.service.ts index c7588a5231..98e21c6ba3 100644 --- a/src/app/core/data/data.service.ts +++ b/src/app/core/data/data.service.ts @@ -1,5 +1,5 @@ import { Store } from '@ngrx/store'; -import { Observable } from 'rxjs/Observable'; +import { Observable } from 'rxjs'; import { hasValue, isNotEmpty } from '../../shared/empty.util'; import { RemoteDataBuildService } from '../cache/builders/remote-data-build.service'; import { ResponseCacheService } from '../cache/response-cache.service'; diff --git a/src/app/core/data/dspace-object-data.service.ts b/src/app/core/data/dspace-object-data.service.ts index 39feea4c30..09eea8a95f 100644 --- a/src/app/core/data/dspace-object-data.service.ts +++ b/src/app/core/data/dspace-object-data.service.ts @@ -1,6 +1,6 @@ import { Injectable } from '@angular/core'; import { Store } from '@ngrx/store'; -import { Observable } from 'rxjs/Observable'; +import { Observable } from 'rxjs'; import { RemoteDataBuildService } from '../cache/builders/remote-data-build.service'; import { NormalizedDSpaceObject } from '../cache/models/normalized-dspace-object.model'; import { ResponseCacheService } from '../cache/response-cache.service'; diff --git a/src/app/core/data/item-data.service.spec.ts b/src/app/core/data/item-data.service.spec.ts index 4d0dc8aec3..b48d3735f7 100644 --- a/src/app/core/data/item-data.service.spec.ts +++ b/src/app/core/data/item-data.service.spec.ts @@ -1,6 +1,6 @@ import { Store } from '@ngrx/store'; import { cold, getTestScheduler } from 'jasmine-marbles'; -import { TestScheduler } from 'rxjs/Rx'; +import { TestScheduler } from 'rxjs'; import { BrowseService } from '../browse/browse.service'; import { RemoteDataBuildService } from '../cache/builders/remote-data-build.service'; import { ResponseCacheService } from '../cache/response-cache.service'; diff --git a/src/app/core/data/item-data.service.ts b/src/app/core/data/item-data.service.ts index 6b0937d8e4..40724b7319 100644 --- a/src/app/core/data/item-data.service.ts +++ b/src/app/core/data/item-data.service.ts @@ -1,7 +1,7 @@ import { Inject, Injectable } from '@angular/core'; import { Store } from '@ngrx/store'; -import { Observable } from 'rxjs/Observable'; +import { Observable } from 'rxjs'; import { GLOBAL_CONFIG, GlobalConfig } from '../../../config'; import { isEmpty, isNotEmpty } from '../../shared/empty.util'; import { BrowseService } from '../browse/browse.service'; diff --git a/src/app/core/data/request.service.spec.ts b/src/app/core/data/request.service.spec.ts index aa9954f680..4c9d623941 100644 --- a/src/app/core/data/request.service.spec.ts +++ b/src/app/core/data/request.service.spec.ts @@ -1,6 +1,6 @@ import { Store } from '@ngrx/store'; import { cold, hot } from 'jasmine-marbles'; -import { Observable } from 'rxjs/Observable'; +import { Observable } from 'rxjs'; import 'rxjs/add/observable/of'; import { getMockObjectCacheService } from '../../shared/mocks/mock-object-cache.service'; import { getMockResponseCacheService } from '../../shared/mocks/mock-response-cache.service'; diff --git a/src/app/core/data/request.service.ts b/src/app/core/data/request.service.ts index 12933f83fc..9fb12215b7 100644 --- a/src/app/core/data/request.service.ts +++ b/src/app/core/data/request.service.ts @@ -2,7 +2,7 @@ import { Injectable } from '@angular/core'; import { createSelector, MemoizedSelector, Store } from '@ngrx/store'; -import { Observable } from 'rxjs/Observable'; +import { Observable } from 'rxjs'; import { hasValue } from '../../shared/empty.util'; import { CacheableObject } from '../cache/object-cache.reducer'; import { ObjectCacheService } from '../cache/object-cache.service'; diff --git a/src/app/core/dspace-rest-v2/dspace-rest-v2.service.ts b/src/app/core/dspace-rest-v2/dspace-rest-v2.service.ts index 78c93b8c08..2402678d06 100644 --- a/src/app/core/dspace-rest-v2/dspace-rest-v2.service.ts +++ b/src/app/core/dspace-rest-v2/dspace-rest-v2.service.ts @@ -1,7 +1,8 @@ + +import {throwError as observableThrowError, Observable } from 'rxjs'; import { Injectable } from '@angular/core'; import { Request } from '@angular/http'; import { HttpClient, HttpHeaders, HttpParams, HttpResponse } from '@angular/common/http' -import { Observable } from 'rxjs/Observable'; import { RestRequestMethod } from '../data/request.models'; import { DSpaceRESTV2Response } from './dspace-rest-v2-response.model'; @@ -40,7 +41,7 @@ export class DSpaceRESTv2Service { .map((res: HttpResponse) => ({ payload: res.body, statusCode: res.statusText })) .catch((err) => { console.log('Error: ', err); - return Observable.throw(err); + return observableThrowError(err); }); } @@ -70,7 +71,7 @@ export class DSpaceRESTv2Service { .map((res) => ({ payload: res.body, headers: res.headers, statusCode: res.statusText })) .catch((err) => { console.log('Error: ', err); - return Observable.throw(err); + return observableThrowError(err); }); } diff --git a/src/app/core/integration/integration.service.spec.ts b/src/app/core/integration/integration.service.spec.ts index b7f4e019f7..60a2e8577a 100644 --- a/src/app/core/integration/integration.service.spec.ts +++ b/src/app/core/integration/integration.service.spec.ts @@ -1,5 +1,5 @@ import { cold, getTestScheduler } from 'jasmine-marbles'; -import { TestScheduler } from 'rxjs/Rx'; +import { TestScheduler } from 'rxjs'; import { getMockRequestService } from '../../shared/mocks/mock-request.service'; import { ResponseCacheService } from '../cache/response-cache.service'; diff --git a/src/app/core/integration/integration.service.ts b/src/app/core/integration/integration.service.ts index f1c770336a..7642848ed6 100644 --- a/src/app/core/integration/integration.service.ts +++ b/src/app/core/integration/integration.service.ts @@ -1,4 +1,5 @@ -import { Observable } from 'rxjs/Observable'; + +import {throwError as observableThrowError, Observable } from 'rxjs'; import { RequestService } from '../data/request.service'; import { ResponseCacheService } from '../cache/response-cache.service'; import { ErrorResponse, IntegrationSuccessResponse, RestResponse } from '../cache/response-cache.models'; @@ -23,7 +24,7 @@ export abstract class IntegrationService { .partition((response: RestResponse) => response.isSuccessful); return Observable.merge( errorResponse.flatMap((response: ErrorResponse) => - Observable.throw(new Error(`Couldn't retrieve the integration data`))), + observableThrowError(new Error(`Couldn't retrieve the integration data`))), successResponse .filter((response: IntegrationSuccessResponse) => isNotEmpty(response)) .map((response: IntegrationSuccessResponse) => new IntegrationData(response.pageInfo, response.dataDefinition)) diff --git a/src/app/core/metadata/metadata.service.spec.ts b/src/app/core/metadata/metadata.service.spec.ts index f8f36a358e..39bedb33d2 100644 --- a/src/app/core/metadata/metadata.service.spec.ts +++ b/src/app/core/metadata/metadata.service.spec.ts @@ -10,7 +10,7 @@ import { TranslateModule, TranslateLoader } from '@ngx-translate/core'; import { Store, StoreModule } from '@ngrx/store'; -import { Observable } from 'rxjs/Observable'; +import { Observable } from 'rxjs'; import { RemoteDataError } from '../data/remote-data-error'; import { UUIDService } from '../shared/uuid.service'; diff --git a/src/app/core/metadata/metadata.service.ts b/src/app/core/metadata/metadata.service.ts index cf597195e9..4689b2048c 100644 --- a/src/app/core/metadata/metadata.service.ts +++ b/src/app/core/metadata/metadata.service.ts @@ -1,5 +1,5 @@ -import 'rxjs/add/operator/first' -import 'rxjs/add/operator/take' + + import { Inject, Injectable } from '@angular/core'; import { @@ -14,8 +14,7 @@ import { Meta, MetaDefinition, Title } from '@angular/platform-browser'; import { TranslateService } from '@ngx-translate/core'; -import { BehaviorSubject } from 'rxjs/BehaviorSubject'; -import { Observable } from 'rxjs/Observable'; +import { BehaviorSubject , Observable } from 'rxjs'; import { RemoteData } from '../data/remote-data'; import { Bitstream } from '../shared/bitstream.model'; diff --git a/src/app/core/registry/registry.service.spec.ts b/src/app/core/registry/registry.service.spec.ts index ef1533278d..2dceec7f08 100644 --- a/src/app/core/registry/registry.service.spec.ts +++ b/src/app/core/registry/registry.service.spec.ts @@ -6,7 +6,7 @@ import { RequestService } from '../data/request.service'; import { RemoteDataBuildService } from '../cache/builders/remote-data-build.service'; import { HALEndpointService } from '../shared/hal-endpoint.service'; import { PaginationComponentOptions } from '../../shared/pagination/pagination-component-options.model'; -import { Observable } from 'rxjs/Observable'; +import { Observable } from 'rxjs'; import { ResponseCacheEntry } from '../cache/response-cache.reducer'; import { RequestEntry } from '../data/request.reducer'; import { RemoteData } from '../data/remote-data'; diff --git a/src/app/core/registry/registry.service.ts b/src/app/core/registry/registry.service.ts index 4359284158..cc976f37f2 100644 --- a/src/app/core/registry/registry.service.ts +++ b/src/app/core/registry/registry.service.ts @@ -1,5 +1,5 @@ import { Injectable } from '@angular/core'; -import { Observable } from 'rxjs/Observable'; +import { Observable } from 'rxjs'; import { RemoteData } from '../data/remote-data'; import { PaginatedList } from '../data/paginated-list'; import { PageInfo } from '../shared/page-info.model'; diff --git a/src/app/core/shared/bitstream.model.ts b/src/app/core/shared/bitstream.model.ts index 511c2c5cd2..794282e867 100644 --- a/src/app/core/shared/bitstream.model.ts +++ b/src/app/core/shared/bitstream.model.ts @@ -2,7 +2,7 @@ import { DSpaceObject } from './dspace-object.model'; import { RemoteData } from '../data/remote-data'; import { Item } from './item.model'; import { BitstreamFormat } from './bitstream-format.model'; -import { Observable } from 'rxjs/Observable'; +import { Observable } from 'rxjs'; export class Bitstream extends DSpaceObject { diff --git a/src/app/core/shared/bundle.model.ts b/src/app/core/shared/bundle.model.ts index 9a8afb2661..3f5b5df877 100644 --- a/src/app/core/shared/bundle.model.ts +++ b/src/app/core/shared/bundle.model.ts @@ -2,7 +2,7 @@ import { DSpaceObject } from './dspace-object.model'; import { Bitstream } from './bitstream.model'; import { Item } from './item.model'; import { RemoteData } from '../data/remote-data'; -import { Observable } from 'rxjs/Observable'; +import { Observable } from 'rxjs'; export class Bundle extends DSpaceObject { /** diff --git a/src/app/core/shared/collection.model.ts b/src/app/core/shared/collection.model.ts index b2f8d90a65..8fdc14bd6e 100644 --- a/src/app/core/shared/collection.model.ts +++ b/src/app/core/shared/collection.model.ts @@ -2,7 +2,7 @@ import { DSpaceObject } from './dspace-object.model'; import { Bitstream } from './bitstream.model'; import { Item } from './item.model'; import { RemoteData } from '../data/remote-data'; -import { Observable } from 'rxjs/Observable'; +import { Observable } from 'rxjs'; export class Collection extends DSpaceObject { diff --git a/src/app/core/shared/community.model.ts b/src/app/core/shared/community.model.ts index 20bd50f4a9..893a7e0b94 100644 --- a/src/app/core/shared/community.model.ts +++ b/src/app/core/shared/community.model.ts @@ -2,7 +2,7 @@ import { DSpaceObject } from './dspace-object.model'; import { Bitstream } from './bitstream.model'; import { Collection } from './collection.model'; import { RemoteData } from '../data/remote-data'; -import { Observable } from 'rxjs/Observable'; +import { Observable } from 'rxjs'; import { PaginatedList } from '../data/paginated-list'; export class Community extends DSpaceObject { diff --git a/src/app/core/shared/dspace-object.model.ts b/src/app/core/shared/dspace-object.model.ts index 5e62e3e321..061e525fe7 100644 --- a/src/app/core/shared/dspace-object.model.ts +++ b/src/app/core/shared/dspace-object.model.ts @@ -4,7 +4,7 @@ import { CacheableObject } from '../cache/object-cache.reducer'; import { RemoteData } from '../data/remote-data'; import { ResourceType } from './resource-type'; import { ListableObject } from '../../shared/object-collection/shared/listable-object.model'; -import { Observable } from 'rxjs/Observable'; +import { Observable } from 'rxjs'; /** * An abstract model class for a DSpaceObject. diff --git a/src/app/core/shared/hal-endpoint.service.ts b/src/app/core/shared/hal-endpoint.service.ts index 3bedeb9915..8e8d6b73d6 100644 --- a/src/app/core/shared/hal-endpoint.service.ts +++ b/src/app/core/shared/hal-endpoint.service.ts @@ -1,4 +1,4 @@ -import { Observable } from 'rxjs/Observable'; +import { Observable } from 'rxjs'; import { distinctUntilChanged, map, flatMap, startWith, tap } from 'rxjs/operators'; import { RequestService } from '../data/request.service'; import { ResponseCacheService } from '../cache/response-cache.service'; diff --git a/src/app/core/shared/item.model.spec.ts b/src/app/core/shared/item.model.spec.ts index c020cd3454..601ad3c0dc 100644 --- a/src/app/core/shared/item.model.spec.ts +++ b/src/app/core/shared/item.model.spec.ts @@ -1,4 +1,4 @@ -import { Observable } from 'rxjs/Observable'; +import { Observable } from 'rxjs'; import { Item } from './item.model'; import { RemoteData } from '../data/remote-data'; diff --git a/src/app/core/shared/item.model.ts b/src/app/core/shared/item.model.ts index cc84694e84..2d42a189a7 100644 --- a/src/app/core/shared/item.model.ts +++ b/src/app/core/shared/item.model.ts @@ -1,4 +1,4 @@ -import { Observable } from 'rxjs/Observable'; +import { Observable } from 'rxjs'; import { DSpaceObject } from './dspace-object.model'; import { Collection } from './collection.model'; diff --git a/src/app/core/shared/operators.ts b/src/app/core/shared/operators.ts index fcb4c2c256..a3e934341e 100644 --- a/src/app/core/shared/operators.ts +++ b/src/app/core/shared/operators.ts @@ -1,4 +1,4 @@ -import { Observable } from 'rxjs/Observable'; +import { Observable } from 'rxjs'; import { filter, first, flatMap, map, tap } from 'rxjs/operators'; import { hasValueOperator } from '../../shared/empty.util'; import { DSOSuccessResponse } from '../cache/response-cache.models'; diff --git a/src/app/header/header.component.spec.ts b/src/app/header/header.component.spec.ts index 87fa2995d6..c88bdae08e 100644 --- a/src/app/header/header.component.spec.ts +++ b/src/app/header/header.component.spec.ts @@ -4,7 +4,7 @@ import { Store, StoreModule } from '@ngrx/store'; import { TranslateModule } from '@ngx-translate/core'; import { NgbCollapseModule } from '@ng-bootstrap/ng-bootstrap'; -import { Observable } from 'rxjs/Observable'; +import { Observable } from 'rxjs'; import { HeaderComponent } from './header.component'; import { HeaderState } from './header.reducer'; diff --git a/src/app/header/header.component.ts b/src/app/header/header.component.ts index 93cb329f4f..442f60612c 100644 --- a/src/app/header/header.component.ts +++ b/src/app/header/header.component.ts @@ -1,6 +1,6 @@ import { Component, OnInit } from '@angular/core'; import { createSelector, Store } from '@ngrx/store'; -import { Observable } from 'rxjs/Observable'; +import { Observable } from 'rxjs'; import { RouterReducerState } from '@ngrx/router-store'; import { HeaderState } from './header.reducer'; diff --git a/src/app/header/header.effects.spec.ts b/src/app/header/header.effects.spec.ts index e67043dcba..97b428bf8c 100644 --- a/src/app/header/header.effects.spec.ts +++ b/src/app/header/header.effects.spec.ts @@ -2,7 +2,7 @@ import { TestBed } from '@angular/core/testing'; import { HeaderEffects } from './header.effects'; import { HeaderCollapseAction } from './header.actions'; import { HostWindowResizeAction } from '../shared/host-window.actions'; -import { Observable } from 'rxjs/Observable'; +import { Observable } from 'rxjs'; import { provideMockActions } from '@ngrx/effects/testing'; import { cold, hot } from 'jasmine-marbles'; import * as fromRouter from '@ngrx/router-store'; diff --git a/src/app/shared/animations/slide.ts b/src/app/shared/animations/slide.ts index fa4a451863..ee16f9936f 100644 --- a/src/app/shared/animations/slide.ts +++ b/src/app/shared/animations/slide.ts @@ -1,4 +1,4 @@ -import { animate, state, transition, trigger, style, stagger, query } from '@angular/animations'; +import { animate, state, style, transition, trigger } from '@angular/animations'; export const slide = trigger('slide', [ diff --git a/src/app/shared/auth-nav-menu/auth-nav-menu.component.ts b/src/app/shared/auth-nav-menu/auth-nav-menu.component.ts index 1c376258fb..0cc9fb277a 100644 --- a/src/app/shared/auth-nav-menu/auth-nav-menu.component.ts +++ b/src/app/shared/auth-nav-menu/auth-nav-menu.component.ts @@ -1,5 +1,5 @@ import { Component, OnInit } from '@angular/core'; -import { Observable } from 'rxjs/Observable'; +import { Observable } from 'rxjs'; import { RouterReducerState } from '@ngrx/router-store'; import { Store } from '@ngrx/store'; diff --git a/src/app/shared/chips/models/chips.model.ts b/src/app/shared/chips/models/chips.model.ts index e133a416f4..9e6aa653e1 100644 --- a/src/app/shared/chips/models/chips.model.ts +++ b/src/app/shared/chips/models/chips.model.ts @@ -1,5 +1,5 @@ import { findIndex, isEqual, isObject } from 'lodash'; -import { BehaviorSubject } from 'rxjs/BehaviorSubject'; +import { BehaviorSubject } from 'rxjs'; import { ChipsItem, ChipsItemIcon } from './chips-item.model'; import { hasValue, isNotEmpty } from '../../empty.util'; diff --git a/src/app/shared/empty.util.ts b/src/app/shared/empty.util.ts index c1498d11af..d79c520fda 100644 --- a/src/app/shared/empty.util.ts +++ b/src/app/shared/empty.util.ts @@ -1,4 +1,4 @@ -import { Observable } from 'rxjs/Observable'; +import { Observable } from 'rxjs'; import { filter, map } from 'rxjs/operators'; /** diff --git a/src/app/shared/error/error.component.ts b/src/app/shared/error/error.component.ts index 08d06c31d6..6900869183 100644 --- a/src/app/shared/error/error.component.ts +++ b/src/app/shared/error/error.component.ts @@ -2,7 +2,7 @@ import { Component, Input } from '@angular/core'; import { TranslateService } from '@ngx-translate/core'; -import { Subscription } from 'rxjs/Subscription'; +import { Subscription } from 'rxjs'; @Component({ selector: 'ds-error', diff --git a/src/app/shared/form/builder/ds-dynamic-form-ui/models/date-picker/date-picker.model.ts b/src/app/shared/form/builder/ds-dynamic-form-ui/models/date-picker/date-picker.model.ts index a75a1d2f1a..214e2d1907 100644 --- a/src/app/shared/form/builder/ds-dynamic-form-ui/models/date-picker/date-picker.model.ts +++ b/src/app/shared/form/builder/ds-dynamic-form-ui/models/date-picker/date-picker.model.ts @@ -1,6 +1,6 @@ import { DynamicDateControlModel, DynamicFormControlLayout, serializable } from '@ng-dynamic-forms/core'; import { DynamicDateControlModelConfig } from '@ng-dynamic-forms/core/src/model/dynamic-date-control.model'; -import { Subject } from 'rxjs/Subject'; +import { Subject } from 'rxjs'; export const DYNAMIC_FORM_CONTROL_TYPE_DSDATEPICKER = 'DATE'; diff --git a/src/app/shared/form/builder/ds-dynamic-form-ui/models/ds-dynamic-input.model.ts b/src/app/shared/form/builder/ds-dynamic-form-ui/models/ds-dynamic-input.model.ts index f739c17cf3..860c481820 100644 --- a/src/app/shared/form/builder/ds-dynamic-form-ui/models/ds-dynamic-input.model.ts +++ b/src/app/shared/form/builder/ds-dynamic-form-ui/models/ds-dynamic-input.model.ts @@ -4,7 +4,7 @@ import { DynamicInputModelConfig, serializable } from '@ng-dynamic-forms/core'; -import { Subject } from 'rxjs/Subject'; +import { Subject } from 'rxjs'; import { LanguageCode } from '../../models/form-field-language-value.model'; import { AuthorityOptions } from '../../../../../core/integration/models/authority-options.model'; diff --git a/src/app/shared/form/builder/ds-dynamic-form-ui/models/ds-dynamic-qualdrop.model.ts b/src/app/shared/form/builder/ds-dynamic-form-ui/models/ds-dynamic-qualdrop.model.ts index bae79cc348..6bd5a604a0 100644 --- a/src/app/shared/form/builder/ds-dynamic-form-ui/models/ds-dynamic-qualdrop.model.ts +++ b/src/app/shared/form/builder/ds-dynamic-form-ui/models/ds-dynamic-qualdrop.model.ts @@ -1,6 +1,6 @@ import { DynamicFormControlLayout, DynamicFormGroupModel, DynamicInputModelConfig, serializable } from '@ng-dynamic-forms/core'; import { DsDynamicInputModel, DsDynamicInputModelConfig } from './ds-dynamic-input.model'; -import { Subject } from 'rxjs/Subject'; +import { Subject } from 'rxjs'; import { DynamicFormGroupModelConfig } from '@ng-dynamic-forms/core/src/model/form-group/dynamic-form-group.model'; import { LanguageCode } from '../../models/form-field-language-value.model'; diff --git a/src/app/shared/form/builder/ds-dynamic-form-ui/models/dynamic-group/dynamic-group.component.spec.ts b/src/app/shared/form/builder/ds-dynamic-form-ui/models/dynamic-group/dynamic-group.component.spec.ts index d1e6f67287..d9f821cc4d 100644 --- a/src/app/shared/form/builder/ds-dynamic-form-ui/models/dynamic-group/dynamic-group.component.spec.ts +++ b/src/app/shared/form/builder/ds-dynamic-form-ui/models/dynamic-group/dynamic-group.component.spec.ts @@ -6,7 +6,7 @@ import { FormControl, FormGroup, FormsModule, ReactiveFormsModule } from '@angul import { DynamicFormValidationService } from '@ng-dynamic-forms/core'; import { Store } from '@ngrx/store'; import { TranslateModule } from '@ngx-translate/core'; -import { Observable } from 'rxjs/Observable'; +import { Observable } from 'rxjs'; import 'rxjs/add/observable/of'; import { NgbModule } from '@ng-bootstrap/ng-bootstrap'; diff --git a/src/app/shared/form/builder/ds-dynamic-form-ui/models/dynamic-group/dynamic-group.components.ts b/src/app/shared/form/builder/ds-dynamic-form-ui/models/dynamic-group/dynamic-group.components.ts index a55e7aff9d..9387a69107 100644 --- a/src/app/shared/form/builder/ds-dynamic-form-ui/models/dynamic-group/dynamic-group.components.ts +++ b/src/app/shared/form/builder/ds-dynamic-form-ui/models/dynamic-group/dynamic-group.components.ts @@ -10,7 +10,7 @@ import { ViewChild } from '@angular/core'; -import { Observable } from 'rxjs/Observable'; +import { Observable , Subscription } from 'rxjs'; import { DynamicFormControlModel, DynamicFormGroupModel, DynamicInputModel } from '@ng-dynamic-forms/core'; import { isEqual } from 'lodash'; @@ -26,7 +26,6 @@ import { ChipsItem } from '../../../../../chips/models/chips-item.model'; import { GlobalConfig } from '../../../../../../../config/global-config.interface'; import { GLOBAL_CONFIG } from '../../../../../../../config'; import { FormGroup } from '@angular/forms'; -import { Subscription } from 'rxjs/Subscription'; import { hasOnlyEmptyProperties } from '../../../../../object.util'; import { FormFieldMetadataValueObject } from '../../../models/form-field-metadata-value.model'; import { AuthorityValueModel } from '../../../../../../core/integration/models/authority-value.model'; diff --git a/src/app/shared/form/builder/ds-dynamic-form-ui/models/list/dynamic-list-checkbox-group.model.ts b/src/app/shared/form/builder/ds-dynamic-form-ui/models/list/dynamic-list-checkbox-group.model.ts index 5fdc530ebd..ed9db8b1a5 100644 --- a/src/app/shared/form/builder/ds-dynamic-form-ui/models/list/dynamic-list-checkbox-group.model.ts +++ b/src/app/shared/form/builder/ds-dynamic-form-ui/models/list/dynamic-list-checkbox-group.model.ts @@ -1,4 +1,4 @@ -import { Subject } from 'rxjs/Subject'; +import { Subject } from 'rxjs'; import { DynamicCheckboxGroupModel, DynamicFormControlLayout, diff --git a/src/app/shared/form/builder/ds-dynamic-form-ui/models/lookup/dynamic-lookup.component.ts b/src/app/shared/form/builder/ds-dynamic-form-ui/models/lookup/dynamic-lookup.component.ts index 4e88e9c78e..8928b14ae5 100644 --- a/src/app/shared/form/builder/ds-dynamic-form-ui/models/lookup/dynamic-lookup.component.ts +++ b/src/app/shared/form/builder/ds-dynamic-form-ui/models/lookup/dynamic-lookup.component.ts @@ -7,7 +7,7 @@ import { IntegrationSearchOptions } from '../../../../../../core/integration/mod import { hasValue, isEmpty, isNotEmpty, isNull, isUndefined } from '../../../../../empty.util'; import { IntegrationData } from '../../../../../../core/integration/integration-data'; import { PageInfo } from '../../../../../../core/shared/page-info.model'; -import { Subscription } from 'rxjs/Subscription'; +import { Subscription } from 'rxjs'; import { FormFieldMetadataValueObject } from '../../../models/form-field-metadata-value.model'; import { AuthorityValueModel } from '../../../../../../core/integration/models/authority-value.model'; import { DynamicLookupNameModel } from './dynamic-lookup-name.model'; diff --git a/src/app/shared/form/builder/ds-dynamic-form-ui/models/tag/dynamic-tag.component.spec.ts b/src/app/shared/form/builder/ds-dynamic-form-ui/models/tag/dynamic-tag.component.spec.ts index 24959f4be4..9ef63e4d57 100644 --- a/src/app/shared/form/builder/ds-dynamic-form-ui/models/tag/dynamic-tag.component.spec.ts +++ b/src/app/shared/form/builder/ds-dynamic-form-ui/models/tag/dynamic-tag.component.spec.ts @@ -6,7 +6,7 @@ import { async, ComponentFixture, fakeAsync, flush, inject, TestBed, } from '@an import { DynamicFormsCoreModule } from '@ng-dynamic-forms/core'; import { DynamicFormsNGBootstrapUIModule } from '@ng-dynamic-forms/ui-ng-bootstrap'; import { NgbModule, NgbTypeaheadSelectItemEvent } from '@ng-bootstrap/ng-bootstrap'; -import { Observable } from 'rxjs/Observable'; +import { Observable } from 'rxjs'; import 'rxjs/add/observable/of' import { AuthorityOptions } from '../../../../../../core/integration/models/authority-options.model'; diff --git a/src/app/shared/form/builder/ds-dynamic-form-ui/models/tag/dynamic-tag.component.ts b/src/app/shared/form/builder/ds-dynamic-form-ui/models/tag/dynamic-tag.component.ts index ac23e665d0..318259f792 100644 --- a/src/app/shared/form/builder/ds-dynamic-form-ui/models/tag/dynamic-tag.component.ts +++ b/src/app/shared/form/builder/ds-dynamic-form-ui/models/tag/dynamic-tag.component.ts @@ -1,7 +1,7 @@ import { ChangeDetectorRef, Component, EventEmitter, Inject, Input, OnInit, Output } from '@angular/core'; import { FormGroup } from '@angular/forms'; -import { Observable } from 'rxjs/Observable'; +import { Observable } from 'rxjs'; import { NgbTypeaheadSelectItemEvent } from '@ng-bootstrap/ng-bootstrap'; import { AuthorityService } from '../../../../../../core/integration/authority.service'; diff --git a/src/app/shared/form/builder/ds-dynamic-form-ui/models/typeahead/dynamic-typeahead.component.spec.ts b/src/app/shared/form/builder/ds-dynamic-form-ui/models/typeahead/dynamic-typeahead.component.spec.ts index 2ed145b03a..c146615a99 100644 --- a/src/app/shared/form/builder/ds-dynamic-form-ui/models/typeahead/dynamic-typeahead.component.spec.ts +++ b/src/app/shared/form/builder/ds-dynamic-form-ui/models/typeahead/dynamic-typeahead.component.spec.ts @@ -4,7 +4,7 @@ import { FormControl, FormGroup, FormsModule, ReactiveFormsModule } from '@angul import { async, ComponentFixture, fakeAsync, inject, TestBed, } from '@angular/core/testing'; import { By } from '@angular/platform-browser'; -import { Observable } from 'rxjs/Observable'; +import { Observable } from 'rxjs'; import 'rxjs/add/observable/of'; import { AuthorityOptions } from '../../../../../../core/integration/models/authority-options.model'; diff --git a/src/app/shared/form/builder/ds-dynamic-form-ui/models/typeahead/dynamic-typeahead.component.ts b/src/app/shared/form/builder/ds-dynamic-form-ui/models/typeahead/dynamic-typeahead.component.ts index dade5d037a..dbaa8b4fcd 100644 --- a/src/app/shared/form/builder/ds-dynamic-form-ui/models/typeahead/dynamic-typeahead.component.ts +++ b/src/app/shared/form/builder/ds-dynamic-form-ui/models/typeahead/dynamic-typeahead.component.ts @@ -1,7 +1,7 @@ import { ChangeDetectorRef, Component, EventEmitter, Input, OnInit, Output } from '@angular/core'; import { FormGroup } from '@angular/forms'; -import { Observable } from 'rxjs/Observable'; +import { Observable } from 'rxjs'; import { NgbTypeaheadSelectItemEvent } from '@ng-bootstrap/ng-bootstrap'; import { AuthorityService } from '../../../../../../core/integration/authority.service'; diff --git a/src/app/shared/form/form.component.ts b/src/app/shared/form/form.component.ts index 54a39a80fa..c149b51d7b 100644 --- a/src/app/shared/form/form.component.ts +++ b/src/app/shared/form/form.component.ts @@ -20,8 +20,7 @@ import { FormStatusChangeAction } from './form.actions'; import { FormBuilderService } from './builder/form-builder.service'; -import { Observable } from 'rxjs/Observable'; -import { Subscription } from 'rxjs/Subscription'; +import { Observable , Subscription } from 'rxjs'; import { hasValue, isNotEmpty, isNotNull, isNull } from '../empty.util'; import { FormService } from './form.service'; import { formObjectFromIdSelector } from './selectors'; diff --git a/src/app/shared/form/form.service.ts b/src/app/shared/form/form.service.ts index d3f6c984ba..d9a1402ebd 100644 --- a/src/app/shared/form/form.service.ts +++ b/src/app/shared/form/form.service.ts @@ -1,6 +1,6 @@ import { Inject, Injectable } from '@angular/core'; import { AbstractControl, FormControl, FormGroup } from '@angular/forms'; -import { Observable } from 'rxjs/Observable'; +import { Observable } from 'rxjs'; import { Store } from '@ngrx/store'; import { AppState } from '../../app.reducer'; diff --git a/src/app/shared/host-window.service.spec.ts b/src/app/shared/host-window.service.spec.ts index 41be3211e9..b7dc58757b 100644 --- a/src/app/shared/host-window.service.spec.ts +++ b/src/app/shared/host-window.service.spec.ts @@ -1,6 +1,6 @@ import { Store } from '@ngrx/store'; import { cold, hot } from 'jasmine-marbles'; -import { Observable } from 'rxjs/Observable'; +import { Observable } from 'rxjs'; import { AppState } from '../app.reducer'; import { HostWindowState } from './host-window.reducer'; diff --git a/src/app/shared/host-window.service.ts b/src/app/shared/host-window.service.ts index ecbee685f1..3c26e717d2 100644 --- a/src/app/shared/host-window.service.ts +++ b/src/app/shared/host-window.service.ts @@ -2,7 +2,7 @@ import { distinctUntilChanged, map } from 'rxjs/operators'; import { HostWindowState } from './host-window.reducer'; import { Injectable } from '@angular/core'; import { createSelector, Store } from '@ngrx/store'; -import { Observable } from 'rxjs/Observable'; +import { Observable } from 'rxjs'; import { hasValue } from './empty.util'; import { AppState } from '../app.reducer'; diff --git a/src/app/shared/input-suggestions/input-suggestions.component.ts b/src/app/shared/input-suggestions/input-suggestions.component.ts index eb28583eaa..8a8069d71e 100644 --- a/src/app/shared/input-suggestions/input-suggestions.component.ts +++ b/src/app/shared/input-suggestions/input-suggestions.component.ts @@ -7,7 +7,7 @@ import { ViewChild, ViewChildren } from '@angular/core'; -import { BehaviorSubject } from 'rxjs/BehaviorSubject'; +import { BehaviorSubject } from 'rxjs'; import { hasValue, isNotEmpty } from '../empty.util'; @Component({ diff --git a/src/app/shared/loading/loading.component.ts b/src/app/shared/loading/loading.component.ts index 8276ab574a..b827bcc683 100644 --- a/src/app/shared/loading/loading.component.ts +++ b/src/app/shared/loading/loading.component.ts @@ -2,7 +2,7 @@ import { Component, Input, OnDestroy, OnInit } from '@angular/core'; import { TranslateService } from '@ngx-translate/core'; -import { Subscription } from 'rxjs/Subscription'; +import { Subscription } from 'rxjs'; @Component({ selector: 'ds-loading', diff --git a/src/app/shared/log-in/log-in.component.ts b/src/app/shared/log-in/log-in.component.ts index 3364b1067d..3b732e4bae 100644 --- a/src/app/shared/log-in/log-in.component.ts +++ b/src/app/shared/log-in/log-in.component.ts @@ -2,9 +2,9 @@ import { Component, OnDestroy, OnInit } from '@angular/core'; import { FormBuilder, FormGroup, Validators } from '@angular/forms'; import { Store } from '@ngrx/store'; -import { Observable } from 'rxjs/Observable'; -import 'rxjs/add/operator/filter'; -import 'rxjs/add/operator/takeWhile'; +import { Observable } from 'rxjs'; + + import { AuthenticateAction, ResetAuthenticationMessagesAction } from '../../core/auth/auth.actions'; diff --git a/src/app/shared/log-out/log-out.component.ts b/src/app/shared/log-out/log-out.component.ts index 37d0b142f9..3b821a0edc 100644 --- a/src/app/shared/log-out/log-out.component.ts +++ b/src/app/shared/log-out/log-out.component.ts @@ -15,7 +15,7 @@ import { } from '../../core/auth/selectors'; import { AppState } from '../../app.reducer'; -import { Observable } from 'rxjs/Observable'; +import { Observable } from 'rxjs'; import { fadeOut } from '../animations/fade'; @Component({ diff --git a/src/app/shared/mocks/mock-active-router.ts b/src/app/shared/mocks/mock-active-router.ts index 183d6c13d0..672cdcd8f6 100644 --- a/src/app/shared/mocks/mock-active-router.ts +++ b/src/app/shared/mocks/mock-active-router.ts @@ -1,6 +1,6 @@ import { Params } from '@angular/router'; -import { BehaviorSubject } from 'rxjs/BehaviorSubject'; +import { BehaviorSubject } from 'rxjs'; export class MockActivatedRoute { diff --git a/src/app/shared/mocks/mock-host-window-service.ts b/src/app/shared/mocks/mock-host-window-service.ts index e7d108407b..ac6b58f23a 100644 --- a/src/app/shared/mocks/mock-host-window-service.ts +++ b/src/app/shared/mocks/mock-host-window-service.ts @@ -1,4 +1,4 @@ -import { Observable } from 'rxjs/Observable'; +import { Observable } from 'rxjs'; // declare a stub service export class MockHostWindowService { diff --git a/src/app/shared/mocks/mock-item.ts b/src/app/shared/mocks/mock-item.ts index f6dd0be861..453b518c87 100644 --- a/src/app/shared/mocks/mock-item.ts +++ b/src/app/shared/mocks/mock-item.ts @@ -1,4 +1,4 @@ -import { Observable } from 'rxjs/Observable'; +import { Observable } from 'rxjs'; import { Item } from '../../core/shared/item.model'; diff --git a/src/app/shared/mocks/mock-remote-data-build.service.ts b/src/app/shared/mocks/mock-remote-data-build.service.ts index c10032eb94..cb01f65972 100644 --- a/src/app/shared/mocks/mock-remote-data-build.service.ts +++ b/src/app/shared/mocks/mock-remote-data-build.service.ts @@ -1,4 +1,4 @@ -import { Observable } from 'rxjs/Observable'; +import { Observable } from 'rxjs'; import { map, take } from 'rxjs/operators'; import { RemoteDataBuildService } from '../../core/cache/builders/remote-data-build.service'; import { ResponseCacheEntry } from '../../core/cache/response-cache.reducer'; diff --git a/src/app/shared/mocks/mock-request.service.ts b/src/app/shared/mocks/mock-request.service.ts index b4d8c693e5..c87ae3d3fe 100644 --- a/src/app/shared/mocks/mock-request.service.ts +++ b/src/app/shared/mocks/mock-request.service.ts @@ -1,4 +1,4 @@ -import { Observable } from 'rxjs/Observable'; +import { Observable } from 'rxjs'; import { RequestService } from '../../core/data/request.service'; import { RequestEntry } from '../../core/data/request.reducer'; diff --git a/src/app/shared/mocks/mock-response-cache.service.ts b/src/app/shared/mocks/mock-response-cache.service.ts index 2c21b07777..64c8356044 100644 --- a/src/app/shared/mocks/mock-response-cache.service.ts +++ b/src/app/shared/mocks/mock-response-cache.service.ts @@ -1,4 +1,4 @@ -import { Observable } from 'rxjs/Observable'; +import { Observable } from 'rxjs'; import { ResponseCacheEntry } from '../../core/cache/response-cache.reducer'; import { ResponseCacheService } from '../../core/cache/response-cache.service'; diff --git a/src/app/shared/mocks/mock-store.ts b/src/app/shared/mocks/mock-store.ts index 73c87d324a..c27133c586 100644 --- a/src/app/shared/mocks/mock-store.ts +++ b/src/app/shared/mocks/mock-store.ts @@ -1,5 +1,5 @@ import { Store } from '@ngrx/store'; -import { Observable } from 'rxjs/Observable'; +import { Observable } from 'rxjs'; export function getMockStore(): Store { return jasmine.createSpyObj('store', [ diff --git a/src/app/shared/mocks/mock-translate-loader.ts b/src/app/shared/mocks/mock-translate-loader.ts index 6e22066f8a..06a13ae70a 100644 --- a/src/app/shared/mocks/mock-translate-loader.ts +++ b/src/app/shared/mocks/mock-translate-loader.ts @@ -1,5 +1,5 @@ import { TranslateLoader } from '@ngx-translate/core'; -import { Observable } from 'rxjs/Observable'; +import { Observable } from 'rxjs'; export class MockTranslateLoader implements TranslateLoader { getTranslation(lang: string): Observable { diff --git a/src/app/shared/notifications/models/notification.model.ts b/src/app/shared/notifications/models/notification.model.ts index 3c7c54e156..98562a19b4 100644 --- a/src/app/shared/notifications/models/notification.model.ts +++ b/src/app/shared/notifications/models/notification.model.ts @@ -1,7 +1,7 @@ import { INotificationOptions, NotificationOptions } from './notification-options.model'; import { NotificationType } from './notification-type'; import { isEmpty } from '../../empty.util'; -import { Observable } from 'rxjs/Observable'; +import { Observable } from 'rxjs'; export interface INotification { id: string; diff --git a/src/app/shared/notifications/notification/notification.component.spec.ts b/src/app/shared/notifications/notification/notification.component.spec.ts index 600615fc39..e2a80f9f70 100644 --- a/src/app/shared/notifications/notification/notification.component.spec.ts +++ b/src/app/shared/notifications/notification/notification.component.spec.ts @@ -12,7 +12,7 @@ import { BrowserAnimationsModule } from '@angular/platform-browser/animations'; import { Router } from '@angular/router'; import { NotificationsServiceStub } from '../../testing/notifications-service-stub'; import { AppState } from '../../../app.reducer'; -import { Observable } from 'rxjs/Observable'; +import { Observable } from 'rxjs'; import { SearchPageComponent } from '../../../+search-page/search-page.component'; import { INotificationBoardOptions } from '../../../../config/notifications-config.interfaces'; import { GlobalConfig } from '../../../../config/global-config.interface'; diff --git a/src/app/shared/notifications/notification/notification.component.ts b/src/app/shared/notifications/notification/notification.component.ts index d80ec87750..f922ff590d 100644 --- a/src/app/shared/notifications/notification/notification.component.ts +++ b/src/app/shared/notifications/notification/notification.component.ts @@ -21,7 +21,7 @@ import { fromLeftEnter, fromLeftInState, fromLeftLeave, fromLeftOutState } from import { fromTopEnter, fromTopInState, fromTopLeave, fromTopOutState } from '../../animations/fromTop'; import { fadeInEnter, fadeInState, fadeOutLeave, fadeOutState } from '../../animations/fade'; import { NotificationAnimationsStatus } from '../models/notification-animations-type'; -import { Observable } from 'rxjs/Observable'; +import { Observable } from 'rxjs'; import { isNotEmpty } from '../../empty.util'; @Component({ diff --git a/src/app/shared/notifications/notifications-board/notifications-board.component.ts b/src/app/shared/notifications/notifications-board/notifications-board.component.ts index 59c9f04dbc..40ea52949a 100644 --- a/src/app/shared/notifications/notifications-board/notifications-board.component.ts +++ b/src/app/shared/notifications/notifications-board/notifications-board.component.ts @@ -9,7 +9,7 @@ import { } from '@angular/core'; import { Store } from '@ngrx/store'; -import { Subscription } from 'rxjs/Subscription'; +import { Subscription } from 'rxjs'; import { difference } from 'lodash'; import { NotificationsService } from '../notifications.service'; diff --git a/src/app/shared/notifications/notifications.service.spec.ts b/src/app/shared/notifications/notifications.service.spec.ts index e5af2860a1..e2820629c6 100644 --- a/src/app/shared/notifications/notifications.service.spec.ts +++ b/src/app/shared/notifications/notifications.service.spec.ts @@ -4,7 +4,7 @@ import { NotificationsBoardComponent } from './notifications-board/notifications import { NotificationComponent } from './notification/notification.component'; import { Store, StoreModule } from '@ngrx/store'; import { notificationsReducer } from './notifications.reducers'; -import { Observable } from 'rxjs/Observable'; +import { Observable } from 'rxjs'; import 'rxjs/add/observable/of'; import { NewNotificationAction, RemoveAllNotificationsAction, RemoveNotificationAction } from './notifications.actions'; import { Notification } from './models/notification.model'; diff --git a/src/app/shared/notifications/notifications.service.ts b/src/app/shared/notifications/notifications.service.ts index 92b6f58aed..8cf067f4de 100644 --- a/src/app/shared/notifications/notifications.service.ts +++ b/src/app/shared/notifications/notifications.service.ts @@ -5,7 +5,7 @@ import { NotificationOptions } from './models/notification-options.model'; import { uniqueId } from 'lodash'; import { Store } from '@ngrx/store'; import { NewNotificationAction, RemoveAllNotificationsAction, RemoveNotificationAction } from './notifications.actions'; -import { Observable } from 'rxjs/Observable'; +import { Observable } from 'rxjs'; import { GLOBAL_CONFIG, GlobalConfig } from '../../../config'; @Injectable() diff --git a/src/app/shared/object-collection/object-collection.component.spec.ts b/src/app/shared/object-collection/object-collection.component.spec.ts index 0548efc967..336cb13474 100644 --- a/src/app/shared/object-collection/object-collection.component.spec.ts +++ b/src/app/shared/object-collection/object-collection.component.spec.ts @@ -3,7 +3,7 @@ import { By } from '@angular/platform-browser'; import { async, ComponentFixture, TestBed } from '@angular/core/testing'; import { NO_ERRORS_SCHEMA } from '@angular/core'; import { ActivatedRoute, Router } from '@angular/router'; -import { Observable } from 'rxjs/Observable'; +import { Observable } from 'rxjs'; import { RouterStub } from '../testing/router-stub'; import { ViewMode } from '../../core/shared/view-mode.model'; diff --git a/src/app/shared/object-collection/object-collection.component.ts b/src/app/shared/object-collection/object-collection.component.ts index b4a436c5de..637b2f3a5f 100644 --- a/src/app/shared/object-collection/object-collection.component.ts +++ b/src/app/shared/object-collection/object-collection.component.ts @@ -4,7 +4,7 @@ import { Component, EventEmitter, Output, SimpleChanges, OnChanges, ChangeDetectorRef } from '@angular/core'; import { ActivatedRoute, Router } from '@angular/router'; -import { Observable } from 'rxjs/Observable'; +import { Observable } from 'rxjs'; import { RemoteData } from '../../core/data/remote-data'; import { PageInfo } from '../../core/shared/page-info.model'; diff --git a/src/app/shared/object-grid/item-grid-element/item-grid-element.component.spec.ts b/src/app/shared/object-grid/item-grid-element/item-grid-element.component.spec.ts index 0dd7f0be0a..245235e725 100644 --- a/src/app/shared/object-grid/item-grid-element/item-grid-element.component.spec.ts +++ b/src/app/shared/object-grid/item-grid-element/item-grid-element.component.spec.ts @@ -4,7 +4,7 @@ import { ChangeDetectionStrategy, NO_ERRORS_SCHEMA } from '@angular/core'; import { By } from '@angular/platform-browser'; import { TruncatePipe } from '../../utils/truncate.pipe'; import { Item } from '../../../core/shared/item.model'; -import { Observable } from 'rxjs/Observable'; +import { Observable } from 'rxjs'; let itemGridElementComponent: ItemGridElementComponent; let fixture: ComponentFixture; diff --git a/src/app/shared/object-grid/object-grid.component.ts b/src/app/shared/object-grid/object-grid.component.ts index 4c4add9b06..db600b48a9 100644 --- a/src/app/shared/object-grid/object-grid.component.ts +++ b/src/app/shared/object-grid/object-grid.component.ts @@ -6,8 +6,7 @@ import { Output, ViewEncapsulation } from '@angular/core'; -import { BehaviorSubject } from 'rxjs/BehaviorSubject'; -import { Observable } from 'rxjs/Observable'; +import { BehaviorSubject , Observable } from 'rxjs'; import { distinctUntilChanged, map } from 'rxjs/operators'; import { SortDirection, SortOptions } from '../../core/cache/models/sort-options.model'; diff --git a/src/app/shared/object-grid/search-result-grid-element/collection-search-result/collection-search-result-grid-element.component.spec.ts b/src/app/shared/object-grid/search-result-grid-element/collection-search-result/collection-search-result-grid-element.component.spec.ts index f3220baaa3..88c1fab8cd 100644 --- a/src/app/shared/object-grid/search-result-grid-element/collection-search-result/collection-search-result-grid-element.component.spec.ts +++ b/src/app/shared/object-grid/search-result-grid-element/collection-search-result/collection-search-result-grid-element.component.spec.ts @@ -1,6 +1,6 @@ import { CollectionSearchResultGridElementComponent } from './collection-search-result-grid-element.component'; import { async, ComponentFixture, TestBed } from '@angular/core/testing'; -import { Observable } from 'rxjs/Observable'; +import { Observable } from 'rxjs'; import { ChangeDetectionStrategy, NO_ERRORS_SCHEMA } from '@angular/core'; import { By } from '@angular/platform-browser'; import { TruncatePipe } from '../../../utils/truncate.pipe'; diff --git a/src/app/shared/object-grid/search-result-grid-element/community-search-result/community-search-result-grid-element.component.spec.ts b/src/app/shared/object-grid/search-result-grid-element/community-search-result/community-search-result-grid-element.component.spec.ts index aa62baadc9..06612b8a3f 100644 --- a/src/app/shared/object-grid/search-result-grid-element/community-search-result/community-search-result-grid-element.component.spec.ts +++ b/src/app/shared/object-grid/search-result-grid-element/community-search-result/community-search-result-grid-element.component.spec.ts @@ -1,6 +1,6 @@ import { CommunitySearchResultGridElementComponent } from './community-search-result-grid-element.component'; import { async, ComponentFixture, TestBed } from '@angular/core/testing'; -import { Observable } from 'rxjs/Observable'; +import { Observable } from 'rxjs'; import { ChangeDetectionStrategy, NO_ERRORS_SCHEMA } from '@angular/core'; import { By } from '@angular/platform-browser'; import { TruncatePipe } from '../../../utils/truncate.pipe'; diff --git a/src/app/shared/object-grid/search-result-grid-element/item-search-result/item-search-result-grid-element.component.spec.ts b/src/app/shared/object-grid/search-result-grid-element/item-search-result/item-search-result-grid-element.component.spec.ts index cf8a097ddb..839ec9271b 100644 --- a/src/app/shared/object-grid/search-result-grid-element/item-search-result/item-search-result-grid-element.component.spec.ts +++ b/src/app/shared/object-grid/search-result-grid-element/item-search-result/item-search-result-grid-element.component.spec.ts @@ -1,6 +1,6 @@ import { ItemSearchResultGridElementComponent } from './item-search-result-grid-element.component'; import { async, ComponentFixture, TestBed } from '@angular/core/testing'; -import { Observable } from 'rxjs/Observable'; +import { Observable } from 'rxjs'; import { NO_ERRORS_SCHEMA, ChangeDetectionStrategy } from '@angular/core'; import { By } from '@angular/platform-browser'; import { TruncatePipe } from '../../../utils/truncate.pipe'; diff --git a/src/app/shared/object-grid/search-result-grid-element/search-result-grid-element.component.ts b/src/app/shared/object-grid/search-result-grid-element/search-result-grid-element.component.ts index 5ab9f472b4..5fd1c87edd 100644 --- a/src/app/shared/object-grid/search-result-grid-element/search-result-grid-element.component.ts +++ b/src/app/shared/object-grid/search-result-grid-element/search-result-grid-element.component.ts @@ -7,7 +7,7 @@ import { isEmpty, hasNoValue, hasValue } from '../../empty.util'; import { AbstractListableElementComponent } from '../../object-collection/shared/object-collection-element/abstract-listable-element.component'; import { ListableObject } from '../../object-collection/shared/listable-object.model'; import { TruncatableService } from '../../truncatable/truncatable.service'; -import { Observable } from 'rxjs/Observable'; +import { Observable } from 'rxjs'; @Component({ selector: 'ds-search-result-grid-element', diff --git a/src/app/shared/object-grid/wrapper-grid-element/wrapper-grid-element.component.spec.ts b/src/app/shared/object-grid/wrapper-grid-element/wrapper-grid-element.component.spec.ts index 390b003e2e..cf98f7268c 100644 --- a/src/app/shared/object-grid/wrapper-grid-element/wrapper-grid-element.component.spec.ts +++ b/src/app/shared/object-grid/wrapper-grid-element/wrapper-grid-element.component.spec.ts @@ -1,6 +1,6 @@ import { WrapperGridElementComponent } from './wrapper-grid-element.component'; import { async, ComponentFixture, TestBed } from '@angular/core/testing'; -import { Observable } from 'rxjs/Observable'; +import { Observable } from 'rxjs'; import { ActivatedRoute, Router } from '@angular/router'; import { RouterStub } from '../../testing/router-stub'; import { NO_ERRORS_SCHEMA } from '@angular/core'; diff --git a/src/app/shared/object-list/item-list-element/item-list-element.component.spec.ts b/src/app/shared/object-list/item-list-element/item-list-element.component.spec.ts index fc40527693..1e77f56505 100644 --- a/src/app/shared/object-list/item-list-element/item-list-element.component.spec.ts +++ b/src/app/shared/object-list/item-list-element/item-list-element.component.spec.ts @@ -4,7 +4,7 @@ import { ChangeDetectionStrategy, NO_ERRORS_SCHEMA } from '@angular/core'; import { By } from '@angular/platform-browser'; import { TruncatePipe } from '../../utils/truncate.pipe'; import { Item } from '../../../core/shared/item.model'; -import { Observable } from 'rxjs/Observable'; +import { Observable } from 'rxjs'; let itemListElementComponent: ItemListElementComponent; let fixture: ComponentFixture; diff --git a/src/app/shared/object-list/search-result-list-element/collection-search-result/collection-search-result-list-element.component.spec.ts b/src/app/shared/object-list/search-result-list-element/collection-search-result/collection-search-result-list-element.component.spec.ts index 0395904070..fa73f8df3f 100644 --- a/src/app/shared/object-list/search-result-list-element/collection-search-result/collection-search-result-list-element.component.spec.ts +++ b/src/app/shared/object-list/search-result-list-element/collection-search-result/collection-search-result-list-element.component.spec.ts @@ -1,6 +1,6 @@ import { CollectionSearchResultListElementComponent } from './collection-search-result-list-element.component'; import { async, ComponentFixture, TestBed } from '@angular/core/testing'; -import { Observable } from 'rxjs/Observable'; +import { Observable } from 'rxjs'; import { ChangeDetectionStrategy, NO_ERRORS_SCHEMA } from '@angular/core'; import { By } from '@angular/platform-browser'; import { TruncatePipe } from '../../../utils/truncate.pipe'; diff --git a/src/app/shared/object-list/search-result-list-element/community-search-result/community-search-result-list-element.component.spec.ts b/src/app/shared/object-list/search-result-list-element/community-search-result/community-search-result-list-element.component.spec.ts index 54dde5dee6..8551d7b908 100644 --- a/src/app/shared/object-list/search-result-list-element/community-search-result/community-search-result-list-element.component.spec.ts +++ b/src/app/shared/object-list/search-result-list-element/community-search-result/community-search-result-list-element.component.spec.ts @@ -1,6 +1,6 @@ import { CommunitySearchResultListElementComponent } from './community-search-result-list-element.component'; import { async, ComponentFixture, TestBed } from '@angular/core/testing'; -import { Observable } from 'rxjs/Observable'; +import { Observable } from 'rxjs'; import { ChangeDetectionStrategy, NO_ERRORS_SCHEMA } from '@angular/core'; import { By } from '@angular/platform-browser'; import { TruncatePipe } from '../../../utils/truncate.pipe'; diff --git a/src/app/shared/object-list/search-result-list-element/item-search-result/item-search-result-list-element.component.spec.ts b/src/app/shared/object-list/search-result-list-element/item-search-result/item-search-result-list-element.component.spec.ts index f492c58483..674620eef5 100644 --- a/src/app/shared/object-list/search-result-list-element/item-search-result/item-search-result-list-element.component.spec.ts +++ b/src/app/shared/object-list/search-result-list-element/item-search-result/item-search-result-list-element.component.spec.ts @@ -1,6 +1,6 @@ import { ItemSearchResultListElementComponent } from './item-search-result-list-element.component'; import { async, ComponentFixture, TestBed } from '@angular/core/testing'; -import { Observable } from 'rxjs/Observable'; +import { Observable } from 'rxjs'; import { NO_ERRORS_SCHEMA, ChangeDetectionStrategy } from '@angular/core'; import { By } from '@angular/platform-browser'; import { TruncatePipe } from '../../../utils/truncate.pipe'; diff --git a/src/app/shared/object-list/search-result-list-element/search-result-list-element.component.ts b/src/app/shared/object-list/search-result-list-element/search-result-list-element.component.ts index fd821997ad..6a3b698dd6 100644 --- a/src/app/shared/object-list/search-result-list-element/search-result-list-element.component.ts +++ b/src/app/shared/object-list/search-result-list-element/search-result-list-element.component.ts @@ -1,5 +1,5 @@ import { Component, Inject } from '@angular/core'; -import { Observable } from 'rxjs/Observable'; +import { Observable } from 'rxjs'; import { SearchResult } from '../../../+search-page/search-result.model'; import { DSpaceObject } from '../../../core/shared/dspace-object.model'; diff --git a/src/app/shared/pagination/pagination.component.spec.ts b/src/app/shared/pagination/pagination.component.spec.ts index 1bd97086d8..7b340b2eed 100644 --- a/src/app/shared/pagination/pagination.component.spec.ts +++ b/src/app/shared/pagination/pagination.component.spec.ts @@ -20,7 +20,7 @@ import { RouterTestingModule } from '@angular/router/testing'; import { ActivatedRoute, Router } from '@angular/router'; import { By } from '@angular/platform-browser'; -import { Observable } from 'rxjs/Observable'; +import { Observable } from 'rxjs'; import { TranslateModule, TranslateLoader } from '@ngx-translate/core'; import { StoreModule } from '@ngrx/store'; diff --git a/src/app/shared/pagination/pagination.component.ts b/src/app/shared/pagination/pagination.component.ts index 3a1ba34e0c..cfed30b012 100644 --- a/src/app/shared/pagination/pagination.component.ts +++ b/src/app/shared/pagination/pagination.component.ts @@ -11,10 +11,8 @@ import { import { ActivatedRoute, Router } from '@angular/router'; -import { Subscription } from 'rxjs/Subscription'; -import { isNumeric } from 'rxjs/util/isNumeric'; - -import { Observable } from 'rxjs/Observable'; +import { Subscription , Observable } from 'rxjs'; +import { isNumeric } from 'rxjs/util'; import { HostWindowService } from '../host-window.service'; import { HostWindowState } from '../host-window.reducer'; diff --git a/src/app/shared/services/api.service.ts b/src/app/shared/services/api.service.ts index 90c79d132e..96e1007f37 100644 --- a/src/app/shared/services/api.service.ts +++ b/src/app/shared/services/api.service.ts @@ -1,9 +1,6 @@ -import 'rxjs/add/observable/throw'; -import 'rxjs/add/operator/catch'; - +import { throwError as observableThrowError } from 'rxjs'; import { Injectable } from '@angular/core'; import { HttpClient } from '@angular/common/http'; -import { Observable } from 'rxjs/Observable'; @Injectable() export class ApiService { @@ -18,7 +15,7 @@ export class ApiService { return this._http.get(url, options) .catch((err) => { console.log('Error: ', err); - return Observable.throw(err); + return observableThrowError(err); }); } diff --git a/src/app/shared/services/cookie.service.ts b/src/app/shared/services/cookie.service.ts index 8265651d81..aaae800a6e 100644 --- a/src/app/shared/services/cookie.service.ts +++ b/src/app/shared/services/cookie.service.ts @@ -2,8 +2,7 @@ import { Inject, Injectable } from '@angular/core' import { REQUEST } from '@nguniversal/express-engine/tokens' -import { Subject } from 'rxjs/Subject' -import { Observable } from 'rxjs/Observable' +import { Subject , Observable } from 'rxjs' import { CookieAttributes } from 'js-cookie' export interface ICookieService { diff --git a/src/app/shared/services/route.service.spec.ts b/src/app/shared/services/route.service.spec.ts index b134771b3e..3d0f31573d 100644 --- a/src/app/shared/services/route.service.spec.ts +++ b/src/app/shared/services/route.service.spec.ts @@ -1,7 +1,7 @@ import { RouteService } from './route.service'; import { async, TestBed } from '@angular/core/testing'; import { ActivatedRoute, convertToParamMap, Params } from '@angular/router'; -import { Observable } from 'rxjs/Observable'; +import { Observable } from 'rxjs'; describe('RouteService', () => { let service: RouteService; diff --git a/src/app/shared/services/route.service.ts b/src/app/shared/services/route.service.ts index 7c24c6f6c1..fcb6f80f29 100644 --- a/src/app/shared/services/route.service.ts +++ b/src/app/shared/services/route.service.ts @@ -1,5 +1,5 @@ import { Injectable } from '@angular/core'; -import { Observable } from 'rxjs/Observable'; +import { Observable } from 'rxjs'; import { ActivatedRoute, convertToParamMap, NavigationExtras, Params, Router, diff --git a/src/app/shared/testing/active-router-stub.ts b/src/app/shared/testing/active-router-stub.ts index 22c4060855..e09ff2299a 100644 --- a/src/app/shared/testing/active-router-stub.ts +++ b/src/app/shared/testing/active-router-stub.ts @@ -1,6 +1,6 @@ import { convertToParamMap, ParamMap, Params } from '@angular/router'; -import { BehaviorSubject } from 'rxjs/BehaviorSubject'; +import { BehaviorSubject } from 'rxjs'; export class ActivatedRouteStub { diff --git a/src/app/shared/testing/auth-request-service-stub.ts b/src/app/shared/testing/auth-request-service-stub.ts index 2c47068af4..8a38fff9e7 100644 --- a/src/app/shared/testing/auth-request-service-stub.ts +++ b/src/app/shared/testing/auth-request-service-stub.ts @@ -1,4 +1,4 @@ -import { Observable } from 'rxjs/Observable'; +import { Observable } from 'rxjs'; import { HttpOptions } from '../../core/dspace-rest-v2/dspace-rest-v2.service'; import { AuthStatus } from '../../core/auth/models/auth-status.model'; import { AuthTokenInfo } from '../../core/auth/models/auth-token-info.model'; diff --git a/src/app/shared/testing/auth-service-stub.ts b/src/app/shared/testing/auth-service-stub.ts index c7d5556910..2746eb392e 100644 --- a/src/app/shared/testing/auth-service-stub.ts +++ b/src/app/shared/testing/auth-service-stub.ts @@ -1,5 +1,5 @@ import { AuthStatus } from '../../core/auth/models/auth-status.model'; -import { Observable } from 'rxjs/Observable'; +import { Observable } from 'rxjs'; import { AuthTokenInfo } from '../../core/auth/models/auth-token-info.model'; import { EpersonMock } from './eperson-mock'; import { Eperson } from '../../core/eperson/models/eperson.model'; diff --git a/src/app/shared/testing/authority-service-stub.ts b/src/app/shared/testing/authority-service-stub.ts index 0bc8179fe3..cc74708172 100644 --- a/src/app/shared/testing/authority-service-stub.ts +++ b/src/app/shared/testing/authority-service-stub.ts @@ -1,4 +1,4 @@ -import { Observable } from 'rxjs/Observable'; +import { Observable } from 'rxjs'; import { IntegrationSearchOptions } from '../../core/integration/models/integration-options.model'; import { IntegrationData } from '../../core/integration/integration-data'; import { PageInfo } from '../../core/shared/page-info.model'; diff --git a/src/app/shared/testing/hal-endpoint-service-stub.ts b/src/app/shared/testing/hal-endpoint-service-stub.ts index a1764df009..deefef7f2a 100644 --- a/src/app/shared/testing/hal-endpoint-service-stub.ts +++ b/src/app/shared/testing/hal-endpoint-service-stub.ts @@ -1,4 +1,4 @@ -import { Observable } from 'rxjs/Observable'; +import { Observable } from 'rxjs'; export class HALEndpointServiceStub { diff --git a/src/app/shared/testing/host-window-service-stub.ts b/src/app/shared/testing/host-window-service-stub.ts index 2833415477..df1bb567fc 100644 --- a/src/app/shared/testing/host-window-service-stub.ts +++ b/src/app/shared/testing/host-window-service-stub.ts @@ -1,4 +1,4 @@ -import { Observable } from 'rxjs/Observable'; +import { Observable } from 'rxjs'; // declare a stub service export class HostWindowServiceStub { diff --git a/src/app/shared/testing/mock-store.ts b/src/app/shared/testing/mock-store.ts index a3bca3c1b5..f366ad45ab 100644 --- a/src/app/shared/testing/mock-store.ts +++ b/src/app/shared/testing/mock-store.ts @@ -1,6 +1,5 @@ import { Action } from '@ngrx/store'; -import { Observable } from 'rxjs/Observable'; -import { BehaviorSubject } from 'rxjs/BehaviorSubject'; +import { Observable , BehaviorSubject } from 'rxjs'; export class MockStore extends BehaviorSubject { diff --git a/src/app/shared/testing/mock-translate-loader.ts b/src/app/shared/testing/mock-translate-loader.ts index 6e22066f8a..06a13ae70a 100644 --- a/src/app/shared/testing/mock-translate-loader.ts +++ b/src/app/shared/testing/mock-translate-loader.ts @@ -1,5 +1,5 @@ import { TranslateLoader } from '@ngx-translate/core'; -import { Observable } from 'rxjs/Observable'; +import { Observable } from 'rxjs'; export class MockTranslateLoader implements TranslateLoader { getTranslation(lang: string): Observable { diff --git a/src/app/shared/testing/notifications-service-stub.ts b/src/app/shared/testing/notifications-service-stub.ts index 5629a05a96..d8ec867fea 100644 --- a/src/app/shared/testing/notifications-service-stub.ts +++ b/src/app/shared/testing/notifications-service-stub.ts @@ -1,4 +1,4 @@ -import { Observable } from 'rxjs/Observable'; +import { Observable } from 'rxjs'; import { INotification } from '../notifications/models/notification.model'; import { NotificationOptions } from '../notifications/models/notification-options.model'; diff --git a/src/app/shared/testing/search-service-stub.ts b/src/app/shared/testing/search-service-stub.ts index b9c1d7533f..f58e6df954 100644 --- a/src/app/shared/testing/search-service-stub.ts +++ b/src/app/shared/testing/search-service-stub.ts @@ -1,5 +1,4 @@ -import { Observable } from 'rxjs/Observable'; -import { BehaviorSubject } from 'rxjs/BehaviorSubject'; +import { Observable, BehaviorSubject } from 'rxjs'; import { ViewMode } from '../../core/shared/view-mode.model'; export class SearchServiceStub { diff --git a/src/app/shared/truncatable/truncatable-part/truncatable-part.component.spec.ts b/src/app/shared/truncatable/truncatable-part/truncatable-part.component.spec.ts index 4c3af4cd7d..bc9dc6dabf 100644 --- a/src/app/shared/truncatable/truncatable-part/truncatable-part.component.spec.ts +++ b/src/app/shared/truncatable/truncatable-part/truncatable-part.component.spec.ts @@ -1,5 +1,5 @@ import { async, ComponentFixture, TestBed } from '@angular/core/testing'; -import { Observable } from 'rxjs/Observable'; +import { Observable } from 'rxjs'; import { TruncatablePartComponent } from './truncatable-part.component'; import { TruncatableService } from '../truncatable.service'; import { ChangeDetectionStrategy, NO_ERRORS_SCHEMA } from '@angular/core'; diff --git a/src/app/shared/truncatable/truncatable.component.spec.ts b/src/app/shared/truncatable/truncatable.component.spec.ts index 3c2ce7150a..a9de30461e 100644 --- a/src/app/shared/truncatable/truncatable.component.spec.ts +++ b/src/app/shared/truncatable/truncatable.component.spec.ts @@ -1,5 +1,5 @@ import { async, ComponentFixture, TestBed } from '@angular/core/testing'; -import { Observable } from 'rxjs/Observable'; +import { Observable } from 'rxjs'; import { TruncatableComponent } from './truncatable.component'; import { TruncatableService } from './truncatable.service'; import { ChangeDetectionStrategy, NO_ERRORS_SCHEMA } from '@angular/core'; diff --git a/src/app/shared/truncatable/truncatable.service.spec.ts b/src/app/shared/truncatable/truncatable.service.spec.ts index dafa889b87..60982c9a4f 100644 --- a/src/app/shared/truncatable/truncatable.service.spec.ts +++ b/src/app/shared/truncatable/truncatable.service.spec.ts @@ -1,6 +1,6 @@ import { Store } from '@ngrx/store'; import { async, TestBed } from '@angular/core/testing'; -import { Observable } from 'rxjs/Observable'; +import { Observable } from 'rxjs'; import { TruncatableService } from './truncatable.service'; import { TruncatableCollapseAction, TruncatableExpandAction } from './truncatable.actions'; import { TruncatablesState } from './truncatable.reducer'; diff --git a/src/app/shared/truncatable/truncatable.service.ts b/src/app/shared/truncatable/truncatable.service.ts index 2f707d6609..c25bf30c27 100644 --- a/src/app/shared/truncatable/truncatable.service.ts +++ b/src/app/shared/truncatable/truncatable.service.ts @@ -1,6 +1,6 @@ import { Injectable } from '@angular/core'; import { createSelector, MemoizedSelector, Store } from '@ngrx/store'; -import { Observable } from 'rxjs/Observable'; +import { Observable } from 'rxjs'; import { TruncatablesState, TruncatableState } from './truncatable.reducer'; import { TruncatableExpandAction, TruncatableToggleAction, TruncatableCollapseAction } from './truncatable.actions'; import { hasValue } from '../empty.util'; diff --git a/src/app/shared/uploader/uploader.component.ts b/src/app/shared/uploader/uploader.component.ts index 476ba510e0..ac3e701ca2 100644 --- a/src/app/shared/uploader/uploader.component.ts +++ b/src/app/shared/uploader/uploader.component.ts @@ -10,7 +10,7 @@ import { } from '@angular/core' import { FileUploader } from 'ng2-file-upload'; -import { Observable } from 'rxjs/Observable'; +import { Observable } from 'rxjs'; import { uniqueId } from 'lodash'; import { ScrollToConfigOptions, ScrollToService } from '@nicky-lenaers/ngx-scroll-to'; diff --git a/src/app/shared/utils/debounce.directive.ts b/src/app/shared/utils/debounce.directive.ts index 6a39a598c0..3e6b0e6d22 100644 --- a/src/app/shared/utils/debounce.directive.ts +++ b/src/app/shared/utils/debounce.directive.ts @@ -1,9 +1,9 @@ import { Directive, Input, Output, EventEmitter, OnDestroy, OnInit } from '@angular/core'; import { NgControl } from '@angular/forms'; -import 'rxjs/add/operator/debounceTime'; -import 'rxjs/add/operator/distinctUntilChanged'; -import 'rxjs/add/operator/takeUntil'; -import { Subject } from 'rxjs/Subject'; + + + +import { Subject } from 'rxjs'; @Directive({ selector: '[ngModel][dsDebounce]', diff --git a/src/app/shared/view-mode-switch/view-mode-switch.component.ts b/src/app/shared/view-mode-switch/view-mode-switch.component.ts index d34a4b4d60..07c47435ff 100644 --- a/src/app/shared/view-mode-switch/view-mode-switch.component.ts +++ b/src/app/shared/view-mode-switch/view-mode-switch.component.ts @@ -1,4 +1,4 @@ -import { Subscription } from 'rxjs/Subscription'; +import { Subscription } from 'rxjs'; import { Component, OnInit, OnDestroy } from '@angular/core'; import { SearchService } from './../../+search-page/search-service/search.service'; import { ViewMode } from '../../core/shared/view-mode.model'; diff --git a/src/app/store.effects.ts b/src/app/store.effects.ts index ae5f97646d..f264c0f9bd 100644 --- a/src/app/store.effects.ts +++ b/src/app/store.effects.ts @@ -1,10 +1,10 @@ -import 'rxjs/add/operator/withLatestFrom'; + import { Injectable } from '@angular/core'; import { Action, Store } from '@ngrx/store'; import { Effect, Actions } from '@ngrx/effects'; -import { Observable } from 'rxjs/Observable'; +import { Observable } from 'rxjs'; import { AppState } from './app.reducer'; import { StoreAction, StoreActionTypes } from './store.actions'; diff --git a/src/modules/app/server-app.module.ts b/src/modules/app/server-app.module.ts index 10285e75f5..18f9865660 100644 --- a/src/modules/app/server-app.module.ts +++ b/src/modules/app/server-app.module.ts @@ -5,8 +5,8 @@ import { ServerModule } from '@angular/platform-server'; import { RouterModule } from '@angular/router'; import { TranslateLoader, TranslateModule } from '@ngx-translate/core'; -import 'rxjs/add/operator/filter'; -import 'rxjs/add/operator/first'; + + import { AppComponent } from '../../app/app.component'; diff --git a/src/modules/translate-universal-loader.ts b/src/modules/translate-universal-loader.ts index d569ef192d..b2efaf2395 100644 --- a/src/modules/translate-universal-loader.ts +++ b/src/modules/translate-universal-loader.ts @@ -1,5 +1,5 @@ import { TranslateLoader } from '@ngx-translate/core'; -import { Observable } from 'rxjs/Observable'; +import { Observable } from 'rxjs'; import * as fs from 'fs'; export class TranslateUniversalLoader implements TranslateLoader { diff --git a/src/server.ts b/src/server.ts index 040d13311f..0e68e4f139 100644 --- a/src/server.ts +++ b/src/server.ts @@ -1,6 +1,6 @@ import 'zone.js/dist/zone-node'; import 'reflect-metadata'; -import 'rxjs/Rx'; +import 'rxjs'; import * as fs from 'fs'; import * as pem from 'pem'; diff --git a/tslint.json b/tslint.json index aff156ec42..cd7ffadac9 100644 --- a/tslint.json +++ b/tslint.json @@ -16,8 +16,7 @@ "eofline": true, "forin": true, "import-blacklist": [ - true, - "rxjs" + true ], "import-spacing": true, "indent": [ @@ -152,6 +151,10 @@ "use-input-property-decorator": true, "use-life-cycle-interface": false, "use-output-property-decorator": true, - "use-pipe-transform-interface": true + "use-pipe-transform-interface": true, + "rxjs-collapse-imports": true, + "rxjs-pipeable-operators-only": true, + "rxjs-no-static-observable-methods": true, + "rxjs-proper-imports": true } } diff --git a/webpack.config.js b/webpack.config.js index 1ba63a19cc..c867ce48ea 100644 --- a/webpack.config.js +++ b/webpack.config.js @@ -8,9 +8,8 @@ const { getAotPlugin } = require('./webpack/webpack.aot'); -module.exports = function(options, webpackOptions) { +module.exports = function(options) { options = options || {}; - if (options.aot) { console.log(`Running build for ${options.client ? 'client' : 'server'} with AoT Compilation`) } @@ -29,7 +28,7 @@ module.exports = function(options, webpackOptions) { ] }); - if (webpackOptions.p) { + if (options.mode === 'production') { serverConfig = webpackMerge({}, serverConfig, prodPartial); clientConfig = webpackMerge({}, clientConfig, prodPartial); } diff --git a/webpack/webpack.common.js b/webpack/webpack.common.js index 3cbfe5c648..d2ba6b8776 100644 --- a/webpack/webpack.common.js +++ b/webpack/webpack.common.js @@ -6,6 +6,7 @@ const { } = require('./helpers'); module.exports = { + mode: 'development', devtool: 'source-map', resolve: { extensions: ['.ts', '.js', '.json'] diff --git a/webpack/webpack.prod.js b/webpack/webpack.prod.js index 434296ff09..ab2c6a7585 100644 --- a/webpack/webpack.prod.js +++ b/webpack/webpack.prod.js @@ -1,60 +1,68 @@ const webpack = require('webpack'); const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin; const CompressionPlugin = require("compression-webpack-plugin"); +const UglifyJsPlugin = require('uglifyjs-webpack-plugin'); const { - root + root } = require('./helpers'); module.exports = { - recordsOutputPath: root('webpack.records.json'), - plugins: [ - new webpack.DefinePlugin({ - 'process.env.NODE_ENV': JSON.stringify('production'), - 'process.env.AOT': true - }), + mode: 'production', + recordsOutputPath: root('webpack.records.json'), + plugins: [ + new webpack.DefinePlugin({ + 'process.env.NODE_ENV': JSON.stringify('production'), + 'process.env.AOT': true + }), - // Loader options - new webpack.LoaderOptionsPlugin({ - minimize: true, - debug: false - }), + // Loader options + new webpack.LoaderOptionsPlugin({ + minimize: true, + debug: false + }), - new BundleAnalyzerPlugin({ - analyzerMode: 'disabled', // change it to `server` to view bundle stats - reportFilename: 'report.html', - generateStatsFile: true, - statsFilename: 'stats.json', - }), + new BundleAnalyzerPlugin({ + analyzerMode: 'disabled', // change it to `server` to view bundle stats + reportFilename: 'report.html', + generateStatsFile: true, + statsFilename: 'stats.json', + }), - new webpack.optimize.UglifyJsPlugin({ - beautify: false, - mangle: false, - output: { - comments: false - }, - compress: { - warnings: false, - conditionals: false, - unused: true, - comparisons: true, - sequences: true, - dead_code: true, - evaluate: true, - if_return: true, - join_vars: true, - negate_iife: true - }, - sourceMap: true - }), - new CompressionPlugin({ - asset: "[path].gz[query]", - algorithm: "gzip", - test: /\.js$|\.css$|\.html$/, - threshold: 10240, - minRatio: 0.8 - }) + new CompressionPlugin({ + asset: "[path].gz[query]", + algorithm: "gzip", + test: /\.js$|\.css$|\.html$/, + threshold: 10240, + minRatio: 0.8 + }) - ] + ], + optimization: { + minimize: [ + new UglifyJsPlugin({ + uglifyOptions: { + beautify: false, + mangle: false, + output: { + comments: false + }, + compress: { + warnings: false, + conditionals: false, + unused: true, + comparisons: true, + sequences: true, + dead_code: true, + evaluate: true, + if_return: true, + join_vars: true, + negate_iife: true + }, + sourceMap: true + } + }) + ] + }, }; diff --git a/yarn.lock b/yarn.lock index 344093d446..561cdcf27d 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2,137 +2,159 @@ # yarn lockfile v1 -"@angular/animations@^5.2.5": - version "5.2.5" - resolved "https://registry.yarnpkg.com/@angular/animations/-/animations-5.2.5.tgz#3e72184321c4979305619c74902b8be92d76db70" +"@angular-devkit/core@0.7.5": + version "0.7.5" + resolved "https://registry.yarnpkg.com/@angular-devkit/core/-/core-0.7.5.tgz#49f7854ccadf3ddda8d0ea4359543a1cbdc6854d" dependencies: - tslib "^1.7.1" + ajv "~6.4.0" + chokidar "^2.0.3" + rxjs "^6.0.0" + source-map "^0.5.6" -"@angular/common@^5.2.5": - version "5.2.5" - resolved "https://registry.yarnpkg.com/@angular/common/-/common-5.2.5.tgz#08dd636fa46077d047066b13a1aae494066f6c55" +"@angular/animations@^6.1.4": + version "6.1.4" + resolved "https://registry.yarnpkg.com/@angular/animations/-/animations-6.1.4.tgz#ca17acd62b9328404671a569fbf3065472527174" dependencies: - tslib "^1.7.1" + tslib "^1.9.0" -"@angular/compiler-cli@^5.2.5": - version "5.2.5" - resolved "https://registry.yarnpkg.com/@angular/compiler-cli/-/compiler-cli-5.2.5.tgz#b1988bb2c0a956e7fc163acf8c7d794a07a88d08" +"@angular/common@^6.1.4": + version "6.1.4" + resolved "https://registry.yarnpkg.com/@angular/common/-/common-6.1.4.tgz#825de5b1fb98db5a1d3d2253ad7181bb25477551" + dependencies: + tslib "^1.9.0" + +"@angular/compiler-cli@^6.1.4": + version "6.1.4" + resolved "https://registry.yarnpkg.com/@angular/compiler-cli/-/compiler-cli-6.1.4.tgz#65f4c4382bb180d22905db57e28a4ca728b7bf8c" dependencies: chokidar "^1.4.2" minimist "^1.2.0" reflect-metadata "^0.1.2" - tsickle "^0.26.0" + tsickle "^0.32.1" -"@angular/compiler@^5.2.5": - version "5.2.5" - resolved "https://registry.yarnpkg.com/@angular/compiler/-/compiler-5.2.5.tgz#5e3b511906048a579fcd007aba72911472e5aa28" +"@angular/compiler@^6.1.4": + version "6.1.4" + resolved "https://registry.yarnpkg.com/@angular/compiler/-/compiler-6.1.4.tgz#479e792ce012dc8481f1d87b919fcddb11c8eee0" dependencies: - tslib "^1.7.1" + tslib "^1.9.0" -"@angular/core@^5.2.5": - version "5.2.5" - resolved "https://registry.yarnpkg.com/@angular/core/-/core-5.2.5.tgz#24f9cd75c5b2728f2ddd1869777590ea7177bca9" +"@angular/core@^6.1.4": + version "6.1.4" + resolved "https://registry.yarnpkg.com/@angular/core/-/core-6.1.4.tgz#2602ecc031bbb4ad968a7db78786017e92d19b98" dependencies: - tslib "^1.7.1" + tslib "^1.9.0" -"@angular/forms@^5.2.5": - version "5.2.5" - resolved "https://registry.yarnpkg.com/@angular/forms/-/forms-5.2.5.tgz#2ad7a420c6ef6cd87a34071c5319ec83f7ed56aa" +"@angular/forms@^6.1.4": + version "6.1.4" + resolved "https://registry.yarnpkg.com/@angular/forms/-/forms-6.1.4.tgz#d0b83f9cd4cb35f58ee67766d17aae0cbd7de561" dependencies: - tslib "^1.7.1" + tslib "^1.9.0" -"@angular/http@^5.2.5": - version "5.2.5" - resolved "https://registry.yarnpkg.com/@angular/http/-/http-5.2.5.tgz#1208256e36f0e486d96d10a733fdc8424ffa16bf" +"@angular/http@^6.1.4": + version "6.1.4" + resolved "https://registry.yarnpkg.com/@angular/http/-/http-6.1.4.tgz#0ab24a51075daaba60a4241200c44dcfcd87da5e" dependencies: - tslib "^1.7.1" + tslib "^1.9.0" -"@angular/platform-browser-dynamic@^5.2.5": - version "5.2.5" - resolved "https://registry.yarnpkg.com/@angular/platform-browser-dynamic/-/platform-browser-dynamic-5.2.5.tgz#b89df410bd953e2a6843325f9ac3c09a10eadaf0" +"@angular/platform-browser-dynamic@^6.1.4": + version "6.1.4" + resolved "https://registry.yarnpkg.com/@angular/platform-browser-dynamic/-/platform-browser-dynamic-6.1.4.tgz#1af3549decadfb8e73513d917eaa5479184c39ea" dependencies: - tslib "^1.7.1" + tslib "^1.9.0" -"@angular/platform-browser@^5.2.5": - version "5.2.5" - resolved "https://registry.yarnpkg.com/@angular/platform-browser/-/platform-browser-5.2.5.tgz#eae4af2b742fb901d84d6367cd99f9e88102151f" +"@angular/platform-browser@^6.1.4": + version "6.1.4" + resolved "https://registry.yarnpkg.com/@angular/platform-browser/-/platform-browser-6.1.4.tgz#a5763f549f2073ba30b9d8baf8512c8076e8d58b" dependencies: - tslib "^1.7.1" + tslib "^1.9.0" -"@angular/platform-server@^5.2.5": - version "5.2.5" - resolved "https://registry.yarnpkg.com/@angular/platform-server/-/platform-server-5.2.5.tgz#2111bfd836a16c787a10f2099a0c26b6a3a02b05" +"@angular/platform-server@^6.1.4": + version "6.1.4" + resolved "https://registry.yarnpkg.com/@angular/platform-server/-/platform-server-6.1.4.tgz#df9fb37ad58605159f2aa1f777c6260491858c3f" dependencies: - domino "^1.0.29" - tslib "^1.7.1" + domino "^2.0.1" + tslib "^1.9.0" xhr2 "^0.1.4" -"@angular/router@^5.2.5": - version "5.2.5" - resolved "https://registry.yarnpkg.com/@angular/router/-/router-5.2.5.tgz#f8f220d5fb85fc10d60fe606b0f2a64732265142" +"@angular/router@^6.1.4": + version "6.1.4" + resolved "https://registry.yarnpkg.com/@angular/router/-/router-6.1.4.tgz#ec6d7400baea46386e3bbcf3e3acb0135f368fac" dependencies: - tslib "^1.7.1" + tslib "^1.9.0" "@angularclass/bootloader@1.0.1": version "1.0.1" resolved "https://registry.yarnpkg.com/@angularclass/bootloader/-/bootloader-1.0.1.tgz#75de7cf3901b445900a419c2aeca44181d465060" -"@ng-bootstrap/ng-bootstrap@^1.0.0": - version "1.0.0" - resolved "https://registry.yarnpkg.com/@ng-bootstrap/ng-bootstrap/-/ng-bootstrap-1.0.0.tgz#8f2ae70db2fe1dcbf5e0acb49dc2b1bbba2be8d2" - -"@ng-dynamic-forms/core@5.4.7": - version "5.4.7" - resolved "https://registry.yarnpkg.com/@ng-dynamic-forms/core/-/core-5.4.7.tgz#203dffe4bb31a3599e906990ad9dc2b35714e37a" - -"@ng-dynamic-forms/ui-ng-bootstrap@5.4.7": - version "5.4.7" - resolved "https://registry.yarnpkg.com/@ng-dynamic-forms/ui-ng-bootstrap/-/ui-ng-bootstrap-5.4.7.tgz#66d037a226da96fe84c4dbac98e4dba859c551f8" - -"@ngrx/effects@^5.1.0": - version "5.1.0" - resolved "https://registry.yarnpkg.com/@ngrx/effects/-/effects-5.1.0.tgz#cef84576b2d0333f19188aedfe156fd301bff70a" - -"@ngrx/router-store@^5.0.1": - version "5.0.1" - resolved "https://registry.yarnpkg.com/@ngrx/router-store/-/router-store-5.0.1.tgz#db872327bb958a2ebf296734c97de68672ec628a" - -"@ngrx/store-devtools@^5.1.0": - version "5.1.0" - resolved "https://registry.yarnpkg.com/@ngrx/store-devtools/-/store-devtools-5.1.0.tgz#7df8a6da652cc792000ad058ca4072a32e3629b1" - -"@ngrx/store@^5.1.0": - version "5.1.0" - resolved "https://registry.yarnpkg.com/@ngrx/store/-/store-5.1.0.tgz#d957131e62041deede043524fd300db9fa835d68" - -"@ngtools/webpack@^1.10.0": - version "1.10.0" - resolved "https://registry.yarnpkg.com/@ngtools/webpack/-/webpack-1.10.0.tgz#1e4f60bdba8cdb8aeb93ebb976e63bf175acd279" +"@mrmlnc/readdir-enhanced@^2.2.1": + version "2.2.1" + resolved "https://registry.yarnpkg.com/@mrmlnc/readdir-enhanced/-/readdir-enhanced-2.2.1.tgz#524af240d1a360527b730475ecfa1344aa540dde" dependencies: - chalk "~2.2.0" - enhanced-resolve "^3.1.0" - loader-utils "^1.0.2" - magic-string "^0.22.3" - semver "^5.3.0" - source-map "^0.5.6" + call-me-maybe "^1.0.1" + glob-to-regexp "^0.3.0" + +"@ng-bootstrap/ng-bootstrap@^2.0.0": + version "2.2.2" + resolved "https://registry.yarnpkg.com/@ng-bootstrap/ng-bootstrap/-/ng-bootstrap-2.2.2.tgz#07c64badd48b563140eb5a6327b5516bf2226834" + +"@ng-dynamic-forms/core@6.0.9": + version "6.0.9" + resolved "https://registry.yarnpkg.com/@ng-dynamic-forms/core/-/core-6.0.9.tgz#358fa6141ec3fa5a22eb2d74f61068dc367cf257" + +"@ng-dynamic-forms/ui-ng-bootstrap@6.0.9": + version "6.0.9" + resolved "https://registry.yarnpkg.com/@ng-dynamic-forms/ui-ng-bootstrap/-/ui-ng-bootstrap-6.0.9.tgz#875abefaded1587e976fb4c4cccf743ac25981f0" + +"@ngrx/effects@^6.1.0": + version "6.1.0" + resolved "https://registry.yarnpkg.com/@ngrx/effects/-/effects-6.1.0.tgz#3c1e1ab1e5a86c6d9c29d4f3771e42cc9bd8576c" + +"@ngrx/router-store@^6.1.0": + version "6.1.0" + resolved "https://registry.yarnpkg.com/@ngrx/router-store/-/router-store-6.1.0.tgz#a225de3fbb262429561d722e139dde7efdcf0cea" + +"@ngrx/store-devtools@^6.1.0": + version "6.1.0" + resolved "https://registry.yarnpkg.com/@ngrx/store-devtools/-/store-devtools-6.1.0.tgz#cf65a3149628dc37badd094204484dde9ba14200" + +"@ngrx/store@^6.1.0": + version "6.1.0" + resolved "https://registry.yarnpkg.com/@ngrx/store/-/store-6.1.0.tgz#5b027647a797bf027912568214b10375dd75af38" + +"@ngtools/webpack@^6.1.5": + version "6.1.5" + resolved "https://registry.yarnpkg.com/@ngtools/webpack/-/webpack-6.1.5.tgz#134639686eb4519885ed27665babdf80ce098263" + dependencies: + "@angular-devkit/core" "0.7.5" + rxjs "^6.0.0" tree-kill "^1.0.0" webpack-sources "^1.1.0" -"@nguniversal/express-engine@5.0.0": - version "5.0.0" - resolved "https://registry.yarnpkg.com/@nguniversal/express-engine/-/express-engine-5.0.0.tgz#e218fa9fbc7b47379bc106f69ada274e05631243" +"@nguniversal/express-engine@6.1.0": + version "6.1.0" + resolved "https://registry.yarnpkg.com/@nguniversal/express-engine/-/express-engine-6.1.0.tgz#384d761556a0accc0738ae89b8a63afb43e76a86" -"@ngx-translate/core@9.1.1": - version "9.1.1" - resolved "https://registry.yarnpkg.com/@ngx-translate/core/-/core-9.1.1.tgz#ae103928836b8a9e069fd2e2e76fa2198cc7e628" +"@ngx-translate/core@10.0.2": + version "10.0.2" + resolved "https://registry.yarnpkg.com/@ngx-translate/core/-/core-10.0.2.tgz#5eeb78f47845b476a1e892fb2fb153dbbaf72850" + dependencies: + tslib "^1.9.0" -"@ngx-translate/http-loader@2.0.1": - version "2.0.1" - resolved "https://registry.yarnpkg.com/@ngx-translate/http-loader/-/http-loader-2.0.1.tgz#aa67788e64bfa8652691a77b022b3b4031209113" +"@ngx-translate/http-loader@3.0.1": + version "3.0.1" + resolved "https://registry.yarnpkg.com/@ngx-translate/http-loader/-/http-loader-3.0.1.tgz#20b0f98bc6c25321129d3e3302ab3cc489c0a42a" + dependencies: + tslib "^1.9.0" -"@nicky-lenaers/ngx-scroll-to@^0.6.0": - version "0.6.0" - resolved "https://registry.yarnpkg.com/@nicky-lenaers/ngx-scroll-to/-/ngx-scroll-to-0.6.0.tgz#6d2922f5765a472e3c86499d9e53df5ca210e637" +"@nicky-lenaers/ngx-scroll-to@^1.0.0": + version "1.0.0" + resolved "https://registry.yarnpkg.com/@nicky-lenaers/ngx-scroll-to/-/ngx-scroll-to-1.0.0.tgz#2afdc03e5b3218bbb5e19ec69fb1e7f7c8eb83dc" + dependencies: + tslib "^1.9.0" + +"@nodelib/fs.stat@^1.0.1": + version "1.1.1" + resolved "https://registry.yarnpkg.com/@nodelib/fs.stat/-/fs.stat-1.1.1.tgz#53f349bb986ab273d601175aa1b25a655ab90ee3" "@types/acorn@^4.0.3": version "4.0.3" @@ -141,10 +163,16 @@ "@types/estree" "*" "@types/body-parser@*": - version "1.16.8" - resolved "https://registry.yarnpkg.com/@types/body-parser/-/body-parser-1.16.8.tgz#687ec34140624a3bec2b1a8ea9268478ae8f3be3" + version "1.17.0" + resolved "https://registry.yarnpkg.com/@types/body-parser/-/body-parser-1.17.0.tgz#9f5c9d9bd04bb54be32d5eb9fc0d8c974e6cf58c" + dependencies: + "@types/connect" "*" + "@types/node" "*" + +"@types/connect@*": + version "3.4.32" + resolved "https://registry.yarnpkg.com/@types/connect/-/connect-3.4.32.tgz#aa0e9616b9435ccad02bc52b5b454ffc2c70ba28" dependencies: - "@types/express" "*" "@types/node" "*" "@types/cookie-parser@1.4.1": @@ -158,18 +186,20 @@ resolved "https://registry.yarnpkg.com/@types/deep-freeze/-/deep-freeze-0.1.1.tgz#0e1ee6ceee06f51baeb663deec0bb7780bd72827" "@types/estree@*": - version "0.0.38" - resolved "https://registry.yarnpkg.com/@types/estree/-/estree-0.0.38.tgz#c1be40aa933723c608820a99a373a16d215a1ca2" + version "0.0.39" + resolved "https://registry.yarnpkg.com/@types/estree/-/estree-0.0.39.tgz#e177e699ee1b8c22d23174caaa7422644389509f" "@types/events@*": - version "1.1.0" - resolved "https://registry.yarnpkg.com/@types/events/-/events-1.1.0.tgz#93b1be91f63c184450385272c47b6496fd028e02" + version "1.2.0" + resolved "https://registry.yarnpkg.com/@types/events/-/events-1.2.0.tgz#81a6731ce4df43619e5c8c945383b3e62a89ea86" "@types/express-serve-static-core@*": - version "4.0.53" - resolved "https://registry.yarnpkg.com/@types/express-serve-static-core/-/express-serve-static-core-4.0.53.tgz#1723a35d1447f2c55e13c8721eab3448e42f4d82" + version "4.16.0" + resolved "https://registry.yarnpkg.com/@types/express-serve-static-core/-/express-serve-static-core-4.16.0.tgz#fdfe777594ddc1fe8eb8eccce52e261b496e43e7" dependencies: + "@types/events" "*" "@types/node" "*" + "@types/range-parser" "*" "@types/express-serve-static-core@4.11.1": version "4.11.1" @@ -178,16 +208,9 @@ "@types/events" "*" "@types/node" "*" -"@types/express@*": - version "4.0.37" - resolved "https://registry.yarnpkg.com/@types/express/-/express-4.0.37.tgz#625ac3765169676e01897ca47011c26375784971" - dependencies: - "@types/express-serve-static-core" "*" - "@types/serve-static" "*" - -"@types/express@^4.11.1": - version "4.11.1" - resolved "https://registry.yarnpkg.com/@types/express/-/express-4.11.1.tgz#f99663b3ab32d04cb11db612ef5dd7933f75465b" +"@types/express@*", "@types/express@^4.11.1": + version "4.16.0" + resolved "https://registry.yarnpkg.com/@types/express/-/express-4.16.0.tgz#6d8bc42ccaa6f35cf29a2b7c3333cb47b5a32a19" dependencies: "@types/body-parser" "*" "@types/express-serve-static-core" "*" @@ -212,8 +235,8 @@ resolved "https://registry.yarnpkg.com/@types/highlight.js/-/highlight.js-9.1.8.tgz#d227f18bcb8f3f187e16965f2444859a04689758" "@types/jasmine@^2.8.6": - version "2.8.6" - resolved "https://registry.yarnpkg.com/@types/jasmine/-/jasmine-2.8.6.tgz#14445b6a1613cf4e05dd61c3c3256d0e95c0421e" + version "2.8.8" + resolved "https://registry.yarnpkg.com/@types/jasmine/-/jasmine-2.8.8.tgz#bf53a7d193ea8b03867a38bfdb4fbb0e0bf066c9" "@types/js-cookie@2.1.0": version "2.1.0" @@ -223,6 +246,10 @@ version "4.14.74" resolved "https://registry.yarnpkg.com/@types/lodash/-/lodash-4.14.74.tgz#ac3bd8db988e7f7038e5d22bd76a7ba13f876168" +"@types/lodash@^4.14.110": + version "4.14.116" + resolved "https://registry.yarnpkg.com/@types/lodash/-/lodash-4.14.116.tgz#5ccf215653e3e8c786a58390751033a9adca0eb9" + "@types/marked@0.3.0": version "0.3.0" resolved "https://registry.yarnpkg.com/@types/marked/-/marked-0.3.0.tgz#583c223dd33385a1dda01aaf77b0cd0411c4b524" @@ -240,28 +267,32 @@ resolved "https://registry.yarnpkg.com/@types/minimatch/-/minimatch-2.0.29.tgz#5002e14f75e2d71e564281df0431c8c1b4a2a36a" "@types/node@*": - version "8.0.34" - resolved "https://registry.yarnpkg.com/@types/node/-/node-8.0.34.tgz#55f801fa2ddb2a40dd6dfc15ecfe1dde9c129fe9" + version "10.9.1" + resolved "https://registry.yarnpkg.com/@types/node/-/node-10.9.1.tgz#06f002136fbcf51e730995149050bb3c45ee54e6" "@types/node@^6.0.46": - version "6.0.88" - resolved "https://registry.yarnpkg.com/@types/node/-/node-6.0.88.tgz#f618f11a944f6a18d92b5c472028728a3e3d4b66" + version "6.0.116" + resolved "https://registry.yarnpkg.com/@types/node/-/node-6.0.116.tgz#2f9cd62b4ecc4927e3942e2655c182eecf5b45f1" "@types/node@^9.4.6": - version "9.4.6" - resolved "https://registry.yarnpkg.com/@types/node/-/node-9.4.6.tgz#d8176d864ee48753d053783e4e463aec86b8d82e" + version "9.6.29" + resolved "https://registry.yarnpkg.com/@types/node/-/node-9.6.29.tgz#9b3c5b288c77fbd2ab5684d36e3528cb9ee5429f" "@types/q@^0.0.32": version "0.0.32" resolved "https://registry.yarnpkg.com/@types/q/-/q-0.0.32.tgz#bd284e57c84f1325da702babfc82a5328190c0c5" -"@types/selenium-webdriver@^2.53.35", "@types/selenium-webdriver@~2.53.39": - version "2.53.42" - resolved "https://registry.yarnpkg.com/@types/selenium-webdriver/-/selenium-webdriver-2.53.42.tgz#74cb77fb6052edaff2a8984ddafd88d419f25cac" +"@types/range-parser@*": + version "1.2.2" + resolved "https://registry.yarnpkg.com/@types/range-parser/-/range-parser-1.2.2.tgz#fa8e1ad1d474688a757140c91de6dace6f4abc8d" + +"@types/selenium-webdriver@^3.0.0": + version "3.0.10" + resolved "https://registry.yarnpkg.com/@types/selenium-webdriver/-/selenium-webdriver-3.0.10.tgz#e98cc6f05b4b436277671c784ee2f9d05a634f9b" "@types/serve-static@*": - version "1.7.32" - resolved "https://registry.yarnpkg.com/@types/serve-static/-/serve-static-1.7.32.tgz#0f6732e4dab0813771dd8fc8fe14940f34728b4c" + version "1.13.2" + resolved "https://registry.yarnpkg.com/@types/serve-static/-/serve-static-1.13.2.tgz#f5ac4d7a6420a99a6a45af4719f4dcd8cd907a48" dependencies: "@types/express-serve-static-core" "*" "@types/mime" "*" @@ -297,115 +328,271 @@ version "1.6.29" resolved "https://registry.yarnpkg.com/@types/webfontloader/-/webfontloader-1.6.29.tgz#c6b5f6eb8ca31d0aae6b02b6c1300349dd93ea8e" +"@webassemblyjs/ast@1.5.13": + version "1.5.13" + resolved "https://registry.yarnpkg.com/@webassemblyjs/ast/-/ast-1.5.13.tgz#81155a570bd5803a30ec31436bc2c9c0ede38f25" + dependencies: + "@webassemblyjs/helper-module-context" "1.5.13" + "@webassemblyjs/helper-wasm-bytecode" "1.5.13" + "@webassemblyjs/wast-parser" "1.5.13" + debug "^3.1.0" + mamacro "^0.0.3" + +"@webassemblyjs/floating-point-hex-parser@1.5.13": + version "1.5.13" + resolved "https://registry.yarnpkg.com/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.5.13.tgz#29ce0baa97411f70e8cce68ce9c0f9d819a4e298" + +"@webassemblyjs/helper-api-error@1.5.13": + version "1.5.13" + resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-api-error/-/helper-api-error-1.5.13.tgz#e49b051d67ee19a56e29b9aa8bd949b5b4442a59" + +"@webassemblyjs/helper-buffer@1.5.13": + version "1.5.13" + resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-buffer/-/helper-buffer-1.5.13.tgz#873bb0a1b46449231137c1262ddfd05695195a1e" + dependencies: + debug "^3.1.0" + +"@webassemblyjs/helper-code-frame@1.5.13": + version "1.5.13" + resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-code-frame/-/helper-code-frame-1.5.13.tgz#1bd2181b6a0be14e004f0fe9f5a660d265362b58" + dependencies: + "@webassemblyjs/wast-printer" "1.5.13" + +"@webassemblyjs/helper-fsm@1.5.13": + version "1.5.13" + resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-fsm/-/helper-fsm-1.5.13.tgz#cdf3d9d33005d543a5c5e5adaabf679ffa8db924" + +"@webassemblyjs/helper-module-context@1.5.13": + version "1.5.13" + resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-module-context/-/helper-module-context-1.5.13.tgz#dc29ddfb51ed657655286f94a5d72d8a489147c5" + dependencies: + debug "^3.1.0" + mamacro "^0.0.3" + +"@webassemblyjs/helper-wasm-bytecode@1.5.13": + version "1.5.13" + resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.5.13.tgz#03245817f0a762382e61733146f5773def15a747" + +"@webassemblyjs/helper-wasm-section@1.5.13": + version "1.5.13" + resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.5.13.tgz#efc76f44a10d3073b584b43c38a179df173d5c7d" + dependencies: + "@webassemblyjs/ast" "1.5.13" + "@webassemblyjs/helper-buffer" "1.5.13" + "@webassemblyjs/helper-wasm-bytecode" "1.5.13" + "@webassemblyjs/wasm-gen" "1.5.13" + debug "^3.1.0" + +"@webassemblyjs/ieee754@1.5.13": + version "1.5.13" + resolved "https://registry.yarnpkg.com/@webassemblyjs/ieee754/-/ieee754-1.5.13.tgz#573e97c8c12e4eebb316ca5fde0203ddd90b0364" + dependencies: + ieee754 "^1.1.11" + +"@webassemblyjs/leb128@1.5.13": + version "1.5.13" + resolved "https://registry.yarnpkg.com/@webassemblyjs/leb128/-/leb128-1.5.13.tgz#ab52ebab9cec283c1c1897ac1da833a04a3f4cee" + dependencies: + long "4.0.0" + +"@webassemblyjs/utf8@1.5.13": + version "1.5.13" + resolved "https://registry.yarnpkg.com/@webassemblyjs/utf8/-/utf8-1.5.13.tgz#6b53d2cd861cf94fa99c1f12779dde692fbc2469" + +"@webassemblyjs/wasm-edit@1.5.13": + version "1.5.13" + resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-edit/-/wasm-edit-1.5.13.tgz#c9cef5664c245cf11b3b3a73110c9155831724a8" + dependencies: + "@webassemblyjs/ast" "1.5.13" + "@webassemblyjs/helper-buffer" "1.5.13" + "@webassemblyjs/helper-wasm-bytecode" "1.5.13" + "@webassemblyjs/helper-wasm-section" "1.5.13" + "@webassemblyjs/wasm-gen" "1.5.13" + "@webassemblyjs/wasm-opt" "1.5.13" + "@webassemblyjs/wasm-parser" "1.5.13" + "@webassemblyjs/wast-printer" "1.5.13" + debug "^3.1.0" + +"@webassemblyjs/wasm-gen@1.5.13": + version "1.5.13" + resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-gen/-/wasm-gen-1.5.13.tgz#8e6ea113c4b432fa66540189e79b16d7a140700e" + dependencies: + "@webassemblyjs/ast" "1.5.13" + "@webassemblyjs/helper-wasm-bytecode" "1.5.13" + "@webassemblyjs/ieee754" "1.5.13" + "@webassemblyjs/leb128" "1.5.13" + "@webassemblyjs/utf8" "1.5.13" + +"@webassemblyjs/wasm-opt@1.5.13": + version "1.5.13" + resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-opt/-/wasm-opt-1.5.13.tgz#147aad7717a7ee4211c36b21a5f4c30dddf33138" + dependencies: + "@webassemblyjs/ast" "1.5.13" + "@webassemblyjs/helper-buffer" "1.5.13" + "@webassemblyjs/wasm-gen" "1.5.13" + "@webassemblyjs/wasm-parser" "1.5.13" + debug "^3.1.0" + +"@webassemblyjs/wasm-parser@1.5.13": + version "1.5.13" + resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-parser/-/wasm-parser-1.5.13.tgz#6f46516c5bb23904fbdf58009233c2dd8a54c72f" + dependencies: + "@webassemblyjs/ast" "1.5.13" + "@webassemblyjs/helper-api-error" "1.5.13" + "@webassemblyjs/helper-wasm-bytecode" "1.5.13" + "@webassemblyjs/ieee754" "1.5.13" + "@webassemblyjs/leb128" "1.5.13" + "@webassemblyjs/utf8" "1.5.13" + +"@webassemblyjs/wast-parser@1.5.13": + version "1.5.13" + resolved "https://registry.yarnpkg.com/@webassemblyjs/wast-parser/-/wast-parser-1.5.13.tgz#5727a705d397ae6a3ae99d7f5460acf2ec646eea" + dependencies: + "@webassemblyjs/ast" "1.5.13" + "@webassemblyjs/floating-point-hex-parser" "1.5.13" + "@webassemblyjs/helper-api-error" "1.5.13" + "@webassemblyjs/helper-code-frame" "1.5.13" + "@webassemblyjs/helper-fsm" "1.5.13" + long "^3.2.0" + mamacro "^0.0.3" + +"@webassemblyjs/wast-printer@1.5.13": + version "1.5.13" + resolved "https://registry.yarnpkg.com/@webassemblyjs/wast-printer/-/wast-printer-1.5.13.tgz#bb34d528c14b4f579e7ec11e793ec50ad7cd7c95" + dependencies: + "@webassemblyjs/ast" "1.5.13" + "@webassemblyjs/wast-parser" "1.5.13" + long "^3.2.0" + +"@webpack-contrib/config-loader@^1.2.0": + version "1.2.1" + resolved "https://registry.yarnpkg.com/@webpack-contrib/config-loader/-/config-loader-1.2.1.tgz#5b3dd474e207437939d294d200c68b7b00008e04" + dependencies: + "@webpack-contrib/schema-utils" "^1.0.0-beta.0" + chalk "^2.1.0" + cosmiconfig "^5.0.2" + is-plain-obj "^1.1.0" + loud-rejection "^1.6.0" + merge-options "^1.0.1" + minimist "^1.2.0" + resolve "^1.6.0" + webpack-log "^1.1.2" + +"@webpack-contrib/schema-utils@^1.0.0-beta.0": + version "1.0.0-beta.0" + resolved "https://registry.yarnpkg.com/@webpack-contrib/schema-utils/-/schema-utils-1.0.0-beta.0.tgz#bf9638c9464d177b48209e84209e23bee2eb4f65" + dependencies: + ajv "^6.1.0" + ajv-keywords "^3.1.0" + chalk "^2.3.2" + strip-ansi "^4.0.0" + text-table "^0.2.0" + webpack-log "^1.1.2" + JSONStream@^1.0.3: - version "1.3.2" - resolved "https://registry.yarnpkg.com/JSONStream/-/JSONStream-1.3.2.tgz#c102371b6ec3a7cf3b847ca00c20bb0fce4c6dea" + version "1.3.4" + resolved "https://registry.yarnpkg.com/JSONStream/-/JSONStream-1.3.4.tgz#615bb2adb0cd34c8f4c447b5f6512fa1d8f16a2e" dependencies: jsonparse "^1.2.0" through ">=2.2.7 <3" -abbrev@1, abbrev@1.0.x: +abbrev@1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/abbrev/-/abbrev-1.1.1.tgz#f8f2c887ad10bf67f634f005b6987fed3179aac8" + +abbrev@1.0.x: version "1.0.9" resolved "https://registry.yarnpkg.com/abbrev/-/abbrev-1.0.9.tgz#91b4792588a7738c25f35dd6f63752a2f8776135" -accepts@1.3.3: - version "1.3.3" - resolved "https://registry.yarnpkg.com/accepts/-/accepts-1.3.3.tgz#c3ca7434938648c3e0d9c1e328dd68b622c284ca" +accepts@~1.3.4, accepts@~1.3.5: + version "1.3.5" + resolved "https://registry.yarnpkg.com/accepts/-/accepts-1.3.5.tgz#eb777df6011723a3b14e8a72c0805c8e86746bd2" dependencies: - mime-types "~2.1.11" + mime-types "~2.1.18" negotiator "0.6.1" -accepts@~1.3.4: - version "1.3.4" - resolved "https://registry.yarnpkg.com/accepts/-/accepts-1.3.4.tgz#86246758c7dd6d21a6474ff084a4740ec05eb21f" +acorn-dynamic-import@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/acorn-dynamic-import/-/acorn-dynamic-import-3.0.0.tgz#901ceee4c7faaef7e07ad2a47e890675da50a278" dependencies: - mime-types "~2.1.16" - negotiator "0.6.1" + acorn "^5.0.0" -acorn-dynamic-import@^2.0.0: - version "2.0.2" - resolved "https://registry.yarnpkg.com/acorn-dynamic-import/-/acorn-dynamic-import-2.0.2.tgz#c752bd210bef679501b6c6cb7fc84f8f47158cc4" +acorn-node@^1.2.0, acorn-node@^1.3.0, acorn-node@^1.5.2: + version "1.5.2" + resolved "https://registry.yarnpkg.com/acorn-node/-/acorn-node-1.5.2.tgz#2ca723df19d997b05824b69f6c7fb091fc42c322" dependencies: - acorn "^4.0.3" + acorn "^5.7.1" + acorn-dynamic-import "^3.0.0" + xtend "^4.0.1" -acorn@^4.0.1, acorn@^4.0.3: +acorn@^4.0.1: version "4.0.13" resolved "https://registry.yarnpkg.com/acorn/-/acorn-4.0.13.tgz#105495ae5361d697bd195c825192e1ad7f253787" -acorn@^5.0.0: - version "5.1.2" - resolved "https://registry.yarnpkg.com/acorn/-/acorn-5.1.2.tgz#911cb53e036807cf0fa778dc5d370fbd864246d7" - -acorn@^5.2.1: - version "5.3.0" - resolved "https://registry.yarnpkg.com/acorn/-/acorn-5.3.0.tgz#7446d39459c54fb49a80e6ee6478149b940ec822" - -acorn@^5.3.0: - version "5.4.1" - resolved "https://registry.yarnpkg.com/acorn/-/acorn-5.4.1.tgz#fdc58d9d17f4a4e98d102ded826a9b9759125102" +acorn@^5.0.0, acorn@^5.2.1, acorn@^5.3.0, acorn@^5.6.2, acorn@^5.7.1: + version "5.7.2" + resolved "https://registry.yarnpkg.com/acorn/-/acorn-5.7.2.tgz#91fa871883485d06708800318404e72bfb26dcc5" addressparser@1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/addressparser/-/addressparser-1.0.1.tgz#47afbe1a2a9262191db6838e4fd1d39b40821746" adjust-sourcemap-loader@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/adjust-sourcemap-loader/-/adjust-sourcemap-loader-1.1.0.tgz#412d92404eb61e4113635012cba53a33d008e0e2" + version "1.2.0" + resolved "https://registry.yarnpkg.com/adjust-sourcemap-loader/-/adjust-sourcemap-loader-1.2.0.tgz#e33fde95e50db9f2a802e3647e311d2fc5000c69" dependencies: assert "^1.3.0" camelcase "^1.2.1" - loader-utils "^1.0.2" + loader-utils "^1.1.0" lodash.assign "^4.0.1" lodash.defaults "^3.1.2" object-path "^0.9.2" - regex-parser "^2.2.1" + regex-parser "^2.2.9" -adm-zip@0.4.4: - version "0.4.4" - resolved "https://registry.yarnpkg.com/adm-zip/-/adm-zip-0.4.4.tgz#a61ed5ae6905c3aea58b3a657d25033091052736" - -adm-zip@^0.4.7: - version "0.4.7" - resolved "https://registry.yarnpkg.com/adm-zip/-/adm-zip-0.4.7.tgz#8606c2cbf1c426ce8c8ec00174447fd49b6eafc1" +adm-zip@^0.4.9: + version "0.4.11" + resolved "https://registry.yarnpkg.com/adm-zip/-/adm-zip-0.4.11.tgz#2aa54c84c4b01a9d0fb89bb11982a51f13e3d62a" after@0.8.2: version "0.8.2" resolved "https://registry.yarnpkg.com/after/-/after-0.8.2.tgz#fedb394f9f0e02aa9768e702bda23b505fae7e1f" -agent-base@2: - version "2.1.1" - resolved "https://registry.yarnpkg.com/agent-base/-/agent-base-2.1.1.tgz#d6de10d5af6132d5bd692427d46fc538539094c7" +agent-base@4, agent-base@^4.1.0, agent-base@^4.2.0, agent-base@~4.2.0: + version "4.2.1" + resolved "https://registry.yarnpkg.com/agent-base/-/agent-base-4.2.1.tgz#d89e5999f797875674c07d87f260fc41e83e8ca9" dependencies: - extend "~3.0.0" - semver "~5.0.1" + es6-promisify "^5.0.0" ajv-keywords@^3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/ajv-keywords/-/ajv-keywords-3.1.0.tgz#ac2b27939c543e95d2c06e7f7f5c27be4aa543be" + version "3.2.0" + resolved "https://registry.yarnpkg.com/ajv-keywords/-/ajv-keywords-3.2.0.tgz#e86b819c602cf8821ad637413698f1dec021847a" -ajv@^4.9.1: - version "4.11.8" - resolved "https://registry.yarnpkg.com/ajv/-/ajv-4.11.8.tgz#82ffb02b29e662ae53bdc20af15947706739c536" - dependencies: - co "^4.6.0" - json-stable-stringify "^1.0.1" - -ajv@^5.0.0, ajv@^5.1.0: - version "5.2.3" - resolved "https://registry.yarnpkg.com/ajv/-/ajv-5.2.3.tgz#c06f598778c44c6b161abafe3466b81ad1814ed2" +ajv@^5.0.0, ajv@^5.1.0, ajv@^5.3.0: + version "5.5.2" + resolved "https://registry.yarnpkg.com/ajv/-/ajv-5.5.2.tgz#73b5eeca3fab653e3d3f9422b341ad42205dc965" dependencies: co "^4.6.0" fast-deep-equal "^1.0.0" + fast-json-stable-stringify "^2.0.0" json-schema-traverse "^0.3.0" - json-stable-stringify "^1.0.1" ajv@^6.1.0, ajv@^6.1.1: - version "6.1.1" - resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.1.1.tgz#978d597fbc2b7d0e5a5c3ddeb149a682f2abfa0e" + version "6.5.3" + resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.5.3.tgz#71a569d189ecf4f4f321224fecb166f071dd90f9" + dependencies: + fast-deep-equal "^2.0.1" + fast-json-stable-stringify "^2.0.0" + json-schema-traverse "^0.4.1" + uri-js "^4.2.2" + +ajv@~6.4.0: + version "6.4.0" + resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.4.0.tgz#d3aff78e9277549771daf0164cff48482b754fc6" dependencies: fast-deep-equal "^1.0.0" fast-json-stable-stringify "^2.0.0" json-schema-traverse "^0.3.0" + uri-js "^3.0.2" align-text@^0.1.1, align-text@^0.1.3: version "0.1.4" @@ -433,19 +620,13 @@ amqplib@^0.5.2: readable-stream "1.x >=1.1.9" safe-buffer "^5.0.1" -angular-idle-preload@2.0.4: - version "2.0.4" - resolved "https://registry.yarnpkg.com/angular-idle-preload/-/angular-idle-preload-2.0.4.tgz#7b177c0f52918c090e5c345480b922297cd59a0d" - -angular2-moment@^1.9.0: - version "1.9.0" - resolved "https://registry.yarnpkg.com/angular2-moment/-/angular2-moment-1.9.0.tgz#d198a4d9bc825f61de19106ac7ea07a78569f5a1" - dependencies: - moment "^2.19.3" +angular-idle-preload@3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/angular-idle-preload/-/angular-idle-preload-3.0.0.tgz#decace34d9fac1cb00000727a6dc5caafdb84e4d" angular-sortablejs@^2.5.0: - version "2.5.2" - resolved "https://registry.yarnpkg.com/angular-sortablejs/-/angular-sortablejs-2.5.2.tgz#ffd651e47cc93a191db4c023f617db3789fd9af5" + version "2.6.0" + resolved "https://registry.yarnpkg.com/angular-sortablejs/-/angular-sortablejs-2.6.0.tgz#d41a5dcaf1dd08bcd79677b1fc0c64fb872fe2d3" angular2-template-loader@0.6.2: version "0.6.2" @@ -453,17 +634,17 @@ angular2-template-loader@0.6.2: dependencies: loader-utils "^0.2.15" -angular2-text-mask@8.0.4: - version "8.0.4" - resolved "https://registry.yarnpkg.com/angular2-text-mask/-/angular2-text-mask-8.0.4.tgz#07e485746cfb9f27e710b27b2785eac4cc4871fc" +angular2-text-mask@9.0.0: + version "9.0.0" + resolved "https://registry.yarnpkg.com/angular2-text-mask/-/angular2-text-mask-9.0.0.tgz#70490170a8096241fc3ce9482ed6a758ddbce8ea" dependencies: text-mask-core "^5.0.0" -angulartics2@^5.2.0: - version "5.2.0" - resolved "https://registry.yarnpkg.com/angulartics2/-/angulartics2-5.2.0.tgz#5bac82d4b6acf798b7db906488861e70b49fe04c" +angulartics2@^6.2.0: + version "6.2.0" + resolved "https://registry.yarnpkg.com/angulartics2/-/angulartics2-6.2.0.tgz#52eab311be74c9d055632e385988645c233a2c0f" dependencies: - tslib "^1.7.1" + tslib "^1.9.0" ansi-align@^2.0.0: version "2.0.0" @@ -471,12 +652,26 @@ ansi-align@^2.0.0: dependencies: string-width "^2.0.0" +ansi-colors@^3.0.0: + version "3.0.5" + resolved "https://registry.yarnpkg.com/ansi-colors/-/ansi-colors-3.0.5.tgz#cb9dc64993b64fd6945485f797fc3853137d9a7b" + ansi-cyan@^0.1.1: version "0.1.1" resolved "https://registry.yarnpkg.com/ansi-cyan/-/ansi-cyan-0.1.1.tgz#538ae528af8982f28ae30d86f2f17456d2609873" dependencies: ansi-wrap "0.1.0" +ansi-escapes@^1.1.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-1.4.0.tgz#d3a8a83b319aa67793662b13e761c7911422306e" + +ansi-gray@^0.1.1: + version "0.1.1" + resolved "https://registry.yarnpkg.com/ansi-gray/-/ansi-gray-0.1.1.tgz#2962cf54ec9792c48510a3deb524436861ef7251" + dependencies: + ansi-wrap "0.1.0" + ansi-html@0.0.7: version "0.0.7" resolved "https://registry.yarnpkg.com/ansi-html/-/ansi-html-0.0.7.tgz#813584021962a9e9e6fd039f940d12f56ca7859e" @@ -499,9 +694,9 @@ ansi-styles@^2.2.1: version "2.2.1" resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-2.2.1.tgz#b432dd3358b634cf75e1e4664368240533c1ddbe" -ansi-styles@^3.1.0, ansi-styles@^3.2.0: - version "3.2.0" - resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-3.2.0.tgz#c159b8d5be0f9e5a6f346dab94f16ce022161b88" +ansi-styles@^3.2.0, ansi-styles@^3.2.1: + version "3.2.1" + resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-3.2.1.tgz#41fbb20243e50b12be0f04b8dedbf07520ce841d" dependencies: color-convert "^1.9.0" @@ -527,9 +722,9 @@ anymatch@^2.0.0: micromatch "^3.1.4" normalize-path "^2.1.1" -app-root-path@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/app-root-path/-/app-root-path-2.0.1.tgz#cd62dcf8e4fd5a417efc664d2e5b10653c651b46" +app-root-path@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/app-root-path/-/app-root-path-2.1.0.tgz#98bf6599327ecea199309866e8140368fd2e646a" aproba@^1.0.3, aproba@^1.1.1: version "1.2.0" @@ -546,9 +741,9 @@ archiver-utils@^1.3.0: normalize-path "^2.0.0" readable-stream "^2.0.0" -archiver@1.3.0: - version "1.3.0" - resolved "https://registry.yarnpkg.com/archiver/-/archiver-1.3.0.tgz#4f2194d6d8f99df3f531e6881f14f15d55faaf22" +archiver@2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/archiver/-/archiver-2.1.1.tgz#ff662b4a78201494a3ee544d3a33fe7496509ebc" dependencies: archiver-utils "^1.3.0" async "^2.0.0" @@ -557,19 +752,18 @@ archiver@1.3.0: lodash "^4.8.0" readable-stream "^2.0.0" tar-stream "^1.5.0" - walkdir "^0.0.11" - zip-stream "^1.1.0" + zip-stream "^1.2.0" are-we-there-yet@~1.1.2: - version "1.1.4" - resolved "https://registry.yarnpkg.com/are-we-there-yet/-/are-we-there-yet-1.1.4.tgz#bb5dca382bb94f05e15194373d16fd3ba1ca110d" + version "1.1.5" + resolved "https://registry.yarnpkg.com/are-we-there-yet/-/are-we-there-yet-1.1.5.tgz#4b35c2944f062a8bfcda66410760350fe9ddfc21" dependencies: delegates "^1.0.0" readable-stream "^2.0.6" argparse@^1.0.7: - version "1.0.9" - resolved "https://registry.yarnpkg.com/argparse/-/argparse-1.0.9.tgz#73d83bc263f86e97f8cc4f6bae1b0e90a7d22c86" + version "1.0.10" + resolved "https://registry.yarnpkg.com/argparse/-/argparse-1.0.10.tgz#bcd6791ea5ae09725e17e5ad988134cd40b3d911" dependencies: sprintf-js "~1.0.2" @@ -590,7 +784,7 @@ arr-diff@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/arr-diff/-/arr-diff-4.0.0.tgz#d6461074febfec71e7e15235761a329a5dc7c520" -arr-flatten@^1.0.1, arr-flatten@^1.0.3, arr-flatten@^1.1.0: +arr-flatten@^1.0.1, arr-flatten@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/arr-flatten/-/arr-flatten-1.1.0.tgz#36048bbff4e7b47e136644316c99669ea5ae91f1" @@ -668,16 +862,18 @@ arrify@^1.0.0, arrify@^1.0.1: resolved "https://registry.yarnpkg.com/arrify/-/arrify-1.0.1.tgz#898508da2226f380df904728456849c1501a4b0d" asn1.js@^4.0.0: - version "4.9.1" - resolved "https://registry.yarnpkg.com/asn1.js/-/asn1.js-4.9.1.tgz#48ba240b45a9280e94748990ba597d216617fd40" + version "4.10.1" + resolved "https://registry.yarnpkg.com/asn1.js/-/asn1.js-4.10.1.tgz#b9c2bf5805f1e64aadeed6df3a2bfafb5a73f5a0" dependencies: bn.js "^4.0.0" inherits "^2.0.1" minimalistic-assert "^1.0.0" asn1@~0.2.3: - version "0.2.3" - resolved "https://registry.yarnpkg.com/asn1/-/asn1-0.2.3.tgz#dac8787713c9966849fc8180777ebe9c1ddf3b86" + version "0.2.4" + resolved "https://registry.yarnpkg.com/asn1/-/asn1-0.2.4.tgz#8d2475dfab553bb33e77b54e59e880bb8ce23136" + dependencies: + safer-buffer "~2.1.0" assert-plus@1.0.0, assert-plus@^1.0.0: version "1.0.0" @@ -698,14 +894,8 @@ assign-symbols@^1.0.0: resolved "https://registry.yarnpkg.com/assign-symbols/-/assign-symbols-1.0.0.tgz#59667f41fadd4f20ccbc2bb96b8d4f7f78ec0367" ast-types@0.x.x: - version "0.10.1" - resolved "https://registry.yarnpkg.com/ast-types/-/ast-types-0.10.1.tgz#f52fca9715579a14f841d67d7f8d25432ab6a3dd" - -astw@^2.0.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/astw/-/astw-2.2.0.tgz#7bd41784d32493987aeb239b6b4e1c57a873b917" - dependencies: - acorn "^4.0.3" + version "0.11.5" + resolved "https://registry.yarnpkg.com/ast-types/-/ast-types-0.11.5.tgz#9890825d660c03c28339f315e9fa0a360e31ec28" async-each@^1.0.0: version "1.0.1" @@ -729,39 +919,19 @@ async@2.0.1: dependencies: lodash "^4.8.0" -async@^2.0.0, async@^2.1.2, async@^2.1.5: - version "2.4.1" - resolved "https://registry.yarnpkg.com/async/-/async-2.4.1.tgz#62a56b279c98a11d0987096a01cc3eeb8eb7bbd7" +async@^2.0.0, async@^2.1.5, async@^2.5.0, async@~2.6.0: + version "2.6.1" + resolved "https://registry.yarnpkg.com/async/-/async-2.6.1.tgz#b245a23ca71930044ec53fa46aa00a3e87c6a610" dependencies: - lodash "^4.14.0" - -async@^2.4.1, async@^2.5.0: - version "2.6.0" - resolved "https://registry.yarnpkg.com/async/-/async-2.6.0.tgz#61a29abb6fcc026fea77e56d1c6ec53a795951f4" - dependencies: - lodash "^4.14.0" - -async@~0.9.0: - version "0.9.2" - resolved "https://registry.yarnpkg.com/async/-/async-0.9.2.tgz#aea74d5e61c1f899613bf64bda66d4c78f2fd17d" - -async@~2.1.2: - version "2.1.5" - resolved "https://registry.yarnpkg.com/async/-/async-2.1.5.tgz#e587c68580994ac67fc56ff86d3ac56bdbe810bc" - dependencies: - lodash "^4.14.0" + lodash "^4.17.10" asynckit@^0.4.0: version "0.4.0" resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79" -atob@^2.0.0: - version "2.0.3" - resolved "https://registry.yarnpkg.com/atob/-/atob-2.0.3.tgz#19c7a760473774468f20b2d2d03372ad7d4cbf5d" - -atob@~1.1.0: - version "1.1.3" - resolved "https://registry.yarnpkg.com/atob/-/atob-1.1.3.tgz#95f13629b12c3a51a5d215abdce2aa9f32f80773" +atob@^2.1.1: + version "2.1.2" + resolved "https://registry.yarnpkg.com/atob/-/atob-2.1.2.tgz#6d9517eb9e030d2436666651e86bd9f6f13533c9" autoprefixer@^6.3.1: version "6.7.7" @@ -775,27 +945,27 @@ autoprefixer@^6.3.1: postcss-value-parser "^3.2.3" autoprefixer@^7.1.1: - version "7.1.5" - resolved "https://registry.yarnpkg.com/autoprefixer/-/autoprefixer-7.1.5.tgz#d65d14b83c7cd1dd7bc801daa00557addf5a06b2" + version "7.2.6" + resolved "https://registry.yarnpkg.com/autoprefixer/-/autoprefixer-7.2.6.tgz#256672f86f7c735da849c4f07d008abb056067dc" dependencies: - browserslist "^2.5.0" - caniuse-lite "^1.0.30000744" - normalize-range "^0.1.2" - num2fraction "^1.2.2" - postcss "^6.0.13" - postcss-value-parser "^3.2.3" - -autoprefixer@^8.0.0: - version "8.0.0" - resolved "https://registry.yarnpkg.com/autoprefixer/-/autoprefixer-8.0.0.tgz#c19e480f061013127c373df0b01cf46919943f74" - dependencies: - browserslist "^3.0.0" - caniuse-lite "^1.0.30000808" + browserslist "^2.11.3" + caniuse-lite "^1.0.30000805" normalize-range "^0.1.2" num2fraction "^1.2.2" postcss "^6.0.17" postcss-value-parser "^3.2.3" +autoprefixer@^8.0.0: + version "8.6.5" + resolved "https://registry.yarnpkg.com/autoprefixer/-/autoprefixer-8.6.5.tgz#343f3d193ed568b3208e00117a1b96eb691d4ee9" + dependencies: + browserslist "^3.2.8" + caniuse-lite "^1.0.30000864" + normalize-range "^0.1.2" + num2fraction "^1.2.2" + postcss "^6.0.23" + postcss-value-parser "^3.2.3" + awesome-typescript-loader@3.4.1: version "3.4.1" resolved "https://registry.yarnpkg.com/awesome-typescript-loader/-/awesome-typescript-loader-3.4.1.tgz#22fa49800f0619ec18ab15383aef93b95378dea9" @@ -817,9 +987,9 @@ aws-sign2@~0.7.0: version "0.7.0" resolved "https://registry.yarnpkg.com/aws-sign2/-/aws-sign2-0.7.0.tgz#b46e890934a9591f2d2f6f86d7e6a9f1b3fe76a8" -aws4@^1.2.1, aws4@^1.6.0: - version "1.6.0" - resolved "https://registry.yarnpkg.com/aws4/-/aws4-1.6.0.tgz#83ef5ca860b2b32e4a0deedee8c771b9db57471e" +aws4@^1.2.1, aws4@^1.6.0, aws4@^1.8.0: + version "1.8.0" + resolved "https://registry.yarnpkg.com/aws4/-/aws4-1.8.0.tgz#f0e003d9ca9e7f59c7a508945d7b2ef9a04a542f" axios@^0.15.3: version "0.15.3" @@ -836,8 +1006,8 @@ babel-code-frame@^6.22.0, babel-code-frame@^6.26.0: js-tokens "^3.0.2" babel-generator@^6.18.0: - version "6.26.0" - resolved "https://registry.yarnpkg.com/babel-generator/-/babel-generator-6.26.0.tgz#ac1ae20070b79f6e3ca1d3269613053774f20dc5" + version "6.26.1" + resolved "https://registry.yarnpkg.com/babel-generator/-/babel-generator-6.26.1.tgz#1844408d3b8f0d35a404ea7ac180f087a601bd90" dependencies: babel-messages "^6.23.0" babel-runtime "^6.26.0" @@ -845,7 +1015,7 @@ babel-generator@^6.18.0: detect-indent "^4.0.0" jsesc "^1.3.0" lodash "^4.17.4" - source-map "^0.5.6" + source-map "^0.5.7" trim-right "^1.0.1" babel-messages@^6.23.0: @@ -854,7 +1024,15 @@ babel-messages@^6.23.0: dependencies: babel-runtime "^6.22.0" -babel-runtime@^6.22.0, babel-runtime@^6.23.0, babel-runtime@^6.26.0: +babel-polyfill@6.23.0: + version "6.23.0" + resolved "https://registry.yarnpkg.com/babel-polyfill/-/babel-polyfill-6.23.0.tgz#8364ca62df8eafb830499f699177466c3b03499d" + dependencies: + babel-runtime "^6.22.0" + core-js "^2.4.0" + regenerator-runtime "^0.10.0" + +babel-runtime@^6.0.0, babel-runtime@^6.22.0, babel-runtime@^6.23.0, babel-runtime@^6.26.0: version "6.26.0" resolved "https://registry.yarnpkg.com/babel-runtime/-/babel-runtime-6.26.0.tgz#965c7058668e82b55d7bfe04ff2337bc8b5647fe" dependencies: @@ -919,8 +1097,8 @@ base64-arraybuffer@0.1.5: resolved "https://registry.yarnpkg.com/base64-arraybuffer/-/base64-arraybuffer-0.1.5.tgz#73926771923b5a19747ad666aa5cd4bf9c6e9ce8" base64-js@^1.0.2: - version "1.2.1" - resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-1.2.1.tgz#a91947da1f4a516ea38e5b4ec0ec3773675e0886" + version "1.3.0" + resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-1.3.0.tgz#cab1e6118f051095e58b5281aea8c1cd22bfc0e3" base64id@1.0.0: version "1.0.0" @@ -949,8 +1127,8 @@ batch@0.6.1: resolved "https://registry.yarnpkg.com/batch/-/batch-0.6.1.tgz#dc34314f4e679318093fc760272525f94bf25c16" bcrypt-pbkdf@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.1.tgz#63bc5dcb61331b92bc05fd528953c33462a06f8d" + version "1.0.2" + resolved "https://registry.yarnpkg.com/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz#a4301d389b6a43f9b67ff3ca11a3f6637e360e9e" dependencies: tweetnacl "^0.14.3" @@ -965,8 +1143,8 @@ better-assert@~1.0.0: callsite "1.0.0" bfj-node4@^5.2.0: - version "5.2.1" - resolved "https://registry.yarnpkg.com/bfj-node4/-/bfj-node4-5.2.1.tgz#3a6aa2730cf6911ba2afb836c2f88f015d718f3f" + version "5.3.1" + resolved "https://registry.yarnpkg.com/bfj-node4/-/bfj-node4-5.3.1.tgz#e23d8b27057f1d0214fc561142ad9db998f26830" dependencies: bluebird "^3.5.1" check-types "^7.3.0" @@ -977,8 +1155,8 @@ big.js@^3.1.3: resolved "https://registry.yarnpkg.com/big.js/-/big.js-3.2.0.tgz#a5fc298b81b9e0dca2e458824784b65c52ba588e" binary-extensions@^1.0.0: - version "1.10.0" - resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-1.10.0.tgz#9aeb9a6c5e88638aad171e167f5900abe24835d0" + version "1.11.0" + resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-1.11.0.tgz#46aa1751fb6a2f93ee5e689bb1087d4b14c6c205" bitsyntax@~0.0.4: version "0.0.4" @@ -987,10 +1165,11 @@ bitsyntax@~0.0.4: buffer-more-ints "0.0.2" bl@^1.0.0: - version "1.2.1" - resolved "https://registry.yarnpkg.com/bl/-/bl-1.2.1.tgz#cac328f7bee45730d404b692203fcb590e172d5e" + version "1.2.2" + resolved "https://registry.yarnpkg.com/bl/-/bl-1.2.2.tgz#a160911717103c07410cef63ef51b397c025af9c" dependencies: - readable-stream "^2.0.5" + readable-stream "^2.3.5" + safe-buffer "^5.1.1" bl@~1.1.2: version "1.1.2" @@ -1014,7 +1193,7 @@ blocking-proxy@^1.0.0: dependencies: minimist "^1.2.0" -bluebird@^3.3.0, bluebird@^3.4.6, bluebird@^3.4.7, bluebird@^3.5.0, bluebird@^3.5.1: +bluebird@^3.3.0, bluebird@^3.4.6, bluebird@^3.5.1: version "3.5.1" resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-3.5.1.tgz#d9551f9de98f1fcda1e683d17ee91a0602ee2eb9" @@ -1022,7 +1201,7 @@ bn.js@^4.0.0, bn.js@^4.1.0, bn.js@^4.1.1, bn.js@^4.4.0: version "4.11.8" resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-4.11.8.tgz#2cde09eb5ee341f484746bb0309b3253b1b1442f" -body-parser@1.18.2, body-parser@^1.16.1: +body-parser@1.18.2: version "1.18.2" resolved "https://registry.yarnpkg.com/body-parser/-/body-parser-1.18.2.tgz#87678a19d84b47d859b83199bd59bce222b10454" dependencies: @@ -1037,6 +1216,21 @@ body-parser@1.18.2, body-parser@^1.16.1: raw-body "2.3.2" type-is "~1.6.15" +body-parser@^1.16.1: + version "1.18.3" + resolved "https://registry.yarnpkg.com/body-parser/-/body-parser-1.18.3.tgz#5b292198ffdd553b3a0f20ded0592b956955c8b4" + dependencies: + bytes "3.0.0" + content-type "~1.0.4" + debug "2.6.9" + depd "~1.1.2" + http-errors "~1.6.3" + iconv-lite "0.4.23" + on-finished "~2.3.0" + qs "6.5.2" + raw-body "2.3.3" + type-is "~1.6.16" + bonjour@^3.5.0: version "3.5.0" resolved "https://registry.yarnpkg.com/bonjour/-/bonjour-3.5.0.tgz#8e890a183d8ee9a2393b3844c691a42bcf7bc9f5" @@ -1087,8 +1281,8 @@ boxen@^1.2.1: widest-line "^2.0.0" brace-expansion@^1.1.7: - version "1.1.8" - resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.8.tgz#c07b211c7c952ec1f8efd51a77ef0d1d3990a292" + version "1.1.11" + resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd" dependencies: balanced-match "^1.0.0" concat-map "0.0.1" @@ -1107,29 +1301,12 @@ braces@^1.8.2: preserve "^0.2.0" repeat-element "^1.1.2" -braces@^2.2.2: - version "2.2.2" - resolved "https://registry.yarnpkg.com/braces/-/braces-2.2.2.tgz#241f868c2b2690d9febeee5a7c83fbbf25d00b1b" - dependencies: - arr-flatten "^1.0.3" - array-unique "^0.3.2" - define-property "^1.0.0" - extend-shallow "^2.0.1" - fill-range "^4.0.0" - isobject "^3.0.0" - repeat-element "^1.1.2" - snapdragon "^0.8.1" - snapdragon-node "^2.0.1" - split-string "^2.1.0" - to-regex "^3.0.1" - -braces@^2.3.0: - version "2.3.0" - resolved "https://registry.yarnpkg.com/braces/-/braces-2.3.0.tgz#a46941cb5fb492156b3d6a656e06c35364e3e66e" +braces@^2.3.0, braces@^2.3.1: + version "2.3.2" + resolved "https://registry.yarnpkg.com/braces/-/braces-2.3.2.tgz#5979fd3f14cd531565e5fa2df1abfff1dfaee729" dependencies: arr-flatten "^1.1.0" array-unique "^0.3.2" - define-property "^1.0.0" extend-shallow "^2.0.1" fill-range "^4.0.0" isobject "^3.0.1" @@ -1144,8 +1321,8 @@ brorand@^1.0.1: resolved "https://registry.yarnpkg.com/brorand/-/brorand-1.1.0.tgz#12c25efe40a45e3c323eb8675a0a0ce57b22371f" browser-pack@^6.0.1: - version "6.0.3" - resolved "https://registry.yarnpkg.com/browser-pack/-/browser-pack-6.0.3.tgz#91ca96518583ef580ab063a309de62e407767a39" + version "6.1.0" + resolved "https://registry.yarnpkg.com/browser-pack/-/browser-pack-6.1.0.tgz#c34ba10d0b9ce162b5af227c7131c92c2ecd5774" dependencies: JSONStream "^1.0.3" combine-source-map "~0.8.0" @@ -1155,14 +1332,14 @@ browser-pack@^6.0.1: umd "^3.0.0" browser-resolve@^1.11.0, browser-resolve@^1.7.0: - version "1.11.2" - resolved "https://registry.yarnpkg.com/browser-resolve/-/browser-resolve-1.11.2.tgz#8ff09b0a2c421718a1051c260b32e48f442938ce" + version "1.11.3" + resolved "https://registry.yarnpkg.com/browser-resolve/-/browser-resolve-1.11.3.tgz#9b7cbb3d0f510e4cb86bdbd796124d28b5890af6" dependencies: resolve "1.1.7" browserify-aes@^1.0.0, browserify-aes@^1.0.4: - version "1.0.8" - resolved "https://registry.yarnpkg.com/browserify-aes/-/browserify-aes-1.0.8.tgz#c8fa3b1b7585bb7ba77c5560b60996ddec6d5309" + version "1.2.0" + resolved "https://registry.yarnpkg.com/browserify-aes/-/browserify-aes-1.2.0.tgz#326734642f403dabc3003209853bb70ad428ef48" dependencies: buffer-xor "^1.0.3" cipher-base "^1.0.0" @@ -1172,20 +1349,21 @@ browserify-aes@^1.0.0, browserify-aes@^1.0.4: safe-buffer "^5.0.1" browserify-cipher@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/browserify-cipher/-/browserify-cipher-1.0.0.tgz#9988244874bf5ed4e28da95666dcd66ac8fc363a" + version "1.0.1" + resolved "https://registry.yarnpkg.com/browserify-cipher/-/browserify-cipher-1.0.1.tgz#8d6474c1b870bfdabcd3bcfcc1934a10e94f15f0" dependencies: browserify-aes "^1.0.4" browserify-des "^1.0.0" evp_bytestokey "^1.0.0" browserify-des@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/browserify-des/-/browserify-des-1.0.0.tgz#daa277717470922ed2fe18594118a175439721dd" + version "1.0.2" + resolved "https://registry.yarnpkg.com/browserify-des/-/browserify-des-1.0.2.tgz#3af4f1f59839403572f1c66204375f7a7f703e9c" dependencies: cipher-base "^1.0.1" des.js "^1.0.0" inherits "^2.0.1" + safe-buffer "^5.1.2" browserify-rsa@^4.0.0: version "4.0.1" @@ -1206,13 +1384,7 @@ browserify-sign@^4.0.0: inherits "^2.0.1" parse-asn1 "^5.0.0" -browserify-zlib@^0.1.4: - version "0.1.4" - resolved "https://registry.yarnpkg.com/browserify-zlib/-/browserify-zlib-0.1.4.tgz#bb35f8a519f600e0fa6b8485241c979d0141fb2d" - dependencies: - pako "~0.2.0" - -browserify-zlib@~0.2.0: +browserify-zlib@^0.2.0, browserify-zlib@~0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/browserify-zlib/-/browserify-zlib-0.2.0.tgz#2869459d9aa3be245fe8fe2ca1f46e2e7f54d73f" dependencies: @@ -1277,19 +1449,36 @@ browserslist@^1.3.6, browserslist@^1.5.2, browserslist@^1.7.6: caniuse-db "^1.0.30000639" electron-to-chromium "^1.2.7" -browserslist@^2.0.0, browserslist@^2.5.0: - version "2.5.1" - resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-2.5.1.tgz#68e4bc536bbcc6086d62843a2ffccea8396821c6" +browserslist@^2.0.0, browserslist@^2.11.3: + version "2.11.3" + resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-2.11.3.tgz#fe36167aed1bbcde4827ebfe71347a2cc70b99b2" dependencies: - caniuse-lite "^1.0.30000744" - electron-to-chromium "^1.3.24" + caniuse-lite "^1.0.30000792" + electron-to-chromium "^1.3.30" -browserslist@^3.0.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-3.1.0.tgz#6a1ccc302ddf48e70480e2ee1a9acc293eceb306" +browserslist@^3.2.8: + version "3.2.8" + resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-3.2.8.tgz#b0005361d6471f0f5952797a76fc985f1f978fc6" dependencies: - caniuse-lite "^1.0.30000808" - electron-to-chromium "^1.3.33" + caniuse-lite "^1.0.30000844" + electron-to-chromium "^1.3.47" + +browserstack@^1.5.1: + version "1.5.1" + resolved "https://registry.yarnpkg.com/browserstack/-/browserstack-1.5.1.tgz#e2dfa66ffee940ebad0a07f7e00fd4687c455d66" + dependencies: + https-proxy-agent "^2.2.1" + +buffer-alloc-unsafe@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/buffer-alloc-unsafe/-/buffer-alloc-unsafe-1.1.0.tgz#bd7dc26ae2972d0eda253be061dba992349c19f0" + +buffer-alloc@^1.1.0, buffer-alloc@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/buffer-alloc/-/buffer-alloc-1.2.0.tgz#890dd90d923a873e08e10e5fd51a57e5b7cce0ec" + dependencies: + buffer-alloc-unsafe "^1.1.0" + buffer-fill "^1.0.0" buffer-crc32@^0.2.1: version "0.2.13" @@ -1299,6 +1488,14 @@ buffer-es6@^4.9.1: version "4.9.3" resolved "https://registry.yarnpkg.com/buffer-es6/-/buffer-es6-4.9.3.tgz#f26347b82df76fd37e18bcb5288c4970cfd5c404" +buffer-fill@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/buffer-fill/-/buffer-fill-1.0.0.tgz#f8f78b76789888ef39f205cd637f68e702122b2c" + +buffer-from@^1.0.0: + version "1.1.1" + resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.1.tgz#32713bc028f75c02fdb710d7c7bcec1f2c6070ef" + buffer-indexof@^1.0.0: version "1.1.1" resolved "https://registry.yarnpkg.com/buffer-indexof/-/buffer-indexof-1.1.1.tgz#52fabcc6a606d1a00302802648ef68f639da268c" @@ -1319,9 +1516,9 @@ buffer@^4.3.0: ieee754 "^1.1.4" isarray "^1.0.0" -buffer@^5.0.2: - version "5.0.8" - resolved "https://registry.yarnpkg.com/buffer/-/buffer-5.0.8.tgz#84daa52e7cf2fa8ce4195bc5cf0f7809e0930b24" +buffer@^5.0.2, buffer@^5.1.0: + version "5.2.0" + resolved "https://registry.yarnpkg.com/buffer/-/buffer-5.2.0.tgz#53cf98241100099e9eeae20ee6d51d21b16e541e" dependencies: base64-js "^1.0.2" ieee754 "^1.1.4" @@ -1338,10 +1535,14 @@ buildmail@4.0.1: nodemailer-shared "1.1.0" punycode "1.4.1" -builtin-modules@^1.0.0, builtin-modules@^1.1.0, builtin-modules@^1.1.1: +builtin-modules@^1.0.0, builtin-modules@^1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/builtin-modules/-/builtin-modules-1.1.1.tgz#270f076c5a72c02f5b65a47df94c5fe3a278892f" +builtin-modules@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/builtin-modules/-/builtin-modules-2.0.0.tgz#60b7ef5ae6546bd7deefa74b08b62a43a232648e" + builtin-status-codes@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/builtin-status-codes/-/builtin-status-codes-3.0.0.tgz#85982878e21b98e1c66425e03d0174788f569ee8" @@ -1350,23 +1551,23 @@ bytes@3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/bytes/-/bytes-3.0.0.tgz#d32815404d689699f85a4ea4fa8755dd13a96048" -cacache@^10.0.1: - version "10.0.2" - resolved "https://registry.yarnpkg.com/cacache/-/cacache-10.0.2.tgz#105a93a162bbedf3a25da42e1939ed99ffb145f8" +cacache@^10.0.1, cacache@^10.0.4: + version "10.0.4" + resolved "https://registry.yarnpkg.com/cacache/-/cacache-10.0.4.tgz#6452367999eff9d4188aefd9a14e9d7c6a263460" dependencies: - bluebird "^3.5.0" + bluebird "^3.5.1" chownr "^1.0.1" glob "^7.1.2" graceful-fs "^4.1.11" lru-cache "^4.1.1" - mississippi "^1.3.0" + mississippi "^2.0.0" mkdirp "^0.5.1" move-concurrently "^1.0.1" promise-inflight "^1.0.1" - rimraf "^2.6.1" - ssri "^5.0.0" + rimraf "^2.6.2" + ssri "^5.2.4" unique-filename "^1.1.0" - y18n "^3.2.1" + y18n "^4.0.0" cache-base@^1.0.1: version "1.0.1" @@ -1386,6 +1587,10 @@ cached-path-relative@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/cached-path-relative/-/cached-path-relative-1.0.1.tgz#d09c4b52800aa4c078e2dd81a869aac90d2e54e7" +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" + callsite@1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/callsite/-/callsite-1.0.0.tgz#280398e5d664bd74038b6f0905153e6e8af1bc20" @@ -1404,6 +1609,14 @@ camelcase-keys@^2.0.0: camelcase "^2.0.0" map-obj "^1.0.0" +camelcase-keys@^4.0.0: + version "4.2.0" + resolved "https://registry.yarnpkg.com/camelcase-keys/-/camelcase-keys-4.2.0.tgz#a2aa5fb1af688758259c32c141426d78923b9b77" + dependencies: + camelcase "^4.1.0" + map-obj "^2.0.0" + quick-lru "^1.0.0" + camelcase@^1.0.2, camelcase@^1.2.1: version "1.2.1" resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-1.2.1.tgz#9bb5304d2e0b56698b2c758b08a3eaa9daa58a39" @@ -1420,6 +1633,10 @@ camelcase@^4.0.0, camelcase@^4.1.0: version "4.1.0" resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-4.1.0.tgz#d545635be1e33c542649c69173e5de6acfae34dd" +camelcase@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-5.0.0.tgz#03295527d58bd3cd4aa75363f35b2e8d97be2f42" + caniuse-api@^1.5.2: version "1.6.1" resolved "https://registry.yarnpkg.com/caniuse-api/-/caniuse-api-1.6.1.tgz#b534e7c734c4f81ec5fbe8aca2ad24354b962c6c" @@ -1439,16 +1656,12 @@ caniuse-api@^2.0.0: lodash.uniq "^4.5.0" caniuse-db@^1.0.30000529, caniuse-db@^1.0.30000634, caniuse-db@^1.0.30000639: - version "1.0.30000740" - resolved "https://registry.yarnpkg.com/caniuse-db/-/caniuse-db-1.0.30000740.tgz#03fcaaa176e3ed075895f72d46c1a12149bbeac9" + version "1.0.30000878" + resolved "https://registry.yarnpkg.com/caniuse-db/-/caniuse-db-1.0.30000878.tgz#0d0c6d8500c3aea21441fad059bce4b8f3f509df" -caniuse-lite@^1.0.0, caniuse-lite@^1.0.30000744: - version "1.0.30000745" - resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30000745.tgz#20d6fede1157a4935133502946fc7e0e6b880da5" - -caniuse-lite@^1.0.30000697, caniuse-lite@^1.0.30000808: - version "1.0.30000808" - resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30000808.tgz#7d759b5518529ea08b6705a19e70dbf401628ffc" +caniuse-lite@^1.0.0, caniuse-lite@^1.0.30000697, caniuse-lite@^1.0.30000792, caniuse-lite@^1.0.30000805, caniuse-lite@^1.0.30000844, caniuse-lite@^1.0.30000864: + version "1.0.30000878" + resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30000878.tgz#c644c39588dd42d3498e952234c372e5a40a4123" capture-stack-trace@^1.0.0: version "1.0.0" @@ -1475,7 +1688,7 @@ cerialize@0.1.18: dependencies: typescript "^2.5.0" -chalk@^1.0.0, chalk@^1.1.1, chalk@^1.1.3: +chalk@1.1.3, chalk@^1.0.0, chalk@^1.1.1, chalk@^1.1.3: version "1.1.3" resolved "https://registry.yarnpkg.com/chalk/-/chalk-1.1.3.tgz#a8115c55e4a702fe4d150abd3872822a7e09fc98" dependencies: @@ -1485,47 +1698,27 @@ chalk@^1.0.0, chalk@^1.1.1, chalk@^1.1.3: strip-ansi "^3.0.0" supports-color "^2.0.0" -chalk@^2.0.1, chalk@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.1.0.tgz#ac5becf14fa21b99c6c92ca7a7d7cfd5b17e743e" +chalk@^2.0.1, chalk@^2.1.0, chalk@^2.3.0, chalk@^2.3.1, chalk@^2.3.2, chalk@^2.4.1: + version "2.4.1" + resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.1.tgz#18c49ab16a037b6eb0152cc83e3471338215b66e" dependencies: - ansi-styles "^3.1.0" + ansi-styles "^3.2.1" escape-string-regexp "^1.0.5" - supports-color "^4.0.0" + supports-color "^5.3.0" -chalk@^2.3.0: - version "2.3.0" - resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.3.0.tgz#b5ea48efc9c1793dccc9b4767c93914d3f2d52ba" - dependencies: - ansi-styles "^3.1.0" - escape-string-regexp "^1.0.5" - supports-color "^4.0.0" - -chalk@^2.3.1: - version "2.3.1" - resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.3.1.tgz#523fe2678aec7b04e8041909292fe8b17059b796" - dependencies: - ansi-styles "^3.2.0" - escape-string-regexp "^1.0.5" - supports-color "^5.2.0" - -chalk@~2.2.0: - version "2.2.2" - resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.2.2.tgz#4403f5cf18f35c05f51fbdf152bf588f956cf7cb" - dependencies: - ansi-styles "^3.1.0" - escape-string-regexp "^1.0.5" - supports-color "^4.0.0" +chardet@^0.4.0: + version "0.4.2" + resolved "https://registry.yarnpkg.com/chardet/-/chardet-0.4.2.tgz#b5473b33dc97c424e5d98dc87d55d4d8a29c8bf2" charenc@~0.0.1: version "0.0.2" resolved "https://registry.yarnpkg.com/charenc/-/charenc-0.0.2.tgz#c0a1d2f3a7092e03774bfa83f14c0fc5790a8667" check-types@^7.3.0: - version "7.3.0" - resolved "https://registry.yarnpkg.com/check-types/-/check-types-7.3.0.tgz#468f571a4435c24248f5fd0cb0e8d87c3c341e7d" + version "7.4.0" + resolved "https://registry.yarnpkg.com/check-types/-/check-types-7.4.0.tgz#0378ec1b9616ec71f774931a3c6516fad8c152f4" -chokidar@^1.4.1, chokidar@^1.4.2, chokidar@^1.7.0: +chokidar@^1.4.1, chokidar@^1.4.2: version "1.7.0" resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-1.7.0.tgz#798e689778151c8076b4b360e5edd28cda2bb468" dependencies: @@ -1540,9 +1733,9 @@ chokidar@^1.4.1, chokidar@^1.4.2, chokidar@^1.7.0: optionalDependencies: fsevents "^1.0.0" -chokidar@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-2.0.0.tgz#6686313c541d3274b2a5c01233342037948c911b" +chokidar@^2.0.0, chokidar@^2.0.2, chokidar@^2.0.3: + version "2.0.4" + resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-2.0.4.tgz#356ff4e2b0e8e43e322d18a372460bbcf3accd26" dependencies: anymatch "^2.0.0" async-each "^1.0.0" @@ -1551,34 +1744,28 @@ chokidar@^2.0.0: inherits "^2.0.1" is-binary-path "^1.0.0" is-glob "^4.0.0" + lodash.debounce "^4.0.8" normalize-path "^2.1.1" path-is-absolute "^1.0.0" readdirp "^2.0.0" + upath "^1.0.5" optionalDependencies: - fsevents "^1.0.0" - -chokidar@^2.0.2: - version "2.0.2" - resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-2.0.2.tgz#4dc65139eeb2714977735b6a35d06e97b494dfd7" - dependencies: - anymatch "^2.0.0" - async-each "^1.0.0" - braces "^2.3.0" - glob-parent "^3.1.0" - inherits "^2.0.1" - is-binary-path "^1.0.0" - is-glob "^4.0.0" - normalize-path "^2.1.1" - path-is-absolute "^1.0.0" - readdirp "^2.0.0" - upath "^1.0.0" - optionalDependencies: - fsevents "^1.0.0" + fsevents "^1.2.2" chownr@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/chownr/-/chownr-1.0.1.tgz#e2a75042a9551908bebd25b8523d5f9769d79181" +chrome-trace-event@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/chrome-trace-event/-/chrome-trace-event-1.0.0.tgz#45a91bd2c20c9411f0963b5aaeb9a1b95e09cc48" + dependencies: + tslib "^1.9.0" + +ci-info@^1.3.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/ci-info/-/ci-info-1.4.0.tgz#4841d53cad49f11b827b648ebde27a6e189b412f" + cipher-base@^1.0.0, cipher-base@^1.0.1, cipher-base@^1.0.3: version "1.0.4" resolved "https://registry.yarnpkg.com/cipher-base/-/cipher-base-1.0.4.tgz#8760e4ecc272f4c363532f926d874aae2c1397de" @@ -1586,9 +1773,9 @@ cipher-base@^1.0.0, cipher-base@^1.0.1, cipher-base@^1.0.3: inherits "^2.0.1" safe-buffer "^5.0.1" -circular-json@^0.5.1: - version "0.5.1" - resolved "https://registry.yarnpkg.com/circular-json/-/circular-json-0.5.1.tgz#b8942a09e535863dc21b04417a91971e1d9cd91f" +circular-json@^0.5.4: + version "0.5.5" + resolved "https://registry.yarnpkg.com/circular-json/-/circular-json-0.5.5.tgz#64182ef359042d37cd8e767fc9de878b1e9447d3" clap@^1.0.9: version "1.2.3" @@ -1597,25 +1784,38 @@ clap@^1.0.9: chalk "^1.1.3" class-utils@^0.3.5: - version "0.3.5" - resolved "https://registry.yarnpkg.com/class-utils/-/class-utils-0.3.5.tgz#17e793103750f9627b2176ea34cfd1b565903c80" + version "0.3.6" + resolved "https://registry.yarnpkg.com/class-utils/-/class-utils-0.3.6.tgz#f93369ae8b9a7ce02fd41faad0ca83033190c463" dependencies: arr-union "^3.1.0" define-property "^0.2.5" isobject "^3.0.0" - lazy-cache "^2.0.2" static-extend "^0.1.1" -clean-css@4.1.x: - version "4.1.9" - resolved "https://registry.yarnpkg.com/clean-css/-/clean-css-4.1.9.tgz#35cee8ae7687a49b98034f70de00c4edd3826301" +clean-css@4.2.x: + version "4.2.1" + resolved "https://registry.yarnpkg.com/clean-css/-/clean-css-4.2.1.tgz#2d411ef76b8569b6d0c84068dabe85b0aa5e5c17" dependencies: - source-map "0.5.x" + source-map "~0.6.0" cli-boxes@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/cli-boxes/-/cli-boxes-1.0.0.tgz#4fa917c3e59c94a004cd61f8ee509da651687143" +cli-cursor@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/cli-cursor/-/cli-cursor-2.1.0.tgz#b35dac376479facc3e94747d41d0d0f5238ffcb5" + dependencies: + restore-cursor "^2.0.0" + +cli-spinners@^1.1.0: + version "1.3.1" + resolved "https://registry.yarnpkg.com/cli-spinners/-/cli-spinners-1.3.1.tgz#002c1990912d0d59580c93bd36c056de99e4259a" + +cli-width@^2.0.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/cli-width/-/cli-width-2.2.0.tgz#ff19ede8a9a5e579324147b0c11f0fbcbabed639" + cliui@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/cliui/-/cliui-2.1.0.tgz#4b475760ff80264c762c3a1719032e91c7fea0d1" @@ -1633,8 +1833,8 @@ cliui@^3.2.0: wrap-ansi "^2.0.0" cliui@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/cliui/-/cliui-4.0.0.tgz#743d4650e05f36d1ed2575b59638d87322bfbbcc" + version "4.1.0" + resolved "https://registry.yarnpkg.com/cliui/-/cliui-4.1.0.tgz#348422dbe82d800b3022eef4f6ac10bf2e4d1b49" dependencies: string-width "^2.1.1" strip-ansi "^4.0.0" @@ -1654,17 +1854,13 @@ clone-stats@^0.0.1: resolved "https://registry.yarnpkg.com/clone-stats/-/clone-stats-0.0.1.tgz#b88f94a82cf38b8791d58046ea4029ad88ca99d1" clone@^1.0.0, clone@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/clone/-/clone-1.0.2.tgz#260b7a99ebb1edfe247538175f783243cb19d149" + version "1.0.4" + resolved "https://registry.yarnpkg.com/clone/-/clone-1.0.4.tgz#da309cc263df15994c688ca902179ca3c7cd7c7e" co@^4.6.0: version "4.6.0" resolved "https://registry.yarnpkg.com/co/-/co-4.6.0.tgz#6ea6bdf3d853ae54ccb8e47bfa0bf3f9031fb184" -co@~3.0.6: - version "3.0.6" - resolved "https://registry.yarnpkg.com/co/-/co-3.0.6.tgz#1445f226c5eb956138e68c9ac30167ea7d2e6bda" - coa@~1.0.1: version "1.0.4" resolved "https://registry.yarnpkg.com/coa/-/coa-1.0.4.tgz#a9ef153660d6a86a8bdec0289a5c684d217432fd" @@ -1675,16 +1871,16 @@ 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" -codelyzer@^4.1.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/codelyzer/-/codelyzer-4.1.0.tgz#3117754538d8f5ffa36dff91d340573a836cf373" +codelyzer@^4.4.4: + version "4.4.4" + resolved "https://registry.yarnpkg.com/codelyzer/-/codelyzer-4.4.4.tgz#29b7dbb51ba9ecc45c7300d61280a6564765d402" dependencies: - app-root-path "^2.0.1" + app-root-path "^2.1.0" css-selector-tokenizer "^0.7.0" cssauron "^1.4.0" semver-dsl "^1.0.1" - source-map "^0.5.6" - sprintf-js "^1.0.3" + source-map "^0.5.7" + sprintf-js "^1.1.1" collection-visit@^1.0.0: version "1.0.0" @@ -1693,13 +1889,17 @@ collection-visit@^1.0.0: map-visit "^1.0.0" object-visit "^1.0.0" -color-convert@^1.3.0, color-convert@^1.8.2, color-convert@^1.9.0: - version "1.9.0" - resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-1.9.0.tgz#1accf97dd739b983bf994d56fec8f95853641b7a" +color-convert@^1.3.0, color-convert@^1.8.2, color-convert@^1.9.0, color-convert@^1.9.1: + version "1.9.2" + resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-1.9.2.tgz#49881b8fba67df12a96bdf3f56c0aab9e7913147" dependencies: - color-name "^1.1.1" + color-name "1.1.1" -color-name@^1.0.0, color-name@^1.1.1: +color-name@1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.1.tgz#4b1415304cf50028ea81643643bd82ea05803689" + +color-name@^1.0.0: version "1.1.3" resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.3.tgz#a7d0558bd89c42f795dd42328f740831ca53bc25" @@ -1709,13 +1909,17 @@ color-string@^0.3.0: dependencies: color-name "^1.0.0" -color-string@^1.4.0: - version "1.5.2" - resolved "https://registry.yarnpkg.com/color-string/-/color-string-1.5.2.tgz#26e45814bc3c9a7cbd6751648a41434514a773a9" +color-string@^1.4.0, color-string@^1.5.2: + version "1.5.3" + resolved "https://registry.yarnpkg.com/color-string/-/color-string-1.5.3.tgz#c9bbc5f01b58b5492f3d6857459cb6590ce204cc" dependencies: color-name "^1.0.0" simple-swizzle "^0.2.2" +color-support@^1.1.3: + version "1.1.3" + resolved "https://registry.yarnpkg.com/color-support/-/color-support-1.1.3.tgz#93834379a1cc9a0c61f82f52f0d04322251bd5a2" + color@^0.11.0: version "0.11.4" resolved "https://registry.yarnpkg.com/color/-/color-0.11.4.tgz#6d7b5c74fb65e841cd48792ad1ed5e07b904d764" @@ -1731,6 +1935,13 @@ color@^1.0.3: color-convert "^1.8.2" color-string "^1.4.0" +color@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/color/-/color-2.0.1.tgz#e4ed78a3c4603d0891eba5430b04b86314f4c839" + dependencies: + color-convert "^1.9.1" + color-string "^1.5.2" + colormin@^1.0.5: version "1.1.2" resolved "https://registry.yarnpkg.com/colormin/-/colormin-1.1.2.tgz#ea2f7420a72b96881a38aae59ec124a6f7298133" @@ -1743,26 +1954,21 @@ colors@1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/colors/-/colors-1.0.3.tgz#0433f44d809680fdeb60ed260f1b0c262e82a40b" -colors@1.1.2, colors@^1.1.0, colors@^1.1.2, colors@~1.1.2: +colors@1.1.2, colors@~1.1.2: version "1.1.2" resolved "https://registry.yarnpkg.com/colors/-/colors-1.1.2.tgz#168a4701756b6a7f51a12ce0c97bfa28c084ed63" +colors@^1.1.0, colors@^1.1.2: + version "1.3.2" + resolved "https://registry.yarnpkg.com/colors/-/colors-1.3.2.tgz#2df8ff573dfbf255af562f8ce7181d6b971a359b" + combine-lists@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/combine-lists/-/combine-lists-1.0.1.tgz#458c07e09e0d900fc28b70a3fec2dacd1d2cb7f6" dependencies: lodash "^4.5.0" -combine-source-map@~0.7.1: - version "0.7.2" - resolved "https://registry.yarnpkg.com/combine-source-map/-/combine-source-map-0.7.2.tgz#0870312856b307a87cc4ac486f3a9a62aeccc09e" - dependencies: - convert-source-map "~1.1.0" - inline-source-map "~0.6.0" - lodash.memoize "~3.0.3" - source-map "~0.5.3" - -combine-source-map@~0.8.0: +combine-source-map@^0.8.0, combine-source-map@~0.8.0: version "0.8.0" resolved "https://registry.yarnpkg.com/combine-source-map/-/combine-source-map-0.8.0.tgz#a58d0df042c186fcf822a8e8015f5450d2d79a8b" dependencies: @@ -1771,24 +1977,20 @@ combine-source-map@~0.8.0: lodash.memoize "~3.0.3" source-map "~0.5.3" -combined-stream@^1.0.5, combined-stream@~1.0.5: - version "1.0.5" - resolved "https://registry.yarnpkg.com/combined-stream/-/combined-stream-1.0.5.tgz#938370a57b4a51dea2c77c15d5c5fdf895164009" +combined-stream@1.0.6, combined-stream@^1.0.5, combined-stream@~1.0.5, combined-stream@~1.0.6: + version "1.0.6" + resolved "https://registry.yarnpkg.com/combined-stream/-/combined-stream-1.0.6.tgz#723e7df6e801ac5613113a7e445a9b69cb632818" dependencies: delayed-stream "~1.0.0" -commander@2.11.x, commander@^2.9.0, commander@~2.11.0: - version "2.11.0" - resolved "https://registry.yarnpkg.com/commander/-/commander-2.11.0.tgz#157152fd1e7a6c8d98a5b715cf376df928004563" +commander@2.17.x, commander@^2.12.1, commander@^2.13.0, commander@^2.9.0, commander@~2.17.1: + version "2.17.1" + resolved "https://registry.yarnpkg.com/commander/-/commander-2.17.1.tgz#bd77ab7de6de94205ceacc72f1716d29f20a77bf" -commander@^2.12.1, commander@~2.13.0: +commander@~2.13.0: version "2.13.0" resolved "https://registry.yarnpkg.com/commander/-/commander-2.13.0.tgz#6964bca67685df7c1f1430c584f07d7597885b9c" -commander@^2.13.0: - version "2.14.1" - resolved "https://registry.yarnpkg.com/commander/-/commander-2.14.1.tgz#2235123e37af8ca3c65df45b026dbd357b01b9aa" - commondir@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/commondir/-/commondir-1.0.1.tgz#ddd800da0c66127393cca5950ea968a3aaf1253b" @@ -1806,31 +2008,31 @@ component-inherit@0.0.3: resolved "https://registry.yarnpkg.com/component-inherit/-/component-inherit-0.0.3.tgz#645fc4adf58b72b649d5cae65135619db26ff143" compress-commons@^1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/compress-commons/-/compress-commons-1.2.0.tgz#58587092ef20d37cb58baf000112c9278ff73b9f" + version "1.2.2" + resolved "https://registry.yarnpkg.com/compress-commons/-/compress-commons-1.2.2.tgz#524a9f10903f3a813389b0225d27c48bb751890f" dependencies: buffer-crc32 "^0.2.1" crc32-stream "^2.0.0" normalize-path "^2.0.0" readable-stream "^2.0.0" -compressible@~2.0.11: - version "2.0.11" - resolved "https://registry.yarnpkg.com/compressible/-/compressible-2.0.11.tgz#16718a75de283ed8e604041625a2064586797d8a" +compressible@~2.0.11, compressible@~2.0.14: + version "2.0.14" + resolved "https://registry.yarnpkg.com/compressible/-/compressible-2.0.14.tgz#326c5f507fbb055f54116782b969a81b67a29da7" dependencies: - mime-db ">= 1.29.0 < 2" + mime-db ">= 1.34.0 < 2" compression-webpack-plugin@^1.1.6: - version "1.1.6" - resolved "https://registry.yarnpkg.com/compression-webpack-plugin/-/compression-webpack-plugin-1.1.6.tgz#450808fe143b4c5216a14f0c315c47bec3d83cec" + version "1.1.11" + resolved "https://registry.yarnpkg.com/compression-webpack-plugin/-/compression-webpack-plugin-1.1.11.tgz#8384c7a6ead1d2e2efb190bdfcdcf35878ed8266" dependencies: - async "^2.4.1" cacache "^10.0.1" find-cache-dir "^1.0.0" + neo-async "^2.5.0" serialize-javascript "^1.4.0" webpack-sources "^1.0.1" -compression@1.7.1, compression@^1.5.2: +compression@1.7.1: version "1.7.1" resolved "https://registry.yarnpkg.com/compression/-/compression-1.7.1.tgz#eff2603efc2e22cf86f35d2eb93589f9875373db" dependencies: @@ -1842,14 +2044,27 @@ compression@1.7.1, compression@^1.5.2: safe-buffer "5.1.1" vary "~1.1.2" +compression@^1.5.2: + version "1.7.3" + resolved "https://registry.yarnpkg.com/compression/-/compression-1.7.3.tgz#27e0e176aaf260f7f2c2813c3e440adb9f1993db" + dependencies: + accepts "~1.3.5" + bytes "3.0.0" + compressible "~2.0.14" + debug "2.6.9" + on-headers "~1.0.1" + safe-buffer "5.1.2" + vary "~1.1.2" + concat-map@0.0.1: version "0.0.1" resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" -concat-stream@1.6.0, concat-stream@^1.5.0: - version "1.6.0" - resolved "https://registry.yarnpkg.com/concat-stream/-/concat-stream-1.6.0.tgz#0aac662fd52be78964d5532f694784e70110acf7" +concat-stream@1.6.2, concat-stream@^1.5.0, concat-stream@^1.6.1: + version "1.6.2" + resolved "https://registry.yarnpkg.com/concat-stream/-/concat-stream-1.6.2.tgz#904bdf194cd3122fc675c77fc4ac3d4ff0fd1a34" dependencies: + buffer-from "^1.0.0" inherits "^2.0.3" readable-stream "^2.2.2" typedarray "^0.0.6" @@ -1863,8 +2078,8 @@ concat-stream@~1.5.0, concat-stream@~1.5.1: typedarray "~0.0.5" configstore@^3.0.0: - version "3.1.1" - resolved "https://registry.yarnpkg.com/configstore/-/configstore-3.1.1.tgz#094ee662ab83fad9917678de114faaea8fcdca90" + version "3.1.2" + resolved "https://registry.yarnpkg.com/configstore/-/configstore-3.1.2.tgz#c6f25defaeef26df12dd33414b001fe81a543f8f" dependencies: dot-prop "^4.1.0" graceful-fs "^4.1.2" @@ -1874,15 +2089,15 @@ configstore@^3.0.0: xdg-basedir "^3.0.0" connect-history-api-fallback@^1.3.0: - version "1.3.0" - resolved "https://registry.yarnpkg.com/connect-history-api-fallback/-/connect-history-api-fallback-1.3.0.tgz#e51d17f8f0ef0db90a64fdb47de3051556e9f169" + version "1.5.0" + resolved "https://registry.yarnpkg.com/connect-history-api-fallback/-/connect-history-api-fallback-1.5.0.tgz#b06873934bc5e344fef611a196a6faae0aee015a" connect@^3.6.0: - version "3.6.5" - resolved "https://registry.yarnpkg.com/connect/-/connect-3.6.5.tgz#fb8dde7ba0763877d0ec9df9dac0b4b40e72c7da" + version "3.6.6" + resolved "https://registry.yarnpkg.com/connect/-/connect-3.6.6.tgz#09eff6c55af7236e137135a72574858b6786f524" dependencies: debug "2.6.9" - finalhandler "1.0.6" + finalhandler "1.1.0" parseurl "~1.3.2" utils-merge "1.0.1" @@ -1913,8 +2128,8 @@ convert-source-map@^0.3.3: resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-0.3.5.tgz#f1d802950af7dd2631a1febe0596550c86ab3190" convert-source-map@^1.1.1, convert-source-map@^1.5.0: - version "1.5.0" - resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-1.5.0.tgz#9acd70851c6d5dfdd93d9282e5edf94a03ff46b5" + version "1.5.1" + resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-1.5.1.tgz#b8278097b9bc229365de5c62cf5fcaed8b5599e5" convert-source-map@~1.1.0: version "1.1.3" @@ -1951,14 +2166,14 @@ copy-descriptor@^0.1.0: resolved "https://registry.yarnpkg.com/copy-descriptor/-/copy-descriptor-0.1.1.tgz#676f6eb3c39997c2ee1ac3a924fd6124748f578d" copy-webpack-plugin@^4.4.1: - version "4.4.1" - resolved "https://registry.yarnpkg.com/copy-webpack-plugin/-/copy-webpack-plugin-4.4.1.tgz#1e8c366211db6dc2ddee40e5a3e4fc661dd149e8" + version "4.5.2" + resolved "https://registry.yarnpkg.com/copy-webpack-plugin/-/copy-webpack-plugin-4.5.2.tgz#d53444a8fea2912d806e78937390ddd7e632ee5c" dependencies: - cacache "^10.0.1" + cacache "^10.0.4" find-cache-dir "^1.0.0" globby "^7.1.1" is-glob "^4.0.0" - loader-utils "^0.2.15" + loader-utils "^1.1.0" minimatch "^3.0.4" p-limit "^1.0.0" serialize-javascript "^1.4.0" @@ -1968,8 +2183,8 @@ core-js@2.5.3: resolved "https://registry.yarnpkg.com/core-js/-/core-js-2.5.3.tgz#8acc38345824f16d8365b7c9b4259168e8ed603e" core-js@^2.2.0, core-js@^2.4.0: - version "2.5.1" - resolved "https://registry.yarnpkg.com/core-js/-/core-js-2.5.1.tgz#ae6874dc66937789b80754ff5428df66819ca50b" + version "2.5.7" + resolved "https://registry.yarnpkg.com/core-js/-/core-js-2.5.7.tgz#f972608ff0cead68b841a16a932d0b183791814e" core-js@~2.3.0: version "2.3.0" @@ -1995,6 +2210,23 @@ cosmiconfig@^2.1.0, cosmiconfig@^2.1.1: parse-json "^2.2.0" require-from-string "^1.1.0" +cosmiconfig@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/cosmiconfig/-/cosmiconfig-4.0.0.tgz#760391549580bbd2df1e562bc177b13c290972dc" + dependencies: + is-directory "^0.3.1" + js-yaml "^3.9.0" + parse-json "^4.0.0" + require-from-string "^2.0.1" + +cosmiconfig@^5.0.2: + version "5.0.6" + resolved "https://registry.yarnpkg.com/cosmiconfig/-/cosmiconfig-5.0.6.tgz#dca6cf680a0bd03589aff684700858c81abeeb39" + dependencies: + is-directory "^0.3.1" + js-yaml "^3.9.0" + 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" @@ -2012,13 +2244,19 @@ crc32-stream@^2.0.0: crc "^3.4.4" readable-stream "^2.0.0" -crc@3.4.4, crc@^3.4.4: +crc@3.4.4: version "3.4.4" resolved "https://registry.yarnpkg.com/crc/-/crc-3.4.4.tgz#9da1e980e3bd44fc5c93bf5ab3da3378d85e466b" +crc@^3.4.4: + version "3.8.0" + resolved "https://registry.yarnpkg.com/crc/-/crc-3.8.0.tgz#ad60269c2c856f8c299e2c4cc0de4556914056c6" + dependencies: + buffer "^5.1.0" + create-ecdh@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/create-ecdh/-/create-ecdh-4.0.0.tgz#888c723596cdf7612f6498233eebd7a35301737d" + version "4.0.3" + resolved "https://registry.yarnpkg.com/create-ecdh/-/create-ecdh-4.0.3.tgz#c9111b6f33045c4697f144787f9254cdc77c45ff" dependencies: bn.js "^4.1.0" elliptic "^6.0.0" @@ -2030,17 +2268,18 @@ create-error-class@^3.0.0: capture-stack-trace "^1.0.0" create-hash@^1.1.0, create-hash@^1.1.2: - version "1.1.3" - resolved "https://registry.yarnpkg.com/create-hash/-/create-hash-1.1.3.tgz#606042ac8b9262750f483caddab0f5819172d8fd" + version "1.2.0" + resolved "https://registry.yarnpkg.com/create-hash/-/create-hash-1.2.0.tgz#889078af11a63756bcfb59bd221996be3a9ef196" dependencies: cipher-base "^1.0.1" inherits "^2.0.1" - ripemd160 "^2.0.0" + md5.js "^1.3.4" + ripemd160 "^2.0.1" sha.js "^2.4.0" create-hmac@^1.1.0, create-hmac@^1.1.2, create-hmac@^1.1.4: - version "1.1.6" - resolved "https://registry.yarnpkg.com/create-hmac/-/create-hmac-1.1.6.tgz#acb9e221a4e17bdb076e90657c42b93e3726cf06" + version "1.1.7" + resolved "https://registry.yarnpkg.com/create-hmac/-/create-hmac-1.1.7.tgz#69170c78b3ab957147b2b8b04572e47ead2243ff" dependencies: cipher-base "^1.0.3" create-hash "^1.1.0" @@ -2080,7 +2319,7 @@ cryptiles@3.x.x: dependencies: boom "5.x.x" -crypto-browserify@^3.0.0: +crypto-browserify@^3.0.0, crypto-browserify@^3.11.0: version "3.12.0" resolved "https://registry.yarnpkg.com/crypto-browserify/-/crypto-browserify-3.12.0.tgz#396cf9f3137f03e4b8e532c58f698254e00f80ec" dependencies: @@ -2096,32 +2335,17 @@ crypto-browserify@^3.0.0: randombytes "^2.0.0" randomfill "^1.0.3" -crypto-browserify@^3.11.0: - version "3.11.1" - resolved "https://registry.yarnpkg.com/crypto-browserify/-/crypto-browserify-3.11.1.tgz#948945efc6757a400d6e5e5af47194d10064279f" - dependencies: - browserify-cipher "^1.0.0" - browserify-sign "^4.0.0" - create-ecdh "^4.0.0" - create-hash "^1.1.0" - create-hmac "^1.1.0" - diffie-hellman "^5.0.0" - inherits "^2.0.1" - pbkdf2 "^3.0.3" - public-encrypt "^4.0.0" - randombytes "^2.0.0" - crypto-random-string@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/crypto-random-string/-/crypto-random-string-1.0.0.tgz#a230f64f568310e1498009940790ec99545bca7e" -css-color-function@^1.3.0: - version "1.3.0" - resolved "https://registry.yarnpkg.com/css-color-function/-/css-color-function-1.3.0.tgz#72c767baf978f01b8a8a94f42f17ba5d22a776fc" +css-color-function@~1.3.3: + version "1.3.3" + resolved "https://registry.yarnpkg.com/css-color-function/-/css-color-function-1.3.3.tgz#8ed24c2c0205073339fafa004bc8c141fccb282e" dependencies: balanced-match "0.1.0" color "^0.11.0" - debug "~0.7.4" + debug "^3.1.0" rgb "~0.1.0" css-color-names@0.0.4: @@ -2173,12 +2397,12 @@ css-what@2.1: resolved "https://registry.yarnpkg.com/css-what/-/css-what-2.1.0.tgz#9467d032c38cfaefb9f2d79501253062f87fa1bd" css@^2.0.0: - version "2.2.1" - resolved "https://registry.yarnpkg.com/css/-/css-2.2.1.tgz#73a4c81de85db664d4ee674f7d47085e3b2d55dc" + version "2.2.3" + resolved "https://registry.yarnpkg.com/css/-/css-2.2.3.tgz#f861f4ba61e79bedc962aa548e5780fd95cbc6be" dependencies: inherits "^2.0.1" source-map "^0.1.38" - source-map-resolve "^0.3.0" + source-map-resolve "^0.5.1" urix "^0.1.0" cssauron@^1.4.0: @@ -2280,39 +2504,46 @@ dateformat@^1.0.11, dateformat@^1.0.6: get-stdin "^4.0.1" meow "^3.3.0" -debug@2, debug@2.6.9, debug@^2.2.0, debug@^2.3.3, debug@^2.6.6, debug@^2.6.8, debug@~2.6.4, debug@~2.6.6, debug@~2.6.9: +debug@2, debug@2.6.9, debug@^2.1.2, debug@^2.2.0, debug@^2.3.3, debug@^2.6.6, debug@^2.6.8, debug@~2.6.4, debug@~2.6.6: version "2.6.9" resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f" dependencies: ms "2.0.0" -debug@2.2.0, debug@~2.2.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/debug/-/debug-2.2.0.tgz#f87057e995b1a1f6ae6a4960664137bc56f039da" - dependencies: - ms "0.7.1" - -debug@^3.1.0: +debug@3.1.0, debug@^3.1.0, debug@~3.1.0: version "3.1.0" resolved "https://registry.yarnpkg.com/debug/-/debug-3.1.0.tgz#5bb5a0672628b64149566ba16819e61518c67261" dependencies: ms "2.0.0" -debug@~0.7.4: - version "0.7.4" - resolved "https://registry.yarnpkg.com/debug/-/debug-0.7.4.tgz#06e1ea8082c2cb14e39806e22e2f6f757f92af39" +decamelize-keys@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/decamelize-keys/-/decamelize-keys-1.1.0.tgz#d171a87933252807eb3cb61dc1c1445d078df2d9" + dependencies: + decamelize "^1.1.0" + map-obj "^1.0.0" -decamelize@^1.0.0, decamelize@^1.1.1, decamelize@^1.1.2: +decamelize@^1.0.0, decamelize@^1.1.0, decamelize@^1.1.1, decamelize@^1.1.2: version "1.2.0" resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-1.2.0.tgz#f6534d15148269b20352e7bee26f501f9a191290" +decamelize@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-2.0.0.tgz#656d7bbc8094c4c788ea53c5840908c9c7d063c7" + dependencies: + xregexp "4.0.0" + +decode-uri-component@^0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/decode-uri-component/-/decode-uri-component-0.2.0.tgz#eb3913333458775cb84cd1a1fae062106bb87545" + deep-equal@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/deep-equal/-/deep-equal-1.0.1.tgz#f5d260292b660e084eff4cdbc9f08ad3247448b5" -deep-extend@~0.4.0: - version "0.4.2" - resolved "https://registry.yarnpkg.com/deep-extend/-/deep-extend-0.4.2.tgz#48b699c27e334bf89f10892be432f6e4c7d34a7f" +deep-extend@^0.6.0: + version "0.6.0" + resolved "https://registry.yarnpkg.com/deep-extend/-/deep-extend-0.6.0.tgz#c4fa7c95404a17a9c3e8ca7e1537312b736330ac" deep-freeze-strict@^1.1.1: version "1.1.1" @@ -2326,12 +2557,17 @@ deep-is@~0.1.3: version "0.1.3" resolved "https://registry.yarnpkg.com/deep-is/-/deep-is-0.1.3.tgz#b369d6fb5dbc13eecf524f91b070feedc357cf34" -define-properties@^1.1.2: - version "1.1.2" - resolved "https://registry.yarnpkg.com/define-properties/-/define-properties-1.1.2.tgz#83a73f2fea569898fb737193c8f873caf6d45c94" +defaults@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/defaults/-/defaults-1.0.3.tgz#c656051e9817d9ff08ed881477f3fe4019f3ef7d" dependencies: - foreach "^2.0.5" - object-keys "^1.0.8" + clone "^1.0.2" + +define-properties@^1.1.2: + version "1.1.3" + resolved "https://registry.yarnpkg.com/define-properties/-/define-properties-1.1.3.tgz#cf88da6cbee26fe6db7094f61d870cbd84cee9f1" + dependencies: + object-keys "^1.0.12" define-property@^0.2.5: version "0.2.5" @@ -2345,11 +2581,18 @@ define-property@^1.0.0: dependencies: is-descriptor "^1.0.0" +define-property@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/define-property/-/define-property-2.0.2.tgz#d459689e8d654ba77e02a817f8710d702cb16e9d" + dependencies: + is-descriptor "^1.0.2" + isobject "^3.0.1" + defined@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/defined/-/defined-1.0.0.tgz#c98d9bcef75674188e110969151199e39b1fa693" -degenerator@~1.0.2: +degenerator@^1.0.4: version "1.0.4" resolved "https://registry.yarnpkg.com/degenerator/-/degenerator-1.0.4.tgz#fcf490a37ece266464d9cc431ab98c5819ced095" dependencies: @@ -2388,13 +2631,17 @@ delegates@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/delegates/-/delegates-1.0.0.tgz#84c6e159b81904fdca59a0ef44cd870d31250f9a" -depd@1.1.1, depd@~1.1.1: +depd@1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/depd/-/depd-1.1.1.tgz#5783b4e1c459f06fa5ca27f991f3d06e7a310359" +depd@~1.1.1, depd@~1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/depd/-/depd-1.1.2.tgz#9bcd52e14c097763e749b274c4346ed2e560b5a9" + dependency-graph@^0.7.0: - version "0.7.0" - resolved "https://registry.yarnpkg.com/dependency-graph/-/dependency-graph-0.7.0.tgz#8fc7991ad236e47f0d5742701b5e307b83d7c0d0" + version "0.7.1" + resolved "https://registry.yarnpkg.com/dependency-graph/-/dependency-graph-0.7.1.tgz#0da960213843d8961d444da58da438bad39343a7" deps-sort@^2.0.0: version "2.0.0" @@ -2422,6 +2669,10 @@ detect-indent@^4.0.0: dependencies: repeating "^2.0.0" +detect-libc@^1.0.2: + version "1.0.3" + resolved "https://registry.yarnpkg.com/detect-libc/-/detect-libc-1.0.3.tgz#fa137c4bd698edf55cd5cd02ac559f91a4c4ba9b" + detect-node@^2.0.3: version "2.0.3" resolved "https://registry.yarnpkg.com/detect-node/-/detect-node-2.0.3.tgz#a2033c09cc8e158d37748fbde7507832bd6ce127" @@ -2438,12 +2689,12 @@ di@^0.0.1: resolved "https://registry.yarnpkg.com/di/-/di-0.0.1.tgz#806649326ceaa7caa3306d75d985ea2748ba913c" diff@^3.1.0, diff@^3.2.0: - version "3.3.1" - resolved "https://registry.yarnpkg.com/diff/-/diff-3.3.1.tgz#aa8567a6eed03c531fc89d3f711cd0e5259dec75" + version "3.5.0" + resolved "https://registry.yarnpkg.com/diff/-/diff-3.5.0.tgz#800c0dd1e0a8bfbc95835c202ad220fe317e5a12" diffie-hellman@^5.0.0: - version "5.0.2" - resolved "https://registry.yarnpkg.com/diffie-hellman/-/diffie-hellman-5.0.2.tgz#b5835739270cfe26acf632099fded2a07f209e5e" + version "5.0.3" + resolved "https://registry.yarnpkg.com/diffie-hellman/-/diffie-hellman-5.0.3.tgz#40e8ee98f55a2149607146921c63e1ae5f3d2875" dependencies: bn.js "^4.1.0" miller-rabin "^4.0.0" @@ -2460,9 +2711,9 @@ dns-equal@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/dns-equal/-/dns-equal-1.0.0.tgz#b39e7f1da6eb0a75ba9c17324b34753c47e0654d" -dns-packet@^1.0.1: - version "1.2.2" - resolved "https://registry.yarnpkg.com/dns-packet/-/dns-packet-1.2.2.tgz#a8a26bec7646438963fc86e06f8f8b16d6c8bf7a" +dns-packet@^1.3.1: + version "1.3.1" + resolved "https://registry.yarnpkg.com/dns-packet/-/dns-packet-1.3.1.tgz#12aa426981075be500b910eedcd0b47dd7deda5a" dependencies: ip "^1.1.0" safe-buffer "^5.0.1" @@ -2495,7 +2746,11 @@ dom-serializer@0: domelementtype "~1.1.1" entities "~1.1.1" -domain-browser@^1.1.1, domain-browser@~1.1.0: +domain-browser@^1.1.1: + version "1.2.0" + resolved "https://registry.yarnpkg.com/domain-browser/-/domain-browser-1.2.0.tgz#3d31f50191a6749dd1375a7f522e823d42e54eda" + +domain-browser@~1.1.0: version "1.1.7" resolved "https://registry.yarnpkg.com/domain-browser/-/domain-browser-1.1.7.tgz#867aa4b093faa05f1de08c06f4d7b21fdf8698bc" @@ -2513,9 +2768,9 @@ domhandler@2.1: dependencies: domelementtype "1" -domino@^1.0.29: - version "1.0.30" - resolved "https://registry.yarnpkg.com/domino/-/domino-1.0.30.tgz#54a4154ecae968616680f8feba3cedff355c71f4" +domino@^2.0.1: + version "2.1.0" + resolved "https://registry.yarnpkg.com/domino/-/domino-2.1.0.tgz#653ba7d331441113b42e40ba05f24253ec86e02e" domutils@1.1: version "1.1.6" @@ -2560,9 +2815,9 @@ duplexer@^0.1.1, duplexer@~0.1.1: version "0.1.1" resolved "https://registry.yarnpkg.com/duplexer/-/duplexer-0.1.1.tgz#ace6ff808c1ce66b57d1ebf97977acb02334cfc1" -duplexify@^3.4.2, duplexify@^3.5.3: - version "3.5.3" - resolved "https://registry.yarnpkg.com/duplexify/-/duplexify-3.5.3.tgz#8b5818800df92fd0125b27ab896491912858243e" +duplexify@^3.4.2, duplexify@^3.6.0: + version "3.6.0" + resolved "https://registry.yarnpkg.com/duplexify/-/duplexify-3.6.0.tgz#592903f5d80b38d037220541264d69a198fb3410" dependencies: end-of-stream "^1.0.0" inherits "^2.0.1" @@ -2570,39 +2825,36 @@ duplexify@^3.4.2, duplexify@^3.5.3: stream-shift "^1.0.0" ecc-jsbn@~0.1.1: - version "0.1.1" - resolved "https://registry.yarnpkg.com/ecc-jsbn/-/ecc-jsbn-0.1.1.tgz#0fc73a9ed5f0d53c38193398523ef7e543777505" + version "0.1.2" + resolved "https://registry.yarnpkg.com/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz#3a83a904e54353287874c564b7549386849a98c9" dependencies: jsbn "~0.1.0" + safer-buffer "^2.1.0" ecstatic@^3.0.0: - version "3.1.1" - resolved "https://registry.yarnpkg.com/ecstatic/-/ecstatic-3.1.1.tgz#2564aa9dde84179dcaf926a9e6d12df13a0b666d" + version "3.2.1" + resolved "https://registry.yarnpkg.com/ecstatic/-/ecstatic-3.2.1.tgz#1196a74d63d71d28dea807ed2b6183062671a206" dependencies: he "^1.1.1" - mime "^1.4.1" + mime "^1.6.0" minimist "^1.1.0" - url-join "^2.0.2" + url-join "^2.0.5" ee-first@1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/ee-first/-/ee-first-1.1.1.tgz#590c61156b0ae2f4f0255732a158b266bc56b21d" ejs@^2.5.7: - version "2.5.7" - resolved "https://registry.yarnpkg.com/ejs/-/ejs-2.5.7.tgz#cc872c168880ae3c7189762fd5ffc00896c9518a" + version "2.6.1" + resolved "https://registry.yarnpkg.com/ejs/-/ejs-2.6.1.tgz#498ec0d495655abc6f23cd61868d926464071aa0" -electron-to-chromium@^1.2.7, electron-to-chromium@^1.3.24: - version "1.3.24" - resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.24.tgz#9b7b88bb05ceb9fa016a177833cc2dde388f21b6" - -electron-to-chromium@^1.3.33: - version "1.3.33" - resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.33.tgz#bf00703d62a7c65238136578c352d6c5c042a545" +electron-to-chromium@^1.2.7, electron-to-chromium@^1.3.30, electron-to-chromium@^1.3.47: + version "1.3.61" + resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.61.tgz#a8ac295b28d0f03d85e37326fd16b6b6b17a1795" elliptic@^6.0.0: - version "6.4.0" - resolved "https://registry.yarnpkg.com/elliptic/-/elliptic-6.4.0.tgz#cac9af8762c85836187003c8dfe193e5e2eae5df" + version "6.4.1" + resolved "https://registry.yarnpkg.com/elliptic/-/elliptic-6.4.1.tgz#c2d0b7776911b86722c632c3c06c60f2f819939a" dependencies: bn.js "^4.4.0" brorand "^1.0.1" @@ -2616,29 +2868,29 @@ emojis-list@^2.0.0: version "2.1.0" resolved "https://registry.yarnpkg.com/emojis-list/-/emojis-list-2.1.0.tgz#4daa4d9db00f9819880c79fa457ae5b09a1fd389" -encodeurl@~1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/encodeurl/-/encodeurl-1.0.1.tgz#79e3d58655346909fe6f0f45a5de68103b294d20" +encodeurl@~1.0.1, encodeurl@~1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/encodeurl/-/encodeurl-1.0.2.tgz#ad3ff4c86ec2d029322f5a02c3a9a606c95b3f59" -end-of-stream@^1.0.0: - version "1.4.0" - resolved "https://registry.yarnpkg.com/end-of-stream/-/end-of-stream-1.4.0.tgz#7a90d833efda6cfa6eac0f4949dbb0fad3a63206" +encoding@^0.1.11: + version "0.1.12" + resolved "https://registry.yarnpkg.com/encoding/-/encoding-0.1.12.tgz#538b66f3ee62cd1ab51ec323829d1f9480c74beb" dependencies: - once "^1.4.0" + iconv-lite "~0.4.13" -end-of-stream@^1.1.0: +end-of-stream@^1.0.0, end-of-stream@^1.1.0: version "1.4.1" resolved "https://registry.yarnpkg.com/end-of-stream/-/end-of-stream-1.4.1.tgz#ed29634d19baba463b6ce6b80a37213eab71ec43" dependencies: once "^1.4.0" engine.io-client@~3.1.0: - version "3.1.4" - resolved "https://registry.yarnpkg.com/engine.io-client/-/engine.io-client-3.1.4.tgz#4fcf1370b47163bd2ce9be2733972430350d4ea1" + version "3.1.6" + resolved "https://registry.yarnpkg.com/engine.io-client/-/engine.io-client-3.1.6.tgz#5bdeb130f8b94a50ac5cbeb72583e7a4a063ddfd" dependencies: component-emitter "1.2.1" component-inherit "0.0.3" - debug "~2.6.9" + debug "~3.1.0" engine.io-parser "~2.1.1" has-cors "1.1.0" indexof "0.0.1" @@ -2659,17 +2911,17 @@ engine.io-parser@~2.1.0, engine.io-parser@~2.1.1: has-binary2 "~1.0.2" engine.io@~3.1.0: - version "3.1.4" - resolved "https://registry.yarnpkg.com/engine.io/-/engine.io-3.1.4.tgz#3d0211b70a552ce841ffc7da8627b301a9a4162e" + version "3.1.5" + resolved "https://registry.yarnpkg.com/engine.io/-/engine.io-3.1.5.tgz#0e7ef9d690eb0b35597f1d4ad02a26ca2dba3845" dependencies: - accepts "1.3.3" + accepts "~1.3.4" base64id "1.0.0" cookie "0.3.1" - debug "~2.6.9" + debug "~3.1.0" engine.io-parser "~2.1.0" ws "~3.3.1" optionalDependencies: - uws "~0.14.4" + uws "~9.14.0" enhanced-resolve@3.3.0: version "3.3.0" @@ -2680,14 +2932,13 @@ enhanced-resolve@3.3.0: object-assign "^4.0.1" tapable "^0.2.5" -enhanced-resolve@^3.1.0, enhanced-resolve@^3.4.0: - version "3.4.1" - resolved "https://registry.yarnpkg.com/enhanced-resolve/-/enhanced-resolve-3.4.1.tgz#0421e339fd71419b3da13d129b3979040230476e" +enhanced-resolve@^4.0.0, enhanced-resolve@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/enhanced-resolve/-/enhanced-resolve-4.1.0.tgz#41c7e0bfdfe74ac1ffe1e57ad6a5c6c9f3742a7f" dependencies: graceful-fs "^4.1.2" memory-fs "^0.4.0" - object-assign "^4.0.1" - tapable "^0.2.7" + tapable "^1.0.0" ent@~2.2.0: version "2.2.0" @@ -2697,21 +2948,21 @@ entities@~1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/entities/-/entities-1.1.1.tgz#6e5c2d0a5621b5dadaecef80b90edfb5cd7772f0" -errno@^0.1.3: - version "0.1.4" - resolved "https://registry.yarnpkg.com/errno/-/errno-0.1.4.tgz#b896e23a9e5e8ba33871fc996abd3635fc9a1c7d" +errno@^0.1.3, errno@~0.1.7: + version "0.1.7" + resolved "https://registry.yarnpkg.com/errno/-/errno-0.1.7.tgz#4684d71779ad39af177e3f007996f7c67c852618" dependencies: - prr "~0.0.0" + prr "~1.0.1" error-ex@^1.2.0, error-ex@^1.3.1: - version "1.3.1" - resolved "https://registry.yarnpkg.com/error-ex/-/error-ex-1.3.1.tgz#f855a86ce61adc4e8621c3cda21e7a7612c3a8dc" + version "1.3.2" + resolved "https://registry.yarnpkg.com/error-ex/-/error-ex-1.3.2.tgz#b4ac40648107fdcdcfae242f428bea8a14d4f1bf" dependencies: is-arrayish "^0.2.1" -es-abstract@^1.4.3, es-abstract@^1.7.0: - version "1.8.2" - resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.8.2.tgz#25103263dc4decbda60e0c737ca32313518027ee" +es-abstract@^1.4.3, es-abstract@^1.5.1, es-abstract@^1.6.1, es-abstract@^1.7.0: + version "1.12.0" + resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.12.0.tgz#9dbbdd27c6856f0001421ca18782d786bf8a6165" dependencies: es-to-primitive "^1.1.1" function-bind "^1.1.1" @@ -2727,66 +2978,43 @@ es-to-primitive@^1.1.1: is-date-object "^1.0.1" is-symbol "^1.0.1" -es5-ext@^0.10.14, es5-ext@^0.10.9, es5-ext@~0.10.14: - version "0.10.30" - resolved "https://registry.yarnpkg.com/es5-ext/-/es5-ext-0.10.30.tgz#7141a16836697dbabfaaaeee41495ce29f52c939" +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" dependencies: - es6-iterator "2" - es6-symbol "~3.1" - -es6-iterator@2, es6-iterator@^2.0.1, es6-iterator@~2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/es6-iterator/-/es6-iterator-2.0.1.tgz#8e319c9f0453bf575d374940a655920e59ca5512" - dependencies: - d "1" - es5-ext "^0.10.14" - es6-symbol "^3.1" - -es6-map@^0.1.3: - version "0.1.5" - resolved "https://registry.yarnpkg.com/es6-map/-/es6-map-0.1.5.tgz#9136e0503dcc06a301690f0bb14ff4e364e949f0" - dependencies: - d "1" - es5-ext "~0.10.14" - es6-iterator "~2.0.1" - es6-set "~0.1.5" + es6-iterator "~2.0.3" es6-symbol "~3.1.1" - event-emitter "~0.3.5" + next-tick "1" + +es6-iterator@~2.0.3: + version "2.0.3" + resolved "https://registry.yarnpkg.com/es6-iterator/-/es6-iterator-2.0.3.tgz#a7de889141a05a94b0854403b2d0a0fbfa98f3b7" + dependencies: + d "1" + es5-ext "^0.10.35" + es6-symbol "^3.1.1" + +es6-promise@^4.0.3: + version "4.2.4" + resolved "https://registry.yarnpkg.com/es6-promise/-/es6-promise-4.2.4.tgz#dc4221c2b16518760bd8c39a52d8f356fc00ed29" es6-promise@~3.0.2: version "3.0.2" resolved "https://registry.yarnpkg.com/es6-promise/-/es6-promise-3.0.2.tgz#010d5858423a5f118979665f46486a95c6ee2bb6" -es6-promise@~4.0.3: - version "4.0.5" - resolved "https://registry.yarnpkg.com/es6-promise/-/es6-promise-4.0.5.tgz#7882f30adde5b240ccfa7f7d78c548330951ae42" - -es6-set@~0.1.5: - version "0.1.5" - resolved "https://registry.yarnpkg.com/es6-set/-/es6-set-0.1.5.tgz#d2b3ec5d4d800ced818db538d28974db0a73ccb1" +es6-promisify@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/es6-promisify/-/es6-promisify-5.0.0.tgz#5109d62f3e56ea967c4b63505aef08291c8a5203" dependencies: - d "1" - es5-ext "~0.10.14" - es6-iterator "~2.0.1" - es6-symbol "3.1.1" - event-emitter "~0.3.5" + es6-promise "^4.0.3" -es6-symbol@3.1.1, es6-symbol@^3.1, es6-symbol@^3.1.1, es6-symbol@~3.1, es6-symbol@~3.1.1: +es6-symbol@^3.1.1, es6-symbol@~3.1.1: version "3.1.1" resolved "https://registry.yarnpkg.com/es6-symbol/-/es6-symbol-3.1.1.tgz#bf00ef4fdab6ba1b46ecb7b629b4c7ed5715cc77" dependencies: d "1" es5-ext "~0.10.14" -es6-weak-map@^2.0.1: - version "2.0.2" - resolved "https://registry.yarnpkg.com/es6-weak-map/-/es6-weak-map-2.0.2.tgz#5e3ab32251ffd1538a1f8e5ffa1357772f92d96f" - dependencies: - d "1" - es5-ext "^0.10.14" - es6-iterator "^2.0.1" - es6-symbol "^3.1.1" - escape-html@~1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/escape-html/-/escape-html-1.0.3.tgz#0258eae4d3d0c0974de1c169188ef0051d1d1988" @@ -2807,22 +3035,20 @@ escodegen@1.8.x: source-map "~0.2.0" escodegen@1.x.x: - version "1.9.0" - resolved "https://registry.yarnpkg.com/escodegen/-/escodegen-1.9.0.tgz#9811a2f265dc1cd3894420ee3717064b632b8852" + version "1.11.0" + resolved "https://registry.yarnpkg.com/escodegen/-/escodegen-1.11.0.tgz#b27a9389481d5bfd5bec76f7bb1eb3f8f4556589" dependencies: esprima "^3.1.3" estraverse "^4.2.0" esutils "^2.0.2" optionator "^0.8.1" optionalDependencies: - source-map "~0.5.6" + source-map "~0.6.1" -escope@^3.6.0: - version "3.6.0" - resolved "https://registry.yarnpkg.com/escope/-/escope-3.6.0.tgz#e01975e812781a163a6dadfdd80398dc64c889c3" +eslint-scope@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-4.0.0.tgz#50bf3071e9338bcdc43331794a0cb533f0136172" dependencies: - es6-map "^0.1.3" - es6-weak-map "^2.0.1" esrecurse "^4.1.0" estraverse "^4.1.1" @@ -2835,15 +3061,14 @@ esprima@3.x.x, esprima@^3.1.3: resolved "https://registry.yarnpkg.com/esprima/-/esprima-3.1.3.tgz#fdca51cee6133895e3c88d535ce49dbff62a4633" esprima@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/esprima/-/esprima-4.0.0.tgz#4499eddcd1110e0b218bacf2fa7f7f59f55ca804" + version "4.0.1" + resolved "https://registry.yarnpkg.com/esprima/-/esprima-4.0.1.tgz#13b04cdb3e6c5d19df91ab6987a8695619b0aa71" esrecurse@^4.1.0: - version "4.2.0" - resolved "https://registry.yarnpkg.com/esrecurse/-/esrecurse-4.2.0.tgz#fa9568d98d3823f9a41d91e902dcab9ea6e5b163" + version "4.2.1" + resolved "https://registry.yarnpkg.com/esrecurse/-/esrecurse-4.2.1.tgz#007a3b9fdbc2b3bb87e4879ea19c92fdbd3942cf" dependencies: estraverse "^4.1.0" - object-assign "^4.0.1" estraverse@^1.9.1: version "1.9.3" @@ -2857,13 +3082,9 @@ estree-walker@^0.2.1: version "0.2.1" resolved "https://registry.yarnpkg.com/estree-walker/-/estree-walker-0.2.1.tgz#bdafe8095383d8414d5dc2ecf4c9173b6db9412e" -estree-walker@^0.3.0: - version "0.3.1" - resolved "https://registry.yarnpkg.com/estree-walker/-/estree-walker-0.3.1.tgz#e6b1a51cf7292524e7237c312e5fe6660c1ce1aa" - -estree-walker@^0.5.0: - version "0.5.0" - resolved "https://registry.yarnpkg.com/estree-walker/-/estree-walker-0.5.0.tgz#aae3b57c42deb8010e349c892462f0e71c5dd1aa" +estree-walker@^0.5.0, estree-walker@^0.5.2: + version "0.5.2" + resolved "https://registry.yarnpkg.com/estree-walker/-/estree-walker-0.5.2.tgz#d3850be7529c9580d815600b53126515e146dd39" esutils@^2.0.2: version "2.0.2" @@ -2873,16 +3094,9 @@ etag@~1.8.1: version "1.8.1" resolved "https://registry.yarnpkg.com/etag/-/etag-1.8.1.tgz#41ae2eeb65efa62268aebfea83ac7d79299b0887" -event-emitter@~0.3.5: - version "0.3.5" - resolved "https://registry.yarnpkg.com/event-emitter/-/event-emitter-0.3.5.tgz#df8c69eef1647923c7157b9ce83840610b02cc39" - dependencies: - d "1" - es5-ext "~0.10.14" - event-stream@~3.3.0: version "3.3.4" - resolved "https://registry.yarnpkg.com/event-stream/-/event-stream-3.3.4.tgz#4ab4c9a0f5a54db9338b4c34d86bfce8f4b35571" + resolved "http://registry.npmjs.org/event-stream/-/event-stream-3.3.4.tgz#4ab4c9a0f5a54db9338b4c34d86bfce8f4b35571" dependencies: duplexer "~0.1.1" from "~0" @@ -2892,9 +3106,9 @@ event-stream@~3.3.0: stream-combiner "~0.0.4" through "~2.3.1" -eventemitter3@1.x.x: - version "1.2.0" - resolved "https://registry.yarnpkg.com/eventemitter3/-/eventemitter3-1.2.0.tgz#1c86991d816ad1e504750e73874224ecf3bec508" +eventemitter3@^3.0.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/eventemitter3/-/eventemitter3-3.1.0.tgz#090b4d6cdbd645ed10bf750d4b5407942d7ba163" events@^1.0.0, events@~1.1.0: version "1.1.1" @@ -2989,7 +3203,7 @@ express-session@1.15.6: uid-safe "~2.1.5" utils-merge "1.0.1" -express@4.16.2, express@^4.16.2: +express@4.16.2: version "4.16.2" resolved "https://registry.yarnpkg.com/express/-/express-4.16.2.tgz#e35c6dfe2d64b7dca0a5cd4f21781be3299e076c" dependencies: @@ -3024,6 +3238,41 @@ express@4.16.2, express@^4.16.2: utils-merge "1.0.1" vary "~1.1.2" +express@^4.16.2: + version "4.16.3" + resolved "https://registry.yarnpkg.com/express/-/express-4.16.3.tgz#6af8a502350db3246ecc4becf6b5a34d22f7ed53" + dependencies: + accepts "~1.3.5" + array-flatten "1.1.1" + body-parser "1.18.2" + content-disposition "0.5.2" + content-type "~1.0.4" + cookie "0.3.1" + cookie-signature "1.0.6" + debug "2.6.9" + depd "~1.1.2" + encodeurl "~1.0.2" + escape-html "~1.0.3" + etag "~1.8.1" + finalhandler "1.1.1" + fresh "0.5.2" + merge-descriptors "1.0.1" + methods "~1.1.2" + on-finished "~2.3.0" + parseurl "~1.3.2" + path-to-regexp "0.1.7" + proxy-addr "~2.0.3" + qs "6.5.1" + range-parser "~1.2.0" + safe-buffer "5.1.1" + send "0.16.2" + serve-static "1.13.2" + setprototypeof "1.1.0" + statuses "~1.4.0" + type-is "~1.6.16" + utils-merge "1.0.1" + vary "~1.1.2" + extend-shallow@^1.1.2: version "1.1.4" resolved "https://registry.yarnpkg.com/extend-shallow/-/extend-shallow-1.1.4.tgz#19d6bf94dfc09d76ba711f39b872d21ff4dd9071" @@ -3036,16 +3285,24 @@ extend-shallow@^2.0.1: dependencies: is-extendable "^0.1.0" -extend-shallow@^3.0.0: +extend-shallow@^3.0.0, extend-shallow@^3.0.2: version "3.0.2" resolved "https://registry.yarnpkg.com/extend-shallow/-/extend-shallow-3.0.2.tgz#26a71aaf073b39fb2127172746131c2704028db8" dependencies: assign-symbols "^1.0.0" is-extendable "^1.0.1" -extend@3, extend@^3.0.0, extend@~3.0.0, extend@~3.0.1: - version "3.0.1" - resolved "https://registry.yarnpkg.com/extend/-/extend-3.0.1.tgz#a755ea7bc1adfcc5a31ce7e762dbaadc5e636444" +extend@3, extend@^3.0.0, extend@~3.0.0, extend@~3.0.1, extend@~3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/extend/-/extend-3.0.2.tgz#f8b1136b4071fbd8eb140aff858b1019ec2915fa" + +external-editor@^2.0.1: + version "2.2.0" + resolved "https://registry.yarnpkg.com/external-editor/-/external-editor-2.2.0.tgz#045511cfd8d133f3846673d1047c154e214ad3d5" + dependencies: + chardet "^0.4.0" + iconv-lite "^0.4.17" + tmp "^0.0.33" extglob@^0.3.1: version "0.3.2" @@ -3053,9 +3310,9 @@ extglob@^0.3.1: dependencies: is-extglob "^1.0.0" -extglob@^2.0.2: - version "2.0.2" - resolved "https://registry.yarnpkg.com/extglob/-/extglob-2.0.2.tgz#3290f46208db1b2e8eb8be0c94ed9e6ad80edbe2" +extglob@^2.0.4: + version "2.0.4" + resolved "https://registry.yarnpkg.com/extglob/-/extglob-2.0.4.tgz#ad00fe4dc612a9232e8718711dc5cb5ab0285543" dependencies: array-unique "^0.3.2" define-property "^1.0.0" @@ -3066,29 +3323,49 @@ extglob@^2.0.2: snapdragon "^0.8.1" to-regex "^3.0.1" -extract-zip@~1.6.5: - version "1.6.5" - resolved "https://registry.yarnpkg.com/extract-zip/-/extract-zip-1.6.5.tgz#99a06735b6ea20ea9b705d779acffcc87cff0440" +extract-zip@^1.6.5: + version "1.6.7" + resolved "https://registry.yarnpkg.com/extract-zip/-/extract-zip-1.6.7.tgz#a840b4b8af6403264c8db57f4f1a74333ef81fe9" dependencies: - concat-stream "1.6.0" - debug "2.2.0" - mkdirp "0.5.0" + concat-stream "1.6.2" + debug "2.6.9" + mkdirp "0.5.1" yauzl "2.4.1" -extsprintf@1.3.0, extsprintf@^1.2.0: +extsprintf@1.3.0: version "1.3.0" resolved "https://registry.yarnpkg.com/extsprintf/-/extsprintf-1.3.0.tgz#96918440e3041a7a414f8c52e3c574eb3c3e1e05" +extsprintf@^1.2.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/extsprintf/-/extsprintf-1.4.0.tgz#e2689f8f356fad62cca65a3a91c5df5f9551692f" + fancy-log@^1.1.0: - version "1.3.0" - resolved "https://registry.yarnpkg.com/fancy-log/-/fancy-log-1.3.0.tgz#45be17d02bb9917d60ccffd4995c999e6c8c9948" + version "1.3.2" + resolved "https://registry.yarnpkg.com/fancy-log/-/fancy-log-1.3.2.tgz#f41125e3d84f2e7d89a43d06d958c8f78be16be1" dependencies: - chalk "^1.1.1" + ansi-gray "^0.1.1" + color-support "^1.1.3" time-stamp "^1.0.0" fast-deep-equal@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-1.0.0.tgz#96256a3bc975595eb36d82e9929d060d893439ff" + version "1.1.0" + resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-1.1.0.tgz#c053477817c86b51daa853c81e059b733d023614" + +fast-deep-equal@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-2.0.1.tgz#7b05218ddf9667bf7f370bf7fdb2cb15fdd0aa49" + +fast-glob@^2.0.2: + version "2.2.2" + resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-2.2.2.tgz#71723338ac9b4e0e2fff1d6748a2a13d5ed352bf" + dependencies: + "@mrmlnc/readdir-enhanced" "^2.2.1" + "@nodelib/fs.stat" "^1.0.1" + glob-parent "^3.1.0" + is-glob "^4.0.0" + merge2 "^1.2.1" + micromatch "^3.1.10" fast-json-stable-stringify@^2.0.0: version "2.0.0" @@ -3120,6 +3397,12 @@ fd-slicer@~1.0.1: dependencies: pend "~1.2.0" +figures@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/figures/-/figures-2.0.0.tgz#3ab1a2d2a62c8bfb431a0c94cb797a2fce27c962" + dependencies: + escape-string-regexp "^1.0.5" + file-uri-to-path@1: version "1.0.0" resolved "https://registry.yarnpkg.com/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz#553a7b8446ff6f684359c445f1e37a05dacc33dd" @@ -3129,16 +3412,16 @@ filename-regex@^2.0.0: resolved "https://registry.yarnpkg.com/filename-regex/-/filename-regex-2.0.1.tgz#c1c4b9bee3e09725ddb106b75c1e301fe2f18b26" filesize@^3.5.11: - version "3.6.0" - resolved "https://registry.yarnpkg.com/filesize/-/filesize-3.6.0.tgz#22d079615624bb6fd3c04026120628a41b3f4efa" + version "3.6.1" + resolved "https://registry.yarnpkg.com/filesize/-/filesize-3.6.1.tgz#090bb3ee01b6f801a8a8be99d31710b3422bb317" fill-range@^2.1.0: - version "2.2.3" - resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-2.2.3.tgz#50b77dfd7e469bc7492470963699fe7a8485a723" + version "2.2.4" + resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-2.2.4.tgz#eb1e773abb056dcd8df2bfdf6af59b8b3a936565" dependencies: is-number "^2.1.0" isobject "^2.0.0" - randomatic "^1.1.3" + randomatic "^3.0.0" repeat-element "^1.1.2" repeat-string "^1.5.2" @@ -3151,18 +3434,6 @@ fill-range@^4.0.0: repeat-string "^1.6.1" to-regex-range "^2.1.0" -finalhandler@1.0.6: - version "1.0.6" - resolved "https://registry.yarnpkg.com/finalhandler/-/finalhandler-1.0.6.tgz#007aea33d1a4d3e42017f624848ad58d212f814f" - dependencies: - debug "2.6.9" - encodeurl "~1.0.1" - escape-html "~1.0.3" - on-finished "~2.3.0" - parseurl "~1.3.2" - statuses "~1.3.1" - unpipe "~1.0.0" - finalhandler@1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/finalhandler/-/finalhandler-1.1.0.tgz#ce0b6855b45853e791b2fcc680046d88253dd7f5" @@ -3175,6 +3446,18 @@ finalhandler@1.1.0: statuses "~1.3.1" unpipe "~1.0.0" +finalhandler@1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/finalhandler/-/finalhandler-1.1.1.tgz#eebf4ed840079c83f4249038c9d703008301b105" + dependencies: + debug "2.6.9" + encodeurl "~1.0.2" + escape-html "~1.0.3" + on-finished "~2.3.0" + parseurl "~1.3.2" + statuses "~1.4.0" + unpipe "~1.0.0" + find-cache-dir@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/find-cache-dir/-/find-cache-dir-1.0.0.tgz#9288e3e9e3cc3748717d39eade17cf71fc30ee6f" @@ -3201,8 +3484,8 @@ flatten@^1.0.2: resolved "https://registry.yarnpkg.com/flatten/-/flatten-1.0.2.tgz#dae46a9d78fbe25292258cc1e780a41d95c03782" flush-write-stream@^1.0.0: - version "1.0.2" - resolved "https://registry.yarnpkg.com/flush-write-stream/-/flush-write-stream-1.0.2.tgz#c81b90d8746766f1a609a46809946c45dd8ae417" + version "1.0.3" + resolved "https://registry.yarnpkg.com/flush-write-stream/-/flush-write-stream-1.0.3.tgz#c5d586ef38af6097650b49bc41b55fabb19f35bd" dependencies: inherits "^2.0.1" readable-stream "^2.0.4" @@ -3213,6 +3496,12 @@ follow-redirects@1.0.0: dependencies: debug "^2.2.0" +follow-redirects@^1.0.0: + version "1.5.7" + resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.5.7.tgz#a39e4804dacb90202bca76a9e2ac10433ca6a69a" + dependencies: + debug "^3.1.0" + font-awesome@4.7.0: version "4.7.0" resolved "https://registry.yarnpkg.com/font-awesome/-/font-awesome-4.7.0.tgz#8fa8cf0411a1a31afd07b06d2902bb9fc815a133" @@ -3237,10 +3526,6 @@ for-own@^1.0.0: dependencies: for-in "^1.0.1" -foreach@^2.0.5: - version "2.0.5" - resolved "https://registry.yarnpkg.com/foreach/-/foreach-2.0.5.tgz#0bee005018aeb260d0a3af3ae658dd0136ec1b99" - forever-agent@~0.6.1: version "0.6.1" resolved "https://registry.yarnpkg.com/forever-agent/-/forever-agent-0.6.1.tgz#fbc71f0c41adeb37f96c577ad1ed42d8fdacca91" @@ -3253,20 +3538,12 @@ form-data@~2.0.0: combined-stream "^1.0.5" mime-types "^2.1.11" -form-data@~2.1.1: - version "2.1.4" - resolved "https://registry.yarnpkg.com/form-data/-/form-data-2.1.4.tgz#33c183acf193276ecaa98143a69e94bfee1750d1" +form-data@~2.3.0, form-data@~2.3.1, form-data@~2.3.2: + version "2.3.2" + resolved "https://registry.yarnpkg.com/form-data/-/form-data-2.3.2.tgz#4970498be604c20c005d4f5c23aecd21d6b49099" dependencies: asynckit "^0.4.0" - combined-stream "^1.0.5" - mime-types "^2.1.12" - -form-data@~2.3.1: - version "2.3.1" - resolved "https://registry.yarnpkg.com/form-data/-/form-data-2.3.1.tgz#6fb94fbd71885306d73d15cc497fe4cc4ecd44bf" - dependencies: - asynckit "^0.4.0" - combined-stream "^1.0.5" + combined-stream "1.0.6" mime-types "^2.1.12" forwarded@~0.1.2: @@ -3300,6 +3577,10 @@ fs-access@^1.0.0: dependencies: null-check "^1.0.0" +fs-constants@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/fs-constants/-/fs-constants-1.0.0.tgz#6be0de9be998ce16af8afc24497b9ee9b7ccd9ad" + fs-extra@^0.22.1: version "0.22.1" resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-0.22.1.tgz#5fd6f8049dc976ca19eb2355d658173cabcce056" @@ -3308,6 +3589,14 @@ fs-extra@^0.22.1: jsonfile "^2.1.0" rimraf "^2.2.8" +fs-extra@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-1.0.0.tgz#cd3ce5f7e7cb6145883fcae3191e9877f8587950" + dependencies: + graceful-fs "^4.1.2" + jsonfile "^2.1.0" + klaw "^1.0.0" + fs-extra@^4.0.0: version "4.0.3" resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-4.0.3.tgz#0d852122e5bc5beb453fb028e9c0c9bf36340c94" @@ -3324,13 +3613,11 @@ fs-extra@^5.0.0: jsonfile "^4.0.0" universalify "^0.1.0" -fs-extra@~1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-1.0.0.tgz#cd3ce5f7e7cb6145883fcae3191e9877f8587950" +fs-minipass@^1.2.5: + version "1.2.5" + resolved "https://registry.yarnpkg.com/fs-minipass/-/fs-minipass-1.2.5.tgz#06c277218454ec288df77ada54a03b8702aacb9d" dependencies: - graceful-fs "^4.1.2" - jsonfile "^2.1.0" - klaw "^1.0.0" + minipass "^2.2.1" fs-write-stream-atomic@^1.0.8: version "1.0.10" @@ -3345,22 +3632,14 @@ fs.realpath@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" -fsevents@^1.0.0: - version "1.1.2" - resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-1.1.2.tgz#3282b713fb3ad80ede0e9fcf4611b5aa6fc033f4" +fsevents@^1.0.0, fsevents@^1.2.2: + version "1.2.4" + resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-1.2.4.tgz#f41dcb1af2582af3692da36fc55cbd8e1041c426" dependencies: - nan "^2.3.0" - node-pre-gyp "^0.6.36" + nan "^2.9.2" + node-pre-gyp "^0.10.0" -fstream-ignore@^1.0.5: - version "1.0.5" - resolved "https://registry.yarnpkg.com/fstream-ignore/-/fstream-ignore-1.0.5.tgz#9c31dae34767018fe1d249b24dada67d092da105" - dependencies: - fstream "^1.0.0" - inherits "2" - minimatch "^3.0.0" - -fstream@^1.0.0, fstream@^1.0.10, fstream@^1.0.2: +fstream@^1.0.0, fstream@^1.0.2: version "1.0.11" resolved "https://registry.yarnpkg.com/fstream/-/fstream-1.0.11.tgz#5c1fb1f117477114f0632a0eb4b71b3cb0fd3171" dependencies: @@ -3376,7 +3655,7 @@ ftp@~0.3.10: readable-stream "1.1.x" xregexp "2.0.0" -function-bind@^1.0.2, function-bind@^1.1.1: +function-bind@^1.0.2, function-bind@^1.1.0, function-bind@^1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.1.tgz#a56899d3ea3c9bab874bb9773b7c5ede92f4895d" @@ -3394,8 +3673,8 @@ gauge@~2.7.3: wide-align "^1.1.0" gaze@^1.0.0: - version "1.1.2" - resolved "https://registry.yarnpkg.com/gaze/-/gaze-1.1.2.tgz#847224677adb8870d679257ed3388fdb61e40105" + version "1.1.3" + resolved "https://registry.yarnpkg.com/gaze/-/gaze-1.1.3.tgz#c441733e13b927ac8c0ff0b4c3b033f28812924a" dependencies: globule "^1.0.0" @@ -3409,25 +3688,29 @@ generate-object-property@^1.1.0: dependencies: is-property "^1.0.0" +get-assigned-identifiers@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/get-assigned-identifiers/-/get-assigned-identifiers-1.2.0.tgz#6dbf411de648cbaf8d9169ebb0d2d576191e2ff1" + get-caller-file@^1.0.1: - version "1.0.2" - resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-1.0.2.tgz#f702e63127e7e231c160a80c1554acb70d5047e5" + version "1.0.3" + resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-1.0.3.tgz#f978fa4c90d1dfe7ff2d6beda2a515e713bdcf4a" get-stdin@^4.0.1: version "4.0.1" resolved "https://registry.yarnpkg.com/get-stdin/-/get-stdin-4.0.1.tgz#b968c6b0a04384324902e8bf1a5df32579a450fe" -get-stdin@^5.0.1: - version "5.0.1" - resolved "https://registry.yarnpkg.com/get-stdin/-/get-stdin-5.0.1.tgz#122e161591e21ff4c52530305693f20e6393a398" +get-stdin@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/get-stdin/-/get-stdin-6.0.0.tgz#9e09bf712b360ab9225e812048f71fde9c89657b" get-stream@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-3.0.0.tgz#8e943d1358dc37555054ecbe2edb05aa174ede14" -get-uri@2: - version "2.0.1" - resolved "https://registry.yarnpkg.com/get-uri/-/get-uri-2.0.1.tgz#dbdcacacd8c608a38316869368117697a1631c59" +get-uri@^2.0.0: + version "2.0.2" + resolved "https://registry.yarnpkg.com/get-uri/-/get-uri-2.0.2.tgz#5c795e71326f6ca1286f2fc82575cd2bab2af578" dependencies: data-uri-to-buffer "1" debug "2" @@ -3466,6 +3749,10 @@ glob-parent@^3.1.0: is-glob "^3.1.0" path-dirname "^1.0.0" +glob-to-regexp@^0.3.0: + version "0.3.0" + resolved "https://registry.yarnpkg.com/glob-to-regexp/-/glob-to-regexp-0.3.0.tgz#8c5a1494d2066c570cc3bfe4496175acc4d502ab" + glob@^5.0.15: version "5.0.15" resolved "https://registry.yarnpkg.com/glob/-/glob-5.0.15.tgz#1bc936b9e02f4a603fcc222ecf7633d30b8b93b1" @@ -3539,23 +3826,35 @@ globby@^7.1.1: pify "^3.0.0" slash "^1.0.0" +globby@^8.0.0: + version "8.0.1" + resolved "https://registry.yarnpkg.com/globby/-/globby-8.0.1.tgz#b5ad48b8aa80b35b814fc1281ecc851f1d2b5b50" + dependencies: + array-union "^1.0.1" + dir-glob "^2.0.0" + fast-glob "^2.0.2" + glob "^7.1.2" + ignore "^3.3.5" + pify "^3.0.0" + slash "^1.0.0" + globule@^1.0.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/globule/-/globule-1.2.0.tgz#1dc49c6822dd9e8a2fa00ba2a295006e8664bd09" + version "1.2.1" + resolved "https://registry.yarnpkg.com/globule/-/globule-1.2.1.tgz#5dffb1b191f22d20797a9369b49eab4e9839696d" dependencies: glob "~7.1.1" - lodash "~4.17.4" + lodash "~4.17.10" minimatch "~3.0.2" glogg@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/glogg/-/glogg-1.0.0.tgz#7fe0f199f57ac906cf512feead8f90ee4a284fc5" + version "1.0.1" + resolved "https://registry.yarnpkg.com/glogg/-/glogg-1.0.1.tgz#dcf758e44789cc3f3d32c1f3562a3676e6a34810" dependencies: sparkles "^1.0.0" gonzales-pe@^4.0.3: - version "4.2.2" - resolved "https://registry.yarnpkg.com/gonzales-pe/-/gonzales-pe-4.2.2.tgz#f50a8c17842f13a9007909b7cb32188266e4d74c" + version "4.2.3" + resolved "https://registry.yarnpkg.com/gonzales-pe/-/gonzales-pe-4.2.3.tgz#41091703625433285e0aee3aa47829fc1fbeb6f2" dependencies: minimist "1.1.x" @@ -3620,8 +3919,8 @@ handle-thing@^1.2.5: resolved "https://registry.yarnpkg.com/handle-thing/-/handle-thing-1.2.5.tgz#fd7aad726bf1a5fd16dfc29b2f7a6601d27139c4" handlebars@^4.0.1, handlebars@^4.0.6: - version "4.0.10" - resolved "https://registry.yarnpkg.com/handlebars/-/handlebars-4.0.10.tgz#3d30c718b09a3d96f23ea4cc1f403c4d3ba9ff4f" + version "4.0.11" + resolved "https://registry.yarnpkg.com/handlebars/-/handlebars-4.0.11.tgz#630a35dfe0294bc281edae6ffc5d329fc7982dcc" dependencies: async "^1.4.0" optimist "^0.6.1" @@ -3629,10 +3928,6 @@ handlebars@^4.0.1, handlebars@^4.0.6: optionalDependencies: uglify-js "^2.6" -har-schema@^1.0.5: - version "1.0.5" - resolved "https://registry.yarnpkg.com/har-schema/-/har-schema-1.0.5.tgz#d263135f43307c02c602afc8fe95970c0151369e" - har-schema@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/har-schema/-/har-schema-2.0.0.tgz#a94c2224ebcac04782a0d9035521f24735b7ec92" @@ -3646,13 +3941,6 @@ har-validator@~2.0.6: is-my-json-valid "^2.12.4" pinkie-promise "^2.0.0" -har-validator@~4.2.1: - version "4.2.1" - resolved "https://registry.yarnpkg.com/har-validator/-/har-validator-4.2.1.tgz#33481d0f1bbff600dd203d75812a6a5fba002e2a" - dependencies: - ajv "^4.9.1" - har-schema "^1.0.5" - har-validator@~5.0.3: version "5.0.3" resolved "https://registry.yarnpkg.com/har-validator/-/har-validator-5.0.3.tgz#ba402c266194f15956ef15e0fcf242993f6a7dfd" @@ -3660,6 +3948,13 @@ har-validator@~5.0.3: ajv "^5.1.0" har-schema "^2.0.0" +har-validator@~5.1.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/har-validator/-/har-validator-5.1.0.tgz#44657f5688a22cfd4b72486e81b3a3fb11742c29" + dependencies: + ajv "^5.3.0" + har-schema "^2.0.0" + has-ansi@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/has-ansi/-/has-ansi-2.0.0.tgz#34f5049ce1ecdf2b0649af3ef24e45ed35416d91" @@ -3667,8 +3962,8 @@ has-ansi@^2.0.0: ansi-regex "^2.0.0" has-binary2@~1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/has-binary2/-/has-binary2-1.0.2.tgz#e83dba49f0b9be4d026d27365350d9f03f54be98" + version "1.0.3" + resolved "https://registry.yarnpkg.com/has-binary2/-/has-binary2-1.0.3.tgz#7776ac627f3ea77250cfc332dab7ddf5e4f5d11d" dependencies: isarray "2.0.1" @@ -3680,10 +3975,6 @@ has-flag@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-1.0.0.tgz#9d9e793165ce017a00f00418c43f942a7b1d11fa" -has-flag@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-2.0.0.tgz#e8207af1cc7b30d446cc70b734b5e8be18f88d51" - has-flag@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-3.0.0.tgz#b5d454dc2199ae225699f3467e5a07f3b955bafd" @@ -3694,6 +3985,10 @@ has-gulplog@^0.1.0: dependencies: sparkles "^1.0.0" +has-symbols@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.0.0.tgz#ba1a8f1af2a0fc39650f5c850367704122063b44" + has-unicode@^2.0.0: version "2.0.1" resolved "https://registry.yarnpkg.com/has-unicode/-/has-unicode-2.0.1.tgz#e0e6fe6a28cf51138855e086d1691e771de2a8b9" @@ -3726,16 +4021,10 @@ has-values@^1.0.0: kind-of "^4.0.0" has@^1.0.0, has@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/has/-/has-1.0.1.tgz#8461733f538b0837c9361e39a9ab9e9704dc2f28" + version "1.0.3" + resolved "https://registry.yarnpkg.com/has/-/has-1.0.3.tgz#722d7cbfc1f6aa8241f16dd814e011e1f41e8796" dependencies: - function-bind "^1.0.2" - -hash-base@^2.0.0: - version "2.0.2" - resolved "https://registry.yarnpkg.com/hash-base/-/hash-base-2.0.2.tgz#66ea1d856db4e8a5470cadf6fce23ae5244ef2e1" - dependencies: - inherits "^2.0.1" + function-bind "^1.1.1" hash-base@^3.0.0: version "3.0.4" @@ -3745,20 +4034,20 @@ hash-base@^3.0.0: safe-buffer "^5.0.1" hash.js@^1.0.0, hash.js@^1.0.3: - version "1.1.3" - resolved "https://registry.yarnpkg.com/hash.js/-/hash.js-1.1.3.tgz#340dedbe6290187151c1ea1d777a3448935df846" + version "1.1.5" + resolved "https://registry.yarnpkg.com/hash.js/-/hash.js-1.1.5.tgz#e38ab4b85dfb1e0c40fe9265c0e9b54854c23812" dependencies: inherits "^2.0.3" - minimalistic-assert "^1.0.0" + minimalistic-assert "^1.0.1" -hasha@~2.2.0: +hasha@^2.2.0: version "2.2.0" resolved "https://registry.yarnpkg.com/hasha/-/hasha-2.2.0.tgz#78d7cbfc1e6d66303fe79837365984517b2f6ee1" dependencies: is-stream "^1.0.1" pinkie-promise "^2.0.0" -hawk@3.1.3, hawk@~3.1.3: +hawk@~3.1.3: version "3.1.3" resolved "https://registry.yarnpkg.com/hawk/-/hawk-3.1.3.tgz#078444bd7c1640b0fe540d2c9b73d59678e8e1c4" dependencies: @@ -3804,8 +4093,8 @@ hoek@2.x.x: resolved "https://registry.yarnpkg.com/hoek/-/hoek-2.16.3.tgz#20bb7403d3cea398e91dc4710a8ff1b8274a25ed" hoek@4.x.x: - version "4.2.0" - resolved "https://registry.yarnpkg.com/hoek/-/hoek-4.2.0.tgz#72d9d0754f7fe25ca2d01ad8f8f9a9449a89526d" + version "4.2.1" + resolved "https://registry.yarnpkg.com/hoek/-/hoek-4.2.1.tgz#9634502aa12c445dd5a7c5734b572bb8738aacbb" homedir-polyfill@^1.0.1: version "1.0.1" @@ -3814,8 +4103,8 @@ homedir-polyfill@^1.0.1: parse-passwd "^1.0.0" hosted-git-info@^2.1.4: - version "2.5.0" - resolved "https://registry.yarnpkg.com/hosted-git-info/-/hosted-git-info-2.5.0.tgz#6d60e34b3abbc8313062c3b798ef8d901a07af3c" + version "2.7.1" + resolved "https://registry.yarnpkg.com/hosted-git-info/-/hosted-git-info-2.7.1.tgz#97f236977bd6e125408930ff6de3eec6281ec047" hpack.js@^2.1.6: version "2.1.6" @@ -3835,28 +4124,28 @@ html-entities@^1.2.0: resolved "https://registry.yarnpkg.com/html-entities/-/html-entities-1.2.1.tgz#0df29351f0721163515dfb9e5543e5f6eed5162f" html-minifier@^3.2.3: - version "3.5.5" - resolved "https://registry.yarnpkg.com/html-minifier/-/html-minifier-3.5.5.tgz#3bdc9427e638bbe3dbde96c0eb988b044f02739e" + version "3.5.20" + resolved "https://registry.yarnpkg.com/html-minifier/-/html-minifier-3.5.20.tgz#7b19fd3caa0cb79f7cde5ee5c3abdf8ecaa6bb14" dependencies: camel-case "3.0.x" - clean-css "4.1.x" - commander "2.11.x" + clean-css "4.2.x" + commander "2.17.x" he "1.1.x" - ncname "1.0.x" param-case "2.1.x" relateurl "0.2.x" - uglify-js "3.1.x" + uglify-js "3.4.x" -html-webpack-plugin@2.30.1: - version "2.30.1" - resolved "https://registry.yarnpkg.com/html-webpack-plugin/-/html-webpack-plugin-2.30.1.tgz#7f9c421b7ea91ec460f56527d78df484ee7537d5" +html-webpack-plugin@3.2.0: + version "3.2.0" + resolved "https://registry.yarnpkg.com/html-webpack-plugin/-/html-webpack-plugin-3.2.0.tgz#b01abbd723acaaa7b37b6af4492ebda03d9dd37b" dependencies: - bluebird "^3.4.7" html-minifier "^3.2.3" loader-utils "^0.2.16" lodash "^4.17.3" pretty-error "^2.0.2" + tapable "^1.0.0" toposort "^1.0.0" + util.promisify "1.0.0" htmlescape@^1.1.0: version "1.1.1" @@ -3875,7 +4164,7 @@ http-deceiver@^1.2.7: version "1.2.7" resolved "https://registry.yarnpkg.com/http-deceiver/-/http-deceiver-1.2.7.tgz#fa7168944ab9a519d337cb0bec7284dc3e723d87" -http-errors@1.6.2, http-errors@~1.6.2: +http-errors@1.6.2: version "1.6.2" resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-1.6.2.tgz#0a002cc85707192a7e7946ceedc11155f60ec736" dependencies: @@ -3884,33 +4173,42 @@ http-errors@1.6.2, http-errors@~1.6.2: setprototypeof "1.0.3" statuses ">= 1.3.1 < 2" -http-parser-js@>=0.4.0: - version "0.4.8" - resolved "https://registry.yarnpkg.com/http-parser-js/-/http-parser-js-0.4.8.tgz#763f75c4b771a0bb44653b07070bff6ca7bc5561" - -http-proxy-agent@1: - version "1.0.0" - resolved "https://registry.yarnpkg.com/http-proxy-agent/-/http-proxy-agent-1.0.0.tgz#cc1ce38e453bf984a0f7702d2dd59c73d081284a" +http-errors@1.6.3, http-errors@~1.6.2, http-errors@~1.6.3: + version "1.6.3" + resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-1.6.3.tgz#8b55680bb4be283a0b5bf4ea2e38580be1d9320d" dependencies: - agent-base "2" - debug "2" - extend "3" + depd "~1.1.2" + inherits "2.0.3" + setprototypeof "1.1.0" + statuses ">= 1.4.0 < 2" -http-proxy-middleware@~0.17.4: - version "0.17.4" - resolved "https://registry.yarnpkg.com/http-proxy-middleware/-/http-proxy-middleware-0.17.4.tgz#642e8848851d66f09d4f124912846dbaeb41b833" +http-parser-js@>=0.4.0: + version "0.4.13" + resolved "https://registry.yarnpkg.com/http-parser-js/-/http-parser-js-0.4.13.tgz#3bd6d6fde6e3172c9334c3b33b6c193d80fe1137" + +http-proxy-agent@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/http-proxy-agent/-/http-proxy-agent-2.1.0.tgz#e4821beef5b2142a2026bd73926fe537631c5405" + dependencies: + agent-base "4" + debug "3.1.0" + +http-proxy-middleware@~0.18.0: + version "0.18.0" + resolved "https://registry.yarnpkg.com/http-proxy-middleware/-/http-proxy-middleware-0.18.0.tgz#0987e6bb5a5606e5a69168d8f967a87f15dd8aab" dependencies: http-proxy "^1.16.2" - is-glob "^3.1.0" - lodash "^4.17.2" - micromatch "^2.3.11" + is-glob "^4.0.0" + lodash "^4.17.5" + micromatch "^3.1.9" http-proxy@^1.13.0, http-proxy@^1.16.2, http-proxy@^1.8.1: - version "1.16.2" - resolved "https://registry.yarnpkg.com/http-proxy/-/http-proxy-1.16.2.tgz#06dff292952bf64dbe8471fa9df73066d4f37742" + version "1.17.0" + resolved "https://registry.yarnpkg.com/http-proxy/-/http-proxy-1.17.0.tgz#7ad38494658f84605e2f6db4436df410f4e5be9a" dependencies: - eventemitter3 "1.x.x" - requires-port "1.x.x" + eventemitter3 "^3.0.0" + follow-redirects "^1.0.0" + requires-port "^1.0.0" http-server@0.11.1: version "0.11.1" @@ -3952,21 +4250,16 @@ httpreq@>=0.4.22: version "0.4.24" resolved "https://registry.yarnpkg.com/httpreq/-/httpreq-0.4.24.tgz#4335ffd82cd969668a39465c929ac61d6393627f" -https-browserify@0.0.1: - version "0.0.1" - resolved "https://registry.yarnpkg.com/https-browserify/-/https-browserify-0.0.1.tgz#3f91365cabe60b77ed0ebba24b454e3e09d95a82" - https-browserify@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/https-browserify/-/https-browserify-1.0.0.tgz#ec06c10e0a34c0f2faf199f7fd7fc78fffd03c73" -https-proxy-agent@1, https-proxy-agent@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/https-proxy-agent/-/https-proxy-agent-1.0.0.tgz#35f7da6c48ce4ddbfa264891ac593ee5ff8671e6" +https-proxy-agent@^2.2.1: + version "2.2.1" + resolved "https://registry.yarnpkg.com/https-proxy-agent/-/https-proxy-agent-2.2.1.tgz#51552970fa04d723e04c56d04178c3f92592bbc0" dependencies: - agent-base "2" - debug "2" - extend "3" + agent-base "^4.1.0" + debug "^3.1.0" https@1.0.0: version "1.0.0" @@ -3980,6 +4273,18 @@ iconv-lite@0.4.19: version "0.4.19" resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.19.tgz#f7468f60135f5e5dad3399c0a81be9a1603a082b" +iconv-lite@0.4.23: + version "0.4.23" + resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.23.tgz#297871f63be507adcfbfca715d0cd0eed84e9a63" + dependencies: + safer-buffer ">= 2.1.2 < 3" + +iconv-lite@^0.4.17, iconv-lite@^0.4.4, iconv-lite@~0.4.13: + version "0.4.24" + resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.24.tgz#2022b4b25fbddc21d2f524974a474aafe733908b" + dependencies: + safer-buffer ">= 2.1.2 < 3" + icss-replace-symbols@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/icss-replace-symbols/-/icss-replace-symbols-1.1.0.tgz#06ea6f83679a7749e386cfe1fe812ae5db223ded" @@ -3990,9 +4295,9 @@ icss-utils@^2.1.0: dependencies: postcss "^6.0.1" -ieee754@^1.1.4: - version "1.1.8" - resolved "https://registry.yarnpkg.com/ieee754/-/ieee754-1.1.8.tgz#be33d40ac10ef1926701f6f08a2d86fbfd1ad3e4" +ieee754@^1.1.11, ieee754@^1.1.4: + version "1.1.12" + resolved "https://registry.yarnpkg.com/ieee754/-/ieee754-1.1.12.tgz#50bf24e5b9c8bb98af4964c941cdb0918da7b60b" iferr@^0.1.5: version "0.1.5" @@ -4002,14 +4307,32 @@ ignore-by-default@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/ignore-by-default/-/ignore-by-default-1.0.1.tgz#48ca6d72f6c6a3af00a9ad4ae6876be3889e2b09" +ignore-walk@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/ignore-walk/-/ignore-walk-3.0.1.tgz#a83e62e7d272ac0e3b551aaa82831a19b69f82f8" + dependencies: + minimatch "^3.0.4" + ignore@^3.3.5: - version "3.3.7" - resolved "https://registry.yarnpkg.com/ignore/-/ignore-3.3.7.tgz#612289bfb3c220e186a58118618d5be8c1bab021" + version "3.3.10" + resolved "https://registry.yarnpkg.com/ignore/-/ignore-3.3.10.tgz#0a97fb876986e8081c631160f8f9f389157f0043" immediate@~3.0.5: version "3.0.6" resolved "https://registry.yarnpkg.com/immediate/-/immediate-3.0.6.tgz#9db1dbd0faf8de6fbe0f5dd5e56bb606280de69b" +import-cwd@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/import-cwd/-/import-cwd-2.1.0.tgz#aa6cf36e722761285cb371ec6519f53e2435b0a9" + dependencies: + import-from "^2.1.0" + +import-from@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/import-from/-/import-from-2.1.0.tgz#335db7f2a7affd53aaa471d4b8021dee36b7f3b1" + dependencies: + resolve-from "^3.0.0" + import-lazy@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/import-lazy/-/import-lazy-2.1.0.tgz#05698e3d45c88e8d7e9d92cb0584e77f096f3e43" @@ -4042,6 +4365,10 @@ indent-string@^2.1.0: dependencies: repeating "^2.0.0" +indent-string@^3.0.0: + version "3.2.0" + resolved "https://registry.yarnpkg.com/indent-string/-/indent-string-3.2.0.tgz#4a5fd6d27cc332f37e5419a504dbb837105c9289" + indexes-of@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/indexes-of/-/indexes-of-1.0.1.tgz#f30f716c8e2bd346c7b67d3df3915566a7c05607" @@ -4050,9 +4377,9 @@ indexof@0.0.1: version "0.0.1" resolved "https://registry.yarnpkg.com/indexof/-/indexof-0.0.1.tgz#82dc336d232b9062179d05ab3293a66059fd435d" -inflection@~1.10.0: - version "1.10.0" - resolved "https://registry.yarnpkg.com/inflection/-/inflection-1.10.0.tgz#5bffcb1197ad3e81050f8e17e21668087ee9eb2f" +inflection@~1.12.0: + version "1.12.0" + resolved "https://registry.yarnpkg.com/inflection/-/inflection-1.12.0.tgz#a200935656d6f5f6bc4dc7502e1aecb703228416" inflection@~1.3.0: version "1.3.8" @@ -4074,8 +4401,8 @@ inherits@2.0.1: resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.1.tgz#b17d08d326b4423e568eff719f91b0b1cbdf69f1" ini@^1.3.4, ini@~1.3.0: - version "1.3.4" - resolved "https://registry.yarnpkg.com/ini/-/ini-1.3.4.tgz#0537cb79daf59b59a1a517dff706c86ec039162e" + version "1.3.5" + resolved "https://registry.yarnpkg.com/ini/-/ini-1.3.5.tgz#eee25f56db1c9ec6085e0c22778083f596abf927" inline-source-map@~0.6.0: version "0.6.2" @@ -4083,17 +4410,37 @@ inline-source-map@~0.6.0: dependencies: source-map "~0.5.3" +inquirer@3.0.6: + version "3.0.6" + resolved "https://registry.yarnpkg.com/inquirer/-/inquirer-3.0.6.tgz#e04aaa9d05b7a3cb9b0f407d04375f0447190347" + dependencies: + ansi-escapes "^1.1.0" + chalk "^1.0.0" + cli-cursor "^2.1.0" + cli-width "^2.0.0" + external-editor "^2.0.1" + figures "^2.0.0" + lodash "^4.3.0" + mute-stream "0.0.7" + run-async "^2.2.0" + rx "^4.1.0" + string-width "^2.0.0" + strip-ansi "^3.0.0" + through "^2.3.6" + insert-module-globals@^7.0.0: - version "7.0.1" - resolved "https://registry.yarnpkg.com/insert-module-globals/-/insert-module-globals-7.0.1.tgz#c03bf4e01cb086d5b5e5ace8ad0afe7889d638c3" + version "7.2.0" + resolved "https://registry.yarnpkg.com/insert-module-globals/-/insert-module-globals-7.2.0.tgz#ec87e5b42728479e327bd5c5c71611ddfb4752ba" dependencies: JSONStream "^1.0.3" - combine-source-map "~0.7.1" - concat-stream "~1.5.1" + acorn-node "^1.5.2" + combine-source-map "^0.8.0" + concat-stream "^1.6.1" is-buffer "^1.1.0" - lexical-scope "^1.2.0" + path-is-absolute "^1.0.1" process "~0.11.0" through2 "^2.0.0" + undeclared-identifiers "^1.1.2" xtend "^4.0.0" internal-ip@1.2.0: @@ -4103,12 +4450,12 @@ internal-ip@1.2.0: meow "^3.3.0" interpret@^1.0.0: - version "1.0.4" - resolved "https://registry.yarnpkg.com/interpret/-/interpret-1.0.4.tgz#820cdd588b868ffb191a809506d6c9c8f212b1b0" + version "1.1.0" + resolved "https://registry.yarnpkg.com/interpret/-/interpret-1.1.0.tgz#7ed1b1410c6a0e0f78cf95d3b8440c63f78b8614" invariant@^2.2.2: - version "2.2.2" - resolved "https://registry.yarnpkg.com/invariant/-/invariant-2.2.2.tgz#9e1f56ac0acdb6bf303306f338be3b204ae60360" + version "2.2.4" + resolved "https://registry.yarnpkg.com/invariant/-/invariant-2.2.4.tgz#610f3c92c9359ce1db616e538008d23ff35158e6" dependencies: loose-envify "^1.0.0" @@ -4116,17 +4463,17 @@ invert-kv@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/invert-kv/-/invert-kv-1.0.0.tgz#104a8e4aaca6d3d8cd157a8ef8bfab2d7a3ffdb6" -ip@1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/ip/-/ip-1.0.1.tgz#c7e356cdea225ae71b36d70f2e71a92ba4e42590" - ip@^1.1.0, ip@^1.1.2, ip@^1.1.4, ip@^1.1.5: version "1.1.5" resolved "https://registry.yarnpkg.com/ip/-/ip-1.1.5.tgz#bdded70114290828c0a039e72ef25f5aaec4354a" -ipaddr.js@1.5.2: - version "1.5.2" - resolved "https://registry.yarnpkg.com/ipaddr.js/-/ipaddr.js-1.5.2.tgz#d4b505bde9946987ccf0fc58d9010ff9607e3fa0" +ipaddr.js@1.8.0: + version "1.8.0" + resolved "https://registry.yarnpkg.com/ipaddr.js/-/ipaddr.js-1.8.0.tgz#eaa33d6ddd7ace8f7f6fe0c9ca0440e706738b1e" + +irregular-plurals@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/irregular-plurals/-/irregular-plurals-2.0.0.tgz#39d40f05b00f656d0b7fa471230dd3b714af2872" is-absolute-url@^2.0.0: version "2.1.0" @@ -4138,13 +4485,19 @@ is-accessor-descriptor@^0.1.6: dependencies: kind-of "^3.0.2" +is-accessor-descriptor@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz#169c2f6d3df1f992618072365c9b0ea1f6878656" + dependencies: + kind-of "^6.0.0" + is-arrayish@^0.2.1: version "0.2.1" resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.2.1.tgz#77c99840527aa8ecb1a8ba697b80645a7a926a9d" is-arrayish@^0.3.1: - version "0.3.1" - resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.3.1.tgz#c2dfc386abaa0c3e33c48db3fe87059e69065efd" + version "0.3.2" + resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.3.2.tgz#4574a2ae56f7ab206896fb431eaeed066fdf8f03" is-binary-path@^1.0.0: version "1.0.1" @@ -4152,11 +4505,7 @@ is-binary-path@^1.0.0: dependencies: binary-extensions "^1.0.0" -is-buffer@^1.0.2, is-buffer@^1.1.5, is-buffer@~1.1.1: - version "1.1.5" - resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-1.1.5.tgz#1f3b26ef613b214b88cbca23cc6c01d87961eecc" - -is-buffer@^1.1.0: +is-buffer@^1.0.2, is-buffer@^1.1.0, is-buffer@^1.1.5, is-buffer@~1.1.1: version "1.1.6" resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-1.1.6.tgz#efaa2ea9daa0d7ab2ea13a97b2b8ad51fefbe8be" @@ -4167,8 +4516,14 @@ is-builtin-module@^1.0.0: builtin-modules "^1.0.0" is-callable@^1.1.1, is-callable@^1.1.3: - version "1.1.3" - resolved "https://registry.yarnpkg.com/is-callable/-/is-callable-1.1.3.tgz#86eb75392805ddc33af71c92a0eedf74ee7604b2" + version "1.1.4" + resolved "https://registry.yarnpkg.com/is-callable/-/is-callable-1.1.4.tgz#1e1adf219e1eeb684d691f9d6a05ff0d30a24d75" + +is-ci@^1.0.10: + version "1.2.0" + resolved "https://registry.yarnpkg.com/is-ci/-/is-ci-1.2.0.tgz#3f4a08d6303a09882cef3f0fb97439c5f5ce2d53" + dependencies: + ci-info "^1.3.0" is-data-descriptor@^0.1.4: version "0.1.4" @@ -4176,6 +4531,12 @@ is-data-descriptor@^0.1.4: dependencies: kind-of "^3.0.2" +is-data-descriptor@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz#d84876321d0e7add03990406abbbbd36ba9268c7" + dependencies: + kind-of "^6.0.0" + is-date-object@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/is-date-object/-/is-date-object-1.0.1.tgz#9aa20eb6aeebbff77fbd33e74ca01b33581d3a16" @@ -4188,13 +4549,13 @@ is-descriptor@^0.1.0: is-data-descriptor "^0.1.4" kind-of "^5.0.0" -is-descriptor@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/is-descriptor/-/is-descriptor-1.0.1.tgz#2c6023599bde2de9d5d2c8b9a9d94082036b6ef2" +is-descriptor@^1.0.0, is-descriptor@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/is-descriptor/-/is-descriptor-1.0.2.tgz#3b159746a66604b04f8c81524ba365c5f14d86ec" dependencies: - is-accessor-descriptor "^0.1.6" - is-data-descriptor "^0.1.4" - kind-of "^5.0.0" + is-accessor-descriptor "^1.0.0" + is-data-descriptor "^1.0.0" + kind-of "^6.0.2" is-directory@^0.3.1: version "0.3.1" @@ -4273,12 +4634,17 @@ is-module@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/is-module/-/is-module-1.0.0.tgz#3258fb69f78c14d5b815d664336b4cffb6441591" +is-my-ip-valid@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-my-ip-valid/-/is-my-ip-valid-1.0.0.tgz#7b351b8e8edd4d3995d4d066680e664d94696824" + is-my-json-valid@^2.12.4: - version "2.16.1" - resolved "https://registry.yarnpkg.com/is-my-json-valid/-/is-my-json-valid-2.16.1.tgz#5a846777e2c2620d1e69104e5d3a03b1f6088f11" + version "2.19.0" + resolved "https://registry.yarnpkg.com/is-my-json-valid/-/is-my-json-valid-2.19.0.tgz#8fd6e40363cd06b963fa877d444bfb5eddc62175" dependencies: generate-function "^2.0.0" generate-object-property "^1.1.0" + is-my-ip-valid "^1.0.0" jsonpointer "^4.0.0" xtend "^4.0.0" @@ -4302,33 +4668,31 @@ is-number@^3.0.0: dependencies: kind-of "^3.0.2" +is-number@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/is-number/-/is-number-4.0.0.tgz#0026e37f5454d73e356dfe6564699867c6a7f0ff" + is-obj@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/is-obj/-/is-obj-1.0.1.tgz#3e4729ac1f5fde025cd7d83a896dab9f4f67db0f" -is-odd@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/is-odd/-/is-odd-1.0.0.tgz#3b8a932eb028b3775c39bb09e91767accdb69088" - dependencies: - is-number "^3.0.0" - is-path-cwd@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/is-path-cwd/-/is-path-cwd-1.0.0.tgz#d225ec23132e89edd38fda767472e62e65f1106d" is-path-in-cwd@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/is-path-in-cwd/-/is-path-in-cwd-1.0.0.tgz#6477582b8214d602346094567003be8a9eac04dc" + version "1.0.1" + resolved "https://registry.yarnpkg.com/is-path-in-cwd/-/is-path-in-cwd-1.0.1.tgz#5ac48b345ef675339bd6c7a48a912110b241cf52" dependencies: is-path-inside "^1.0.0" is-path-inside@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/is-path-inside/-/is-path-inside-1.0.0.tgz#fc06e5a1683fbda13de667aff717bbc10a48f37f" + version "1.0.1" + resolved "https://registry.yarnpkg.com/is-path-inside/-/is-path-inside-1.0.1.tgz#8ef5b7de50437a3fdca6b4e865ef7aa55cb48036" dependencies: path-is-inside "^1.0.1" -is-plain-obj@^1.0.0: +is-plain-obj@^1.0.0, is-plain-obj@^1.1, is-plain-obj@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/is-plain-obj/-/is-plain-obj-1.1.0.tgz#71a50c8429dfca773c92a390a4a03b39fcd51d3e" @@ -4346,6 +4710,10 @@ is-primitive@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/is-primitive/-/is-primitive-2.0.0.tgz#207bab91638499c07b2adf240a41a87210034575" +is-promise@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/is-promise/-/is-promise-2.1.0.tgz#79a2a9ece7f096e80f36d2b2f3bc16c1ff4bf3fa" + is-property@^1.0.0: version "1.0.2" resolved "https://registry.yarnpkg.com/is-property/-/is-property-1.0.2.tgz#57fe1c4e48474edd65b09911f26b1cd4095dda84" @@ -4386,11 +4754,15 @@ is-utf8@^0.2.0: version "0.2.1" resolved "https://registry.yarnpkg.com/is-utf8/-/is-utf8-0.2.1.tgz#4b0da1442104d1b336340e80797e865cf39f7d72" +is-windows@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/is-windows/-/is-windows-1.0.2.tgz#d1850eb9791ecd18e6182ce12a30f396634bb19d" + is-wsl@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/is-wsl/-/is-wsl-1.1.0.tgz#1f16e4aa22b04d1336b66188a66af3c600c3a66d" -isarray@0.0.1, isarray@~0.0.1: +isarray@0.0.1: version "0.0.1" resolved "https://registry.yarnpkg.com/isarray/-/isarray-0.0.1.tgz#8a18acfca9a8f4177e09abfc6038939b05d1eedf" @@ -4402,9 +4774,15 @@ isarray@2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/isarray/-/isarray-2.0.1.tgz#a37d94ed9cda2d59865c9f76fe596ee1f338741e" +isarray@^2.0.4: + version "2.0.4" + resolved "https://registry.yarnpkg.com/isarray/-/isarray-2.0.4.tgz#38e7bcbb0f3ba1b7933c86ba1894ddfc3781bbb7" + isbinaryfile@^3.0.0: - version "3.0.2" - resolved "https://registry.yarnpkg.com/isbinaryfile/-/isbinaryfile-3.0.2.tgz#4a3e974ec0cba9004d3fc6cde7209ea69368a621" + version "3.0.3" + resolved "https://registry.yarnpkg.com/isbinaryfile/-/isbinaryfile-3.0.3.tgz#5d6def3edebf6e8ca8cae9c30183a804b5f8be80" + dependencies: + buffer-alloc "^1.2.0" isexe@^2.0.0: version "2.0.0" @@ -4428,29 +4806,29 @@ isstream@~0.1.2: version "0.1.2" resolved "https://registry.yarnpkg.com/isstream/-/isstream-0.1.2.tgz#47e63f7af55afa6f92e1500e690eb8b8529c099a" -istanbul-instrumenter-loader@3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/istanbul-instrumenter-loader/-/istanbul-instrumenter-loader-3.0.0.tgz#9f553923b22360bac95e617aaba01add1f7db0b2" +istanbul-instrumenter-loader@3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/istanbul-instrumenter-loader/-/istanbul-instrumenter-loader-3.0.1.tgz#9957bd59252b373fae5c52b7b5188e6fde2a0949" dependencies: convert-source-map "^1.5.0" istanbul-lib-instrument "^1.7.3" loader-utils "^1.1.0" schema-utils "^0.3.0" -istanbul-lib-coverage@^1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/istanbul-lib-coverage/-/istanbul-lib-coverage-1.1.1.tgz#73bfb998885299415c93d38a3e9adf784a77a9da" +istanbul-lib-coverage@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/istanbul-lib-coverage/-/istanbul-lib-coverage-1.2.0.tgz#f7d8f2e42b97e37fe796114cb0f9d68b5e3a4341" istanbul-lib-instrument@^1.7.3: - version "1.8.0" - resolved "https://registry.yarnpkg.com/istanbul-lib-instrument/-/istanbul-lib-instrument-1.8.0.tgz#66f6c9421cc9ec4704f76f2db084ba9078a2b532" + version "1.10.1" + resolved "https://registry.yarnpkg.com/istanbul-lib-instrument/-/istanbul-lib-instrument-1.10.1.tgz#724b4b6caceba8692d3f1f9d0727e279c401af7b" dependencies: babel-generator "^6.18.0" babel-template "^6.16.0" babel-traverse "^6.18.0" babel-types "^6.18.0" babylon "^6.18.0" - istanbul-lib-coverage "^1.1.1" + istanbul-lib-coverage "^1.2.0" semver "^5.3.0" istanbul@0.4.5, istanbul@^0.4.0, istanbul@^0.4.3: @@ -4472,17 +4850,23 @@ istanbul@0.4.5, istanbul@^0.4.0, istanbul@^0.4.3: which "^1.1.1" wordwrap "^1.0.0" -jasmine-core@^2.99.1: - version "2.99.1" - resolved "https://registry.yarnpkg.com/jasmine-core/-/jasmine-core-2.99.1.tgz#e6400df1e6b56e130b61c4bcd093daa7f6e8ca15" +jasmine-core@^3.2.1: + version "3.2.1" + resolved "https://registry.yarnpkg.com/jasmine-core/-/jasmine-core-3.2.1.tgz#8e4ff5b861603ee83343f2b49eee6a0ffe9650ce" jasmine-core@~2.8.0: version "2.8.0" resolved "https://registry.yarnpkg.com/jasmine-core/-/jasmine-core-2.8.0.tgz#bcc979ae1f9fd05701e45e52e65d3a5d63f1a24e" -jasmine-marbles@0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/jasmine-marbles/-/jasmine-marbles-0.2.0.tgz#b893d8508b75790b634876d3a1bea1345d65c156" +jasmine-diff@^0.1.3: + version "0.1.3" + resolved "https://registry.yarnpkg.com/jasmine-diff/-/jasmine-diff-0.1.3.tgz#93ccc2dcc41028c5ddd4606558074839f2deeaa8" + dependencies: + diff "^3.2.0" + +jasmine-marbles@0.3.0: + version "0.3.0" + resolved "https://registry.yarnpkg.com/jasmine-marbles/-/jasmine-marbles-0.3.0.tgz#1e0c75ee68d44d00267dde60021de0800314f8d7" dependencies: lodash "^4.5.0" @@ -4501,24 +4885,28 @@ jasmine@2.8.0: jasmine-core "~2.8.0" jasminewd2@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/jasminewd2/-/jasminewd2-2.1.0.tgz#da595275d1ae631de736ac0a7c7d85c9f73ef652" + version "2.2.0" + resolved "https://registry.yarnpkg.com/jasminewd2/-/jasminewd2-2.2.0.tgz#e37cf0b17f199cce23bea71b2039395246b4ec4e" js-base64@^2.1.8, js-base64@^2.1.9: - version "2.3.2" - resolved "https://registry.yarnpkg.com/js-base64/-/js-base64-2.3.2.tgz#a79a923666372b580f8e27f51845c6f7e8fbfbaf" + version "2.4.8" + resolved "https://registry.yarnpkg.com/js-base64/-/js-base64-2.4.8.tgz#57a9b130888f956834aa40c5b165ba59c758f033" js-cookie@2.2.0: version "2.2.0" resolved "https://registry.yarnpkg.com/js-cookie/-/js-cookie-2.2.0.tgz#1b2c279a6eece380a12168b92485265b35b1effb" -js-tokens@^3.0.0, js-tokens@^3.0.2: +"js-tokens@^3.0.0 || ^4.0.0": + version "4.0.0" + resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499" + +js-tokens@^3.0.2: version "3.0.2" resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-3.0.2.tgz#9866df395102130e38f7f996bceb65443209c25b" -js-yaml@3.x, js-yaml@^3.4.3, js-yaml@^3.6.1, js-yaml@^3.7.0: - version "3.10.0" - resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.10.0.tgz#2e78441646bd4682e963f22b6e92823c309c62dc" +js-yaml@3.x, js-yaml@^3.4.3, js-yaml@^3.6.1, js-yaml@^3.7.0, js-yaml@^3.9.0: + version "3.12.0" + resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.12.0.tgz#eaed656ec8344f10f527c6bfa1b6e2244de167d1" dependencies: argparse "^1.0.7" esprima "^4.0.0" @@ -4546,28 +4934,26 @@ jsesc@~0.5.0: version "0.5.0" resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-0.5.0.tgz#e7dee66e35d6fc16f710fe91d5cf69f70f08911d" -json-loader@0.5.7, json-loader@^0.5.4: +json-loader@0.5.7: version "0.5.7" resolved "https://registry.yarnpkg.com/json-loader/-/json-loader-0.5.7.tgz#dca14a70235ff82f0ac9a3abeb60d337a365185d" -json-parse-better-errors@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/json-parse-better-errors/-/json-parse-better-errors-1.0.1.tgz#50183cd1b2d25275de069e9e71b467ac9eab973a" +json-parse-better-errors@^1.0.1, json-parse-better-errors@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz#bb867cfb3450e69107c131d1c514bab3dc8bcaa9" json-schema-traverse@^0.3.0: version "0.3.1" resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-0.3.1.tgz#349a6d44c53a51de89b40805c5d5e59b417d3340" +json-schema-traverse@^0.4.1: + version "0.4.1" + resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz#69f6a87d9513ab8bb8fe63bdb0979c448e684660" + json-schema@0.2.3: version "0.2.3" resolved "https://registry.yarnpkg.com/json-schema/-/json-schema-0.2.3.tgz#b480c892e59a2f05954ce727bd3f2a4e882f9e13" -json-stable-stringify@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/json-stable-stringify/-/json-stable-stringify-1.0.1.tgz#9a759d39c5f2ff503fd5300646ed445f88c4f9af" - dependencies: - jsonify "~0.0.0" - json-stable-stringify@~0.0.0: version "0.0.1" resolved "https://registry.yarnpkg.com/json-stable-stringify/-/json-stable-stringify-0.0.1.tgz#611c23e814db375527df851193db59dd2af27f45" @@ -4582,7 +4968,7 @@ json3@^3.3.2: version "3.3.2" resolved "https://registry.yarnpkg.com/json3/-/json3-3.3.2.tgz#3c0434743df93e2f5c42aee7b19bcb483575f4e1" -json5@^0.5.0, json5@^0.5.1: +json5@^0.5.0: version "0.5.1" resolved "https://registry.yarnpkg.com/json5/-/json5-0.5.1.tgz#1eade7acc012034ad84e2396767ead9fa5495821" @@ -4710,15 +5096,16 @@ karma-webdriver-launcher@1.0.5: dependencies: wd "^1.0.0" -karma-webpack@2.0.9: - version "2.0.9" - resolved "https://registry.yarnpkg.com/karma-webpack/-/karma-webpack-2.0.9.tgz#61c88091f7dd910635134c032b266a465affb57f" +karma-webpack@3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/karma-webpack/-/karma-webpack-3.0.0.tgz#bf009c5b73c667c11c015717e9e520f581317c44" dependencies: - async "~0.9.0" - loader-utils "^0.2.5" - lodash "^3.8.0" + async "^2.0.0" + babel-runtime "^6.0.0" + loader-utils "^1.0.0" + lodash "^4.0.0" source-map "^0.5.6" - webpack-dev-middleware "^1.12.0" + webpack-dev-middleware "^2.0.6" karma@2.0.0: version "2.0.0" @@ -4753,7 +5140,7 @@ karma@2.0.0: tmp "0.0.33" useragent "^2.1.12" -kew@~0.7.0: +kew@^0.7.0: version "0.7.0" resolved "https://registry.yarnpkg.com/kew/-/kew-0.7.0.tgz#79d93d2d33363d6fdd2970b335d9141ad591d79b" @@ -4783,11 +5170,11 @@ kind-of@^4.0.0: dependencies: is-buffer "^1.1.5" -kind-of@^5.0.0, kind-of@^5.0.2: - version "5.0.2" - resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-5.0.2.tgz#f57bec933d9a2209ffa96c5c08343607b7035fda" +kind-of@^5.0.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-5.1.0.tgz#729c91e2d857b7a419a1f9aa65685c4c33f5845d" -kind-of@^6.0.0: +kind-of@^6.0.0, kind-of@^6.0.2: version "6.0.2" resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-6.0.2.tgz#01146b36a6218e64e58f3a8d66de5d7fc6f6d051" @@ -4798,11 +5185,11 @@ klaw@^1.0.0: graceful-fs "^4.1.9" labeled-stream-splicer@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/labeled-stream-splicer/-/labeled-stream-splicer-2.0.0.tgz#a52e1d138024c00b86b1c0c91f677918b8ae0a59" + version "2.0.1" + resolved "https://registry.yarnpkg.com/labeled-stream-splicer/-/labeled-stream-splicer-2.0.1.tgz#9cffa32fd99e1612fd1d86a8db962416d5292926" dependencies: inherits "^2.0.1" - isarray "~0.0.1" + isarray "^2.0.4" stream-splicer "^2.0.0" latest-version@^3.0.0: @@ -4819,12 +5206,6 @@ lazy-cache@^1.0.3: version "1.0.4" resolved "https://registry.yarnpkg.com/lazy-cache/-/lazy-cache-1.0.4.tgz#a1d78fc3a50474cb80845d3b3b6e1da49a446e8e" -lazy-cache@^2.0.2: - version "2.0.2" - resolved "https://registry.yarnpkg.com/lazy-cache/-/lazy-cache-2.0.2.tgz#b9190a4f913354694840859f8a8f7084d8822264" - dependencies: - set-getter "^0.1.0" - lazystream@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/lazystream/-/lazystream-1.0.0.tgz#f6995fe0f820392f61396be89462407bb77168e4" @@ -4848,12 +5229,6 @@ levn@~0.3.0: prelude-ls "~1.1.2" type-check "~0.3.2" -lexical-scope@^1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/lexical-scope/-/lexical-scope-1.2.0.tgz#fcea5edc704a4b3a8796cdca419c3a0afaf22df4" - dependencies: - astw "^2.0.0" - libbase64@0.1.0: version "0.1.0" resolved "https://registry.yarnpkg.com/libbase64/-/libbase64-0.1.0.tgz#62351a839563ac5ff5bd26f12f60e9830bb751e6" @@ -4886,15 +5261,6 @@ load-json-file@^1.0.0: pinkie-promise "^2.0.0" strip-bom "^2.0.0" -load-json-file@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/load-json-file/-/load-json-file-2.0.0.tgz#7947e42149af80d696cbf797bcaabcfe1fe29ca8" - dependencies: - graceful-fs "^4.1.2" - parse-json "^2.2.0" - pify "^2.0.0" - strip-bom "^3.0.0" - load-json-file@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/load-json-file/-/load-json-file-4.0.0.tgz#2f5f45ab91e33216234fd53adab668eb4ec0993b" @@ -4908,7 +5274,7 @@ loader-runner@^2.3.0: version "2.3.0" resolved "https://registry.yarnpkg.com/loader-runner/-/loader-runner-2.3.0.tgz#f482aea82d543e07921700d5a46ef26fdac6b8a2" -loader-utils@^0.2.15, loader-utils@^0.2.16, loader-utils@^0.2.5, loader-utils@~0.2.2: +loader-utils@^0.2.15, loader-utils@^0.2.16, loader-utils@~0.2.2: version "0.2.17" resolved "https://registry.yarnpkg.com/loader-utils/-/loader-utils-0.2.17.tgz#f86e6374d43205a6e6c60e9196f17c0299bfb348" dependencies: @@ -5007,6 +5373,10 @@ lodash.clonedeep@^4.3.2: version "4.5.0" resolved "https://registry.yarnpkg.com/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz#e23f3f9c4f8fbdde872529c1071857a086e5ccef" +lodash.debounce@^4.0.8: + version "4.0.8" + resolved "https://registry.yarnpkg.com/lodash.debounce/-/lodash.debounce-4.0.8.tgz#82d79bff30a67c4005ffd5e2515300ad9ca4d7af" + lodash.defaults@^3.1.2: version "3.1.2" resolved "https://registry.yarnpkg.com/lodash.defaults/-/lodash.defaults-3.1.2.tgz#c7308b18dbf8bc9372d701a73493c61192bd2e2c" @@ -5018,10 +5388,6 @@ lodash.defaults@^4.0.0: version "4.2.0" resolved "https://registry.yarnpkg.com/lodash.defaults/-/lodash.defaults-4.2.0.tgz#d09178716ffea4dde9e5fb7b37f6f0802274580c" -lodash.endswith@^4.2.1: - version "4.2.1" - resolved "https://registry.yarnpkg.com/lodash.endswith/-/lodash.endswith-4.2.1.tgz#fed59ac1738ed3e236edd7064ec456448b37bc09" - lodash.escape@^3.0.0: version "3.2.0" resolved "https://registry.yarnpkg.com/lodash.escape/-/lodash.escape-3.2.0.tgz#995ee0dc18c1b48cc92effae71a10aab5b487698" @@ -5036,14 +5402,6 @@ lodash.isarray@^3.0.0: version "3.0.4" resolved "https://registry.yarnpkg.com/lodash.isarray/-/lodash.isarray-3.0.4.tgz#79e4eb88c36a8122af86f844aa9bcd851b5fbb55" -lodash.isfunction@^3.0.8: - version "3.0.9" - resolved "https://registry.yarnpkg.com/lodash.isfunction/-/lodash.isfunction-3.0.9.tgz#06de25df4db327ac931981d1bdb067e5af68d051" - -lodash.isstring@^4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/lodash.isstring/-/lodash.isstring-4.0.1.tgz#d527dfb5456eca7cc9bb95d5daeaf88ba54a5451" - lodash.keys@^3.0.0: version "3.1.2" resolved "https://registry.yarnpkg.com/lodash.keys/-/lodash.keys-3.1.2.tgz#4dbc0472b156be50a0b286855d1bd0b0c656098a" @@ -5061,17 +5419,13 @@ lodash.memoize@~3.0.3: resolved "https://registry.yarnpkg.com/lodash.memoize/-/lodash.memoize-3.0.4.tgz#2dcbd2c287cbc0a55cc42328bd0c736150d53e3f" lodash.mergewith@^4.6.0: - version "4.6.0" - resolved "https://registry.yarnpkg.com/lodash.mergewith/-/lodash.mergewith-4.6.0.tgz#150cf0a16791f5903b8891eab154609274bdea55" + version "4.6.1" + resolved "https://registry.yarnpkg.com/lodash.mergewith/-/lodash.mergewith-4.6.1.tgz#639057e726c3afbdb3e7d42741caa8d6e4335927" lodash.restparam@^3.0.0: version "3.6.1" resolved "https://registry.yarnpkg.com/lodash.restparam/-/lodash.restparam-3.6.1.tgz#936a4e309ef330a7645ed4145986c85ae5b20805" -lodash.startswith@^4.2.1: - version "4.2.1" - resolved "https://registry.yarnpkg.com/lodash.startswith/-/lodash.startswith-4.2.1.tgz#c598c4adce188a27e53145731cdc6c0e7177600c" - lodash.tail@^4.1.1: version "4.1.1" resolved "https://registry.yarnpkg.com/lodash.tail/-/lodash.tail-4.1.1.tgz#d2333a36d9e7717c8ad2f7cacafec7c32b444664" @@ -5114,49 +5468,39 @@ lodash.uniq@^4.5.0: version "4.5.0" resolved "https://registry.yarnpkg.com/lodash.uniq/-/lodash.uniq-4.5.0.tgz#d0225373aeb652adc1bc82e4945339a842754773" -lodash@4.16.2: - version "4.16.2" - resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.16.2.tgz#3e626db827048a699281a8a125226326cfc0e652" +lodash@4.17.10, lodash@^4.0.0, lodash@^4.0.1, lodash@^4.13.1, lodash@^4.15.0, lodash@^4.17.10, lodash@^4.17.3, lodash@^4.17.4, lodash@^4.17.5, lodash@^4.3.0, lodash@^4.5.0, lodash@^4.8.0, lodash@~4.17.10: + version "4.17.10" + resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.10.tgz#1b7793cf7259ea38fb3661d4d38b3260af8ae4e7" lodash@^3.8.0: version "3.10.1" resolved "https://registry.yarnpkg.com/lodash/-/lodash-3.10.1.tgz#5bf45e8e49ba4189e17d482789dfd15bd140b7b6" -lodash@^4, lodash@^4.0.0, lodash@^4.0.1, lodash@^4.13.1, lodash@^4.14.0, lodash@^4.15.0, lodash@^4.17.2, lodash@^4.17.3, lodash@^4.17.4, lodash@^4.5.0, lodash@^4.8.0, lodash@~4.17.4: - version "4.17.4" - resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.4.tgz#78203a4d1c328ae1d86dca6460e369b57f4055ae" - log-driver@^1.2.5: - version "1.2.5" - resolved "https://registry.yarnpkg.com/log-driver/-/log-driver-1.2.5.tgz#7ae4ec257302fd790d557cb10c97100d857b0056" + version "1.2.7" + resolved "https://registry.yarnpkg.com/log-driver/-/log-driver-1.2.7.tgz#63b95021f0702fedfa2c9bb0a24e7797d71871d8" -log-symbols@^2.0.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/log-symbols/-/log-symbols-2.1.0.tgz#f35fa60e278832b538dc4dddcbb478a45d3e3be6" - dependencies: - chalk "^2.0.1" - -log-symbols@^2.1.0: +log-symbols@^2.0.0, log-symbols@^2.1.0, log-symbols@^2.2.0: version "2.2.0" resolved "https://registry.yarnpkg.com/log-symbols/-/log-symbols-2.2.0.tgz#5740e1c5d6f0dfda4ad9323b5332107ef6b4c40a" dependencies: chalk "^2.0.1" log4js@^2.3.9: - version "2.5.2" - resolved "https://registry.yarnpkg.com/log4js/-/log4js-2.5.2.tgz#234e9c688bc4aab3999bd4b149c85851a4e62faa" + version "2.11.0" + resolved "https://registry.yarnpkg.com/log4js/-/log4js-2.11.0.tgz#bf3902eff65c6923d9ce9cfbd2db54160e34005a" dependencies: - circular-json "^0.5.1" + circular-json "^0.5.4" date-format "^1.2.0" debug "^3.1.0" - semver "^5.3.0" - streamroller "^0.7.0" + semver "^5.5.0" + streamroller "0.7.0" optionalDependencies: amqplib "^0.5.2" axios "^0.15.3" hipchat-notifier "^1.1.0" loggly "^1.1.0" - mailgun-js "^0.7.0" + mailgun-js "^0.18.0" nodemailer "^2.5.0" redis "^2.7.1" slack-node "~0.2.0" @@ -5170,22 +5514,33 @@ loggly@^1.1.0: timespan "2.3.x" loglevel@^1.4.1: - version "1.5.0" - resolved "https://registry.yarnpkg.com/loglevel/-/loglevel-1.5.0.tgz#3863984a2c326b986fbb965f378758a6dc8a4324" + version "1.6.1" + resolved "https://registry.yarnpkg.com/loglevel/-/loglevel-1.6.1.tgz#e0fc95133b6ef276cdc8887cdaf24aa6f156f8fa" loglevelnext@^1.0.1: - version "1.0.3" - resolved "https://registry.yarnpkg.com/loglevelnext/-/loglevelnext-1.0.3.tgz#0f69277e73bbbf2cd61b94d82313216bf87ac66e" + version "1.0.5" + resolved "https://registry.yarnpkg.com/loglevelnext/-/loglevelnext-1.0.5.tgz#36fc4f5996d6640f539ff203ba819641680d75a2" + dependencies: + es6-symbol "^3.1.1" + object.assign "^4.1.0" + +long@4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/long/-/long-4.0.0.tgz#9a7b71cfb7d361a194ea555241c92f7468d5bf28" + +long@^3.2.0: + version "3.2.0" + resolved "https://registry.yarnpkg.com/long/-/long-3.2.0.tgz#d821b7138ca1cb581c172990ef14db200b5c474b" longest@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/longest/-/longest-1.0.1.tgz#30a0b2da38f73770e8294a0d22e6625ed77d0097" loose-envify@^1.0.0: - version "1.3.1" - resolved "https://registry.yarnpkg.com/loose-envify/-/loose-envify-1.3.1.tgz#d1a8ad33fa9ce0e713d65fdd0ac8b748d478c848" + version "1.4.0" + resolved "https://registry.yarnpkg.com/loose-envify/-/loose-envify-1.4.0.tgz#71ee51fa7be4caec1a63839f7e682d8132d30caf" dependencies: - js-tokens "^3.0.0" + js-tokens "^3.0.0 || ^4.0.0" loud-rejection@^1.0.0, loud-rejection@^1.6.0: version "1.6.0" @@ -5199,39 +5554,27 @@ lower-case@^1.1.1: resolved "https://registry.yarnpkg.com/lower-case/-/lower-case-1.1.4.tgz#9a2cabd1b9e8e0ae993a4bf7d5875c39c42e8eac" lowercase-keys@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/lowercase-keys/-/lowercase-keys-1.0.0.tgz#4e3366b39e7f5457e35f1324bdf6f88d0bfc7306" + version "1.0.1" + resolved "https://registry.yarnpkg.com/lowercase-keys/-/lowercase-keys-1.0.1.tgz#6f9e30b47084d971a7c820ff15a6c5167b74c26f" -lru-cache@2.2.x: - version "2.2.4" - resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-2.2.4.tgz#6c658619becf14031d0d0b594b16042ce4dc063d" - -lru-cache@^4.0.1, lru-cache@^4.1.1: - version "4.1.1" - resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-4.1.1.tgz#622e32e82488b49279114a4f9ecf45e7cd6bba55" +lru-cache@4.1.x, lru-cache@^4.0.1, lru-cache@^4.1.1, lru-cache@^4.1.2: + version "4.1.3" + resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-4.1.3.tgz#a1175cf3496dfc8436c156c334b4955992bce69c" dependencies: pseudomap "^1.0.2" yallist "^2.1.2" -lru-cache@~2.6.5: - version "2.6.5" - resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-2.6.5.tgz#e56d6354148ede8d7707b58d143220fd08df0fd5" - -macaddress@^0.2.8: - version "0.2.8" - resolved "https://registry.yarnpkg.com/macaddress/-/macaddress-0.2.8.tgz#5904dc537c39ec6dbefeae902327135fa8511f12" - magic-string@^0.16.0: version "0.16.0" resolved "https://registry.yarnpkg.com/magic-string/-/magic-string-0.16.0.tgz#970ebb0da7193301285fb1aa650f39bdd81eb45a" dependencies: vlq "^0.2.1" -magic-string@^0.22.3, magic-string@^0.22.4: - version "0.22.4" - resolved "https://registry.yarnpkg.com/magic-string/-/magic-string-0.22.4.tgz#31039b4e40366395618c1d6cf8193c53917475ff" +magic-string@^0.22.4: + version "0.22.5" + resolved "https://registry.yarnpkg.com/magic-string/-/magic-string-0.22.5.tgz#8e9cf5afddf44385c1da5bc2a6a0dbd10b03657e" dependencies: - vlq "^0.2.1" + vlq "^0.2.2" mailcomposer@4.0.1: version "4.0.1" @@ -5240,29 +5583,33 @@ mailcomposer@4.0.1: buildmail "4.0.1" libmime "3.0.0" -mailgun-js@^0.7.0: - version "0.7.15" - resolved "https://registry.yarnpkg.com/mailgun-js/-/mailgun-js-0.7.15.tgz#ee366a20dac64c3c15c03d6c1b3e0ed795252abb" +mailgun-js@^0.18.0: + version "0.18.1" + resolved "https://registry.yarnpkg.com/mailgun-js/-/mailgun-js-0.18.1.tgz#ee39aa18d7bb598a5ce9ede84afb681defc8a6b0" dependencies: - async "~2.1.2" - debug "~2.2.0" - form-data "~2.1.1" - inflection "~1.10.0" + async "~2.6.0" + debug "~3.1.0" + form-data "~2.3.0" + inflection "~1.12.0" is-stream "^1.1.0" path-proxy "~1.0.0" - proxy-agent "~2.0.0" - q "~1.4.0" + promisify-call "^2.0.2" + proxy-agent "~3.0.0" tsscmp "~1.0.0" make-dir@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/make-dir/-/make-dir-1.0.0.tgz#97a011751e91dd87cfadef58832ebb04936de978" + version "1.3.0" + resolved "https://registry.yarnpkg.com/make-dir/-/make-dir-1.3.0.tgz#79c1033b80515bd6d24ec9933e860ca75ee27f0c" dependencies: - pify "^2.3.0" + pify "^3.0.0" make-error@^1.1.1: - version "1.3.0" - resolved "https://registry.yarnpkg.com/make-error/-/make-error-1.3.0.tgz#52ad3a339ccf10ce62b4040b708fe707244b8b96" + version "1.3.4" + resolved "https://registry.yarnpkg.com/make-error/-/make-error-1.3.4.tgz#19978ed575f9e9545d2ff8c13e33b5d18a67d535" + +mamacro@^0.0.3: + version "0.0.3" + resolved "https://registry.yarnpkg.com/mamacro/-/mamacro-0.0.3.tgz#ad2c9576197c9f1abf308d0787865bd975a3f3e4" map-cache@^0.2.2: version "0.2.2" @@ -5272,6 +5619,10 @@ map-obj@^1.0.0, map-obj@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/map-obj/-/map-obj-1.0.1.tgz#d933ceb9205d82bdcf4886f6742bdc2b4dea146d" +map-obj@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/map-obj/-/map-obj-2.0.0.tgz#a65cd29087a92598b8791257a523e021222ac1f9" + map-stream@~0.1.0: version "0.1.0" resolved "https://registry.yarnpkg.com/map-stream/-/map-stream-0.1.0.tgz#e56aa94c4c8055a16404a0674b78f215f7c8e194" @@ -5283,13 +5634,17 @@ map-visit@^1.0.0: object-visit "^1.0.0" marked@^0.3.5: - version "0.3.12" - resolved "https://registry.yarnpkg.com/marked/-/marked-0.3.12.tgz#7cf25ff2252632f3fe2406bde258e94eee927519" + version "0.3.19" + resolved "https://registry.yarnpkg.com/marked/-/marked-0.3.19.tgz#5d47f709c4c9fc3c216b6d46127280f40b39d790" math-expression-evaluator@^1.2.14: version "1.2.17" resolved "https://registry.yarnpkg.com/math-expression-evaluator/-/math-expression-evaluator-1.2.17.tgz#de819fdbcd84dccd8fae59c6aeb79615b9d266ac" +math-random@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/math-random/-/math-random-1.0.1.tgz#8b3aac588b8a66e4975e3cdea67f7bb329601fac" + md5.js@^1.3.4: version "1.3.4" resolved "https://registry.yarnpkg.com/md5.js/-/md5.js-1.3.4.tgz#e9bdbde94a20a5ac18b04340fc5764d5b09d901d" @@ -5305,6 +5660,10 @@ md5@^2.2.1: crypt "~0.0.1" is-buffer "~1.1.1" +meant@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/meant/-/meant-1.0.1.tgz#66044fea2f23230ec806fb515efea29c44d2115d" + media-typer@0.3.0: version "0.3.0" resolved "https://registry.yarnpkg.com/media-typer/-/media-typer-0.3.0.tgz#8710d7af0aa626f8fffa1ce00168545263255748" @@ -5341,10 +5700,34 @@ meow@^3.3.0, meow@^3.7.0: redent "^1.0.0" trim-newlines "^1.0.0" +meow@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/meow/-/meow-5.0.0.tgz#dfc73d63a9afc714a5e371760eb5c88b91078aa4" + dependencies: + camelcase-keys "^4.0.0" + decamelize-keys "^1.0.0" + loud-rejection "^1.0.0" + minimist-options "^3.0.1" + normalize-package-data "^2.3.4" + read-pkg-up "^3.0.0" + redent "^2.0.0" + trim-newlines "^2.0.0" + yargs-parser "^10.0.0" + merge-descriptors@1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/merge-descriptors/-/merge-descriptors-1.0.1.tgz#b00aaa556dd8b44568150ec9d1b953f3f90cbb61" +merge-options@^1.0.0, merge-options@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/merge-options/-/merge-options-1.0.1.tgz#2a64b24457becd4e4dc608283247e94ce589aa32" + dependencies: + is-plain-obj "^1.1" + +merge2@^1.2.1: + version "1.2.2" + resolved "https://registry.yarnpkg.com/merge2/-/merge2-1.2.2.tgz#03212e3da8d86c4d8523cebd6318193414f94e34" + merge@^1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/merge/-/merge-1.2.0.tgz#7531e39d4949c281a66b8c5a6e0265e8b05894da" @@ -5371,41 +5754,23 @@ micromatch@^2.1.5, micromatch@^2.3.11: parse-glob "^3.0.4" regex-cache "^0.4.2" -micromatch@^3.0.3: - version "3.1.0" - resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-3.1.0.tgz#5102d4eaf20b6997d6008e3acfe1c44a3fa815e2" +micromatch@^3.0.3, micromatch@^3.1.10, micromatch@^3.1.4, micromatch@^3.1.8, micromatch@^3.1.9: + version "3.1.10" + resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-3.1.10.tgz#70859bc95c9840952f359a068a3fc49f9ecfac23" dependencies: arr-diff "^4.0.0" array-unique "^0.3.2" - braces "^2.2.2" - define-property "^1.0.0" - extend-shallow "^2.0.1" - extglob "^2.0.2" + braces "^2.3.1" + define-property "^2.0.2" + extend-shallow "^3.0.2" + extglob "^2.0.4" fragment-cache "^0.2.1" - kind-of "^5.0.2" - nanomatch "^1.2.1" + kind-of "^6.0.2" + nanomatch "^1.2.9" object.pick "^1.3.0" regex-not "^1.0.0" snapdragon "^0.8.1" - to-regex "^3.0.1" - -micromatch@^3.1.4: - version "3.1.5" - resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-3.1.5.tgz#d05e168c206472dfbca985bfef4f57797b4cd4ba" - dependencies: - arr-diff "^4.0.0" - array-unique "^0.3.2" - braces "^2.3.0" - define-property "^1.0.0" - extend-shallow "^2.0.1" - extglob "^2.0.2" - fragment-cache "^0.2.1" - kind-of "^6.0.0" - nanomatch "^1.2.5" - object.pick "^1.3.0" - regex-not "^1.0.0" - snapdragon "^0.8.1" - to-regex "^3.0.1" + to-regex "^3.0.2" miller-rabin@^4.0.0: version "4.0.1" @@ -5414,35 +5779,39 @@ miller-rabin@^4.0.0: bn.js "^4.0.0" brorand "^1.0.1" -"mime-db@>= 1.29.0 < 2", mime-db@~1.30.0: - version "1.30.0" - resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.30.0.tgz#74c643da2dd9d6a45399963465b26d5ca7d71f01" +"mime-db@>= 1.34.0 < 2": + version "1.36.0" + resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.36.0.tgz#5020478db3c7fe93aad7bbcc4dcf869c43363397" -mime-types@^2.1.11, mime-types@^2.1.12, mime-types@~2.1.11, mime-types@~2.1.15, mime-types@~2.1.16, mime-types@~2.1.17, mime-types@~2.1.7: - version "2.1.17" - resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.17.tgz#09d7a393f03e995a79f8af857b70a9e0ab16557a" +mime-db@~1.35.0: + version "1.35.0" + resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.35.0.tgz#0569d657466491283709663ad379a99b90d9ab47" + +mime-types@^2.1.11, mime-types@^2.1.12, mime-types@~2.1.17, mime-types@~2.1.18, mime-types@~2.1.19, mime-types@~2.1.7: + version "2.1.19" + resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.19.tgz#71e464537a7ef81c15f2db9d97e913fc0ff606f0" dependencies: - mime-db "~1.30.0" + mime-db "~1.35.0" -mime@1.4.1, mime@^1.3.4: +mime@1.4.1: version "1.4.1" resolved "https://registry.yarnpkg.com/mime/-/mime-1.4.1.tgz#121f9ebc49e3766f311a76e1fa1c8003c4b03aa6" -mime@^1.4.1, mime@^1.5.0: +mime@^1.3.4, mime@^1.6.0: version "1.6.0" resolved "https://registry.yarnpkg.com/mime/-/mime-1.6.0.tgz#32cd9e5c64553bd58d19a568af452acff04981b1" -mime@^2.1.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/mime/-/mime-2.2.0.tgz#161e541965551d3b549fa1114391e3a3d55b923b" +mime@^2.1.0, mime@^2.3.1: + version "2.3.1" + resolved "https://registry.yarnpkg.com/mime/-/mime-2.3.1.tgz#b1621c54d63b97c47d3cfe7f7215f7d64517c369" mimic-fn@^1.0.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-1.1.0.tgz#e667783d92e89dbd342818b5230b9d62a672ad18" + version "1.2.0" + resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-1.2.0.tgz#820c86a39334640e99516928bd03fca88057d022" -minimalistic-assert@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/minimalistic-assert/-/minimalistic-assert-1.0.0.tgz#702be2dda6b37f4836bcb3f5db56641b64a1d3d3" +minimalistic-assert@^1.0.0, minimalistic-assert@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz#2e194de044626d4a10e7f7fbc00ce73e83e4d5c7" minimalistic-crypto-utils@^1.0.0, minimalistic-crypto-utils@^1.0.1: version "1.0.1" @@ -5454,6 +5823,13 @@ minimalistic-crypto-utils@^1.0.0, minimalistic-crypto-utils@^1.0.1: dependencies: brace-expansion "^1.1.7" +minimist-options@^3.0.1: + version "3.0.2" + resolved "https://registry.yarnpkg.com/minimist-options/-/minimist-options-3.0.2.tgz#fba4c8191339e13ecf4d61beb03f070103f3d954" + dependencies: + arrify "^1.0.1" + is-plain-obj "^1.1.0" + minimist@0.0.8: version "0.0.8" resolved "https://registry.yarnpkg.com/minimist/-/minimist-0.0.8.tgz#857fcabfc3397d2625b8228262e86aa7a011b05d" @@ -5462,7 +5838,7 @@ minimist@1.1.x: version "1.1.3" resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.1.3.tgz#3bedfd91a92d39016fcfaa1c681e8faa1a1efda8" -minimist@^1.1.0, minimist@^1.1.3, minimist@^1.2.0: +minimist@1.2.0, minimist@^1.1.0, minimist@^1.1.3, minimist@^1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.0.tgz#a35008b20f41383eec1fb914f4cd5df79a264284" @@ -5470,9 +5846,22 @@ minimist@~0.0.1: version "0.0.10" resolved "https://registry.yarnpkg.com/minimist/-/minimist-0.0.10.tgz#de3f98543dbf96082be48ad1a0c7cda836301dcf" -mississippi@^1.3.0: - version "1.3.0" - resolved "https://registry.yarnpkg.com/mississippi/-/mississippi-1.3.0.tgz#d201583eb12327e3c5c1642a404a9cacf94e34f5" +minipass@^2.2.1, minipass@^2.3.3: + version "2.3.4" + resolved "https://registry.yarnpkg.com/minipass/-/minipass-2.3.4.tgz#4768d7605ed6194d6d576169b9e12ef71e9d9957" + dependencies: + safe-buffer "^5.1.2" + yallist "^3.0.0" + +minizlib@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/minizlib/-/minizlib-1.1.0.tgz#11e13658ce46bc3a70a267aac58359d1e0c29ceb" + dependencies: + minipass "^2.2.1" + +mississippi@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/mississippi/-/mississippi-2.0.0.tgz#3442a508fafc28500486feea99409676e4ee5a6f" dependencies: concat-stream "^1.5.0" duplexify "^3.4.2" @@ -5480,17 +5869,17 @@ mississippi@^1.3.0: flush-write-stream "^1.0.0" from2 "^2.1.0" parallel-transform "^1.1.0" - pump "^1.0.0" + pump "^2.0.1" pumpify "^1.3.3" stream-each "^1.1.0" through2 "^2.0.0" mixin-deep@^1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/mixin-deep/-/mixin-deep-1.2.0.tgz#d02b8c6f8b6d4b8f5982d3fd009c4919851c3fe2" + version "1.3.1" + resolved "https://registry.yarnpkg.com/mixin-deep/-/mixin-deep-1.3.1.tgz#a49e7268dce1a0d9698e45326c5626df3543d0fe" dependencies: for-in "^1.0.2" - is-extendable "^0.1.1" + is-extendable "^1.0.1" mixin-object@^2.0.1: version "2.0.1" @@ -5499,13 +5888,7 @@ mixin-object@^2.0.1: for-in "^0.1.3" is-extendable "^0.1.1" -mkdirp@0.5.0: - version "0.5.0" - resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.0.tgz#1d73076a6df986cd9344e15e71fcc05a4c9abf12" - dependencies: - minimist "0.0.8" - -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.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 "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.1.tgz#30057438eac6cf7f8c4767f38648d6697d75c903" dependencies: @@ -5531,9 +5914,9 @@ module-deps@^4.0.8: through2 "^2.0.0" xtend "^4.0.0" -moment@^2.19.3, moment@^2.22.1: - version "2.22.1" - resolved "https://registry.yarnpkg.com/moment/-/moment-2.22.1.tgz#529a2e9bf973f259c9643d237fda84de3a26e8ad" +moment@^2.22.1: + version "2.22.2" + resolved "https://registry.yarnpkg.com/moment/-/moment-2.22.2.tgz#3c257f9839fc0e93ff53149632239eb90783ff66" morgan@1.9.0: version "1.9.0" @@ -5556,10 +5939,6 @@ move-concurrently@^1.0.1: rimraf "^2.5.4" run-queue "^1.0.3" -ms@0.7.1: - version "0.7.1" - resolved "https://registry.yarnpkg.com/ms/-/ms-0.7.1.tgz#9cd13c03adbff25b65effde7ce864ee952017098" - ms@2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8" @@ -5569,11 +5948,11 @@ multicast-dns-service-types@^1.1.0: resolved "https://registry.yarnpkg.com/multicast-dns-service-types/-/multicast-dns-service-types-1.1.0.tgz#899f11d9686e5e05cb91b35d5f0e63b773cfc901" multicast-dns@^6.0.1: - version "6.1.1" - resolved "https://registry.yarnpkg.com/multicast-dns/-/multicast-dns-6.1.1.tgz#6e7de86a570872ab17058adea7160bbeca814dde" + version "6.2.3" + resolved "https://registry.yarnpkg.com/multicast-dns/-/multicast-dns-6.2.3.tgz#a0ec7bd9055c4282f790c3c82f4e28db3b31b229" dependencies: - dns-packet "^1.0.1" - thunky "^0.1.0" + dns-packet "^1.3.1" + thunky "^1.0.2" multipipe@^0.1.2: version "0.1.2" @@ -5581,73 +5960,77 @@ multipipe@^0.1.2: dependencies: duplexer2 "0.0.2" -nan@^2.3.0, nan@^2.3.2: - version "2.7.0" - resolved "https://registry.yarnpkg.com/nan/-/nan-2.7.0.tgz#d95bf721ec877e08db276ed3fc6eb78f9083ad46" +mute-stream@0.0.7: + version "0.0.7" + resolved "https://registry.yarnpkg.com/mute-stream/-/mute-stream-0.0.7.tgz#3075ce93bc21b8fab43e1bc4da7e8115ed1e7bab" -nanomatch@^1.2.1: - version "1.2.3" - resolved "https://registry.yarnpkg.com/nanomatch/-/nanomatch-1.2.3.tgz#15e1c02dcf990c27a283b08c0ba1801ce249a6a6" +nan@^2.10.0, nan@^2.9.2: + version "2.10.0" + resolved "https://registry.yarnpkg.com/nan/-/nan-2.10.0.tgz#96d0cd610ebd58d4b4de9cc0c6828cda99c7548f" + +nanomatch@^1.2.9: + version "1.2.13" + resolved "https://registry.yarnpkg.com/nanomatch/-/nanomatch-1.2.13.tgz#b87a8aa4fc0de8fe6be88895b38983ff265bd119" dependencies: arr-diff "^4.0.0" array-unique "^0.3.2" - define-property "^1.0.0" - extend-shallow "^2.0.1" + define-property "^2.0.2" + extend-shallow "^3.0.2" fragment-cache "^0.2.1" - is-odd "^1.0.0" - kind-of "^5.0.2" + is-windows "^1.0.2" + kind-of "^6.0.2" object.pick "^1.3.0" regex-not "^1.0.0" snapdragon "^0.8.1" to-regex "^3.0.1" -nanomatch@^1.2.5: - version "1.2.7" - resolved "https://registry.yarnpkg.com/nanomatch/-/nanomatch-1.2.7.tgz#53cd4aa109ff68b7f869591fdc9d10daeeea3e79" +needle@^2.2.1: + version "2.2.2" + resolved "https://registry.yarnpkg.com/needle/-/needle-2.2.2.tgz#1120ca4c41f2fcc6976fd28a8968afe239929418" dependencies: - arr-diff "^4.0.0" - array-unique "^0.3.2" - define-property "^1.0.0" - extend-shallow "^2.0.1" - fragment-cache "^0.2.1" - is-odd "^1.0.0" - kind-of "^5.0.2" - object.pick "^1.3.0" - regex-not "^1.0.0" - snapdragon "^0.8.1" - to-regex "^3.0.1" - -ncname@1.0.x: - version "1.0.0" - resolved "https://registry.yarnpkg.com/ncname/-/ncname-1.0.0.tgz#5b57ad18b1ca092864ef62b0b1ed8194f383b71c" - dependencies: - xml-char-classes "^1.0.0" + debug "^2.1.2" + iconv-lite "^0.4.4" + sax "^1.2.4" negotiator@0.6.1: version "0.6.1" resolved "https://registry.yarnpkg.com/negotiator/-/negotiator-0.6.1.tgz#2b327184e8992101177b28563fb5e7102acd0ca9" -netmask@~1.0.4: +neo-async@^2.5.0: + version "2.5.2" + resolved "https://registry.yarnpkg.com/neo-async/-/neo-async-2.5.2.tgz#489105ce7bc54e709d736b195f82135048c50fcc" + +netmask@^1.0.6: version "1.0.6" resolved "https://registry.yarnpkg.com/netmask/-/netmask-1.0.6.tgz#20297e89d86f6f6400f250d9f4f6b4c1945fcd35" +next-tick@1: + version "1.0.0" + resolved "https://registry.yarnpkg.com/next-tick/-/next-tick-1.0.0.tgz#ca86d1fe8828169b0120208e3dc8424b9db8342c" + ng2-file-upload@1.2.1: version "1.2.1" resolved "https://registry.yarnpkg.com/ng2-file-upload/-/ng2-file-upload-1.2.1.tgz#5563c5dfd6f43fbfbe815c206e343464a0a6a197" ng2-nouislider@^1.7.11: - version "1.7.11" - resolved "https://registry.yarnpkg.com/ng2-nouislider/-/ng2-nouislider-1.7.11.tgz#b8ba5e3d2ffc23e1e32dfe54dd1726e2b4be316b" + version "1.7.12" + resolved "https://registry.yarnpkg.com/ng2-nouislider/-/ng2-nouislider-1.7.12.tgz#874640463bd464ce2eeb442bfd650259f90102e2" -ngrx-store-freeze@^0.2.1: - version "0.2.1" - resolved "https://registry.yarnpkg.com/ngrx-store-freeze/-/ngrx-store-freeze-0.2.1.tgz#04fb29db33cafda0f2d6ea32adeaac4891b1b27b" +ngrx-store-freeze@^0.2.4: + version "0.2.4" + resolved "https://registry.yarnpkg.com/ngrx-store-freeze/-/ngrx-store-freeze-0.2.4.tgz#146687cdf7e21244eb9003c7e883f2125847076c" dependencies: deep-freeze-strict "^1.1.1" -ngx-infinite-scroll@0.8.2: - version "0.8.2" - resolved "https://registry.yarnpkg.com/ngx-infinite-scroll/-/ngx-infinite-scroll-0.8.2.tgz#9cc615c01fbb6307599453c9d9cfb5c1db4fd3e8" +ngx-bootstrap@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/ngx-bootstrap/-/ngx-bootstrap-3.0.1.tgz#e98d2fc6340f32a9d358cd08e8fda7dcb23bdab3" + +ngx-infinite-scroll@6.0.1: + version "6.0.1" + resolved "https://registry.yarnpkg.com/ngx-infinite-scroll/-/ngx-infinite-scroll-6.0.1.tgz#571e54860ce32839451569bcf6e7a63cfae327bd" + dependencies: + opencollective "^1.0.3" ngx-pagination@3.0.3: version "3.0.3" @@ -5659,74 +6042,80 @@ no-case@^2.2.0: dependencies: lower-case "^1.1.1" -node-forge@0.6.33: - version "0.6.33" - resolved "https://registry.yarnpkg.com/node-forge/-/node-forge-0.6.33.tgz#463811879f573d45155ad6a9f43dc296e8e85ebc" +node-fetch@1.6.3: + version "1.6.3" + resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-1.6.3.tgz#dc234edd6489982d58e8f0db4f695029abcd8c04" + dependencies: + encoding "^0.1.11" + is-stream "^1.0.1" -node-gyp@^3.3.1: - version "3.6.2" - resolved "https://registry.yarnpkg.com/node-gyp/-/node-gyp-3.6.2.tgz#9bfbe54562286284838e750eac05295853fa1c60" +node-forge@0.7.5: + version "0.7.5" + resolved "https://registry.yarnpkg.com/node-forge/-/node-forge-0.7.5.tgz#6c152c345ce11c52f465c2abd957e8639cd674df" + +node-gyp@^3.8.0: + version "3.8.0" + resolved "https://registry.yarnpkg.com/node-gyp/-/node-gyp-3.8.0.tgz#540304261c330e80d0d5edce253a68cb3964218c" dependencies: fstream "^1.0.0" glob "^7.0.3" graceful-fs "^4.1.2" - minimatch "^3.0.2" mkdirp "^0.5.0" nopt "2 || 3" npmlog "0 || 1 || 2 || 3 || 4" osenv "0" - request "2" + request "^2.87.0" rimraf "2" semver "~5.3.0" tar "^2.0.0" which "1" node-libs-browser@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/node-libs-browser/-/node-libs-browser-2.0.0.tgz#a3a59ec97024985b46e958379646f96c4b616646" + version "2.1.0" + resolved "https://registry.yarnpkg.com/node-libs-browser/-/node-libs-browser-2.1.0.tgz#5f94263d404f6e44767d726901fff05478d600df" dependencies: assert "^1.1.1" - browserify-zlib "^0.1.4" + browserify-zlib "^0.2.0" buffer "^4.3.0" console-browserify "^1.1.0" constants-browserify "^1.0.0" crypto-browserify "^3.11.0" domain-browser "^1.1.1" events "^1.0.0" - https-browserify "0.0.1" - os-browserify "^0.2.0" + https-browserify "^1.0.0" + os-browserify "^0.3.0" path-browserify "0.0.0" - process "^0.11.0" + process "^0.11.10" punycode "^1.2.4" querystring-es3 "^0.2.0" - readable-stream "^2.0.5" + readable-stream "^2.3.3" stream-browserify "^2.0.1" - stream-http "^2.3.1" - string_decoder "^0.10.25" - timers-browserify "^2.0.2" + stream-http "^2.7.2" + string_decoder "^1.0.0" + timers-browserify "^2.0.4" tty-browserify "0.0.0" url "^0.11.0" util "^0.10.3" vm-browserify "0.0.4" -node-pre-gyp@^0.6.36: - version "0.6.38" - resolved "https://registry.yarnpkg.com/node-pre-gyp/-/node-pre-gyp-0.6.38.tgz#e92a20f83416415bb4086f6d1fb78b3da73d113d" +node-pre-gyp@^0.10.0: + version "0.10.3" + resolved "https://registry.yarnpkg.com/node-pre-gyp/-/node-pre-gyp-0.10.3.tgz#3070040716afdc778747b61b6887bf78880b80fc" dependencies: - hawk "3.1.3" + detect-libc "^1.0.2" mkdirp "^0.5.1" + needle "^2.2.1" nopt "^4.0.1" + npm-packlist "^1.1.6" npmlog "^4.0.2" - rc "^1.1.7" - request "2.81.0" + rc "^1.2.7" rimraf "^2.6.1" semver "^5.3.0" - tar "^2.2.1" - tar-pack "^3.4.0" + tar "^4" node-sass@^4.7.2: - version "4.7.2" - resolved "https://registry.yarnpkg.com/node-sass/-/node-sass-4.7.2.tgz#9366778ba1469eb01438a9e8592f4262bcb6794e" + version "4.9.3" + resolved "https://registry.yarnpkg.com/node-sass/-/node-sass-4.9.3.tgz#f407cf3d66f78308bb1e346b24fa428703196224" dependencies: async-foreach "^0.1.3" chalk "^1.1.1" @@ -5740,10 +6129,10 @@ node-sass@^4.7.2: lodash.mergewith "^4.6.0" meow "^3.7.0" mkdirp "^0.5.1" - nan "^2.3.2" - node-gyp "^3.3.1" + nan "^2.10.0" + node-gyp "^3.8.0" npmlog "^4.0.0" - request "~2.79.0" + request "2.87.0" sass-graph "^2.2.4" stdout-stream "^1.4.0" "true-case-path" "^1.0.2" @@ -5802,17 +6191,18 @@ nodemailer@^2.5.0: socks "1.1.9" nodemon@^1.15.0: - version "1.15.0" - resolved "https://registry.yarnpkg.com/nodemon/-/nodemon-1.15.0.tgz#ddec01eeb9c33d53dfbf7eddb2fa32f723474c1e" + version "1.18.3" + resolved "https://registry.yarnpkg.com/nodemon/-/nodemon-1.18.3.tgz#46e681ee0dd1b590562e03019b4c5df234f906f9" dependencies: chokidar "^2.0.2" debug "^3.1.0" ignore-by-default "^1.0.1" minimatch "^3.0.4" pstree.remy "^1.1.0" - semver "^5.4.1" + semver "^5.5.0" + supports-color "^5.2.0" touch "^3.1.0" - undefsafe "^2.0.1" + undefsafe "^2.0.2" update-notifier "^2.3.0" "nopt@2 || 3", nopt@3.x: @@ -5866,6 +6256,17 @@ nouislider@^11.0.0: version "11.1.0" resolved "https://registry.yarnpkg.com/nouislider/-/nouislider-11.1.0.tgz#1768eb5b854917325d41b96f2dc4eb3757d73381" +npm-bundled@^1.0.1: + version "1.0.5" + resolved "https://registry.yarnpkg.com/npm-bundled/-/npm-bundled-1.0.5.tgz#3c1732b7ba936b3a10325aef616467c0ccbcc979" + +npm-packlist@^1.1.6: + version "1.1.11" + resolved "https://registry.yarnpkg.com/npm-packlist/-/npm-packlist-1.1.11.tgz#84e8c683cbe7867d34b1d357d893ce29e28a02de" + dependencies: + ignore-walk "^3.0.1" + npm-bundled "^1.0.1" + npm-run-all@4.1.2: version "4.1.2" resolved "https://registry.yarnpkg.com/npm-run-all/-/npm-run-all-4.1.2.tgz#90d62d078792d20669139e718621186656cea056" @@ -5917,6 +6318,10 @@ oauth-sign@~0.8.1, oauth-sign@~0.8.2: version "0.8.2" resolved "https://registry.yarnpkg.com/oauth-sign/-/oauth-sign-0.8.2.tgz#46a6ab7f0aead8deae9ec0565780b7d4efeb9d43" +oauth-sign@~0.9.0: + version "0.9.0" + resolved "https://registry.yarnpkg.com/oauth-sign/-/oauth-sign-0.9.0.tgz#47a7b016baa68b5fa0ecf3dee08a85c679ac6455" + object-assign@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-3.0.0.tgz#9bedd5ca0897949bca47e7ff408062d549f587f2" @@ -5937,9 +6342,9 @@ object-copy@^0.1.0: define-property "^0.2.5" kind-of "^3.0.3" -object-keys@^1.0.8: - version "1.0.11" - resolved "https://registry.yarnpkg.com/object-keys/-/object-keys-1.0.11.tgz#c54601778ad560f1142ce0e01bcca8b56d13426d" +object-keys@^1.0.11, object-keys@^1.0.12: + version "1.0.12" + resolved "https://registry.yarnpkg.com/object-keys/-/object-keys-1.0.12.tgz#09c53855377575310cca62f55bb334abff7b3ed2" object-path@^0.9.2: version "0.9.2" @@ -5951,6 +6356,22 @@ object-visit@^1.0.0: dependencies: isobject "^3.0.0" +object.assign@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/object.assign/-/object.assign-4.1.0.tgz#968bf1100d7956bb3ca086f006f846b3bc4008da" + dependencies: + define-properties "^1.1.2" + function-bind "^1.1.1" + has-symbols "^1.0.0" + object-keys "^1.0.11" + +object.getownpropertydescriptors@^2.0.3: + version "2.0.3" + resolved "https://registry.yarnpkg.com/object.getownpropertydescriptors/-/object.getownpropertydescriptors-2.0.3.tgz#8758c846f5b407adab0f236e0986f14b051caa16" + dependencies: + define-properties "^1.1.2" + es-abstract "^1.5.1" + object.omit@^2.0.0: version "2.0.1" resolved "https://registry.yarnpkg.com/object.omit/-/object.omit-2.0.1.tgz#1a9c744829f39dbb858c76ca3579ae2a54ebd1fa" @@ -5964,9 +6385,18 @@ object.pick@^1.3.0: dependencies: isobject "^3.0.1" +object.values@^1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/object.values/-/object.values-1.0.4.tgz#e524da09b4f66ff05df457546ec72ac99f13069a" + dependencies: + define-properties "^1.1.2" + es-abstract "^1.6.1" + function-bind "^1.1.0" + has "^1.0.1" + obuf@^1.0.0, obuf@^1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/obuf/-/obuf-1.1.1.tgz#104124b6c602c6796881a042541d36db43a5264e" + version "1.1.2" + resolved "https://registry.yarnpkg.com/obuf/-/obuf-1.1.2.tgz#09bea3343d41859ebd446292d11c9d4db619084e" on-finished@~2.3.0: version "2.3.0" @@ -5978,23 +6408,51 @@ on-headers@~1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/on-headers/-/on-headers-1.0.1.tgz#928f5d0f470d49342651ea6794b0857c100693f7" -once@1.x, once@^1.3.0, once@^1.3.1, once@^1.3.3, once@^1.4.0: +once@1.x, once@^1.3.0, once@^1.3.1, once@^1.4.0: version "1.4.0" resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" dependencies: wrappy "1" onecolor@^3.0.4: - version "3.0.4" - resolved "https://registry.yarnpkg.com/onecolor/-/onecolor-3.0.4.tgz#75a46f80da6c7aaa5b4daae17a47198bd9652494" + version "3.0.5" + resolved "https://registry.yarnpkg.com/onecolor/-/onecolor-3.0.5.tgz#36eff32201379efdf1180fb445e51a8e2425f9f6" -opener@^1.4.3, opener@~1.4.0: +onetime@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/onetime/-/onetime-2.0.1.tgz#067428230fd67443b2794b22bba528b6867962d4" + dependencies: + mimic-fn "^1.0.0" + +opencollective@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/opencollective/-/opencollective-1.0.3.tgz#aee6372bc28144583690c3ca8daecfc120dd0ef1" + dependencies: + babel-polyfill "6.23.0" + chalk "1.1.3" + inquirer "3.0.6" + minimist "1.2.0" + node-fetch "1.6.3" + opn "4.0.2" + +opener@^1.4.3: + version "1.5.0" + resolved "https://registry.yarnpkg.com/opener/-/opener-1.5.0.tgz#24222fb4ad423ba21f5bf38855cebe44220f6531" + +opener@~1.4.0: version "1.4.3" resolved "https://registry.yarnpkg.com/opener/-/opener-1.4.3.tgz#5c6da2c5d7e5831e8ffa3964950f8d6674ac90b8" -opn@^5.1.0: - version "5.1.0" - resolved "https://registry.yarnpkg.com/opn/-/opn-5.1.0.tgz#72ce2306a17dbea58ff1041853352b4a8fc77519" +opn@4.0.2: + version "4.0.2" + resolved "https://registry.yarnpkg.com/opn/-/opn-4.0.2.tgz#7abc22e644dff63b0a96d5ab7f2790c0f01abc95" + dependencies: + object-assign "^4.0.1" + pinkie-promise "^2.0.0" + +opn@^5.1.0, opn@^5.3.0: + version "5.3.0" + resolved "https://registry.yarnpkg.com/opn/-/opn-5.3.0.tgz#64871565c863875f052cfdf53d3e3cb5adb53b1c" dependencies: is-wsl "^1.1.0" @@ -6016,21 +6474,24 @@ optionator@^0.8.1: type-check "~0.3.2" wordwrap "~1.0.0" -options@>=0.0.5: - version "0.0.6" - resolved "https://registry.yarnpkg.com/options/-/options-0.0.6.tgz#ec22d312806bb53e731773e7cdaefcf1c643128f" +ora@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/ora/-/ora-2.1.0.tgz#6caf2830eb924941861ec53a173799e008b51e5b" + dependencies: + chalk "^2.3.1" + cli-cursor "^2.1.0" + cli-spinners "^1.1.0" + log-symbols "^2.2.0" + strip-ansi "^4.0.0" + wcwidth "^1.0.1" original@>=0.0.5: - version "1.0.0" - resolved "https://registry.yarnpkg.com/original/-/original-1.0.0.tgz#9147f93fa1696d04be61e01bd50baeaca656bd3b" + version "1.0.2" + resolved "https://registry.yarnpkg.com/original/-/original-1.0.2.tgz#e442a61cffe1c5fd20a65f3261c26663b303f25f" dependencies: - url-parse "1.0.x" + url-parse "^1.4.3" -os-browserify@^0.2.0: - version "0.2.1" - resolved "https://registry.yarnpkg.com/os-browserify/-/os-browserify-0.2.1.tgz#63fc4ccee5d2d7763d26bbf8601078e6c2e0044f" - -os-browserify@~0.3.0: +os-browserify@^0.3.0, os-browserify@~0.3.0: version "0.3.0" resolved "https://registry.yarnpkg.com/os-browserify/-/os-browserify-0.3.0.tgz#854373c7f5c2315914fc9bfc6bd8238fdda1ec27" @@ -6057,8 +6518,8 @@ os-tmpdir@^1.0.0, os-tmpdir@^1.0.1, os-tmpdir@~1.0.1, os-tmpdir@~1.0.2: resolved "https://registry.yarnpkg.com/os-tmpdir/-/os-tmpdir-1.0.2.tgz#bbe67406c79aa85c5cfec766fe5734555dfa1274" osenv@0, osenv@^0.1.4: - version "0.1.4" - resolved "https://registry.yarnpkg.com/osenv/-/osenv-0.1.4.tgz#42fe6d5953df06c8064be6f176c3d05aaaa34644" + version "0.1.5" + resolved "https://registry.yarnpkg.com/osenv/-/osenv-0.1.5.tgz#85cdfafaeb28e8677f416e287592b5f3f49ea410" dependencies: os-homedir "^1.0.0" os-tmpdir "^1.0.0" @@ -6067,16 +6528,12 @@ p-finally@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/p-finally/-/p-finally-1.0.0.tgz#3fbcfb15b899a44123b34b6dcc18b724336a2cae" -p-limit@^1.0.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-1.2.0.tgz#0e92b6bedcb59f022c13d0f1949dc82d15909f1c" +p-limit@^1.0.0, p-limit@^1.1.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-1.3.0.tgz#b86bd5f0c25690911c7590fcbfc2010d54b3ccb8" dependencies: p-try "^1.0.0" -p-limit@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-1.1.0.tgz#b07ff2d9a5d88bec806035895a2bab66a27988bc" - p-locate@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-2.0.0.tgz#20a0103b222a70c8fd39cc2e580680f3dde5ec43" @@ -6091,29 +6548,28 @@ p-try@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/p-try/-/p-try-1.0.0.tgz#cbc79cdbaf8fd4228e13f621f2b1a237c1b207b3" -pac-proxy-agent@1: - version "1.1.0" - resolved "https://registry.yarnpkg.com/pac-proxy-agent/-/pac-proxy-agent-1.1.0.tgz#34a385dfdf61d2f0ecace08858c745d3e791fd4d" +pac-proxy-agent@^2.0.1: + version "2.0.2" + resolved "https://registry.yarnpkg.com/pac-proxy-agent/-/pac-proxy-agent-2.0.2.tgz#90d9f6730ab0f4d2607dcdcd4d3d641aa26c3896" dependencies: - agent-base "2" - debug "2" - extend "3" - get-uri "2" - http-proxy-agent "1" - https-proxy-agent "1" - pac-resolver "~2.0.0" - raw-body "2" - socks-proxy-agent "2" + agent-base "^4.2.0" + debug "^3.1.0" + get-uri "^2.0.0" + http-proxy-agent "^2.1.0" + https-proxy-agent "^2.2.1" + pac-resolver "^3.0.0" + raw-body "^2.2.0" + socks-proxy-agent "^3.0.0" -pac-resolver@~2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/pac-resolver/-/pac-resolver-2.0.0.tgz#99b88d2f193fbdeefc1c9a529c1f3260ab5277cd" +pac-resolver@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/pac-resolver/-/pac-resolver-3.0.0.tgz#6aea30787db0a891704deb7800a722a7615a6f26" dependencies: - co "~3.0.6" - degenerator "~1.0.2" - ip "1.0.1" - netmask "~1.0.4" - thunkify "~2.1.1" + co "^4.6.0" + degenerator "^1.0.4" + ip "^1.1.5" + netmask "^1.0.6" + thunkify "^2.1.2" package-json@^4.0.0: version "4.0.1" @@ -6124,10 +6580,6 @@ package-json@^4.0.0: registry-url "^3.0.3" semver "^5.1.0" -pako@~0.2.0: - version "0.2.9" - resolved "https://registry.yarnpkg.com/pako/-/pako-0.2.9.tgz#f3f7522f4ef782348da8161bad9ecfd51bf83a75" - pako@~1.0.2, pako@~1.0.5: version "1.0.6" resolved "https://registry.yarnpkg.com/pako/-/pako-1.0.6.tgz#0101211baa70c4bca4a0f63f2206e97b7dfaf258" @@ -6153,8 +6605,8 @@ parents@^1.0.0, parents@^1.0.1: path-platform "~0.11.15" parse-asn1@^5.0.0: - version "5.1.0" - resolved "https://registry.yarnpkg.com/parse-asn1/-/parse-asn1-5.1.0.tgz#37c4f9b7ed3ab65c74817b5f2480937fbf97c712" + version "5.1.1" + resolved "https://registry.yarnpkg.com/parse-asn1/-/parse-asn1-5.1.1.tgz#f6bf293818332bd0dab54efb16087724745e6ca8" dependencies: asn1.js "^4.0.0" browserify-aes "^1.0.0" @@ -6208,10 +6660,14 @@ pascalcase@^0.1.1: version "0.1.1" resolved "https://registry.yarnpkg.com/pascalcase/-/pascalcase-0.1.1.tgz#b363e55e8006ca6fe21784d2db22bd15d7917f14" -path-browserify@0.0.0, path-browserify@~0.0.0: +path-browserify@0.0.0: version "0.0.0" resolved "https://registry.yarnpkg.com/path-browserify/-/path-browserify-0.0.0.tgz#a0b870729aae214005b7d5032ec2cbbb0fb4451a" +path-browserify@~0.0.0: + version "0.0.1" + resolved "https://registry.yarnpkg.com/path-browserify/-/path-browserify-0.0.1.tgz#e6c4ddd7ed3aa27c68a20cc4e50e1a4ee83bbc4a" + path-dirname@^1.0.0: version "1.0.2" resolved "https://registry.yarnpkg.com/path-dirname/-/path-dirname-1.0.2.tgz#cc33d24d525e099a5388c0336c6e32b9160609e0" @@ -6226,7 +6682,7 @@ path-exists@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-3.0.0.tgz#ce0ebeaa5f78cb18925ea7d810d7b59b010fd515" -path-is-absolute@^1.0.0: +path-is-absolute@^1.0.0, path-is-absolute@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" @@ -6239,8 +6695,8 @@ path-key@^2.0.0: resolved "https://registry.yarnpkg.com/path-key/-/path-key-2.0.1.tgz#411cadb574c5a140d3a4b1910d40d80cc9f40b40" path-parse@^1.0.5: - version "1.0.5" - resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.5.tgz#3c1adf871ea9cd6c9431b6ea2bd74a0ff055c4c1" + version "1.0.6" + resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.6.tgz#d62dbb5679405d72c4737ec58600e9ddcf06d24c" path-platform@~0.11.15: version "0.11.15" @@ -6264,12 +6720,6 @@ path-type@^1.0.0: pify "^2.0.0" pinkie-promise "^2.0.0" -path-type@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/path-type/-/path-type-2.0.0.tgz#f012ccb8415b7096fc2daa1054c3d72389594c73" - dependencies: - pify "^2.0.0" - path-type@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/path-type/-/path-type-3.0.0.tgz#cef31dc8e0a1a3bb0d105c0cd97cf3bf47f4e36f" @@ -6283,8 +6733,8 @@ pause-stream@0.0.11: through "~2.3" pbkdf2@^3.0.3: - version "3.0.14" - resolved "https://registry.yarnpkg.com/pbkdf2/-/pbkdf2-3.0.14.tgz#a35e13c64799b06ce15320f459c230e68e73bade" + version "3.0.16" + resolved "https://registry.yarnpkg.com/pbkdf2/-/pbkdf2-3.0.16.tgz#7404208ec6b01b62d85bf83853a8064f8d9c2a5c" dependencies: create-hash "^1.1.2" create-hmac "^1.1.4" @@ -6305,27 +6755,23 @@ pend@~1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/pend/-/pend-1.2.0.tgz#7a57eb550a6783f9115331fcf4663d5c8e007a50" -performance-now@^0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/performance-now/-/performance-now-0.2.0.tgz#33ef30c5c77d4ea21c5a53869d91b56d8f2555e5" - performance-now@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/performance-now/-/performance-now-2.1.0.tgz#6309f4e0e5fa913ec1c69307ae364b4b377c9e7b" phantomjs-prebuilt@^2.1.7: - version "2.1.15" - resolved "https://registry.yarnpkg.com/phantomjs-prebuilt/-/phantomjs-prebuilt-2.1.15.tgz#20f86e82d3349c505917527745b7a411e08b3903" + version "2.1.16" + resolved "https://registry.yarnpkg.com/phantomjs-prebuilt/-/phantomjs-prebuilt-2.1.16.tgz#efd212a4a3966d3647684ea8ba788549be2aefef" dependencies: - es6-promise "~4.0.3" - extract-zip "~1.6.5" - fs-extra "~1.0.0" - hasha "~2.2.0" - kew "~0.7.0" - progress "~1.1.8" - request "~2.81.0" - request-progress "~2.0.1" - which "~1.2.10" + es6-promise "^4.0.3" + extract-zip "^1.6.5" + fs-extra "^1.0.0" + hasha "^2.2.0" + kew "^0.7.0" + progress "^1.1.8" + request "^2.81.0" + request-progress "^2.0.1" + which "^1.2.10" pify@^2.0.0, pify@^2.3.0: version "2.3.0" @@ -6376,9 +6822,15 @@ plugin-error@^0.1.2: arr-union "^2.0.1" extend-shallow "^1.1.2" +plur@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/plur/-/plur-3.0.1.tgz#268652d605f816699b42b86248de73c9acd06a7c" + dependencies: + irregular-plurals "^2.0.0" + portfinder@^1.0.13, portfinder@^1.0.9: - version "1.0.13" - resolved "https://registry.yarnpkg.com/portfinder/-/portfinder-1.0.13.tgz#bb32ecd87c27104ae6ee44b5a3ccbf0ebb1aede9" + version "1.0.17" + resolved "https://registry.yarnpkg.com/portfinder/-/portfinder-1.0.17.tgz#a8a1691143e46c4735edefcf4fbcccedad26456a" dependencies: async "^1.5.2" debug "^2.2.0" @@ -6412,8 +6864,8 @@ postcss-calc@^5.2.0: reduce-css-calc "^1.2.6" postcss-calc@^6.0.0: - version "6.0.0" - resolved "https://registry.yarnpkg.com/postcss-calc/-/postcss-calc-6.0.0.tgz#b681b279c6d24fbe0e33ed9045803705445d613b" + version "6.0.1" + resolved "https://registry.yarnpkg.com/postcss-calc/-/postcss-calc-6.0.1.tgz#3d24171bbf6e7629d422a436ebfe6dd9511f4330" dependencies: css-unit-converter "^1.1.1" postcss "^6.0.0" @@ -6421,15 +6873,15 @@ postcss-calc@^6.0.0: reduce-css-calc "^2.0.0" postcss-cli@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/postcss-cli/-/postcss-cli-5.0.0.tgz#3d6aee7652b8dc6566f0189dd90d11bb0a535a20" + version "5.0.1" + resolved "https://registry.yarnpkg.com/postcss-cli/-/postcss-cli-5.0.1.tgz#95f309fffbee3273c161704e2b9f58d5a4993cf1" dependencies: chalk "^2.1.0" chokidar "^2.0.0" dependency-graph "^0.7.0" fs-extra "^5.0.0" - get-stdin "^5.0.1" - globby "^7.1.1" + get-stdin "^6.0.0" + globby "^8.0.0" postcss "^6.0.1" postcss-load-config "^1.1.0" postcss-reporter "^5.0.0" @@ -6438,20 +6890,20 @@ postcss-cli@^5.0.0: yargs "^11.0.0" postcss-color-function@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/postcss-color-function/-/postcss-color-function-4.0.0.tgz#7e0106f4f6a1ecb1ad5b3a8553ace5e828aae187" + version "4.0.1" + resolved "https://registry.yarnpkg.com/postcss-color-function/-/postcss-color-function-4.0.1.tgz#402b3f2cebc3f6947e618fb6be3654fbecef6444" dependencies: - css-color-function "^1.3.0" + css-color-function "~1.3.3" postcss "^6.0.1" postcss-message-helpers "^2.0.0" postcss-value-parser "^3.3.0" postcss-color-gray@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/postcss-color-gray/-/postcss-color-gray-4.0.0.tgz#681bf305097dd66bfef0e1e6282d5d99b5acc95d" + version "4.1.0" + resolved "https://registry.yarnpkg.com/postcss-color-gray/-/postcss-color-gray-4.1.0.tgz#e5581ed57eaa826fb652ca11b1e2b7b136a9f9df" dependencies: - color "^1.0.3" - postcss "^6.0.1" + color "^2.0.1" + postcss "^6.0.14" postcss-message-helpers "^2.0.0" reduce-function-call "^1.0.2" @@ -6481,11 +6933,11 @@ postcss-color-hwb@^3.0.0: reduce-function-call "^1.0.2" postcss-color-rebeccapurple@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/postcss-color-rebeccapurple/-/postcss-color-rebeccapurple-3.0.0.tgz#eebaf03d363b4300b96792bd3081c19ed66513d3" + version "3.1.0" + resolved "https://registry.yarnpkg.com/postcss-color-rebeccapurple/-/postcss-color-rebeccapurple-3.1.0.tgz#ce1269ecc2d0d8bf92aab44bd884e633124c33ec" dependencies: - postcss "^6.0.1" - postcss-value-parser "^3.3.0" + postcss "^6.0.22" + postcss-values-parser "^1.5.0" postcss-color-rgb@^2.0.0: version "2.0.0" @@ -6560,11 +7012,11 @@ postcss-custom-media@^6.0.0: postcss "^6.0.1" postcss-custom-properties@^6.1.0: - version "6.1.0" - resolved "https://registry.yarnpkg.com/postcss-custom-properties/-/postcss-custom-properties-6.1.0.tgz#9caf1151ac41b1e9e64d3a2ff9ece996ca18977d" + version "6.3.1" + resolved "https://registry.yarnpkg.com/postcss-custom-properties/-/postcss-custom-properties-6.3.1.tgz#5c52abde313d7ec9368c4abf67d27a656cba8b39" dependencies: balanced-match "^1.0.0" - postcss "^6.0.3" + postcss "^6.0.18" postcss-custom-selectors@^4.0.1: version "4.0.1" @@ -6605,11 +7057,10 @@ postcss-discard-unused@^2.2.1: uniqs "^2.0.0" postcss-filter-plugins@^2.0.0: - version "2.0.2" - resolved "https://registry.yarnpkg.com/postcss-filter-plugins/-/postcss-filter-plugins-2.0.2.tgz#6d85862534d735ac420e4a85806e1f5d4286d84c" + version "2.0.3" + resolved "https://registry.yarnpkg.com/postcss-filter-plugins/-/postcss-filter-plugins-2.0.3.tgz#82245fdf82337041645e477114d8e593aa18b8ec" dependencies: postcss "^5.0.4" - uniqid "^4.0.0" postcss-font-family-system-ui@^3.0.0: version "3.0.0" @@ -6637,7 +7088,7 @@ postcss-initial@^2.0.0: lodash.template "^4.2.4" postcss "^6.0.1" -postcss-load-config@^1.1.0, postcss-load-config@^1.2.0: +postcss-load-config@^1.1.0: version "1.2.0" resolved "https://registry.yarnpkg.com/postcss-load-config/-/postcss-load-config-1.2.0.tgz#539e9afc9ddc8620121ebf9d8c3673e0ce50d28a" dependencies: @@ -6646,6 +7097,13 @@ postcss-load-config@^1.1.0, postcss-load-config@^1.2.0: postcss-load-options "^1.2.0" postcss-load-plugins "^2.3.0" +postcss-load-config@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/postcss-load-config/-/postcss-load-config-2.0.0.tgz#f1312ddbf5912cd747177083c5ef7a19d62ee484" + dependencies: + cosmiconfig "^4.0.0" + import-cwd "^2.0.0" + postcss-load-options@^1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/postcss-load-options/-/postcss-load-options-1.2.0.tgz#b098b1559ddac2df04bc0bb375f99a5cfe2b6d8c" @@ -6661,12 +7119,12 @@ postcss-load-plugins@^2.3.0: object-assign "^4.1.0" postcss-loader@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/postcss-loader/-/postcss-loader-2.1.0.tgz#038c2d6d59753fef4667827fd3ae03f5dc5e6a7a" + version "2.1.6" + resolved "https://registry.yarnpkg.com/postcss-loader/-/postcss-loader-2.1.6.tgz#1d7dd7b17c6ba234b9bed5af13e0bea40a42d740" dependencies: loader-utils "^1.1.0" postcss "^6.0.0" - postcss-load-config "^1.2.0" + postcss-load-config "^2.0.0" schema-utils "^0.4.0" postcss-media-minmax@^3.0.0: @@ -6858,10 +7316,10 @@ postcss-sass@^0.2.0: postcss "^6.0.6" postcss-scss@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/postcss-scss/-/postcss-scss-1.0.2.tgz#ff45cf3354b879ee89a4eb68680f46ac9bb14f94" + version "1.0.6" + resolved "https://registry.yarnpkg.com/postcss-scss/-/postcss-scss-1.0.6.tgz#ab903f3bb20161bc177896462293a53d4bff5f7a" dependencies: - postcss "^6.0.3" + postcss "^6.0.23" postcss-selector-matches@^3.0.0, postcss-selector-matches@^3.0.1: version "3.0.1" @@ -6922,6 +7380,14 @@ postcss-value-parser@^3.0.1, postcss-value-parser@^3.0.2, postcss-value-parser@^ version "3.3.0" resolved "https://registry.yarnpkg.com/postcss-value-parser/-/postcss-value-parser-3.3.0.tgz#87f38f9f18f774a4ab4c8a232f5c5ce8872a9d15" +postcss-values-parser@^1.5.0: + version "1.5.0" + resolved "https://registry.yarnpkg.com/postcss-values-parser/-/postcss-values-parser-1.5.0.tgz#5d9fa63e2bcb0179ce48f3235303765eb89f3047" + dependencies: + flatten "^1.0.2" + indexes-of "^1.0.1" + uniq "^1.0.1" + postcss-zindex@^2.0.1: version "2.2.0" resolved "https://registry.yarnpkg.com/postcss-zindex/-/postcss-zindex-2.2.0.tgz#d2109ddc055b91af67fc4cb3b025946639d2af22" @@ -6931,37 +7397,21 @@ postcss-zindex@^2.0.1: uniqs "^2.0.0" postcss@^5.0.10, postcss@^5.0.11, postcss@^5.0.12, postcss@^5.0.13, postcss@^5.0.14, postcss@^5.0.16, postcss@^5.0.2, postcss@^5.0.4, postcss@^5.0.5, postcss@^5.0.6, postcss@^5.0.8, postcss@^5.2.16: - version "5.2.17" - resolved "https://registry.yarnpkg.com/postcss/-/postcss-5.2.17.tgz#cf4f597b864d65c8a492b2eabe9d706c879c388b" + version "5.2.18" + resolved "https://registry.yarnpkg.com/postcss/-/postcss-5.2.18.tgz#badfa1497d46244f6390f58b319830d9107853c5" dependencies: chalk "^1.1.3" js-base64 "^2.1.9" source-map "^0.5.6" supports-color "^3.2.3" -postcss@^6.0, postcss@^6.0.14: - version "6.0.16" - resolved "https://registry.yarnpkg.com/postcss/-/postcss-6.0.16.tgz#112e2fe2a6d2109be0957687243170ea5589e146" +postcss@^6.0, postcss@^6.0.0, postcss@^6.0.1, postcss@^6.0.11, postcss@^6.0.14, postcss@^6.0.17, postcss@^6.0.18, postcss@^6.0.22, postcss@^6.0.23, postcss@^6.0.5, postcss@^6.0.6, postcss@^6.0.8: + version "6.0.23" + resolved "https://registry.yarnpkg.com/postcss/-/postcss-6.0.23.tgz#61c82cc328ac60e677645f979054eb98bc0e3324" dependencies: - chalk "^2.3.0" + chalk "^2.4.1" source-map "^0.6.1" - supports-color "^5.1.0" - -postcss@^6.0.0, postcss@^6.0.1, postcss@^6.0.11, postcss@^6.0.13, postcss@^6.0.3, postcss@^6.0.5, postcss@^6.0.6, postcss@^6.0.8: - version "6.0.13" - resolved "https://registry.yarnpkg.com/postcss/-/postcss-6.0.13.tgz#b9ecab4ee00c89db3ec931145bd9590bbf3f125f" - dependencies: - chalk "^2.1.0" - source-map "^0.6.1" - supports-color "^4.4.0" - -postcss@^6.0.17, postcss@^6.0.18: - version "6.0.18" - resolved "https://registry.yarnpkg.com/postcss/-/postcss-6.0.18.tgz#370f5f44d47f3a205f0eb2f6262bbf202df2a80e" - dependencies: - chalk "^2.3.1" - source-map "^0.6.1" - supports-color "^5.2.0" + supports-color "^5.4.0" prelude-ls@~1.1.2: version "1.1.2" @@ -6975,6 +7425,10 @@ preserve@^0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/preserve/-/preserve-0.2.0.tgz#815ed1f6ebc65926f865b310c0713bcb3315ce4b" +pretty-bytes@^5.0.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/pretty-bytes/-/pretty-bytes-5.1.0.tgz#6237ecfbdc6525beaef4de722cc60a58ae0e6c6d" + pretty-error@^2.0.2: version "2.1.1" resolved "https://registry.yarnpkg.com/pretty-error/-/pretty-error-2.1.1.tgz#5f4f87c8f91e5ae3f3ba87ab4cf5e03b1a17f1a3" @@ -6994,18 +7448,22 @@ process-nextick-args@~1.0.6: version "1.0.7" resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-1.0.7.tgz#150e20b756590ad3f91093f25a4f2ad8bff30ba3" -process@^0.11.0, process@~0.11.0: +process-nextick-args@~2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-2.0.0.tgz#a37d732f4271b4ab1ad070d35508e8290788ffaa" + +process@^0.11.10, process@~0.11.0: version "0.11.10" resolved "https://registry.yarnpkg.com/process/-/process-0.11.10.tgz#7332300e840161bda3e69a1d1d91a7d4bc16f182" +progress@^1.1.8: + version "1.1.8" + resolved "https://registry.yarnpkg.com/progress/-/progress-1.1.8.tgz#e260c78f6161cdd9b0e56cc3e0a85de17c7a57be" + progress@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/progress/-/progress-2.0.0.tgz#8a1be366bf8fc23db2bd23f10c6fe920b4389d1f" -progress@~1.1.8: - version "1.1.8" - resolved "https://registry.yarnpkg.com/progress/-/progress-1.1.8.tgz#e260c78f6161cdd9b0e56cc3e0a85de17c7a57be" - promise-each@^2.2.0: version "2.2.0" resolved "https://registry.yarnpkg.com/promise-each/-/promise-each-2.2.0.tgz#3353174eff2694481037e04e01f77aa0fb6d1b60" @@ -7016,6 +7474,12 @@ promise-inflight@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/promise-inflight/-/promise-inflight-1.0.1.tgz#98472870bf228132fcbdd868129bad12c3c029e3" +promisify-call@^2.0.2: + version "2.0.4" + resolved "https://registry.yarnpkg.com/promisify-call/-/promisify-call-2.0.4.tgz#d48c2d45652ccccd52801ddecbd533a6d4bd5fba" + dependencies: + with-callback "^1.0.2" + protractor-istanbul-plugin@2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/protractor-istanbul-plugin/-/protractor-istanbul-plugin-2.0.0.tgz#f6271d2a5d6382488e86ff9fb7770f46a8b2c5e2" @@ -7026,48 +7490,53 @@ protractor-istanbul-plugin@2.0.0: uuid "^2.0.1" protractor@^5.3.0: - version "5.3.0" - resolved "https://registry.yarnpkg.com/protractor/-/protractor-5.3.0.tgz#5df98201cbdaeb50826af6d05630ef1945bf9c32" + version "5.4.0" + resolved "https://registry.yarnpkg.com/protractor/-/protractor-5.4.0.tgz#e71c9c1f5cf6c5e9bdbcdb71e7f31b17ffd2878f" dependencies: "@types/node" "^6.0.46" "@types/q" "^0.0.32" - "@types/selenium-webdriver" "~2.53.39" + "@types/selenium-webdriver" "^3.0.0" blocking-proxy "^1.0.0" + browserstack "^1.5.1" chalk "^1.1.3" glob "^7.0.3" jasmine "2.8.0" jasminewd2 "^2.1.0" optimist "~0.6.0" q "1.4.1" - saucelabs "~1.3.0" + saucelabs "^1.5.0" selenium-webdriver "3.6.0" source-map-support "~0.4.0" - webdriver-js-extender "^1.0.0" + webdriver-js-extender "2.0.0" webdriver-manager "^12.0.6" -proxy-addr@~2.0.2: - version "2.0.2" - resolved "https://registry.yarnpkg.com/proxy-addr/-/proxy-addr-2.0.2.tgz#6571504f47bb988ec8180253f85dd7e14952bdec" +proxy-addr@~2.0.2, proxy-addr@~2.0.3: + version "2.0.4" + resolved "https://registry.yarnpkg.com/proxy-addr/-/proxy-addr-2.0.4.tgz#ecfc733bf22ff8c6f407fa275327b9ab67e48b93" dependencies: forwarded "~0.1.2" - ipaddr.js "1.5.2" + ipaddr.js "1.8.0" -proxy-agent@~2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/proxy-agent/-/proxy-agent-2.0.0.tgz#57eb5347aa805d74ec681cb25649dba39c933499" +proxy-agent@~3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/proxy-agent/-/proxy-agent-3.0.1.tgz#4fb7b61b1476d0fe8e3a3384d90e2460bbded3f9" dependencies: - agent-base "2" - debug "2" - extend "3" - http-proxy-agent "1" - https-proxy-agent "1" - lru-cache "~2.6.5" - pac-proxy-agent "1" - socks-proxy-agent "2" + agent-base "^4.2.0" + debug "^3.1.0" + http-proxy-agent "^2.1.0" + https-proxy-agent "^2.2.1" + lru-cache "^4.1.2" + pac-proxy-agent "^2.0.1" + proxy-from-env "^1.0.0" + socks-proxy-agent "^4.0.1" -prr@~0.0.0: - version "0.0.0" - resolved "https://registry.yarnpkg.com/prr/-/prr-0.0.0.tgz#1a84b85908325501411853d0081ee3fa86e2926a" +proxy-from-env@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/proxy-from-env/-/proxy-from-env-1.0.0.tgz#33c50398f70ea7eb96d21f7b817630a55791c7ee" + +prr@~1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/prr/-/prr-1.0.1.tgz#d3fc114ba06995a45ec6893f484ceb1d78f5f476" ps-tree@^1.1.0: version "1.1.0" @@ -7079,6 +7548,10 @@ pseudomap@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/pseudomap/-/pseudomap-1.0.2.tgz#f052a28da70e618917ef0a8ac34c1ae5a68286b3" +psl@^1.1.24: + version "1.1.29" + resolved "https://registry.yarnpkg.com/psl/-/psl-1.1.29.tgz#60f580d360170bb722a797cc704411e6da850c67" + pstree.remy@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/pstree.remy/-/pstree.remy-1.1.0.tgz#f2af27265bd3e5b32bbfcc10e80bac55ba78688b" @@ -7086,8 +7559,8 @@ pstree.remy@^1.1.0: ps-tree "^1.1.0" public-encrypt@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/public-encrypt/-/public-encrypt-4.0.0.tgz#39f699f3a46560dd5ebacbca693caf7c65c18cc6" + version "4.0.2" + resolved "https://registry.yarnpkg.com/public-encrypt/-/public-encrypt-4.0.2.tgz#46eb9107206bf73489f8b85b69d91334c6610994" dependencies: bn.js "^4.1.0" browserify-rsa "^4.0.0" @@ -7095,25 +7568,18 @@ public-encrypt@^4.0.0: parse-asn1 "^5.0.0" randombytes "^2.0.1" -pump@^1.0.0: - version "1.0.3" - resolved "https://registry.yarnpkg.com/pump/-/pump-1.0.3.tgz#5dfe8311c33bbf6fc18261f9f34702c47c08a954" - dependencies: - end-of-stream "^1.1.0" - once "^1.3.1" - -pump@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/pump/-/pump-2.0.0.tgz#7946da1c8d622b098e2ceb2d3476582470829c9d" +pump@^2.0.0, pump@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/pump/-/pump-2.0.1.tgz#12399add6e4cf7526d973cbc8b5ce2e2908b3909" dependencies: end-of-stream "^1.1.0" once "^1.3.1" pumpify@^1.3.3: - version "1.4.0" - resolved "https://registry.yarnpkg.com/pumpify/-/pumpify-1.4.0.tgz#80b7c5df7e24153d03f0e7ac8a05a5d068bd07fb" + version "1.5.1" + resolved "https://registry.yarnpkg.com/pumpify/-/pumpify-1.5.1.tgz#36513be246ab27570b1a374a5ce278bfd74370ce" dependencies: - duplexify "^3.5.3" + duplexify "^3.6.0" inherits "^2.0.3" pump "^2.0.0" @@ -7125,18 +7591,30 @@ punycode@1.4.1, punycode@^1.2.4, punycode@^1.3.2, punycode@^1.4.1: version "1.4.1" resolved "https://registry.yarnpkg.com/punycode/-/punycode-1.4.1.tgz#c0d5a63b2718800ad8e1eb0fa5269c84dd41845e" -q@1.4.1, q@^1.1.2, q@^1.4.1, q@~1.4.0: +punycode@^2.1.0: + version "2.1.1" + resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.1.1.tgz#b58b010ac40c22c5657616c8d2c2c02c7bf479ec" + +q@1.4.1: version "1.4.1" resolved "https://registry.yarnpkg.com/q/-/q-1.4.1.tgz#55705bcd93c5f3673530c2c2cbc0c2b3addc286e" -qjobs@^1.1.4: - version "1.1.5" - resolved "https://registry.yarnpkg.com/qjobs/-/qjobs-1.1.5.tgz#659de9f2cf8dcc27a1481276f205377272382e73" +q@^1.1.2, q@^1.4.1: + version "1.5.1" + resolved "https://registry.yarnpkg.com/q/-/q-1.5.1.tgz#7e32f75b41381291d04611f1bf14109ac00651d7" -qs@6.5.1, qs@~6.5.1: +qjobs@^1.1.4: + version "1.2.0" + resolved "https://registry.yarnpkg.com/qjobs/-/qjobs-1.2.0.tgz#c45e9c61800bd087ef88d7e256423bdd49e5d071" + +qs@6.5.1: version "6.5.1" resolved "https://registry.yarnpkg.com/qs/-/qs-6.5.1.tgz#349cdf6eef89ec45c12d7d5eb3fc0c870343a6d8" +qs@6.5.2, qs@~6.5.1, qs@~6.5.2: + version "6.5.2" + resolved "https://registry.yarnpkg.com/qs/-/qs-6.5.2.tgz#cb3ae806e8740444584ef154ce8ee98d403f3e36" + qs@~2.3.3: version "2.3.3" resolved "https://registry.yarnpkg.com/qs/-/qs-2.3.3.tgz#e9e85adbe75da0bbe4c8e0476a086290f863b404" @@ -7145,14 +7623,6 @@ qs@~6.2.0: version "6.2.3" resolved "https://registry.yarnpkg.com/qs/-/qs-6.2.3.tgz#1cfcb25c10a9b2b483053ff39f5dfc9233908cfe" -qs@~6.3.0: - version "6.3.2" - resolved "https://registry.yarnpkg.com/qs/-/qs-6.3.2.tgz#e75bd5f6e268122a2a0e0bda630b2550c166502c" - -qs@~6.4.0: - version "6.4.0" - resolved "https://registry.yarnpkg.com/qs/-/qs-6.4.0.tgz#13e26d28ad6b0ffaa91312cd3bf708ed351e7233" - query-string@^4.1.0: version "4.3.4" resolved "https://registry.yarnpkg.com/query-string/-/query-string-4.3.4.tgz#bbb693b9ca915c232515b228b1a02b609043dbeb" @@ -7168,40 +7638,35 @@ querystring@0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/querystring/-/querystring-0.2.0.tgz#b209849203bb25df820da756e747005878521620" -querystringify@0.0.x: - version "0.0.4" - resolved "https://registry.yarnpkg.com/querystringify/-/querystringify-0.0.4.tgz#0cf7f84f9463ff0ae51c4c4b142d95be37724d9c" +querystringify@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/querystringify/-/querystringify-2.0.0.tgz#fa3ed6e68eb15159457c89b37bc6472833195755" -querystringify@~1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/querystringify/-/querystringify-1.0.0.tgz#6286242112c5b712fa654e526652bf6a13ff05cb" +quick-lru@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/quick-lru/-/quick-lru-1.1.0.tgz#4360b17c61136ad38078397ff11416e186dcfbb8" random-bytes@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/random-bytes/-/random-bytes-1.0.0.tgz#4f68a1dc0ae58bd3fb95848c30324db75d64360b" -randomatic@^1.1.3: - version "1.1.7" - resolved "https://registry.yarnpkg.com/randomatic/-/randomatic-1.1.7.tgz#c7abe9cc8b87c0baa876b19fde83fd464797e38c" +randomatic@^3.0.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/randomatic/-/randomatic-3.1.0.tgz#36f2ca708e9e567f5ed2ec01949026d50aa10116" dependencies: - is-number "^3.0.0" - kind-of "^4.0.0" + is-number "^4.0.0" + kind-of "^6.0.0" + math-random "^1.0.1" -randombytes@^2.0.0, randombytes@^2.0.1: - version "2.0.5" - resolved "https://registry.yarnpkg.com/randombytes/-/randombytes-2.0.5.tgz#dc009a246b8d09a177b4b7a0ae77bc570f4b1b79" - dependencies: - safe-buffer "^5.1.0" - -randombytes@^2.0.5: +randombytes@^2.0.0, randombytes@^2.0.1, randombytes@^2.0.5: version "2.0.6" resolved "https://registry.yarnpkg.com/randombytes/-/randombytes-2.0.6.tgz#d302c522948588848a8d300c932b44c24231da80" dependencies: safe-buffer "^5.1.0" randomfill@^1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/randomfill/-/randomfill-1.0.3.tgz#b96b7df587f01dd91726c418f30553b1418e3d62" + version "1.0.4" + resolved "https://registry.yarnpkg.com/randomfill/-/randomfill-1.0.4.tgz#c92196fc86ab42be983f1bf31778224931d61458" dependencies: randombytes "^2.0.5" safe-buffer "^5.1.0" @@ -7210,7 +7675,7 @@ range-parser@^1.0.3, range-parser@^1.2.0, range-parser@~1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/range-parser/-/range-parser-1.2.0.tgz#f49be6b487894ddc40dcc94a322f611092e00d5e" -raw-body@2, raw-body@2.3.2: +raw-body@2.3.2: version "2.3.2" resolved "https://registry.yarnpkg.com/raw-body/-/raw-body-2.3.2.tgz#bcd60c77d3eb93cde0050295c3f379389bc88f89" dependencies: @@ -7219,15 +7684,24 @@ raw-body@2, raw-body@2.3.2: iconv-lite "0.4.19" unpipe "1.0.0" +raw-body@2.3.3, raw-body@^2.2.0: + version "2.3.3" + resolved "https://registry.yarnpkg.com/raw-body/-/raw-body-2.3.3.tgz#1b324ece6b5706e153855bc1148c65bb7f6ea0c3" + dependencies: + bytes "3.0.0" + http-errors "1.6.3" + iconv-lite "0.4.23" + unpipe "1.0.0" + raw-loader@0.5.1: version "0.5.1" resolved "https://registry.yarnpkg.com/raw-loader/-/raw-loader-0.5.1.tgz#0c3d0beaed8a01c966d9787bf778281252a979aa" -rc@^1.0.1, rc@^1.1.6, rc@^1.1.7: - version "1.2.1" - resolved "https://registry.yarnpkg.com/rc/-/rc-1.2.1.tgz#2e03e8e42ee450b8cb3dce65be1bf8974e1dfd95" +rc@^1.0.1, rc@^1.1.6, rc@^1.2.7: + version "1.2.8" + resolved "https://registry.yarnpkg.com/rc/-/rc-1.2.8.tgz#cd924bf5200a075b83c188cd6b9e211b7fc0d3ed" dependencies: - deep-extend "~0.4.0" + deep-extend "^0.6.0" ini "~1.3.0" minimist "^1.2.0" strip-json-comments "~2.0.1" @@ -7251,12 +7725,12 @@ read-pkg-up@^1.0.1: find-up "^1.0.0" read-pkg "^1.0.0" -read-pkg-up@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/read-pkg-up/-/read-pkg-up-2.0.0.tgz#6b72a8048984e0c41e79510fd5e9fa99b3b549be" +read-pkg-up@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/read-pkg-up/-/read-pkg-up-3.0.0.tgz#3ed496685dba0f8fe118d0691dc51f4a1ff96f07" dependencies: find-up "^2.0.0" - read-pkg "^2.0.0" + read-pkg "^3.0.0" read-pkg@^1.0.0: version "1.1.0" @@ -7266,14 +7740,6 @@ read-pkg@^1.0.0: normalize-package-data "^2.3.2" path-type "^1.0.0" -read-pkg@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/read-pkg/-/read-pkg-2.0.0.tgz#8ef1c0623c6a6db0dc6713c4bfac46332b2368f8" - dependencies: - load-json-file "^2.0.0" - normalize-package-data "^2.3.2" - path-type "^2.0.0" - read-pkg@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/read-pkg/-/read-pkg-3.0.0.tgz#9cbc686978fee65d16c00e2b19c237fcf6e38389" @@ -7282,16 +7748,16 @@ read-pkg@^3.0.0: normalize-package-data "^2.3.2" path-type "^3.0.0" -"readable-stream@1 || 2", readable-stream@2, readable-stream@^2.0.0, readable-stream@^2.0.1, readable-stream@^2.0.2, readable-stream@^2.0.4, readable-stream@^2.0.5, readable-stream@^2.0.6, readable-stream@^2.1.4, readable-stream@^2.1.5, readable-stream@^2.2.2, readable-stream@^2.2.6, readable-stream@^2.2.9, readable-stream@^2.3.0, readable-stream@^2.3.3: - version "2.3.3" - resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.3.tgz#368f2512d79f9d46fdfc71349ae7878bbc1eb95c" +"readable-stream@1 || 2", readable-stream@2, readable-stream@^2.0.0, readable-stream@^2.0.1, readable-stream@^2.0.2, readable-stream@^2.0.4, readable-stream@^2.0.5, readable-stream@^2.0.6, readable-stream@^2.1.5, readable-stream@^2.2.2, readable-stream@^2.2.9, readable-stream@^2.3.0, readable-stream@^2.3.3, readable-stream@^2.3.5, readable-stream@^2.3.6: + version "2.3.6" + resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.6.tgz#b11c27d88b8ff1fbe070643cf94b0c79ae1b0aaf" dependencies: core-util-is "~1.0.0" inherits "~2.0.3" isarray "~1.0.0" - process-nextick-args "~1.0.6" + process-nextick-args "~2.0.0" safe-buffer "~5.1.1" - string_decoder "~1.0.3" + string_decoder "~1.1.1" util-deprecate "~1.0.1" readable-stream@1.0: @@ -7345,9 +7811,16 @@ redent@^1.0.0: indent-string "^2.1.0" strip-indent "^1.0.1" +redent@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/redent/-/redent-2.0.0.tgz#c1b2007b42d57eb1389079b3c8333639d5e1ccaa" + dependencies: + indent-string "^3.0.0" + strip-indent "^2.0.0" + redis-commands@^1.2.0: - version "1.3.1" - resolved "https://registry.yarnpkg.com/redis-commands/-/redis-commands-1.3.1.tgz#81d826f45fa9c8b2011f4cd7a0fe597d241d442b" + version "1.3.5" + resolved "https://registry.yarnpkg.com/redis-commands/-/redis-commands-1.3.5.tgz#4495889414f1e886261180b1442e7295602d83a2" redis-parser@^2.6.0: version "2.6.0" @@ -7370,8 +7843,8 @@ reduce-css-calc@^1.2.6, reduce-css-calc@^1.2.7: reduce-function-call "^1.0.1" reduce-css-calc@^2.0.0: - version "2.0.5" - resolved "https://registry.yarnpkg.com/reduce-css-calc/-/reduce-css-calc-2.0.5.tgz#33c97838c5d4c711a5c14ef85ce4fde41483f7bd" + version "2.1.4" + resolved "https://registry.yarnpkg.com/reduce-css-calc/-/reduce-css-calc-2.1.4.tgz#c20e9cda8445ad73d4ff4bea960c6f8353791708" dependencies: css-unit-converter "^1.1.1" postcss-value-parser "^3.3.0" @@ -7382,21 +7855,21 @@ reduce-function-call@^1.0.1, reduce-function-call@^1.0.2: dependencies: balanced-match "^0.4.2" -reflect-metadata@0.1.12: +reflect-metadata@0.1.12, reflect-metadata@^0.1.2: version "0.1.12" resolved "https://registry.yarnpkg.com/reflect-metadata/-/reflect-metadata-0.1.12.tgz#311bf0c6b63cd782f228a81abe146a2bfa9c56f2" -reflect-metadata@^0.1.2: - version "0.1.10" - resolved "https://registry.yarnpkg.com/reflect-metadata/-/reflect-metadata-0.1.10.tgz#b4f83704416acad89988c9b15635d47e03b9344a" - regenerate@^1.2.1: - version "1.3.3" - resolved "https://registry.yarnpkg.com/regenerate/-/regenerate-1.3.3.tgz#0c336d3980553d755c39b586ae3b20aa49c82b7f" + version "1.4.0" + resolved "https://registry.yarnpkg.com/regenerate/-/regenerate-1.4.0.tgz#4a856ec4b56e4077c557589cae85e7a4c8869a11" + +regenerator-runtime@^0.10.0: + version "0.10.5" + resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.10.5.tgz#336c3efc1220adcedda2c9fab67b5a7955a33658" regenerator-runtime@^0.11.0: - version "0.11.0" - resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.11.0.tgz#7e54fe5b5ccd5d6624ea6255c3473be090b802e1" + version "0.11.1" + resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz#be05ad7f9bf7d22e056f9726cee5017fbf19e2e9" regex-cache@^0.4.2: version "0.4.4" @@ -7404,15 +7877,16 @@ regex-cache@^0.4.2: dependencies: is-equal-shallow "^0.1.3" -regex-not@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/regex-not/-/regex-not-1.0.0.tgz#42f83e39771622df826b02af176525d6a5f157f9" +regex-not@^1.0.0, regex-not@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/regex-not/-/regex-not-1.0.2.tgz#1f4ece27e00b0b65e0247a6810e6a85d83a5752c" dependencies: - extend-shallow "^2.0.1" + extend-shallow "^3.0.2" + safe-regex "^1.1.0" -regex-parser@^2.2.1: - version "2.2.8" - resolved "https://registry.yarnpkg.com/regex-parser/-/regex-parser-2.2.8.tgz#da4c0cda5a828559094168930f455f532b6ffbac" +regex-parser@^2.2.9: + version "2.2.9" + resolved "https://registry.yarnpkg.com/regex-parser/-/regex-parser-2.2.9.tgz#a372f45a248b62976a568037c1b6e60a60599192" regexpu-core@^1.0.0: version "1.0.0" @@ -7423,8 +7897,8 @@ regexpu-core@^1.0.0: regjsparser "^0.1.4" registry-auth-token@^3.0.1: - version "3.3.1" - resolved "https://registry.yarnpkg.com/registry-auth-token/-/registry-auth-token-3.3.1.tgz#fb0d3289ee0d9ada2cbb52af5dfe66cb070d3006" + version "3.3.2" + resolved "https://registry.yarnpkg.com/registry-auth-token/-/registry-auth-token-3.3.2.tgz#851fd49038eecb586911115af845260eec983f20" dependencies: rc "^1.1.6" safe-buffer "^5.0.1" @@ -7461,14 +7935,14 @@ remap-istanbul@^0.10: through2 "2.0.1" remap-istanbul@^0.9.0: - version "0.9.5" - resolved "https://registry.yarnpkg.com/remap-istanbul/-/remap-istanbul-0.9.5.tgz#a18617b1f31eec5a7dbee77538298b775606aaa8" + version "0.9.6" + resolved "https://registry.yarnpkg.com/remap-istanbul/-/remap-istanbul-0.9.6.tgz#bbd5a688fe265192f067a0ca5b2b0d7f746c5f4b" dependencies: amdefine "^1.0.0" gulp-util "3.0.7" istanbul "0.4.5" minimatch "^3.0.3" - source-map ">=0.5.6" + source-map "^0.6.1" through2 "2.0.1" remove-trailing-separator@^1.0.1: @@ -7486,8 +7960,8 @@ renderkid@^2.0.1: utila "~0.3" repeat-element@^1.1.2: - version "1.1.2" - resolved "https://registry.yarnpkg.com/repeat-element/-/repeat-element-1.1.2.tgz#ef089a178d1483baae4d93eb98b4f9e4e11d990a" + version "1.1.3" + resolved "https://registry.yarnpkg.com/repeat-element/-/repeat-element-1.1.3.tgz#782e0d825c0c5a3bb39731f84efee6b742e6b1ce" repeat-string@^0.2.2: version "0.2.2" @@ -7507,39 +7981,12 @@ replace-ext@0.0.1: version "0.0.1" resolved "https://registry.yarnpkg.com/replace-ext/-/replace-ext-0.0.1.tgz#29bbd92078a739f0bcce2b4ee41e837953522924" -request-progress@~2.0.1: +request-progress@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/request-progress/-/request-progress-2.0.1.tgz#5d36bb57961c673aa5b788dbc8141fdf23b44e08" dependencies: throttleit "^1.0.0" -request@2, request@^2.0.0, request@^2.74.0, request@^2.78.0, request@^2.79.0: - version "2.83.0" - resolved "https://registry.yarnpkg.com/request/-/request-2.83.0.tgz#ca0b65da02ed62935887808e6f510381034e3356" - dependencies: - aws-sign2 "~0.7.0" - aws4 "^1.6.0" - caseless "~0.12.0" - combined-stream "~1.0.5" - extend "~3.0.1" - forever-agent "~0.6.1" - form-data "~2.3.1" - har-validator "~5.0.3" - hawk "~6.0.2" - http-signature "~1.2.0" - is-typedarray "~1.0.0" - isstream "~0.1.2" - json-stringify-safe "~5.0.1" - mime-types "~2.1.17" - oauth-sign "~0.8.2" - performance-now "^2.1.0" - qs "~6.5.1" - safe-buffer "^5.1.1" - stringstream "~0.0.5" - tough-cookie "~2.3.3" - tunnel-agent "^0.6.0" - uuid "^3.1.0" - request@2.75.x: version "2.75.0" resolved "https://registry.yarnpkg.com/request/-/request-2.75.0.tgz#d2b8268a286da13eaa5d01adf5d18cc90f657d93" @@ -7566,57 +8013,82 @@ request@2.75.x: tough-cookie "~2.3.0" tunnel-agent "~0.4.1" -request@2.79.0, request@~2.79.0: - version "2.79.0" - resolved "https://registry.yarnpkg.com/request/-/request-2.79.0.tgz#4dfe5bf6be8b8cdc37fcf93e04b65577722710de" +request@2.85.0: + version "2.85.0" + resolved "https://registry.yarnpkg.com/request/-/request-2.85.0.tgz#5a03615a47c61420b3eb99b7dba204f83603e1fa" dependencies: - aws-sign2 "~0.6.0" - aws4 "^1.2.1" - caseless "~0.11.0" - combined-stream "~1.0.5" - extend "~3.0.0" - forever-agent "~0.6.1" - form-data "~2.1.1" - har-validator "~2.0.6" - hawk "~3.1.3" - http-signature "~1.1.0" - is-typedarray "~1.0.0" - isstream "~0.1.2" - json-stringify-safe "~5.0.1" - mime-types "~2.1.7" - oauth-sign "~0.8.1" - qs "~6.3.0" - stringstream "~0.0.4" - tough-cookie "~2.3.0" - tunnel-agent "~0.4.1" - uuid "^3.0.0" - -request@2.81.0, request@~2.81.0: - version "2.81.0" - resolved "https://registry.yarnpkg.com/request/-/request-2.81.0.tgz#c6928946a0e06c5f8d6f8a9333469ffda46298a0" - dependencies: - aws-sign2 "~0.6.0" - aws4 "^1.2.1" + aws-sign2 "~0.7.0" + aws4 "^1.6.0" caseless "~0.12.0" combined-stream "~1.0.5" - extend "~3.0.0" + extend "~3.0.1" forever-agent "~0.6.1" - form-data "~2.1.1" - har-validator "~4.2.1" - hawk "~3.1.3" - http-signature "~1.1.0" + form-data "~2.3.1" + har-validator "~5.0.3" + hawk "~6.0.2" + http-signature "~1.2.0" is-typedarray "~1.0.0" isstream "~0.1.2" json-stringify-safe "~5.0.1" - mime-types "~2.1.7" - oauth-sign "~0.8.1" - performance-now "^0.2.0" - qs "~6.4.0" - safe-buffer "^5.0.1" - stringstream "~0.0.4" - tough-cookie "~2.3.0" + mime-types "~2.1.17" + oauth-sign "~0.8.2" + performance-now "^2.1.0" + qs "~6.5.1" + safe-buffer "^5.1.1" + stringstream "~0.0.5" + tough-cookie "~2.3.3" tunnel-agent "^0.6.0" - uuid "^3.0.0" + uuid "^3.1.0" + +request@2.87.0: + version "2.87.0" + resolved "https://registry.yarnpkg.com/request/-/request-2.87.0.tgz#32f00235cd08d482b4d0d68db93a829c0ed5756e" + dependencies: + aws-sign2 "~0.7.0" + aws4 "^1.6.0" + caseless "~0.12.0" + combined-stream "~1.0.5" + extend "~3.0.1" + forever-agent "~0.6.1" + form-data "~2.3.1" + har-validator "~5.0.3" + http-signature "~1.2.0" + is-typedarray "~1.0.0" + isstream "~0.1.2" + json-stringify-safe "~5.0.1" + mime-types "~2.1.17" + oauth-sign "~0.8.2" + performance-now "^2.1.0" + qs "~6.5.1" + safe-buffer "^5.1.1" + tough-cookie "~2.3.3" + tunnel-agent "^0.6.0" + uuid "^3.1.0" + +request@^2.0.0, request@^2.74.0, request@^2.79.0, request@^2.81.0, request@^2.87.0: + version "2.88.0" + resolved "https://registry.yarnpkg.com/request/-/request-2.88.0.tgz#9c2fca4f7d35b592efe57c7f0a55e81052124fef" + dependencies: + aws-sign2 "~0.7.0" + aws4 "^1.8.0" + caseless "~0.12.0" + combined-stream "~1.0.6" + extend "~3.0.2" + forever-agent "~0.6.1" + form-data "~2.3.2" + har-validator "~5.1.0" + http-signature "~1.2.0" + is-typedarray "~1.0.0" + isstream "~0.1.2" + json-stringify-safe "~5.0.1" + mime-types "~2.1.19" + oauth-sign "~0.9.0" + performance-now "^2.1.0" + qs "~6.5.2" + safe-buffer "^5.1.2" + tough-cookie "~2.4.3" + tunnel-agent "^0.6.0" + uuid "^3.3.2" requestretry@^1.2.2: version "1.13.0" @@ -7635,11 +8107,15 @@ require-from-string@^1.1.0: version "1.2.1" resolved "https://registry.yarnpkg.com/require-from-string/-/require-from-string-1.2.1.tgz#529c9ccef27380adfec9a2f965b649bbee636418" +require-from-string@^2.0.1: + version "2.0.2" + resolved "https://registry.yarnpkg.com/require-from-string/-/require-from-string-2.0.2.tgz#89a7fdd938261267318eafe14f9c32e598c36909" + require-main-filename@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/require-main-filename/-/require-main-filename-1.0.1.tgz#97f717b69d48784f5f526a6c5aa8ffdda055a4d1" -requires-port@1.0.x, requires-port@1.x.x: +requires-port@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/requires-port/-/requires-port-1.0.0.tgz#925d2601d39ac485e091cf0da5c6e694dc3dcaff" @@ -7667,7 +8143,7 @@ resolve-url-loader@2.2.1: source-map "^0.5.6" urix "^0.1.0" -resolve-url@^0.2.1, resolve-url@~0.2.1: +resolve-url@^0.2.1: version "0.2.1" resolved "https://registry.yarnpkg.com/resolve-url/-/resolve-url-0.2.1.tgz#2c637fe77c893afd2a663fe21aa9080068e2052a" @@ -7675,17 +8151,22 @@ resolve@1.1.7, resolve@1.1.x: version "1.1.7" resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.1.7.tgz#203114d82ad2c5ed9e8e0411b3932875e889e97b" -resolve@^1.1.3, resolve@^1.1.4, resolve@^1.5.0: - version "1.5.0" - resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.5.0.tgz#1f09acce796c9a762579f31b2c1cc4c3cddf9f36" +resolve@^1.1.3, resolve@^1.1.4, resolve@^1.1.6, resolve@^1.3.2, resolve@^1.4.0, resolve@^1.5.0, resolve@^1.6.0: + version "1.8.1" + resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.8.1.tgz#82f1ec19a423ac1fbd080b0bab06ba36e84a7a26" dependencies: path-parse "^1.0.5" -resolve@^1.1.6, resolve@^1.3.2, resolve@^1.4.0: - version "1.4.0" - resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.4.0.tgz#a75be01c53da25d934a98ebd0e4c4a7312f92a86" +restore-cursor@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/restore-cursor/-/restore-cursor-2.0.0.tgz#9f7ee287f82fd326d4fd162923d62129eee0dfaf" dependencies: - path-parse "^1.0.5" + onetime "^2.0.0" + signal-exit "^3.0.2" + +ret@~0.1.10: + version "0.1.15" + resolved "https://registry.yarnpkg.com/ret/-/ret-0.1.15.tgz#b8a4825d5bdb1fc3f6f53c2bc33f81388681c7bc" rework-visit@^1.0.0: version "1.0.0" @@ -7712,22 +8193,22 @@ right-align@^0.1.1: dependencies: align-text "^0.1.1" -rimraf@2, rimraf@2.6.2, rimraf@^2.2.8, rimraf@^2.5.1, rimraf@^2.5.2, rimraf@^2.5.4, rimraf@^2.6.0, rimraf@^2.6.1: +rimraf@2, rimraf@2.6.2, rimraf@^2.2.8, rimraf@^2.5.2, rimraf@^2.5.4, rimraf@^2.6.0, rimraf@^2.6.1, rimraf@^2.6.2: version "2.6.2" resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.6.2.tgz#2ed8150d24a16ea8651e6d6ef0f47c4158ce7a36" dependencies: glob "^7.0.5" ripemd160@^2.0.0, ripemd160@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/ripemd160/-/ripemd160-2.0.1.tgz#0f4584295c53a3628af7e6d79aca21ce57d1c6e7" + version "2.0.2" + resolved "https://registry.yarnpkg.com/ripemd160/-/ripemd160-2.0.2.tgz#a1c1a6f624751577ba5d07914cbc92850585890c" dependencies: - hash-base "^2.0.0" + hash-base "^3.0.0" inherits "^2.0.1" rollup-plugin-commonjs@^8.3.0: - version "8.3.0" - resolved "https://registry.yarnpkg.com/rollup-plugin-commonjs/-/rollup-plugin-commonjs-8.3.0.tgz#91b4ba18f340951e39ed7b1901f377a80ab3f9c3" + version "8.4.1" + resolved "https://registry.yarnpkg.com/rollup-plugin-commonjs/-/rollup-plugin-commonjs-8.4.1.tgz#5c9cea2b2c3de322f5fbccd147e07ed5e502d7a0" dependencies: acorn "^5.2.1" estree-walker "^0.5.0" @@ -7747,10 +8228,10 @@ rollup-plugin-node-globals@1.1.0: rollup-pluginutils "^1.5.2" rollup-plugin-node-resolve@^3.0.3: - version "3.0.3" - resolved "https://registry.yarnpkg.com/rollup-plugin-node-resolve/-/rollup-plugin-node-resolve-3.0.3.tgz#8f57b253edd00e5b0ad0aed7b7e9cf5982e98fa4" + version "3.3.0" + resolved "https://registry.yarnpkg.com/rollup-plugin-node-resolve/-/rollup-plugin-node-resolve-3.3.0.tgz#c26d110a36812cbefa7ce117cadcd3439aa1c713" dependencies: - builtin-modules "^1.1.0" + builtin-modules "^2.0.0" is-module "^1.0.0" resolve "^1.1.6" @@ -7768,15 +8249,21 @@ rollup-pluginutils@^1.5.2: minimatch "^3.0.2" rollup-pluginutils@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/rollup-pluginutils/-/rollup-pluginutils-2.0.1.tgz#7ec95b3573f6543a46a6461bd9a7c544525d0fc0" + version "2.3.1" + resolved "https://registry.yarnpkg.com/rollup-pluginutils/-/rollup-pluginutils-2.3.1.tgz#760d185ccc237dedc12d7ae48c6bcd127b4892d0" dependencies: - estree-walker "^0.3.0" + estree-walker "^0.5.2" micromatch "^2.3.11" rollup@^0.56.0: - version "0.56.0" - resolved "https://registry.yarnpkg.com/rollup/-/rollup-0.56.0.tgz#4aefe9cef84a01ac3245e3fbba155e38dc2cc2e8" + version "0.56.5" + resolved "https://registry.yarnpkg.com/rollup/-/rollup-0.56.5.tgz#40fe3cf0cd1659d469baad11f4d5b6336c14ce84" + +run-async@^2.2.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/run-async/-/run-async-2.3.0.tgz#0371ab4ae0bdd720d4166d7dfda64ff7a445a6c0" + dependencies: + is-promise "^2.1.0" run-queue@^1.0.0, run-queue@^1.0.3: version "1.0.3" @@ -7784,16 +8271,34 @@ run-queue@^1.0.0, run-queue@^1.0.3: dependencies: aproba "^1.1.1" -rxjs@5.5.6: - version "5.5.6" - resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-5.5.6.tgz#e31fb96d6fd2ff1fd84bcea8ae9c02d007179c02" - dependencies: - symbol-observable "1.0.1" +rx@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/rx/-/rx-4.1.0.tgz#a5f13ff79ef3b740fe30aa803fb09f98805d4782" -safe-buffer@5.1.1, safe-buffer@^5.0.1, safe-buffer@^5.1.0, safe-buffer@^5.1.1, safe-buffer@~5.1.0, safe-buffer@~5.1.1: +rxjs@^6.0.0, rxjs@^6.2.2: + version "6.2.2" + resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-6.2.2.tgz#eb75fa3c186ff5289907d06483a77884586e1cf9" + dependencies: + tslib "^1.9.0" + +safe-buffer@5.1.1: version "5.1.1" resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.1.tgz#893312af69b2123def71f57889001671eeb2c853" +safe-buffer@5.1.2, safe-buffer@^5.0.1, safe-buffer@^5.1.0, safe-buffer@^5.1.1, safe-buffer@^5.1.2, safe-buffer@~5.1.0, safe-buffer@~5.1.1: + version "5.1.2" + resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d" + +safe-regex@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/safe-regex/-/safe-regex-1.1.0.tgz#40a3669f3b077d1e943d44629e157dd48023bf2e" + dependencies: + ret "~0.1.10" + +"safer-buffer@>= 2.1.2 < 3", safer-buffer@^2.0.2, safer-buffer@^2.1.0, safer-buffer@~2.1.0: + version "2.1.2" + resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a" + sass-graph@^2.2.4: version "2.2.4" resolved "https://registry.yarnpkg.com/sass-graph/-/sass-graph-2.2.4.tgz#13fbd63cd1caf0908b9fd93476ad43a51d1e0b49" @@ -7813,17 +8318,13 @@ sass-loader@6.0.6: lodash.tail "^4.1.1" pify "^3.0.0" -saucelabs@~1.3.0: - version "1.3.0" - resolved "https://registry.yarnpkg.com/saucelabs/-/saucelabs-1.3.0.tgz#d240e8009df7fa87306ec4578a69ba3b5c424fee" +saucelabs@^1.5.0: + version "1.5.0" + resolved "https://registry.yarnpkg.com/saucelabs/-/saucelabs-1.5.0.tgz#9405a73c360d449b232839919a86c396d379fd9d" dependencies: - https-proxy-agent "^1.0.0" + https-proxy-agent "^2.2.1" -sax@0.6.x: - version "0.6.1" - resolved "https://registry.yarnpkg.com/sax/-/sax-0.6.1.tgz#563b19c7c1de892e09bfc4f2fc30e3c27f0952b9" - -sax@>=0.6.0, sax@~1.2.1: +sax@>=0.6.0, sax@^1.2.4, sax@~1.2.1: version "1.2.4" resolved "https://registry.yarnpkg.com/sax/-/sax-1.2.4.tgz#2816234e2378bddc4e5354fab5caa895df7100d9" @@ -7833,16 +8334,16 @@ schema-utils@^0.3.0: dependencies: ajv "^5.0.0" -schema-utils@^0.4.0: - version "0.4.5" - resolved "https://registry.yarnpkg.com/schema-utils/-/schema-utils-0.4.5.tgz#21836f0608aac17b78f9e3e24daff14a5ca13a3e" +schema-utils@^0.4.0, schema-utils@^0.4.4, schema-utils@^0.4.5: + version "0.4.7" + resolved "https://registry.yarnpkg.com/schema-utils/-/schema-utils-0.4.7.tgz#ba74f597d2be2ea880131746ee17d0a093c68187" dependencies: ajv "^6.1.0" ajv-keywords "^3.1.0" -script-ext-html-webpack-plugin@1.8.8: - version "1.8.8" - resolved "https://registry.yarnpkg.com/script-ext-html-webpack-plugin/-/script-ext-html-webpack-plugin-1.8.8.tgz#faa888a286ce746fcd06a5e0a9e39ed7b9d24f66" +script-ext-html-webpack-plugin@2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/script-ext-html-webpack-plugin/-/script-ext-html-webpack-plugin-2.0.1.tgz#90ac3d77f1892ad9054c3752f0e4673607f6d9a3" dependencies: debug "^3.1.0" @@ -7857,7 +8358,7 @@ select-hose@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/select-hose/-/select-hose-2.0.0.tgz#625d8658f865af43ec962bfc376a37359a4994ca" -selenium-webdriver@3.6.0: +selenium-webdriver@3.6.0, selenium-webdriver@^3.0.1: version "3.6.0" resolved "https://registry.yarnpkg.com/selenium-webdriver/-/selenium-webdriver-3.6.0.tgz#2ba87a1662c020b8988c981ae62cb2a01298eafc" dependencies: @@ -7866,21 +8367,11 @@ selenium-webdriver@3.6.0: tmp "0.0.30" xml2js "^0.4.17" -selenium-webdriver@^2.53.2: - version "2.53.3" - resolved "https://registry.yarnpkg.com/selenium-webdriver/-/selenium-webdriver-2.53.3.tgz#d29ff5a957dff1a1b49dc457756e4e4bfbdce085" - dependencies: - adm-zip "0.4.4" - rimraf "^2.2.8" - tmp "0.0.24" - ws "^1.0.1" - xml2js "0.4.4" - selfsigned@^1.9.1: - version "1.10.1" - resolved "https://registry.yarnpkg.com/selfsigned/-/selfsigned-1.10.1.tgz#bf8cb7b83256c4551e31347c6311778db99eec52" + version "1.10.3" + resolved "https://registry.yarnpkg.com/selfsigned/-/selfsigned-1.10.3.tgz#d628ecf9e3735f84e8bafba936b3cf85bea43823" dependencies: - node-forge "0.6.33" + node-forge "0.7.5" semver-diff@^2.0.0: version "2.1.0" @@ -7894,17 +8385,9 @@ semver-dsl@^1.0.1: dependencies: semver "^5.3.0" -"semver@2 || 3 || 4 || 5", semver@^5.0.3, semver@^5.1.0, semver@^5.3.0: - version "5.4.1" - resolved "https://registry.yarnpkg.com/semver/-/semver-5.4.1.tgz#e059c09d8571f0540823733433505d3a2f00b18e" - -semver@^5.4.1: - version "5.5.0" - resolved "https://registry.yarnpkg.com/semver/-/semver-5.5.0.tgz#dc4bbc7a6ca9d916dee5d43516f0092b58f7b8ab" - -semver@~5.0.1: - version "5.0.3" - resolved "https://registry.yarnpkg.com/semver/-/semver-5.0.3.tgz#77466de589cd5d3c95f138aa78bc569a3cb5d27a" +"semver@2 || 3 || 4 || 5", semver@^5.0.3, semver@^5.1.0, semver@^5.3.0, semver@^5.5.0: + version "5.5.1" + resolved "https://registry.yarnpkg.com/semver/-/semver-5.5.1.tgz#7dfdd8814bdb7cabc7be0fb1d734cfb66c940477" semver@~5.3.0: version "5.3.0" @@ -7928,9 +8411,27 @@ send@0.16.1: range-parser "~1.2.0" statuses "~1.3.1" +send@0.16.2: + version "0.16.2" + resolved "https://registry.yarnpkg.com/send/-/send-0.16.2.tgz#6ecca1e0f8c156d141597559848df64730a6bbc1" + dependencies: + debug "2.6.9" + depd "~1.1.2" + destroy "~1.0.4" + encodeurl "~1.0.2" + escape-html "~1.0.3" + etag "~1.8.1" + fresh "0.5.2" + http-errors "~1.6.2" + mime "1.4.1" + ms "2.0.0" + on-finished "~2.3.0" + range-parser "~1.2.0" + statuses "~1.4.0" + serialize-javascript@^1.4.0: - version "1.4.0" - resolved "https://registry.yarnpkg.com/serialize-javascript/-/serialize-javascript-1.4.0.tgz#7c958514db6ac2443a8abc062dc9f7886a7f6005" + version "1.5.0" + resolved "https://registry.yarnpkg.com/serialize-javascript/-/serialize-javascript-1.5.0.tgz#1aa336162c88a890ddad5384baebc93a655161fe" serve-index@^1.7.2: version "1.9.1" @@ -7953,16 +8454,19 @@ serve-static@1.13.1: parseurl "~1.3.2" send "0.16.1" +serve-static@1.13.2: + version "1.13.2" + resolved "https://registry.yarnpkg.com/serve-static/-/serve-static-1.13.2.tgz#095e8472fd5b46237db50ce486a43f4b86c6cec1" + dependencies: + encodeurl "~1.0.2" + escape-html "~1.0.3" + parseurl "~1.3.2" + send "0.16.2" + set-blocking@^2.0.0, set-blocking@~2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/set-blocking/-/set-blocking-2.0.0.tgz#045f9782d011ae9a6803ddd382b24392b3d890f7" -set-getter@^0.1.0: - version "0.1.0" - resolved "https://registry.yarnpkg.com/set-getter/-/set-getter-0.1.0.tgz#d769c182c9d5a51f409145f2fba82e5e86e80376" - dependencies: - to-object-path "^0.3.0" - set-immediate-shim@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/set-immediate-shim/-/set-immediate-shim-1.0.1.tgz#4b2b1b27eb808a9f8dcc481a58e5e56f599f3f61" @@ -7997,16 +8501,9 @@ setprototypeof@1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/setprototypeof/-/setprototypeof-1.1.0.tgz#d0bd85536887b6fe7c0d818cb962d9d91c54e656" -sha.js@^2.4.0, sha.js@^2.4.8: - version "2.4.9" - resolved "https://registry.yarnpkg.com/sha.js/-/sha.js-2.4.9.tgz#98f64880474b74f4a38b8da9d3c0f2d104633e7d" - dependencies: - inherits "^2.0.1" - safe-buffer "^5.0.1" - -sha.js@~2.4.4: - version "2.4.10" - resolved "https://registry.yarnpkg.com/sha.js/-/sha.js-2.4.10.tgz#b1fde5cd7d11a5626638a07c604ab909cfa31f9b" +sha.js@^2.4.0, sha.js@^2.4.8, sha.js@~2.4.4: + version "2.4.11" + resolved "https://registry.yarnpkg.com/sha.js/-/sha.js-2.4.11.tgz#37a5cf0b81ecbc6943de109ba2960d1b26584ae7" dependencies: inherits "^2.0.1" safe-buffer "^5.0.1" @@ -8058,6 +8555,10 @@ signal-exit@^3.0.0, signal-exit@^3.0.2: version "3.0.2" resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.2.tgz#b5fdc08f1287ea1178628e415e25132b73646c6d" +simple-concat@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/simple-concat/-/simple-concat-1.0.0.tgz#7344cbb8b6e26fb27d66b2fc86f9f6d5997521c6" + simple-swizzle@^0.2.2: version "0.2.2" resolved "https://registry.yarnpkg.com/simple-swizzle/-/simple-swizzle-0.2.2.tgz#a4da6b635ffcccca33f70d17cb92592de95e557a" @@ -8078,6 +8579,10 @@ smart-buffer@^1.0.13, smart-buffer@^1.0.4: version "1.1.15" resolved "https://registry.yarnpkg.com/smart-buffer/-/smart-buffer-1.1.15.tgz#7f114b5b65fab3e2a35aa775bb12f0d1c649bf16" +smart-buffer@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/smart-buffer/-/smart-buffer-4.0.1.tgz#07ea1ca8d4db24eb4cac86537d7d18995221ace3" + smtp-connection@2.12.0: version "2.12.0" resolved "https://registry.yarnpkg.com/smtp-connection/-/smtp-connection-2.12.0.tgz#d76ef9127cb23c2259edb1e8349c2e8d5e2d74c1" @@ -8100,8 +8605,8 @@ snapdragon-util@^3.0.1: kind-of "^3.2.0" snapdragon@^0.8.1: - version "0.8.1" - resolved "https://registry.yarnpkg.com/snapdragon/-/snapdragon-0.8.1.tgz#e12b5487faded3e3dea0ac91e9400bf75b401370" + version "0.8.2" + resolved "https://registry.yarnpkg.com/snapdragon/-/snapdragon-0.8.2.tgz#64922e7c565b0e14204ba1aa7d6964278d25182d" dependencies: base "^0.11.1" debug "^2.2.0" @@ -8110,7 +8615,7 @@ snapdragon@^0.8.1: map-cache "^0.2.2" source-map "^0.5.6" source-map-resolve "^0.5.0" - use "^2.0.0" + use "^3.1.0" sntp@1.x.x: version "1.0.9" @@ -8119,8 +8624,8 @@ sntp@1.x.x: hoek "2.x.x" sntp@2.x.x: - version "2.0.2" - resolved "https://registry.yarnpkg.com/sntp/-/sntp-2.0.2.tgz#5064110f0af85f7cfdb7d6b67a40028ce52b4b2b" + version "2.1.0" + resolved "https://registry.yarnpkg.com/sntp/-/sntp-2.1.0.tgz#2c6cec14fedc2222739caf9b5c3d85d1cc5a2cc8" dependencies: hoek "4.x.x" @@ -8147,11 +8652,11 @@ socket.io-client@2.0.4: to-array "0.1.4" socket.io-parser@~3.1.1: - version "3.1.2" - resolved "https://registry.yarnpkg.com/socket.io-parser/-/socket.io-parser-3.1.2.tgz#dbc2282151fc4faebbe40aeedc0772eba619f7f2" + version "3.1.3" + resolved "https://registry.yarnpkg.com/socket.io-parser/-/socket.io-parser-3.1.3.tgz#ed2da5ee79f10955036e3da413bfd7f1e4d86c8e" dependencies: component-emitter "1.2.1" - debug "~2.6.4" + debug "~3.1.0" has-binary2 "~1.0.2" isarray "2.0.1" @@ -8165,9 +8670,9 @@ socket.io@2.0.4: socket.io-client "2.0.4" socket.io-parser "~3.1.1" -sockjs-client@1.1.4: - version "1.1.4" - resolved "https://registry.yarnpkg.com/sockjs-client/-/sockjs-client-1.1.4.tgz#5babe386b775e4cf14e7520911452654016c8b12" +sockjs-client@1.1.5: + version "1.1.5" + resolved "https://registry.yarnpkg.com/sockjs-client/-/sockjs-client-1.1.5.tgz#1bb7c0f7222c40f42adf14f4442cbd1269771a83" dependencies: debug "^2.6.6" eventsource "0.1.6" @@ -8183,13 +8688,19 @@ sockjs@0.3.19: faye-websocket "^0.10.0" uuid "^3.0.1" -socks-proxy-agent@2: - version "2.1.1" - resolved "https://registry.yarnpkg.com/socks-proxy-agent/-/socks-proxy-agent-2.1.1.tgz#86ebb07193258637870e13b7bd99f26c663df3d3" +socks-proxy-agent@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/socks-proxy-agent/-/socks-proxy-agent-3.0.1.tgz#2eae7cf8e2a82d34565761539a7f9718c5617659" dependencies: - agent-base "2" - extend "3" - socks "~1.1.5" + agent-base "^4.1.0" + socks "^1.1.10" + +socks-proxy-agent@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/socks-proxy-agent/-/socks-proxy-agent-4.0.1.tgz#5936bf8b707a993079c6f37db2091821bffa6473" + dependencies: + agent-base "~4.2.0" + socks "~2.2.0" socks@1.1.9: version "1.1.9" @@ -8198,13 +8709,20 @@ socks@1.1.9: ip "^1.1.2" smart-buffer "^1.0.4" -socks@~1.1.5: +socks@^1.1.10: version "1.1.10" resolved "https://registry.yarnpkg.com/socks/-/socks-1.1.10.tgz#5b8b7fc7c8f341c53ed056e929b7bf4de8ba7b5a" dependencies: ip "^1.1.4" smart-buffer "^1.0.13" +socks@~2.2.0: + version "2.2.1" + resolved "https://registry.yarnpkg.com/socks/-/socks-2.2.1.tgz#68ad678b3642fbc5d99c64c165bc561eab0215f9" + dependencies: + ip "^1.1.5" + smart-buffer "^4.0.1" + sort-keys@^1.0.0: version "1.1.2" resolved "https://registry.yarnpkg.com/sort-keys/-/sort-keys-1.1.2.tgz#441b6d4d346798f1b4e49e8920adfba0e543f9ad" @@ -8227,53 +8745,38 @@ source-map-loader@0.2.3: loader-utils "~0.2.2" source-map "~0.6.1" -source-map-resolve@^0.3.0: - version "0.3.1" - resolved "https://registry.yarnpkg.com/source-map-resolve/-/source-map-resolve-0.3.1.tgz#610f6122a445b8dd51535a2a71b783dfc1248761" +source-map-resolve@^0.5.0, source-map-resolve@^0.5.1: + version "0.5.2" + resolved "https://registry.yarnpkg.com/source-map-resolve/-/source-map-resolve-0.5.2.tgz#72e2cc34095543e43b2c62b2c4c10d4a9054f259" dependencies: - atob "~1.1.0" - resolve-url "~0.2.1" - source-map-url "~0.3.0" - urix "~0.1.0" - -source-map-resolve@^0.5.0: - version "0.5.0" - resolved "https://registry.yarnpkg.com/source-map-resolve/-/source-map-resolve-0.5.0.tgz#fcad0b64b70afb27699e425950cb5ebcd410bc20" - dependencies: - atob "^2.0.0" + atob "^2.1.1" + decode-uri-component "^0.2.0" resolve-url "^0.2.1" source-map-url "^0.4.0" urix "^0.1.0" -source-map-support@^0.4.15, source-map-support@^0.4.2, source-map-support@~0.4.0: +source-map-support@^0.4.15, source-map-support@~0.4.0: version "0.4.18" resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.4.18.tgz#0286a6de8be42641338594e97ccea75f0a2c585f" dependencies: source-map "^0.5.6" source-map-support@^0.5.0: - version "0.5.2" - resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.2.tgz#1a6297fd5b2e762b39688c7fc91233b60984f0a5" + version "0.5.9" + resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.9.tgz#41bc953b2534267ea2d605bccfa7bfa3111ced5f" dependencies: + buffer-from "^1.0.0" source-map "^0.6.0" source-map-url@^0.4.0: version "0.4.0" resolved "https://registry.yarnpkg.com/source-map-url/-/source-map-url-0.4.0.tgz#3e935d7ddd73631b97659956d55128e87b5084a3" -source-map-url@~0.3.0: - version "0.3.0" - resolved "https://registry.yarnpkg.com/source-map-url/-/source-map-url-0.3.0.tgz#7ecaf13b57bcd09da8a40c5d269db33799d4aaf9" - source-map@0.5.0: version "0.5.0" resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.5.0.tgz#0fe96503ac86a5adb5de63f4e412ae4872cdbe86" -source-map@0.5.x, source-map@^0.5.1, source-map@^0.5.3, source-map@^0.5.6, source-map@~0.5.1, source-map@~0.5.3, source-map@~0.5.6: - version "0.5.7" - resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.5.7.tgz#8a039d2d1021d22d1ea14c80d8ea468ba2ef3fcc" - -source-map@0.6.1, source-map@>=0.5.6, source-map@^0.6.0, source-map@^0.6.1, source-map@~0.6.1: +source-map@0.6.1, source-map@^0.6.0, source-map@^0.6.1, source-map@~0.6.0, source-map@~0.6.1: version "0.6.1" resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263" @@ -8289,6 +8792,10 @@ source-map@^0.4.2, source-map@^0.4.4: dependencies: amdefine ">=0.0.4" +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, source-map@~0.5.3: + version "0.5.7" + resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.5.7.tgz#8a039d2d1021d22d1ea14c80d8ea468ba2ef3fcc" + source-map@~0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.2.0.tgz#dab73fbcfc2ba819b4de03bd6f6eaa48164b3f9d" @@ -8296,26 +8803,34 @@ source-map@~0.2.0: amdefine ">=0.0.4" sparkles@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/sparkles/-/sparkles-1.0.0.tgz#1acbbfb592436d10bbe8f785b7cc6f82815012c3" + version "1.0.1" + resolved "https://registry.yarnpkg.com/sparkles/-/sparkles-1.0.1.tgz#008db65edce6c50eec0c5e228e1945061dd0437c" -spdx-correct@~1.0.0: - version "1.0.2" - resolved "https://registry.yarnpkg.com/spdx-correct/-/spdx-correct-1.0.2.tgz#4b3073d933ff51f3912f03ac5519498a4150db40" +spdx-correct@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/spdx-correct/-/spdx-correct-3.0.0.tgz#05a5b4d7153a195bc92c3c425b69f3b2a9524c82" dependencies: - spdx-license-ids "^1.0.2" + spdx-expression-parse "^3.0.0" + spdx-license-ids "^3.0.0" -spdx-expression-parse@~1.0.0: - version "1.0.4" - resolved "https://registry.yarnpkg.com/spdx-expression-parse/-/spdx-expression-parse-1.0.4.tgz#9bdf2f20e1f40ed447fbe273266191fced51626c" +spdx-exceptions@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/spdx-exceptions/-/spdx-exceptions-2.1.0.tgz#2c7ae61056c714a5b9b9b2b2af7d311ef5c78fe9" -spdx-license-ids@^1.0.2: - version "1.2.2" - resolved "https://registry.yarnpkg.com/spdx-license-ids/-/spdx-license-ids-1.2.2.tgz#c9df7a3424594ade6bd11900d596696dc06bac57" +spdx-expression-parse@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/spdx-expression-parse/-/spdx-expression-parse-3.0.0.tgz#99e119b7a5da00e05491c9fa338b7904823b41d0" + dependencies: + spdx-exceptions "^2.1.0" + spdx-license-ids "^3.0.0" + +spdx-license-ids@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/spdx-license-ids/-/spdx-license-ids-3.0.0.tgz#7a7cd28470cc6d3a1cfe6d66886f6bc430d3ac87" spdy-transport@^2.0.18: - version "2.0.20" - resolved "https://registry.yarnpkg.com/spdy-transport/-/spdy-transport-2.0.20.tgz#735e72054c486b2354fe89e702256004a39ace4d" + version "2.1.0" + resolved "https://registry.yarnpkg.com/spdy-transport/-/spdy-transport-2.1.0.tgz#4bbb15aaffed0beefdd56ad61dbdc8ba3e2cb7a1" dependencies: debug "^2.6.8" detect-node "^2.0.3" @@ -8336,19 +8851,7 @@ spdy@^3.4.1: select-hose "^2.0.0" spdy-transport "^2.0.18" -split-string@^2.1.0: - version "2.1.1" - resolved "https://registry.yarnpkg.com/split-string/-/split-string-2.1.1.tgz#af4b06d821560426446c3cd931cda618940d37d0" - dependencies: - extend-shallow "^2.0.1" - -split-string@^3.0.1: - version "3.0.2" - resolved "https://registry.yarnpkg.com/split-string/-/split-string-3.0.2.tgz#6129bc92731716e5aa1fb73c333078f0b7c114c8" - dependencies: - extend-shallow "^2.0.1" - -split-string@^3.0.2: +split-string@^3.0.1, split-string@^3.0.2: version "3.1.0" resolved "https://registry.yarnpkg.com/split-string/-/split-string-3.1.0.tgz#7cb09dda3a86585705c64b39a6466038682e8fe2" dependencies: @@ -8360,29 +8863,34 @@ split@0.3: dependencies: through "2" -sprintf-js@^1.0.3, sprintf-js@~1.0.2: +sprintf-js@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.1.1.tgz#36be78320afe5801f6cea3ee78b6e5aab940ea0c" + +sprintf-js@~1.0.2: version "1.0.3" resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.0.3.tgz#04e6926f662895354f3dd015203633b857297e2c" sshpk@^1.7.0: - version "1.13.1" - resolved "https://registry.yarnpkg.com/sshpk/-/sshpk-1.13.1.tgz#512df6da6287144316dc4c18fe1cf1d940739be3" + version "1.14.2" + resolved "https://registry.yarnpkg.com/sshpk/-/sshpk-1.14.2.tgz#c6fc61648a3d9c4e764fd3fcdf4ea105e492ba98" dependencies: asn1 "~0.2.3" assert-plus "^1.0.0" dashdash "^1.12.0" getpass "^0.1.1" + safer-buffer "^2.0.2" optionalDependencies: bcrypt-pbkdf "^1.0.0" ecc-jsbn "~0.1.1" jsbn "~0.1.0" tweetnacl "~0.14.0" -ssri@^5.0.0: - version "5.1.0" - resolved "https://registry.yarnpkg.com/ssri/-/ssri-5.1.0.tgz#2cbf1df36b74d0fc91fcf89640a4b3e1d10b1899" +ssri@^5.2.4: + version "5.3.0" + resolved "https://registry.yarnpkg.com/ssri/-/ssri-5.3.0.tgz#ba3872c9c6d33a0704a7d71ff045e5ec48999d06" dependencies: - safe-buffer "^5.1.0" + safe-buffer "^5.1.1" static-extend@^0.1.1: version "0.1.2" @@ -8391,10 +8899,18 @@ static-extend@^0.1.1: define-property "^0.2.5" object-copy "^0.1.0" -"statuses@>= 1.3.1 < 2", statuses@~1.3.1: +"statuses@>= 1.3.1 < 2", "statuses@>= 1.4.0 < 2": + version "1.5.0" + resolved "https://registry.yarnpkg.com/statuses/-/statuses-1.5.0.tgz#161c7dac177659fd9811f43771fa99381478628c" + +statuses@~1.3.1: version "1.3.1" resolved "https://registry.yarnpkg.com/statuses/-/statuses-1.3.1.tgz#faf51b9eb74aaef3b3acf4ad5f61abf24cb7b93e" +statuses@~1.4.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/statuses/-/statuses-1.4.0.tgz#bb73d446da2796106efcc1b601a253d6c46bd087" + stdout-stream@^1.4.0: version "1.4.0" resolved "https://registry.yarnpkg.com/stdout-stream/-/stdout-stream-1.4.0.tgz#a2c7c8587e54d9427ea9edb3ac3f2cd522df378b" @@ -8422,29 +8938,19 @@ stream-combiner@~0.0.4: duplexer "~0.1.1" stream-each@^1.1.0: - version "1.2.2" - resolved "https://registry.yarnpkg.com/stream-each/-/stream-each-1.2.2.tgz#8e8c463f91da8991778765873fe4d960d8f616bd" + version "1.2.3" + resolved "https://registry.yarnpkg.com/stream-each/-/stream-each-1.2.3.tgz#ebe27a0c389b04fbcc233642952e10731afa9bae" dependencies: end-of-stream "^1.1.0" stream-shift "^1.0.0" -stream-http@^2.0.0: - version "2.8.0" - resolved "https://registry.yarnpkg.com/stream-http/-/stream-http-2.8.0.tgz#fd86546dac9b1c91aff8fc5d287b98fafb41bc10" +stream-http@^2.0.0, stream-http@^2.7.2: + version "2.8.3" + resolved "https://registry.yarnpkg.com/stream-http/-/stream-http-2.8.3.tgz#b2d242469288a5a27ec4fe8933acf623de6514fc" dependencies: builtin-status-codes "^3.0.0" inherits "^2.0.1" - readable-stream "^2.3.3" - to-arraybuffer "^1.0.0" - xtend "^4.0.0" - -stream-http@^2.3.1: - version "2.7.2" - resolved "https://registry.yarnpkg.com/stream-http/-/stream-http-2.7.2.tgz#40a050ec8dc3b53b33d9909415c02c0bf1abfbad" - dependencies: - builtin-status-codes "^3.0.0" - inherits "^2.0.1" - readable-stream "^2.2.6" + readable-stream "^2.3.6" to-arraybuffer "^1.0.0" xtend "^4.0.0" @@ -8459,7 +8965,7 @@ stream-splicer@^2.0.0: inherits "^2.0.1" readable-stream "^2.0.2" -streamroller@^0.7.0: +streamroller@0.7.0: version "0.7.0" resolved "https://registry.yarnpkg.com/streamroller/-/streamroller-0.7.0.tgz#a1d1b7cf83d39afb0d63049a5acbf93493bdf64b" dependencies: @@ -8472,12 +8978,12 @@ strict-uri-encode@^1.0.0: version "1.1.0" resolved "https://registry.yarnpkg.com/strict-uri-encode/-/strict-uri-encode-1.1.0.tgz#279b225df1d582b1f54e65addd4352e18faa0713" -string-replace-loader@1.3.0: - version "1.3.0" - resolved "https://registry.yarnpkg.com/string-replace-loader/-/string-replace-loader-1.3.0.tgz#1d404a7bf5e2ec21b08ffc76d89445fbe49bc01d" +string-replace-loader@2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/string-replace-loader/-/string-replace-loader-2.1.1.tgz#b72e7b57b6ef04efe615aff0ad989b5c14ca63d1" dependencies: loader-utils "^1.1.0" - lodash "^4" + schema-utils "^0.4.5" string-width@^1.0.1, string-width@^1.0.2: version "1.0.2" @@ -8487,7 +8993,7 @@ string-width@^1.0.1, string-width@^1.0.2: is-fullwidth-code-point "^1.0.0" strip-ansi "^3.0.0" -string-width@^2.0.0, string-width@^2.1.1: +"string-width@^1.0.2 || 2", string-width@^2.0.0, string-width@^2.1.1: version "2.1.1" resolved "https://registry.yarnpkg.com/string-width/-/string-width-2.1.1.tgz#ab93f27a8dc13d28cac815c462143a6d9012ae9e" dependencies: @@ -8502,19 +9008,25 @@ string.prototype.padend@^3.0.0: es-abstract "^1.4.3" function-bind "^1.0.2" -string_decoder@^0.10.25, string_decoder@~0.10.x: +string_decoder@^1.0.0, string_decoder@~1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.1.1.tgz#9cf1611ba62685d7030ae9e4ba34149c3af03fc8" + dependencies: + safe-buffer "~5.1.0" + +string_decoder@~0.10.x: version "0.10.31" resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-0.10.31.tgz#62e203bc41766c6c28c9fc84301dab1c5310fa94" -string_decoder@~1.0.0, string_decoder@~1.0.3: +string_decoder@~1.0.0: version "1.0.3" resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.0.3.tgz#0fc67d7c141825de94282dd536bec6b9bce860ab" dependencies: safe-buffer "~5.1.0" stringstream@~0.0.4, stringstream@~0.0.5: - version "0.0.5" - resolved "https://registry.yarnpkg.com/stringstream/-/stringstream-0.0.5.tgz#4e484cd4de5a0bbbee18e46307710a8a81621878" + version "0.0.6" + resolved "https://registry.yarnpkg.com/stringstream/-/stringstream-0.0.6.tgz#7880225b0d4ad10e30927d167a1d6f2fd3b33a72" strip-ansi@^3.0.0, strip-ansi@^3.0.1: version "3.0.1" @@ -8548,6 +9060,10 @@ strip-indent@^1.0.1: dependencies: get-stdin "^4.0.1" +strip-indent@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/strip-indent/-/strip-indent-2.0.0.tgz#5ef8db295d01e6ed6cbf7aab96998d7822527b68" + 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" @@ -8574,21 +9090,9 @@ supports-color@^3.1.0, supports-color@^3.2.3: dependencies: has-flag "^1.0.0" -supports-color@^4.0.0, supports-color@^4.2.1, supports-color@^4.4.0: - version "4.4.0" - resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-4.4.0.tgz#883f7ddabc165142b2a61427f3352ded195d1a3e" - dependencies: - has-flag "^2.0.0" - -supports-color@^5.1.0: - version "5.1.0" - resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.1.0.tgz#058a021d1b619f7ddf3980d712ea3590ce7de3d5" - dependencies: - has-flag "^2.0.0" - -supports-color@^5.2.0: - version "5.2.0" - resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.2.0.tgz#b0d5333b1184dd3666cbe5aa0b45c5ac7ac17a4a" +supports-color@^5.1.0, supports-color@^5.2.0, supports-color@^5.3.0, supports-color@^5.4.0: + version "5.5.0" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.5.0.tgz#e2e69a44ac8772f78a1ec0b35b689df6530efc8f" dependencies: has-flag "^3.0.0" @@ -8604,43 +9108,33 @@ svgo@^0.7.0: sax "~1.2.1" whet.extend "~0.9.9" -symbol-observable@1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/symbol-observable/-/symbol-observable-1.0.1.tgz#8340fc4702c3122df5d22288f88283f513d3fdd4" - syntax-error@^1.1.1: - version "1.3.0" - resolved "https://registry.yarnpkg.com/syntax-error/-/syntax-error-1.3.0.tgz#1ed9266c4d40be75dc55bf9bb1cb77062bb96ca1" + version "1.4.0" + resolved "https://registry.yarnpkg.com/syntax-error/-/syntax-error-1.4.0.tgz#2d9d4ff5c064acb711594a3e3b95054ad51d907c" dependencies: - acorn "^4.0.3" + acorn-node "^1.2.0" -tapable@^0.2.5, tapable@^0.2.7: +tapable@^0.2.5: version "0.2.8" resolved "https://registry.yarnpkg.com/tapable/-/tapable-0.2.8.tgz#99372a5c999bf2df160afc0d74bed4f47948cd22" -tar-pack@^3.4.0: - version "3.4.0" - resolved "https://registry.yarnpkg.com/tar-pack/-/tar-pack-3.4.0.tgz#23be2d7f671a8339376cbdb0b8fe3fdebf317984" - dependencies: - debug "^2.2.0" - fstream "^1.0.10" - fstream-ignore "^1.0.5" - once "^1.3.3" - readable-stream "^2.1.4" - rimraf "^2.5.1" - tar "^2.2.1" - uid-number "^0.0.6" +tapable@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/tapable/-/tapable-1.0.0.tgz#cbb639d9002eed9c6b5975eb20598d7936f1f9f2" tar-stream@^1.5.0: - version "1.5.4" - resolved "https://registry.yarnpkg.com/tar-stream/-/tar-stream-1.5.4.tgz#36549cf04ed1aee9b2a30c0143252238daf94016" + version "1.6.1" + resolved "https://registry.yarnpkg.com/tar-stream/-/tar-stream-1.6.1.tgz#f84ef1696269d6223ca48f6e1eeede3f7e81f395" dependencies: bl "^1.0.0" + buffer-alloc "^1.1.0" end-of-stream "^1.0.0" - readable-stream "^2.0.0" + fs-constants "^1.0.0" + readable-stream "^2.3.0" + to-buffer "^1.1.0" xtend "^4.0.0" -tar@^2.0.0, tar@^2.2.1: +tar@^2.0.0: version "2.2.1" resolved "https://registry.yarnpkg.com/tar/-/tar-2.2.1.tgz#8e4d2a256c0e2185c6b18ad694aec968b83cb1d1" dependencies: @@ -8648,6 +9142,18 @@ tar@^2.0.0, tar@^2.2.1: fstream "^1.0.2" inherits "2" +tar@^4: + version "4.4.6" + resolved "https://registry.yarnpkg.com/tar/-/tar-4.4.6.tgz#63110f09c00b4e60ac8bcfe1bf3c8660235fbc9b" + dependencies: + chownr "^1.0.1" + fs-minipass "^1.2.5" + minipass "^2.3.3" + minizlib "^1.1.0" + mkdirp "^0.5.0" + safe-buffer "^5.1.2" + yallist "^3.0.2" + term-size@^1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/term-size/-/term-size-1.2.0.tgz#458b83887f288fc56d6fffbfad262e26638efa69" @@ -8659,40 +9165,47 @@ text-mask-core@5.0.1: resolved "https://registry.yarnpkg.com/text-mask-core/-/text-mask-core-5.0.1.tgz#86db742bdfe3b4c383bb51a3b4ca342c86110639" text-mask-core@^5.0.0: - version "5.1.1" - resolved "https://registry.yarnpkg.com/text-mask-core/-/text-mask-core-5.1.1.tgz#a7f65634e11236818fd36a92668e17bf9368f357" + version "5.1.2" + resolved "https://registry.yarnpkg.com/text-mask-core/-/text-mask-core-5.1.2.tgz#80dd5ebe04825757e46619e691407a9f8b3c1b6f" + +text-table@^0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/text-table/-/text-table-0.2.0.tgz#7f5ee823ae805207c00af2df4a84ec3fcfa570b4" throttleit@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/throttleit/-/throttleit-1.0.0.tgz#9e785836daf46743145a5984b6268d828528ac6c" -through2@2.0.1, through2@^2.0.0: +through2@2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/through2/-/through2-2.0.1.tgz#384e75314d49f32de12eebb8136b8eb6b5d59da9" dependencies: readable-stream "~2.0.0" xtend "~4.0.0" -through@2, "through@>=2.2.7 <3", through@X.X.X, through@~2.3, through@~2.3.1: +through2@^2.0.0: + version "2.0.3" + resolved "https://registry.yarnpkg.com/through2/-/through2-2.0.3.tgz#0004569b37c7c74ba39c43f3ced78d1ad94140be" + dependencies: + readable-stream "^2.1.5" + xtend "~4.0.1" + +through@2, "through@>=2.2.7 <3", through@X.X.X, through@^2.3.6, through@~2.3, through@~2.3.1: version "2.3.8" resolved "https://registry.yarnpkg.com/through/-/through-2.3.8.tgz#0dd4c9ffaabc357960b1b724115d7e0e86a2e1f5" -thunkify@~2.1.1: +thunkify@^2.1.2: version "2.1.2" resolved "https://registry.yarnpkg.com/thunkify/-/thunkify-2.1.2.tgz#faa0e9d230c51acc95ca13a361ac05ca7e04553d" -thunky@^0.1.0: - version "0.1.0" - resolved "https://registry.yarnpkg.com/thunky/-/thunky-0.1.0.tgz#bf30146824e2b6e67b0f2d7a4ac8beb26908684e" +thunky@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/thunky/-/thunky-1.0.2.tgz#a862e018e3fb1ea2ec3fce5d55605cf57f247371" time-stamp@^1.0.0: version "1.1.0" resolved "https://registry.yarnpkg.com/time-stamp/-/time-stamp-1.1.0.tgz#764a5a11af50561921b133f3b44e618687e0f5c3" -time-stamp@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/time-stamp/-/time-stamp-2.0.0.tgz#95c6a44530e15ba8d6f4a3ecb8c3a3fac46da357" - timed-out@^4.0.0: version "4.0.1" resolved "https://registry.yarnpkg.com/timed-out/-/timed-out-4.0.1.tgz#f32eacac5a175bea25d7fab565ab3ed8741ef56f" @@ -8703,9 +9216,9 @@ timers-browserify@^1.0.1: dependencies: process "~0.11.0" -timers-browserify@^2.0.2: - version "2.0.4" - resolved "https://registry.yarnpkg.com/timers-browserify/-/timers-browserify-2.0.4.tgz#96ca53f4b794a5e7c0e1bd7cc88a372298fa01e6" +timers-browserify@^2.0.4: + version "2.0.10" + resolved "https://registry.yarnpkg.com/timers-browserify/-/timers-browserify-2.0.10.tgz#1d28e3d2aadf1d5a5996c4e9f95601cd053480ae" dependencies: setimmediate "^1.0.4" @@ -8713,9 +9226,9 @@ timespan@2.3.x: version "2.3.0" resolved "https://registry.yarnpkg.com/timespan/-/timespan-2.3.0.tgz#4902ce040bd13d845c8f59b27e9d59bad6f39929" -tmp@0.0.24: - version "0.0.24" - resolved "https://registry.yarnpkg.com/tmp/-/tmp-0.0.24.tgz#d6a5e198d14a9835cc6f2d7c3d9e302428c8cf12" +titleize@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/titleize/-/titleize-1.0.1.tgz#21bc24fcca658eadc6d3bd3c38f2bd173769b4c5" tmp@0.0.30: version "0.0.30" @@ -8723,18 +9236,12 @@ tmp@0.0.30: dependencies: os-tmpdir "~1.0.1" -tmp@0.0.33: +tmp@0.0.33, tmp@0.0.x, tmp@^0.0.33: version "0.0.33" resolved "https://registry.yarnpkg.com/tmp/-/tmp-0.0.33.tgz#6d34335889768d21b2bcda0aa277ced3b1bfadf9" dependencies: os-tmpdir "~1.0.2" -tmp@0.0.x: - version "0.0.31" - resolved "https://registry.yarnpkg.com/tmp/-/tmp-0.0.31.tgz#8f38ab9438e17315e5dbd8b3657e8bfb277ae4a7" - dependencies: - os-tmpdir "~1.0.1" - to-array@0.1.4: version "0.1.4" resolved "https://registry.yarnpkg.com/to-array/-/to-array-0.1.4.tgz#17e6c11f73dd4f3d74cda7a4ff3238e9ad9bf890" @@ -8743,6 +9250,10 @@ to-arraybuffer@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/to-arraybuffer/-/to-arraybuffer-1.0.1.tgz#7d229b1fcc637e466ca081180836a7aabff83f43" +to-buffer@^1.1.0: + version "1.1.1" + resolved "https://registry.yarnpkg.com/to-buffer/-/to-buffer-1.1.1.tgz#493bd48f62d7c43fcded313a03dcadb2e1213a80" + to-fast-properties@^1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/to-fast-properties/-/to-fast-properties-1.0.3.tgz#b83571fa4d8c25b82e231b06e3a3055de4ca1a47" @@ -8760,13 +9271,14 @@ to-regex-range@^2.1.0: is-number "^3.0.0" repeat-string "^1.6.1" -to-regex@^3.0.1: - version "3.0.1" - resolved "https://registry.yarnpkg.com/to-regex/-/to-regex-3.0.1.tgz#15358bee4a2c83bd76377ba1dc049d0f18837aae" +to-regex@^3.0.1, to-regex@^3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/to-regex/-/to-regex-3.0.2.tgz#13cfdd9b336552f30b51f33a8ae1b42a7a7599ce" dependencies: - define-property "^0.2.5" - extend-shallow "^2.0.1" - regex-not "^1.0.0" + define-property "^2.0.2" + extend-shallow "^3.0.2" + regex-not "^1.0.2" + safe-regex "^1.1.0" to-string-loader@1.1.5: version "1.1.5" @@ -8775,8 +9287,8 @@ to-string-loader@1.1.5: loader-utils "^0.2.16" toposort@^1.0.0: - version "1.0.4" - resolved "https://registry.yarnpkg.com/toposort/-/toposort-1.0.4.tgz#a86107690cbee8cae43b349d2f60162500924dfc" + version "1.0.7" + resolved "https://registry.yarnpkg.com/toposort/-/toposort-1.0.7.tgz#2e68442d9f64ec720b8cc89e6443ac6caa950029" touch@^3.1.0: version "3.1.0" @@ -8785,11 +9297,18 @@ touch@^3.1.0: nopt "~1.0.10" tough-cookie@~2.3.0, tough-cookie@~2.3.3: - version "2.3.3" - resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-2.3.3.tgz#0b618a5565b6dea90bf3425d04d55edc475a7561" + version "2.3.4" + resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-2.3.4.tgz#ec60cee38ac675063ffc97a5c18970578ee83655" dependencies: punycode "^1.4.1" +tough-cookie@~2.4.3: + version "2.4.3" + resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-2.4.3.tgz#53f36da3f47783b0925afa06ff9f3b165280f781" + dependencies: + psl "^1.1.24" + punycode "^1.4.1" + tree-kill@^1.0.0: version "1.2.0" resolved "https://registry.yarnpkg.com/tree-kill/-/tree-kill-1.2.0.tgz#5846786237b4239014f05db156b643212d4c6f36" @@ -8798,6 +9317,10 @@ trim-newlines@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/trim-newlines/-/trim-newlines-1.0.0.tgz#5887966bb582a4503a41eb524f7d35011815a613" +trim-newlines@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/trim-newlines/-/trim-newlines-2.0.0.tgz#b403d0b91be50c331dfc4b82eeceb22c3de16d20" + trim-right@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/trim-right/-/trim-right-1.0.1.tgz#cb2e1203067e0c8de1f614094b9fe45704ea6003" @@ -8809,8 +9332,8 @@ trim-right@^1.0.1: glob "^6.0.4" tryer@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/tryer/-/tryer-1.0.0.tgz#027b69fa823225e551cace3ef03b11f6ab37c1d7" + version "1.0.1" + resolved "https://registry.yarnpkg.com/tryer/-/tryer-1.0.1.tgz#f2c85406800b9b0f74c9f7465b81eaad241252f8" ts-helpers@1.1.2: version "1.1.2" @@ -8844,22 +9367,19 @@ tsconfig@^7.0.0: strip-bom "^3.0.0" strip-json-comments "^2.0.0" -tsickle@^0.26.0: - version "0.26.0" - resolved "https://registry.yarnpkg.com/tsickle/-/tsickle-0.26.0.tgz#40b30a2dd6abcb33b182e37596674bd1cfe4039c" +tsickle@^0.32.1: + version "0.32.1" + resolved "https://registry.yarnpkg.com/tsickle/-/tsickle-0.32.1.tgz#f16e94ba80b32fc9ebe320dc94fbc2ca7f3521a5" dependencies: + jasmine-diff "^0.1.3" minimist "^1.2.0" mkdirp "^0.5.1" - source-map "^0.5.6" - source-map-support "^0.4.2" + source-map "^0.6.0" + source-map-support "^0.5.0" -tslib@^1.7.1: - version "1.7.1" - resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.7.1.tgz#bc8004164691923a79fe8378bbeb3da2017538ec" - -tslib@^1.8.0, tslib@^1.8.1: - version "1.9.0" - resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.9.0.tgz#e37a86fda8cbbaf23a057f473c9f4dc64e5fc2e8" +tslib@^1.8.0, tslib@^1.8.1, tslib@^1.9.0: + version "1.9.3" + resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.9.3.tgz#d7e4dd79245d85428c4d7e4822a79917954ca286" tslint@5.9.1: version "5.9.1" @@ -8879,19 +9399,23 @@ tslint@5.9.1: tsutils "^2.12.1" tsscmp@~1.0.0: - version "1.0.5" - resolved "https://registry.yarnpkg.com/tsscmp/-/tsscmp-1.0.5.tgz#7dc4a33af71581ab4337da91d85ca5427ebd9a97" + version "1.0.6" + resolved "https://registry.yarnpkg.com/tsscmp/-/tsscmp-1.0.6.tgz#85b99583ac3589ec4bfef825b5000aa911d605eb" tsutils@^2.12.1: - version "2.19.1" - resolved "https://registry.yarnpkg.com/tsutils/-/tsutils-2.19.1.tgz#76d7ebdea9d7a7bf4a05f50ead3701b0168708d7" + version "2.29.0" + resolved "https://registry.yarnpkg.com/tsutils/-/tsutils-2.29.0.tgz#32b488501467acbedd4b85498673a0812aca0b99" dependencies: tslib "^1.8.1" -tty-browserify@0.0.0, tty-browserify@~0.0.0: +tty-browserify@0.0.0: version "0.0.0" resolved "https://registry.yarnpkg.com/tty-browserify/-/tty-browserify-0.0.0.tgz#a157ba402da24e9bf957f9aa69d524eed42901a6" +tty-browserify@~0.0.0: + version "0.0.1" + resolved "https://registry.yarnpkg.com/tty-browserify/-/tty-browserify-0.0.1.tgz#3f05251ee17904dfd0677546670db9651682b811" + tunnel-agent@^0.6.0: version "0.6.0" resolved "https://registry.yarnpkg.com/tunnel-agent/-/tunnel-agent-0.6.0.tgz#27a5dea06b36b04a0a9966774b290868f0fc40fd" @@ -8912,12 +9436,12 @@ type-check@~0.3.2: dependencies: prelude-ls "~1.1.2" -type-is@~1.6.15: - version "1.6.15" - resolved "https://registry.yarnpkg.com/type-is/-/type-is-1.6.15.tgz#cab10fb4909e441c82842eafe1ad646c81804410" +type-is@~1.6.15, type-is@~1.6.16: + version "1.6.16" + resolved "https://registry.yarnpkg.com/type-is/-/type-is-1.6.16.tgz#f89ce341541c672b25ee7ae3c73dee3b2be50194" dependencies: media-typer "0.3.0" - mime-types "~2.1.15" + mime-types "~2.1.18" typedarray@^0.0.6, typedarray@~0.0.5: version "0.0.6" @@ -8953,29 +9477,29 @@ typescript@2.4.1: version "2.4.1" resolved "https://registry.yarnpkg.com/typescript/-/typescript-2.4.1.tgz#c3ccb16ddaa0b2314de031e7e6fee89e5ba346bc" -typescript@2.6.2: - version "2.6.2" - resolved "https://registry.yarnpkg.com/typescript/-/typescript-2.6.2.tgz#3c5b6fd7f6de0914269027f03c0946758f7673a4" - typescript@^2.5.0: - version "2.5.3" - resolved "https://registry.yarnpkg.com/typescript/-/typescript-2.5.3.tgz#df3dcdc38f3beb800d4bc322646b04a3f6ca7f0d" + version "2.9.2" + resolved "https://registry.yarnpkg.com/typescript/-/typescript-2.9.2.tgz#1cbf61d05d6b96269244eb6a3bce4bd914e0f00c" -uglify-es@^3.3.7: - version "3.3.8" - resolved "https://registry.yarnpkg.com/uglify-es/-/uglify-es-3.3.8.tgz#f2c68e6cff0d0f9dc9577e4da207151c2e753b7e" +typescript@^2.9.1: + version "2.9.1" + resolved "https://registry.yarnpkg.com/typescript/-/typescript-2.9.1.tgz#fdb19d2c67a15d11995fd15640e373e09ab09961" + +uglify-es@^3.3.4, uglify-es@^3.3.7: + version "3.3.9" + resolved "https://registry.yarnpkg.com/uglify-es/-/uglify-es-3.3.9.tgz#0c1c4f0700bed8dbc124cdb304d2592ca203e677" dependencies: commander "~2.13.0" source-map "~0.6.1" -uglify-js@3.1.x: - version "3.1.2" - resolved "https://registry.yarnpkg.com/uglify-js/-/uglify-js-3.1.2.tgz#b50bcf15a5fd9e9ed40afbcdef3b59d6891b291f" +uglify-js@3.4.x: + version "3.4.8" + resolved "https://registry.yarnpkg.com/uglify-js/-/uglify-js-3.4.8.tgz#d590777b208258b54131b1ae45bc9d3f68033a3e" dependencies: - commander "~2.11.0" - source-map "~0.5.1" + commander "~2.17.1" + source-map "~0.6.1" -uglify-js@^2.6, uglify-js@^2.8.29: +uglify-js@^2.6: version "2.8.29" resolved "https://registry.yarnpkg.com/uglify-js/-/uglify-js-2.8.29.tgz#29c5733148057bb4e1f75df35b7a9cb72e6a59dd" dependencies: @@ -8988,17 +9512,18 @@ uglify-to-browserify@~1.0.0: version "1.0.2" resolved "https://registry.yarnpkg.com/uglify-to-browserify/-/uglify-to-browserify-1.0.2.tgz#6e0924d6bda6b5afe349e39a6d632850a0f882b7" -uglifyjs-webpack-plugin@^0.4.6: - version "0.4.6" - resolved "https://registry.yarnpkg.com/uglifyjs-webpack-plugin/-/uglifyjs-webpack-plugin-0.4.6.tgz#b951f4abb6bd617e66f63eb891498e391763e309" +uglifyjs-webpack-plugin@^1.2.4: + version "1.3.0" + resolved "https://registry.yarnpkg.com/uglifyjs-webpack-plugin/-/uglifyjs-webpack-plugin-1.3.0.tgz#75f548160858163a08643e086d5fefe18a5d67de" dependencies: - source-map "^0.5.6" - uglify-js "^2.8.29" - webpack-sources "^1.0.1" - -uid-number@^0.0.6: - version "0.0.6" - resolved "https://registry.yarnpkg.com/uid-number/-/uid-number-0.0.6.tgz#0ea10e8035e8eb5b8e4449f06da1c730663baa81" + cacache "^10.0.4" + find-cache-dir "^1.0.0" + schema-utils "^0.4.5" + serialize-javascript "^1.4.0" + source-map "^0.6.1" + uglify-es "^3.3.4" + webpack-sources "^1.1.0" + worker-farm "^1.5.2" uid-safe@~2.1.5: version "2.1.5" @@ -9006,31 +9531,29 @@ uid-safe@~2.1.5: dependencies: random-bytes "~1.0.0" -ultron@1.0.x: - version "1.0.2" - resolved "https://registry.yarnpkg.com/ultron/-/ultron-1.0.2.tgz#ace116ab557cd197386a4e88f4685378c8b2e4fa" - ultron@~1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/ultron/-/ultron-1.1.0.tgz#b07a2e6a541a815fc6a34ccd4533baec307ca864" + version "1.1.1" + resolved "https://registry.yarnpkg.com/ultron/-/ultron-1.1.1.tgz#9fe1536a10a664a65266a1e3ccf85fd36302bc9c" umd@^3.0.0: - version "3.0.1" - resolved "https://registry.yarnpkg.com/umd/-/umd-3.0.1.tgz#8ae556e11011f63c2596708a8837259f01b3d60e" + version "3.0.3" + resolved "https://registry.yarnpkg.com/umd/-/umd-3.0.3.tgz#aa9fe653c42b9097678489c01000acb69f0b26cf" -undefsafe@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/undefsafe/-/undefsafe-2.0.1.tgz#03b2f2a16c94556e14b2edef326cd66aaf82707a" +undeclared-identifiers@^1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/undeclared-identifiers/-/undeclared-identifiers-1.1.2.tgz#7d850a98887cff4bd0bf64999c014d08ed6d1acc" + dependencies: + acorn-node "^1.3.0" + get-assigned-identifiers "^1.2.0" + simple-concat "^1.0.0" + xtend "^4.0.1" + +undefsafe@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/undefsafe/-/undefsafe-2.0.2.tgz#225f6b9e0337663e0d8e7cfd686fc2836ccace76" dependencies: debug "^2.2.0" -underscore.string@3.3.4: - version "3.3.4" - resolved "https://registry.yarnpkg.com/underscore.string/-/underscore.string-3.3.4.tgz#2c2a3f9f83e64762fdc45e6ceac65142864213db" - dependencies: - sprintf-js "^1.0.3" - util-deprecate "^1.0.2" - underscore@~1.7.0: version "1.7.0" resolved "https://registry.yarnpkg.com/underscore/-/underscore-1.7.0.tgz#6bbaf0877500d36be34ecaa584e0db9fef035209" @@ -9054,12 +9577,6 @@ uniq@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/uniq/-/uniq-1.0.1.tgz#b31c5ae8254844a3a8281541ce2b04b865a734ff" -uniqid@^4.0.0: - version "4.1.1" - resolved "https://registry.yarnpkg.com/uniqid/-/uniqid-4.1.1.tgz#89220ddf6b751ae52b5f72484863528596bb84c1" - dependencies: - macaddress "^0.2.8" - uniqs@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/uniqs/-/uniqs-2.0.0.tgz#ffede4b36b25290696e6e165d4a59edb998e6b02" @@ -9090,8 +9607,8 @@ units-css@^0.4.0: viewport-dimensions "^0.2.0" universalify@^0.1.0: - version "0.1.1" - resolved "https://registry.yarnpkg.com/universalify/-/universalify-0.1.1.tgz#fa71badd4437af4c148841e3b3b165f9e9e590b7" + version "0.1.2" + resolved "https://registry.yarnpkg.com/universalify/-/universalify-0.1.2.tgz#b646f69be3942dabcecc9d6639c80dc105efaa66" unpipe@1.0.0, unpipe@~1.0.0: version "1.0.0" @@ -9108,23 +9625,19 @@ unzip-response@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/unzip-response/-/unzip-response-2.0.1.tgz#d2f0f737d16b0615e72a6935ed04214572d56f97" -upath@^1.0.0: - version "1.0.2" - resolved "https://registry.yarnpkg.com/upath/-/upath-1.0.2.tgz#80aaae5395abc5fd402933ae2f58694f0860204c" - dependencies: - lodash.endswith "^4.2.1" - lodash.isfunction "^3.0.8" - lodash.isstring "^4.0.1" - lodash.startswith "^4.2.1" +upath@^1.0.5: + version "1.1.0" + resolved "https://registry.yarnpkg.com/upath/-/upath-1.1.0.tgz#35256597e46a581db4793d0ce47fa9aebfc9fabd" update-notifier@^2.3.0: - version "2.3.0" - resolved "https://registry.yarnpkg.com/update-notifier/-/update-notifier-2.3.0.tgz#4e8827a6bb915140ab093559d7014e3ebb837451" + version "2.5.0" + resolved "https://registry.yarnpkg.com/update-notifier/-/update-notifier-2.5.0.tgz#d0744593e13f161e406acb1d9408b72cad08aff6" dependencies: boxen "^1.2.1" chalk "^2.0.1" configstore "^3.0.0" import-lazy "^2.1.0" + is-ci "^1.0.10" is-installed-globally "^0.1.0" is-npm "^1.0.0" latest-version "^3.0.0" @@ -9135,13 +9648,29 @@ upper-case@^1.1.1: version "1.1.3" resolved "https://registry.yarnpkg.com/upper-case/-/upper-case-1.1.3.tgz#f6b4501c2ec4cdd26ba78be7222961de77621598" -urix@^0.1.0, urix@~0.1.0: +uri-js@^3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/uri-js/-/uri-js-3.0.2.tgz#f90b858507f81dea4dcfbb3c4c3dbfa2b557faaa" + dependencies: + punycode "^2.1.0" + +uri-js@^4.2.2: + version "4.2.2" + resolved "https://registry.yarnpkg.com/uri-js/-/uri-js-4.2.2.tgz#94c540e1ff772956e2299507c010aea6c8838eb0" + dependencies: + punycode "^2.1.0" + +urix@^0.1.0: version "0.1.0" resolved "https://registry.yarnpkg.com/urix/-/urix-0.1.0.tgz#da937f7a62e21fec1fd18d49b35c2935067a6c72" -url-join@^2.0.2: - version "2.0.2" - resolved "https://registry.yarnpkg.com/url-join/-/url-join-2.0.2.tgz#c072756967ad24b8b59e5741551caac78f50b8b7" +url-join@^2.0.2, url-join@^2.0.5: + version "2.0.5" + resolved "https://registry.yarnpkg.com/url-join/-/url-join-2.0.5.tgz#5af22f18c052a000a48d7b82c5e9c2e2feeda728" + +url-join@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/url-join/-/url-join-4.0.0.tgz#4d3340e807d3773bda9991f8305acdcc2a665d2a" url-parse-lax@^1.0.0: version "1.0.0" @@ -9149,19 +9678,12 @@ url-parse-lax@^1.0.0: dependencies: prepend-http "^1.0.1" -url-parse@1.0.x: - version "1.0.5" - resolved "https://registry.yarnpkg.com/url-parse/-/url-parse-1.0.5.tgz#0854860422afdcfefeb6c965c662d4800169927b" +url-parse@^1.1.8, url-parse@^1.4.3: + version "1.4.3" + resolved "https://registry.yarnpkg.com/url-parse/-/url-parse-1.4.3.tgz#bfaee455c889023219d757e045fa6a684ec36c15" dependencies: - querystringify "0.0.x" - requires-port "1.0.x" - -url-parse@^1.1.8: - version "1.1.9" - resolved "https://registry.yarnpkg.com/url-parse/-/url-parse-1.1.9.tgz#c67f1d775d51f0a18911dd7b3ffad27bb9e5bd19" - dependencies: - querystringify "~1.0.0" - requires-port "1.0.x" + querystringify "^2.0.0" + requires-port "^1.0.0" url@^0.11.0, url@~0.11.0: version "0.11.0" @@ -9170,31 +9692,40 @@ url@^0.11.0, url@~0.11.0: punycode "1.3.2" querystring "0.2.0" -use@^2.0.0: - version "2.0.2" - resolved "https://registry.yarnpkg.com/use/-/use-2.0.2.tgz#ae28a0d72f93bf22422a18a2e379993112dec8e8" - dependencies: - define-property "^0.2.5" - isobject "^3.0.0" - lazy-cache "^2.0.2" +use@^3.1.0: + version "3.1.1" + resolved "https://registry.yarnpkg.com/use/-/use-3.1.1.tgz#d50c8cac79a19fbc20f2911f56eb973f4e10070f" useragent@^2.1.12: - version "2.2.1" - resolved "https://registry.yarnpkg.com/useragent/-/useragent-2.2.1.tgz#cf593ef4f2d175875e8bb658ea92e18a4fd06d8e" + version "2.3.0" + resolved "https://registry.yarnpkg.com/useragent/-/useragent-2.3.0.tgz#217f943ad540cb2128658ab23fc960f6a88c9972" dependencies: - lru-cache "2.2.x" + lru-cache "4.1.x" tmp "0.0.x" -util-deprecate@^1.0.2, util-deprecate@~1.0.1: +util-deprecate@~1.0.1: version "1.0.2" resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf" -util@0.10.3, util@^0.10.3, util@~0.10.1: +util.promisify@1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/util.promisify/-/util.promisify-1.0.0.tgz#440f7165a459c9a16dc145eb8e72f35687097030" + dependencies: + define-properties "^1.1.2" + object.getownpropertydescriptors "^2.0.3" + +util@0.10.3: version "0.10.3" resolved "https://registry.yarnpkg.com/util/-/util-0.10.3.tgz#7afb1afe50805246489e3db7fe0ed379336ac0f9" dependencies: inherits "2.0.1" +util@^0.10.3, util@~0.10.1: + version "0.10.4" + resolved "https://registry.yarnpkg.com/util/-/util-0.10.4.tgz#3aa0125bfe668a4672de58857d3ace27ecb76901" + dependencies: + inherits "2.0.3" + utila@~0.3: version "0.3.3" resolved "https://registry.yarnpkg.com/utila/-/utila-0.3.3.tgz#d7e8e7d7e309107092b05f8d9688824d633a4226" @@ -9211,30 +9742,30 @@ uuid@^2.0.1: version "2.0.3" resolved "https://registry.yarnpkg.com/uuid/-/uuid-2.0.3.tgz#67e2e863797215530dff318e5bf9dcebfd47b21a" -uuid@^3.0.0, uuid@^3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.1.0.tgz#3dd3d3e790abc24d7b0d3a034ffababe28ebbc04" +uuid@^3.0.1, uuid@^3.1.0, uuid@^3.2.1, uuid@^3.3.2: + version "3.3.2" + resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.3.2.tgz#1b4af4955eb3077c501c23872fc6513811587131" -uuid@^3.0.1, uuid@^3.2.1: - version "3.2.1" - resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.2.1.tgz#12c528bb9d58d0b9265d9a2f6f0fe8be17ff1f14" +uws@~9.14.0: + version "9.14.0" + resolved "https://registry.yarnpkg.com/uws/-/uws-9.14.0.tgz#fac8386befc33a7a3705cbd58dc47b430ca4dd95" -uws@~0.14.4: - version "0.14.5" - resolved "https://registry.yarnpkg.com/uws/-/uws-0.14.5.tgz#67aaf33c46b2a587a5f6666d00f7691328f149dc" +v8-compile-cache@^2.0.0: + version "2.0.2" + resolved "https://registry.yarnpkg.com/v8-compile-cache/-/v8-compile-cache-2.0.2.tgz#a428b28bb26790734c4fc8bc9fa106fccebf6a6c" v8flags@^3.0.0: - version "3.0.1" - resolved "https://registry.yarnpkg.com/v8flags/-/v8flags-3.0.1.tgz#dce8fc379c17d9f2c9e9ed78d89ce00052b1b76b" + version "3.1.1" + resolved "https://registry.yarnpkg.com/v8flags/-/v8flags-3.1.1.tgz#42259a1461c08397e37fe1d4f1cfb59cad85a053" dependencies: homedir-polyfill "^1.0.1" validate-npm-package-license@^3.0.1: - version "3.0.1" - resolved "https://registry.yarnpkg.com/validate-npm-package-license/-/validate-npm-package-license-3.0.1.tgz#2804babe712ad3379459acfbe24746ab2c303fbc" + version "3.0.4" + resolved "https://registry.yarnpkg.com/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz#fc91f6b9c7ba15c857f4cb2c5defeec39d4f410a" dependencies: - spdx-correct "~1.0.0" - spdx-expression-parse "~1.0.0" + spdx-correct "^3.0.0" + spdx-expression-parse "^3.0.0" vargs@0.1.0: version "0.1.0" @@ -9245,8 +9776,8 @@ vary@~1.1.2: resolved "https://registry.yarnpkg.com/vary/-/vary-1.1.2.tgz#2299f02c6ded30d4a5961b0b9f74524a18f634fc" vendors@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/vendors/-/vendors-1.0.1.tgz#37ad73c8ee417fb3d580e785312307d274847f22" + version "1.0.2" + resolved "https://registry.yarnpkg.com/vendors/-/vendors-1.0.2.tgz#7fcb5eef9f5623b156bcea89ec37d63676f21801" verror@1.10.0: version "1.10.0" @@ -9268,9 +9799,9 @@ vinyl@^0.5.0: clone-stats "^0.0.1" replace-ext "0.0.1" -vlq@^0.2.1: - version "0.2.2" - resolved "https://registry.yarnpkg.com/vlq/-/vlq-0.2.2.tgz#e316d5257b40b86bb43cb8d5fea5d7f54d6b0ca1" +vlq@^0.2.1, vlq@^0.2.2: + version "0.2.3" + resolved "https://registry.yarnpkg.com/vlq/-/vlq-0.2.3.tgz#8f3e4328cf63b1540c0d67e1b2778386f8975b26" vm-browserify@0.0.4, vm-browserify@~0.0.1: version "0.0.4" @@ -9282,56 +9813,57 @@ void-elements@^2.0.0: version "2.0.1" resolved "https://registry.yarnpkg.com/void-elements/-/void-elements-2.0.1.tgz#c066afb582bb1cb4128d60ea92392e94d5e9dbec" -walkdir@^0.0.11: - version "0.0.11" - resolved "https://registry.yarnpkg.com/walkdir/-/walkdir-0.0.11.tgz#a16d025eb931bd03b52f308caed0f40fcebe9532" - -watchpack@^1.4.0: - version "1.4.0" - resolved "https://registry.yarnpkg.com/watchpack/-/watchpack-1.4.0.tgz#4a1472bcbb952bd0a9bb4036801f954dfb39faac" +watchpack@^1.5.0: + version "1.6.0" + resolved "https://registry.yarnpkg.com/watchpack/-/watchpack-1.6.0.tgz#4bc12c2ebe8aa277a71f1d3f14d685c7b446cd00" dependencies: - async "^2.1.2" - chokidar "^1.7.0" + chokidar "^2.0.2" graceful-fs "^4.1.2" + neo-async "^2.5.0" wbuf@^1.1.0, wbuf@^1.7.2: - version "1.7.2" - resolved "https://registry.yarnpkg.com/wbuf/-/wbuf-1.7.2.tgz#d697b99f1f59512df2751be42769c1580b5801fe" + version "1.7.3" + resolved "https://registry.yarnpkg.com/wbuf/-/wbuf-1.7.3.tgz#c1d8d149316d3ea852848895cb6a0bfe887b87df" dependencies: minimalistic-assert "^1.0.0" -wd@^1.0.0: - version "1.4.1" - resolved "https://registry.yarnpkg.com/wd/-/wd-1.4.1.tgz#6b1ab39aab1728ee276c1a2b6d7321da68b16e8c" +wcwidth@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/wcwidth/-/wcwidth-1.0.1.tgz#f0b0dcf915bc5ff1528afadb2c0e17b532da2fe8" dependencies: - archiver "1.3.0" + defaults "^1.0.3" + +wd@^1.0.0: + version "1.10.3" + resolved "https://registry.yarnpkg.com/wd/-/wd-1.10.3.tgz#395ac7eb58a98e556369f8f8e5f845d91fb152a3" + dependencies: + archiver "2.1.1" async "2.0.1" - lodash "4.16.2" + lodash "4.17.10" mkdirp "^0.5.1" q "1.4.1" - request "2.79.0" - underscore.string "3.3.4" + request "2.85.0" vargs "0.1.0" -webdriver-js-extender@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/webdriver-js-extender/-/webdriver-js-extender-1.0.0.tgz#81c533a9e33d5bfb597b4e63e2cdb25b54777515" +webdriver-js-extender@2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/webdriver-js-extender/-/webdriver-js-extender-2.0.0.tgz#b27fc1ed1afbf78f0ac57e4c878f31b10e57f146" dependencies: - "@types/selenium-webdriver" "^2.53.35" - selenium-webdriver "^2.53.2" + "@types/selenium-webdriver" "^3.0.0" + selenium-webdriver "^3.0.1" webdriver-manager@^12.0.6: - version "12.0.6" - resolved "https://registry.yarnpkg.com/webdriver-manager/-/webdriver-manager-12.0.6.tgz#3df1a481977010b4cbf8c9d85c7a577828c0e70b" + version "12.1.0" + resolved "https://registry.yarnpkg.com/webdriver-manager/-/webdriver-manager-12.1.0.tgz#f6601e52de5f0c97fc7024c889eeb2416f2f1d9d" dependencies: - adm-zip "^0.4.7" + adm-zip "^0.4.9" chalk "^1.1.1" del "^2.2.0" glob "^7.0.3" ini "^1.3.4" minimist "^1.2.0" q "^1.4.1" - request "^2.78.0" + request "^2.87.0" rimraf "^2.5.2" semver "^5.3.0" xml2js "^0.4.17" @@ -9340,9 +9872,9 @@ webfontloader@1.6.28: version "1.6.28" resolved "https://registry.yarnpkg.com/webfontloader/-/webfontloader-1.6.28.tgz#db786129253cb6e8eae54c2fb05f870af6675bae" -webpack-bundle-analyzer@^2.10.0: - version "2.10.0" - resolved "https://registry.yarnpkg.com/webpack-bundle-analyzer/-/webpack-bundle-analyzer-2.10.0.tgz#d0646cda342939f6f05eb632a090abbd90317446" +webpack-bundle-analyzer@^2.13.1: + version "2.13.1" + resolved "https://registry.yarnpkg.com/webpack-bundle-analyzer/-/webpack-bundle-analyzer-2.13.1.tgz#07d2176c6e86c3cdce4c23e56fae2a7b6b4ad526" dependencies: acorn "^5.3.0" bfj-node4 "^5.2.0" @@ -9357,19 +9889,65 @@ webpack-bundle-analyzer@^2.10.0: opener "^1.4.3" ws "^4.0.0" -webpack-dev-middleware@1.12.2, webpack-dev-middleware@^1.12.0: - version "1.12.2" - resolved "https://registry.yarnpkg.com/webpack-dev-middleware/-/webpack-dev-middleware-1.12.2.tgz#f8fc1120ce3b4fc5680ceecb43d777966b21105e" +webpack-command@^0.4.1: + version "0.4.1" + resolved "https://registry.yarnpkg.com/webpack-command/-/webpack-command-0.4.1.tgz#3f88aae87c28292ed0a97293615a2e962a1c66f4" dependencies: + "@webpack-contrib/config-loader" "^1.2.0" + "@webpack-contrib/schema-utils" "^1.0.0-beta.0" + camelcase "^5.0.0" + chalk "^2.3.2" + debug "^3.1.0" + decamelize "^2.0.0" + enhanced-resolve "^4.0.0" + import-local "^1.0.0" + isobject "^3.0.1" + loader-utils "^1.1.0" + log-symbols "^2.2.0" + loud-rejection "^1.6.0" + meant "^1.0.1" + meow "^5.0.0" + merge-options "^1.0.0" + object.values "^1.0.4" + opn "^5.3.0" + ora "^2.1.0" + plur "^3.0.0" + pretty-bytes "^5.0.0" + strip-ansi "^4.0.0" + text-table "^0.2.0" + titleize "^1.0.1" + update-notifier "^2.3.0" + v8-compile-cache "^2.0.0" + webpack-log "^1.1.2" + wordwrap "^1.0.0" + +webpack-dev-middleware@3.1.3: + version "3.1.3" + resolved "https://registry.yarnpkg.com/webpack-dev-middleware/-/webpack-dev-middleware-3.1.3.tgz#8b32aa43da9ae79368c1bf1183f2b6cf5e1f39ed" + dependencies: + loud-rejection "^1.6.0" memory-fs "~0.4.1" - mime "^1.5.0" + mime "^2.1.0" path-is-absolute "^1.0.0" range-parser "^1.0.3" - time-stamp "^2.0.0" + url-join "^4.0.0" + webpack-log "^1.0.1" -webpack-dev-middleware@^2.0.5: - version "2.0.5" - resolved "https://registry.yarnpkg.com/webpack-dev-middleware/-/webpack-dev-middleware-2.0.5.tgz#2a1d07afb599e1993033d72c2181ec2344c15e31" +webpack-dev-middleware@3.2.0: + version "3.2.0" + resolved "https://registry.yarnpkg.com/webpack-dev-middleware/-/webpack-dev-middleware-3.2.0.tgz#a20ceef194873710052da678f3c6ee0aeed92552" + dependencies: + loud-rejection "^1.6.0" + memory-fs "~0.4.1" + mime "^2.3.1" + path-is-absolute "^1.0.0" + range-parser "^1.0.3" + url-join "^4.0.0" + webpack-log "^2.0.0" + +webpack-dev-middleware@^2.0.6: + version "2.0.6" + resolved "https://registry.yarnpkg.com/webpack-dev-middleware/-/webpack-dev-middleware-2.0.6.tgz#a51692801e8310844ef3e3790e1eacfe52326fd4" dependencies: loud-rejection "^1.6.0" memory-fs "~0.4.1" @@ -9379,9 +9957,9 @@ webpack-dev-middleware@^2.0.5: url-join "^2.0.2" webpack-log "^1.0.1" -webpack-dev-server@2.11.1: - version "2.11.1" - resolved "https://registry.yarnpkg.com/webpack-dev-server/-/webpack-dev-server-2.11.1.tgz#6f9358a002db8403f016e336816f4485384e5ec0" +webpack-dev-server@^3.1.5: + version "3.1.5" + resolved "https://registry.yarnpkg.com/webpack-dev-server/-/webpack-dev-server-3.1.5.tgz#87477252e1ac6789303fb8cd3e585fa5d508a401" dependencies: ansi-html "0.0.7" array-includes "^3.0.3" @@ -9393,7 +9971,7 @@ webpack-dev-server@2.11.1: del "^3.0.0" express "^4.16.2" html-entities "^1.2.0" - http-proxy-middleware "~0.17.4" + http-proxy-middleware "~0.18.0" import-local "^1.0.0" internal-ip "1.2.0" ip "^1.1.5" @@ -9404,72 +9982,76 @@ webpack-dev-server@2.11.1: selfsigned "^1.9.1" serve-index "^1.7.2" sockjs "0.3.19" - sockjs-client "1.1.4" + sockjs-client "1.1.5" spdy "^3.4.1" strip-ansi "^3.0.0" supports-color "^5.1.0" - webpack-dev-middleware "1.12.2" - yargs "6.6.0" + webpack-dev-middleware "3.1.3" + webpack-log "^1.1.2" + yargs "11.0.0" -webpack-log@^1.0.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/webpack-log/-/webpack-log-1.1.1.tgz#a0c7beb385245da7b2172afe46c02cf3a471ef31" +webpack-log@^1.0.1, webpack-log@^1.1.2: + version "1.2.0" + resolved "https://registry.yarnpkg.com/webpack-log/-/webpack-log-1.2.0.tgz#a4b34cda6b22b518dbb0ab32e567962d5c72a43d" dependencies: chalk "^2.1.0" log-symbols "^2.1.0" loglevelnext "^1.0.1" uuid "^3.1.0" -webpack-merge@4.1.1: - version "4.1.1" - resolved "https://registry.yarnpkg.com/webpack-merge/-/webpack-merge-4.1.1.tgz#f1197a0a973e69c6fbeeb6d658219aa8c0c13555" +webpack-log@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/webpack-log/-/webpack-log-2.0.0.tgz#5b7928e0637593f119d32f6227c1e0ac31e1b47f" dependencies: - lodash "^4.17.4" + ansi-colors "^3.0.0" + uuid "^3.3.2" -webpack-node-externals@1.6.0: - version "1.6.0" - resolved "https://registry.yarnpkg.com/webpack-node-externals/-/webpack-node-externals-1.6.0.tgz#232c62ec6092b100635a3d29d83c1747128df9bd" - -webpack-sources@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/webpack-sources/-/webpack-sources-1.0.1.tgz#c7356436a4d13123be2e2426a05d1dad9cbe65cf" +webpack-merge@4.1.4: + version "4.1.4" + resolved "https://registry.yarnpkg.com/webpack-merge/-/webpack-merge-4.1.4.tgz#0fde38eabf2d5fd85251c24a5a8c48f8a3f4eb7b" dependencies: - source-list-map "^2.0.0" - source-map "~0.5.3" + lodash "^4.17.5" -webpack-sources@^1.1.0: +webpack-node-externals@1.7.2: + version "1.7.2" + resolved "https://registry.yarnpkg.com/webpack-node-externals/-/webpack-node-externals-1.7.2.tgz#6e1ee79ac67c070402ba700ef033a9b8d52ac4e3" + +webpack-sources@^1.0.1, webpack-sources@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/webpack-sources/-/webpack-sources-1.1.0.tgz#a101ebae59d6507354d71d8013950a3a8b7a5a54" dependencies: source-list-map "^2.0.0" source-map "~0.6.1" -webpack@^3.11.0: - version "3.11.0" - resolved "https://registry.yarnpkg.com/webpack/-/webpack-3.11.0.tgz#77da451b1d7b4b117adaf41a1a93b5742f24d894" +webpack@^4.17.1: + version "4.17.1" + resolved "https://registry.yarnpkg.com/webpack/-/webpack-4.17.1.tgz#0f026e3d823f3fc604f811ed3ea8f0d9b267fb1e" dependencies: - acorn "^5.0.0" - acorn-dynamic-import "^2.0.0" + "@webassemblyjs/ast" "1.5.13" + "@webassemblyjs/helper-module-context" "1.5.13" + "@webassemblyjs/wasm-edit" "1.5.13" + "@webassemblyjs/wasm-opt" "1.5.13" + "@webassemblyjs/wasm-parser" "1.5.13" + acorn "^5.6.2" + acorn-dynamic-import "^3.0.0" ajv "^6.1.0" ajv-keywords "^3.1.0" - async "^2.1.2" - enhanced-resolve "^3.4.0" - escope "^3.6.0" - interpret "^1.0.0" - json-loader "^0.5.4" - json5 "^0.5.1" + chrome-trace-event "^1.0.0" + enhanced-resolve "^4.1.0" + eslint-scope "^4.0.0" + json-parse-better-errors "^1.0.2" loader-runner "^2.3.0" loader-utils "^1.1.0" memory-fs "~0.4.1" + micromatch "^3.1.8" mkdirp "~0.5.0" + neo-async "^2.5.0" node-libs-browser "^2.0.0" - source-map "^0.5.3" - supports-color "^4.2.1" - tapable "^0.2.7" - uglifyjs-webpack-plugin "^0.4.6" - watchpack "^1.4.0" + schema-utils "^0.4.4" + tapable "^1.0.0" + uglifyjs-webpack-plugin "^1.2.4" + watchpack "^1.5.0" webpack-sources "^1.0.1" - yargs "^8.0.2" websocket-driver@>=0.5.1: version "0.7.0" @@ -9479,8 +10061,8 @@ websocket-driver@>=0.5.1: websocket-extensions ">=0.1.1" websocket-extensions@>=0.1.1: - version "0.1.2" - resolved "https://registry.yarnpkg.com/websocket-extensions/-/websocket-extensions-0.1.2.tgz#0e18781de629a18308ce1481650f67ffa2693a5d" + version "0.1.3" + resolved "https://registry.yarnpkg.com/websocket-extensions/-/websocket-extensions-0.1.3.tgz#5d2ff22977003ec687a4b87073dfbbac146ccf29" when@^3.7.7: version "3.7.8" @@ -9498,23 +10080,17 @@ which-module@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/which-module/-/which-module-2.0.0.tgz#d9ef07dce77b9902b8a3a8fa4b31c3e3f7e6e87a" -which@1, which@^1.1.1, which@^1.2.1, which@^1.2.4, which@^1.2.9: - version "1.3.0" - resolved "https://registry.yarnpkg.com/which/-/which-1.3.0.tgz#ff04bdfc010ee547d780bec38e1ac1c2777d253a" - dependencies: - isexe "^2.0.0" - -which@~1.2.10: - version "1.2.14" - resolved "https://registry.yarnpkg.com/which/-/which-1.2.14.tgz#9a87c4378f03e827cecaf1acdf56c736c01c14e5" +which@1, which@^1.1.1, which@^1.2.1, which@^1.2.10, which@^1.2.4, which@^1.2.9: + version "1.3.1" + resolved "https://registry.yarnpkg.com/which/-/which-1.3.1.tgz#a45043d54f5805316da8d62f9f50918d3da70b0a" dependencies: isexe "^2.0.0" wide-align@^1.1.0: - version "1.1.2" - resolved "https://registry.yarnpkg.com/wide-align/-/wide-align-1.1.2.tgz#571e0f1b0604636ebc0dfc21b0339bbe31341710" + version "1.1.3" + resolved "https://registry.yarnpkg.com/wide-align/-/wide-align-1.1.3.tgz#ae074e6bdc0c14a431e804e624549c633b000457" dependencies: - string-width "^1.0.2" + string-width "^1.0.2 || 2" widest-line@^2.0.0: version "2.0.0" @@ -9526,6 +10102,10 @@ window-size@0.1.0: version "0.1.0" resolved "https://registry.yarnpkg.com/window-size/-/window-size-0.1.0.tgz#5438cd2ea93b202efa3a19fe8887aee7c94f9c9d" +with-callback@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/with-callback/-/with-callback-1.0.2.tgz#a09629b9a920028d721404fb435bdcff5c91bc21" + wordwrap@0.0.2: version "0.0.2" resolved "https://registry.yarnpkg.com/wordwrap/-/wordwrap-0.0.2.tgz#b79669bb42ecb409f83d583cad52ca17eaa1643f" @@ -9538,6 +10118,12 @@ wordwrap@~0.0.2: version "0.0.3" resolved "https://registry.yarnpkg.com/wordwrap/-/wordwrap-0.0.3.tgz#a3d5da6cd5c0bc0008d37234bbaf1bed63059107" +worker-farm@^1.5.2: + version "1.6.0" + resolved "https://registry.yarnpkg.com/worker-farm/-/worker-farm-1.6.0.tgz#aecc405976fab5a95526180846f0dba288f3a4a0" + dependencies: + errno "~0.1.7" + wrap-ansi@^2.0.0: version "2.1.0" resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-2.1.0.tgz#d8fc3d284dd05794fe84973caecdd1cf824fdd85" @@ -9557,20 +10143,12 @@ write-file-atomic@^2.0.0: imurmurhash "^0.1.4" signal-exit "^3.0.2" -ws@^1.0.1: - version "1.1.2" - resolved "https://registry.yarnpkg.com/ws/-/ws-1.1.2.tgz#8a244fa052401e08c9886cf44a85189e1fd4067f" - dependencies: - options ">=0.0.5" - ultron "1.0.x" - ws@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/ws/-/ws-4.0.0.tgz#bfe1da4c08eeb9780b986e0e4d10eccd7345999f" + version "4.1.0" + resolved "https://registry.yarnpkg.com/ws/-/ws-4.1.0.tgz#a979b5d7d4da68bf54efe0408967c324869a7289" dependencies: async-limiter "~1.0.0" safe-buffer "~5.1.0" - ultron "~1.1.0" ws@~3.3.1: version "3.3.3" @@ -9588,17 +10166,6 @@ xhr2@^0.1.4: version "0.1.4" resolved "https://registry.yarnpkg.com/xhr2/-/xhr2-0.1.4.tgz#7f87658847716db5026323812f818cadab387a5f" -xml-char-classes@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/xml-char-classes/-/xml-char-classes-1.0.0.tgz#64657848a20ffc5df583a42ad8a277b4512bbc4d" - -xml2js@0.4.4: - version "0.4.4" - resolved "https://registry.yarnpkg.com/xml2js/-/xml2js-0.4.4.tgz#3111010003008ae19240eba17497b57c729c555d" - dependencies: - sax "0.6.x" - xmlbuilder ">=1.0.0" - xml2js@^0.4.17: version "0.4.19" resolved "https://registry.yarnpkg.com/xml2js/-/xml2js-0.4.19.tgz#686c20f213209e94abf0d1bcf1efaa291c7827a7" @@ -9606,9 +10173,9 @@ xml2js@^0.4.17: sax ">=0.6.0" xmlbuilder "~9.0.1" -xmlbuilder@>=1.0.0, xmlbuilder@~9.0.1: - version "9.0.4" - resolved "https://registry.yarnpkg.com/xmlbuilder/-/xmlbuilder-9.0.4.tgz#519cb4ca686d005a8420d3496f3f0caeecca580f" +xmlbuilder@~9.0.1: + version "9.0.7" + resolved "https://registry.yarnpkg.com/xmlbuilder/-/xmlbuilder-9.0.7.tgz#132ee63d2ec5565c557e20f4c22df9aca686b10d" xmlhttprequest-ssl@~1.5.4: version "1.5.5" @@ -9618,7 +10185,11 @@ xregexp@2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/xregexp/-/xregexp-2.0.0.tgz#52a63e56ca0b84a7f3a5f3d61872f126ad7a5943" -xtend@^4.0.0, xtend@~4.0.0: +xregexp@4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/xregexp/-/xregexp-4.0.0.tgz#e698189de49dd2a18cc5687b05e17c8e43943020" + +xtend@^4.0.0, xtend@^4.0.1, xtend@~4.0.0, xtend@~4.0.1: version "4.0.1" resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.1.tgz#a5c6d532be656e23db820efb943a1f04998d63af" @@ -9626,15 +10197,23 @@ y18n@^3.2.1: version "3.2.1" resolved "https://registry.yarnpkg.com/y18n/-/y18n-3.2.1.tgz#6d15fba884c08679c0d77e88e7759e811e07fa41" +y18n@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/y18n/-/y18n-4.0.0.tgz#95ef94f85ecc81d007c264e190a120f0a3c8566b" + yallist@^2.1.2: version "2.1.2" resolved "https://registry.yarnpkg.com/yallist/-/yallist-2.1.2.tgz#1c11f9218f076089a47dd512f93c6699a6a81d52" -yargs-parser@^4.2.0: - version "4.2.1" - resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-4.2.1.tgz#29cceac0dc4f03c6c87b4a9f217dd18c9f74871c" +yallist@^3.0.0, yallist@^3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/yallist/-/yallist-3.0.2.tgz#8452b4bb7e83c7c188d8041c1a837c773d6d8bb9" + +yargs-parser@^10.0.0: + version "10.1.0" + resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-10.1.0.tgz#7202265b89f7e9e9f2e5765e0fe735a905edbaa8" dependencies: - camelcase "^3.0.0" + camelcase "^4.1.0" yargs-parser@^5.0.0: version "5.0.0" @@ -9642,39 +10221,32 @@ yargs-parser@^5.0.0: dependencies: camelcase "^3.0.0" -yargs-parser@^7.0.0: - version "7.0.0" - resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-7.0.0.tgz#8d0ac42f16ea55debd332caf4c4038b3e3f5dfd9" - dependencies: - camelcase "^4.1.0" - yargs-parser@^9.0.2: version "9.0.2" resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-9.0.2.tgz#9ccf6a43460fe4ed40a9bb68f48d43b8a68cc077" dependencies: camelcase "^4.1.0" -yargs@6.6.0: - version "6.6.0" - resolved "https://registry.yarnpkg.com/yargs/-/yargs-6.6.0.tgz#782ec21ef403345f830a808ca3d513af56065208" +yargs@11.0.0: + version "11.0.0" + resolved "https://registry.yarnpkg.com/yargs/-/yargs-11.0.0.tgz#c052931006c5eee74610e5fc0354bedfd08a201b" dependencies: - camelcase "^3.0.0" - cliui "^3.2.0" + cliui "^4.0.0" decamelize "^1.1.1" + find-up "^2.1.0" get-caller-file "^1.0.1" - os-locale "^1.4.0" - read-pkg-up "^1.0.1" + os-locale "^2.0.0" require-directory "^2.1.1" require-main-filename "^1.0.1" set-blocking "^2.0.0" - string-width "^1.0.2" - which-module "^1.0.0" + string-width "^2.0.0" + which-module "^2.0.0" y18n "^3.2.1" - yargs-parser "^4.2.0" + yargs-parser "^9.0.2" yargs@^11.0.0: - version "11.0.0" - resolved "https://registry.yarnpkg.com/yargs/-/yargs-11.0.0.tgz#c052931006c5eee74610e5fc0354bedfd08a201b" + version "11.1.0" + resolved "https://registry.yarnpkg.com/yargs/-/yargs-11.1.0.tgz#90b869934ed6e871115ea2ff58b03f4724ed2d77" dependencies: cliui "^4.0.0" decamelize "^1.1.1" @@ -9707,24 +10279,6 @@ yargs@^7.0.0: y18n "^3.2.1" yargs-parser "^5.0.0" -yargs@^8.0.2: - version "8.0.2" - resolved "https://registry.yarnpkg.com/yargs/-/yargs-8.0.2.tgz#6299a9055b1cefc969ff7e79c1d918dceb22c360" - dependencies: - camelcase "^4.1.0" - cliui "^3.2.0" - decamelize "^1.1.1" - get-caller-file "^1.0.1" - os-locale "^2.0.0" - read-pkg-up "^2.0.0" - require-directory "^2.1.1" - require-main-filename "^1.0.1" - set-blocking "^2.0.0" - string-width "^2.0.0" - which-module "^2.0.0" - y18n "^3.2.1" - yargs-parser "^7.0.0" - yargs@~3.10.0: version "3.10.0" resolved "https://registry.yarnpkg.com/yargs/-/yargs-3.10.0.tgz#f7ee7bd857dd7c1d2d38c0e74efbd681d1431fd1" @@ -9748,7 +10302,7 @@ yn@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/yn/-/yn-2.0.0.tgz#e5adabc8acf408f6385fc76495684c88e6af689a" -zip-stream@^1.1.0: +zip-stream@^1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/zip-stream/-/zip-stream-1.2.0.tgz#a8bc45f4c1b49699c6b90198baacaacdbcd4ba04" dependencies: @@ -9757,6 +10311,6 @@ zip-stream@^1.1.0: lodash "^4.8.0" readable-stream "^2.0.0" -zone.js@0.8.20: - version "0.8.20" - resolved "https://registry.yarnpkg.com/zone.js/-/zone.js-0.8.20.tgz#a218c48db09464b19ff6fc8f0d4bb5b1046e185d" +zone.js@^0.8.26: + version "0.8.26" + resolved "https://registry.yarnpkg.com/zone.js/-/zone.js-0.8.26.tgz#7bdd72f7668c5a7ad6b118148b4ea39c59d08d2d" From 535034ec8e87a72200810f3255df2d73765d7711 Mon Sep 17 00:00:00 2001 From: Kristof De Langhe Date: Wed, 29 Aug 2018 12:46:20 +0200 Subject: [PATCH 06/48] Added type docs --- src/app/core/data/browse-items-response-parsing-service.ts | 6 ++++++ src/app/core/data/item-data.service.ts | 6 ++++++ .../browse-entry-list-element.component.ts | 5 +++-- 3 files changed, 15 insertions(+), 2 deletions(-) diff --git a/src/app/core/data/browse-items-response-parsing-service.ts b/src/app/core/data/browse-items-response-parsing-service.ts index 840d59b863..6e3c7b4723 100644 --- a/src/app/core/data/browse-items-response-parsing-service.ts +++ b/src/app/core/data/browse-items-response-parsing-service.ts @@ -30,6 +30,12 @@ export class BrowseItemsResponseParsingService extends BaseResponseParsingServic ) { super(); } + /** + * Parses data from the browse endpoint to a list of DSpaceObjects + * @param {RestRequest} request + * @param {DSpaceRESTV2Response} data + * @returns {RestResponse} + */ parse(request: RestRequest, data: DSpaceRESTV2Response): RestResponse { if (isNotEmpty(data.payload) && isNotEmpty(data.payload._embedded) && Array.isArray(data.payload._embedded[Object.keys(data.payload._embedded)[0]])) { diff --git a/src/app/core/data/item-data.service.ts b/src/app/core/data/item-data.service.ts index e86003f308..f984dceb12 100644 --- a/src/app/core/data/item-data.service.ts +++ b/src/app/core/data/item-data.service.ts @@ -31,6 +31,12 @@ export class ItemDataService extends DataService { super(); } + /** + * Get the endpoint for browsing items + * (When options.sort.field is empty, the default field to browse by will be 'dc.date.issued') + * @param {FindAllOptions} options + * @returns {Observable} + */ public getBrowseEndpoint(options: FindAllOptions = {}): Observable { let field = 'dc.date.issued'; if (options.sort && options.sort.field) { diff --git a/src/app/shared/object-list/browse-entry-list-element/browse-entry-list-element.component.ts b/src/app/shared/object-list/browse-entry-list-element/browse-entry-list-element.component.ts index a5c92e87ae..6581d4c4ae 100644 --- a/src/app/shared/object-list/browse-entry-list-element/browse-entry-list-element.component.ts +++ b/src/app/shared/object-list/browse-entry-list-element/browse-entry-list-element.component.ts @@ -4,8 +4,6 @@ import { AbstractListableElementComponent } from '../../object-collection/shared import { renderElementsFor } from '../../object-collection/shared/dso-element-decorator'; import { ViewMode } from '../../../+search-page/search-options.model'; import { BrowseEntry } from '../../../core/shared/browse-entry.model'; -import { ActivatedRoute, Router } from '@angular/router'; -import { ListableObject } from '../../object-collection/shared/listable-object.model'; @Component({ selector: 'ds-browse-entry-list-element', @@ -13,5 +11,8 @@ import { ListableObject } from '../../object-collection/shared/listable-object.m templateUrl: './browse-entry-list-element.component.html' }) +/** + * This component is automatically used to create a list view for BrowseEntry objects when used in ObjectCollectionComponent + */ @renderElementsFor(BrowseEntry, ViewMode.List) export class BrowseEntryListElementComponent extends AbstractListableElementComponent {} From 777facf5cd2ce3cd65ba7a7403588b5ba285f55f Mon Sep 17 00:00:00 2001 From: lotte Date: Wed, 29 Aug 2018 15:12:01 +0200 Subject: [PATCH 07/48] intermediate commit --- package.json | 5 +- .../collection-page.component.ts | 2 +- .../community-page.component.ts | 13 +- .../collections/collections.component.ts | 6 +- .../full-file-section.component.ts | 5 +- .../full/full-item-page.component.ts | 10 +- .../+item-page/simple/item-page.component.ts | 12 +- .../search-facet-filter.component.ts | 35 ++-- .../search-filter/search-filter.component.ts | 4 +- .../search-filter/search-filter.service.ts | 24 ++- .../search-range-filter.component.ts | 11 +- .../search-filters.component.ts | 32 +-- src/app/+search-page/search-page.component.ts | 8 +- .../search-configuration.service.ts | 55 +++--- .../search-service/search.service.ts | 16 +- .../search-sidebar/search-sidebar.effects.ts | 15 +- .../search-sidebar/search-sidebar.service.ts | 8 +- src/app/app.component.ts | 11 +- src/app/core/auth/auth-request.service.ts | 60 +++--- src/app/core/auth/auth.effects.ts | 185 ++++++++++-------- src/app/core/auth/auth.interceptor.ts | 35 ++-- src/app/core/auth/auth.service.ts | 104 ++++++---- src/app/core/auth/authenticated.guard.ts | 10 +- src/app/core/auth/server-auth.service.ts | 12 +- .../builders/remote-data-build.service.ts | 31 +-- src/app/core/cache/object-cache.effects.ts | 11 +- src/app/core/cache/object-cache.service.ts | 60 +++--- src/app/core/cache/response-cache.effects.ts | 11 +- src/app/core/cache/response-cache.service.ts | 25 ++- src/app/core/config/config.service.ts | 75 +++---- src/app/core/data/comcol-data.service.ts | 50 ++--- src/app/core/data/community-data.service.ts | 12 +- src/app/core/data/data.service.ts | 29 +-- src/app/core/data/item-data.service.ts | 10 +- src/app/core/data/request.effects.ts | 9 +- src/app/core/data/request.service.spec.ts | 32 +-- src/app/core/data/request.service.ts | 65 +++--- .../dspace-rest-v2/dspace-rest-v2.service.ts | 18 +- src/app/core/index/index.effects.ts | 67 ++++--- .../core/integration/integration.service.ts | 44 +++-- src/app/core/metadata/metadata.service.ts | 32 +-- src/app/core/registry/registry.service.ts | 9 +- src/app/core/shared/hal-endpoint.service.ts | 16 +- src/app/core/shared/item.model.ts | 25 +-- src/app/header/header.component.ts | 4 +- src/app/header/header.effects.ts | 15 +- .../auth-nav-menu/auth-nav-menu.component.ts | 30 +-- .../ds-dynamic-form-control.component.ts | 39 ++-- .../ds-dynamic-form.component.ts | 19 +- .../dynamic-group/dynamic-group.components.ts | 13 +- .../models/list/dynamic-list.component.ts | 2 +- .../models/lookup/dynamic-lookup.component.ts | 6 +- .../dynamic-scrollable-dropdown.component.ts | 6 +- .../models/tag/dynamic-tag.component.ts | 40 ++-- .../typeahead/dynamic-typeahead.component.ts | 44 +++-- src/app/shared/form/form.component.ts | 17 +- src/app/shared/form/form.service.ts | 43 ++-- src/app/shared/host-window.service.ts | 23 ++- src/app/shared/log-in/log-in.component.ts | 41 ++-- src/app/shared/log-out/log-out.component.ts | 9 +- .../shared/mocks/mock-host-window-service.ts | 6 +- src/app/shared/mocks/mock-item.ts | 10 +- src/app/shared/mocks/mock-request.service.ts | 4 +- .../mocks/mock-response-cache.service.ts | 6 +- src/app/shared/mocks/mock-translate-loader.ts | 4 +- .../notification/notification.component.ts | 7 +- .../notifications-board.component.ts | 4 +- .../notifications/notifications.effects.ts | 8 +- .../notifications/notifications.service.ts | 19 +- .../object-collection.component.ts | 6 +- .../object-grid/object-grid.component.ts | 10 +- .../shared/pagination/pagination.component.ts | 5 +- src/app/shared/services/api.service.ts | 8 +- src/app/shared/services/route.service.ts | 18 +- src/app/shared/shared.module.ts | 11 +- src/app/shared/testing/active-router-stub.ts | 4 +- .../testing/auth-request-service-stub.ts | 6 +- src/app/shared/testing/auth-service-stub.ts | 15 +- .../shared/testing/authority-service-stub.ts | 4 +- .../testing/hal-endpoint-service-stub.ts | 4 +- .../testing/host-window-service-stub.ts | 4 +- src/app/shared/testing/mock-store.ts | 6 +- .../shared/testing/mock-translate-loader.ts | 4 +- .../testing/notifications-service-stub.ts | 18 +- src/app/shared/testing/search-service-stub.ts | 4 +- .../shared/truncatable/truncatable.service.ts | 17 +- src/app/shared/uploader/uploader.component.ts | 15 +- src/app/shared/utils/debounce.directive.ts | 10 +- src/app/store.effects.ts | 32 +-- .../dspace-server-transfer-state.service.ts | 4 +- yarn.lock | 181 +++++++++-------- 91 files changed, 1150 insertions(+), 964 deletions(-) diff --git a/package.json b/package.json index 47bc7a419c..b3e16e29e8 100644 --- a/package.json +++ b/package.json @@ -109,6 +109,7 @@ "ng2-nouislider": "^1.7.11", "ngx-bootstrap": "^3.0.1", "ngx-infinite-scroll": "6.0.1", + "ngx-moment": "^3.1.0", "ngx-pagination": "3.0.3", "nouislider": "^11.0.0", "pem": "1.12.3", @@ -154,7 +155,7 @@ "css-loader": "0.28.9", "deep-freeze": "0.0.1", "exports-loader": "^0.7.0", - "html-webpack-plugin": "3.2.0", + "html-webpack-plugin": "^4.0.0-alpha", "imports-loader": "0.7.1", "istanbul-instrumenter-loader": "3.0.1", "jasmine-core": "^3.2.1", @@ -188,7 +189,7 @@ "protractor": "^5.3.0", "protractor-istanbul-plugin": "2.0.0", "raw-loader": "0.5.1", - "resolve-url-loader": "2.2.1", + "resolve-url-loader": "^2.3.0", "rimraf": "2.6.2", "rollup": "^0.56.0", "rollup-plugin-commonjs": "^8.3.0", diff --git a/src/app/+collection-page/collection-page.component.ts b/src/app/+collection-page/collection-page.component.ts index 127fd8ce98..59cf83777f 100644 --- a/src/app/+collection-page/collection-page.component.ts +++ b/src/app/+collection-page/collection-page.component.ts @@ -1,6 +1,6 @@ import { ChangeDetectionStrategy, Component, OnDestroy, OnInit } from '@angular/core'; import { ActivatedRoute } from '@angular/router'; -import { Observable , Subscription } from 'rxjs'; +import { Observable, Subscription } from 'rxjs'; import { SortDirection, SortOptions } from '../core/cache/models/sort-options.model'; import { CollectionDataService } from '../core/data/collection-data.service'; import { PaginatedList } from '../core/data/paginated-list'; diff --git a/src/app/+community-page/community-page.component.ts b/src/app/+community-page/community-page.component.ts index 69738733a8..a6e1d5376c 100644 --- a/src/app/+community-page/community-page.component.ts +++ b/src/app/+community-page/community-page.component.ts @@ -1,7 +1,8 @@ +import {mergeMap, filter, map} from 'rxjs/operators'; import { ChangeDetectionStrategy, Component, OnDestroy, OnInit } from '@angular/core'; import { ActivatedRoute } from '@angular/router'; -import { Subscription , Observable } from 'rxjs'; +import { Subscription, Observable } from 'rxjs'; import { CommunityDataService } from '../core/data/community-data.service'; import { RemoteData } from '../core/data/remote-data'; import { Bitstream } from '../core/shared/bitstream.model'; @@ -34,11 +35,11 @@ export class CommunityPageComponent implements OnInit, OnDestroy { } ngOnInit(): void { - this.communityRD$ = this.route.data.pipe((data) => data.community); - this.logoRD$ = this.communityRD$ - .map((rd: RemoteData) => rd.payload) - .filter((community: Community) => hasValue(community)) - .flatMap((community: Community) => community.logo); + this.communityRD$ = this.route.data.pipe(map((data) => data.community)); + this.logoRD$ = this.communityRD$.pipe( + map((rd: RemoteData) => rd.payload), + filter((community: Community) => hasValue(community)), + mergeMap((community: Community) => community.logo)); } ngOnDestroy(): void { diff --git a/src/app/+item-page/field-components/collections/collections.component.ts b/src/app/+item-page/field-components/collections/collections.component.ts index 4665d60caf..b33c5fd41b 100644 --- a/src/app/+item-page/field-components/collections/collections.component.ts +++ b/src/app/+item-page/field-components/collections/collections.component.ts @@ -1,3 +1,5 @@ + +import {map} from 'rxjs/operators'; import { Component, Input, OnInit } from '@angular/core'; import { Observable } from 'rxjs'; @@ -35,11 +37,11 @@ export class CollectionsComponent implements OnInit { // TODO: this should use parents, but the collections // for an Item aren't returned by the REST API yet, // only the owning collection - this.collections = this.item.owner.map((rd: RemoteData) => [rd.payload]); + this.collections = this.item.owner.pipe(map((rd: RemoteData) => [rd.payload])); } hasSucceeded() { - return this.item.owner.map((rd: RemoteData) => rd.hasSucceeded); + return this.item.owner.pipe(map((rd: RemoteData) => rd.hasSucceeded)); } } diff --git a/src/app/+item-page/full/field-components/file-section/full-file-section.component.ts b/src/app/+item-page/full/field-components/file-section/full-file-section.component.ts index 5dc5bfdf6c..db3c30aea2 100644 --- a/src/app/+item-page/full/field-components/file-section/full-file-section.component.ts +++ b/src/app/+item-page/full/field-components/file-section/full-file-section.component.ts @@ -1,5 +1,6 @@ + +import {combineLatest as observableCombineLatest, Observable } from 'rxjs'; import { Component, Input, OnInit } from '@angular/core'; -import { Observable } from 'rxjs'; import { Bitstream } from '../../../../core/shared/bitstream.model'; import { Item } from '../../../../core/shared/item.model'; @@ -33,7 +34,7 @@ export class FullFileSectionComponent extends FileSectionComponent implements On initialize(): void { const originals = this.item.getFiles(); const licenses = this.item.getBitstreamsByBundleName('LICENSE'); - this.bitstreamsObs = Observable.combineLatest(originals, licenses, (o, l) => [...o, ...l]); + this.bitstreamsObs = observableCombineLatest(originals, licenses, (o, l) => [...o, ...l]); this.bitstreamsObs.subscribe( (files) => files.forEach( diff --git a/src/app/+item-page/full/full-item-page.component.ts b/src/app/+item-page/full/full-item-page.component.ts index 4d27b9d8c7..d09ac268ec 100644 --- a/src/app/+item-page/full/full-item-page.component.ts +++ b/src/app/+item-page/full/full-item-page.component.ts @@ -1,3 +1,5 @@ + +import {filter, map} from 'rxjs/operators'; import { ChangeDetectionStrategy, Component, OnInit } from '@angular/core'; import { ActivatedRoute } from '@angular/router'; @@ -41,9 +43,9 @@ export class FullItemPageComponent extends ItemPageComponent implements OnInit { /*** AoT inheritance fix, will hopefully be resolved in the near future **/ ngOnInit(): void { super.ngOnInit(); - this.metadata$ = this.itemRD$ - .map((rd: RemoteData) => rd.payload) - .filter((item: Item) => hasValue(item)) - .map((item: Item) => item.metadata); + this.metadata$ = this.itemRD$.pipe( + map((rd: RemoteData) => rd.payload), + filter((item: Item) => hasValue(item)), + map((item: Item) => item.metadata),); } } diff --git a/src/app/+item-page/simple/item-page.component.ts b/src/app/+item-page/simple/item-page.component.ts index 6f01a30613..35162b011f 100644 --- a/src/app/+item-page/simple/item-page.component.ts +++ b/src/app/+item-page/simple/item-page.component.ts @@ -1,3 +1,5 @@ + +import {mergeMap, filter, map} from 'rxjs/operators'; import { ChangeDetectionStrategy, Component, OnInit } from '@angular/core'; import { ActivatedRoute } from '@angular/router'; @@ -44,11 +46,11 @@ export class ItemPageComponent implements OnInit { } ngOnInit(): void { - this.itemRD$ = this.route.data.map((data) => data.item); + this.itemRD$ = this.route.data.pipe(map((data) => data.item)); this.metadataService.processRemoteData(this.itemRD$); - this.thumbnail$ = this.itemRD$ - .map((rd: RemoteData) => rd.payload) - .filter((item: Item) => hasValue(item)) - .flatMap((item: Item) => item.getThumbnail()); + this.thumbnail$ = this.itemRD$.pipe( + map((rd: RemoteData) => rd.payload), + filter((item: Item) => hasValue(item)), + mergeMap((item: Item) => item.getThumbnail()),); } } diff --git a/src/app/+search-page/search-filters/search-filter/search-facet-filter/search-facet-filter.component.ts b/src/app/+search-page/search-filters/search-filter/search-facet-filter/search-facet-filter.component.ts index 00cf6bdc00..154eb21600 100644 --- a/src/app/+search-page/search-filters/search-filter/search-facet-filter/search-facet-filter.component.ts +++ b/src/app/+search-page/search-filters/search-filter/search-facet-filter/search-facet-filter.component.ts @@ -1,20 +1,19 @@ +import {combineLatest as observableCombineLatest, of as observableOf, BehaviorSubject , Observable , Subject , Subscription } from 'rxjs'; +import {switchMap, distinctUntilChanged, first, map } from 'rxjs/operators'; import { animate, state, style, transition, trigger } from '@angular/animations'; import { Component, Inject, OnDestroy, OnInit } from '@angular/core'; import { Router } from '@angular/router'; -import { BehaviorSubject , Observable , Subject , Subscription } from 'rxjs'; import { RemoteDataBuildService } from '../../../../core/cache/builders/remote-data-build.service'; import { PaginatedList } from '../../../../core/data/paginated-list'; import { RemoteData } from '../../../../core/data/remote-data'; import { hasNoValue, hasValue, isNotEmpty } from '../../../../shared/empty.util'; import { EmphasizePipe } from '../../../../shared/utils/emphasize.pipe'; -import { SearchOptions } from '../../../search-options.model'; import { FacetValue } from '../../../search-service/facet-value.model'; import { SearchFilterConfig } from '../../../search-service/search-filter-config.model'; import { SearchService } from '../../../search-service/search.service'; import { FILTER_CONFIG, SearchFilterService } from '../search-filter.service'; import { SearchConfigurationService } from '../../../search-service/search-configuration.service'; import { getSucceededRemoteData } from '../../../../core/shared/operators'; -import { map } from 'rxjs/operators'; @Component({ selector: 'ds-search-facet-filter', @@ -53,7 +52,7 @@ export class SearchFacetFilterComponent implements OnInit, OnDestroy { /** * Emits the result values for this filter found by the current filter query */ - filterSearchResults: Observable = Observable.of([]); + filterSearchResults: Observable = observableOf([]); /** * Emits the active values for this filter @@ -79,25 +78,25 @@ export class SearchFacetFilterComponent implements OnInit, OnDestroy { */ ngOnInit(): void { this.filterValues$ = new BehaviorSubject(new RemoteData(true, false, undefined, undefined, undefined)); - this.currentPage = this.getCurrentPage().distinctUntilChanged(); + this.currentPage = this.getCurrentPage().pipe(distinctUntilChanged()); this.selectedValues = this.filterService.getSelectedValuesForFilter(this.filterConfig); const searchOptions = this.searchConfigService.searchOptions; this.subs.push(this.searchConfigService.searchOptions.subscribe(() => this.updateFilterValueList())); - const facetValues = Observable.combineLatest(searchOptions, this.currentPage, (options, page) => { + const facetValues = observableCombineLatest(searchOptions, this.currentPage, (options, page) => { return { options, page } - }).switchMap(({ options, page }) => { + }).pipe(switchMap(({ options, page }) => { return this.searchService.getFacetValuesFor(this.filterConfig, page, options) .pipe( getSucceededRemoteData(), map((results) => { return { - values: Observable.of(results), + values: observableOf(results), page: page }; } ) ) - }); + })); let filterValues = []; this.subs.push(facetValues.subscribe((facetOutcome) => { const newValues$ = facetOutcome.values; @@ -117,7 +116,7 @@ export class SearchFacetFilterComponent implements OnInit, OnDestroy { this.animationState = 'ready'; this.filterValues$.next(rd); })); - this.subs.push(newValues$.first().subscribe((rd) => { + this.subs.push(newValues$.pipe(first()).subscribe((rd) => { this.isLastPage$.next(hasNoValue(rd.payload.next)) })); })); @@ -180,7 +179,7 @@ export class SearchFacetFilterComponent implements OnInit, OnDestroy { * @param data The string from the input field */ onSubmit(data: any) { - this.selectedValues.first().subscribe((selectedValues) => { + this.selectedValues.pipe(first()).subscribe((selectedValues) => { if (isNotEmpty(data)) { this.router.navigate([this.getSearchLink()], { queryParams: @@ -189,7 +188,7 @@ export class SearchFacetFilterComponent implements OnInit, OnDestroy { }); this.filter = ''; } - this.filterSearchResults = Observable.of([]); + this.filterSearchResults = observableOf([]); } ) } @@ -211,12 +210,12 @@ export class SearchFacetFilterComponent implements OnInit, OnDestroy { * @returns {Observable} The changed filter parameters */ getRemoveParams(value: string): Observable { - return this.selectedValues.map((selectedValues) => { + return this.selectedValues.pipe(map((selectedValues) => { return { [this.filterConfig.paramName]: selectedValues.filter((v) => v !== value), page: 1 }; - }); + })); } /** @@ -225,12 +224,12 @@ export class SearchFacetFilterComponent implements OnInit, OnDestroy { * @returns {Observable} The changed filter parameters */ getAddParams(value: string): Observable { - return this.selectedValues.map((selectedValues) => { + return this.selectedValues.pipe(map((selectedValues) => { return { [this.filterConfig.paramName]: [...selectedValues, value], page: 1 }; - }); + })); } /** @@ -249,7 +248,7 @@ export class SearchFacetFilterComponent implements OnInit, OnDestroy { */ findSuggestions(data): void { if (isNotEmpty(data)) { - this.searchConfigService.searchOptions.first().subscribe( + this.searchConfigService.searchOptions.pipe(first()).subscribe( (options) => { this.filterSearchResults = this.searchService.getFacetValuesFor(this.filterConfig, 1, options, data.toLowerCase()) .pipe( @@ -264,7 +263,7 @@ export class SearchFacetFilterComponent implements OnInit, OnDestroy { } ) } else { - this.filterSearchResults = Observable.of([]); + this.filterSearchResults = observableOf([]); } } diff --git a/src/app/+search-page/search-filters/search-filter/search-filter.component.ts b/src/app/+search-page/search-filters/search-filter/search-filter.component.ts index 8d20378910..87f8edc1ea 100644 --- a/src/app/+search-page/search-filters/search-filter/search-filter.component.ts +++ b/src/app/+search-page/search-filters/search-filter/search-filter.component.ts @@ -1,3 +1,5 @@ + +import {first} from 'rxjs/operators'; import { Component, Input, OnInit } from '@angular/core'; import { SearchFilterConfig } from '../../search-service/search-filter-config.model'; import { SearchFilterService } from './search-filter.service'; @@ -35,7 +37,7 @@ export class SearchFilterComponent implements OnInit { * Else, the filter should initially be collapsed */ ngOnInit() { - this.getSelectedValues().first().subscribe((isActive) => { + this.getSelectedValues().pipe(first()).subscribe((isActive) => { if (this.filter.isOpenByDefault || isNotEmpty(isActive)) { this.initialExpand(); } else { diff --git a/src/app/+search-page/search-filters/search-filter/search-filter.service.ts b/src/app/+search-page/search-filters/search-filter/search-filter.service.ts index 3f3f14b9e6..35e6558375 100644 --- a/src/app/+search-page/search-filters/search-filter/search-filter.service.ts +++ b/src/app/+search-page/search-filters/search-filter/search-filter.service.ts @@ -1,8 +1,8 @@ +import { combineLatest as observableCombineLatest, Observable } from 'rxjs'; import { Injectable, InjectionToken } from '@angular/core'; import { distinctUntilChanged, map } from 'rxjs/operators'; import { SearchFiltersState, SearchFilterState } from './search-filter.reducer'; -import { createSelector, MemoizedSelector, Store } from '@ngrx/store'; -import { Observable } from 'rxjs'; +import { createSelector, MemoizedSelector, select, Store } from '@ngrx/store'; import { SearchFilterCollapseAction, SearchFilterDecrementPageAction, @@ -63,8 +63,8 @@ export class SearchFilterService { */ getSelectedValuesForFilter(filterConfig: SearchFilterConfig): Observable { const values$ = this.routeService.getQueryParameterValues(filterConfig.paramName); - const prefixValues$ = this.routeService.getQueryParamsWithPrefix(filterConfig.paramName + '.').map((params: Params) => [].concat(...Object.values(params))); - return Observable.combineLatest(values$, prefixValues$, (values, prefixValues) => { + const prefixValues$ = this.routeService.getQueryParamsWithPrefix(filterConfig.paramName + '.').pipe(map((params: Params) => [].concat(...Object.values(params)))); + return observableCombineLatest(values$, prefixValues$, (values, prefixValues) => { if (isNotEmpty(values)) { return values; } @@ -78,14 +78,16 @@ export class SearchFilterService { * @returns {Observable} Emits the current collapsed state of the given filter, if it's unavailable, return false */ isCollapsed(filterName: string): Observable { - return this.store.select(filterByNameSelector(filterName)) - .map((object: SearchFilterState) => { + return this.store.pipe( + select(filterByNameSelector(filterName)), + map((object: SearchFilterState) => { if (object) { return object.filterCollapsed; } else { return false; } - }); + }) + ); } /** @@ -94,14 +96,15 @@ export class SearchFilterService { * @returns {Observable} Emits the current page state of the given filter, if it's unavailable, return 1 */ getPage(filterName: string): Observable { - return this.store.select(filterByNameSelector(filterName)) - .map((object: SearchFilterState) => { + return this.store.pipe( + select(filterByNameSelector(filterName)), + map((object: SearchFilterState) => { if (object) { return object.page; } else { return 1; } - }); + })); } /** @@ -159,6 +162,7 @@ export class SearchFilterService { public incrementPage(filterName: string): void { this.store.dispatch(new SearchFilterIncrementPageAction(filterName)); } + /** * Dispatches a reset page action to the store for a given filter * @param {string} filterName The filter for which the action is dispatched diff --git a/src/app/+search-page/search-filters/search-filter/search-range-filter/search-range-filter.component.ts b/src/app/+search-page/search-filters/search-filter/search-range-filter/search-range-filter.component.ts index 0f3832a226..3c76d4391b 100644 --- a/src/app/+search-page/search-filters/search-filter/search-range-filter/search-range-filter.component.ts +++ b/src/app/+search-page/search-filters/search-filter/search-range-filter/search-range-filter.component.ts @@ -1,3 +1,5 @@ +import {of as observableOf, combineLatest as observableCombineLatest, Observable , Subscription } from 'rxjs'; +import {startWith} from 'rxjs/operators'; import { isPlatformBrowser } from '@angular/common'; import { Component, Inject, OnDestroy, OnInit, PLATFORM_ID } from '@angular/core'; import { RemoteDataBuildService } from '../../../../core/cache/builders/remote-data-build.service'; @@ -12,7 +14,6 @@ import { FILTER_CONFIG, SearchFilterService } from '../search-filter.service'; import { SearchService } from '../../../search-service/search.service'; import { Router } from '@angular/router'; import * as moment from 'moment'; -import { Observable , Subscription } from 'rxjs'; import { RouteService } from '../../../../shared/services/route.service'; import { hasValue } from '../../../../shared/empty.util'; import { SearchConfigurationService } from '../../../search-service/search-configuration.service'; @@ -79,9 +80,9 @@ export class SearchRangeFilterComponent extends SearchFacetFilterComponent imple super.ngOnInit(); this.min = moment(this.filterConfig.minValue, dateFormats).year() || this.min; this.max = moment(this.filterConfig.maxValue, dateFormats).year() || this.max; - const iniMin = this.route.getQueryParameterValue(this.filterConfig.paramName + minSuffix).startWith(undefined); - const iniMax = this.route.getQueryParameterValue(this.filterConfig.paramName + maxSuffix).startWith(undefined); - this.sub = Observable.combineLatest(iniMin, iniMax, (min, max) => { + const iniMin = this.route.getQueryParameterValue(this.filterConfig.paramName + minSuffix).pipe(startWith(undefined)); + const iniMax = this.route.getQueryParameterValue(this.filterConfig.paramName + maxSuffix).pipe(startWith(undefined)); + this.sub = observableCombineLatest(iniMin, iniMax, (min, max) => { const minimum = hasValue(min) ? min : this.min; const maximum = hasValue(max) ? max : this.max; return [minimum, maximum] @@ -97,7 +98,7 @@ export class SearchRangeFilterComponent extends SearchFacetFilterComponent imple const parts = value.split(rangeDelimiter); const min = parts.length > 1 ? parts[0].trim() : value; const max = parts.length > 1 ? parts[1].trim() : value; - return Observable.of( + return observableOf( { [this.filterConfig.paramName + minSuffix]: [min], [this.filterConfig.paramName + maxSuffix]: [max], diff --git a/src/app/+search-page/search-filters/search-filters.component.ts b/src/app/+search-page/search-filters/search-filters.component.ts index f65c3b4b5b..7f1eb513ea 100644 --- a/src/app/+search-page/search-filters/search-filters.component.ts +++ b/src/app/+search-page/search-filters/search-filters.component.ts @@ -1,8 +1,10 @@ +import { Observable, of as observableOf } from 'rxjs'; + +import { filter, map, mergeMap, startWith, switchMap } from 'rxjs/operators'; import { Component } from '@angular/core'; import { SearchService } from '../search-service/search.service'; import { RemoteData } from '../../core/data/remote-data'; import { SearchFilterConfig } from '../search-service/search-filter-config.model'; -import { Observable } from 'rxjs'; import { SearchConfigurationService } from '../search-service/search-configuration.service'; import { isNotEmpty } from '../../shared/empty.util'; import { SearchFilterService } from './search-filter/search-filter.service'; @@ -37,10 +39,10 @@ export class SearchFiltersComponent { */ constructor(private searchService: SearchService, private searchConfigService: SearchConfigurationService, private filterService: SearchFilterService) { this.filters = searchService.getConfig().pipe(getSucceededRemoteData()); - this.clearParams = searchConfigService.getCurrentFrontendFilters().map((filters) => { + this.clearParams = searchConfigService.getCurrentFrontendFilters().pipe(map((filters) => { Object.keys(filters).forEach((f) => filters[f] = null); return filters; - }); + })); } /** @@ -55,23 +57,23 @@ export class SearchFiltersComponent { * @param {SearchFilterConfig} filter The filter to check for * @returns {Observable} Emits true whenever a given filter config should be shown */ - isActive(filter: SearchFilterConfig): Observable { + isActive(filterConfig: SearchFilterConfig): Observable { // console.log(filter.name); - return this.filterService.getSelectedValuesForFilter(filter) - .flatMap((isActive) => { + return this.filterService.getSelectedValuesForFilter(filterConfig).pipe( + mergeMap((isActive) => { if (isNotEmpty(isActive)) { - return Observable.of(true); + return observableOf(true); } else { - return this.searchConfigService.searchOptions - .switchMap((options) => { - return this.searchService.getFacetValuesFor(filter, 1, options) - .filter((RD) => !RD.isLoading) - .map((valuesRD) => { + return this.searchConfigService.searchOptions.pipe( + switchMap((options) => { + return this.searchService.getFacetValuesFor(filterConfig, 1, options).pipe( + filter((RD) => !RD.isLoading), + map((valuesRD) => { return valuesRD.payload.totalElements > 0 - }) + }),) } - ) + )) } - }).startWith(true); + }),startWith(true),); } } diff --git a/src/app/+search-page/search-page.component.ts b/src/app/+search-page/search-page.component.ts index a305193cf6..816e3d67bf 100644 --- a/src/app/+search-page/search-page.component.ts +++ b/src/app/+search-page/search-page.component.ts @@ -1,6 +1,6 @@ import { ChangeDetectionStrategy, Component, OnInit } from '@angular/core'; -import { Observable , Subscription , BehaviorSubject } from 'rxjs'; -import { flatMap, switchMap, } from 'rxjs/operators'; +import { BehaviorSubject, Observable, Subscription } from 'rxjs'; +import { switchMap, } from 'rxjs/operators'; import { PaginatedList } from '../core/data/paginated-list'; import { RemoteData } from '../core/data/remote-data'; import { DSpaceObject } from '../core/shared/dspace-object.model'; @@ -76,8 +76,8 @@ export class SearchPageComponent implements OnInit { */ ngOnInit(): void { this.searchOptions$ = this.searchConfigService.paginatedSearchOptions; - this.sub = this.searchOptions$ - .switchMap((options) => this.service.search(options).pipe(getSucceededRemoteData())) + this.sub = this.searchOptions$.pipe( + switchMap((options) => this.service.search(options).pipe(getSucceededRemoteData()))) .subscribe((results) => { this.resultsRD$.next(results); }); diff --git a/src/app/+search-page/search-service/search-configuration.service.ts b/src/app/+search-page/search-service/search-configuration.service.ts index b509a13274..39389e6065 100644 --- a/src/app/+search-page/search-service/search-configuration.service.ts +++ b/src/app/+search-page/search-service/search-configuration.service.ts @@ -1,7 +1,8 @@ +import {of as observableOf, merge as observableMerge, combineLatest as observableCombineLatest, Observable , BehaviorSubject , Subscription } from 'rxjs'; +import {filter, map} from 'rxjs/operators'; import { SortDirection, SortOptions } from '../../core/cache/models/sort-options.model'; import { PaginationComponentOptions } from '../../shared/pagination/pagination-component-options.model'; import { SearchOptions } from '../search-options.model'; -import { Observable , BehaviorSubject , Subscription } from 'rxjs'; import { ActivatedRoute, Params } from '@angular/router'; import { PaginatedSearchOptions } from '../paginated-search-options.model'; import { Injectable, OnDestroy } from '@angular/core'; @@ -85,27 +86,27 @@ export class SearchConfigurationService implements OnDestroy { * @returns {Observable} Emits the current scope's identifier */ getCurrentScope(defaultScope: string) { - return this.routeService.getQueryParameterValue('scope').map((scope) => { + return this.routeService.getQueryParameterValue('scope').pipe(map((scope) => { return scope || defaultScope; - }); + })); } /** * @returns {Observable} Emits the current query string */ getCurrentQuery(defaultQuery: string) { - return this.routeService.getQueryParameterValue('query').map((query) => { + return this.routeService.getQueryParameterValue('query').pipe(map((query) => { return query || defaultQuery; - }); + })); } /** * @returns {Observable} Emits the current DSpaceObject type as a number */ getCurrentDSOType(): Observable { - return this.routeService.getQueryParameterValue('dsoType') - .filter((type) => hasValue(type) && hasValue(DSpaceObjectType[type.toUpperCase()])) - .map((type) => DSpaceObjectType[type.toUpperCase()]); + return this.routeService.getQueryParameterValue('dsoType').pipe( + filter((type) => hasValue(type) && hasValue(DSpaceObjectType[type.toUpperCase()])), + map((type) => DSpaceObjectType[type.toUpperCase()]),); } /** @@ -114,7 +115,7 @@ export class SearchConfigurationService implements OnDestroy { getCurrentPagination(defaultPagination: PaginationComponentOptions): Observable { const page$ = this.routeService.getQueryParameterValue('page'); const size$ = this.routeService.getQueryParameterValue('pageSize'); - return Observable.combineLatest(page$, size$, (page, size) => { + return observableCombineLatest(page$, size$, (page, size) => { return Object.assign(new PaginationComponentOptions(), defaultPagination, { currentPage: page || defaultPagination.currentPage, pageSize: size || defaultPagination.pageSize @@ -128,7 +129,7 @@ export class SearchConfigurationService implements OnDestroy { getCurrentSort(defaultSort: SortOptions): Observable { const sortDirection$ = this.routeService.getQueryParameterValue('sortDirection'); const sortField$ = this.routeService.getQueryParameterValue('sortField'); - return Observable.combineLatest(sortDirection$, sortField$, (sortDirection, sortField) => { + return observableCombineLatest(sortDirection$, sortField$, (sortDirection, sortField) => { // Dirty fix because sometimes the observable value is null somehow sortField = this.route.snapshot.queryParamMap.get('sortField'); @@ -143,7 +144,7 @@ export class SearchConfigurationService implements OnDestroy { * @returns {Observable} Emits the current active filters with their values as they are sent to the backend */ getCurrentFilters(): Observable { - return this.routeService.getQueryParamsWithPrefix('f.').map((filterParams) => { + return this.routeService.getQueryParamsWithPrefix('f.').pipe(map((filterParams) => { if (isNotEmpty(filterParams)) { const filters = []; Object.keys(filterParams).forEach((key) => { @@ -161,7 +162,7 @@ export class SearchConfigurationService implements OnDestroy { return filters; } return []; - }); + })); } /** @@ -177,7 +178,7 @@ export class SearchConfigurationService implements OnDestroy { * @returns {Subscription} The subscription to unsubscribe from */ subscribeToSearchOptions(defaults: SearchOptions): Subscription { - return Observable.merge( + return observableMerge( this.getScopePart(defaults.scope), this.getQueryPart(defaults.query), this.getDSOTypePart(), @@ -195,7 +196,7 @@ export class SearchConfigurationService implements OnDestroy { * @returns {Subscription} The subscription to unsubscribe from */ subscribeToPaginatedSearchOptions(defaults: PaginatedSearchOptions): Subscription { - return Observable.merge( + return observableMerge( this.getPaginationPart(defaults.pagination), this.getSortPart(defaults.sort), this.getScopePart(defaults.scope), @@ -220,7 +221,7 @@ export class SearchConfigurationService implements OnDestroy { scope: this.defaultScope, query: this.defaultQuery }); - this._defaults = Observable.of(new RemoteData(false, false, true, null, options)); + this._defaults = observableOf(new RemoteData(false, false, true, null, options)); } return this._defaults; } @@ -238,53 +239,53 @@ export class SearchConfigurationService implements OnDestroy { * @returns {Observable} Emits the current scope's identifier */ private getScopePart(defaultScope: string): Observable { - return this.getCurrentScope(defaultScope).map((scope) => { + return this.getCurrentScope(defaultScope).pipe(map((scope) => { return { scope } - }); + })); } /** * @returns {Observable} Emits the current query string as a partial SearchOptions object */ private getQueryPart(defaultQuery: string): Observable { - return this.getCurrentQuery(defaultQuery).map((query) => { + return this.getCurrentQuery(defaultQuery).pipe(map((query) => { return { query } - }); + })); } /** * @returns {Observable} Emits the current query string as a partial SearchOptions object */ private getDSOTypePart(): Observable { - return this.getCurrentDSOType().map((dsoType) => { + return this.getCurrentDSOType().pipe(map((dsoType) => { return { dsoType } - }); + })); } /** * @returns {Observable} Emits the current pagination settings as a partial SearchOptions object */ private getPaginationPart(defaultPagination: PaginationComponentOptions): Observable { - return this.getCurrentPagination(defaultPagination).map((pagination) => { + return this.getCurrentPagination(defaultPagination).pipe(map((pagination) => { return { pagination } - }); + })); } /** * @returns {Observable} Emits the current sorting settings as a partial SearchOptions object */ private getSortPart(defaultSort: SortOptions): Observable { - return this.getCurrentSort(defaultSort).map((sort) => { + return this.getCurrentSort(defaultSort).pipe(map((sort) => { return { sort } - }); + })); } /** * @returns {Observable} Emits the current active filters as a partial SearchOptions object */ private getFiltersPart(): Observable { - return this.getCurrentFilters().map((filters) => { + return this.getCurrentFilters().pipe(map((filters) => { return { filters } - }); + })); } } diff --git a/src/app/+search-page/search-service/search.service.ts b/src/app/+search-page/search-service/search.service.ts index 0d30c7f458..12ab6124c1 100644 --- a/src/app/+search-page/search-service/search.service.ts +++ b/src/app/+search-page/search-service/search.service.ts @@ -1,3 +1,4 @@ +import {of as observableOf, combineLatest as observableCombineLatest, Observable } from 'rxjs'; import { Injectable, OnDestroy } from '@angular/core'; import { ActivatedRoute, @@ -6,7 +7,6 @@ import { Router, UrlSegmentGroup } from '@angular/router'; -import { Observable } from 'rxjs'; import { flatMap, map, switchMap } from 'rxjs/operators'; import { RemoteDataBuildService } from '../../core/cache/builders/remote-data-build.service'; import { @@ -122,7 +122,7 @@ export class SearchService implements OnDestroy { ); // Create search results again with the correct dso objects linked to each result - const tDomainListObs = Observable.combineLatest(sqrObs, dsoObs, (sqr: SearchQueryResponse, dsos: RemoteData) => { + const tDomainListObs = observableCombineLatest(sqrObs, dsoObs, (sqr: SearchQueryResponse, dsos: RemoteData) => { return sqr.objects.map((object: NormalizedSearchResult, index: number) => { let co = DSpaceObject; @@ -143,7 +143,7 @@ export class SearchService implements OnDestroy { map((response: FacetValueSuccessResponse) => response.pageInfo) ); - const payloadObs = Observable.combineLatest(tDomainListObs, pageInfoObs, (tDomainList, pageInfo) => { + const payloadObs = observableCombineLatest(tDomainListObs, pageInfoObs, (tDomainList, pageInfo) => { return new PaginatedList(pageInfo, tDomainList); }); @@ -244,7 +244,7 @@ export class SearchService implements OnDestroy { map((response: FacetValueSuccessResponse) => response.pageInfo) ); - const payloadObs = Observable.combineLatest(facetValueObs, pageInfoObs, (facetValue, pageInfo) => { + const payloadObs = observableCombineLatest(facetValueObs, pageInfoObs, (facetValue, pageInfo) => { return new PaginatedList(pageInfo, facetValue); }); @@ -272,12 +272,12 @@ export class SearchService implements OnDestroy { switchMap((dsoRD: RemoteData) => { if (dsoRD.payload.type === ResourceType.Community) { const community: Community = dsoRD.payload as Community; - return Observable.combineLatest(community.subcommunities, community.collections, (subCommunities, collections) => { + return observableCombineLatest(community.subcommunities, community.collections, (subCommunities, collections) => { /*if this is a community, we also need to show the direct children*/ return [community, ...subCommunities.payload.page, ...collections.payload.page] }) } else { - return Observable.of([dsoRD.payload]); + return observableOf([dsoRD.payload]); } } )); @@ -291,13 +291,13 @@ export class SearchService implements OnDestroy { * @returns {Observable} The current view mode */ getViewMode(): Observable { - return this.route.queryParams.map((params) => { + return this.route.queryParams.pipe(map((params) => { if (isNotEmpty(params.view) && hasValue(params.view)) { return params.view; } else { return ViewMode.List; } - }); + })); } /** diff --git a/src/app/+search-page/search-sidebar/search-sidebar.effects.ts b/src/app/+search-page/search-sidebar/search-sidebar.effects.ts index 758ef2320b..1f5fb0ef60 100644 --- a/src/app/+search-page/search-sidebar/search-sidebar.effects.ts +++ b/src/app/+search-page/search-sidebar/search-sidebar.effects.ts @@ -1,5 +1,6 @@ +import { map, tap, filter } from 'rxjs/operators'; import { Injectable } from '@angular/core'; -import { Effect, Actions } from '@ngrx/effects' +import { Effect, Actions, ofType } from '@ngrx/effects' import * as fromRouter from '@ngrx/router-store'; import { SearchSidebarCollapseAction } from './search-sidebar.actions'; @@ -12,10 +13,14 @@ import { URLBaser } from '../../core/url-baser/url-baser'; export class SearchSidebarEffects { private previousPath: string; @Effect() routeChange$ = this.actions$ - .ofType(fromRouter.ROUTER_NAVIGATION) - .filter((action) => this.previousPath !== this.getBaseUrl(action)) - .do((action) => {this.previousPath = this.getBaseUrl(action)}) - .map(() => new SearchSidebarCollapseAction()); + .pipe( + ofType(fromRouter.ROUTER_NAVIGATION), + filter((action) => this.previousPath !== this.getBaseUrl(action)), + tap((action) => { + this.previousPath = this.getBaseUrl(action) + }), + map(() => new SearchSidebarCollapseAction()) + ); constructor(private actions$: Actions) { diff --git a/src/app/+search-page/search-sidebar/search-sidebar.service.ts b/src/app/+search-page/search-sidebar/search-sidebar.service.ts index c9a7fb57c0..d74fe66348 100644 --- a/src/app/+search-page/search-sidebar/search-sidebar.service.ts +++ b/src/app/+search-page/search-sidebar/search-sidebar.service.ts @@ -1,8 +1,8 @@ +import { combineLatest as observableCombineLatest, Observable } from 'rxjs'; import { Injectable } from '@angular/core'; import { SearchSidebarState } from './search-sidebar.reducer'; -import { createSelector, Store } from '@ngrx/store'; +import { createSelector, select, Store } from '@ngrx/store'; import { SearchSidebarCollapseAction, SearchSidebarExpandAction } from './search-sidebar.actions'; -import { Observable } from 'rxjs'; import { AppState } from '../../app.reducer'; import { HostWindowService } from '../../shared/host-window.service'; @@ -26,7 +26,7 @@ export class SearchSidebarService { constructor(private store: Store, private windowService: HostWindowService) { this.isXsOrSm$ = this.windowService.isXsOrSm(); - this.isCollapsedInStore = this.store.select(sidebarCollapsedSelector); + this.isCollapsedInStore = this.store.pipe(select(sidebarCollapsedSelector)); } /** @@ -34,7 +34,7 @@ export class SearchSidebarService { * @returns {Observable} Emits true if the user's screen size is mobile or when the state in the store is currently collapsed */ get isCollapsed(): Observable { - return Observable.combineLatest( + return observableCombineLatest( this.isXsOrSm$, this.isCollapsedInStore, (mobile, store) => mobile ? store : true); diff --git a/src/app/app.component.ts b/src/app/app.component.ts index 092c61bdf9..7d4bfe4f33 100644 --- a/src/app/app.component.ts +++ b/src/app/app.component.ts @@ -1,3 +1,4 @@ +import { filter, first, take } from 'rxjs/operators'; import { AfterViewInit, ChangeDetectionStrategy, @@ -9,7 +10,7 @@ import { } from '@angular/core'; import { NavigationCancel, NavigationEnd, NavigationStart, Router } from '@angular/router'; -import { Store } from '@ngrx/store'; +import { select, Store } from '@ngrx/store'; import { TranslateService } from '@ngx-translate/core'; @@ -62,10 +63,10 @@ export class AppComponent implements OnInit, AfterViewInit { this.dispatchWindowSize(this._window.nativeWindow.innerWidth, this._window.nativeWindow.innerHeight); // Whether is not authenticathed try to retrieve a possible stored auth token - this.store.select(isAuthenticated) - .take(1) - .filter((authenticated) => !authenticated) - .subscribe((authenticated) => this.authService.checkAuthenticationToken()); + this.store.pipe(select(isAuthenticated), + first(), + filter((authenticated) => !authenticated) + ).subscribe((authenticated) => this.authService.checkAuthenticationToken()); } diff --git a/src/app/core/auth/auth-request.service.ts b/src/app/core/auth/auth-request.service.ts index 8204f02556..92af4644c6 100644 --- a/src/app/core/auth/auth-request.service.ts +++ b/src/app/core/auth/auth-request.service.ts @@ -1,4 +1,6 @@ -import { Observable, throwError as observableThrowError } from 'rxjs'; +import { Observable, of as observableOf, throwError as observableThrowError } from 'rxjs'; + +import { distinctUntilChanged, filter, map, mergeMap, tap } from 'rxjs/operators'; import { Inject, Injectable } from '@angular/core'; import { HALEndpointService } from '../shared/hal-endpoint.service'; import { ResponseCacheService } from '../cache/response-cache.service'; @@ -8,7 +10,7 @@ import { GlobalConfig } from '../../../config/global-config.interface'; import { isNotEmpty } from '../../shared/empty.util'; import { AuthGetRequest, AuthPostRequest, PostRequest, RestRequest } from '../data/request.models'; import { ResponseCacheEntry } from '../cache/response-cache.reducer'; -import { AuthStatusResponse, ErrorResponse, RestResponse } from '../cache/response-cache.models'; +import { AuthStatusResponse, ErrorResponse } from '../cache/response-cache.models'; import { HttpOptions } from '../dspace-rest-v2/dspace-rest-v2.service'; @Injectable() @@ -23,18 +25,18 @@ export class AuthRequestService { } protected fetchRequest(request: RestRequest): Observable { - const [successResponse, errorResponse] = this.responseCache.get(request.href) - .map((entry: ResponseCacheEntry) => entry.response) + return this.responseCache.get(request.href).pipe( + map((entry: ResponseCacheEntry) => entry.response), // TODO to review when https://github.com/DSpace/dspace-angular/issues/217 will be fixed - .do(() => this.responseCache.remove(request.href)) - .partition((response: RestResponse) => response.isSuccessful); - return Observable.merge( - errorResponse.flatMap((response: ErrorResponse) => - observableThrowError(new Error(response.errorMessage))), - successResponse - .filter((response: AuthStatusResponse) => isNotEmpty(response)) - .map((response: AuthStatusResponse) => response.response) - .distinctUntilChanged()); + tap(() => this.responseCache.remove(request.href)), + mergeMap((response) => { + if (response.isSuccessful && isNotEmpty(response)) { + return observableOf((response as AuthStatusResponse).response); + } else if (!response.isSuccessful) { + return observableThrowError(new Error((response as ErrorResponse).errorMessage)); + } + }) + ); } protected getEndpointByMethod(endpoint: string, method: string): string { @@ -42,24 +44,24 @@ export class AuthRequestService { } public postToEndpoint(method: string, body: any, options?: HttpOptions): Observable { - return this.halService.getEndpoint(this.linkName) - .filter((href: string) => isNotEmpty(href)) - .map((endpointURL) => this.getEndpointByMethod(endpointURL, method)) - .distinctUntilChanged() - .map((endpointURL: string) => new AuthPostRequest(this.requestService.generateRequestId(), endpointURL, body, options)) - .do((request: PostRequest) => this.requestService.configure(request, true)) - .flatMap((request: PostRequest) => this.fetchRequest(request)) - .distinctUntilChanged(); + return this.halService.getEndpoint(this.linkName).pipe( + filter((href: string) => isNotEmpty(href)), + map((endpointURL) => this.getEndpointByMethod(endpointURL, method)), + distinctUntilChanged(), + map((endpointURL: string) => new AuthPostRequest(this.requestService.generateRequestId(), endpointURL, body, options)), + tap((request: PostRequest) => this.requestService.configure(request, true)), + mergeMap((request: PostRequest) => this.fetchRequest(request)), + distinctUntilChanged()); } public getRequest(method: string, options?: HttpOptions): Observable { - return this.halService.getEndpoint(this.linkName) - .filter((href: string) => isNotEmpty(href)) - .map((endpointURL) => this.getEndpointByMethod(endpointURL, method)) - .distinctUntilChanged() - .map((endpointURL: string) => new AuthGetRequest(this.requestService.generateRequestId(), endpointURL, options)) - .do((request: PostRequest) => this.requestService.configure(request, true)) - .flatMap((request: PostRequest) => this.fetchRequest(request)) - .distinctUntilChanged(); + return this.halService.getEndpoint(this.linkName).pipe( + filter((href: string) => isNotEmpty(href)), + map((endpointURL) => this.getEndpointByMethod(endpointURL, method)), + distinctUntilChanged(), + map((endpointURL: string) => new AuthGetRequest(this.requestService.generateRequestId(), endpointURL, options)), + tap((request: PostRequest) => this.requestService.configure(request, true)), + mergeMap((request: PostRequest) => this.fetchRequest(request)), + distinctUntilChanged()); } } diff --git a/src/app/core/auth/auth.effects.ts b/src/app/core/auth/auth.effects.ts index 223100056b..785fee84eb 100644 --- a/src/app/core/auth/auth.effects.ts +++ b/src/app/core/auth/auth.effects.ts @@ -1,11 +1,11 @@ +import { of as observableOf, Observable } from 'rxjs'; + +import { filter, debounceTime, switchMap, take, tap, catchError, map, first } from 'rxjs/operators'; import { Injectable } from '@angular/core'; // import @ngrx -import { Actions, Effect } from '@ngrx/effects'; -import { Action, Store } from '@ngrx/store'; - -// import rxjs -import { Observable } from 'rxjs'; +import { Actions, Effect, ofType } from '@ngrx/effects'; +import { Action, select, Store } from '@ngrx/store'; // import services import { AuthService } from './auth.service'; @@ -43,112 +43,131 @@ export class AuthEffects { * @method authenticate */ @Effect() - public authenticate$: Observable = this.actions$ - .ofType(AuthActionTypes.AUTHENTICATE) - .switchMap((action: AuthenticateAction) => { - return this.authService.authenticate(action.payload.email, action.payload.password) - .first() - .map((response: AuthStatus) => new AuthenticationSuccessAction(response.token)) - .catch((error) => Observable.of(new AuthenticationErrorAction(error))); - }); + public authenticate$: Observable = this.actions$.pipe( + ofType(AuthActionTypes.AUTHENTICATE), + switchMap((action: AuthenticateAction) => { + return this.authService.authenticate(action.payload.email, action.payload.password).pipe( + first(), + map((response: AuthStatus) => new AuthenticationSuccessAction(response.token)), + catchError((error) => observableOf(new AuthenticationErrorAction(error))) + ); + }) + ); @Effect() - public authenticateSuccess$: Observable = this.actions$ - .ofType(AuthActionTypes.AUTHENTICATE_SUCCESS) - .do((action: AuthenticationSuccessAction) => this.authService.storeToken(action.payload)) - .map((action: AuthenticationSuccessAction) => new AuthenticatedAction(action.payload)); + public authenticateSuccess$: Observable = this.actions$.pipe( + ofType(AuthActionTypes.AUTHENTICATE_SUCCESS), + tap((action: AuthenticationSuccessAction) => this.authService.storeToken(action.payload)), + map((action: AuthenticationSuccessAction) => new AuthenticatedAction(action.payload)) + ); @Effect() - public authenticated$: Observable = this.actions$ - .ofType(AuthActionTypes.AUTHENTICATED) - .switchMap((action: AuthenticatedAction) => { - return this.authService.authenticatedUser(action.payload) - .map((user: Eperson) => new AuthenticatedSuccessAction((user !== null), action.payload, user)) - .catch((error) => Observable.of(new AuthenticatedErrorAction(error))); - }); + public authenticated$: Observable = this.actions$.pipe( + ofType(AuthActionTypes.AUTHENTICATED), + switchMap((action: AuthenticatedAction) => { + return this.authService.authenticatedUser(action.payload).pipe( + map((user: Eperson) => new AuthenticatedSuccessAction((user !== null), action.payload, user)), + catchError((error) => observableOf(new AuthenticatedErrorAction(error))),); + }) + ); // It means "reacts to this action but don't send another" - @Effect({dispatch: false}) - public authenticatedError$: Observable = this.actions$ - .ofType(AuthActionTypes.AUTHENTICATED_ERROR) - .do((action: LogOutSuccessAction) => this.authService.removeToken()); + @Effect({ dispatch: false }) + public authenticatedError$: Observable = this.actions$.pipe( + ofType(AuthActionTypes.AUTHENTICATED_ERROR), + tap((action: LogOutSuccessAction) => this.authService.removeToken()) + ); @Effect() - public checkToken$: Observable = this.actions$ - .ofType(AuthActionTypes.CHECK_AUTHENTICATION_TOKEN) - .switchMap(() => { - return this.authService.hasValidAuthenticationToken() - .map((token: AuthTokenInfo) => new AuthenticatedAction(token)) - .catch((error) => Observable.of(new CheckAuthenticationTokenErrorAction())); - }); + public checkToken$: Observable = this.actions$.pipe(ofType(AuthActionTypes.CHECK_AUTHENTICATION_TOKEN), + switchMap(() => { + return this.authService.hasValidAuthenticationToken().pipe( + map((token: AuthTokenInfo) => new AuthenticatedAction(token)), + catchError((error) => observableOf(new CheckAuthenticationTokenErrorAction())) + ); + }) + ); @Effect() - public createUser$: Observable = this.actions$ - .ofType(AuthActionTypes.REGISTRATION) - .debounceTime(500) // to remove when functionality is implemented - .switchMap((action: RegistrationAction) => { - return this.authService.create(action.payload) - .map((user: Eperson) => new RegistrationSuccessAction(user)) - .catch((error) => Observable.of(new RegistrationErrorAction(error))); - }); + public createUser$: Observable = this.actions$.pipe( + ofType(AuthActionTypes.REGISTRATION), + debounceTime(500), // to remove when functionality is implemented + switchMap((action: RegistrationAction) => { + return this.authService.create(action.payload).pipe( + map((user: Eperson) => new RegistrationSuccessAction(user)), + catchError((error) => observableOf(new RegistrationErrorAction(error))) + ); + }) + ); @Effect() - public refreshToken$: Observable = this.actions$ - .ofType(AuthActionTypes.REFRESH_TOKEN) - .switchMap((action: RefreshTokenAction) => { - return this.authService.refreshAuthenticationToken(action.payload) - .map((token: AuthTokenInfo) => new RefreshTokenSuccessAction(token)) - .catch((error) => Observable.of(new RefreshTokenErrorAction())); - }); + public refreshToken$: Observable = this.actions$.pipe(ofType(AuthActionTypes.REFRESH_TOKEN), + switchMap((action: RefreshTokenAction) => { + return this.authService.refreshAuthenticationToken(action.payload).pipe( + map((token: AuthTokenInfo) => new RefreshTokenSuccessAction(token)), + catchError((error) => observableOf(new RefreshTokenErrorAction())) + ); + }) + ); // It means "reacts to this action but don't send another" - @Effect({dispatch: false}) - public refreshTokenSuccess$: Observable = this.actions$ - .ofType(AuthActionTypes.REFRESH_TOKEN_SUCCESS) - .do((action: RefreshTokenSuccessAction) => this.authService.replaceToken(action.payload)); + @Effect({ dispatch: false }) + public refreshTokenSuccess$: Observable = this.actions$.pipe( + ofType(AuthActionTypes.REFRESH_TOKEN_SUCCESS), + tap((action: RefreshTokenSuccessAction) => this.authService.replaceToken(action.payload)) + ); /** * When the store is rehydrated in the browser, * clear a possible invalid token or authentication errors */ - @Effect({dispatch: false}) - public clearInvalidTokenOnRehydrate$: Observable = this.actions$ - .ofType(StoreActionTypes.REHYDRATE) - .switchMap(() => { - return this.store.select(isAuthenticated) - .take(1) - .filter((authenticated) => !authenticated) - .do(() => this.authService.removeToken()) - .do(() => this.authService.resetAuthenticationError()); - }); + @Effect({ dispatch: false }) + public clearInvalidTokenOnRehydrate$: Observable = this.actions$.pipe( + ofType(StoreActionTypes.REHYDRATE), + switchMap(() => { + return this.store.pipe( + select(isAuthenticated), + first(), + filter((authenticated) => !authenticated), + tap(() => this.authService.removeToken()), + tap(() => this.authService.resetAuthenticationError()) + ); + })); @Effect() public logOut$: Observable = this.actions$ - .ofType(AuthActionTypes.LOG_OUT) - .switchMap(() => { - return this.authService.logout() - .map((value) => new LogOutSuccessAction()) - .catch((error) => Observable.of(new LogOutErrorAction(error))); - }); + .pipe( + ofType(AuthActionTypes.LOG_OUT), + switchMap(() => { + return this.authService.logout().pipe( + map((value) => new LogOutSuccessAction()), + catchError((error) => observableOf(new LogOutErrorAction(error))) + ); + }) + ); - @Effect({dispatch: false}) + @Effect({ dispatch: false }) public logOutSuccess$: Observable = this.actions$ - .ofType(AuthActionTypes.LOG_OUT_SUCCESS) - .do(() => this.authService.removeToken()) - .do(() => this.authService.clearRedirectUrl()) - .do(() => this.authService.refreshAfterLogout()); + .pipe(ofType(AuthActionTypes.LOG_OUT_SUCCESS), + tap(() => this.authService.removeToken()), + tap(() => this.authService.clearRedirectUrl()), + tap(() => this.authService.refreshAfterLogout()) + ); - @Effect({dispatch: false}) + @Effect({ dispatch: false }) public redirectToLogin$: Observable = this.actions$ - .ofType(AuthActionTypes.REDIRECT_AUTHENTICATION_REQUIRED) - .do(() => this.authService.removeToken()) - .do(() => this.authService.redirectToLogin()); + .pipe(ofType(AuthActionTypes.REDIRECT_AUTHENTICATION_REQUIRED), + tap(() => this.authService.removeToken()), + tap(() => this.authService.redirectToLogin()) + ); - @Effect({dispatch: false}) + @Effect({ dispatch: false }) public redirectToLoginTokenExpired$: Observable = this.actions$ - .ofType(AuthActionTypes.REDIRECT_TOKEN_EXPIRED) - .do(() => this.authService.removeToken()) - .do(() => this.authService.redirectToLoginWhenTokenExpired()); + .pipe( + ofType(AuthActionTypes.REDIRECT_TOKEN_EXPIRED), + tap(() => this.authService.removeToken()), + tap(() => this.authService.redirectToLoginWhenTokenExpired()) + ); /** * @constructor diff --git a/src/app/core/auth/auth.interceptor.ts b/src/app/core/auth/auth.interceptor.ts index 95a93fa0c7..dc751ce19f 100644 --- a/src/app/core/auth/auth.interceptor.ts +++ b/src/app/core/auth/auth.interceptor.ts @@ -1,10 +1,20 @@ +import { of as observableOf, throwError as observableThrowError } from 'rxjs'; -import {throwError as observableThrowError, Observable } from 'rxjs'; +import { catchError, filter, map } from 'rxjs/operators'; import { Injectable, Injector } from '@angular/core'; import { - HttpEvent, HttpInterceptor, HttpHandler, HttpRequest, HttpResponse, - HttpErrorResponse, HttpResponseBase + HttpErrorResponse, + HttpEvent, + HttpHandler, + HttpInterceptor, + HttpRequest, + HttpResponse, + HttpResponseBase } from '@angular/common/http'; + +import { Observable } from 'rxjs'; + + import { find } from 'lodash'; import { AppState } from '../../app.reducer'; @@ -76,11 +86,11 @@ export class AuthInterceptor implements HttpInterceptor { // The access token is expired // Redirect to the login route this.store.dispatch(new RedirectWhenTokenExpiredAction('auth.messages.expired')); - return Observable.of(null); + return observableOf(null); } else if (!this.isAuthRequest(req) && isNotEmpty(token)) { // Intercept a request that is not to the authentication endpoint - authService.isTokenExpiring() - .filter((isExpiring) => isExpiring) + authService.isTokenExpiring().pipe( + filter((isExpiring) => isExpiring)) .subscribe(() => { // If the current request url is already in the refresh token request list, skip it if (isUndefined(find(this.refreshTokenRequestUrls, req.url))) { @@ -98,8 +108,8 @@ export class AuthInterceptor implements HttpInterceptor { } // Pass on the new request instead of the original request. - return next.handle(newReq) - .map((response) => { + return next.handle(newReq).pipe( + map((response) => { // Intercept a Login/Logout response if (response instanceof HttpResponse && this.isSuccess(response) && (this.isLoginResponse(response) || this.isLogoutResponse(response))) { // It's a success Login/Logout response @@ -119,8 +129,8 @@ export class AuthInterceptor implements HttpInterceptor { } else { return response; } - }) - .catch((error, caught) => { + }), + catchError((error, caught) => { // Intercept an error response if (error instanceof HttpErrorResponse) { // Checks if is a response from a request to an authentication endpoint @@ -135,7 +145,7 @@ export class AuthInterceptor implements HttpInterceptor { statusText: error.statusText, url: error.url }); - return Observable.of(authResponse); + return observableOf(authResponse); } else if (this.isUnauthorized(error)) { // The access token provided is expired, revoked, malformed, or invalid for other reasons // Redirect to the login route @@ -144,7 +154,6 @@ export class AuthInterceptor implements HttpInterceptor { } // Return error response as is. return observableThrowError(error); - }) as any; - + })) as any; } } diff --git a/src/app/core/auth/auth.service.ts b/src/app/core/auth/auth.service.ts index ff1e0df0be..5ed2483bce 100644 --- a/src/app/core/auth/auth.service.ts +++ b/src/app/core/auth/auth.service.ts @@ -1,13 +1,21 @@ +import { of as observableOf, Observable } from 'rxjs'; +import { + take, + filter, + startWith, + first, + distinctUntilChanged, + map, + withLatestFrom +} from 'rxjs/operators'; import { Inject, Injectable } from '@angular/core'; import { PRIMARY_OUTLET, Router, UrlSegmentGroup, UrlTree } from '@angular/router'; import { HttpHeaders } from '@angular/common/http'; import { REQUEST } from '@nguniversal/express-engine/tokens'; import { RouterReducerState } from '@ngrx/router-store'; -import { Store } from '@ngrx/store'; +import { select, Store } from '@ngrx/store'; import { CookieAttributes } from 'js-cookie'; -import { Observable } from 'rxjs'; -import { map, withLatestFrom } from 'rxjs/operators'; import { Eperson } from '../eperson/models/eperson.model'; import { AuthRequestService } from './auth-request.service'; @@ -17,7 +25,12 @@ import { AuthStatus } from './models/auth-status.model'; import { AuthTokenInfo, TOKENITEM } from './models/auth-token-info.model'; import { isEmpty, isNotEmpty, isNotNull, isNotUndefined } from '../../shared/empty.util'; import { CookieService } from '../../shared/services/cookie.service'; -import { getAuthenticationToken, getRedirectUrl, isAuthenticated, isTokenRefreshing } from './selectors'; +import { + getAuthenticationToken, + getRedirectUrl, + isAuthenticated, + isTokenRefreshing +} from './selectors'; import { AppState, routerStateSelector } from '../../app.reducer'; import { ResetAuthenticationMessagesAction, SetRedirectUrlAction } from './auth.actions'; import { NativeWindowRef, NativeWindowService } from '../../shared/services/window.service'; @@ -46,21 +59,24 @@ export class AuthService { protected router: Router, protected storage: CookieService, protected store: Store) { - this.store.select(isAuthenticated) - .startWith(false) - .subscribe((authenticated: boolean) => this._authenticated = authenticated); + this.store.pipe( + select(isAuthenticated), + startWith(false) + ).subscribe((authenticated: boolean) => this._authenticated = authenticated); // If current route is different from the one setted in authentication guard // and is not the login route, clear redirect url and messages - const routeUrl$ = this.store.select(routerStateSelector) - .filter((routerState: RouterReducerState) => isNotUndefined(routerState) && isNotUndefined(routerState.state)) - .filter((routerState: RouterReducerState) => !this.isLoginRoute(routerState.state.url)) - .map((routerState: RouterReducerState) => routerState.state.url); - const redirectUrl$ = this.store.select(getRedirectUrl).distinctUntilChanged(); + const routeUrl$ = this.store.pipe( + select(routerStateSelector), + filter((routerState: RouterReducerState) => isNotUndefined(routerState) && isNotUndefined(routerState.state)), + filter((routerState: RouterReducerState) => !this.isLoginRoute(routerState.state.url)), + map((routerState: RouterReducerState) => routerState.state.url) + ); + const redirectUrl$ = this.store.pipe(select(getRedirectUrl), distinctUntilChanged()); routeUrl$.pipe( withLatestFrom(redirectUrl$), map(([routeUrl, redirectUrl]) => [routeUrl, redirectUrl]) - ).filter(([routeUrl, redirectUrl]) => isNotEmpty(redirectUrl) && (routeUrl !== redirectUrl)) + ).pipe(filter(([routeUrl, redirectUrl]) => isNotEmpty(redirectUrl) && (routeUrl !== redirectUrl))) .subscribe(() => { this.clearRedirectUrl(); }); @@ -93,14 +109,14 @@ export class AuthService { let headers = new HttpHeaders(); headers = headers.append('Content-Type', 'application/x-www-form-urlencoded'); options.headers = headers; - return this.authRequestService.postToEndpoint('login', body, options) - .map((status: AuthStatus) => { + return this.authRequestService.postToEndpoint('login', body, options).pipe( + map((status: AuthStatus) => { if (status.authenticated) { return status; } else { throw(new Error('Invalid email or password')); } - }) + })) } @@ -109,7 +125,7 @@ export class AuthService { * @returns {Observable} */ public isAuthenticated(): Observable { - return this.store.select(isAuthenticated); + return this.store.pipe(select(isAuthenticated)); } /** @@ -123,14 +139,14 @@ export class AuthService { headers = headers.append('Accept', 'application/json'); headers = headers.append('Authorization', `Bearer ${token.accessToken}`); options.headers = headers; - return this.authRequestService.getRequest('status', options) - .map((status: AuthStatus) => { + return this.authRequestService.getRequest('status', options).pipe( + map((status: AuthStatus) => { if (status.authenticated) { return status.eperson[0]; } else { throw(new Error('Not authenticated')); } - }); + })); } /** @@ -144,9 +160,10 @@ export class AuthService { * Checks if token is present into storage and is not expired */ public hasValidAuthenticationToken(): Observable { - return this.store.select(getAuthenticationToken) - .take(1) - .map((authTokenInfo: AuthTokenInfo) => { + return this.store.pipe( + select(getAuthenticationToken), + take(1), + map((authTokenInfo: AuthTokenInfo) => { let token: AuthTokenInfo; // Retrieve authentication token info and check if is valid token = isNotEmpty(authTokenInfo) ? authTokenInfo : this.storage.get(TOKENITEM); @@ -155,7 +172,8 @@ export class AuthService { } else { throw false; } - }); + }) + ); } /** @@ -167,14 +185,14 @@ export class AuthService { headers = headers.append('Accept', 'application/json'); headers = headers.append('Authorization', `Bearer ${token.accessToken}`); options.headers = headers; - return this.authRequestService.postToEndpoint('login', {}, options) - .map((status: AuthStatus) => { + return this.authRequestService.postToEndpoint('login', {}, options).pipe( + map((status: AuthStatus) => { if (status.authenticated) { return status.token; } else { throw(new Error('Not authenticated')); } - }); + })); } /** @@ -193,7 +211,7 @@ export class AuthService { // details and then return the new user object // but, let's just return the new user for this example. // this._authenticated = true; - return Observable.of(user); + return observableOf(user); } /** @@ -204,15 +222,15 @@ export class AuthService { // Send a request that sign end the session let headers = new HttpHeaders(); headers = headers.append('Content-Type', 'application/x-www-form-urlencoded'); - const options: HttpOptions = Object.create({headers, responseType: 'text'}); - return this.authRequestService.getRequest('logout', options) - .map((status: AuthStatus) => { + const options: HttpOptions = Object.create({ headers, responseType: 'text' }); + return this.authRequestService.getRequest('logout', options).pipe( + map((status: AuthStatus) => { if (!status.authenticated) { return true; } else { throw(new Error('auth.errors.invalid-user')); } - }) + })) } @@ -233,7 +251,7 @@ export class AuthService { */ public getToken(): AuthTokenInfo { let token: AuthTokenInfo; - this.store.select(getAuthenticationToken) + this.store.pipe(select(getAuthenticationToken)) .subscribe((authTokenInfo: AuthTokenInfo) => { // Retrieve authentication token info and check if is valid token = authTokenInfo || null; @@ -246,9 +264,10 @@ export class AuthService { * @returns {boolean} */ public isTokenExpiring(): Observable { - return this.store.select(isTokenRefreshing) - .first() - .map((isRefreshing: boolean) => { + return this.store.pipe( + select(isTokenRefreshing), + first(), + map((isRefreshing: boolean) => { if (this.isTokenExpired() || isRefreshing) { return false; } else { @@ -256,6 +275,7 @@ export class AuthService { return token.expires - (60 * 5 * 1000) < Date.now(); } }) + ) } /** @@ -279,7 +299,7 @@ export class AuthService { // Set the cookie expire date const expires = new Date(expireDate); - const options: CookieAttributes = {expires: expires}; + const options: CookieAttributes = { expires: expires }; // Save cookie with the token return this.storage.set(TOKENITEM, token, options); @@ -324,8 +344,8 @@ export class AuthService { * Redirect to the route navigated before the login */ public redirectToPreviousUrl() { - this.getRedirectUrl() - .first() + this.getRedirectUrl().pipe( + first()) .subscribe((redirectUrl) => { if (isNotEmpty(redirectUrl)) { this.clearRedirectUrl(); @@ -359,9 +379,9 @@ export class AuthService { getRedirectUrl(): Observable { const redirectUrl = this.storage.get(REDIRECT_COOKIE); if (isNotEmpty(redirectUrl)) { - return Observable.of(redirectUrl); + return observableOf(redirectUrl); } else { - return this.store.select(getRedirectUrl); + return this.store.pipe(select(getRedirectUrl)); } } @@ -374,7 +394,7 @@ export class AuthService { // Set the cookie expire date const expires = new Date(expireDate); - const options: CookieAttributes = {expires: expires}; + const options: CookieAttributes = { expires: expires }; this.storage.set(REDIRECT_COOKIE, url, options); this.store.dispatch(new SetRedirectUrlAction(isNotUndefined(url) ? url : '')); } diff --git a/src/app/core/auth/authenticated.guard.ts b/src/app/core/auth/authenticated.guard.ts index 66fa34992d..b9091a86ad 100644 --- a/src/app/core/auth/authenticated.guard.ts +++ b/src/app/core/auth/authenticated.guard.ts @@ -1,8 +1,10 @@ + +import {take} from 'rxjs/operators'; import { Injectable } from '@angular/core'; import { ActivatedRouteSnapshot, CanActivate, CanLoad, Route, Router, RouterStateSnapshot } from '@angular/router'; import { Observable } from 'rxjs'; -import { Store } from '@ngrx/store'; +import { select, Store } from '@ngrx/store'; // reducers import { CoreState } from '../core.reducers'; @@ -52,12 +54,12 @@ export class AuthenticatedGuard implements CanActivate, CanLoad { private handleAuth(url: string): Observable { // get observable - const observable = this.store.select(isAuthenticated); + const observable = this.store.pipe(select(isAuthenticated)); // redirect to sign in page if user is not authenticated - observable + observable.pipe( // .filter(() => isEmpty(this.router.routerState.snapshot.url) || this.router.routerState.snapshot.url === url) - .take(1) + take(1)) .subscribe((authenticated) => { if (!authenticated) { this.authService.setRedirectUrl(url); diff --git a/src/app/core/auth/server-auth.service.ts b/src/app/core/auth/server-auth.service.ts index e65452e872..7111eed255 100644 --- a/src/app/core/auth/server-auth.service.ts +++ b/src/app/core/auth/server-auth.service.ts @@ -1,3 +1,5 @@ + +import {first, map} from 'rxjs/operators'; import { Injectable } from '@angular/core'; import { Observable } from 'rxjs'; @@ -32,14 +34,14 @@ export class ServerAuthService extends AuthService { headers = headers.append('X-Forwarded-For', clientIp); options.headers = headers; - return this.authRequestService.getRequest('status', options) - .map((status: AuthStatus) => { + return this.authRequestService.getRequest('status', options).pipe( + map((status: AuthStatus) => { if (status.authenticated) { return status.eperson[0]; } else { throw(new Error('Not authenticated')); } - }); + })); } /** @@ -53,8 +55,8 @@ export class ServerAuthService extends AuthService { * Redirect to the route navigated before the login */ public redirectToPreviousUrl() { - this.getRedirectUrl() - .first() + this.getRedirectUrl().pipe( + first()) .subscribe((redirectUrl) => { if (isNotEmpty(redirectUrl)) { // override the route reuse strategy 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 9078bb05da..eb11db3ca4 100644 --- a/src/app/core/cache/builders/remote-data-build.service.ts +++ b/src/app/core/cache/builders/remote-data-build.service.ts @@ -1,5 +1,6 @@ + +import {combineLatest as observableCombineLatest, of as observableOf, Observable, race as observableRace } from 'rxjs'; import { Injectable } from '@angular/core'; -import { Observable } from 'rxjs'; import { distinctUntilChanged, flatMap, map, startWith } from 'rxjs/operators'; import { hasValue, hasValueOperator, isEmpty, isNotEmpty } from '../../../shared/empty.util'; import { PaginatedList } from '../../data/paginated-list'; @@ -32,24 +33,24 @@ export class RemoteDataBuildService { buildSingle(href$: string | Observable): Observable> { if (typeof href$ === 'string') { - href$ = Observable.of(href$); + href$ = observableOf(href$); } const requestHref$ = href$.pipe(flatMap((href: string) => this.objectCache.getRequestHrefBySelfLink(href))); - const requestEntry$ = Observable.race( + const requestEntry$ = observableRace( href$.pipe(getRequestFromSelflink(this.requestService)), requestHref$.pipe(getRequestFromSelflink(this.requestService)) ); - const responseCache$ = Observable.race( + const responseCache$ = observableRace( href$.pipe(getResponseFromSelflink(this.responseCache)), requestHref$.pipe(getResponseFromSelflink(this.responseCache)) ); // always use self link if that is cached, only if it isn't, get it via the response. const payload$ = - Observable.combineLatest( + observableCombineLatest( href$.pipe( flatMap((href: string) => this.objectCache.getBySelfLink(href)), startWith(undefined) @@ -60,7 +61,7 @@ export class RemoteDataBuildService { if (isNotEmpty(resourceSelfLinks)) { return this.objectCache.getBySelfLink(resourceSelfLinks[0]); } else { - return Observable.of(undefined); + return observableOf(undefined); } }), distinctUntilChanged(), @@ -85,7 +86,7 @@ export class RemoteDataBuildService { } toRemoteDataObservable(requestEntry$: Observable, responseCache$: Observable, payload$: Observable) { - return Observable.combineLatest(requestEntry$, responseCache$.startWith(undefined), payload$, + return observableCombineLatest(requestEntry$, responseCache$.pipe(startWith(undefined)), payload$, (reqEntry: RequestEntry, resEntry: ResponseCacheEntry, payload: T) => { const requestPending = hasValue(reqEntry.requestPending) ? reqEntry.requestPending : true; const responsePending = hasValue(reqEntry.responsePending) ? reqEntry.responsePending : false; @@ -110,7 +111,7 @@ export class RemoteDataBuildService { buildList(href$: string | Observable): Observable>> { if (typeof href$ === 'string') { - href$ = Observable.of(href$); + href$ = observableOf(href$); } const requestEntry$ = href$.pipe(getRequestFromSelflink(this.requestService)); @@ -119,12 +120,12 @@ export class RemoteDataBuildService { const tDomainList$ = responseCache$.pipe( getResourceLinksFromResponse(), flatMap((resourceUUIDs: string[]) => { - return this.objectCache.getList(resourceUUIDs) - .map((normList: TNormalized[]) => { + return this.objectCache.getList(resourceUUIDs).pipe( + map((normList: TNormalized[]) => { return normList.map((normalized: TNormalized) => { return this.build(normalized); }); - }); + })); }), startWith([]), distinctUntilChanged() @@ -144,7 +145,7 @@ export class RemoteDataBuildService { }) ); - const payload$ = Observable.combineLatest(tDomainList$, pageInfo$, (tDomainList, pageInfo) => { + const payload$ = observableCombineLatest(tDomainList$, pageInfo$, (tDomainList, pageInfo) => { return new PaginatedList(pageInfo, tDomainList); }); @@ -204,10 +205,10 @@ export class RemoteDataBuildService { aggregate(input: Array>>): Observable> { if (isEmpty(input)) { - return Observable.of(new RemoteData(false, false, true, null, [])); + return observableOf(new RemoteData(false, false, true, null, [])); } - return Observable.combineLatest( + return observableCombineLatest( ...input, (...arr: Array>) => { const requestPending: boolean = arr @@ -255,7 +256,7 @@ export class RemoteDataBuildService { } aggregatePaginatedList(input: Observable>, pageInfo: PageInfo): Observable>> { - return input.map((rd) => Object.assign(rd, {payload: new PaginatedList(pageInfo, rd.payload)})); + return input.pipe(map((rd) => Object.assign(rd, {payload: new PaginatedList(pageInfo, rd.payload)}))); } } diff --git a/src/app/core/cache/object-cache.effects.ts b/src/app/core/cache/object-cache.effects.ts index 019c792973..2bd8ad0e3c 100644 --- a/src/app/core/cache/object-cache.effects.ts +++ b/src/app/core/cache/object-cache.effects.ts @@ -1,5 +1,6 @@ +import { map } from 'rxjs/operators'; import { Injectable } from '@angular/core'; -import { Actions, Effect } from '@ngrx/effects'; +import { Actions, Effect, ofType } from '@ngrx/effects'; import { StoreActionTypes } from '../../store.actions'; import { ResetObjectCacheTimestampsAction } from './object-cache.actions'; @@ -16,9 +17,11 @@ export class ObjectCacheEffects { * time ago, and will likely need to be revisited later */ @Effect() fixTimestampsOnRehydrate = this.actions$ - .ofType(StoreActionTypes.REHYDRATE) - .map(() => new ResetObjectCacheTimestampsAction(new Date().getTime())); + .pipe(ofType(StoreActionTypes.REHYDRATE), + map(() => new ResetObjectCacheTimestampsAction(new Date().getTime())) + ); - constructor(private actions$: Actions) { } + constructor(private actions$: Actions) { + } } diff --git a/src/app/core/cache/object-cache.service.ts b/src/app/core/cache/object-cache.service.ts index dbeb02cb0a..dbe241ffb3 100644 --- a/src/app/core/cache/object-cache.service.ts +++ b/src/app/core/cache/object-cache.service.ts @@ -1,16 +1,16 @@ -import { Injectable } from '@angular/core'; -import { MemoizedSelector, Store } from '@ngrx/store'; +import { combineLatest as observableCombineLatest, Observable } from 'rxjs'; -import { Observable } from 'rxjs'; +import { distinctUntilChanged, filter, first, map, mergeMap, take } from 'rxjs/operators'; +import { Injectable } from '@angular/core'; +import { MemoizedSelector, select, Store } from '@ngrx/store'; import { IndexName } from '../index/index.reducer'; -import { ObjectCacheEntry, CacheableObject } from './object-cache.reducer'; +import { CacheableObject, ObjectCacheEntry } from './object-cache.reducer'; import { AddToObjectCacheAction, RemoveFromObjectCacheAction } from './object-cache.actions'; import { hasNoValue } from '../../shared/empty.util'; import { GenericConstructor } from '../shared/generic-constructor'; import { coreSelector, CoreState } from '../core.reducers'; import { pathSelector } from '../shared/selectors'; -import { Item } from '../shared/item.model'; import { NormalizedObjectFactory } from './models/normalized-object-factory'; import { NormalizedObject } from './models/normalized-object.model'; @@ -73,33 +73,40 @@ export class ObjectCacheService { * An observable of the requested object */ getByUUID(uuid: string): Observable { - return this.store.select(selfLinkFromUuidSelector(uuid)) - .flatMap((selfLink: string) => this.getBySelfLink(selfLink)) + return this.store.pipe( + select(selfLinkFromUuidSelector(uuid)), + mergeMap((selfLink: string) => this.getBySelfLink(selfLink) + ) + ) } getBySelfLink(selfLink: string): Observable { - return this.getEntry(selfLink) - .map((entry: ObjectCacheEntry) => { - const type: GenericConstructor= NormalizedObjectFactory.getConstructor(entry.data.type); + return this.getEntry(selfLink).pipe( + map((entry: ObjectCacheEntry) => { + const type: GenericConstructor = NormalizedObjectFactory.getConstructor(entry.data.type); return Object.assign(new type(), entry.data) as T - }); + })); } private getEntry(selfLink: string): Observable { - return this.store.select(entryFromSelfLinkSelector(selfLink)) - .filter((entry) => this.isValid(entry)) - .distinctUntilChanged(); + return this.store.pipe( + select(entryFromSelfLinkSelector(selfLink)), + filter((entry) => this.isValid(entry)), + distinctUntilChanged() + ); } getRequestHrefBySelfLink(selfLink: string): Observable { - return this.getEntry(selfLink) - .map((entry: ObjectCacheEntry) => entry.requestHref) - .distinctUntilChanged(); + return this.getEntry(selfLink).pipe( + map((entry: ObjectCacheEntry) => entry.requestHref), + distinctUntilChanged(),); } getRequestHrefByUUID(uuid: string): Observable { - return this.store.select(selfLinkFromUuidSelector(uuid)) - .flatMap((selfLink: string) => this.getRequestHrefBySelfLink(selfLink)); + return this.store.pipe( + select(selfLinkFromUuidSelector(uuid)), + mergeMap((selfLink: string) => this.getRequestHrefBySelfLink(selfLink)) + ); } /** @@ -122,7 +129,7 @@ export class ObjectCacheService { * @return Observable> */ getList(selfLinks: string[]): Observable { - return Observable.combineLatest( + return observableCombineLatest( selfLinks.map((selfLink: string) => this.getBySelfLink(selfLink)) ); } @@ -139,9 +146,10 @@ export class ObjectCacheService { hasByUUID(uuid: string): boolean { let result: boolean; - this.store.select(selfLinkFromUuidSelector(uuid)) - .take(1) - .subscribe((selfLink: string) => result = this.hasBySelfLink(selfLink)); + this.store.pipe( + select(selfLinkFromUuidSelector(uuid)), + first() + ).subscribe((selfLink: string) => result = this.hasBySelfLink(selfLink)); return result; } @@ -158,9 +166,9 @@ export class ObjectCacheService { hasBySelfLink(selfLink: string): boolean { let result = false; - this.store.select(entryFromSelfLinkSelector(selfLink)) - .take(1) - .subscribe((entry: ObjectCacheEntry) => result = this.isValid(entry)); + this.store.pipe(select(entryFromSelfLinkSelector(selfLink)), + first() + ).subscribe((entry: ObjectCacheEntry) => result = this.isValid(entry)); return result; } diff --git a/src/app/core/cache/response-cache.effects.ts b/src/app/core/cache/response-cache.effects.ts index d340750797..5a1e53e20c 100644 --- a/src/app/core/cache/response-cache.effects.ts +++ b/src/app/core/cache/response-cache.effects.ts @@ -1,5 +1,6 @@ +import { map } from 'rxjs/operators'; import { Injectable } from '@angular/core'; -import { Actions, Effect } from '@ngrx/effects'; +import { Actions, Effect, ofType } from '@ngrx/effects'; import { ResetResponseCacheTimestampsAction } from './response-cache.actions'; import { StoreActionTypes } from '../../store.actions'; @@ -16,9 +17,11 @@ export class ResponseCacheEffects { * time ago, and will likely need to be revisited later */ @Effect() fixTimestampsOnRehydrate = this.actions$ - .ofType(StoreActionTypes.REHYDRATE) - .map(() => new ResetResponseCacheTimestampsAction(new Date().getTime())); + .pipe(ofType(StoreActionTypes.REHYDRATE), + map(() => new ResetResponseCacheTimestampsAction(new Date().getTime())) + ); - constructor(private actions$: Actions, ) { } + constructor(private actions$: Actions,) { + } } diff --git a/src/app/core/cache/response-cache.service.ts b/src/app/core/cache/response-cache.service.ts index 19e7711168..21430d451c 100644 --- a/src/app/core/cache/response-cache.service.ts +++ b/src/app/core/cache/response-cache.service.ts @@ -1,5 +1,6 @@ +import { filter, take, distinctUntilChanged, first } from 'rxjs/operators'; import { Injectable } from '@angular/core'; -import { MemoizedSelector, Store } from '@ngrx/store'; +import { MemoizedSelector, select, Store } from '@ngrx/store'; import { Observable } from 'rxjs'; @@ -21,7 +22,8 @@ function entryFromKeySelector(key: string): MemoizedSelector - ) { } + ) { + } add(key: string, response: RestResponse, msToLive: number): Observable { if (!this.has(key)) { @@ -39,9 +41,11 @@ export class ResponseCacheService { * an observable of the ResponseCacheEntry with the specified key */ get(key: string): Observable { - return this.store.select(entryFromKeySelector(key)) - .filter((entry: ResponseCacheEntry) => this.isValid(entry)) - .distinctUntilChanged() + return this.store.pipe( + select(entryFromKeySelector(key)), + filter((entry: ResponseCacheEntry) => this.isValid(entry)), + distinctUntilChanged() + ) } /** @@ -56,11 +60,11 @@ export class ResponseCacheService { has(key: string): boolean { let result: boolean; - this.store.select(entryFromKeySelector(key)) - .take(1) - .subscribe((entry: ResponseCacheEntry) => { - result = this.isValid(entry); - }); + this.store.pipe(select(entryFromKeySelector(key)), + first() + ).subscribe((entry: ResponseCacheEntry) => { + result = this.isValid(entry); + }); return result; } @@ -70,6 +74,7 @@ export class ResponseCacheService { this.store.dispatch(new ResponseCacheRemoveAction(key)); } } + /** * Check whether a ResponseCacheEntry should still be cached * diff --git a/src/app/core/config/config.service.ts b/src/app/core/config/config.service.ts index d1b042afd3..2199deedcf 100644 --- a/src/app/core/config/config.service.ts +++ b/src/app/core/config/config.service.ts @@ -1,9 +1,8 @@ - -import {throwError as observableThrowError, Observable } from 'rxjs'; - +import { Observable, of as observableOf, throwError as observableThrowError } from 'rxjs'; +import { distinctUntilChanged, filter, map, mergeMap, tap } from 'rxjs/operators'; import { RequestService } from '../data/request.service'; import { ResponseCacheService } from '../cache/response-cache.service'; -import { ConfigSuccessResponse, ErrorResponse, RestResponse } from '../cache/response-cache.models'; +import { ConfigSuccessResponse } from '../cache/response-cache.models'; import { ConfigRequest, FindAllOptions, RestRequest } from '../data/request.models'; import { ResponseCacheEntry } from '../cache/response-cache.reducer'; import { hasValue, isNotEmpty } from '../../shared/empty.util'; @@ -19,16 +18,18 @@ export abstract class ConfigService { protected abstract halService: HALEndpointService; protected getConfig(request: RestRequest): Observable { - const [successResponse, errorResponse] = this.responseCache.get(request.href) - .map((entry: ResponseCacheEntry) => entry.response) - .partition((response: RestResponse) => response.isSuccessful); - return Observable.merge( - errorResponse.flatMap((response: ErrorResponse) => - observableThrowError(new Error(`Couldn't retrieve the config`))), - successResponse - .filter((response: ConfigSuccessResponse) => isNotEmpty(response) && isNotEmpty(response.configDefinition)) - .map((response: ConfigSuccessResponse) => new ConfigData(response.pageInfo, response.configDefinition)) - .distinctUntilChanged()); + return this.responseCache.get(request.href).pipe( + map((entry: ResponseCacheEntry) => entry.response), + mergeMap((response) => { + if (response.isSuccessful && isNotEmpty(response) && isNotEmpty((response as ConfigSuccessResponse).configDefinition)) { + const configResponse = response as ConfigSuccessResponse; + return observableOf(new ConfigData(configResponse.pageInfo, configResponse.configDefinition)); + } else if (!response.isSuccessful) { + return observableThrowError(new Error(`Couldn't retrieve the config`)); + } + }), + distinctUntilChanged() + ); } protected getConfigByNameHref(endpoint, resourceName): string { @@ -66,13 +67,13 @@ export abstract class ConfigService { } public getConfigAll(): Observable { - return this.halService.getEndpoint(this.linkPath) - .filter((href: string) => isNotEmpty(href)) - .distinctUntilChanged() - .map((endpointURL: string) => new ConfigRequest(this.requestService.generateRequestId(), endpointURL)) - .do((request: RestRequest) => this.requestService.configure(request)) - .flatMap((request: RestRequest) => this.getConfig(request)) - .distinctUntilChanged(); + return this.halService.getEndpoint(this.linkPath).pipe( + filter((href: string) => isNotEmpty(href)), + distinctUntilChanged(), + map((endpointURL: string) => new ConfigRequest(this.requestService.generateRequestId(), endpointURL)), + tap((request: RestRequest) => this.requestService.configure(request)), + mergeMap((request: RestRequest) => this.getConfig(request)), + distinctUntilChanged(),); } public getConfigByHref(href: string): Observable { @@ -83,25 +84,25 @@ export abstract class ConfigService { } public getConfigByName(name: string): Observable { - return this.halService.getEndpoint(this.linkPath) - .map((endpoint: string) => this.getConfigByNameHref(endpoint, name)) - .filter((href: string) => isNotEmpty(href)) - .distinctUntilChanged() - .map((endpointURL: string) => new ConfigRequest(this.requestService.generateRequestId(), endpointURL)) - .do((request: RestRequest) => this.requestService.configure(request)) - .flatMap((request: RestRequest) => this.getConfig(request)) - .distinctUntilChanged(); + return this.halService.getEndpoint(this.linkPath).pipe( + map((endpoint: string) => this.getConfigByNameHref(endpoint, name)), + filter((href: string) => isNotEmpty(href)), + distinctUntilChanged(), + map((endpointURL: string) => new ConfigRequest(this.requestService.generateRequestId(), endpointURL)), + tap((request: RestRequest) => this.requestService.configure(request)), + mergeMap((request: RestRequest) => this.getConfig(request)), + distinctUntilChanged(),); } public getConfigBySearch(options: FindAllOptions = {}): Observable { - return this.halService.getEndpoint(this.linkPath) - .map((endpoint: string) => this.getConfigSearchHref(endpoint, options)) - .filter((href: string) => isNotEmpty(href)) - .distinctUntilChanged() - .map((endpointURL: string) => new ConfigRequest(this.requestService.generateRequestId(), endpointURL)) - .do((request: RestRequest) => this.requestService.configure(request)) - .flatMap((request: RestRequest) => this.getConfig(request)) - .distinctUntilChanged(); + return this.halService.getEndpoint(this.linkPath).pipe( + map((endpoint: string) => this.getConfigSearchHref(endpoint, options)), + filter((href: string) => isNotEmpty(href)), + distinctUntilChanged(), + map((endpointURL: string) => new ConfigRequest(this.requestService.generateRequestId(), endpointURL)), + tap((request: RestRequest) => this.requestService.configure(request)), + mergeMap((request: RestRequest) => this.getConfig(request)), + distinctUntilChanged(),); } } diff --git a/src/app/core/data/comcol-data.service.ts b/src/app/core/data/comcol-data.service.ts index f2c7a743d5..de3955eb14 100644 --- a/src/app/core/data/comcol-data.service.ts +++ b/src/app/core/data/comcol-data.service.ts @@ -1,10 +1,8 @@ - -import {throwError as observableThrowError, Observable } from 'rxjs'; +import { Observable, throwError as observableThrowError } from 'rxjs'; +import { distinctUntilChanged, filter, first, map, mergeMap, tap } from 'rxjs/operators'; import { isEmpty, isNotEmpty } from '../../shared/empty.util'; import { NormalizedCommunity } from '../cache/models/normalized-community.model'; -import { CacheableObject } from '../cache/object-cache.reducer'; import { ObjectCacheService } from '../cache/object-cache.service'; -import { DSOSuccessResponse, ErrorResponse, RestResponse } from '../cache/response-cache.models'; import { ResponseCacheEntry } from '../cache/response-cache.reducer'; import { CommunityDataService } from './community-data.service'; @@ -13,7 +11,7 @@ import { FindByIDRequest } from './request.models'; import { NormalizedObject } from '../cache/models/normalized-object.model'; import { HALEndpointService } from '../shared/hal-endpoint.service'; -export abstract class ComColDataService extends DataService { +export abstract class ComColDataService extends DataService { protected abstract cds: CommunityDataService; protected abstract objectCache: ObjectCacheService; protected abstract halService: HALEndpointService; @@ -32,29 +30,31 @@ export abstract class ComColDataService this.cds.getFindByIDHref(endpoint, scopeID)) - .filter((href: string) => isNotEmpty(href)) - .take(1) - .do((href: string) => { + const scopeCommunityHrefObs = this.cds.getEndpoint().pipe( + mergeMap((endpoint: string) => this.cds.getFindByIDHref(endpoint, scopeID)), + first((href: string) => isNotEmpty(href)), + tap((href: string) => { const request = new FindByIDRequest(this.requestService.generateRequestId(), href, scopeID); this.requestService.configure(request); - }); + }),); - const [successResponse, errorResponse] = scopeCommunityHrefObs - .flatMap((href: string) => this.responseCache.get(href)) - .map((entry: ResponseCacheEntry) => entry.response) - .share() - .partition((response: RestResponse) => response.isSuccessful); - - return Observable.merge( - errorResponse.flatMap((response: ErrorResponse) => - observableThrowError(new Error(`The Community with scope ${scopeID} couldn't be retrieved`))), - successResponse - .flatMap((response: DSOSuccessResponse) => this.objectCache.getByUUID(scopeID)) - .map((nc: NormalizedCommunity) => nc._links[this.linkPath]) - .filter((href) => isNotEmpty(href)) - ).distinctUntilChanged(); + return scopeCommunityHrefObs.pipe( + mergeMap((href: string) => this.responseCache.get(href)), + map((entry: ResponseCacheEntry) => entry.response), + mergeMap((response) => { + if (response.isSuccessful) { + const community$: Observable = this.objectCache.getByUUID(scopeID); + return community$.pipe( + map((community) => community._links[this.linkPath]), + filter((href) => isNotEmpty(href)), + distinctUntilChanged() + ); + } else if (!response.isSuccessful) { + return observableThrowError(new Error(`The Community with scope ${scopeID} couldn't be retrieved`)) + } + }), + distinctUntilChanged() + ); } } } diff --git a/src/app/core/data/community-data.service.ts b/src/app/core/data/community-data.service.ts index 206955ea9f..b8e8bd5ce0 100644 --- a/src/app/core/data/community-data.service.ts +++ b/src/app/core/data/community-data.service.ts @@ -1,3 +1,5 @@ + +import {mergeMap, filter, take} from 'rxjs/operators'; import { Injectable } from '@angular/core'; import { Store } from '@ngrx/store'; @@ -38,12 +40,12 @@ export class CommunityDataService extends ComColDataService>> { - const hrefObs = this.halService.getEndpoint(this.topLinkPath).filter((href: string) => isNotEmpty(href)) - .flatMap((endpoint: string) => this.getFindAllHref(endpoint, options)); + const hrefObs = this.halService.getEndpoint(this.topLinkPath).pipe(filter((href: string) => isNotEmpty(href)), + mergeMap((endpoint: string) => this.getFindAllHref(endpoint, options)),); - hrefObs - .filter((href: string) => hasValue(href)) - .take(1) + hrefObs.pipe( + filter((href: string) => hasValue(href)), + take(1),) .subscribe((href: string) => { const request = new FindAllRequest(this.requestService.generateRequestId(), href, options); this.requestService.configure(request); diff --git a/src/app/core/data/data.service.ts b/src/app/core/data/data.service.ts index 98e21c6ba3..1d0703bb47 100644 --- a/src/app/core/data/data.service.ts +++ b/src/app/core/data/data.service.ts @@ -1,5 +1,8 @@ + +import {of as observableOf, Observable } from 'rxjs'; + +import {mergeMap, first, take, distinctUntilChanged, map, filter} from 'rxjs/operators'; import { Store } from '@ngrx/store'; -import { Observable } from 'rxjs'; import { hasValue, isNotEmpty } from '../../shared/empty.util'; import { RemoteDataBuildService } from '../cache/builders/remote-data-build.service'; import { ResponseCacheService } from '../cache/response-cache.service'; @@ -27,9 +30,9 @@ export abstract class DataService const args = []; if (hasValue(options.scopeID)) { - result = this.getScopedEndpoint(options.scopeID).distinctUntilChanged(); + result = this.getScopedEndpoint(options.scopeID).pipe(distinctUntilChanged()); } else { - result = Observable.of(endpoint); + result = observableOf(endpoint); } if (hasValue(options.currentPage) && typeof options.currentPage === 'number') { @@ -50,19 +53,19 @@ export abstract class DataService } if (isNotEmpty(args)) { - return result.map((href: string) => new URLCombiner(href, `?${args.join('&')}`).toString()); + return result.pipe(map((href: string) => new URLCombiner(href, `?${args.join('&')}`).toString())); } else { return result; } } findAll(options: FindAllOptions = {}): Observable>> { - const hrefObs = this.halService.getEndpoint(this.linkPath).filter((href: string) => isNotEmpty(href)) - .flatMap((endpoint: string) => this.getFindAllHref(endpoint, options)); + const hrefObs = this.halService.getEndpoint(this.linkPath).pipe(filter((href: string) => isNotEmpty(href)), + mergeMap((endpoint: string) => this.getFindAllHref(endpoint, options)),); - hrefObs - .filter((href: string) => hasValue(href)) - .take(1) + hrefObs.pipe( + filter((href: string) => hasValue(href)), + take(1),) .subscribe((href: string) => { const request = new FindAllRequest(this.requestService.generateRequestId(), href, options); this.requestService.configure(request); @@ -76,11 +79,11 @@ export abstract class DataService } findById(id: string): Observable> { - const hrefObs = this.halService.getEndpoint(this.linkPath) - .map((endpoint: string) => this.getFindByIDHref(endpoint, id)); + const hrefObs = this.halService.getEndpoint(this.linkPath).pipe( + map((endpoint: string) => this.getFindByIDHref(endpoint, id))); - hrefObs - .first((href: string) => hasValue(href)) + hrefObs.pipe( + first((href: string) => hasValue(href))) .subscribe((href: string) => { const request = new FindByIDRequest(this.requestService.generateRequestId(), href, id); this.requestService.configure(request); diff --git a/src/app/core/data/item-data.service.ts b/src/app/core/data/item-data.service.ts index 40724b7319..dead4e5f48 100644 --- a/src/app/core/data/item-data.service.ts +++ b/src/app/core/data/item-data.service.ts @@ -1,3 +1,5 @@ + +import {distinctUntilChanged, map, filter} from 'rxjs/operators'; import { Inject, Injectable } from '@angular/core'; import { Store } from '@ngrx/store'; @@ -34,10 +36,10 @@ export class ItemDataService extends DataService { if (isEmpty(scopeID)) { return this.halService.getEndpoint(this.linkPath); } else { - return this.bs.getBrowseURLFor('dc.date.issued', this.linkPath) - .filter((href: string) => isNotEmpty(href)) - .map((href: string) => new URLCombiner(href, `?scope=${scopeID}`).toString()) - .distinctUntilChanged(); + return this.bs.getBrowseURLFor('dc.date.issued', this.linkPath).pipe( + filter((href: string) => isNotEmpty(href)), + map((href: string) => new URLCombiner(href, `?scope=${scopeID}`).toString()), + distinctUntilChanged(),); } } diff --git a/src/app/core/data/request.effects.ts b/src/app/core/data/request.effects.ts index 5fadd316f4..29c9ced472 100644 --- a/src/app/core/data/request.effects.ts +++ b/src/app/core/data/request.effects.ts @@ -1,9 +1,9 @@ + +import {of as observableOf, Observable } from 'rxjs'; import { Inject, Injectable, Injector } from '@angular/core'; import { Request } from '@angular/http'; import { RequestArgs } from '@angular/http/src/interfaces'; import { Actions, Effect, ofType } from '@ngrx/effects'; -// tslint:disable-next-line:import-blacklist -import { Observable } from 'rxjs'; import { GLOBAL_CONFIG, GlobalConfig } from '../../../config'; import { isNotEmpty } from '../../shared/empty.util'; @@ -30,7 +30,8 @@ export const addToResponseCacheAndCompleteAction = (request: RestRequest, respon @Injectable() export class RequestEffects { - @Effect() execute = this.actions$.ofType(RequestActionTypes.EXECUTE).pipe( + @Effect() execute = this.actions$.pipe( + ofType(RequestActionTypes.EXECUTE), flatMap((action: RequestExecuteAction) => { return this.requestService.getByUUID(action.payload).pipe( take(1) @@ -46,7 +47,7 @@ export class RequestEffects { return this.restApi.request(request.method, request.href, body, request.options).pipe( map((data: DSpaceRESTV2Response) => this.injector.get(request.getResponseParser()).parse(request, data)), addToResponseCacheAndCompleteAction(request, this.responseCache, this.EnvConfig), - catchError((error: RequestError) => Observable.of(new ErrorResponse(error)).pipe( + catchError((error: RequestError) => observableOf(new ErrorResponse(error)).pipe( addToResponseCacheAndCompleteAction(request, this.responseCache, this.EnvConfig) )) ); diff --git a/src/app/core/data/request.service.spec.ts b/src/app/core/data/request.service.spec.ts index 4c9d623941..92dd2c126b 100644 --- a/src/app/core/data/request.service.spec.ts +++ b/src/app/core/data/request.service.spec.ts @@ -1,7 +1,6 @@ import { Store } from '@ngrx/store'; import { cold, hot } from 'jasmine-marbles'; -import { Observable } from 'rxjs'; -import 'rxjs/add/observable/of'; +import { of as observableOf } from 'rxjs'; import { getMockObjectCacheService } from '../../shared/mocks/mock-object-cache.service'; import { getMockResponseCacheService } from '../../shared/mocks/mock-response-cache.service'; import { getMockStore } from '../../shared/mocks/mock-store'; @@ -18,7 +17,8 @@ import { OptionsRequest, PatchRequest, PostRequest, - PutRequest, RestRequest + PutRequest, + RestRequest } from './request.models'; import { RequestService } from './request.service'; @@ -46,12 +46,12 @@ describe('RequestService', () => { responseCache = getMockResponseCacheService(); (responseCache.has as any).and.returnValue(false); - (responseCache.get as any).and.returnValue(Observable.of(undefined)); + (responseCache.get as any).and.returnValue(observableOf(undefined)); uuidService = getMockUUIDService(); store = getMockStore(); - (store.select as any).and.returnValue(Observable.of(undefined)); + (store.pipe as any).and.returnValue(observableOf(undefined)); service = new RequestService( objectCache, @@ -74,7 +74,7 @@ describe('RequestService', () => { describe('isPending', () => { describe('before the request is configured', () => { beforeEach(() => { - spyOn(service, 'getByHref').and.returnValue(Observable.of(undefined)); + spyOn(service, 'getByHref').and.returnValue(observableOf(undefined)); }); it('should return false', () => { @@ -87,7 +87,7 @@ describe('RequestService', () => { describe('when the request has been configured but hasn\'t reached the store yet', () => { beforeEach(() => { - spyOn(service, 'getByHref').and.returnValue(Observable.of(undefined)); + spyOn(service, 'getByHref').and.returnValue(observableOf(undefined)); serviceAsAny.requestsOnTheirWayToTheStore = [testHref]; }); @@ -101,7 +101,7 @@ describe('RequestService', () => { describe('when the request has reached the store, before the server responds', () => { beforeEach(() => { - spyOn(service, 'getByHref').and.returnValue(Observable.of({ + spyOn(service, 'getByHref').and.returnValue(observableOf({ completed: false })) }); @@ -116,7 +116,7 @@ describe('RequestService', () => { describe('after the server responds', () => { beforeEach(() => { - spyOn(service, 'getByHref').and.returnValues(Observable.of({ + spyOn(service, 'getByHref').and.returnValues(observableOf({ completed: true })); }); @@ -134,7 +134,7 @@ describe('RequestService', () => { describe('getByUUID', () => { describe('if the request with the specified UUID exists in the store', () => { beforeEach(() => { - (store.select as any).and.returnValues(hot('a', { + (store.pipe as any).and.returnValues(hot('a', { a: { completed: true } @@ -155,7 +155,7 @@ describe('RequestService', () => { describe('if the request with the specified UUID doesn\'t exist in the store', () => { beforeEach(() => { - (store.select as any).and.returnValues(hot('a', { + (store.pipe as any).and.returnValues(hot('a', { a: undefined })); }); @@ -175,7 +175,7 @@ describe('RequestService', () => { describe('getByHref', () => { describe('when the request with the specified href exists in the store', () => { beforeEach(() => { - (store.select as any).and.returnValues(hot('a', { + (store.pipe as any).and.returnValues(hot('a', { a: testUUID })); spyOn(service, 'getByUUID').and.returnValue(cold('b', { @@ -199,7 +199,7 @@ describe('RequestService', () => { describe('when the request with the specified href doesn\'t exist in the store', () => { beforeEach(() => { - (store.select as any).and.returnValues(hot('a', { + (store.pipe as any).and.returnValues(hot('a', { a: undefined })); spyOn(service, 'getByUUID').and.returnValue(cold('b', { @@ -323,7 +323,7 @@ describe('RequestService', () => { describe('and it\'s a DSOSuccessResponse', () => { beforeEach(() => { - (responseCache.get as any).and.returnValues(Observable.of({ + (responseCache.get as any).and.returnValues(observableOf({ response: { isSuccessful: true, resourceSelfLinks: [ @@ -356,7 +356,7 @@ describe('RequestService', () => { beforeEach(() => { (objectCache.hasBySelfLink as any).and.returnValues(false); (responseCache.has as any).and.returnValues(true); - (responseCache.get as any).and.returnValues(Observable.of({ + (responseCache.get as any).and.returnValues(observableOf({ response: { isSuccessful: true } @@ -428,7 +428,7 @@ describe('RequestService', () => { describe('when the request is added to the store', () => { it('should stop tracking the request', () => { - (store.select as any).and.returnValues(Observable.of({ request })); + (store.pipe as any).and.returnValues(observableOf({ request })); serviceAsAny.trackRequestsOnTheirWayToTheStore(request); expect(serviceAsAny.requestsOnTheirWayToTheStore.includes(request.href)).toBeFalsy(); }); diff --git a/src/app/core/data/request.service.ts b/src/app/core/data/request.service.ts index 9fb12215b7..92eb4b55e7 100644 --- a/src/app/core/data/request.service.ts +++ b/src/app/core/data/request.service.ts @@ -1,12 +1,12 @@ +import { Observable } from 'rxjs'; +import { filter, first, map, mergeMap, take } from 'rxjs/operators'; import { Injectable } from '@angular/core'; -import { createSelector, MemoizedSelector, Store } from '@ngrx/store'; - -import { Observable } from 'rxjs'; +import { MemoizedSelector, select, Store } from '@ngrx/store'; import { hasValue } from '../../shared/empty.util'; import { CacheableObject } from '../cache/object-cache.reducer'; import { ObjectCacheService } from '../cache/object-cache.service'; -import { DSOSuccessResponse, RestResponse } from '../cache/response-cache.models'; +import { DSOSuccessResponse } from '../cache/response-cache.models'; import { ResponseCacheEntry } from '../cache/response-cache.reducer'; import { ResponseCacheService } from '../cache/response-cache.service'; import { coreSelector, CoreState } from '../core.reducers'; @@ -16,8 +16,7 @@ import { UUIDService } from '../shared/uuid.service'; import { RequestConfigureAction, RequestExecuteAction } from './request.actions'; import { GetRequest, RestRequest, RestRequestMethod } from './request.models'; -import { RequestEntry, RequestState } from './request.reducer'; -import { ResponseCacheRemoveAction } from '../cache/response-cache.actions'; +import { RequestEntry } from './request.reducer'; @Injectable() export class RequestService { @@ -49,8 +48,8 @@ export class RequestService { // then check the store let isPending = false; - this.getByHref(request.href) - .take(1) + this.getByHref(request.href).pipe( + take(1)) .subscribe((re: RequestEntry) => { isPending = (hasValue(re) && !re.completed) }); @@ -59,12 +58,14 @@ export class RequestService { } getByUUID(uuid: string): Observable { - return this.store.select(this.entryFromUUIDSelector(uuid)); + return this.store.pipe(select(this.entryFromUUIDSelector(uuid))); } getByHref(href: string): Observable { - return this.store.select(this.uuidFromHrefSelector(href)) - .flatMap((uuid: string) => this.getByUUID(uuid)); + return this.store.pipe( + select(this.uuidFromHrefSelector(href)), + mergeMap((uuid: string) => this.getByUUID(uuid)) + ); } // TODO to review "overrideRequest" param when https://github.com/DSpace/dspace-angular/issues/217 will be fixed @@ -81,29 +82,19 @@ export class RequestService { private isCachedOrPending(request: GetRequest) { let isCached = this.objectCache.hasBySelfLink(request.href); if (!isCached && this.responseCache.has(request.href)) { - const [successResponse, errorResponse] = this.responseCache.get(request.href) - .take(1) - .map((entry: ResponseCacheEntry) => entry.response) - .share() - .partition((response: RestResponse) => response.isSuccessful); - - const [dsoSuccessResponse, otherSuccessResponse] = successResponse - .share() - .partition((response: DSOSuccessResponse) => hasValue(response.resourceSelfLinks)); - - Observable.merge( - errorResponse.map(() => true), // TODO add a configurable number of retries in case of an error. - otherSuccessResponse.map(() => true), - dsoSuccessResponse // a DSOSuccessResponse should only be considered cached if all its resources are cached - .map((response: DSOSuccessResponse) => response.resourceSelfLinks) - .map((resourceSelfLinks: string[]) => resourceSelfLinks - .every((selfLink) => this.objectCache.hasBySelfLink(selfLink)) - ) + this.responseCache.get(request.href).pipe( + first(), + map((entry: ResponseCacheEntry) => { + const response = entry.response; + if (response.isSuccessful && hasValue((response as DSOSuccessResponse).resourceSelfLinks)) { + return (response as DSOSuccessResponse).resourceSelfLinks.every((selfLink) => this.objectCache.hasBySelfLink(selfLink)) + } else { + return true; + } + }) ).subscribe((c) => isCached = c); } - const isPending = this.isPending(request); - return isCached || isPending; } @@ -121,11 +112,11 @@ export class RequestService { */ private trackRequestsOnTheirWayToTheStore(request: GetRequest) { this.requestsOnTheirWayToTheStore = [...this.requestsOnTheirWayToTheStore, request.href]; - this.store.select(this.entryFromUUIDSelector(request.href)) - .filter((re: RequestEntry) => hasValue(re)) - .take(1) - .subscribe((re: RequestEntry) => { - this.requestsOnTheirWayToTheStore = this.requestsOnTheirWayToTheStore.filter((pendingHref: string) => pendingHref !== request.href) - }); + this.store.pipe(select(this.entryFromUUIDSelector(request.href)), + filter((re: RequestEntry) => hasValue(re)), + take(1) + ).subscribe((re: RequestEntry) => { + this.requestsOnTheirWayToTheStore = this.requestsOnTheirWayToTheStore.filter((pendingHref: string) => pendingHref !== request.href) + }); } } diff --git a/src/app/core/dspace-rest-v2/dspace-rest-v2.service.ts b/src/app/core/dspace-rest-v2/dspace-rest-v2.service.ts index 2402678d06..1570613c17 100644 --- a/src/app/core/dspace-rest-v2/dspace-rest-v2.service.ts +++ b/src/app/core/dspace-rest-v2/dspace-rest-v2.service.ts @@ -1,5 +1,5 @@ - import {throwError as observableThrowError, Observable } from 'rxjs'; +import {catchError, map} from 'rxjs/operators'; import { Injectable } from '@angular/core'; import { Request } from '@angular/http'; import { HttpClient, HttpHeaders, HttpParams, HttpResponse } from '@angular/common/http' @@ -37,12 +37,12 @@ export class DSpaceRESTv2Service { * An Observable containing the response from the server */ get(absoluteURL: string): Observable { - return this.http.get(absoluteURL, { observe: 'response' }) - .map((res: HttpResponse) => ({ payload: res.body, statusCode: res.statusText })) - .catch((err) => { + return this.http.get(absoluteURL, { observe: 'response' }).pipe( + map((res: HttpResponse) => ({ payload: res.body, statusCode: res.statusText })), + catchError((err) => { console.log('Error: ', err); return observableThrowError(err); - }); + })); } /** @@ -67,12 +67,12 @@ export class DSpaceRESTv2Service { if (options && options.responseType) { requestOptions.responseType = options.responseType; } - return this.http.request(method, url, requestOptions) - .map((res) => ({ payload: res.body, headers: res.headers, statusCode: res.statusText })) - .catch((err) => { + return this.http.request(method, url, requestOptions).pipe( + map((res) => ({ payload: res.body, headers: res.headers, statusCode: res.statusText })), + catchError((err) => { console.log('Error: ', err); return observableThrowError(err); - }); + })); } } diff --git a/src/app/core/index/index.effects.ts b/src/app/core/index/index.effects.ts index 05ae529c8e..de1ba681a2 100644 --- a/src/app/core/index/index.effects.ts +++ b/src/app/core/index/index.effects.ts @@ -1,5 +1,6 @@ +import { filter, map } from 'rxjs/operators'; import { Injectable } from '@angular/core'; -import { Effect, Actions } from '@ngrx/effects'; +import { Effect, Actions, ofType } from '@ngrx/effects'; import { ObjectCacheActionTypes, AddToObjectCacheAction, @@ -15,44 +16,52 @@ import { IndexName } from './index.reducer'; export class UUIDIndexEffects { @Effect() addObject$ = this.actions$ - .ofType(ObjectCacheActionTypes.ADD) - .filter((action: AddToObjectCacheAction) => hasValue(action.payload.objectToCache.uuid)) - .map((action: AddToObjectCacheAction) => { - return new AddToIndexAction( - IndexName.OBJECT, - action.payload.objectToCache.uuid, - action.payload.objectToCache.self - ); - }); + .pipe( + ofType(ObjectCacheActionTypes.ADD), + filter((action: AddToObjectCacheAction) => hasValue(action.payload.objectToCache.uuid)), + map((action: AddToObjectCacheAction) => { + return new AddToIndexAction( + IndexName.OBJECT, + action.payload.objectToCache.uuid, + action.payload.objectToCache.self + ); + }) + ); @Effect() removeObject$ = this.actions$ - .ofType(ObjectCacheActionTypes.REMOVE) - .map((action: RemoveFromObjectCacheAction) => { - return new RemoveFromIndexByValueAction( - IndexName.OBJECT, - action.payload - ); - }); + .pipe( + ofType(ObjectCacheActionTypes.REMOVE), + map((action: RemoveFromObjectCacheAction) => { + return new RemoveFromIndexByValueAction( + IndexName.OBJECT, + action.payload + ); + }) + ); @Effect() addRequest$ = this.actions$ - .ofType(RequestActionTypes.CONFIGURE) - .filter((action: RequestConfigureAction) => action.payload.method === RestRequestMethod.Get) - .map((action: RequestConfigureAction) => { - return new AddToIndexAction( - IndexName.REQUEST, - action.payload.href, - action.payload.uuid - ); - }); + .pipe( + ofType(RequestActionTypes.CONFIGURE), + filter((action: RequestConfigureAction) => action.payload.method === RestRequestMethod.Get), + map((action: RequestConfigureAction) => { + return new AddToIndexAction( + IndexName.REQUEST, + action.payload.href, + action.payload.uuid + ); + }) + ); // @Effect() removeRequest$ = this.actions$ - // .ofType(ObjectCacheActionTypes.REMOVE) - // .map((action: RemoveFromObjectCacheAction) => { + // .pipe( + // ofType(ObjectCacheActionTypes.REMOVE), + // map((action: RemoveFromObjectCacheAction) => { // return new RemoveFromIndexByValueAction( // IndexName.OBJECT, // action.payload // ); - // }); + // }) + // ) constructor(private actions$: Actions) { diff --git a/src/app/core/integration/integration.service.ts b/src/app/core/integration/integration.service.ts index 7642848ed6..3c71ca5f3b 100644 --- a/src/app/core/integration/integration.service.ts +++ b/src/app/core/integration/integration.service.ts @@ -1,8 +1,8 @@ - -import {throwError as observableThrowError, Observable } from 'rxjs'; +import { Observable, of as observableOf, throwError as observableThrowError } from 'rxjs'; +import { distinctUntilChanged, filter, map, mergeMap, tap } from 'rxjs/operators'; import { RequestService } from '../data/request.service'; import { ResponseCacheService } from '../cache/response-cache.service'; -import { ErrorResponse, IntegrationSuccessResponse, RestResponse } from '../cache/response-cache.models'; +import { IntegrationSuccessResponse } from '../cache/response-cache.models'; import { GetRequest, IntegrationRequest } from '../data/request.models'; import { ResponseCacheEntry } from '../cache/response-cache.reducer'; import { hasValue, isNotEmpty } from '../../shared/empty.util'; @@ -19,16 +19,18 @@ export abstract class IntegrationService { protected abstract halService: HALEndpointService; protected getData(request: GetRequest): Observable { - const [successResponse, errorResponse] = this.responseCache.get(request.href) - .map((entry: ResponseCacheEntry) => entry.response) - .partition((response: RestResponse) => response.isSuccessful); - return Observable.merge( - errorResponse.flatMap((response: ErrorResponse) => - observableThrowError(new Error(`Couldn't retrieve the integration data`))), - successResponse - .filter((response: IntegrationSuccessResponse) => isNotEmpty(response)) - .map((response: IntegrationSuccessResponse) => new IntegrationData(response.pageInfo, response.dataDefinition)) - .distinctUntilChanged()); + return this.responseCache.get(request.href).pipe( + map((entry: ResponseCacheEntry) => entry.response), + mergeMap((response) => { + if (response.isSuccessful && isNotEmpty(response)) { + const dataResponse = response as IntegrationSuccessResponse; + return observableOf(new IntegrationData(dataResponse.pageInfo, dataResponse.dataDefinition)); + } else if (!response.isSuccessful) { + return observableThrowError(new Error(`Couldn't retrieve the integration data`)); + } + }), + distinctUntilChanged() + ); } protected getIntegrationHref(endpoint, options: IntegrationSearchOptions = new IntegrationSearchOptions()): string { @@ -73,14 +75,14 @@ export abstract class IntegrationService { } public getEntriesByName(options: IntegrationSearchOptions): Observable { - return this.halService.getEndpoint(this.linkPath) - .map((endpoint: string) => this.getIntegrationHref(endpoint, options)) - .filter((href: string) => isNotEmpty(href)) - .distinctUntilChanged() - .map((endpointURL: string) => new IntegrationRequest(this.requestService.generateRequestId(), endpointURL)) - .do((request: GetRequest) => this.requestService.configure(request)) - .flatMap((request: GetRequest) => this.getData(request)) - .distinctUntilChanged(); + return this.halService.getEndpoint(this.linkPath).pipe( + map((endpoint: string) => this.getIntegrationHref(endpoint, options)), + filter((href: string) => isNotEmpty(href)), + distinctUntilChanged(), + map((endpointURL: string) => new IntegrationRequest(this.requestService.generateRequestId(), endpointURL)), + tap((request: GetRequest) => this.requestService.configure(request)), + mergeMap((request: GetRequest) => this.getData(request)), + distinctUntilChanged()); } } diff --git a/src/app/core/metadata/metadata.service.ts b/src/app/core/metadata/metadata.service.ts index 4689b2048c..860dd71ce6 100644 --- a/src/app/core/metadata/metadata.service.ts +++ b/src/app/core/metadata/metadata.service.ts @@ -1,4 +1,6 @@ +import {distinctUntilKeyChanged, map, filter, first, take} from 'rxjs/operators'; + import { Inject, Injectable } from '@angular/core'; @@ -54,21 +56,21 @@ export class MetadataService { } public listenForRouteChange(): void { - this.router.events - .filter((event) => event instanceof NavigationEnd) - .map(() => this.router.routerState.root) - .map((route: ActivatedRoute) => { + this.router.events.pipe( + filter((event) => event instanceof NavigationEnd), + map(() => this.router.routerState.root), + map((route: ActivatedRoute) => { route = this.getCurrentRoute(route); return { params: route.params, data: route.data }; - }).subscribe((routeInfo: any) => { + }),).subscribe((routeInfo: any) => { this.processRouteChange(routeInfo); }); } public processRemoteData(remoteData: Observable>): void { - remoteData.map((rd: RemoteData) => rd.payload) - .filter((co: CacheableObject) => hasValue(co)) - .take(1) + remoteData.pipe(map((rd: RemoteData) => rd.payload), + filter((co: CacheableObject) => hasValue(co)), + take(1),) .subscribe((dspaceObject: DSpaceObject) => { if (!this.initialized) { this.initialize(dspaceObject); @@ -82,13 +84,13 @@ export class MetadataService { this.clearMetaTags(); } if (routeInfo.data.value.title) { - this.translate.get(routeInfo.data.value.title).take(1).subscribe((translatedTitle: string) => { + this.translate.get(routeInfo.data.value.title).pipe(take(1)).subscribe((translatedTitle: string) => { this.addMetaTag('title', translatedTitle); this.title.setTitle(translatedTitle); }); } if (routeInfo.data.value.description) { - this.translate.get(routeInfo.data.value.description).take(1).subscribe((translatedDescription: string) => { + this.translate.get(routeInfo.data.value.description).pipe(take(1)).subscribe((translatedDescription: string) => { this.addMetaTag('description', translatedDescription); }); } @@ -96,7 +98,7 @@ export class MetadataService { private initialize(dspaceObject: DSpaceObject): void { this.currentObject = new BehaviorSubject(dspaceObject); - this.currentObject.asObservable().distinctUntilKeyChanged('uuid').subscribe(() => { + this.currentObject.asObservable().pipe(distinctUntilKeyChanged('uuid')).subscribe(() => { this.setMetaTags(); }); this.initialized = true; @@ -268,11 +270,11 @@ export class MetadataService { private setCitationPdfUrlTag(): void { if (this.currentObject.value instanceof Item) { const item = this.currentObject.value as Item; - item.getFiles().filter((files) => isNotEmpty(files)).first().subscribe((bitstreams: Bitstream[]) => { + item.getFiles().pipe(filter((files) => isNotEmpty(files)),first(),).subscribe((bitstreams: Bitstream[]) => { for (const bitstream of bitstreams) { - bitstream.format.first() - .map((rd: RemoteData) => rd.payload) - .filter((format: BitstreamFormat) => hasValue(format)) + bitstream.format.pipe(first(), + map((rd: RemoteData) => rd.payload), + filter((format: BitstreamFormat) => hasValue(format)),) .subscribe((format: BitstreamFormat) => { if (format.mimetype === 'application/pdf') { this.addMetaTag('citation_pdf_url', bitstream.content); diff --git a/src/app/core/registry/registry.service.ts b/src/app/core/registry/registry.service.ts index cc976f37f2..94c137dfd8 100644 --- a/src/app/core/registry/registry.service.ts +++ b/src/app/core/registry/registry.service.ts @@ -1,5 +1,6 @@ + +import {combineLatest as observableCombineLatest, Observable } from 'rxjs'; import { Injectable } from '@angular/core'; -import { Observable } from 'rxjs'; import { RemoteData } from '../data/remote-data'; import { PaginatedList } from '../data/paginated-list'; import { PageInfo } from '../shared/page-info.model'; @@ -70,7 +71,7 @@ export class RegistryService { map((response: RegistryMetadataschemasSuccessResponse) => response.pageInfo) ); - const payloadObs = Observable.combineLatest(metadataschemasObs, pageInfoObs, (metadataschemas, pageInfo) => { + const payloadObs = observableCombineLatest(metadataschemasObs, pageInfoObs, (metadataschemas, pageInfo) => { return new PaginatedList(pageInfo, metadataschemas); }); @@ -132,7 +133,7 @@ export class RegistryService { map((response: RegistryMetadatafieldsSuccessResponse) => response.pageInfo) ); - const payloadObs = Observable.combineLatest(metadatafieldsObs, pageInfoObs, (metadatafields, pageInfo) => { + const payloadObs = observableCombineLatest(metadatafieldsObs, pageInfoObs, (metadatafields, pageInfo) => { return new PaginatedList(pageInfo, metadatafields); }); @@ -164,7 +165,7 @@ export class RegistryService { map((response: RegistryBitstreamformatsSuccessResponse) => response.pageInfo) ); - const payloadObs = Observable.combineLatest(bitstreamformatsObs, pageInfoObs, (bitstreamformats, pageInfo) => { + const payloadObs = observableCombineLatest(bitstreamformatsObs, pageInfoObs, (bitstreamformats, pageInfo) => { return new PaginatedList(pageInfo, bitstreamformats); }); diff --git a/src/app/core/shared/hal-endpoint.service.ts b/src/app/core/shared/hal-endpoint.service.ts index 8e8d6b73d6..d72b9e9a9f 100644 --- a/src/app/core/shared/hal-endpoint.service.ts +++ b/src/app/core/shared/hal-endpoint.service.ts @@ -1,5 +1,5 @@ -import { Observable } from 'rxjs'; -import { distinctUntilChanged, map, flatMap, startWith, tap } from 'rxjs/operators'; +import {of as observableOf, Observable } from 'rxjs'; +import {filter, distinctUntilChanged, map, flatMap, startWith, tap } from 'rxjs/operators'; import { RequestService } from '../data/request.service'; import { ResponseCacheService } from '../cache/response-cache.service'; import { GlobalConfig } from '../../../config/global-config.interface'; @@ -30,11 +30,11 @@ export class HALEndpointService { private getEndpointMapAt(href): Observable { const request = new EndpointMapRequest(this.requestService.generateRequestId(), href); this.requestService.configure(request); - return this.responseCache.get(request.href) - .map((entry: ResponseCacheEntry) => entry.response) - .filter((response: EndpointMapSuccessResponse) => isNotEmpty(response)) - .map((response: EndpointMapSuccessResponse) => response.endpointMap) - .distinctUntilChanged(); + return this.responseCache.get(request.href).pipe( + map((entry: ResponseCacheEntry) => entry.response), + filter((response: EndpointMapSuccessResponse) => isNotEmpty(response)), + map((response: EndpointMapSuccessResponse) => response.endpointMap), + distinctUntilChanged(),); } public getEndpoint(linkPath: string): Observable { @@ -61,7 +61,7 @@ export class HALEndpointService { }), ]) .reduce((combined, thisElement) => [...combined, ...thisElement], []); - return Observable.of(this.getRootHref()).pipe(...pipeArguments, distinctUntilChanged()); + return observableOf(this.getRootHref()).pipe(...pipeArguments, distinctUntilChanged()); } public isEnabledOnRestApi(linkPath: string): Observable { diff --git a/src/app/core/shared/item.model.ts b/src/app/core/shared/item.model.ts index 2d42a189a7..69def7b969 100644 --- a/src/app/core/shared/item.model.ts +++ b/src/app/core/shared/item.model.ts @@ -1,3 +1,4 @@ +import {map, startWith, filter} from 'rxjs/operators'; import { Observable } from 'rxjs'; import { DSpaceObject } from './dspace-object.model'; @@ -58,9 +59,9 @@ export class Item extends DSpaceObject { // TODO: currently this just picks the first thumbnail // should be adjusted when we have a way to determine // the primary thumbnail from rest - return this.getBitstreamsByBundleName('THUMBNAIL') - .filter((thumbnails) => isNotEmpty(thumbnails)) - .map((thumbnails) => thumbnails[0]) + return this.getBitstreamsByBundleName('THUMBNAIL').pipe( + filter((thumbnails) => isNotEmpty(thumbnails)), + map((thumbnails) => thumbnails[0]),) } /** @@ -68,10 +69,10 @@ export class Item extends DSpaceObject { * @returns {Observable} the primaryBitstream of the 'THUMBNAIL' bundle */ getThumbnailForOriginal(original: Bitstream): Observable { - return this.getBitstreamsByBundleName('THUMBNAIL') - .map((files) => { + return this.getBitstreamsByBundleName('THUMBNAIL').pipe( + map((files) => { return files.find((thumbnail) => thumbnail.name.startsWith(original.name)) - }).startWith(undefined); + }),startWith(undefined),); } /** @@ -88,15 +89,15 @@ export class Item extends DSpaceObject { * @returns {Observable} the bitstreams with the given bundleName */ getBitstreamsByBundleName(bundleName: string): Observable { - return this.bitstreams - .map((rd: RemoteData>) => rd.payload.page) - .filter((bitstreams: Bitstream[]) => hasValue(bitstreams)) - .startWith([]) - .map((bitstreams) => { + return this.bitstreams.pipe( + map((rd: RemoteData>) => rd.payload.page), + filter((bitstreams: Bitstream[]) => hasValue(bitstreams)), + startWith([]), + map((bitstreams) => { return bitstreams .filter((bitstream) => hasValue(bitstream)) .filter((bitstream) => bitstream.bundleName === bundleName) - }); + }),); } } diff --git a/src/app/header/header.component.ts b/src/app/header/header.component.ts index 442f60612c..e1f8da0f9d 100644 --- a/src/app/header/header.component.ts +++ b/src/app/header/header.component.ts @@ -1,5 +1,5 @@ import { Component, OnInit } from '@angular/core'; -import { createSelector, Store } from '@ngrx/store'; +import { createSelector, select, Store } from '@ngrx/store'; import { Observable } from 'rxjs'; import { RouterReducerState } from '@ngrx/router-store'; @@ -33,7 +33,7 @@ export class HeaderComponent implements OnInit { ngOnInit(): void { // set loading - this.isNavBarCollapsed = this.store.select(navCollapsedSelector); + this.isNavBarCollapsed = this.store.pipe(select(navCollapsedSelector)); } public toggle(): void { diff --git a/src/app/header/header.effects.ts b/src/app/header/header.effects.ts index e1d281958b..cdc018d2d9 100644 --- a/src/app/header/header.effects.ts +++ b/src/app/header/header.effects.ts @@ -1,5 +1,6 @@ +import { map } from 'rxjs/operators'; import { Injectable } from '@angular/core'; -import { Effect, Actions } from '@ngrx/effects' +import { Effect, Actions, ofType } from '@ngrx/effects' import * as fromRouter from '@ngrx/router-store'; import { HostWindowActionTypes } from '../shared/host-window.actions'; @@ -9,12 +10,16 @@ import { HeaderCollapseAction } from './header.actions'; export class HeaderEffects { @Effect() resize$ = this.actions$ - .ofType(HostWindowActionTypes.RESIZE) - .map(() => new HeaderCollapseAction()); + .pipe( + ofType(HostWindowActionTypes.RESIZE), + map(() => new HeaderCollapseAction()) + ); @Effect() routeChange$ = this.actions$ - .ofType(fromRouter.ROUTER_NAVIGATION) - .map(() => new HeaderCollapseAction()); + .pipe( + ofType(fromRouter.ROUTER_NAVIGATION), + map(() => new HeaderCollapseAction()) + ); constructor(private actions$: Actions) { diff --git a/src/app/shared/auth-nav-menu/auth-nav-menu.component.ts b/src/app/shared/auth-nav-menu/auth-nav-menu.component.ts index 0cc9fb277a..d2924fc2e0 100644 --- a/src/app/shared/auth-nav-menu/auth-nav-menu.component.ts +++ b/src/app/shared/auth-nav-menu/auth-nav-menu.component.ts @@ -1,13 +1,19 @@ +import { of as observableOf, Observable } from 'rxjs'; + +import { map, filter } from 'rxjs/operators'; import { Component, OnInit } from '@angular/core'; -import { Observable } from 'rxjs'; import { RouterReducerState } from '@ngrx/router-store'; -import { Store } from '@ngrx/store'; +import { select, Store } from '@ngrx/store'; import { fadeInOut, fadeOut } from '../animations/fade'; import { HostWindowService } from '../host-window.service'; import { AppState, routerStateSelector } from '../../app.reducer'; import { isNotUndefined } from '../empty.util'; -import { getAuthenticatedUser, isAuthenticated, isAuthenticationLoading } from '../../core/auth/selectors'; +import { + getAuthenticatedUser, + isAuthenticated, + isAuthenticationLoading +} from '../../core/auth/selectors'; import { Eperson } from '../../core/eperson/models/eperson.model'; import { LOGIN_ROUTE, LOGOUT_ROUTE } from '../../core/auth/auth.service'; @@ -32,7 +38,7 @@ export class AuthNavMenuComponent implements OnInit { public isXsOrSm$: Observable; - public showAuth = Observable.of(false); + public showAuth = observableOf(false); public user: Observable; @@ -43,17 +49,19 @@ export class AuthNavMenuComponent implements OnInit { ngOnInit(): void { // set isAuthenticated - this.isAuthenticated = this.store.select(isAuthenticated); + this.isAuthenticated = this.store.pipe(select(isAuthenticated)); // set loading - this.loading = this.store.select(isAuthenticationLoading); + this.loading = this.store.pipe(select(isAuthenticationLoading)); - this.user = this.store.select(getAuthenticatedUser); + this.user = this.store.pipe(select(getAuthenticatedUser)); - this.showAuth = this.store.select(routerStateSelector) - .filter((router: RouterReducerState) => isNotUndefined(router) && isNotUndefined(router.state)) - .map((router: RouterReducerState) => { + this.showAuth = this.store.pipe( + select(routerStateSelector), + filter((router: RouterReducerState) => isNotUndefined(router) && isNotUndefined(router.state)), + map((router: RouterReducerState) => { return !router.state.url.startsWith(LOGIN_ROUTE) && !router.state.url.startsWith(LOGOUT_ROUTE); - }); + }) + ); } } diff --git a/src/app/shared/form/builder/ds-dynamic-form-ui/ds-dynamic-form-control.component.ts b/src/app/shared/form/builder/ds-dynamic-form-ui/ds-dynamic-form-control.component.ts index 3a39d22bef..432c3959b8 100644 --- a/src/app/shared/form/builder/ds-dynamic-form-ui/ds-dynamic-form-control.component.ts +++ b/src/app/shared/form/builder/ds-dynamic-form-ui/ds-dynamic-form-control.component.ts @@ -1,24 +1,16 @@ import { - ChangeDetectorRef, Component, + ComponentFactoryResolver, ContentChildren, EventEmitter, Input, OnChanges, Output, QueryList, - SimpleChanges + SimpleChanges, Type } from '@angular/core'; import { FormGroup } from '@angular/forms'; import { - DynamicDatePickerModel, - DynamicFormControlComponent, - DynamicFormControlEvent, - DynamicFormControlModel, - DynamicFormLayout, - DynamicFormLayoutService, - DynamicFormValidationService, - DynamicTemplateDirective, DYNAMIC_FORM_CONTROL_TYPE_ARRAY, DYNAMIC_FORM_CONTROL_TYPE_CHECKBOX, DYNAMIC_FORM_CONTROL_TYPE_CHECKBOX_GROUP, @@ -29,6 +21,14 @@ import { DYNAMIC_FORM_CONTROL_TYPE_SELECT, DYNAMIC_FORM_CONTROL_TYPE_TEXTAREA, DYNAMIC_FORM_CONTROL_TYPE_TIMEPICKER, + DynamicDatePickerModel, DynamicFormControl, + DynamicFormControlContainerComponent, + DynamicFormControlEvent, + DynamicFormControlModel, + DynamicFormLayout, + DynamicFormLayoutService, + DynamicFormValidationService, + DynamicTemplateDirective, } from '@ng-dynamic-forms/core'; import { DYNAMIC_FORM_CONTROL_TYPE_TYPEAHEAD } from './models/typeahead/dynamic-typeahead.model'; import { DYNAMIC_FORM_CONTROL_TYPE_SCROLLABLE_DROPDOWN } from './models/scrollable-dropdown/dynamic-scrollable-dropdown.model'; @@ -38,7 +38,6 @@ import { DYNAMIC_FORM_CONTROL_TYPE_DSDATEPICKER } from './models/date-picker/dat import { DYNAMIC_FORM_CONTROL_TYPE_LOOKUP } from './models/lookup/dynamic-lookup.model'; import { DynamicListCheckboxGroupModel } from './models/list/dynamic-list-checkbox-group.model'; import { DynamicListRadioGroupModel } from './models/list/dynamic-list-radio-group.model'; -import { isNotEmpty } from '../../../empty.util'; import { DYNAMIC_FORM_CONTROL_TYPE_LOOKUP_NAME } from './models/lookup/dynamic-lookup-name.model'; export const enum NGBootstrapFormControlType { @@ -69,11 +68,11 @@ export const enum NGBootstrapFormControlType { styleUrls: ['../../form.component.scss', './ds-dynamic-form.component.scss'], templateUrl: './ds-dynamic-form-control.component.html' }) -export class DsDynamicFormControlComponent extends DynamicFormControlComponent implements OnChanges { +export class DsDynamicFormControlComponent extends DynamicFormControlContainerComponent implements OnChanges { - @ContentChildren(DynamicTemplateDirective) contentTemplateList: QueryList; - // tslint:disable-next-line:no-input-rename - @Input('templates') inputTemplateList: QueryList; + @ContentChildren(DynamicTemplateDirective) contentTemplateList: QueryList; + // tslint:disable-next-line:no-input-rename + @Input('templates') inputTemplateList: QueryList; @Input() formId: string; @Input() asBootstrapFormGroup = true; @@ -90,6 +89,7 @@ export class DsDynamicFormControlComponent extends DynamicFormControlComponent i @Output('dfFocus') focus: EventEmitter = new EventEmitter(); /* tslint:enable:no-output-rename */ + componentType: Type | null; type: NGBootstrapFormControlType | null; static getFormControlType(model: DynamicFormControlModel): NGBootstrapFormControlType | null { @@ -154,10 +154,10 @@ export class DsDynamicFormControlComponent extends DynamicFormControlComponent i } } - constructor(protected changeDetectorRef: ChangeDetectorRef, protected layoutService: DynamicFormLayoutService, + constructor(protected componentFactoryResolver: ComponentFactoryResolver, protected layoutService: DynamicFormLayoutService, protected validationService: DynamicFormValidationService) { - super(changeDetectorRef, layoutService, validationService); + super(componentFactoryResolver, layoutService, validationService); } ngOnChanges(changes: SimpleChanges) { @@ -170,9 +170,4 @@ export class DsDynamicFormControlComponent extends DynamicFormControlComponent i } } - onChangeLanguage(event) { - if (isNotEmpty((this.model as any).value)) { - this.onValueChange(event); - } - } } diff --git a/src/app/shared/form/builder/ds-dynamic-form-ui/ds-dynamic-form.component.ts b/src/app/shared/form/builder/ds-dynamic-form-ui/ds-dynamic-form.component.ts index 7789d910a8..c0c207eaff 100644 --- a/src/app/shared/form/builder/ds-dynamic-form-ui/ds-dynamic-form.component.ts +++ b/src/app/shared/form/builder/ds-dynamic-form-ui/ds-dynamic-form.component.ts @@ -9,13 +9,13 @@ import { } from '@angular/core'; import { FormGroup } from '@angular/forms'; import { - DynamicFormComponent, + DynamicFormComponent, DynamicFormControlContainerComponent, DynamicFormControlEvent, DynamicFormControlModel, - DynamicFormLayout, - DynamicFormLayoutService, - DynamicFormService, - DynamicTemplateDirective, + DynamicFormLayout, + DynamicFormLayoutService, + DynamicFormService, + DynamicTemplateDirective, } from '@ng-dynamic-forms/core'; import { DsDynamicFormControlComponent } from './ds-dynamic-form-control.component'; import { FormBuilderService } from '../form-builder.service'; @@ -39,9 +39,10 @@ export class DsDynamicFormComponent extends DynamicFormComponent { @ContentChildren(DynamicTemplateDirective) templates: QueryList; - @ViewChildren(DsDynamicFormControlComponent) components: QueryList; + @ViewChildren(DsDynamicFormControlComponent) components: QueryList; + + constructor(protected formService: FormBuilderService, protected layoutService: DynamicFormLayoutService) { + super(formService, layoutService); + } - constructor(protected formService: FormBuilderService, protected layoutService: DynamicFormLayoutService) { - super(formService, layoutService); - } } diff --git a/src/app/shared/form/builder/ds-dynamic-form-ui/models/dynamic-group/dynamic-group.components.ts b/src/app/shared/form/builder/ds-dynamic-form-ui/models/dynamic-group/dynamic-group.components.ts index 9387a69107..5aa80bbcd0 100644 --- a/src/app/shared/form/builder/ds-dynamic-form-ui/models/dynamic-group/dynamic-group.components.ts +++ b/src/app/shared/form/builder/ds-dynamic-form-ui/models/dynamic-group/dynamic-group.components.ts @@ -1,3 +1,4 @@ +import {of as observableOf, Observable , Subscription } from 'rxjs'; import { ChangeDetectorRef, Component, @@ -9,8 +10,6 @@ import { Output, ViewChild } from '@angular/core'; - -import { Observable , Subscription } from 'rxjs'; import { DynamicFormControlModel, DynamicFormGroupModel, DynamicInputModel } from '@ng-dynamic-forms/core'; import { isEqual } from 'lodash'; @@ -48,7 +47,7 @@ export class DsDynamicGroupComponent implements OnDestroy, OnInit { @Output() focus: EventEmitter = new EventEmitter(); public chips: Chips; - public formCollapsed = Observable.of(false); + public formCollapsed = observableOf(false); public formModel: DynamicFormControlModel[]; public editMode = false; @@ -66,7 +65,7 @@ export class DsDynamicGroupComponent implements OnDestroy, OnInit { ngOnInit() { const config = {rows: this.model.formConfiguration} as SubmissionFormsModel; if (!this.model.isEmpty()) { - this.formCollapsed = Observable.of(true); + this.formCollapsed = observableOf(true); } this.model.valueUpdates.subscribe((value: any[]) => { if ((isNotEmpty(value) && !(value.length === 1 && hasOnlyEmptyProperties(value[0])))) { @@ -151,12 +150,12 @@ export class DsDynamicGroupComponent implements OnDestroy, OnInit { } collapseForm() { - this.formCollapsed = Observable.of(true); + this.formCollapsed = observableOf(true); this.clear(); } expandForm() { - this.formCollapsed = Observable.of(false); + this.formCollapsed = observableOf(false); } clear() { @@ -167,7 +166,7 @@ export class DsDynamicGroupComponent implements OnDestroy, OnInit { } this.resetForm(); if (!this.model.isEmpty()) { - this.formCollapsed = Observable.of(true); + this.formCollapsed = observableOf(true); } } diff --git a/src/app/shared/form/builder/ds-dynamic-form-ui/models/list/dynamic-list.component.ts b/src/app/shared/form/builder/ds-dynamic-form-ui/models/list/dynamic-list.component.ts index ec0d3e343a..15b60235ce 100644 --- a/src/app/shared/form/builder/ds-dynamic-form-ui/models/list/dynamic-list.component.ts +++ b/src/app/shared/form/builder/ds-dynamic-form-ui/models/list/dynamic-list.component.ts @@ -99,7 +99,7 @@ export class DsDynamicListComponent implements OnInit { const value = option.id || option.value; const checked: boolean = isNotEmpty(findKey( this.model.value, - {value: option.value})); + (v) => v.value === option.value)); const item: ListItem = { id: value, diff --git a/src/app/shared/form/builder/ds-dynamic-form-ui/models/lookup/dynamic-lookup.component.ts b/src/app/shared/form/builder/ds-dynamic-form-ui/models/lookup/dynamic-lookup.component.ts index 8928b14ae5..b184b4f4db 100644 --- a/src/app/shared/form/builder/ds-dynamic-form-ui/models/lookup/dynamic-lookup.component.ts +++ b/src/app/shared/form/builder/ds-dynamic-form-ui/models/lookup/dynamic-lookup.component.ts @@ -1,3 +1,5 @@ + +import {distinctUntilChanged} from 'rxjs/operators'; import { ChangeDetectorRef, Component, EventEmitter, Input, OnDestroy, OnInit, Output } from '@angular/core'; import { FormGroup } from '@angular/forms'; @@ -137,8 +139,8 @@ export class DsDynamicLookupComponent implements OnDestroy, OnInit { this.searchOptions.query = this.getCurrentValue(); this.loading = true; - this.authorityService.getEntriesByName(this.searchOptions) - .distinctUntilChanged() + this.authorityService.getEntriesByName(this.searchOptions).pipe( + distinctUntilChanged()) .subscribe((object: IntegrationData) => { this.optionsList = object.payload; this.pageInfo = object.pageInfo; diff --git a/src/app/shared/form/builder/ds-dynamic-form-ui/models/scrollable-dropdown/dynamic-scrollable-dropdown.component.ts b/src/app/shared/form/builder/ds-dynamic-form-ui/models/scrollable-dropdown/dynamic-scrollable-dropdown.component.ts index 1c8bf15f1a..8a1bf21b64 100644 --- a/src/app/shared/form/builder/ds-dynamic-form-ui/models/scrollable-dropdown/dynamic-scrollable-dropdown.component.ts +++ b/src/app/shared/form/builder/ds-dynamic-form-ui/models/scrollable-dropdown/dynamic-scrollable-dropdown.component.ts @@ -1,3 +1,5 @@ + +import {tap} from 'rxjs/operators'; import { ChangeDetectorRef, Component, EventEmitter, Input, OnInit, Output, ViewChild } from '@angular/core'; import { FormGroup } from '@angular/forms'; @@ -66,8 +68,8 @@ export class DsDynamicScrollableDropdownComponent implements OnInit { if (!this.loading && this.pageInfo.currentPage <= this.pageInfo.totalPages) { this.loading = true; this.searchOptions.currentPage++; - this.authorityService.getEntriesByName(this.searchOptions) - .do(() => this.loading = false) + this.authorityService.getEntriesByName(this.searchOptions).pipe( + tap(() => this.loading = false)) .subscribe((object: IntegrationData) => { this.optionsList = this.optionsList.concat(object.payload); this.pageInfo = object.pageInfo; diff --git a/src/app/shared/form/builder/ds-dynamic-form-ui/models/tag/dynamic-tag.component.ts b/src/app/shared/form/builder/ds-dynamic-form-ui/models/tag/dynamic-tag.component.ts index 318259f792..1ccbd21f5c 100644 --- a/src/app/shared/form/builder/ds-dynamic-form-ui/models/tag/dynamic-tag.component.ts +++ b/src/app/shared/form/builder/ds-dynamic-form-ui/models/tag/dynamic-tag.component.ts @@ -1,7 +1,9 @@ + +import {of as observableOf, Observable } from 'rxjs'; + +import {catchError, debounceTime, distinctUntilChanged, tap, switchMap, map, merge} from 'rxjs/operators'; import { ChangeDetectorRef, Component, EventEmitter, Inject, Input, OnInit, Output } from '@angular/core'; import { FormGroup } from '@angular/forms'; - -import { Observable } from 'rxjs'; import { NgbTypeaheadSelectItemEvent } from '@ng-bootstrap/ng-bootstrap'; import { AuthorityService } from '../../../../../../core/integration/authority.service'; @@ -40,33 +42,33 @@ export class DsDynamicTagComponent implements OnInit { formatter = (x: { display: string }) => x.display; search = (text$: Observable) => - text$ - .debounceTime(300) - .distinctUntilChanged() - .do(() => this.changeSearchingStatus(true)) - .switchMap((term) => { + text$.pipe( + debounceTime(300), + distinctUntilChanged(), + tap(() => this.changeSearchingStatus(true)), + switchMap((term) => { if (term === '' || term.length < this.model.minChars) { - return Observable.of({list: []}); + return observableOf({list: []}); } else { this.searchOptions.query = term; - return this.authorityService.getEntriesByName(this.searchOptions) - .map((authorities) => { + return this.authorityService.getEntriesByName(this.searchOptions).pipe( + map((authorities) => { // @TODO Pagination for authority is not working, to refactor when it will be fixed return { list: authorities.payload, pageInfo: authorities.pageInfo }; - }) - .do(() => this.searchFailed = false) - .catch(() => { + }), + tap(() => this.searchFailed = false), + catchError(() => { this.searchFailed = true; - return Observable.of({list: []}); - }); + return observableOf({list: []}); + }),); } - }) - .map((results) => results.list) - .do(() => this.changeSearchingStatus(false)) - .merge(this.hideSearchingWhenUnsubscribed); + }), + map((results) => results.list), + tap(() => this.changeSearchingStatus(false)), + merge(this.hideSearchingWhenUnsubscribed),); constructor(@Inject(GLOBAL_CONFIG) protected EnvConfig: GlobalConfig, private authorityService: AuthorityService, diff --git a/src/app/shared/form/builder/ds-dynamic-form-ui/models/typeahead/dynamic-typeahead.component.ts b/src/app/shared/form/builder/ds-dynamic-form-ui/models/typeahead/dynamic-typeahead.component.ts index dbaa8b4fcd..01285e1228 100644 --- a/src/app/shared/form/builder/ds-dynamic-form-ui/models/typeahead/dynamic-typeahead.component.ts +++ b/src/app/shared/form/builder/ds-dynamic-form-ui/models/typeahead/dynamic-typeahead.component.ts @@ -1,7 +1,9 @@ + +import {of as observableOf, Observable } from 'rxjs'; + +import {distinctUntilChanged, switchMap, tap, filter, catchError, debounceTime, merge, map} from 'rxjs/operators'; import { ChangeDetectorRef, Component, EventEmitter, Input, OnInit, Output } from '@angular/core'; import { FormGroup } from '@angular/forms'; - -import { Observable } from 'rxjs'; import { NgbTypeaheadSelectItemEvent } from '@ng-bootstrap/ng-bootstrap'; import { AuthorityService } from '../../../../../../core/integration/authority.service'; @@ -37,33 +39,33 @@ export class DsDynamicTypeaheadComponent implements OnInit { }; search = (text$: Observable) => - text$ - .debounceTime(300) - .distinctUntilChanged() - .do(() => this.changeSearchingStatus(true)) - .switchMap((term) => { + text$.pipe( + debounceTime(300), + distinctUntilChanged(), + tap(() => this.changeSearchingStatus(true)), + switchMap((term) => { if (term === '' || term.length < this.model.minChars) { - return Observable.of({list: []}); + return observableOf({list: []}); } else { this.searchOptions.query = term; - return this.authorityService.getEntriesByName(this.searchOptions) - .map((authorities) => { + return this.authorityService.getEntriesByName(this.searchOptions).pipe( + map((authorities) => { // @TODO Pagination for authority is not working, to refactor when it will be fixed return { list: authorities.payload, pageInfo: authorities.pageInfo }; - }) - .do(() => this.searchFailed = false) - .catch(() => { + }), + tap(() => this.searchFailed = false), + catchError(() => { this.searchFailed = true; - return Observable.of({list: []}); - }); + return observableOf({list: []}); + }),); } - }) - .map((results) => results.list) - .do(() => this.changeSearchingStatus(false)) - .merge(this.hideSearchingWhenUnsubscribed); + }), + map((results) => results.list), + tap(() => this.changeSearchingStatus(false)), + merge(this.hideSearchingWhenUnsubscribed),); constructor(private authorityService: AuthorityService, private cdr: ChangeDetectorRef) { } @@ -74,8 +76,8 @@ export class DsDynamicTypeaheadComponent implements OnInit { this.model.authorityOptions.scope, this.model.authorityOptions.name, this.model.authorityOptions.metadata); - this.group.get(this.model.id).valueChanges - .filter((value) => this.currentValue !== value) + this.group.get(this.model.id).valueChanges.pipe( + filter((value) => this.currentValue !== value)) .subscribe((value) => { this.currentValue = value; }); diff --git a/src/app/shared/form/form.component.ts b/src/app/shared/form/form.component.ts index c149b51d7b..a8e5ccc499 100644 --- a/src/app/shared/form/form.component.ts +++ b/src/app/shared/form/form.component.ts @@ -1,3 +1,5 @@ + +import {distinctUntilChanged, map, filter} from 'rxjs/operators'; import { ChangeDetectorRef, Component, EventEmitter, Input, OnDestroy, OnInit, Output } from '@angular/core'; import { AbstractControl, FormArray, FormControl, FormGroup } from '@angular/forms'; @@ -8,7 +10,7 @@ import { DynamicFormGroupModel, DynamicFormLayout, } from '@ng-dynamic-forms/core'; -import { Store } from '@ngrx/store'; +import { select, Store } from '@ngrx/store'; import { findIndex } from 'lodash'; import { AppState } from '../../app.reducer'; @@ -143,8 +145,8 @@ export class FormComponent implements OnDestroy, OnInit { this.formValid = this.getFormGroupValidStatus(); - this.subs.push(this.formGroup.statusChanges - .filter((currentStatus) => this.formValid !== this.getFormGroupValidStatus()) + this.subs.push(this.formGroup.statusChanges.pipe( + filter((currentStatus) => this.formValid !== this.getFormGroupValidStatus())) .subscribe((currentStatus) => { // Dispatch a FormStatusChangeAction if the form status has changed this.store.dispatch(new FormStatusChangeAction(this.formId, this.getFormGroupValidStatus())); @@ -152,10 +154,11 @@ export class FormComponent implements OnDestroy, OnInit { })); this.subs.push( - this.store.select(formObjectFromIdSelector(this.formId)) - .filter((formState: FormEntry) => !!formState && (isNotEmpty(formState.errors) || isNotEmpty(this.formErrors))) - .map((formState) => formState.errors) - .distinctUntilChanged() + this.store.pipe( + select(formObjectFromIdSelector(this.formId)), + filter((formState: FormEntry) => !!formState && (isNotEmpty(formState.errors) || isNotEmpty(this.formErrors))), + map((formState) => formState.errors), + distinctUntilChanged(),) // .delay(100) // this terrible delay is here to prevent the detection change error .subscribe((errors: FormError[]) => { const {formGroup, formModel} = this; diff --git a/src/app/shared/form/form.service.ts b/src/app/shared/form/form.service.ts index d9a1402ebd..f17da20db4 100644 --- a/src/app/shared/form/form.service.ts +++ b/src/app/shared/form/form.service.ts @@ -1,7 +1,8 @@ +import { map, distinctUntilChanged, filter } from 'rxjs/operators'; import { Inject, Injectable } from '@angular/core'; import { AbstractControl, FormControl, FormGroup } from '@angular/forms'; import { Observable } from 'rxjs'; -import { Store } from '@ngrx/store'; +import { select, Store } from '@ngrx/store'; import { AppState } from '../../app.reducer'; import { formObjectFromIdSelector } from './selectors'; @@ -25,39 +26,47 @@ export class FormService { * Method to retrieve form's status from state */ public isValid(formId: string): Observable { - return this.store.select(formObjectFromIdSelector(formId)) - .filter((state) => isNotUndefined(state)) - .map((state) => state.valid) - .distinctUntilChanged(); + return this.store.pipe( + select(formObjectFromIdSelector(formId)), + filter((state) => isNotUndefined(state)), + map((state) => state.valid), + distinctUntilChanged() + ); } /** * Method to retrieve form's data from state */ public getFormData(formId: string): Observable { - return this.store.select(formObjectFromIdSelector(formId)) - .filter((state) => isNotUndefined(state)) - .map((state) => state.data) - .distinctUntilChanged(); + return this.store.pipe( + select(formObjectFromIdSelector(formId)), + filter((state) => isNotUndefined(state)), + map((state) => state.data), + distinctUntilChanged() + ); } /** * Method to retrieve form's errors from state */ public getFormErrors(formId: string): Observable { - return this.store.select(formObjectFromIdSelector(formId)) - .filter((state) => isNotUndefined(state)) - .map((state) => state.errors) - .distinctUntilChanged(); + return this.store.pipe( + select(formObjectFromIdSelector(formId)), + filter((state) => isNotUndefined(state)), + map((state) => state.errors), + distinctUntilChanged() + ); } /** * Method to retrieve form's data from state */ public isFormInitialized(formId: string): Observable { - return this.store.select(formObjectFromIdSelector(formId)) - .distinctUntilChanged() - .map((state) => isNotUndefined(state)); + return this.store.pipe( + select(formObjectFromIdSelector(formId)), + distinctUntilChanged(), + map((state) => isNotUndefined(state)) + ); } public getUniqueId(formId): string { @@ -71,7 +80,7 @@ export class FormService { Object.keys(formGroup.controls).forEach((field) => { const control = formGroup.get(field); if (control instanceof FormControl) { - control.markAsTouched({onlySelf: true}); + control.markAsTouched({ onlySelf: true }); } else if (control instanceof FormGroup) { this.validateAllFormFields(control); } diff --git a/src/app/shared/host-window.service.ts b/src/app/shared/host-window.service.ts index 3c26e717d2..9023a4e719 100644 --- a/src/app/shared/host-window.service.ts +++ b/src/app/shared/host-window.service.ts @@ -1,8 +1,9 @@ -import { distinctUntilChanged, map } from 'rxjs/operators'; +import { combineLatest as observableCombineLatest, Observable } from 'rxjs'; + +import { filter, distinctUntilChanged, map } from 'rxjs/operators'; import { HostWindowState } from './host-window.reducer'; import { Injectable } from '@angular/core'; -import { createSelector, Store } from '@ngrx/store'; -import { Observable } from 'rxjs'; +import { createSelector, select, Store } from '@ngrx/store'; import { hasValue } from './empty.util'; import { AppState } from '../app.reducer'; @@ -35,8 +36,10 @@ export class HostWindowService { } private getWidthObs(): Observable { - return this.store.select(widthSelector) - .filter((width) => hasValue(width)); + return this.store.pipe( + select(widthSelector), + filter((width) => hasValue(width)) + ); } get widthCategory(): Observable { @@ -94,10 +97,10 @@ export class HostWindowService { } isXsOrSm(): Observable { - return Observable.combineLatest( - this.isXs(), - this.isSm(), - ((isXs, isSm) => isXs || isSm) - ).distinctUntilChanged(); + return observableCombineLatest( + this.isXs(), + this.isSm(), + ((isXs, isSm) => isXs || isSm) + ).pipe(distinctUntilChanged()); } } diff --git a/src/app/shared/log-in/log-in.component.ts b/src/app/shared/log-in/log-in.component.ts index 3b732e4bae..0868a95b86 100644 --- a/src/app/shared/log-in/log-in.component.ts +++ b/src/app/shared/log-in/log-in.component.ts @@ -1,12 +1,15 @@ +import { filter, takeWhile, map } from 'rxjs/operators'; import { Component, OnDestroy, OnInit } from '@angular/core'; import { FormBuilder, FormGroup, Validators } from '@angular/forms'; -import { Store } from '@ngrx/store'; +import { select, Store } from '@ngrx/store'; import { Observable } from 'rxjs'; - -import { AuthenticateAction, ResetAuthenticationMessagesAction } from '../../core/auth/auth.actions'; +import { + AuthenticateAction, + ResetAuthenticationMessagesAction +} from '../../core/auth/auth.actions'; import { getAuthenticationError, @@ -99,7 +102,7 @@ export class LogInComponent implements OnDestroy, OnInit { */ public ngOnInit() { // set isAuthenticated - this.isAuthenticated = this.store.select(isAuthenticated); + this.isAuthenticated = this.store.pipe(select(isAuthenticated)); // set formGroup this.form = this.formBuilder.group({ @@ -108,29 +111,35 @@ export class LogInComponent implements OnDestroy, OnInit { }); // set error - this.error = this.store.select(getAuthenticationError) - .map((error) => { + this.error = this.store.pipe(select( + getAuthenticationError), + map((error) => { this.hasError = (isNotEmpty(error)); return error; - }); + }) + ); // set error - this.message = this.store.select(getAuthenticationInfo) - .map((message) => { + this.message = this.store.pipe( + select(getAuthenticationInfo), + map((message) => { this.hasMessage = (isNotEmpty(message)); return message; - }); + }) + ); // set loading - this.loading = this.store.select(isAuthenticationLoading); + this.loading = this.store.pipe(select(isAuthenticationLoading)); // subscribe to success - this.store.select(isAuthenticated) - .takeWhile(() => this.alive) - .filter((authenticated) => authenticated) + this.store.pipe( + select(isAuthenticated), + takeWhile(() => this.alive), + filter((authenticated) => authenticated),) .subscribe(() => { - this.authService.redirectToPreviousUrl(); - }); + this.authService.redirectToPreviousUrl(); + } + ); } /** diff --git a/src/app/shared/log-out/log-out.component.ts b/src/app/shared/log-out/log-out.component.ts index 3b821a0edc..9e8e7f7865 100644 --- a/src/app/shared/log-out/log-out.component.ts +++ b/src/app/shared/log-out/log-out.component.ts @@ -2,7 +2,7 @@ import { Component, OnDestroy, OnInit } from '@angular/core'; import { Router } from '@angular/router'; // @ngrx -import { Store } from '@ngrx/store'; +import { select, Store } from '@ngrx/store'; // actions import { LogOutAction } from '../../core/auth/auth.actions'; @@ -48,7 +48,8 @@ export class LogOutComponent implements OnDestroy, OnInit { * @param {Store} store */ constructor(private router: Router, - private store: Store) { } + private store: Store) { + } /** * Lifecycle hook that is called when a directive, pipe or service is destroyed. @@ -62,10 +63,10 @@ export class LogOutComponent implements OnDestroy, OnInit { */ ngOnInit() { // set error - this.error = this.store.select(getLogOutError); + this.error = this.store.pipe(select(getLogOutError)); // set loading - this.loading = this.store.select(isAuthenticationLoading); + this.loading = this.store.pipe(select(isAuthenticationLoading)); } /** diff --git a/src/app/shared/mocks/mock-host-window-service.ts b/src/app/shared/mocks/mock-host-window-service.ts index ac6b58f23a..a9be248240 100644 --- a/src/app/shared/mocks/mock-host-window-service.ts +++ b/src/app/shared/mocks/mock-host-window-service.ts @@ -1,4 +1,4 @@ -import { Observable } from 'rxjs'; +import {of as observableOf, Observable } from 'rxjs'; // declare a stub service export class MockHostWindowService { @@ -14,10 +14,10 @@ export class MockHostWindowService { } isXs(): Observable { - return Observable.of(this.width < 576); + return observableOf(this.width < 576); } isSm(): Observable { - return Observable.of(this.width < 768); + return observableOf(this.width < 768); } } diff --git a/src/app/shared/mocks/mock-item.ts b/src/app/shared/mocks/mock-item.ts index 453b518c87..f3db69a0f2 100644 --- a/src/app/shared/mocks/mock-item.ts +++ b/src/app/shared/mocks/mock-item.ts @@ -1,4 +1,4 @@ -import { Observable } from 'rxjs'; +import {of as observableOf, Observable } from 'rxjs'; import { Item } from '../../core/shared/item.model'; @@ -9,7 +9,7 @@ export const MockItem: Item = Object.assign(new Item(), { isArchived: true, isDiscoverable: true, isWithdrawn: false, - bitstreams: Observable.of({ + bitstreams: observableOf({ self: 'dspace-angular://aggregated/object/1507836003548', requestPending: false, responsePending: false, @@ -28,7 +28,7 @@ export const MockItem: Item = Object.assign(new Item(), { { sizeBytes: 10201, content: 'https://dspace7.4science.it/dspace-spring-rest/api/core/bitstreams/cf9b0c8e-a1eb-4b65-afd0-567366448713/content', - format: Observable.of({ + format: observableOf({ self: 'https://dspace7.4science.it/dspace-spring-rest/api/core/bitstreamformats/10', requestPending: false, responsePending: false, @@ -63,7 +63,7 @@ export const MockItem: Item = Object.assign(new Item(), { { sizeBytes: 31302, content: 'https://dspace7.4science.it/dspace-spring-rest/api/core/bitstreams/99b00f3c-1cc6-4689-8158-91965bee6b28/content', - format: Observable.of({ + format: observableOf({ self: 'https://dspace7.4science.it/dspace-spring-rest/api/core/bitstreamformats/4', requestPending: false, responsePending: false, @@ -195,7 +195,7 @@ export const MockItem: Item = Object.assign(new Item(), { value: 'text' } ], - owningCollection: Observable.of({ + owningCollection: observableOf({ self: 'https://dspace7.4science.it/dspace-spring-rest/api/core/collections/1c11f3f1-ba1f-4f36-908a-3f1ea9a557eb', requestPending: false, responsePending: false, diff --git a/src/app/shared/mocks/mock-request.service.ts b/src/app/shared/mocks/mock-request.service.ts index c87ae3d3fe..d46100d56c 100644 --- a/src/app/shared/mocks/mock-request.service.ts +++ b/src/app/shared/mocks/mock-request.service.ts @@ -1,8 +1,8 @@ -import { Observable } from 'rxjs'; +import {of as observableOf, Observable } from 'rxjs'; import { RequestService } from '../../core/data/request.service'; import { RequestEntry } from '../../core/data/request.reducer'; -export function getMockRequestService(getByHref$: Observable = Observable.of(new RequestEntry())): RequestService { +export function getMockRequestService(getByHref$: Observable = observableOf(new RequestEntry())): RequestService { return jasmine.createSpyObj('requestService', { configure: false, generateRequestId: 'clients/b186e8ce-e99c-4183-bc9a-42b4821bdb78', diff --git a/src/app/shared/mocks/mock-response-cache.service.ts b/src/app/shared/mocks/mock-response-cache.service.ts index 64c8356044..a5a999873d 100644 --- a/src/app/shared/mocks/mock-response-cache.service.ts +++ b/src/app/shared/mocks/mock-response-cache.service.ts @@ -1,10 +1,10 @@ -import { Observable } from 'rxjs'; +import {of as observableOf, Observable } from 'rxjs'; import { ResponseCacheEntry } from '../../core/cache/response-cache.reducer'; import { ResponseCacheService } from '../../core/cache/response-cache.service'; export function getMockResponseCacheService( - add$: Observable = Observable.of(new ResponseCacheEntry()), - get$: Observable = Observable.of(new ResponseCacheEntry()), + add$: Observable = observableOf(new ResponseCacheEntry()), + get$: Observable = observableOf(new ResponseCacheEntry()), has: boolean = false ): ResponseCacheService { return jasmine.createSpyObj('ResponseCacheService', { diff --git a/src/app/shared/mocks/mock-translate-loader.ts b/src/app/shared/mocks/mock-translate-loader.ts index 06a13ae70a..529a257ec0 100644 --- a/src/app/shared/mocks/mock-translate-loader.ts +++ b/src/app/shared/mocks/mock-translate-loader.ts @@ -1,8 +1,8 @@ +import {of as observableOf, Observable } from 'rxjs'; import { TranslateLoader } from '@ngx-translate/core'; -import { Observable } from 'rxjs'; export class MockTranslateLoader implements TranslateLoader { getTranslation(lang: string): Observable { - return Observable.of({}); + return observableOf({}); } } diff --git a/src/app/shared/notifications/notification/notification.component.ts b/src/app/shared/notifications/notification/notification.component.ts index f922ff590d..f3fbe83fde 100644 --- a/src/app/shared/notifications/notification/notification.component.ts +++ b/src/app/shared/notifications/notification/notification.component.ts @@ -1,3 +1,5 @@ + +import {of as observableOf, Observable } from 'rxjs'; import { ChangeDetectionStrategy, ChangeDetectorRef, @@ -21,7 +23,6 @@ import { fromLeftEnter, fromLeftInState, fromLeftLeave, fromLeftOutState } from import { fromTopEnter, fromTopInState, fromTopLeave, fromTopOutState } from '../../animations/fromTop'; import { fadeInEnter, fadeInState, fadeOutLeave, fadeOutState } from '../../animations/fade'; import { NotificationAnimationsStatus } from '../models/notification-animations-type'; -import { Observable } from 'rxjs'; import { isNotEmpty } from '../../empty.util'; @Component({ @@ -130,14 +131,14 @@ export class NotificationComponent implements OnInit, OnDestroy { let value = null; if (isNotEmpty(item)) { if (typeof item === 'string') { - value = Observable.of(item); + value = observableOf(item); } else if (item instanceof Observable) { value = item; } else if (typeof item === 'object' && isNotEmpty(item.value)) { // when notifications state is transferred from SSR to CSR, // Observables Object loses the instance type and become simply object, // so converts it again to Observable - value = Observable.of(item.value); + value = observableOf(item.value); } } this[key] = value diff --git a/src/app/shared/notifications/notifications-board/notifications-board.component.ts b/src/app/shared/notifications/notifications-board/notifications-board.component.ts index 40ea52949a..829cfadf0f 100644 --- a/src/app/shared/notifications/notifications-board/notifications-board.component.ts +++ b/src/app/shared/notifications/notifications-board/notifications-board.component.ts @@ -8,7 +8,7 @@ import { ViewEncapsulation } from '@angular/core'; -import { Store } from '@ngrx/store'; +import { select, Store } from '@ngrx/store'; import { Subscription } from 'rxjs'; import { difference } from 'lodash'; @@ -50,7 +50,7 @@ export class NotificationsBoardComponent implements OnInit, OnDestroy { } ngOnInit(): void { - this.sub = this.store.select(notificationsStateSelector) + this.sub = this.store.pipe(select(notificationsStateSelector)) .subscribe((state: NotificationsState) => { if (state.length === 0) { this.notifications = []; diff --git a/src/app/shared/notifications/notifications.effects.ts b/src/app/shared/notifications/notifications.effects.ts index f2627f1806..20f2b618cb 100644 --- a/src/app/shared/notifications/notifications.effects.ts +++ b/src/app/shared/notifications/notifications.effects.ts @@ -12,14 +12,14 @@ export class NotificationsEffects { */ /* @Effect() public timer: Observable = this.actions$ - .ofType(NotificationsActionTypes.NEW_NOTIFICATION_WITH_TIMER) + .pipe(ofType(NotificationsActionTypes.NEW_NOTIFICATION_WITH_TIMER), // .debounceTime((action: any) => action.payload.options.timeOut) - .debounceTime(3000) - .map(() => new RemoveNotificationAction()); + debounceTime(3000), + map(() => new RemoveNotificationAction()); .switchMap((action: NewNotificationWithTimerAction) => Observable .timer(30000) .mapTo(() => new RemoveNotificationAction()) - );*/ + ));*/ /** * @constructor diff --git a/src/app/shared/notifications/notifications.service.ts b/src/app/shared/notifications/notifications.service.ts index 8cf067f4de..d6bb210652 100644 --- a/src/app/shared/notifications/notifications.service.ts +++ b/src/app/shared/notifications/notifications.service.ts @@ -1,3 +1,5 @@ + +import {of as observableOf, Observable } from 'rxjs'; import { Inject, Injectable } from '@angular/core'; import { INotification, Notification } from './models/notification.model'; import { NotificationType } from './models/notification-type'; @@ -5,7 +7,6 @@ import { NotificationOptions } from './models/notification-options.model'; import { uniqueId } from 'lodash'; import { Store } from '@ngrx/store'; import { NewNotificationAction, RemoveAllNotificationsAction, RemoveNotificationAction } from './notifications.actions'; -import { Observable } from 'rxjs'; import { GLOBAL_CONFIG, GlobalConfig } from '../../../config'; @Injectable() @@ -21,8 +22,8 @@ export class NotificationsService { this.store.dispatch(notificationAction); } - success(title: any = Observable.of(''), - content: any = Observable.of(''), + success(title: any = observableOf(''), + content: any = observableOf(''), options: NotificationOptions = this.getDefaultOptions(), html: boolean = false): INotification { const notification = new Notification(uniqueId(), NotificationType.Success, title, content, options, html); @@ -30,8 +31,8 @@ export class NotificationsService { return notification; } - error(title: any = Observable.of(''), - content: any = Observable.of(''), + error(title: any = observableOf(''), + content: any = observableOf(''), options: NotificationOptions = this.getDefaultOptions(), html: boolean = false): INotification { const notification = new Notification(uniqueId(), NotificationType.Error, title, content, options, html); @@ -39,8 +40,8 @@ export class NotificationsService { return notification; } - info(title: any = Observable.of(''), - content: any = Observable.of(''), + info(title: any = observableOf(''), + content: any = observableOf(''), options: NotificationOptions = this.getDefaultOptions(), html: boolean = false): INotification { const notification = new Notification(uniqueId(), NotificationType.Info, title, content, options, html); @@ -48,8 +49,8 @@ export class NotificationsService { return notification; } - warning(title: any = Observable.of(''), - content: any = Observable.of(''), + warning(title: any = observableOf(''), + content: any = observableOf(''), options: NotificationOptions = this.getDefaultOptions(), html: boolean = false): INotification { const notification = new Notification(uniqueId(), NotificationType.Warning, title, content, options, html); diff --git a/src/app/shared/object-collection/object-collection.component.ts b/src/app/shared/object-collection/object-collection.component.ts index 637b2f3a5f..0018c55c7f 100644 --- a/src/app/shared/object-collection/object-collection.component.ts +++ b/src/app/shared/object-collection/object-collection.component.ts @@ -1,3 +1,5 @@ + +import {map} from 'rxjs/operators'; import { Component, EventEmitter, Input, OnInit, @@ -88,11 +90,11 @@ export class ObjectCollectionComponent implements OnChanges, OnInit { } getViewMode(): ViewMode { - this.route.queryParams.map((params) => { + this.route.queryParams.pipe(map((params) => { if (isNotEmpty(params.view) && hasValue(params.view)) { this.currentMode = params.view; } - }); + })); return this.currentMode; } diff --git a/src/app/shared/object-grid/object-grid.component.ts b/src/app/shared/object-grid/object-grid.component.ts index db600b48a9..c5ded101b3 100644 --- a/src/app/shared/object-grid/object-grid.component.ts +++ b/src/app/shared/object-grid/object-grid.component.ts @@ -1,3 +1,7 @@ + +import {combineLatest as observableCombineLatest, BehaviorSubject , Observable } from 'rxjs'; + +import {startWith, distinctUntilChanged, map } from 'rxjs/operators'; import { ChangeDetectionStrategy, Component, @@ -6,8 +10,6 @@ import { Output, ViewEncapsulation } from '@angular/core'; -import { BehaviorSubject , Observable } from 'rxjs'; -import { distinctUntilChanged, map } from 'rxjs/operators'; import { SortDirection, SortOptions } from '../../core/cache/models/sort-options.model'; import { PaginatedList } from '../../core/data/paginated-list'; @@ -105,9 +107,9 @@ export class ObjectGridComponent implements OnInit { } }), distinctUntilChanged() - ).startWith(3); + ).pipe(startWith(3)); - this.columns$ = Observable.combineLatest( + this.columns$ = observableCombineLatest( nbColumns$, this._objects$, (nbColumns, objects) => { diff --git a/src/app/shared/pagination/pagination.component.ts b/src/app/shared/pagination/pagination.component.ts index cfed30b012..0dc1892e47 100644 --- a/src/app/shared/pagination/pagination.component.ts +++ b/src/app/shared/pagination/pagination.component.ts @@ -11,15 +11,14 @@ import { import { ActivatedRoute, Router } from '@angular/router'; -import { Subscription , Observable } from 'rxjs'; -import { isNumeric } from 'rxjs/util'; - +import { Subscription, Observable } from 'rxjs'; import { HostWindowService } from '../host-window.service'; import { HostWindowState } from '../host-window.reducer'; import { PaginationComponentOptions } from './pagination-component-options.model'; import { SortDirection, SortOptions } from '../../core/cache/models/sort-options.model'; import { hasValue, isNotEmpty } from '../empty.util'; import { PageInfo } from '../../core/shared/page-info.model'; +import { isNumeric } from 'tslint'; /** * The default pagination controls component. diff --git a/src/app/shared/services/api.service.ts b/src/app/shared/services/api.service.ts index 96e1007f37..4f8474e0c1 100644 --- a/src/app/shared/services/api.service.ts +++ b/src/app/shared/services/api.service.ts @@ -1,4 +1,6 @@ import { throwError as observableThrowError } from 'rxjs'; +import { catchError } from 'rxjs/operators'; + import { Injectable } from '@angular/core'; import { HttpClient } from '@angular/common/http'; @@ -12,11 +14,11 @@ export class ApiService { * whatever domain/feature method name */ get(url: string, options?: any) { - return this._http.get(url, options) - .catch((err) => { + return this._http.get(url, options).pipe( + catchError((err) => { console.log('Error: ', err); return observableThrowError(err); - }); + })); } } diff --git a/src/app/shared/services/route.service.ts b/src/app/shared/services/route.service.ts index fcb6f80f29..8565379007 100644 --- a/src/app/shared/services/route.service.ts +++ b/src/app/shared/services/route.service.ts @@ -1,3 +1,5 @@ + +import {distinctUntilChanged, map} from 'rxjs/operators'; import { Injectable } from '@angular/core'; import { Observable } from 'rxjs'; import { @@ -13,24 +15,24 @@ export class RouteService { } getQueryParameterValues(paramName: string): Observable { - return this.route.queryParamMap.map((map) => [...map.getAll(paramName)]).distinctUntilChanged(); + return this.route.queryParamMap.pipe(map((map) => [...map.getAll(paramName)]),distinctUntilChanged(),); } getQueryParameterValue(paramName: string): Observable { - return this.route.queryParamMap.map((map) => map.get(paramName)).distinctUntilChanged(); + return this.route.queryParamMap.pipe(map((map) => map.get(paramName)),distinctUntilChanged(),); } hasQueryParam(paramName: string): Observable { - return this.route.queryParamMap.map((map) => map.has(paramName)).distinctUntilChanged(); + return this.route.queryParamMap.pipe(map((map) => map.has(paramName)),distinctUntilChanged(),); } hasQueryParamWithValue(paramName: string, paramValue: string): Observable { - return this.route.queryParamMap.map((map) => map.getAll(paramName).indexOf(paramValue) > -1).distinctUntilChanged(); + return this.route.queryParamMap.pipe(map((map) => map.getAll(paramName).indexOf(paramValue) > -1),distinctUntilChanged(),); } getQueryParamsWithPrefix(prefix: string): Observable { - return this.route.queryParamMap - .map((map) => { + return this.route.queryParamMap.pipe( + map((map) => { const params = {}; map.keys .filter((key) => key.startsWith(prefix)) @@ -38,7 +40,7 @@ export class RouteService { params[key] = [...map.getAll(key)]; }); return params; - }) - .distinctUntilChanged((a, b) => JSON.stringify(a) === JSON.stringify(b)); + }), + distinctUntilChanged((a, b) => JSON.stringify(a) === JSON.stringify(b)),); } } diff --git a/src/app/shared/shared.module.ts b/src/app/shared/shared.module.ts index bc8292d6bb..5cc90d4e07 100644 --- a/src/app/shared/shared.module.ts +++ b/src/app/shared/shared.module.ts @@ -4,7 +4,12 @@ import { RouterModule } from '@angular/router'; import { FormsModule, ReactiveFormsModule } from '@angular/forms'; import { NouisliderModule } from 'ng2-nouislider'; -import { NgbDatepickerModule, NgbModule, NgbTimepickerModule, NgbTypeaheadModule } from '@ng-bootstrap/ng-bootstrap'; +import { + NgbDatepickerModule, + NgbModule, + NgbTimepickerModule, + NgbTypeaheadModule +} from '@ng-bootstrap/ng-bootstrap'; import { TranslateModule } from '@ngx-translate/core'; @@ -56,8 +61,6 @@ import { DsDynamicFormComponent } from './form/builder/ds-dynamic-form-ui/ds-dyn import { DynamicFormsCoreModule } from '@ng-dynamic-forms/core'; import { DynamicFormsNGBootstrapUIModule } from '@ng-dynamic-forms/ui-ng-bootstrap'; import { TextMaskModule } from 'angular2-text-mask'; -import { NotificationComponent } from './notifications/notification/notification.component'; -import { NotificationsBoardComponent } from './notifications/notifications-board/notifications-board.component'; import { DragClickDirective } from './utils/drag-click.directive'; import { TruncatePipe } from './utils/truncate.pipe'; import { TruncatableComponent } from './truncatable/truncatable.component'; @@ -78,8 +81,8 @@ import { ClickOutsideDirective } from './utils/click-outside.directive'; import { EmphasizePipe } from './utils/emphasize.pipe'; import { InputSuggestionsComponent } from './input-suggestions/input-suggestions.component'; import { CapitalizePipe } from './utils/capitalize.pipe'; -import { MomentModule } from 'angular2-moment'; import { ObjectKeysPipe } from './utils/object-keys-pipe'; +import { MomentModule } from 'ngx-moment'; const MODULES = [ // Do NOT include UniversalModule, HttpModule, or JsonpModule here diff --git a/src/app/shared/testing/active-router-stub.ts b/src/app/shared/testing/active-router-stub.ts index e09ff2299a..89a417149a 100644 --- a/src/app/shared/testing/active-router-stub.ts +++ b/src/app/shared/testing/active-router-stub.ts @@ -1,3 +1,5 @@ + +import {map} from 'rxjs/operators'; import { convertToParamMap, ParamMap, Params } from '@angular/router'; import { BehaviorSubject } from 'rxjs'; @@ -10,7 +12,7 @@ export class ActivatedRouteStub { params = this.subject.asObservable(); queryParams = this.subject.asObservable(); - queryParamMap = this.subject.asObservable().map((params: Params) => convertToParamMap(params)); + queryParamMap = this.subject.asObservable().pipe(map((params: Params) => convertToParamMap(params))); constructor(params?: Params) { if (params) { diff --git a/src/app/shared/testing/auth-request-service-stub.ts b/src/app/shared/testing/auth-request-service-stub.ts index 8a38fff9e7..7ade392aa0 100644 --- a/src/app/shared/testing/auth-request-service-stub.ts +++ b/src/app/shared/testing/auth-request-service-stub.ts @@ -1,4 +1,4 @@ -import { Observable } from 'rxjs'; +import {of as observableOf, Observable } from 'rxjs'; import { HttpOptions } from '../../core/dspace-rest-v2/dspace-rest-v2.service'; import { AuthStatus } from '../../core/auth/models/auth-status.model'; import { AuthTokenInfo } from '../../core/auth/models/auth-token-info.model'; @@ -31,7 +31,7 @@ export class AuthRequestServiceStub { authStatusStub.authenticated = false; } } - return Observable.of(authStatusStub); + return observableOf(authStatusStub); } public getRequest(method: string, options?: HttpOptions): Observable { @@ -51,7 +51,7 @@ export class AuthRequestServiceStub { } break; } - return Observable.of(authStatusStub); + return observableOf(authStatusStub); } private validateToken(token): boolean { diff --git a/src/app/shared/testing/auth-service-stub.ts b/src/app/shared/testing/auth-service-stub.ts index 2746eb392e..ea0993d8dd 100644 --- a/src/app/shared/testing/auth-service-stub.ts +++ b/src/app/shared/testing/auth-service-stub.ts @@ -1,5 +1,6 @@ + +import {of as observableOf, Observable } from 'rxjs'; import { AuthStatus } from '../../core/auth/models/auth-status.model'; -import { Observable } from 'rxjs'; import { AuthTokenInfo } from '../../core/auth/models/auth-token-info.model'; import { EpersonMock } from './eperson-mock'; import { Eperson } from '../../core/eperson/models/eperson.model'; @@ -20,7 +21,7 @@ export class AuthServiceStub { authStatus.authenticated = true; authStatus.token = this.token; authStatus.eperson = [EpersonMock]; - return Observable.of(authStatus); + return observableOf(authStatus); } else { console.log('error'); throw(new Error('Message Error test')); @@ -29,7 +30,7 @@ export class AuthServiceStub { public authenticatedUser(token: AuthTokenInfo): Observable { if (token.accessToken === 'token_test') { - return Observable.of(EpersonMock); + return observableOf(EpersonMock); } else { throw(new Error('Message Error test')); } @@ -44,11 +45,11 @@ export class AuthServiceStub { } public hasValidAuthenticationToken(): Observable { - return Observable.of(this.token); + return observableOf(this.token); } public logout(): Observable { - return Observable.of(true); + return observableOf(true); } public isTokenExpired(token?: AuthTokenInfo): boolean { @@ -70,11 +71,11 @@ export class AuthServiceStub { } public isTokenExpiring(): Observable { - return Observable.of(false); + return observableOf(false); } public refreshAuthenticationToken(token: AuthTokenInfo): Observable { - return Observable.of(this.token); + return observableOf(this.token); } public redirectToPreviousUrl() { diff --git a/src/app/shared/testing/authority-service-stub.ts b/src/app/shared/testing/authority-service-stub.ts index cc74708172..1122901f7f 100644 --- a/src/app/shared/testing/authority-service-stub.ts +++ b/src/app/shared/testing/authority-service-stub.ts @@ -1,4 +1,4 @@ -import { Observable } from 'rxjs'; +import {of as observableOf, Observable } from 'rxjs'; import { IntegrationSearchOptions } from '../../core/integration/models/integration-options.model'; import { IntegrationData } from '../../core/integration/integration-data'; import { PageInfo } from '../../core/shared/page-info.model'; @@ -16,6 +16,6 @@ export class AuthorityServiceStub { } getEntriesByName(options: IntegrationSearchOptions) { - return Observable.of(new IntegrationData(new PageInfo(), this._payload)); + return observableOf(new IntegrationData(new PageInfo(), this._payload)); } } diff --git a/src/app/shared/testing/hal-endpoint-service-stub.ts b/src/app/shared/testing/hal-endpoint-service-stub.ts index deefef7f2a..46d6a452a3 100644 --- a/src/app/shared/testing/hal-endpoint-service-stub.ts +++ b/src/app/shared/testing/hal-endpoint-service-stub.ts @@ -1,9 +1,9 @@ -import { Observable } from 'rxjs'; +import { of as observableOf } from 'rxjs'; export class HALEndpointServiceStub { constructor(private url: string) {}; getEndpoint(path: string) { - return Observable.of(this.url + '/' + path); + return observableOf(this.url + '/' + path); } } diff --git a/src/app/shared/testing/host-window-service-stub.ts b/src/app/shared/testing/host-window-service-stub.ts index df1bb567fc..ecb8c26acb 100644 --- a/src/app/shared/testing/host-window-service-stub.ts +++ b/src/app/shared/testing/host-window-service-stub.ts @@ -1,4 +1,4 @@ -import { Observable } from 'rxjs'; +import {of as observableOf, Observable } from 'rxjs'; // declare a stub service export class HostWindowServiceStub { @@ -14,7 +14,7 @@ export class HostWindowServiceStub { } isXs(): Observable { - return Observable.of(this.width < 576); + return observableOf(this.width < 576); } isXsOrSm(): Observable { diff --git a/src/app/shared/testing/mock-store.ts b/src/app/shared/testing/mock-store.ts index f366ad45ab..fd47c71ae0 100644 --- a/src/app/shared/testing/mock-store.ts +++ b/src/app/shared/testing/mock-store.ts @@ -1,3 +1,5 @@ + +import {map} from 'rxjs/operators'; import { Action } from '@ngrx/store'; import { Observable , BehaviorSubject } from 'rxjs'; @@ -12,8 +14,8 @@ export class MockStore extends BehaviorSubject { }; select = (pathOrMapFn: any): Observable => { - return this.asObservable() - .map((value) => pathOrMapFn.projector(value)) + return this.asObservable().pipe( + map((value) => pathOrMapFn.projector(value))) }; nextState(_newState: T) { diff --git a/src/app/shared/testing/mock-translate-loader.ts b/src/app/shared/testing/mock-translate-loader.ts index 06a13ae70a..529a257ec0 100644 --- a/src/app/shared/testing/mock-translate-loader.ts +++ b/src/app/shared/testing/mock-translate-loader.ts @@ -1,8 +1,8 @@ +import {of as observableOf, Observable } from 'rxjs'; import { TranslateLoader } from '@ngx-translate/core'; -import { Observable } from 'rxjs'; export class MockTranslateLoader implements TranslateLoader { getTranslation(lang: string): Observable { - return Observable.of({}); + return observableOf({}); } } diff --git a/src/app/shared/testing/notifications-service-stub.ts b/src/app/shared/testing/notifications-service-stub.ts index d8ec867fea..16588c2017 100644 --- a/src/app/shared/testing/notifications-service-stub.ts +++ b/src/app/shared/testing/notifications-service-stub.ts @@ -1,32 +1,32 @@ -import { Observable } from 'rxjs'; +import {of as observableOf, Observable } from 'rxjs'; import { INotification } from '../notifications/models/notification.model'; import { NotificationOptions } from '../notifications/models/notification-options.model'; export class NotificationsServiceStub { - success(title: any = Observable.of(''), - content: any = Observable.of(''), + success(title: any = observableOf(''), + content: any = observableOf(''), options: NotificationOptions = this.getDefaultOptions(), html?: any): INotification { return } - error(title: any = Observable.of(''), - content: any = Observable.of(''), + error(title: any = observableOf(''), + content: any = observableOf(''), options: NotificationOptions = this.getDefaultOptions(), html?: any): INotification { return } - info(title: any = Observable.of(''), - content: any = Observable.of(''), + info(title: any = observableOf(''), + content: any = observableOf(''), options: NotificationOptions = this.getDefaultOptions(), html?: any): INotification { return } - warning(title: any = Observable.of(''), - content: any = Observable.of(''), + warning(title: any = observableOf(''), + content: any = observableOf(''), options: NotificationOptions = this.getDefaultOptions(), html?: any): INotification { return diff --git a/src/app/shared/testing/search-service-stub.ts b/src/app/shared/testing/search-service-stub.ts index f58e6df954..cbc0611a47 100644 --- a/src/app/shared/testing/search-service-stub.ts +++ b/src/app/shared/testing/search-service-stub.ts @@ -1,4 +1,4 @@ -import { Observable, BehaviorSubject } from 'rxjs'; +import {of as observableOf, Observable , BehaviorSubject } from 'rxjs'; import { ViewMode } from '../../core/shared/view-mode.model'; export class SearchServiceStub { @@ -38,6 +38,6 @@ export class SearchServiceStub { } getFilterLabels() { - return Observable.of([]); + return observableOf([]); } } diff --git a/src/app/shared/truncatable/truncatable.service.ts b/src/app/shared/truncatable/truncatable.service.ts index c25bf30c27..60e8a7df41 100644 --- a/src/app/shared/truncatable/truncatable.service.ts +++ b/src/app/shared/truncatable/truncatable.service.ts @@ -1,8 +1,13 @@ +import { map } from 'rxjs/operators'; import { Injectable } from '@angular/core'; -import { createSelector, MemoizedSelector, Store } from '@ngrx/store'; +import { createSelector, MemoizedSelector, select, Store } from '@ngrx/store'; import { Observable } from 'rxjs'; import { TruncatablesState, TruncatableState } from './truncatable.reducer'; -import { TruncatableExpandAction, TruncatableToggleAction, TruncatableCollapseAction } from './truncatable.actions'; +import { + TruncatableExpandAction, + TruncatableToggleAction, + TruncatableCollapseAction +} from './truncatable.actions'; import { hasValue } from '../empty.util'; const truncatableStateSelector = (state: TruncatablesState) => state.truncatable; @@ -22,14 +27,16 @@ export class TruncatableService { * @returns {Observable} Emits true if the state in the store is currently collapsed for the given truncatable component */ isCollapsed(id: string): Observable { - return this.store.select(truncatableByIdSelector(id)) - .map((object: TruncatableState) => { + return this.store.pipe( + select(truncatableByIdSelector(id)), + map((object: TruncatableState) => { if (object) { return object.collapsed; } else { return false; } - }); + }) + ); } /** diff --git a/src/app/shared/uploader/uploader.component.ts b/src/app/shared/uploader/uploader.component.ts index ac3e701ca2..c43ac91082 100644 --- a/src/app/shared/uploader/uploader.component.ts +++ b/src/app/shared/uploader/uploader.component.ts @@ -1,3 +1,5 @@ + +import {of as observableOf, Observable } from 'rxjs'; import { ChangeDetectionStrategy, ChangeDetectorRef, @@ -10,7 +12,6 @@ import { } from '@angular/core' import { FileUploader } from 'ng2-file-upload'; -import { Observable } from 'rxjs'; import { uniqueId } from 'lodash'; import { ScrollToConfigOptions, ScrollToService } from '@nicky-lenaers/ngx-scroll-to'; @@ -60,8 +61,8 @@ export class UploaderComponent { public uploader: FileUploader; public uploaderId: string; - public isOverBaseDropZone = Observable.of(false); - public isOverDocumentDropZone = Observable.of(false); + public isOverBaseDropZone = observableOf(false); + public isOverDocumentDropZone = observableOf(false); @HostListener('window:dragover', ['$event']) onDragOver(event: any) { @@ -70,7 +71,7 @@ export class UploaderComponent { // Show drop area on the page event.preventDefault(); if ((event.target as any).tagName !== 'HTML') { - this.isOverDocumentDropZone = Observable.of(true); + this.isOverDocumentDropZone = observableOf(true); } } } @@ -111,7 +112,7 @@ export class UploaderComponent { }); this.uploader.onBeforeUploadItem = () => { this.onBeforeUpload(); - this.isOverDocumentDropZone = Observable.of(false); + this.isOverDocumentDropZone = observableOf(false); // Move page target to the uploader const config: ScrollToConfigOptions = { @@ -133,7 +134,7 @@ export class UploaderComponent { * Called when files are dragged on the base drop area. */ public fileOverBase(isOver: boolean): void { - this.isOverBaseDropZone = Observable.of(isOver); + this.isOverBaseDropZone = observableOf(isOver); } /** @@ -141,7 +142,7 @@ export class UploaderComponent { */ public fileOverDocument(isOver: boolean) { if (!isOver) { - this.isOverDocumentDropZone = Observable.of(isOver); + this.isOverDocumentDropZone = observableOf(isOver); } } diff --git a/src/app/shared/utils/debounce.directive.ts b/src/app/shared/utils/debounce.directive.ts index 3e6b0e6d22..48cabe006f 100644 --- a/src/app/shared/utils/debounce.directive.ts +++ b/src/app/shared/utils/debounce.directive.ts @@ -1,3 +1,5 @@ + +import {distinctUntilChanged, debounceTime, takeUntil} from 'rxjs/operators'; import { Directive, Input, Output, EventEmitter, OnDestroy, OnInit } from '@angular/core'; import { NgControl } from '@angular/forms'; @@ -44,10 +46,10 @@ export class DebounceDirective implements OnInit, OnDestroy { * Emit it when the debounceTime is over without new changes */ ngOnInit() { - this.model.valueChanges - .takeUntil(this.subject) - .debounceTime(this.dsDebounce) - .distinctUntilChanged() + this.model.valueChanges.pipe( + takeUntil(this.subject), + debounceTime(this.dsDebounce), + distinctUntilChanged(),) .subscribe((modelValue) => { if (this.isFirstChange) { this.isFirstChange = false; diff --git a/src/app/store.effects.ts b/src/app/store.effects.ts index f264c0f9bd..b13e816652 100644 --- a/src/app/store.effects.ts +++ b/src/app/store.effects.ts @@ -1,27 +1,33 @@ +import { of as observableOf } from 'rxjs'; + +import { map } from 'rxjs/operators'; import { Injectable } from '@angular/core'; import { Action, Store } from '@ngrx/store'; -import { Effect, Actions } from '@ngrx/effects'; - -import { Observable } from 'rxjs'; +import { Actions, Effect, ofType } from '@ngrx/effects'; import { AppState } from './app.reducer'; -import { StoreAction, StoreActionTypes } from './store.actions'; -import { HostWindowResizeAction, HostWindowActionTypes } from './shared/host-window.actions'; +import { StoreActionTypes } from './store.actions'; +import { HostWindowResizeAction } from './shared/host-window.actions'; @Injectable() export class StoreEffects { - @Effect({ dispatch: false }) replay = this.actions.ofType(StoreActionTypes.REPLAY).map((replayAction: Action) => { - // TODO: should be able to replay all actions before the browser attempts to - // replayAction.payload.forEach((action: Action) => { - // this.store.dispatch(action); - // }); - return Observable.of({}); - }); + @Effect({ dispatch: false }) replay = this.actions.pipe( + ofType(StoreActionTypes.REPLAY), + map((replayAction: Action) => { + // TODO: should be able to replay all actions before the browser attempts to + // replayAction.payload.forEach((action: Action) => { + // this.store.dispatch(action); + // }); + return observableOf({}); + })); - @Effect() resize = this.actions.ofType(StoreActionTypes.REPLAY, StoreActionTypes.REHYDRATE).map(() => new HostWindowResizeAction(window.innerWidth, window.innerHeight)); + @Effect() resize = this.actions.pipe( + ofType(StoreActionTypes.REPLAY, StoreActionTypes.REHYDRATE), + map(() => new HostWindowResizeAction(window.innerWidth, window.innerHeight)) + ); constructor(private actions: Actions, private store: Store) { diff --git a/src/modules/transfer-state/dspace-server-transfer-state.service.ts b/src/modules/transfer-state/dspace-server-transfer-state.service.ts index 380bb3f9f3..ac8c817d84 100644 --- a/src/modules/transfer-state/dspace-server-transfer-state.service.ts +++ b/src/modules/transfer-state/dspace-server-transfer-state.service.ts @@ -1,3 +1,5 @@ + +import {take} from 'rxjs/operators'; import { Injectable } from '@angular/core'; import { DSpaceTransferState } from './dspace-transfer-state.service'; @@ -6,7 +8,7 @@ export class DSpaceServerTransferState extends DSpaceTransferState { transfer() { this.transferState.onSerialize(DSpaceTransferState.NGRX_STATE, () => { let state; - this.store.take(1).subscribe((saveState: any) => { + this.store.pipe(take(1)).subscribe((saveState: any) => { state = saveState; }); diff --git a/yarn.lock b/yarn.lock index 561cdcf27d..7e479f9404 100644 --- a/yarn.lock +++ b/yarn.lock @@ -267,16 +267,16 @@ resolved "https://registry.yarnpkg.com/@types/minimatch/-/minimatch-2.0.29.tgz#5002e14f75e2d71e564281df0431c8c1b4a2a36a" "@types/node@*": - version "10.9.1" - resolved "https://registry.yarnpkg.com/@types/node/-/node-10.9.1.tgz#06f002136fbcf51e730995149050bb3c45ee54e6" + version "10.9.2" + resolved "https://registry.yarnpkg.com/@types/node/-/node-10.9.2.tgz#f0ab8dced5cd6c56b26765e1c0d9e4fdcc9f2a00" "@types/node@^6.0.46": version "6.0.116" resolved "https://registry.yarnpkg.com/@types/node/-/node-6.0.116.tgz#2f9cd62b4ecc4927e3942e2655c182eecf5b45f1" "@types/node@^9.4.6": - version "9.6.29" - resolved "https://registry.yarnpkg.com/@types/node/-/node-9.6.29.tgz#9b3c5b288c77fbd2ab5684d36e3528cb9ee5429f" + version "9.6.30" + resolved "https://registry.yarnpkg.com/@types/node/-/node-9.6.30.tgz#1ecf83eaf7ac2d0dada7a9d61a1e4e7a6183ac06" "@types/q@^0.0.32": version "0.0.32" @@ -318,6 +318,10 @@ version "0.0.30" resolved "https://registry.yarnpkg.com/@types/strip-json-comments/-/strip-json-comments-0.0.30.tgz#9aa30c04db212a9a0649d6ae6fd50accc40748a1" +"@types/tapable@1.0.2": + version "1.0.2" + resolved "https://registry.yarnpkg.com/@types/tapable/-/tapable-1.0.2.tgz#e13182e1b69871a422d7863e11a4a6f5b814a4bd" + "@types/uuid@^3.4.3": version "3.4.3" resolved "https://registry.yarnpkg.com/@types/uuid/-/uuid-3.4.3.tgz#121ace265f5569ce40f4f6d0ff78a338c732a754" @@ -816,13 +820,6 @@ array-flatten@^2.1.0: version "2.1.1" resolved "https://registry.yarnpkg.com/array-flatten/-/array-flatten-2.1.1.tgz#426bb9da84090c1838d812c8150af20a8331e296" -array-includes@^3.0.3: - version "3.0.3" - resolved "https://registry.yarnpkg.com/array-includes/-/array-includes-3.0.3.tgz#184b48f62d92d7452bb31b323165c7f8bd02266d" - dependencies: - define-properties "^1.1.2" - es-abstract "^1.7.0" - array-map@~0.0.0: version "0.0.0" resolved "https://registry.yarnpkg.com/array-map/-/array-map-0.0.0.tgz#88a2bab73d1cf7bcd5c1b118a003f66f665fa662" @@ -2127,7 +2124,7 @@ convert-source-map@^0.3.3: version "0.3.5" resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-0.3.5.tgz#f1d802950af7dd2631a1febe0596550c86ab3190" -convert-source-map@^1.1.1, convert-source-map@^1.5.0: +convert-source-map@^1.5.0, convert-source-map@^1.5.1: version "1.5.1" resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-1.5.1.tgz#b8278097b9bc229365de5c62cf5fcaed8b5599e5" @@ -2960,7 +2957,7 @@ error-ex@^1.2.0, error-ex@^1.3.1: dependencies: is-arrayish "^0.2.1" -es-abstract@^1.4.3, es-abstract@^1.5.1, es-abstract@^1.6.1, es-abstract@^1.7.0: +es-abstract@^1.4.3, es-abstract@^1.5.1, es-abstract@^1.6.1: version "1.12.0" resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.12.0.tgz#9dbbdd27c6856f0001421ca18782d786bf8a6165" dependencies: @@ -3479,6 +3476,12 @@ find-up@^2.0.0, find-up@^2.1.0: dependencies: locate-path "^2.0.0" +find-up@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/find-up/-/find-up-3.0.0.tgz#49169f1d7993430646da61ecc5ae355c21c97b73" + dependencies: + locate-path "^3.0.0" + flatten@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/flatten/-/flatten-1.0.2.tgz#dae46a9d78fbe25292258cc1e780a41d95c03782" @@ -3679,8 +3682,8 @@ gaze@^1.0.0: globule "^1.0.0" generate-function@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/generate-function/-/generate-function-2.0.0.tgz#6858fe7c0969b7d4e9093337647ac79f60dfbe74" + version "2.2.0" + resolved "https://registry.yarnpkg.com/generate-function/-/generate-function-2.2.0.tgz#1aeac896147293d27bce65eb295ce5f3f094a292" generate-object-property@^1.1.0: version "1.2.0" @@ -3763,19 +3766,9 @@ glob@^5.0.15: once "^1.3.0" path-is-absolute "^1.0.0" -glob@^6.0.4: - version "6.0.4" - resolved "https://registry.yarnpkg.com/glob/-/glob-6.0.4.tgz#0f08860f6a155127b2fadd4f9ce24b1aab6e4d22" - dependencies: - inflight "^1.0.4" - inherits "2" - minimatch "2 || 3" - once "^1.3.0" - path-is-absolute "^1.0.0" - glob@^7.0.0, glob@^7.0.3, glob@^7.0.5, glob@^7.0.6, glob@^7.1.0, glob@^7.1.1, glob@^7.1.2, glob@~7.1.1: - version "7.1.2" - resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.2.tgz#c19c9df9a028702d678612384a6552404c636d15" + version "7.1.3" + resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.3.tgz#3960832d3f1574108342dafd3a67b332c0969df1" dependencies: fs.realpath "^1.0.0" inflight "^1.0.4" @@ -4135,16 +4128,16 @@ html-minifier@^3.2.3: relateurl "0.2.x" uglify-js "3.4.x" -html-webpack-plugin@3.2.0: - version "3.2.0" - resolved "https://registry.yarnpkg.com/html-webpack-plugin/-/html-webpack-plugin-3.2.0.tgz#b01abbd723acaaa7b37b6af4492ebda03d9dd37b" +html-webpack-plugin@^4.0.0-alpha: + version "4.0.0-alpha" + resolved "https://registry.yarnpkg.com/html-webpack-plugin/-/html-webpack-plugin-4.0.0-alpha.tgz#b2c7b6d4885a209c999dfce3ffb9866e2c8c0eaa" dependencies: + "@types/tapable" "1.0.2" html-minifier "^3.2.3" - loader-utils "^0.2.16" - lodash "^4.17.3" + loader-utils "^1.1.0" + lodash "^4.17.10" pretty-error "^2.0.2" tapable "^1.0.0" - toposort "^1.0.0" util.promisify "1.0.0" htmlescape@^1.1.0: @@ -5298,6 +5291,13 @@ locate-path@^2.0.0: p-locate "^2.0.0" path-exists "^3.0.0" +locate-path@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-3.0.0.tgz#dbec3b3ab759758071b58fe59fc41871af21400e" + dependencies: + p-locate "^3.0.0" + path-exists "^3.0.0" + lodash._baseassign@^3.0.0: version "3.2.0" resolved "https://registry.yarnpkg.com/lodash._baseassign/-/lodash._baseassign-3.2.0.tgz#8c38a099500f215ad09e59f1722fd0c52bfe0a4e" @@ -5468,7 +5468,7 @@ lodash.uniq@^4.5.0: version "4.5.0" resolved "https://registry.yarnpkg.com/lodash.uniq/-/lodash.uniq-4.5.0.tgz#d0225373aeb652adc1bc82e4945339a842754773" -lodash@4.17.10, lodash@^4.0.0, lodash@^4.0.1, lodash@^4.13.1, lodash@^4.15.0, lodash@^4.17.10, lodash@^4.17.3, lodash@^4.17.4, lodash@^4.17.5, lodash@^4.3.0, lodash@^4.5.0, lodash@^4.8.0, lodash@~4.17.10: +lodash@4.17.10, lodash@^4.0.0, lodash@^4.0.1, lodash@^4.13.1, lodash@^4.15.0, lodash@^4.17.10, lodash@^4.17.4, lodash@^4.17.5, lodash@^4.3.0, lodash@^4.5.0, lodash@^4.8.0, lodash@~4.17.10: version "4.17.10" resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.10.tgz#1b7793cf7259ea38fb3661d4d38b3260af8ae4e7" @@ -5779,19 +5779,15 @@ miller-rabin@^4.0.0: bn.js "^4.0.0" brorand "^1.0.1" -"mime-db@>= 1.34.0 < 2": +"mime-db@>= 1.34.0 < 2", mime-db@~1.36.0: version "1.36.0" resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.36.0.tgz#5020478db3c7fe93aad7bbcc4dcf869c43363397" -mime-db@~1.35.0: - version "1.35.0" - resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.35.0.tgz#0569d657466491283709663ad379a99b90d9ab47" - mime-types@^2.1.11, mime-types@^2.1.12, mime-types@~2.1.17, mime-types@~2.1.18, mime-types@~2.1.19, mime-types@~2.1.7: - version "2.1.19" - resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.19.tgz#71e464537a7ef81c15f2db9d97e913fc0ff606f0" + version "2.1.20" + resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.20.tgz#930cb719d571e903738520f8470911548ca2cc19" dependencies: - mime-db "~1.35.0" + mime-db "~1.36.0" mime@1.4.1: version "1.4.1" @@ -5965,8 +5961,8 @@ mute-stream@0.0.7: resolved "https://registry.yarnpkg.com/mute-stream/-/mute-stream-0.0.7.tgz#3075ce93bc21b8fab43e1bc4da7e8115ed1e7bab" nan@^2.10.0, nan@^2.9.2: - version "2.10.0" - resolved "https://registry.yarnpkg.com/nan/-/nan-2.10.0.tgz#96d0cd610ebd58d4b4de9cc0c6828cda99c7548f" + version "2.11.0" + resolved "https://registry.yarnpkg.com/nan/-/nan-2.11.0.tgz#574e360e4d954ab16966ec102c0c049fd961a099" nanomatch@^1.2.9: version "1.2.13" @@ -6032,6 +6028,12 @@ ngx-infinite-scroll@6.0.1: dependencies: opencollective "^1.0.3" +ngx-moment@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/ngx-moment/-/ngx-moment-3.1.0.tgz#41380b4dd8b68e7bd6d17cc6fe7f703ae506dc3a" + dependencies: + tslib "^1.9.0" + ngx-pagination@3.0.3: version "3.0.3" resolved "https://registry.yarnpkg.com/ngx-pagination/-/ngx-pagination-3.0.3.tgz#314145263613738d8c544da36cd8dacc5aa89a6f" @@ -6534,12 +6536,24 @@ p-limit@^1.0.0, p-limit@^1.1.0: dependencies: p-try "^1.0.0" +p-limit@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-2.0.0.tgz#e624ed54ee8c460a778b3c9f3670496ff8a57aec" + dependencies: + p-try "^2.0.0" + p-locate@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-2.0.0.tgz#20a0103b222a70c8fd39cc2e580680f3dde5ec43" dependencies: p-limit "^1.1.0" +p-locate@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-3.0.0.tgz#322d69a05c0264b25997d9f40cd8a891ab0064a4" + dependencies: + p-limit "^2.0.0" + p-map@^1.1.1: version "1.2.0" resolved "https://registry.yarnpkg.com/p-map/-/p-map-1.2.0.tgz#e4e94f311eabbc8633a1e79908165fca26241b6b" @@ -6548,6 +6562,10 @@ p-try@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/p-try/-/p-try-1.0.0.tgz#cbc79cdbaf8fd4228e13f621f2b1a237c1b207b3" +p-try@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/p-try/-/p-try-2.0.0.tgz#85080bb87c64688fa47996fe8f7dfbe8211760b1" + pac-proxy-agent@^2.0.1: version "2.0.2" resolved "https://registry.yarnpkg.com/pac-proxy-agent/-/pac-proxy-agent-2.0.2.tgz#90d9f6730ab0f4d2607dcdcd4d3d641aa26c3896" @@ -8129,18 +8147,18 @@ resolve-from@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-3.0.0.tgz#b22c7af7d9d6881bc8b6e653335eebcb0a188748" -resolve-url-loader@2.2.1: - version "2.2.1" - resolved "https://registry.yarnpkg.com/resolve-url-loader/-/resolve-url-loader-2.2.1.tgz#13a1396fb773edf959550e400e688f5ed32548bf" +resolve-url-loader@^2.3.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/resolve-url-loader/-/resolve-url-loader-2.3.0.tgz#e1b37034d48f22f8cfb9f04c026faaa070fdaf26" dependencies: adjust-sourcemap-loader "^1.1.0" - camelcase "^4.0.0" - convert-source-map "^1.1.1" - loader-utils "^1.0.0" + camelcase "^4.1.0" + convert-source-map "^1.5.1" + loader-utils "^1.1.0" lodash.defaults "^4.0.0" rework "^1.0.1" rework-visit "^1.0.0" - source-map "^0.5.6" + source-map "^0.5.7" urix "^0.1.0" resolve-url@^0.2.1: @@ -8912,8 +8930,8 @@ statuses@~1.4.0: resolved "https://registry.yarnpkg.com/statuses/-/statuses-1.4.0.tgz#bb73d446da2796106efcc1b601a253d6c46bd087" stdout-stream@^1.4.0: - version "1.4.0" - resolved "https://registry.yarnpkg.com/stdout-stream/-/stdout-stream-1.4.0.tgz#a2c7c8587e54d9427ea9edb3ac3f2cd522df378b" + version "1.4.1" + resolved "https://registry.yarnpkg.com/stdout-stream/-/stdout-stream-1.4.1.tgz#5ac174cdd5cd726104aa0c0b2bd83815d8d535de" dependencies: readable-stream "^2.0.1" @@ -9286,10 +9304,6 @@ to-string-loader@1.1.5: dependencies: loader-utils "^0.2.16" -toposort@^1.0.0: - version "1.0.7" - resolved "https://registry.yarnpkg.com/toposort/-/toposort-1.0.7.tgz#2e68442d9f64ec720b8cc89e6443ac6caa950029" - touch@^3.1.0: version "3.1.0" resolved "https://registry.yarnpkg.com/touch/-/touch-3.1.0.tgz#fe365f5f75ec9ed4e56825e0bb76d24ab74af83b" @@ -9326,10 +9340,10 @@ trim-right@^1.0.1: resolved "https://registry.yarnpkg.com/trim-right/-/trim-right-1.0.1.tgz#cb2e1203067e0c8de1f614094b9fe45704ea6003" "true-case-path@^1.0.2": - version "1.0.2" - resolved "https://registry.yarnpkg.com/true-case-path/-/true-case-path-1.0.2.tgz#7ec91130924766c7f573be3020c34f8fdfd00d62" + version "1.0.3" + resolved "https://registry.yarnpkg.com/true-case-path/-/true-case-path-1.0.3.tgz#f813b5a8c86b40da59606722b144e3225799f47d" dependencies: - glob "^6.0.4" + glob "^7.1.2" tryer@^1.0.0: version "1.0.1" @@ -9477,14 +9491,10 @@ typescript@2.4.1: version "2.4.1" resolved "https://registry.yarnpkg.com/typescript/-/typescript-2.4.1.tgz#c3ccb16ddaa0b2314de031e7e6fee89e5ba346bc" -typescript@^2.5.0: +typescript@^2.5.0, typescript@^2.9.1: version "2.9.2" resolved "https://registry.yarnpkg.com/typescript/-/typescript-2.9.2.tgz#1cbf61d05d6b96269244eb6a3bce4bd914e0f00c" -typescript@^2.9.1: - version "2.9.1" - resolved "https://registry.yarnpkg.com/typescript/-/typescript-2.9.1.tgz#fdb19d2c67a15d11995fd15640e373e09ab09961" - uglify-es@^3.3.4, uglify-es@^3.3.7: version "3.3.9" resolved "https://registry.yarnpkg.com/uglify-es/-/uglify-es-3.3.9.tgz#0c1c4f0700bed8dbc124cdb304d2592ca203e677" @@ -9921,18 +9931,6 @@ webpack-command@^0.4.1: webpack-log "^1.1.2" wordwrap "^1.0.0" -webpack-dev-middleware@3.1.3: - version "3.1.3" - resolved "https://registry.yarnpkg.com/webpack-dev-middleware/-/webpack-dev-middleware-3.1.3.tgz#8b32aa43da9ae79368c1bf1183f2b6cf5e1f39ed" - dependencies: - loud-rejection "^1.6.0" - memory-fs "~0.4.1" - mime "^2.1.0" - path-is-absolute "^1.0.0" - range-parser "^1.0.3" - url-join "^4.0.0" - webpack-log "^1.0.1" - webpack-dev-middleware@3.2.0: version "3.2.0" resolved "https://registry.yarnpkg.com/webpack-dev-middleware/-/webpack-dev-middleware-3.2.0.tgz#a20ceef194873710052da678f3c6ee0aeed92552" @@ -9958,11 +9956,10 @@ webpack-dev-middleware@^2.0.6: webpack-log "^1.0.1" webpack-dev-server@^3.1.5: - version "3.1.5" - resolved "https://registry.yarnpkg.com/webpack-dev-server/-/webpack-dev-server-3.1.5.tgz#87477252e1ac6789303fb8cd3e585fa5d508a401" + version "3.1.6" + resolved "https://registry.yarnpkg.com/webpack-dev-server/-/webpack-dev-server-3.1.6.tgz#8617503768b1131fd539cf43c3e2e63bd34c1521" dependencies: ansi-html "0.0.7" - array-includes "^3.0.3" bonjour "^3.5.0" chokidar "^2.0.0" compression "^1.5.2" @@ -9986,9 +9983,9 @@ webpack-dev-server@^3.1.5: spdy "^3.4.1" strip-ansi "^3.0.0" supports-color "^5.1.0" - webpack-dev-middleware "3.1.3" - webpack-log "^1.1.2" - yargs "11.0.0" + webpack-dev-middleware "3.2.0" + webpack-log "^2.0.0" + yargs "12.0.1" webpack-log@^1.0.1, webpack-log@^1.1.2: version "1.2.0" @@ -10197,7 +10194,7 @@ y18n@^3.2.1: version "3.2.1" resolved "https://registry.yarnpkg.com/y18n/-/y18n-3.2.1.tgz#6d15fba884c08679c0d77e88e7759e811e07fa41" -y18n@^4.0.0: +"y18n@^3.2.1 || ^4.0.0", y18n@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/y18n/-/y18n-4.0.0.tgz#95ef94f85ecc81d007c264e190a120f0a3c8566b" @@ -10209,7 +10206,7 @@ yallist@^3.0.0, yallist@^3.0.2: version "3.0.2" resolved "https://registry.yarnpkg.com/yallist/-/yallist-3.0.2.tgz#8452b4bb7e83c7c188d8041c1a837c773d6d8bb9" -yargs-parser@^10.0.0: +yargs-parser@^10.0.0, yargs-parser@^10.1.0: version "10.1.0" resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-10.1.0.tgz#7202265b89f7e9e9f2e5765e0fe735a905edbaa8" dependencies: @@ -10227,13 +10224,13 @@ yargs-parser@^9.0.2: dependencies: camelcase "^4.1.0" -yargs@11.0.0: - version "11.0.0" - resolved "https://registry.yarnpkg.com/yargs/-/yargs-11.0.0.tgz#c052931006c5eee74610e5fc0354bedfd08a201b" +yargs@12.0.1: + version "12.0.1" + resolved "https://registry.yarnpkg.com/yargs/-/yargs-12.0.1.tgz#6432e56123bb4e7c3562115401e98374060261c2" dependencies: cliui "^4.0.0" - decamelize "^1.1.1" - find-up "^2.1.0" + decamelize "^2.0.0" + find-up "^3.0.0" get-caller-file "^1.0.1" os-locale "^2.0.0" require-directory "^2.1.1" @@ -10241,8 +10238,8 @@ yargs@11.0.0: set-blocking "^2.0.0" string-width "^2.0.0" which-module "^2.0.0" - y18n "^3.2.1" - yargs-parser "^9.0.2" + y18n "^3.2.1 || ^4.0.0" + yargs-parser "^10.1.0" yargs@^11.0.0: version "11.1.0" From 28d7a169fc3b88200daf4c0f3097cb70f09aecd3 Mon Sep 17 00:00:00 2001 From: Kristof De Langhe Date: Thu, 30 Aug 2018 10:05:09 +0200 Subject: [PATCH 08/48] removed browse-by pages empty test files --- .../browse-by-author-page.component.spec.ts | 0 .../+browse-by-title-page/browse-by-title-page.component.spec.ts | 0 2 files changed, 0 insertions(+), 0 deletions(-) delete mode 100644 src/app/+browse-by/+browse-by-author-page/browse-by-author-page.component.spec.ts delete mode 100644 src/app/+browse-by/+browse-by-title-page/browse-by-title-page.component.spec.ts diff --git a/src/app/+browse-by/+browse-by-author-page/browse-by-author-page.component.spec.ts b/src/app/+browse-by/+browse-by-author-page/browse-by-author-page.component.spec.ts deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/src/app/+browse-by/+browse-by-title-page/browse-by-title-page.component.spec.ts b/src/app/+browse-by/+browse-by-title-page/browse-by-title-page.component.spec.ts deleted file mode 100644 index e69de29bb2..0000000000 From f11d486d1478508c6ea4092990ed790727896bdf Mon Sep 17 00:00:00 2001 From: lotte Date: Fri, 31 Aug 2018 15:40:39 +0200 Subject: [PATCH 09/48] updated angular/rxjs to v6 successfully --- package.json | 33 +- rollup.config.js | 5 +- .../bitstream-formats.component.spec.ts | 5 +- .../metadata-registry.component.spec.ts | 6 +- .../metadata-schema.component.spec.ts | 14 +- .../collections/collections.component.spec.ts | 6 +- .../full-file-section.component.ts | 7 +- .../+login-page/login-page.component.spec.ts | 4 +- .../paginated-search-options.model.spec.ts | 1 - .../search-facet-filter.component.spec.ts | 12 +- .../search-facet-filter.component.ts | 42 +- .../search-filter.component.spec.ts | 14 +- .../search-filter.service.spec.ts | 16 +- .../search-filter/search-filter.service.ts | 30 +- .../search-range-filter.component.spec.ts | 14 +- .../search-range-filter.component.ts | 21 +- .../search-filters.component.spec.ts | 6 +- .../search-labels.component.spec.ts | 6 +- .../search-page.component.spec.ts | 29 +- .../search-configuration.service.spec.ts | 6 +- .../search-configuration.service.ts | 31 +- .../search-service/search.service.spec.ts | 34 +- .../search-service/search.service.ts | 59 +- .../search-settings.component.spec.ts | 19 +- .../search-settings.component.ts | 1 - .../search-sidebar.service.spec.ts | 12 +- .../search-sidebar/search-sidebar.service.ts | 7 +- src/app/app.component.spec.ts | 2 +- src/app/core/auth/auth.effects.spec.ts | 4 +- src/app/core/auth/auth.interceptor.spec.ts | 4 +- src/app/core/auth/auth.service.spec.ts | 4 +- src/app/core/browse/browse.service.spec.ts | 2 +- .../builders/remote-data-build.service.ts | 42 +- .../core/cache/object-cache.service.spec.ts | 19 +- .../core/cache/response-cache.service.spec.ts | 15 +- src/app/core/config/config.service.spec.ts | 2 +- src/app/core/data/comcol-data.service.spec.ts | 3 +- .../data/dspace-object-data.service.spec.ts | 2 +- src/app/core/data/item-data.service.spec.ts | 2 +- .../integration/integration.service.spec.ts | 2 +- .../core/metadata/metadata.service.spec.ts | 14 +- .../core/registry/registry.service.spec.ts | 57 +- src/app/core/registry/registry.service.ts | 31 +- src/app/core/shared/item.model.spec.ts | 18 +- src/app/core/shared/operators.spec.ts | 2 +- src/app/header/header.component.spec.ts | 10 +- .../ds-dynamic-form-control.component.spec.ts | 6 +- .../ds-dynamic-form-control.component.ts | 16 +- .../dynamic-group.component.spec.ts | 22 +- .../dynamic-group/dynamic-group.components.ts | 2 +- .../models/tag/dynamic-tag.component.spec.ts | 5 +- .../dynamic-typeahead.component.spec.ts | 5 +- .../form/builder/form-builder.service.spec.ts | 18 +- src/app/shared/host-window.service.spec.ts | 13 +- src/app/shared/host-window.service.ts | 8 +- .../notifications.service.spec.ts | 18 +- .../object-collection.component.spec.ts | 4 +- .../item-grid-element.component.spec.ts | 6 +- .../object-grid/object-grid.component.ts | 44 +- ...arch-result-grid-element.component.spec.ts | 4 +- ...arch-result-grid-element.component.spec.ts | 4 +- ...arch-result-grid-element.component.spec.ts | 10 +- .../wrapper-grid-element.component.spec.ts | 4 +- .../item-list-element.component.spec.ts | 6 +- ...arch-result-list-element.component.spec.ts | 4 +- ...arch-result-list-element.component.spec.ts | 4 +- ...arch-result-list-element.component.spec.ts | 10 +- .../shared/pagination/pagination.component.ts | 3 +- src/app/shared/services/route.service.spec.ts | 6 +- src/app/shared/services/route.service.ts | 41 +- .../truncatable-part.component.spec.ts | 6 +- .../truncatable/truncatable.component.spec.ts | 6 +- .../truncatable/truncatable.service.spec.ts | 4 +- webpack.config.js | 22 +- webpack/webpack.common.js | 186 +-- webpack/webpack.prod.js | 8 +- webpack/webpack.test.js | 13 +- yarn.lock | 1146 +++++------------ 78 files changed, 968 insertions(+), 1361 deletions(-) diff --git a/package.json b/package.json index b3e16e29e8..3ba25572b0 100644 --- a/package.json +++ b/package.json @@ -25,7 +25,7 @@ "prebuild:prod": "yarn run prebuild", "build": "webpack --progress --mode development", "build:aot": "webpack --env.aot --env.server --mode development && webpack --env.aot --env.client --mode development", - "build:prod": "webpack --env.aot --env.server --mode production && webpack --env.aot --env.client --mode production", + "build:prod": "webpack --env.aot --env.server --env.production && webpack --env.aot --env.client --env.production", "postbuild:prod": "yarn run rollup", "rollup": "rollup -c rollup.config.js", "prestart": "yarn run build:prod", @@ -120,6 +120,7 @@ "ts-md5": "^1.2.4", "uuid": "^3.2.1", "webfontloader": "1.6.28", + "webpack-cli": "^3.1.0", "zone.js": "^0.8.26" }, "devDependencies": { @@ -131,37 +132,36 @@ "@types/cookie-parser": "1.4.1", "@types/deep-freeze": "0.1.1", "@types/express": "^4.11.1", - "@types/express-serve-static-core": "4.11.1", + "@types/express-serve-static-core": "4.16.0", "@types/hammerjs": "2.0.35", "@types/jasmine": "^2.8.6", "@types/js-cookie": "2.1.0", "@types/lodash": "^4.14.110", "@types/memory-cache": "0.2.0", "@types/mime": "2.0.0", - "@types/node": "^9.4.6", - "@types/serve-static": "1.13.1", + "@types/node": "^10.9.4", + "@types/serve-static": "1.13.2", "@types/uuid": "^3.4.3", "@types/webfontloader": "1.6.29", "ajv": "^6.1.1", "ajv-keywords": "^3.1.0", "angular2-template-loader": "0.6.2", - "autoprefixer": "^8.0.0", - "awesome-typescript-loader": "3.4.1", + "autoprefixer": "^9.1.3", + "awesome-typescript-loader": "5.2.0", "caniuse-lite": "^1.0.30000697", "codelyzer": "^4.4.4", "compression-webpack-plugin": "^1.1.6", "copy-webpack-plugin": "^4.4.1", "coveralls": "3.0.0", - "css-loader": "0.28.9", + "css-loader": "1.0.0", "deep-freeze": "0.0.1", "exports-loader": "^0.7.0", "html-webpack-plugin": "^4.0.0-alpha", - "imports-loader": "0.7.1", + "imports-loader": "0.8.0", "istanbul-instrumenter-loader": "3.0.1", "jasmine-core": "^3.2.1", "jasmine-marbles": "0.3.0", "jasmine-spec-reporter": "4.2.1", - "json-loader": "0.5.7", "karma": "2.0.0", "karma-chrome-launcher": "2.2.0", "karma-cli": "1.0.1", @@ -191,25 +191,24 @@ "raw-loader": "0.5.1", "resolve-url-loader": "^2.3.0", "rimraf": "2.6.2", - "rollup": "^0.56.0", - "rollup-plugin-commonjs": "^8.3.0", - "rollup-plugin-node-globals": "1.1.0", + "rollup": "^0.65.0", + "rollup-plugin-commonjs": "^9.1.6", + "rollup-plugin-node-globals": "1.2.1", "rollup-plugin-node-resolve": "^3.0.3", - "rollup-plugin-uglify": "3.0.0", + "rollup-plugin-terser": "^2.0.2", "sass-loader": "6.0.6", "script-ext-html-webpack-plugin": "2.0.1", - "source-map": "0.6.1", - "source-map-loader": "0.2.3", + "source-map": "0.7.3", + "source-map-loader": "0.2.4", "string-replace-loader": "2.1.1", "to-string-loader": "1.1.5", "ts-helpers": "1.1.2", "ts-node": "4.1.0", - "tslint": "5.9.1", + "tslint": "5.11.0", "typedoc": "^0.9.0", "typescript": "^2.9.1", "webpack": "^4.17.1", "webpack-bundle-analyzer": "^2.13.1", - "webpack-command": "^0.4.1", "webpack-dev-middleware": "3.2.0", "webpack-dev-server": "^3.1.5", "webpack-merge": "4.1.4", diff --git a/rollup.config.js b/rollup.config.js index 8c8700d387..33e3ec3346 100644 --- a/rollup.config.js +++ b/rollup.config.js @@ -1,6 +1,6 @@ import nodeResolve from 'rollup-plugin-node-resolve' import commonjs from 'rollup-plugin-commonjs'; -import uglify from 'rollup-plugin-uglify' +import terser from 'rollup-plugin-terser' export default { input: 'dist/client.js', @@ -8,7 +8,6 @@ export default { file: 'dist/client.js', format: 'iife', }, - sourcemap: false, plugins: [ nodeResolve({ jsnext: true, @@ -17,6 +16,6 @@ export default { commonjs({ include: 'node_modules/rxjs/**' }), - uglify() + terser.terser() ] } diff --git a/src/app/+admin/admin-registries/bitstream-formats/bitstream-formats.component.spec.ts b/src/app/+admin/admin-registries/bitstream-formats/bitstream-formats.component.spec.ts index 681ad65a83..b6e3b7e989 100644 --- a/src/app/+admin/admin-registries/bitstream-formats/bitstream-formats.component.spec.ts +++ b/src/app/+admin/admin-registries/bitstream-formats/bitstream-formats.component.spec.ts @@ -1,14 +1,13 @@ import { BitstreamFormatsComponent } from './bitstream-formats.component'; import { async, ComponentFixture, TestBed } from '@angular/core/testing'; import { RegistryService } from '../../../core/registry/registry.service'; -import { Observable } from 'rxjs'; +import { of as observableOf } from 'rxjs'; import { RemoteData } from '../../../core/data/remote-data'; import { PaginatedList } from '../../../core/data/paginated-list'; import { CommonModule } from '@angular/common'; import { RouterTestingModule } from '@angular/router/testing'; import { TranslateModule } from '@ngx-translate/core'; import { By } from '@angular/platform-browser'; -import { SharedModule } from '../../../shared/shared.module'; import { PaginationComponent } from '../../../shared/pagination/pagination.component'; import { NgbModule } from '@ng-bootstrap/ng-bootstrap'; import { EnumKeysPipe } from '../../../shared/utils/enum-keys-pipe'; @@ -53,7 +52,7 @@ describe('BitstreamFormatsComponent', () => { extensions: null } ]; - const mockFormats = Observable.of(new RemoteData(false, false, true, undefined, new PaginatedList(null, mockFormatsList))); + const mockFormats = observableOf(new RemoteData(false, false, true, undefined, new PaginatedList(null, mockFormatsList))); const registryServiceStub = { getBitstreamFormats: () => mockFormats }; diff --git a/src/app/+admin/admin-registries/metadata-registry/metadata-registry.component.spec.ts b/src/app/+admin/admin-registries/metadata-registry/metadata-registry.component.spec.ts index 0184bf9245..dc118a1dea 100644 --- a/src/app/+admin/admin-registries/metadata-registry/metadata-registry.component.spec.ts +++ b/src/app/+admin/admin-registries/metadata-registry/metadata-registry.component.spec.ts @@ -1,6 +1,6 @@ import { MetadataRegistryComponent } from './metadata-registry.component'; import { async, ComponentFixture, TestBed } from '@angular/core/testing'; -import { Observable } from 'rxjs'; +import { of as observableOf } from 'rxjs'; import { RemoteData } from '../../../core/data/remote-data'; import { PaginatedList } from '../../../core/data/paginated-list'; import { TranslateModule } from '@ngx-translate/core'; @@ -8,13 +8,13 @@ import { By } from '@angular/platform-browser'; import { CommonModule } from '@angular/common'; import { RouterTestingModule } from '@angular/router/testing'; import { RegistryService } from '../../../core/registry/registry.service'; -import { SharedModule } from '../../../shared/shared.module'; import { NgbModule } from '@ng-bootstrap/ng-bootstrap'; import { EnumKeysPipe } from '../../../shared/utils/enum-keys-pipe'; import { PaginationComponent } from '../../../shared/pagination/pagination.component'; import { HostWindowServiceStub } from '../../../shared/testing/host-window-service-stub'; import { HostWindowService } from '../../../shared/host-window.service'; + describe('MetadataRegistryComponent', () => { let comp: MetadataRegistryComponent; let fixture: ComponentFixture; @@ -33,7 +33,7 @@ describe('MetadataRegistryComponent', () => { namespace: 'http://dspace.org/mockschema' } ]; - const mockSchemas = Observable.of(new RemoteData(false, false, true, undefined, new PaginatedList(null, mockSchemasList))); + const mockSchemas = observableOf(new RemoteData(false, false, true, undefined, new PaginatedList(null, mockSchemasList))); const registryServiceStub = { getMetadataSchemas: () => mockSchemas }; diff --git a/src/app/+admin/admin-registries/metadata-schema/metadata-schema.component.spec.ts b/src/app/+admin/admin-registries/metadata-schema/metadata-schema.component.spec.ts index 9a56d9b5b9..96777116f4 100644 --- a/src/app/+admin/admin-registries/metadata-schema/metadata-schema.component.spec.ts +++ b/src/app/+admin/admin-registries/metadata-schema/metadata-schema.component.spec.ts @@ -1,16 +1,14 @@ import { MetadataSchemaComponent } from './metadata-schema.component'; import { async, ComponentFixture, TestBed } from '@angular/core/testing'; -import { Observable } from 'rxjs'; +import { of as observableOf } from 'rxjs'; import { RemoteData } from '../../../core/data/remote-data'; import { PaginatedList } from '../../../core/data/paginated-list'; import { MetadataSchema } from '../../../core/metadata/metadataschema.model'; -import { TranslateLoader, TranslateModule } from '@ngx-translate/core'; +import { TranslateModule } from '@ngx-translate/core'; import { CommonModule } from '@angular/common'; import { ActivatedRoute, Router } from '@angular/router'; import { By } from '@angular/platform-browser'; -import { MockTranslateLoader } from '../../../shared/testing/mock-translate-loader'; import { RegistryService } from '../../../core/registry/registry.service'; -import { SharedModule } from '../../../shared/shared.module'; import { NgbModule } from '@ng-bootstrap/ng-bootstrap'; import { EnumKeysPipe } from '../../../shared/utils/enum-keys-pipe'; import { PaginationComponent } from '../../../shared/pagination/pagination.component'; @@ -68,15 +66,15 @@ describe('MetadataSchemaComponent', () => { schema: mockSchemasList[1] } ]; - const mockSchemas = Observable.of(new RemoteData(false, false, true, undefined, new PaginatedList(null, mockSchemasList))); + const mockSchemas = observableOf(new RemoteData(false, false, true, undefined, new PaginatedList(null, mockSchemasList))); const registryServiceStub = { getMetadataSchemas: () => mockSchemas, - getMetadataFieldsBySchema: (schema: MetadataSchema) => Observable.of(new RemoteData(false, false, true, undefined, new PaginatedList(null, mockFieldsList.filter((value) => value.schema === schema)))), - getMetadataSchemaByName: (schemaName: string) => Observable.of(new RemoteData(false, false, true, undefined, mockSchemasList.filter((value) => value.prefix === schemaName)[0])) + getMetadataFieldsBySchema: (schema: MetadataSchema) => observableOf(new RemoteData(false, false, true, undefined, new PaginatedList(null, mockFieldsList.filter((value) => value.schema === schema)))), + getMetadataSchemaByName: (schemaName: string) => observableOf(new RemoteData(false, false, true, undefined, mockSchemasList.filter((value) => value.prefix === schemaName)[0])) }; const schemaNameParam = 'mock'; const activatedRouteStub = Object.assign(new ActivatedRouteStub(), { - params: Observable.of({ + params: observableOf({ schemaName: schemaNameParam }) }); diff --git a/src/app/+item-page/field-components/collections/collections.component.spec.ts b/src/app/+item-page/field-components/collections/collections.component.spec.ts index d836c86a8c..865ce78a39 100644 --- a/src/app/+item-page/field-components/collections/collections.component.spec.ts +++ b/src/app/+item-page/field-components/collections/collections.component.spec.ts @@ -6,7 +6,7 @@ import { Collection } from '../../../core/shared/collection.model'; import { RemoteDataBuildService } from '../../../core/cache/builders/remote-data-build.service'; import { getMockRemoteDataBuildService } from '../../../shared/mocks/mock-remote-data-build.service'; import { Item } from '../../../core/shared/item.model'; -import { Observable } from 'rxjs'; +import { of as observableOf } from 'rxjs'; import { RemoteData } from '../../../core/data/remote-data'; import { TranslateModule } from '@ngx-translate/core'; @@ -22,8 +22,8 @@ const mockCollection1: Collection = Object.assign(new Collection(), { }] }); -const succeededMockItem: Item = Object.assign(new Item(), {owningCollection: Observable.of(new RemoteData(false, false, true, null, mockCollection1))}); -const failedMockItem: Item = Object.assign(new Item(), {owningCollection: Observable.of(new RemoteData(false, false, false, null, mockCollection1))}); +const succeededMockItem: Item = Object.assign(new Item(), {owningCollection: observableOf(new RemoteData(false, false, true, null, mockCollection1))}); +const failedMockItem: Item = Object.assign(new Item(), {owningCollection: observableOf(new RemoteData(false, false, false, null, mockCollection1))}); describe('CollectionsComponent', () => { beforeEach(async(() => { diff --git a/src/app/+item-page/full/field-components/file-section/full-file-section.component.ts b/src/app/+item-page/full/field-components/file-section/full-file-section.component.ts index db3c30aea2..23d9ef05d0 100644 --- a/src/app/+item-page/full/field-components/file-section/full-file-section.component.ts +++ b/src/app/+item-page/full/field-components/file-section/full-file-section.component.ts @@ -1,11 +1,10 @@ - -import {combineLatest as observableCombineLatest, Observable } from 'rxjs'; +import { combineLatest as observableCombineLatest, Observable } from 'rxjs'; import { Component, Input, OnInit } from '@angular/core'; import { Bitstream } from '../../../../core/shared/bitstream.model'; import { Item } from '../../../../core/shared/item.model'; import { FileSectionComponent } from '../../../simple/field-components/file-section/file-section.component'; -import { hasValue } from '../../../../shared/empty.util'; +import { map } from 'rxjs/operators'; /** * This component renders the file section of the item @@ -34,7 +33,7 @@ export class FullFileSectionComponent extends FileSectionComponent implements On initialize(): void { const originals = this.item.getFiles(); const licenses = this.item.getBitstreamsByBundleName('LICENSE'); - this.bitstreamsObs = observableCombineLatest(originals, licenses, (o, l) => [...o, ...l]); + this.bitstreamsObs = observableCombineLatest(originals, licenses).pipe(map(([o, l]) => [...o, ...l])); this.bitstreamsObs.subscribe( (files) => files.forEach( diff --git a/src/app/+login-page/login-page.component.spec.ts b/src/app/+login-page/login-page.component.spec.ts index b917a3299b..a0cb44d0d4 100644 --- a/src/app/+login-page/login-page.component.spec.ts +++ b/src/app/+login-page/login-page.component.spec.ts @@ -3,7 +3,7 @@ import { async, ComponentFixture, TestBed } from '@angular/core/testing'; import { Store } from '@ngrx/store'; import { TranslateModule } from '@ngx-translate/core'; -import { Observable } from 'rxjs'; +import { of as observableOf } from 'rxjs'; import 'rxjs/add/observable/of'; import { LoginPageComponent } from './login-page.component'; @@ -16,7 +16,7 @@ describe('LoginPageComponent', () => { /* tslint:disable:no-empty */ dispatch: {}, /* tslint:enable:no-empty */ - select: Observable.of(true) + select: observableOf(true) }); beforeEach(async(() => { diff --git a/src/app/+search-page/paginated-search-options.model.spec.ts b/src/app/+search-page/paginated-search-options.model.spec.ts index e8688fd84f..22b3f146b2 100644 --- a/src/app/+search-page/paginated-search-options.model.spec.ts +++ b/src/app/+search-page/paginated-search-options.model.spec.ts @@ -1,4 +1,3 @@ -import 'rxjs/add/observable/of'; import { SortDirection, SortOptions } from '../core/cache/models/sort-options.model'; import { PaginationComponentOptions } from '../shared/pagination/pagination-component-options.model'; import { PaginatedSearchOptions } from './paginated-search-options.model'; diff --git a/src/app/+search-page/search-filters/search-filter/search-facet-filter/search-facet-filter.component.spec.ts b/src/app/+search-page/search-filters/search-filter/search-facet-filter/search-facet-filter.component.spec.ts index d7aba289c4..498c41dd6c 100644 --- a/src/app/+search-page/search-filters/search-filter/search-facet-filter/search-facet-filter.component.spec.ts +++ b/src/app/+search-page/search-filters/search-filter/search-facet-filter/search-facet-filter.component.spec.ts @@ -7,7 +7,7 @@ import { SearchFilterConfig } from '../../../search-service/search-filter-config import { FilterType } from '../../../search-service/filter-type.model'; import { FacetValue } from '../../../search-service/facet-value.model'; import { FormsModule } from '@angular/forms'; -import { Observable } from 'rxjs'; +import { of as observableOf } from 'rxjs'; import { SearchService } from '../../../search-service/search.service'; import { SearchServiceStub } from '../../../../shared/testing/search-service-stub'; import { RemoteData } from '../../../../core/data/remote-data'; @@ -54,9 +54,9 @@ describe('SearchFacetFilterComponent', () => { let filterService; let searchService; let router; - const page = Observable.of(0); + const page = observableOf(0); - const mockValues = Observable.of(new RemoteData(false, false, true, null, new PaginatedList(new PageInfo(), values))); + const mockValues = observableOf(new RemoteData(false, false, true, null, new PaginatedList(new PageInfo(), values))); beforeEach(async(() => { TestBed.configureTestingModule({ imports: [TranslateModule.forRoot(), NoopAnimationsModule, FormsModule], @@ -65,11 +65,11 @@ describe('SearchFacetFilterComponent', () => { { provide: SearchService, useValue: new SearchServiceStub(searchLink) }, { provide: Router, useValue: new RouterStub() }, { provide: FILTER_CONFIG, useValue: new SearchFilterConfig() }, - { provide: RemoteDataBuildService, useValue: {aggregate: () => Observable.of({})} }, - { provide: SearchConfigurationService, useValue: {searchOptions: Observable.of({})} }, + { provide: RemoteDataBuildService, useValue: {aggregate: () => observableOf({})} }, + { provide: SearchConfigurationService, useValue: {searchOptions: observableOf({})} }, { provide: SearchFilterService, useValue: { - getSelectedValuesForFilter: () => Observable.of(selectedValues), + getSelectedValuesForFilter: () => observableOf(selectedValues), isFilterActiveWithValue: (paramName: string, filterValue: string) => true, getPage: (paramName: string) => page, /* tslint:disable:no-empty */ diff --git a/src/app/+search-page/search-filters/search-filter/search-facet-filter/search-facet-filter.component.ts b/src/app/+search-page/search-filters/search-filter/search-facet-filter/search-facet-filter.component.ts index 154eb21600..4a171a3f3a 100644 --- a/src/app/+search-page/search-filters/search-filter/search-facet-filter/search-facet-filter.component.ts +++ b/src/app/+search-page/search-filters/search-filter/search-facet-filter/search-facet-filter.component.ts @@ -1,5 +1,12 @@ -import {combineLatest as observableCombineLatest, of as observableOf, BehaviorSubject , Observable , Subject , Subscription } from 'rxjs'; -import {switchMap, distinctUntilChanged, first, map } from 'rxjs/operators'; +import { + combineLatest as observableCombineLatest, + of as observableOf, + BehaviorSubject, + Observable, + Subject, + Subscription +} from 'rxjs'; +import { switchMap, distinctUntilChanged, first, map } from 'rxjs/operators'; import { animate, state, style, transition, trigger } from '@angular/animations'; import { Component, Inject, OnDestroy, OnInit } from '@angular/core'; import { Router } from '@angular/router'; @@ -82,21 +89,24 @@ export class SearchFacetFilterComponent implements OnInit, OnDestroy { this.selectedValues = this.filterService.getSelectedValuesForFilter(this.filterConfig); const searchOptions = this.searchConfigService.searchOptions; this.subs.push(this.searchConfigService.searchOptions.subscribe(() => this.updateFilterValueList())); - const facetValues = observableCombineLatest(searchOptions, this.currentPage, (options, page) => { - return { options, page } - }).pipe(switchMap(({ options, page }) => { - return this.searchService.getFacetValuesFor(this.filterConfig, page, options) - .pipe( - getSucceededRemoteData(), - map((results) => { - return { - values: observableOf(results), - page: page - }; - } + const facetValues = observableCombineLatest(searchOptions, this.currentPage).pipe( + map(([options, page]) => { + return { options, page } + }), + switchMap(({ options, page }) => { + return this.searchService.getFacetValuesFor(this.filterConfig, page, options) + .pipe( + getSucceededRemoteData(), + map((results) => { + return { + values: observableOf(results), + page: page + }; + } + ) ) - ) - })); + }) + ); let filterValues = []; this.subs.push(facetValues.subscribe((facetOutcome) => { const newValues$ = facetOutcome.values; diff --git a/src/app/+search-page/search-filters/search-filter/search-filter.component.spec.ts b/src/app/+search-page/search-filters/search-filter/search-filter.component.spec.ts index 1f32ef6c27..caa5a6febc 100644 --- a/src/app/+search-page/search-filters/search-filter/search-filter.component.spec.ts +++ b/src/app/+search-page/search-filters/search-filter/search-filter.component.spec.ts @@ -3,7 +3,7 @@ import { ChangeDetectionStrategy, NO_ERRORS_SCHEMA } from '@angular/core'; import { async, ComponentFixture, TestBed } from '@angular/core/testing'; import { RouterTestingModule } from '@angular/router/testing'; import { TranslateModule } from '@ngx-translate/core'; -import { Observable } from 'rxjs'; +import { Observable, of as observableOf } from 'rxjs'; import { NoopAnimationsModule } from '@angular/platform-browser/animations'; import { SearchFilterService } from './search-filter.service'; import { SearchService } from '../../search-service/search.service'; @@ -38,19 +38,19 @@ describe('SearchFilterComponent', () => { initialExpand: (filter) => { }, getSelectedValuesForFilter: (filter) => { - return Observable.of([filterName1, filterName2, filterName3]) + return observableOf([filterName1, filterName2, filterName3]) }, isFilterActive: (filter) => { - return Observable.of([filterName1, filterName2, filterName3].indexOf(filter) >= 0); + return observableOf([filterName1, filterName2, filterName3].indexOf(filter) >= 0); }, isCollapsed: (filter) => { - return Observable.of(true) + return observableOf(true) } /* tslint:enable:no-empty */ }; let filterService; - const mockResults = Observable.of(['test', 'data']); + const mockResults = observableOf(['test', 'data']); const searchServiceStub = { getFacetValuesFor: (filter) => mockResults }; @@ -140,7 +140,7 @@ describe('SearchFilterComponent', () => { describe('when isCollapsed is called and the filter is collapsed', () => { let isActive: Observable; beforeEach(() => { - filterService.isCollapsed = () => Observable.of(true); + filterService.isCollapsed = () => observableOf(true); isActive = comp.isCollapsed(); }); @@ -155,7 +155,7 @@ describe('SearchFilterComponent', () => { describe('when isCollapsed is called and the filter is not collapsed', () => { let isActive: Observable; beforeEach(() => { - filterService.isCollapsed = () => Observable.of(false); + filterService.isCollapsed = () => observableOf(false); isActive = comp.isCollapsed(); }); diff --git a/src/app/+search-page/search-filters/search-filter/search-filter.service.spec.ts b/src/app/+search-page/search-filters/search-filter/search-filter.service.spec.ts index 4ee7369706..156e8d47ea 100644 --- a/src/app/+search-page/search-filters/search-filter/search-filter.service.spec.ts +++ b/src/app/+search-page/search-filters/search-filter/search-filter.service.spec.ts @@ -1,16 +1,20 @@ -import { Observable } from 'rxjs'; import { SearchFilterService } from './search-filter.service'; import { Store } from '@ngrx/store'; import { - SearchFilterCollapseAction, SearchFilterDecrementPageAction, SearchFilterExpandAction, + SearchFilterCollapseAction, + SearchFilterDecrementPageAction, + SearchFilterExpandAction, SearchFilterIncrementPageAction, - SearchFilterInitialCollapseAction, SearchFilterInitialExpandAction, SearchFilterResetPageAction, + SearchFilterInitialCollapseAction, + SearchFilterInitialExpandAction, + SearchFilterResetPageAction, SearchFilterToggleAction } from './search-filter.actions'; import { SearchFiltersState } from './search-filter.reducer'; import { SearchFilterConfig } from '../../search-service/search-filter-config.model'; import { FilterType } from '../../search-service/filter-type.model'; import { ActivatedRouteStub } from '../../../shared/testing/active-router-stub'; +import { of as observableOf } from 'rxjs'; describe('SearchFilterService', () => { let service: SearchFilterService; @@ -28,7 +32,7 @@ describe('SearchFilterService', () => { /* tslint:disable:no-empty */ dispatch: {}, /* tslint:enable:no-empty */ - select: Observable.of(true) + select: observableOf(true) }); const routeServiceStub: any = { @@ -42,10 +46,10 @@ describe('SearchFilterService', () => { addQueryParameterValue: (param: string, value: string) => { }, getQueryParameterValues: (param: string) => { - return Observable.of({}); + return observableOf({}); }, getQueryParamsWithPrefix: (param: string) => { - return Observable.of({}); + return observableOf({}); } /* tslint:enable:no-empty */ }; diff --git a/src/app/+search-page/search-filters/search-filter/search-filter.service.ts b/src/app/+search-page/search-filters/search-filter/search-filter.service.ts index 35e6558375..bf21eab367 100644 --- a/src/app/+search-page/search-filters/search-filter/search-filter.service.ts +++ b/src/app/+search-page/search-filters/search-filter/search-filter.service.ts @@ -1,6 +1,6 @@ import { combineLatest as observableCombineLatest, Observable } from 'rxjs'; import { Injectable, InjectionToken } from '@angular/core'; -import { distinctUntilChanged, map } from 'rxjs/operators'; +import { map } from 'rxjs/operators'; import { SearchFiltersState, SearchFilterState } from './search-filter.reducer'; import { createSelector, MemoizedSelector, select, Store } from '@ngrx/store'; import { @@ -13,14 +13,10 @@ import { SearchFilterResetPageAction, SearchFilterToggleAction } from './search-filter.actions'; -import { hasValue, isEmpty, isNotEmpty, } from '../../../shared/empty.util'; +import { hasValue, isNotEmpty, } from '../../../shared/empty.util'; import { SearchFilterConfig } from '../../search-service/search-filter-config.model'; import { RouteService } from '../../../shared/services/route.service'; -import { SortDirection, SortOptions } from '../../../core/cache/models/sort-options.model'; -import { PaginationComponentOptions } from '../../../shared/pagination/pagination-component-options.model'; -import { SearchOptions } from '../../search-options.model'; -import { PaginatedSearchOptions } from '../../paginated-search-options.model'; -import { ActivatedRoute, Params } from '@angular/router'; +import { Params } from '@angular/router'; const filterStateSelector = (state: SearchFiltersState) => state.searchFilter; @@ -63,13 +59,19 @@ export class SearchFilterService { */ getSelectedValuesForFilter(filterConfig: SearchFilterConfig): Observable { const values$ = this.routeService.getQueryParameterValues(filterConfig.paramName); - const prefixValues$ = this.routeService.getQueryParamsWithPrefix(filterConfig.paramName + '.').pipe(map((params: Params) => [].concat(...Object.values(params)))); - return observableCombineLatest(values$, prefixValues$, (values, prefixValues) => { - if (isNotEmpty(values)) { - return values; - } - return prefixValues; - }) + const prefixValues$ = this.routeService.getQueryParamsWithPrefix(filterConfig.paramName + '.').pipe( + map((params: Params) => [].concat(...Object.values(params))) + ); + + return observableCombineLatest(values$, prefixValues$).pipe( + map(([values, prefixValues]) => { + if (isNotEmpty(values)) { + return values; + } + return prefixValues; + } + ) + ) } /** diff --git a/src/app/+search-page/search-filters/search-filter/search-range-filter/search-range-filter.component.spec.ts b/src/app/+search-page/search-filters/search-filter/search-range-filter/search-range-filter.component.spec.ts index ce5d5dd6dd..6f3450e18e 100644 --- a/src/app/+search-page/search-filters/search-filter/search-range-filter/search-range-filter.component.spec.ts +++ b/src/app/+search-page/search-filters/search-filter/search-range-filter/search-range-filter.component.spec.ts @@ -7,7 +7,7 @@ import { SearchFilterConfig } from '../../../search-service/search-filter-config import { FilterType } from '../../../search-service/filter-type.model'; import { FacetValue } from '../../../search-service/facet-value.model'; import { FormsModule } from '@angular/forms'; -import { Observable } from 'rxjs'; +import { of as observableOf } from 'rxjs' import { SearchService } from '../../../search-service/search.service'; import { SearchServiceStub } from '../../../../shared/testing/search-service-stub'; import { RemoteData } from '../../../../core/data/remote-data'; @@ -56,13 +56,13 @@ describe('SearchRangeFilterComponent', () => { ]; const searchLink = '/search'; - const selectedValues = Observable.of([value1]); + const selectedValues = observableOf([value1]); let filterService; let searchService; let router; - const page = Observable.of(0); + const page = observableOf(0); - const mockValues = Observable.of(new RemoteData(false, false, true, null, new PaginatedList(new PageInfo(), values))); + const mockValues = observableOf(new RemoteData(false, false, true, null, new PaginatedList(new PageInfo(), values))); beforeEach(async(() => { TestBed.configureTestingModule({ imports: [TranslateModule.forRoot(), NoopAnimationsModule, FormsModule], @@ -71,10 +71,10 @@ describe('SearchRangeFilterComponent', () => { { provide: SearchService, useValue: new SearchServiceStub(searchLink) }, { provide: Router, useValue: new RouterStub() }, { provide: FILTER_CONFIG, useValue: mockFilterConfig }, - { provide: RemoteDataBuildService, useValue: {aggregate: () => Observable.of({})} }, - { provide: RouteService, useValue: {getQueryParameterValue: () => Observable.of({})} }, + { provide: RemoteDataBuildService, useValue: {aggregate: () => observableOf({})} }, + { provide: RouteService, useValue: {getQueryParameterValue: () => observableOf({})} }, { provide: SearchConfigurationService, useValue: { - searchOptions: Observable.of({}) } + searchOptions: observableOf({}) } }, { provide: SearchFilterService, useValue: { diff --git a/src/app/+search-page/search-filters/search-filter/search-range-filter/search-range-filter.component.ts b/src/app/+search-page/search-filters/search-filter/search-range-filter/search-range-filter.component.ts index 3c76d4391b..6cb04c6c1f 100644 --- a/src/app/+search-page/search-filters/search-filter/search-range-filter/search-range-filter.component.ts +++ b/src/app/+search-page/search-filters/search-filter/search-range-filter/search-range-filter.component.ts @@ -1,5 +1,10 @@ -import {of as observableOf, combineLatest as observableCombineLatest, Observable , Subscription } from 'rxjs'; -import {startWith} from 'rxjs/operators'; +import { + of as observableOf, + combineLatest as observableCombineLatest, + Observable, + Subscription +} from 'rxjs'; +import { map, startWith } from 'rxjs/operators'; import { isPlatformBrowser } from '@angular/common'; import { Component, Inject, OnDestroy, OnInit, PLATFORM_ID } from '@angular/core'; import { RemoteDataBuildService } from '../../../../core/cache/builders/remote-data-build.service'; @@ -82,11 +87,13 @@ export class SearchRangeFilterComponent extends SearchFacetFilterComponent imple this.max = moment(this.filterConfig.maxValue, dateFormats).year() || this.max; const iniMin = this.route.getQueryParameterValue(this.filterConfig.paramName + minSuffix).pipe(startWith(undefined)); const iniMax = this.route.getQueryParameterValue(this.filterConfig.paramName + maxSuffix).pipe(startWith(undefined)); - this.sub = observableCombineLatest(iniMin, iniMax, (min, max) => { - const minimum = hasValue(min) ? min : this.min; - const maximum = hasValue(max) ? max : this.max; - return [minimum, maximum] - }).subscribe((minmax) => this.range = minmax); + this.sub = observableCombineLatest(iniMin, iniMax).pipe( + map(([min, max]) => { + const minimum = hasValue(min) ? min : this.min; + const maximum = hasValue(max) ? max : this.max; + return [minimum, maximum] + }) + ).subscribe((minmax) => this.range = minmax); } /** diff --git a/src/app/+search-page/search-filters/search-filters.component.spec.ts b/src/app/+search-page/search-filters/search-filters.component.spec.ts index 58ff30198e..db21fc8a69 100644 --- a/src/app/+search-page/search-filters/search-filters.component.spec.ts +++ b/src/app/+search-page/search-filters/search-filters.component.spec.ts @@ -7,8 +7,8 @@ import { NoopAnimationsModule } from '@angular/platform-browser/animations'; import { SearchFilterService } from './search-filter/search-filter.service'; import { SearchFiltersComponent } from './search-filters.component'; import { SearchService } from '../search-service/search.service'; -import { Observable } from 'rxjs'; import { SearchConfigurationService } from '../search-service/search-configuration.service'; +import { of as observableOf } from 'rxjs'; describe('SearchFiltersComponent', () => { let comp: SearchFiltersComponent; @@ -17,7 +17,7 @@ describe('SearchFiltersComponent', () => { const searchServiceStub = { /* tslint:disable:no-empty */ getConfig: () => - Observable.of({ hasSucceeded: true, payload: [] }), + observableOf({ hasSucceeded: true, payload: [] }), getClearFiltersQueryParams: () => { }, getSearchLink: () => { @@ -31,7 +31,7 @@ describe('SearchFiltersComponent', () => { }; const searchConfigServiceStub = jasmine.createSpyObj('SearchConfigurationService', { - getCurrentFrontendFilters: Observable.of({}) + getCurrentFrontendFilters: observableOf({}) }); beforeEach(async(() => { diff --git a/src/app/+search-page/search-labels/search-labels.component.spec.ts b/src/app/+search-page/search-labels/search-labels.component.spec.ts index 51ddf81459..81fa5b5df8 100644 --- a/src/app/+search-page/search-labels/search-labels.component.spec.ts +++ b/src/app/+search-page/search-labels/search-labels.component.spec.ts @@ -6,7 +6,7 @@ import { SearchService } from '../search-service/search.service'; import { ChangeDetectionStrategy, NO_ERRORS_SCHEMA } from '@angular/core'; import { FormsModule } from '@angular/forms'; import { SearchServiceStub } from '../../shared/testing/search-service-stub'; -import { Observable } from 'rxjs'; +import { Observable, of as observableOf } from 'rxjs'; import { Params } from '@angular/router'; import { ObjectKeysPipe } from '../../shared/utils/object-keys-pipe'; import { SearchConfigurationService } from '../search-service/search-configuration.service'; @@ -35,7 +35,7 @@ describe('SearchLabelsComponent', () => { declarations: [SearchLabelsComponent, ObjectKeysPipe], providers: [ { provide: SearchService, useValue: new SearchServiceStub(searchLink) }, - { provide: SearchConfigurationService, useValue: {getCurrentFrontendFilters : () => Observable.of({})} } + { provide: SearchConfigurationService, useValue: {getCurrentFrontendFilters : () => observableOf({})} } ], schemas: [NO_ERRORS_SCHEMA] }).overrideComponent(SearchLabelsComponent, { @@ -47,7 +47,7 @@ describe('SearchLabelsComponent', () => { fixture = TestBed.createComponent(SearchLabelsComponent); comp = fixture.componentInstance; searchService = (comp as any).searchService; - (comp as any).appliedFilters = Observable.of(mockFilters); + (comp as any).appliedFilters = observableOf(mockFilters); fixture.detectChanges(); }); diff --git a/src/app/+search-page/search-page.component.spec.ts b/src/app/+search-page/search-page.component.spec.ts index 05b85a0a00..1991cf8f1b 100644 --- a/src/app/+search-page/search-page.component.spec.ts +++ b/src/app/+search-page/search-page.component.spec.ts @@ -5,8 +5,7 @@ import { RouterTestingModule } from '@angular/router/testing'; import { Store } from '@ngrx/store'; import { TranslateModule } from '@ngx-translate/core'; import { cold, hot } from 'jasmine-marbles'; -import { Observable } from 'rxjs'; -import 'rxjs/add/observable/of'; +import { of as observableOf } from 'rxjs'; import { SortDirection, SortOptions } from '../core/cache/models/sort-options.model'; import { CommunityDataService } from '../core/data/community-data.service'; import { HostWindowService } from '../shared/host-window.service'; @@ -30,18 +29,18 @@ describe('SearchPageComponent', () => { /* tslint:disable:no-empty */ dispatch: {}, /* tslint:enable:no-empty */ - select: Observable.of(true) + select: observableOf(true) }); const pagination: PaginationComponentOptions = new PaginationComponentOptions(); pagination.id = 'search-results-pagination'; pagination.currentPage = 1; pagination.pageSize = 10; const sort: SortOptions = new SortOptions('score', SortDirection.DESC); - const mockResults = Observable.of(new RemoteData(false, false, true, null, ['test', 'data'])); + const mockResults = observableOf(new RemoteData(false, false, true, null, ['test', 'data'])); const searchServiceStub = jasmine.createSpyObj('SearchService', { search: mockResults, getSearchLink: '/search', - getScopes: Observable.of(['test-scope']) + getScopes: observableOf(['test-scope']) }); const queryParam = 'test query'; const scopeParam = '7669c72a-3f2a-451f-a3b9-9210e7a4c02f'; @@ -52,15 +51,15 @@ describe('SearchPageComponent', () => { sort }; const activatedRouteStub = { - queryParams: Observable.of({ + queryParams: observableOf({ query: queryParam, scope: scopeParam }) }; const sidebarService = { - isCollapsed: Observable.of(true), - collapse: () => this.isCollapsed = Observable.of(true), - expand: () => this.isCollapsed = Observable.of(false) + isCollapsed: observableOf(true), + collapse: () => this.isCollapsed = observableOf(true), + expand: () => this.isCollapsed = observableOf(false) }; beforeEach(async(() => { @@ -80,9 +79,9 @@ describe('SearchPageComponent', () => { { provide: HostWindowService, useValue: jasmine.createSpyObj('hostWindowService', { - isXs: Observable.of(true), - isSm: Observable.of(false), - isXsOrSm: Observable.of(true) + isXs: observableOf(true), + isSm: observableOf(false), + isXsOrSm: observableOf(true) }) }, { @@ -98,7 +97,7 @@ describe('SearchPageComponent', () => { paginatedSearchOptions: hot('a', { a: paginatedSearchOptions }), - getCurrentScope: (a) => Observable.of('test-id') + getCurrentScope: (a) => observableOf('test-id') } }, ], @@ -154,7 +153,7 @@ describe('SearchPageComponent', () => { beforeEach(() => { menu = fixture.debugElement.query(By.css('#search-sidebar-sm')).nativeElement; - comp.isSidebarCollapsed = () => Observable.of(true); + comp.isSidebarCollapsed = () => observableOf(true); fixture.detectChanges(); }); @@ -169,7 +168,7 @@ describe('SearchPageComponent', () => { beforeEach(() => { menu = fixture.debugElement.query(By.css('#search-sidebar-sm')).nativeElement; - comp.isSidebarCollapsed = () => Observable.of(false); + comp.isSidebarCollapsed = () => observableOf(false); fixture.detectChanges(); }); diff --git a/src/app/+search-page/search-service/search-configuration.service.spec.ts b/src/app/+search-page/search-service/search-configuration.service.spec.ts index d911df0426..af8897c93b 100644 --- a/src/app/+search-page/search-service/search-configuration.service.spec.ts +++ b/src/app/+search-page/search-service/search-configuration.service.spec.ts @@ -3,8 +3,8 @@ import { ActivatedRouteStub } from '../../shared/testing/active-router-stub'; import { PaginationComponentOptions } from '../../shared/pagination/pagination-component-options.model'; import { SortDirection, SortOptions } from '../../core/cache/models/sort-options.model'; import { PaginatedSearchOptions } from '../paginated-search-options.model'; -import { Observable } from 'rxjs'; import { SearchFilter } from '../search-filter.model'; +import { of as observableOf } from 'rxjs'; describe('SearchConfigurationService', () => { let service: SearchConfigurationService; @@ -24,8 +24,8 @@ describe('SearchConfigurationService', () => { const backendFilters = [new SearchFilter('f.author', ['another value']), new SearchFilter('f.date', ['[2013 TO 2018]'])]; const spy = jasmine.createSpyObj('RouteService', { - getQueryParameterValue: Observable.of(value1), - getQueryParamsWithPrefix: Observable.of(prefixFilter) + getQueryParameterValue: observableOf(value1), + getQueryParamsWithPrefix: observableOf(prefixFilter) }); const activatedRoute: any = new ActivatedRouteStub(); diff --git a/src/app/+search-page/search-service/search-configuration.service.ts b/src/app/+search-page/search-service/search-configuration.service.ts index 39389e6065..ab62cc0915 100644 --- a/src/app/+search-page/search-service/search-configuration.service.ts +++ b/src/app/+search-page/search-service/search-configuration.service.ts @@ -1,5 +1,12 @@ -import {of as observableOf, merge as observableMerge, combineLatest as observableCombineLatest, Observable , BehaviorSubject , Subscription } from 'rxjs'; -import {filter, map} from 'rxjs/operators'; +import { + BehaviorSubject, + combineLatest as observableCombineLatest, + merge as observableMerge, + Observable, + of as observableOf, + Subscription +} from 'rxjs'; +import { filter, map } from 'rxjs/operators'; import { SortDirection, SortOptions } from '../../core/cache/models/sort-options.model'; import { PaginationComponentOptions } from '../../shared/pagination/pagination-component-options.model'; import { SearchOptions } from '../search-options.model'; @@ -7,7 +14,7 @@ import { ActivatedRoute, Params } from '@angular/router'; import { PaginatedSearchOptions } from '../paginated-search-options.model'; import { Injectable, OnDestroy } from '@angular/core'; import { RouteService } from '../../shared/services/route.service'; -import { hasNoValue, hasValue, isEmpty, isNotEmpty } from '../../shared/empty.util'; +import { hasNoValue, hasValue, isNotEmpty } from '../../shared/empty.util'; import { RemoteData } from '../../core/data/remote-data'; import { getSucceededRemoteData } from '../../core/shared/operators'; import { SearchFilter } from '../search-filter.model'; @@ -115,12 +122,13 @@ export class SearchConfigurationService implements OnDestroy { getCurrentPagination(defaultPagination: PaginationComponentOptions): Observable { const page$ = this.routeService.getQueryParameterValue('page'); const size$ = this.routeService.getQueryParameterValue('pageSize'); - return observableCombineLatest(page$, size$, (page, size) => { - return Object.assign(new PaginationComponentOptions(), defaultPagination, { - currentPage: page || defaultPagination.currentPage, - pageSize: size || defaultPagination.pageSize - }); - }); + return observableCombineLatest(page$, size$).pipe(map(([page, size]) => { + return Object.assign(new PaginationComponentOptions(), defaultPagination, { + currentPage: page || defaultPagination.currentPage, + pageSize: size || defaultPagination.pageSize + }); + }) + ); } /** @@ -129,7 +137,7 @@ export class SearchConfigurationService implements OnDestroy { getCurrentSort(defaultSort: SortOptions): Observable { const sortDirection$ = this.routeService.getQueryParameterValue('sortDirection'); const sortField$ = this.routeService.getQueryParameterValue('sortField'); - return observableCombineLatest(sortDirection$, sortField$, (sortDirection, sortField) => { + return observableCombineLatest(sortDirection$, sortField$).pipe(map(([sortDirection, sortField]) => { // Dirty fix because sometimes the observable value is null somehow sortField = this.route.snapshot.queryParamMap.get('sortField'); @@ -137,7 +145,8 @@ export class SearchConfigurationService implements OnDestroy { const direction = SortDirection[sortDirection] || defaultSort.direction; return new SortOptions(field, direction) } - ) + ) + ); } /** diff --git a/src/app/+search-page/search-service/search.service.spec.ts b/src/app/+search-page/search-service/search.service.spec.ts index a02d101ac4..6bfc9200ec 100644 --- a/src/app/+search-page/search-service/search.service.spec.ts +++ b/src/app/+search-page/search-service/search.service.spec.ts @@ -12,7 +12,7 @@ import { ResponseCacheService } from '../../core/cache/response-cache.service'; import { ActivatedRouteStub } from '../../shared/testing/active-router-stub'; import { RouterStub } from '../../shared/testing/router-stub'; import { HALEndpointService } from '../../core/shared/hal-endpoint.service'; -import { Observable } from 'rxjs'; +import { Observable, combineLatest as observableCombineLatest } from 'rxjs'; import { PaginatedSearchOptions } from '../paginated-search-options.model'; import { RemoteData } from '../../core/data/remote-data'; import { ResponseCacheEntry } from '../../core/cache/response-cache.reducer'; @@ -28,6 +28,8 @@ import { SearchFilterConfig } from './search-filter-config.model'; import { CommunityDataService } from '../../core/data/community-data.service'; import { ViewMode } from '../../core/shared/view-mode.model'; import { DSpaceObjectDataService } from '../../core/data/dspace-object-data.service'; +import { of as observableOf } from 'rxjs'; +import { map } from 'rxjs/operators'; @Component({ template: '' }) class DummyComponent { @@ -56,8 +58,8 @@ describe('SearchService', () => { { provide: RequestService, useValue: getMockRequestService() }, { provide: RemoteDataBuildService, useValue: {} }, { provide: HALEndpointService, useValue: {} }, - { provide: CommunityDataService, useValue: {}}, - { provide: DSpaceObjectDataService, useValue: {}}, + { provide: CommunityDataService, useValue: {} }, + { provide: DSpaceObjectDataService, useValue: {} }, SearchService ], }); @@ -85,13 +87,15 @@ describe('SearchService', () => { const remoteDataBuildService = { toRemoteDataObservable: (requestEntryObs: Observable, responseCacheObs: Observable, payloadObs: Observable) => { - return Observable.combineLatest(requestEntryObs, - responseCacheObs, payloadObs, (req, res, pay) => { + return observableCombineLatest(requestEntryObs, + responseCacheObs, payloadObs).pipe( + map(([req, res, pay]) => { return { req, res, pay }; - }); + }) + ); }, aggregate: (input: Array>>): Observable> => { - return Observable.of(new RemoteData(false, false, true, null, [])); + return observableOf(new RemoteData(false, false, true, null, [])); } }; @@ -113,8 +117,8 @@ describe('SearchService', () => { { provide: RequestService, useValue: getMockRequestService() }, { provide: RemoteDataBuildService, useValue: remoteDataBuildService }, { provide: HALEndpointService, useValue: halService }, - { provide: CommunityDataService, useValue: {}}, - { provide: DSpaceObjectDataService, useValue: {}}, + { provide: CommunityDataService, useValue: {} }, + { provide: DSpaceObjectDataService, useValue: {} }, SearchService ], }); @@ -160,8 +164,8 @@ describe('SearchService', () => { const response = new SearchSuccessResponse(queryResponse, '200'); const responseEntry = Object.assign(new ResponseCacheEntry(), { response: response }); beforeEach(() => { - spyOn((searchService as any).halService, 'getEndpoint').and.returnValue(Observable.of(endPoint)); - (searchService as any).responseCache.get.and.returnValue(Observable.of(responseEntry)); + spyOn((searchService as any).halService, 'getEndpoint').and.returnValue(observableOf(endPoint)); + (searchService as any).responseCache.get.and.returnValue(observableOf(responseEntry)); /* tslint:disable:no-empty */ searchService.search(searchOptions).subscribe((t) => { }); // subscribe to make sure all methods are called @@ -190,8 +194,8 @@ describe('SearchService', () => { const response = new FacetConfigSuccessResponse(filterConfig, '200'); const responseEntry = Object.assign(new ResponseCacheEntry(), { response: response }); beforeEach(() => { - spyOn((searchService as any).halService, 'getEndpoint').and.returnValue(Observable.of(endPoint)); - (searchService as any).responseCache.get.and.returnValue(Observable.of(responseEntry)); + spyOn((searchService as any).halService, 'getEndpoint').and.returnValue(observableOf(endPoint)); + (searchService as any).responseCache.get.and.returnValue(observableOf(responseEntry)); /* tslint:disable:no-empty */ searchService.getConfig(null).subscribe((t) => { }); // subscribe to make sure all methods are called @@ -222,8 +226,8 @@ describe('SearchService', () => { const response = new FacetConfigSuccessResponse(filterConfig, '200'); const responseEntry = Object.assign(new ResponseCacheEntry(), { response: response }); beforeEach(() => { - spyOn((searchService as any).halService, 'getEndpoint').and.returnValue(Observable.of(endPoint)); - (searchService as any).responseCache.get.and.returnValue(Observable.of(responseEntry)); + spyOn((searchService as any).halService, 'getEndpoint').and.returnValue(observableOf(endPoint)); + (searchService as any).responseCache.get.and.returnValue(observableOf(responseEntry)); /* tslint:disable:no-empty */ searchService.getConfig(scope).subscribe((t) => { }); // subscribe to make sure all methods are called diff --git a/src/app/+search-page/search-service/search.service.ts b/src/app/+search-page/search-service/search.service.ts index 12ab6124c1..1503440eb0 100644 --- a/src/app/+search-page/search-service/search.service.ts +++ b/src/app/+search-page/search-service/search.service.ts @@ -1,4 +1,4 @@ -import {of as observableOf, combineLatest as observableCombineLatest, Observable } from 'rxjs'; +import { of as observableOf, combineLatest as observableCombineLatest, Observable } from 'rxjs'; import { Injectable, OnDestroy } from '@angular/core'; import { ActivatedRoute, @@ -122,30 +122,33 @@ export class SearchService implements OnDestroy { ); // Create search results again with the correct dso objects linked to each result - const tDomainListObs = observableCombineLatest(sqrObs, dsoObs, (sqr: SearchQueryResponse, dsos: RemoteData) => { - - return sqr.objects.map((object: NormalizedSearchResult, index: number) => { - let co = DSpaceObject; - if (dsos.payload[index]) { - const constructor: GenericConstructor = dsos.payload[index].constructor as GenericConstructor; - co = getSearchResultFor(constructor); - return Object.assign(new co(), object, { - dspaceObject: dsos.payload[index] - }); - } else { - return undefined; - } - }); - }); + const tDomainListObs = observableCombineLatest(sqrObs, dsoObs).pipe( + map(([sqr, dsos]) => { + return sqr.objects.map((object: NormalizedSearchResult, index: number) => { + let co = DSpaceObject; + if (dsos.payload[index]) { + const constructor: GenericConstructor = dsos.payload[index].constructor as GenericConstructor; + co = getSearchResultFor(constructor); + return Object.assign(new co(), object, { + dspaceObject: dsos.payload[index] + }); + } else { + return undefined; + } + }); + }) + ); const pageInfoObs: Observable = responseCacheObs.pipe( map((entry: ResponseCacheEntry) => entry.response), map((response: FacetValueSuccessResponse) => response.pageInfo) ); - const payloadObs = observableCombineLatest(tDomainListObs, pageInfoObs, (tDomainList, pageInfo) => { - return new PaginatedList(pageInfo, tDomainList); - }); + const payloadObs = observableCombineLatest(tDomainListObs, pageInfoObs).pipe( + map(([tDomainList, pageInfo]) => { + return new PaginatedList(pageInfo, tDomainList); + }) + ); return this.rdb.toRemoteDataObservable(requestEntryObs, responseCacheObs, payloadObs); } @@ -244,9 +247,11 @@ export class SearchService implements OnDestroy { map((response: FacetValueSuccessResponse) => response.pageInfo) ); - const payloadObs = observableCombineLatest(facetValueObs, pageInfoObs, (facetValue, pageInfo) => { - return new PaginatedList(pageInfo, facetValue); - }); + const payloadObs = observableCombineLatest(facetValueObs, pageInfoObs).pipe( + map(([facetValue, pageInfo]) => { + return new PaginatedList(pageInfo, facetValue); + }) + ); return this.rdb.toRemoteDataObservable(requestEntryObs, responseCacheObs, payloadObs); } @@ -272,10 +277,12 @@ export class SearchService implements OnDestroy { switchMap((dsoRD: RemoteData) => { if (dsoRD.payload.type === ResourceType.Community) { const community: Community = dsoRD.payload as Community; - return observableCombineLatest(community.subcommunities, community.collections, (subCommunities, collections) => { - /*if this is a community, we also need to show the direct children*/ - return [community, ...subCommunities.payload.page, ...collections.payload.page] - }) + return observableCombineLatest(community.subcommunities, community.collections).pipe( + map(([subCommunities, collections]) => { + /*if this is a community, we also need to show the direct children*/ + return [community, ...subCommunities.payload.page, ...collections.payload.page] + }) + ); } else { return observableOf([dsoRD.payload]); } diff --git a/src/app/+search-page/search-settings/search-settings.component.spec.ts b/src/app/+search-page/search-settings/search-settings.component.spec.ts index ddd7900b1e..b1585c4347 100644 --- a/src/app/+search-page/search-settings/search-settings.component.spec.ts +++ b/src/app/+search-page/search-settings/search-settings.component.spec.ts @@ -1,7 +1,7 @@ import { SearchService } from '../search-service/search.service'; import { async, ComponentFixture, TestBed } from '@angular/core/testing'; import { SearchSettingsComponent } from './search-settings.component'; -import { Observable } from 'rxjs'; +import { of as observableOf } from 'rxjs'; import { PaginationComponentOptions } from '../../shared/pagination/pagination-component-options.model'; import { SortDirection, SortOptions } from '../../core/cache/models/sort-options.model'; import { TranslateModule } from '@ngx-translate/core'; @@ -15,6 +15,7 @@ import { SearchFilterService } from '../search-filters/search-filter/search-filt import { hot } from 'jasmine-marbles'; import { VarDirective } from '../../shared/utils/var.directive'; import { SearchConfigurationService } from '../search-service/search-configuration.service'; +import { first } from 'rxjs/operators'; describe('SearchSettingsComponent', () => { @@ -43,16 +44,16 @@ describe('SearchSettingsComponent', () => { }; const activatedRouteStub = { - queryParams: Observable.of({ + queryParams: observableOf({ query: queryParam, scope: scopeParam }) }; const sidebarService = { - isCollapsed: Observable.of(true), - collapse: () => this.isCollapsed = Observable.of(true), - expand: () => this.isCollapsed = Observable.of(false) + isCollapsed: observableOf(true), + collapse: () => this.isCollapsed = observableOf(true), + expand: () => this.isCollapsed = observableOf(false) }; beforeEach(async(() => { @@ -101,7 +102,7 @@ describe('SearchSettingsComponent', () => { }); it('it should show the order settings with the respective selectable options', () => { - (comp as any).searchOptions$.first().subscribe((options) => { + (comp as any).searchOptions$.pipe(first()).subscribe((options) => { fixture.detectChanges(); const orderSetting = fixture.debugElement.query(By.css('div.result-order-settings')); expect(orderSetting).toBeDefined(); @@ -111,7 +112,7 @@ describe('SearchSettingsComponent', () => { }); it('it should show the size settings with the respective selectable options', () => { - (comp as any).searchOptions$.first().subscribe((options) => { + (comp as any).searchOptions$.pipe(first()).subscribe((options) => { fixture.detectChanges(); const pageSizeSetting = fixture.debugElement.query(By.css('div.page-size-settings')); expect(pageSizeSetting).toBeDefined(); @@ -122,7 +123,7 @@ describe('SearchSettingsComponent', () => { }); it('should have the proper order value selected by default', () => { - (comp as any).searchOptions$.first().subscribe((options) => { + (comp as any).searchOptions$.pipe(first()).subscribe((options) => { fixture.detectChanges(); const orderSetting = fixture.debugElement.query(By.css('div.result-order-settings')); const childElementToBeSelected = orderSetting.query(By.css('.form-control option[value="0"][selected="selected"]')); @@ -131,7 +132,7 @@ describe('SearchSettingsComponent', () => { }); it('should have the proper rpp value selected by default', () => { - (comp as any).searchOptions$.first().subscribe((options) => { + (comp as any).searchOptions$.pipe(first()).subscribe((options) => { fixture.detectChanges(); const pageSizeSetting = fixture.debugElement.query(By.css('div.page-size-settings')); const childElementToBeSelected = pageSizeSetting.query(By.css('.form-control option[value="10"][selected="selected"]')); diff --git a/src/app/+search-page/search-settings/search-settings.component.ts b/src/app/+search-page/search-settings/search-settings.component.ts index c6415798ef..7fc5645fcc 100644 --- a/src/app/+search-page/search-settings/search-settings.component.ts +++ b/src/app/+search-page/search-settings/search-settings.component.ts @@ -3,7 +3,6 @@ import { SearchService } from '../search-service/search.service'; import { SortDirection, SortOptions } from '../../core/cache/models/sort-options.model'; import { ActivatedRoute, NavigationExtras, Router } from '@angular/router'; import { PaginatedSearchOptions } from '../paginated-search-options.model'; -import { SearchFilterService } from '../search-filters/search-filter/search-filter.service'; import { Observable } from 'rxjs'; import { SearchConfigurationService } from '../search-service/search-configuration.service'; diff --git a/src/app/+search-page/search-sidebar/search-sidebar.service.spec.ts b/src/app/+search-page/search-sidebar/search-sidebar.service.spec.ts index dcc5f536d9..41d2bb2aaa 100644 --- a/src/app/+search-page/search-sidebar/search-sidebar.service.spec.ts +++ b/src/app/+search-page/search-sidebar/search-sidebar.service.spec.ts @@ -1,8 +1,8 @@ import { Store } from '@ngrx/store'; import { SearchSidebarService } from './search-sidebar.service'; import { AppState } from '../../app.reducer'; -import { async, inject, TestBed } from '@angular/core/testing'; -import { Observable } from 'rxjs'; +import { async, TestBed } from '@angular/core/testing'; +import { of as observableOf } from 'rxjs'; import 'rxjs/add/observable/of'; import { SearchSidebarCollapseAction, SearchSidebarExpandAction } from './search-sidebar.actions'; import { HostWindowService } from '../../shared/host-window.service'; @@ -13,13 +13,13 @@ describe('SearchSidebarService', () => { /* tslint:disable:no-empty */ dispatch: {}, /* tslint:enable:no-empty */ - select: Observable.of(true) + select: observableOf(true) }); const windowService = jasmine.createSpyObj('hostWindowService', { - isXs: Observable.of(true), - isSm: Observable.of(false), - isXsOrSm: Observable.of(true) + isXs: observableOf(true), + isSm: observableOf(false), + isXsOrSm: observableOf(true) }); beforeEach(async(() => { TestBed.configureTestingModule({ diff --git a/src/app/+search-page/search-sidebar/search-sidebar.service.ts b/src/app/+search-page/search-sidebar/search-sidebar.service.ts index d74fe66348..7185984538 100644 --- a/src/app/+search-page/search-sidebar/search-sidebar.service.ts +++ b/src/app/+search-page/search-sidebar/search-sidebar.service.ts @@ -5,6 +5,7 @@ import { createSelector, select, Store } from '@ngrx/store'; import { SearchSidebarCollapseAction, SearchSidebarExpandAction } from './search-sidebar.actions'; import { AppState } from '../../app.reducer'; import { HostWindowService } from '../../shared/host-window.service'; +import { map } from 'rxjs/operators'; const sidebarStateSelector = (state: AppState) => state.searchSidebar; const sidebarCollapsedSelector = createSelector(sidebarStateSelector, (sidebar: SearchSidebarState) => sidebar.sidebarCollapsed); @@ -36,8 +37,10 @@ export class SearchSidebarService { get isCollapsed(): Observable { return observableCombineLatest( this.isXsOrSm$, - this.isCollapsedInStore, - (mobile, store) => mobile ? store : true); + this.isCollapsedInStore + ).pipe( + map(([mobile, store]) => mobile ? store : true) + ); } /** diff --git a/src/app/app.component.spec.ts b/src/app/app.component.spec.ts index 0e5af10bcc..c88b999786 100644 --- a/src/app/app.component.spec.ts +++ b/src/app/app.component.spec.ts @@ -92,7 +92,7 @@ describe('App component', () => { let store: Store; beforeEach(() => { - store = fixture.debugElement.injector.get(Store); + store = fixture.debugElement.injector.get(Store) as Store; spyOn(store, 'dispatch'); window.dispatchEvent(new Event('resize')); diff --git a/src/app/core/auth/auth.effects.spec.ts b/src/app/core/auth/auth.effects.spec.ts index b5b7cd6da9..a01a8a2887 100644 --- a/src/app/core/auth/auth.effects.spec.ts +++ b/src/app/core/auth/auth.effects.spec.ts @@ -5,7 +5,7 @@ import { Store } from '@ngrx/store'; import { cold, hot } from 'jasmine-marbles'; import { Observable } from 'rxjs'; -import 'rxjs/add/observable/of' +import { of as observableOf } from 'rxjs'; import { AuthEffects } from './auth.effects'; import { @@ -36,7 +36,7 @@ describe('AuthEffects', () => { /* tslint:disable:no-empty */ dispatch: {}, /* tslint:enable:no-empty */ - select: Observable.of(true) + select: observableOf(true) }); const token = authServiceStub.getToken(); diff --git a/src/app/core/auth/auth.interceptor.spec.ts b/src/app/core/auth/auth.interceptor.spec.ts index e0984bcd3a..89c9ed1951 100644 --- a/src/app/core/auth/auth.interceptor.spec.ts +++ b/src/app/core/auth/auth.interceptor.spec.ts @@ -4,7 +4,7 @@ import { HTTP_INTERCEPTORS } from '@angular/common/http'; import { Router } from '@angular/router'; import { Store } from '@ngrx/store'; -import { Observable } from 'rxjs'; +import { of as observableOf } from 'rxjs'; import { AuthInterceptor } from './auth.interceptor'; import { AuthService } from './auth.service'; @@ -23,7 +23,7 @@ describe(`AuthInterceptor`, () => { /* tslint:disable:no-empty */ dispatch: {}, /* tslint:enable:no-empty */ - select: Observable.of(true) + select: observableOf(true) }); beforeEach(() => { diff --git a/src/app/core/auth/auth.service.spec.ts b/src/app/core/auth/auth.service.spec.ts index 7e3406dece..0b10f38e74 100644 --- a/src/app/core/auth/auth.service.spec.ts +++ b/src/app/core/auth/auth.service.spec.ts @@ -3,9 +3,9 @@ import { CommonModule } from '@angular/common'; import { ActivatedRoute, Router } from '@angular/router'; import { Store, StoreModule } from '@ngrx/store'; -import { Observable } from 'rxjs'; import { REQUEST } from '@nguniversal/express-engine/tokens'; import 'rxjs/add/observable/of'; +import { of as observableOf } from 'rxjs'; import { authReducer, AuthState } from './auth.reducer'; import { NativeWindowRef, NativeWindowService } from '../../shared/services/window.service'; @@ -27,7 +27,7 @@ describe('AuthService test', () => { const mockStore: Store = jasmine.createSpyObj('store', { dispatch: {}, - select: Observable.of(true) + select: observableOf(true) }); let authService: AuthService; const authRequest = new AuthRequestServiceStub(); diff --git a/src/app/core/browse/browse.service.spec.ts b/src/app/core/browse/browse.service.spec.ts index 795a2eb7ff..85fd4b3804 100644 --- a/src/app/core/browse/browse.service.spec.ts +++ b/src/app/core/browse/browse.service.spec.ts @@ -1,5 +1,5 @@ import { cold, getTestScheduler, hot } from 'jasmine-marbles'; -import { TestScheduler } from 'rxjs'; +import { TestScheduler } from 'rxjs/testing'; import { getMockRemoteDataBuildService } from '../../shared/mocks/mock-remote-data-build.service'; import { getMockRequestService } from '../../shared/mocks/mock-request.service'; import { getMockResponseCacheService } from '../../shared/mocks/mock-response-cache.service'; 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 eb11db3ca4..fe7f56220f 100644 --- a/src/app/core/cache/builders/remote-data-build.service.ts +++ b/src/app/core/cache/builders/remote-data-build.service.ts @@ -1,5 +1,9 @@ - -import {combineLatest as observableCombineLatest, of as observableOf, Observable, race as observableRace } from 'rxjs'; +import { + combineLatest as observableCombineLatest, + of as observableOf, + Observable, + race as observableRace +} from 'rxjs'; import { Injectable } from '@angular/core'; import { distinctUntilChanged, flatMap, map, startWith } from 'rxjs/operators'; import { hasValue, hasValueOperator, isEmpty, isNotEmpty } from '../../../shared/empty.util'; @@ -66,15 +70,15 @@ export class RemoteDataBuildService { }), distinctUntilChanged(), startWith(undefined) - ), - (fromSelfLink, fromResponse) => { + ) + ).pipe( + map(([fromSelfLink, fromResponse]) => { if (hasValue(fromSelfLink)) { return fromSelfLink; } else { return fromResponse; } - } - ).pipe( + }), hasValueOperator(), map((normalized: TNormalized) => { return this.build(normalized); @@ -86,8 +90,8 @@ export class RemoteDataBuildService { } toRemoteDataObservable(requestEntry$: Observable, responseCache$: Observable, payload$: Observable) { - return observableCombineLatest(requestEntry$, responseCache$.pipe(startWith(undefined)), payload$, - (reqEntry: RequestEntry, resEntry: ResponseCacheEntry, payload: T) => { + return observableCombineLatest(requestEntry$, responseCache$.pipe(startWith(undefined)), payload$).pipe( + map(([reqEntry, resEntry, payload]) => { const requestPending = hasValue(reqEntry.requestPending) ? reqEntry.requestPending : true; const responsePending = hasValue(reqEntry.responsePending) ? reqEntry.responsePending : false; let isSuccessful: boolean; @@ -106,7 +110,8 @@ export class RemoteDataBuildService { error, payload ); - }); + }) + ); } buildList(href$: string | Observable): Observable>> { @@ -143,11 +148,13 @@ export class RemoteDataBuildService { } } }) - ); + ); - const payload$ = observableCombineLatest(tDomainList$, pageInfo$, (tDomainList, pageInfo) => { - return new PaginatedList(pageInfo, tDomainList); - }); + const payload$ = observableCombineLatest(tDomainList$, pageInfo$).pipe( + map(([tDomainList, pageInfo]) => { + return new PaginatedList(pageInfo, tDomainList); + }) + ); return this.toRemoteDataObservable(requestEntry$, responseCache$, payload$); } @@ -208,9 +215,8 @@ export class RemoteDataBuildService { return observableOf(new RemoteData(false, false, true, null, [])); } - return observableCombineLatest( - ...input, - (...arr: Array>) => { + return observableCombineLatest(...input).pipe( + map((arr) => { const requestPending: boolean = arr .map((d: RemoteData) => d.isRequestPending) .every((b: boolean) => b === true); @@ -252,11 +258,11 @@ export class RemoteDataBuildService { error, payload ); - }) + })) } aggregatePaginatedList(input: Observable>, pageInfo: PageInfo): Observable>> { - return input.pipe(map((rd) => Object.assign(rd, {payload: new PaginatedList(pageInfo, rd.payload)}))); + return input.pipe(map((rd) => Object.assign(rd, { payload: new PaginatedList(pageInfo, rd.payload) }))); } } diff --git a/src/app/core/cache/object-cache.service.spec.ts b/src/app/core/cache/object-cache.service.spec.ts index 39afe0c35e..763d0c195f 100644 --- a/src/app/core/cache/object-cache.service.spec.ts +++ b/src/app/core/cache/object-cache.service.spec.ts @@ -1,11 +1,12 @@ import { Store } from '@ngrx/store'; -import { Observable } from 'rxjs'; +import { of as observableOf } from 'rxjs'; import { ObjectCacheService } from './object-cache.service'; import { AddToObjectCacheAction, RemoveFromObjectCacheAction } from './object-cache.actions'; import { CoreState } from '../core.reducers'; import { ResourceType } from '../shared/resource-type'; import { NormalizedItem } from './models/normalized-item.model'; +import { first } from 'rxjs/operators'; describe('ObjectCacheService', () => { let service: ObjectCacheService; @@ -51,10 +52,10 @@ describe('ObjectCacheService', () => { describe('getBySelfLink', () => { it('should return an observable of the cached object with the specified self link and type', () => { - spyOn(store, 'select').and.returnValue(Observable.of(cacheEntry)); + spyOn(store, 'select').and.returnValue(observableOf(cacheEntry)); // due to the implementation of spyOn above, this subscribe will be synchronous - service.getBySelfLink(selfLink).take(1).subscribe((o) => { + service.getBySelfLink(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(); @@ -63,7 +64,7 @@ describe('ObjectCacheService', () => { }); it('should not return a cached object that has exceeded its time to live', () => { - spyOn(store, 'select').and.returnValue(Observable.of(invalidCacheEntry)); + spyOn(store, 'select').and.returnValue(observableOf(invalidCacheEntry)); let getObsHasFired = false; const subscription = service.getBySelfLink(selfLink).subscribe((o) => getObsHasFired = true); @@ -76,9 +77,9 @@ 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(Observable.of(item)); + spyOn(service, 'getBySelfLink').and.returnValue(observableOf(item)); - service.getList([selfLink, selfLink]).take(1).subscribe((arr) => { + service.getList([selfLink, selfLink]).pipe(first()).subscribe((arr) => { expect(arr[0].self).toBe(selfLink); expect(arr[0] instanceof NormalizedItem).toBeTruthy(); }); @@ -87,19 +88,19 @@ describe('ObjectCacheService', () => { describe('has', () => { it('should return true if the object with the supplied self link is cached and still valid', () => { - spyOn(store, 'select').and.returnValue(Observable.of(cacheEntry)); + spyOn(store, 'select').and.returnValue(observableOf(cacheEntry)); expect(service.hasBySelfLink(selfLink)).toBe(true); }); it("should return false if the object with the supplied self link isn't cached", () => { - spyOn(store, 'select').and.returnValue(Observable.of(undefined)); + spyOn(store, 'select').and.returnValue(observableOf(undefined)); expect(service.hasBySelfLink(selfLink)).toBe(false); }); it('should return false if the object with the supplied self link is cached but has exceeded its time to live', () => { - spyOn(store, 'select').and.returnValue(Observable.of(invalidCacheEntry)); + spyOn(store, 'select').and.returnValue(observableOf(invalidCacheEntry)); expect(service.hasBySelfLink(selfLink)).toBe(false); }); diff --git a/src/app/core/cache/response-cache.service.spec.ts b/src/app/core/cache/response-cache.service.spec.ts index 87db10db1b..9063fbf5a6 100644 --- a/src/app/core/cache/response-cache.service.spec.ts +++ b/src/app/core/cache/response-cache.service.spec.ts @@ -1,10 +1,11 @@ import { Store } from '@ngrx/store'; import { ResponseCacheService } from './response-cache.service'; -import { Observable } from 'rxjs'; +import { of as observableOf } from 'rxjs'; import { CoreState } from '../core.reducers'; import { RestResponse } from './response-cache.models'; import { ResponseCacheEntry } from './response-cache.reducer'; +import { first } from 'rxjs/operators'; describe('ResponseCacheService', () => { let service: ResponseCacheService; @@ -41,11 +42,11 @@ describe('ResponseCacheService', () => { describe('get', () => { it('should return an observable of the cached request with the specified key', () => { spyOn(store, 'select').and.callFake((...args: any[]) => { - return Observable.of(validCacheEntry(keys[1])); + return observableOf(validCacheEntry(keys[1])); }); let testObj: ResponseCacheEntry; - service.get(keys[1]).first().subscribe((entry) => { + service.get(keys[1]).pipe(first()).subscribe((entry) => { testObj = entry; }); expect(testObj.key).toEqual(keys[1]); @@ -53,7 +54,7 @@ describe('ResponseCacheService', () => { it('should not return a cached request that has exceeded its time to live', () => { spyOn(store, 'select').and.callFake((...args: any[]) => { - return Observable.of(invalidCacheEntry(keys[1])); + return observableOf(invalidCacheEntry(keys[1])); }); let getObsHasFired = false; @@ -65,17 +66,17 @@ describe('ResponseCacheService', () => { describe('has', () => { it('should return true if the request with the supplied key is cached and still valid', () => { - spyOn(store, 'select').and.returnValue(Observable.of(validCacheEntry(keys[1]))); + spyOn(store, 'select').and.returnValue(observableOf(validCacheEntry(keys[1]))); expect(service.has(keys[1])).toBe(true); }); it('should return false if the request with the supplied key isn\'t cached', () => { - spyOn(store, 'select').and.returnValue(Observable.of(undefined)); + spyOn(store, 'select').and.returnValue(observableOf(undefined)); expect(service.has(keys[1])).toBe(false); }); it('should return false if the request with the supplied key is cached but has exceeded its time to live', () => { - spyOn(store, 'select').and.returnValue(Observable.of(invalidCacheEntry(keys[1]))); + spyOn(store, 'select').and.returnValue(observableOf(invalidCacheEntry(keys[1]))); expect(service.has(keys[1])).toBe(false); }); }); diff --git a/src/app/core/config/config.service.spec.ts b/src/app/core/config/config.service.spec.ts index 75dff4018e..2cf00713c2 100644 --- a/src/app/core/config/config.service.spec.ts +++ b/src/app/core/config/config.service.spec.ts @@ -1,5 +1,5 @@ import { cold, getTestScheduler, hot } from 'jasmine-marbles'; -import { TestScheduler } from 'rxjs'; +import { TestScheduler } from 'rxjs/testing'; import { getMockRequestService } from '../../shared/mocks/mock-request.service'; import { ResponseCacheService } from '../cache/response-cache.service'; import { ConfigService } from './config.service'; diff --git a/src/app/core/data/comcol-data.service.spec.ts b/src/app/core/data/comcol-data.service.spec.ts index 99a71e5f0e..eb2e1bd1cf 100644 --- a/src/app/core/data/comcol-data.service.spec.ts +++ b/src/app/core/data/comcol-data.service.spec.ts @@ -1,10 +1,9 @@ import { Store } from '@ngrx/store'; import { cold, getTestScheduler, hot } from 'jasmine-marbles'; -import { TestScheduler } from 'rxjs'; +import { TestScheduler } from 'rxjs/testing'; import { GlobalConfig } from '../../../config'; import { getMockRequestService } from '../../shared/mocks/mock-request.service'; import { RemoteDataBuildService } from '../cache/builders/remote-data-build.service'; -import { NormalizedCommunity } from '../cache/models/normalized-community.model'; import { ObjectCacheService } from '../cache/object-cache.service'; import { ResponseCacheService } from '../cache/response-cache.service'; import { CoreState } from '../core.reducers'; diff --git a/src/app/core/data/dspace-object-data.service.spec.ts b/src/app/core/data/dspace-object-data.service.spec.ts index bb2bdc675d..ef767c5d2d 100644 --- a/src/app/core/data/dspace-object-data.service.spec.ts +++ b/src/app/core/data/dspace-object-data.service.spec.ts @@ -1,5 +1,5 @@ import { cold, getTestScheduler } from 'jasmine-marbles'; -import { TestScheduler } from '../../../../node_modules/rxjs'; +import { TestScheduler } from 'rxjs/testing'; import { RemoteDataBuildService } from '../cache/builders/remote-data-build.service'; import { DSpaceObject } from '../shared/dspace-object.model'; import { HALEndpointService } from '../shared/hal-endpoint.service'; diff --git a/src/app/core/data/item-data.service.spec.ts b/src/app/core/data/item-data.service.spec.ts index b48d3735f7..0a233d086c 100644 --- a/src/app/core/data/item-data.service.spec.ts +++ b/src/app/core/data/item-data.service.spec.ts @@ -1,6 +1,6 @@ import { Store } from '@ngrx/store'; import { cold, getTestScheduler } from 'jasmine-marbles'; -import { TestScheduler } from 'rxjs'; +import { TestScheduler } from 'rxjs/testing'; import { BrowseService } from '../browse/browse.service'; import { RemoteDataBuildService } from '../cache/builders/remote-data-build.service'; import { ResponseCacheService } from '../cache/response-cache.service'; diff --git a/src/app/core/integration/integration.service.spec.ts b/src/app/core/integration/integration.service.spec.ts index 60a2e8577a..f7e3769620 100644 --- a/src/app/core/integration/integration.service.spec.ts +++ b/src/app/core/integration/integration.service.spec.ts @@ -1,5 +1,5 @@ import { cold, getTestScheduler } from 'jasmine-marbles'; -import { TestScheduler } from 'rxjs'; +import { TestScheduler } from 'rxjs/testing'; import { getMockRequestService } from '../../shared/mocks/mock-request.service'; import { ResponseCacheService } from '../cache/response-cache.service'; diff --git a/src/app/core/metadata/metadata.service.spec.ts b/src/app/core/metadata/metadata.service.spec.ts index 39bedb33d2..50ce4711ff 100644 --- a/src/app/core/metadata/metadata.service.spec.ts +++ b/src/app/core/metadata/metadata.service.spec.ts @@ -1,17 +1,15 @@ -import { ComponentFixture, TestBed, async, fakeAsync, inject, tick } from '@angular/core/testing'; +import { ComponentFixture, fakeAsync, TestBed, tick } from '@angular/core/testing'; import { RouterTestingModule } from '@angular/router/testing'; -import { Location, CommonModule } from '@angular/common'; +import { CommonModule, Location } from '@angular/common'; import { Component, CUSTOM_ELEMENTS_SCHEMA } from '@angular/core'; -import { By, Meta, MetaDefinition, Title } from '@angular/platform-browser'; +import { Meta, MetaDefinition, Title } from '@angular/platform-browser'; import { ActivatedRoute, Router } from '@angular/router'; -import { TranslateModule, TranslateLoader } from '@ngx-translate/core'; +import { TranslateLoader, TranslateModule } from '@ngx-translate/core'; import { Store, StoreModule } from '@ngrx/store'; - -import { Observable } from 'rxjs'; -import { RemoteDataError } from '../data/remote-data-error'; +import { Observable, of as observableOf } from 'rxjs'; import { UUIDService } from '../shared/uuid.service'; import { MetadataService } from './metadata.service'; @@ -182,7 +180,7 @@ describe('MetadataService', () => { })); const mockRemoteData = (mockItem: Item): Observable> => { - return Observable.of(new RemoteData( + return observableOf(new RemoteData( false, false, true, diff --git a/src/app/core/registry/registry.service.spec.ts b/src/app/core/registry/registry.service.spec.ts index 2dceec7f08..d0ed1e5cb8 100644 --- a/src/app/core/registry/registry.service.spec.ts +++ b/src/app/core/registry/registry.service.spec.ts @@ -1,4 +1,4 @@ -import { async, TestBed } from '@angular/core/testing'; +import { TestBed } from '@angular/core/testing'; import { RegistryService } from './registry.service'; import { CommonModule } from '@angular/common'; import { ResponseCacheService } from '../cache/response-cache.service'; @@ -6,26 +6,24 @@ import { RequestService } from '../data/request.service'; import { RemoteDataBuildService } from '../cache/builders/remote-data-build.service'; import { HALEndpointService } from '../shared/hal-endpoint.service'; import { PaginationComponentOptions } from '../../shared/pagination/pagination-component-options.model'; -import { Observable } from 'rxjs'; +import { Observable, of as observableOf, combineLatest as observableCombineLatest } from 'rxjs'; import { ResponseCacheEntry } from '../cache/response-cache.reducer'; import { RequestEntry } from '../data/request.reducer'; import { RemoteData } from '../data/remote-data'; -import { PaginatedList } from '../data/paginated-list'; import { PageInfo } from '../shared/page-info.model'; -import { GetRequest } from '../data/request.models'; -import { URLCombiner } from '../url-combiner/url-combiner'; import { getMockRequestService } from '../../shared/mocks/mock-request.service'; import { getMockResponseCacheService } from '../../shared/mocks/mock-response-cache.service'; + import { RegistryBitstreamformatsSuccessResponse, - RegistryMetadatafieldsSuccessResponse, RegistryMetadataschemasSuccessResponse, - SearchSuccessResponse + RegistryMetadatafieldsSuccessResponse, + RegistryMetadataschemasSuccessResponse } from '../cache/response-cache.models'; -import { SearchQueryResponse } from '../../+search-page/search-service/search-query-response.model'; import { Component } from '@angular/core'; import { RegistryMetadataschemasResponse } from './registry-metadataschemas-response.model'; import { RegistryMetadatafieldsResponse } from './registry-metadatafields-response.model'; import { RegistryBitstreamformatsResponse } from './registry-bitstreamformats-response.model'; +import { map } from 'rxjs/operators'; @Component({ template: '' }) class DummyComponent { @@ -125,24 +123,25 @@ describe('RegistryService', () => { const endpointWithParams = `${endpoint}?size=${pageInfo.elementsPerPage}&page=${pageInfo.currentPage - 1}`; const halServiceStub = { - getEndpoint: (link: string) => Observable.of(endpoint) + getEndpoint: (link: string) => observableOf(endpoint) }; const rdbStub = { toRemoteDataObservable: (requestEntryObs: Observable, responseCacheObs: Observable, payloadObs: Observable) => { - return Observable.combineLatest(requestEntryObs, - responseCacheObs, payloadObs, (req, res, pay) => { + return observableCombineLatest(requestEntryObs, + responseCacheObs, payloadObs).pipe(map(([req, res, pay]) => { return { req, res, pay }; - }); + }) + ); }, aggregate: (input: Array>>): Observable> => { - return Observable.of(new RemoteData(false, false, true, null, [])); + return observableOf(new RemoteData(false, false, true, null, [])); } }; beforeEach(() => { TestBed.configureTestingModule({ - imports: [ CommonModule ], + imports: [CommonModule], declarations: [ DummyComponent ], @@ -156,16 +155,19 @@ describe('RegistryService', () => { }); registryService = TestBed.get(RegistryService); - spyOn((registryService as any).halService, 'getEndpoint').and.returnValue(Observable.of(endpoint)); + spyOn((registryService as any).halService, 'getEndpoint').and.returnValue(observableOf(endpoint)); }); describe('when requesting metadataschemas', () => { - const queryResponse = Object.assign(new RegistryMetadataschemasResponse(), { metadataschemas: mockSchemasList, page: pageInfo }); + const queryResponse = Object.assign(new RegistryMetadataschemasResponse(), { + metadataschemas: mockSchemasList, + page: pageInfo + }); const response = new RegistryMetadataschemasSuccessResponse(queryResponse, '200', pageInfo); const responseEntry = Object.assign(new ResponseCacheEntry(), { response: response }); beforeEach(() => { - (registryService as any).responseCache.get.and.returnValue(Observable.of(responseEntry)); + (registryService as any).responseCache.get.and.returnValue(observableOf(responseEntry)); /* tslint:disable:no-empty */ registryService.getMetadataSchemas(pagination).subscribe((value) => { }); @@ -190,12 +192,15 @@ describe('RegistryService', () => { }); describe('when requesting metadataschema by name', () => { - const queryResponse = Object.assign(new RegistryMetadataschemasResponse(), { metadataschemas: mockSchemasList, page: pageInfo }); + const queryResponse = Object.assign(new RegistryMetadataschemasResponse(), { + metadataschemas: mockSchemasList, + page: pageInfo + }); const response = new RegistryMetadataschemasSuccessResponse(queryResponse, '200', pageInfo); const responseEntry = Object.assign(new ResponseCacheEntry(), { response: response }); beforeEach(() => { - (registryService as any).responseCache.get.and.returnValue(Observable.of(responseEntry)); + (registryService as any).responseCache.get.and.returnValue(observableOf(responseEntry)); /* tslint:disable:no-empty */ registryService.getMetadataSchemaByName(mockSchemasList[0].prefix).subscribe((value) => { }); @@ -220,12 +225,15 @@ describe('RegistryService', () => { }); describe('when requesting metadatafields', () => { - const queryResponse = Object.assign(new RegistryMetadatafieldsResponse(), { metadatafields: mockFieldsList, page: pageInfo }); + const queryResponse = Object.assign(new RegistryMetadatafieldsResponse(), { + metadatafields: mockFieldsList, + page: pageInfo + }); const response = new RegistryMetadatafieldsSuccessResponse(queryResponse, '200', pageInfo); const responseEntry = Object.assign(new ResponseCacheEntry(), { response: response }); beforeEach(() => { - (registryService as any).responseCache.get.and.returnValue(Observable.of(responseEntry)); + (registryService as any).responseCache.get.and.returnValue(observableOf(responseEntry)); /* tslint:disable:no-empty */ registryService.getMetadataFieldsBySchema(mockSchemasList[0], pagination).subscribe((value) => { }); @@ -250,12 +258,15 @@ describe('RegistryService', () => { }); describe('when requesting bitstreamformats', () => { - const queryResponse = Object.assign(new RegistryBitstreamformatsResponse(), { bitstreamformats: mockFieldsList, page: pageInfo }); + const queryResponse = Object.assign(new RegistryBitstreamformatsResponse(), { + bitstreamformats: mockFieldsList, + page: pageInfo + }); const response = new RegistryBitstreamformatsSuccessResponse(queryResponse, '200', pageInfo); const responseEntry = Object.assign(new ResponseCacheEntry(), { response: response }); beforeEach(() => { - (registryService as any).responseCache.get.and.returnValue(Observable.of(responseEntry)); + (registryService as any).responseCache.get.and.returnValue(observableOf(responseEntry)); /* tslint:disable:no-empty */ registryService.getBitstreamFormats(pagination).subscribe((value) => { }); diff --git a/src/app/core/registry/registry.service.ts b/src/app/core/registry/registry.service.ts index 94c137dfd8..8bd2818b78 100644 --- a/src/app/core/registry/registry.service.ts +++ b/src/app/core/registry/registry.service.ts @@ -1,5 +1,4 @@ - -import {combineLatest as observableCombineLatest, Observable } from 'rxjs'; +import { combineLatest as observableCombineLatest, Observable } from 'rxjs'; import { Injectable } from '@angular/core'; import { RemoteData } from '../data/remote-data'; import { PaginatedList } from '../data/paginated-list'; @@ -18,7 +17,9 @@ import { ResponseCacheService } from '../cache/response-cache.service'; import { RegistryMetadataschemasResponse } from './registry-metadataschemas-response.model'; import { ResponseCacheEntry } from '../cache/response-cache.reducer'; import { - MetadataschemaSuccessResponse, RegistryBitstreamformatsSuccessResponse, RegistryMetadatafieldsSuccessResponse, + MetadataschemaSuccessResponse, + RegistryBitstreamformatsSuccessResponse, + RegistryMetadatafieldsSuccessResponse, RegistryMetadataschemasSuccessResponse } from '../cache/response-cache.models'; import { HALEndpointService } from '../shared/hal-endpoint.service'; @@ -71,9 +72,11 @@ export class RegistryService { map((response: RegistryMetadataschemasSuccessResponse) => response.pageInfo) ); - const payloadObs = observableCombineLatest(metadataschemasObs, pageInfoObs, (metadataschemas, pageInfo) => { - return new PaginatedList(pageInfo, metadataschemas); - }); + const payloadObs = observableCombineLatest(metadataschemasObs, pageInfoObs).pipe( + map(([metadataschemas, pageInfo]) => { + return new PaginatedList(pageInfo, metadataschemas); + }) + ); return this.rdb.toRemoteDataObservable(requestEntryObs, responseCacheObs, payloadObs); } @@ -133,9 +136,11 @@ export class RegistryService { map((response: RegistryMetadatafieldsSuccessResponse) => response.pageInfo) ); - const payloadObs = observableCombineLatest(metadatafieldsObs, pageInfoObs, (metadatafields, pageInfo) => { - return new PaginatedList(pageInfo, metadatafields); - }); + const payloadObs = observableCombineLatest(metadatafieldsObs, pageInfoObs).pipe( + map(([metadatafields, pageInfo]) => { + return new PaginatedList(pageInfo, metadatafields); + }) + ); return this.rdb.toRemoteDataObservable(requestEntryObs, responseCacheObs, payloadObs); } @@ -165,9 +170,11 @@ export class RegistryService { map((response: RegistryBitstreamformatsSuccessResponse) => response.pageInfo) ); - const payloadObs = observableCombineLatest(bitstreamformatsObs, pageInfoObs, (bitstreamformats, pageInfo) => { - return new PaginatedList(pageInfo, bitstreamformats); - }); + const payloadObs = observableCombineLatest(bitstreamformatsObs, pageInfoObs).pipe( + map(([bitstreamformats, pageInfo]) => { + return new PaginatedList(pageInfo, bitstreamformats); + }) + ); return this.rdb.toRemoteDataObservable(requestEntryObs, responseCacheObs, payloadObs); } diff --git a/src/app/core/shared/item.model.spec.ts b/src/app/core/shared/item.model.spec.ts index 601ad3c0dc..2e5388dc4d 100644 --- a/src/app/core/shared/item.model.spec.ts +++ b/src/app/core/shared/item.model.spec.ts @@ -1,10 +1,10 @@ -import { Observable } from 'rxjs'; +import { Observable, of as observableOf } from 'rxjs'; import { Item } from './item.model'; import { RemoteData } from '../data/remote-data'; import { Bitstream } from './bitstream.model'; import { isEmpty } from '../../shared/empty.util'; -import { PageInfo } from './page-info.model'; +import { first, map } from 'rxjs/operators'; describe('Item', () => { @@ -56,30 +56,30 @@ describe('Item', () => { it('should return the bitstreams related to this item with the specified bundle name', () => { const bitObs: Observable = item.getBitstreamsByBundleName(thumbnailBundleName); - bitObs.take(1).subscribe((bs) => + bitObs.pipe(first()).subscribe((bs) => expect(bs.every((b) => b.name === thumbnailBundleName)).toBeTruthy()); }); it('should return an empty array when no bitstreams with this bundleName exist for this item', () => { const bs: Observable = item.getBitstreamsByBundleName(nonExistingBundleName); - bs.take(1).subscribe((b) => expect(isEmpty(b)).toBeTruthy()); + bs.pipe(first()).subscribe((b) => expect(isEmpty(b)).toBeTruthy()); }); describe('get thumbnail', () => { beforeEach(() => { - spyOn(item, 'getBitstreamsByBundleName').and.returnValue(Observable.of([remoteDataThumbnail])); + spyOn(item, 'getBitstreamsByBundleName').and.returnValue(observableOf([remoteDataThumbnail])); }); it('should return the thumbnail of this item', () => { const path: string = thumbnailPath; const bitstream: Observable = item.getThumbnail(); - bitstream.map((b) => expect(b.content).toBe(path)); + bitstream.pipe(map((b) => expect(b.content).toBe(path))); }); }); describe('get files', () => { beforeEach(() => { - spyOn(item, 'getBitstreamsByBundleName').and.returnValue(Observable.of(bitstreams)); + spyOn(item, 'getBitstreamsByBundleName').and.returnValue(observableOf(bitstreams)); }); it("should return all bitstreams with 'ORIGINAL' as bundleName", () => { @@ -87,7 +87,7 @@ describe('Item', () => { const files: Observable = item.getFiles(); let index = 0; - files.map((f) => expect(f.length).toBe(2)); + files.pipe(map((f) => expect(f.length).toBe(2))); files.subscribe( (array) => array.forEach( (file) => { @@ -103,7 +103,7 @@ describe('Item', () => { }); function createRemoteDataObject(object: any) { - return Observable.of(new RemoteData( + return observableOf(new RemoteData( false, false, true, diff --git a/src/app/core/shared/operators.spec.ts b/src/app/core/shared/operators.spec.ts index bb2fc263fd..16bf633705 100644 --- a/src/app/core/shared/operators.spec.ts +++ b/src/app/core/shared/operators.spec.ts @@ -1,5 +1,5 @@ import { cold, getTestScheduler, hot } from 'jasmine-marbles'; -import { TestScheduler } from '../../../../node_modules/rxjs'; +import { TestScheduler } from 'rxjs/testing'; import { getMockRequestService } from '../../shared/mocks/mock-request.service'; import { getMockResponseCacheService } from '../../shared/mocks/mock-response-cache.service'; import { ResponseCacheEntry } from '../cache/response-cache.reducer'; diff --git a/src/app/header/header.component.spec.ts b/src/app/header/header.component.spec.ts index c88bdae08e..1cd0b6c33f 100644 --- a/src/app/header/header.component.spec.ts +++ b/src/app/header/header.component.spec.ts @@ -1,10 +1,10 @@ -import { ComponentFixture, TestBed, async } from '@angular/core/testing'; +import { async, ComponentFixture, TestBed } from '@angular/core/testing'; import { By } from '@angular/platform-browser'; import { Store, StoreModule } from '@ngrx/store'; import { TranslateModule } from '@ngx-translate/core'; import { NgbCollapseModule } from '@ng-bootstrap/ng-bootstrap'; -import { Observable } from 'rxjs'; +import { of as observableOf } from 'rxjs'; import { HeaderComponent } from './header.component'; import { HeaderState } from './header.reducer'; @@ -50,7 +50,7 @@ describe('HeaderComponent', () => { comp = fixture.componentInstance; - store = fixture.debugElement.injector.get(Store); + store = fixture.debugElement.injector.get(Store) as Store; spyOn(store, 'dispatch'); }); @@ -72,7 +72,7 @@ describe('HeaderComponent', () => { beforeEach(() => { menu = fixture.debugElement.query(By.css('#collapsingNav')).nativeElement; - spyOn(store, 'select').and.returnValue(Observable.of({ navCollapsed: true })); + spyOn(store, 'select').and.returnValue(observableOf({ navCollapsed: true })); fixture.detectChanges(); }); @@ -87,7 +87,7 @@ describe('HeaderComponent', () => { beforeEach(() => { menu = fixture.debugElement.query(By.css('#collapsingNav')).nativeElement; - spyOn(store, 'select').and.returnValue(Observable.of(false)); + spyOn(store, 'select').and.returnValue(observableOf(false)); fixture.detectChanges(); }); diff --git a/src/app/shared/form/builder/ds-dynamic-form-ui/ds-dynamic-form-control.component.spec.ts b/src/app/shared/form/builder/ds-dynamic-form-ui/ds-dynamic-form-control.component.spec.ts index 7fc756c470..c44f996102 100644 --- a/src/app/shared/form/builder/ds-dynamic-form-ui/ds-dynamic-form-control.component.spec.ts +++ b/src/app/shared/form/builder/ds-dynamic-form-ui/ds-dynamic-form-control.component.spec.ts @@ -149,7 +149,7 @@ describe('DsDynamicFormControlComponent test suite', () => { expect(component.change).toBeDefined(); expect(component.focus).toBeDefined(); - expect(component.onValueChange).toBeDefined(); + expect(component.onChange).toBeDefined(); expect(component.onBlur).toBeDefined(); expect(component.onFocus).toBeDefined(); @@ -185,11 +185,11 @@ describe('DsDynamicFormControlComponent test suite', () => { it('should listen to native change event', () => { - spyOn(component, 'onValueChange'); + spyOn(component, 'onChange'); testElement.triggerEventHandler('change', null); - expect(component.onValueChange).toHaveBeenCalled(); + expect(component.onChange).toHaveBeenCalled(); }); it('should update model value when control value changes', () => { diff --git a/src/app/shared/form/builder/ds-dynamic-form-ui/ds-dynamic-form-control.component.ts b/src/app/shared/form/builder/ds-dynamic-form-ui/ds-dynamic-form-control.component.ts index 432c3959b8..25d1be6585 100644 --- a/src/app/shared/form/builder/ds-dynamic-form-ui/ds-dynamic-form-control.component.ts +++ b/src/app/shared/form/builder/ds-dynamic-form-ui/ds-dynamic-form-control.component.ts @@ -1,6 +1,5 @@ import { - Component, - ComponentFactoryResolver, + Component, ComponentFactoryResolver, ContentChildren, EventEmitter, Input, @@ -21,7 +20,7 @@ import { DYNAMIC_FORM_CONTROL_TYPE_SELECT, DYNAMIC_FORM_CONTROL_TYPE_TEXTAREA, DYNAMIC_FORM_CONTROL_TYPE_TIMEPICKER, - DynamicDatePickerModel, DynamicFormControl, + DynamicDatePickerModel, DynamicFormControl, DynamicFormControlComponent, DynamicFormControlContainerComponent, DynamicFormControlEvent, DynamicFormControlModel, @@ -38,6 +37,7 @@ import { DYNAMIC_FORM_CONTROL_TYPE_DSDATEPICKER } from './models/date-picker/dat import { DYNAMIC_FORM_CONTROL_TYPE_LOOKUP } from './models/lookup/dynamic-lookup.model'; import { DynamicListCheckboxGroupModel } from './models/list/dynamic-list-checkbox-group.model'; import { DynamicListRadioGroupModel } from './models/list/dynamic-list-radio-group.model'; +import { isNotEmpty } from '../../../empty.util'; import { DYNAMIC_FORM_CONTROL_TYPE_LOOKUP_NAME } from './models/lookup/dynamic-lookup-name.model'; export const enum NGBootstrapFormControlType { @@ -89,9 +89,10 @@ export class DsDynamicFormControlComponent extends DynamicFormControlContainerCo @Output('dfFocus') focus: EventEmitter = new EventEmitter(); /* tslint:enable:no-output-rename */ - componentType: Type | null; type: NGBootstrapFormControlType | null; + readonly componentType: Type | null; + static getFormControlType(model: DynamicFormControlModel): NGBootstrapFormControlType | null { switch (model.type) { @@ -162,7 +163,7 @@ export class DsDynamicFormControlComponent extends DynamicFormControlContainerCo ngOnChanges(changes: SimpleChanges) { if (changes) { - super.ngOnChanges(changes); + // super.ngOnChanges(changes); } if (changes.model) { @@ -170,4 +171,9 @@ export class DsDynamicFormControlComponent extends DynamicFormControlContainerCo } } + onChangeLanguage(event) { + if (isNotEmpty((this.model as any).value)) { + this.onChange(event); + } + } } diff --git a/src/app/shared/form/builder/ds-dynamic-form-ui/models/dynamic-group/dynamic-group.component.spec.ts b/src/app/shared/form/builder/ds-dynamic-form-ui/models/dynamic-group/dynamic-group.component.spec.ts index d9f821cc4d..94c2faba95 100644 --- a/src/app/shared/form/builder/ds-dynamic-form-ui/models/dynamic-group/dynamic-group.component.spec.ts +++ b/src/app/shared/form/builder/ds-dynamic-form-ui/models/dynamic-group/dynamic-group.component.spec.ts @@ -6,13 +6,15 @@ import { FormControl, FormGroup, FormsModule, ReactiveFormsModule } from '@angul import { DynamicFormValidationService } from '@ng-dynamic-forms/core'; import { Store } from '@ngrx/store'; import { TranslateModule } from '@ngx-translate/core'; -import { Observable } from 'rxjs'; -import 'rxjs/add/observable/of'; +import { of as observableOf } from 'rxjs'; import { NgbModule } from '@ng-bootstrap/ng-bootstrap'; import { DsDynamicGroupComponent } from './dynamic-group.components'; import { DynamicGroupModel, DynamicGroupModelConfig } from './dynamic-group.model'; -import { FormRowModel, SubmissionFormsModel } from '../../../../../../core/shared/config/config-submission-forms.model'; +import { + FormRowModel, + SubmissionFormsModel +} from '../../../../../../core/shared/config/config-submission-forms.model'; import { FormFieldModel } from '../../../models/form-field.model'; import { FormBuilderService } from '../../../form-builder.service'; import { FormService } from '../../../../form.service'; @@ -97,7 +99,7 @@ describe('DsDynamicGroupComponent test suite', () => { const store: Store = jasmine.createSpyObj('store', { dispatch: {}, - select: Observable.of(true) + select: observableOf(true) }); // async beforeEach @@ -182,7 +184,7 @@ describe('DsDynamicGroupComponent test suite', () => { const formModel = service.modelFromConfiguration(formConfig, groupComp.model.scopeUUID, {}, groupComp.model.submissionScope, groupComp.model.readOnly); const chips = new Chips([], 'value', 'dc.contributor.author'); - expect(groupComp.formCollapsed).toEqual(Observable.of(false)); + expect(groupComp.formCollapsed).toEqual(observableOf(false)); expect(groupComp.formModel.length).toEqual(formModel.length); expect(groupComp.chips.getChipsItems()).toEqual(chips.getChipsItems()); })); @@ -203,7 +205,7 @@ describe('DsDynamicGroupComponent test suite', () => { btnEl.click(); expect(groupComp.chips.getChipsItems()).toEqual(modelValue); - expect(groupComp.formCollapsed).toEqual(Observable.of(true)); + expect(groupComp.formCollapsed).toEqual(observableOf(true)); }); it('should clear form inputs', () => { @@ -220,7 +222,7 @@ describe('DsDynamicGroupComponent test suite', () => { expect(control1.value).toBeNull(); expect(control2.value).toBeNull(); - expect(groupComp.formCollapsed).toEqual(Observable.of(false)); + expect(groupComp.formCollapsed).toEqual(observableOf(false)); }); }); @@ -252,7 +254,7 @@ describe('DsDynamicGroupComponent test suite', () => { const formModel = service.modelFromConfiguration(formConfig, groupComp.model.scopeUUID, {}, groupComp.model.submissionScope, groupComp.model.readOnly); const chips = new Chips(modelValue, 'value', 'dc.contributor.author'); - expect(groupComp.formCollapsed).toEqual(Observable.of(true)); + expect(groupComp.formCollapsed).toEqual(observableOf(true)); expect(groupComp.formModel.length).toEqual(formModel.length); expect(groupComp.chips.getChipsItems()).toEqual(chips.getChipsItems()); })); @@ -280,7 +282,7 @@ describe('DsDynamicGroupComponent test suite', () => { groupFixture.detectChanges(); expect(groupComp.chips.getChipsItems()).toEqual(modelValue); - expect(groupComp.formCollapsed).toEqual(Observable.of(true)); + expect(groupComp.formCollapsed).toEqual(observableOf(true)); })); it('should delete existing chips item', () => { @@ -292,7 +294,7 @@ describe('DsDynamicGroupComponent test suite', () => { btnEl.click(); expect(groupComp.chips.getChipsItems()).toEqual([]); - expect(groupComp.formCollapsed).toEqual(Observable.of(false)); + expect(groupComp.formCollapsed).toEqual(observableOf(false)); }); }); }); diff --git a/src/app/shared/form/builder/ds-dynamic-form-ui/models/dynamic-group/dynamic-group.components.ts b/src/app/shared/form/builder/ds-dynamic-form-ui/models/dynamic-group/dynamic-group.components.ts index 5aa80bbcd0..4857063540 100644 --- a/src/app/shared/form/builder/ds-dynamic-form-ui/models/dynamic-group/dynamic-group.components.ts +++ b/src/app/shared/form/builder/ds-dynamic-form-ui/models/dynamic-group/dynamic-group.components.ts @@ -73,7 +73,7 @@ export class DsDynamicGroupComponent implements OnDestroy, OnInit { } else { this.expandForm(); } - // this.formCollapsed = (isNotEmpty(value) && !(value.length === 1 && hasOnlyEmptyProperties(value[0]))) ? Observable.of(true) : Observable.of(false); + // this.formCollapsed = (isNotEmpty(value) && !(value.length === 1 && hasOnlyEmptyProperties(value[0]))) ? observableOf(true) : observableOf(false); }); this.formId = this.formService.getUniqueId(this.model.id); diff --git a/src/app/shared/form/builder/ds-dynamic-form-ui/models/tag/dynamic-tag.component.spec.ts b/src/app/shared/form/builder/ds-dynamic-form-ui/models/tag/dynamic-tag.component.spec.ts index 9ef63e4d57..fc5bb8082d 100644 --- a/src/app/shared/form/builder/ds-dynamic-form-ui/models/tag/dynamic-tag.component.spec.ts +++ b/src/app/shared/form/builder/ds-dynamic-form-ui/models/tag/dynamic-tag.component.spec.ts @@ -2,12 +2,11 @@ import { ChangeDetectorRef, Component, CUSTOM_ELEMENTS_SCHEMA } from '@angular/core'; import { FormControl, FormGroup, FormsModule, ReactiveFormsModule } from '@angular/forms'; import { async, ComponentFixture, fakeAsync, flush, inject, TestBed, } from '@angular/core/testing'; +import { of as observableOf } from 'rxjs'; import { DynamicFormsCoreModule } from '@ng-dynamic-forms/core'; import { DynamicFormsNGBootstrapUIModule } from '@ng-dynamic-forms/ui-ng-bootstrap'; import { NgbModule, NgbTypeaheadSelectItemEvent } from '@ng-bootstrap/ng-bootstrap'; -import { Observable } from 'rxjs'; -import 'rxjs/add/observable/of' import { AuthorityOptions } from '../../../../../../core/integration/models/authority-options.model'; import { AuthorityService } from '../../../../../../core/integration/authority.service'; @@ -140,7 +139,7 @@ describe('DsDynamicTagComponent test suite', () => { it('should search when 3+ characters typed', fakeAsync(() => { spyOn((tagComp as any).authorityService, 'getEntriesByName').and.callThrough(); - tagComp.search(Observable.of('test')).subscribe(() => { + tagComp.search(observableOf('test')).subscribe(() => { expect((tagComp as any).authorityService.getEntriesByName).toHaveBeenCalled(); }); })); diff --git a/src/app/shared/form/builder/ds-dynamic-form-ui/models/typeahead/dynamic-typeahead.component.spec.ts b/src/app/shared/form/builder/ds-dynamic-form-ui/models/typeahead/dynamic-typeahead.component.spec.ts index c146615a99..daaf5c47d6 100644 --- a/src/app/shared/form/builder/ds-dynamic-form-ui/models/typeahead/dynamic-typeahead.component.spec.ts +++ b/src/app/shared/form/builder/ds-dynamic-form-ui/models/typeahead/dynamic-typeahead.component.spec.ts @@ -3,8 +3,7 @@ import { ChangeDetectorRef, Component, CUSTOM_ELEMENTS_SCHEMA } from '@angular/c import { FormControl, FormGroup, FormsModule, ReactiveFormsModule } from '@angular/forms'; import { async, ComponentFixture, fakeAsync, inject, TestBed, } from '@angular/core/testing'; import { By } from '@angular/platform-browser'; - -import { Observable } from 'rxjs'; +import { of as observableOf } from 'rxjs'; import 'rxjs/add/observable/of'; import { AuthorityOptions } from '../../../../../../core/integration/models/authority-options.model'; @@ -123,7 +122,7 @@ describe('DsDynamicTypeaheadComponent test suite', () => { it('should search when 3+ characters typed', fakeAsync(() => { spyOn((typeaheadComp as any).authorityService, 'getEntriesByName').and.callThrough(); - typeaheadComp.search(Observable.of('test')).subscribe(() => { + typeaheadComp.search(observableOf('test')).subscribe(() => { expect((typeaheadComp as any).authorityService.getEntriesByName).toHaveBeenCalled(); }); diff --git a/src/app/shared/form/builder/form-builder.service.spec.ts b/src/app/shared/form/builder/form-builder.service.spec.ts index 12f51166b5..c06273a564 100644 --- a/src/app/shared/form/builder/form-builder.service.spec.ts +++ b/src/app/shared/form/builder/form-builder.service.spec.ts @@ -16,7 +16,7 @@ import { DynamicFileUploadModel, DynamicFormArrayGroupModel, DynamicFormArrayModel, DynamicFormControlModel, - DynamicFormControlValue, + // DynamicFormControlValue, DynamicFormGroupModel, DynamicFormService, DynamicFormValidationService, @@ -761,8 +761,8 @@ describe('FormBuilderService test suite', () => { (formArray.at(index) as FormGroup).controls.testFormArrayGroupInput.setValue('next test value 1'); (formArray.at(index + step) as FormGroup).controls.testFormArrayGroupInput.setValue('next test value 2'); - (model.get(index).get(0) as DynamicFormValueControlModel).valueUpdates.next('next test value 1'); - (model.get(index + step).get(0) as DynamicFormValueControlModel).valueUpdates.next('next test value 2'); + (model.get(index).get(0) as DynamicFormValueControlModel).valueUpdates.next('next test value 1'); + (model.get(index + step).get(0) as DynamicFormValueControlModel).valueUpdates.next('next test value 2'); service.moveFormArrayGroup(index, step, formArray, model); @@ -771,8 +771,8 @@ describe('FormBuilderService test suite', () => { expect((formArray.at(index) as FormGroup).controls.testFormArrayGroupInput.value).toEqual('next test value 2'); expect((formArray.at(index + step) as FormGroup).controls.testFormArrayGroupInput.value).toEqual('next test value 1'); - expect((model.get(index).get(0) as DynamicFormValueControlModel).value).toEqual('next test value 2'); - expect((model.get(index + step).get(0) as DynamicFormValueControlModel).value).toEqual('next test value 1'); + expect((model.get(index).get(0) as DynamicFormValueControlModel).value).toEqual('next test value 2'); + expect((model.get(index + step).get(0) as DynamicFormValueControlModel).value).toEqual('next test value 1'); }); it('should move down a form array group', () => { @@ -785,8 +785,8 @@ describe('FormBuilderService test suite', () => { (formArray.at(index) as FormGroup).controls.testFormArrayGroupInput.setValue('next test value 1'); (formArray.at(index + step) as FormGroup).controls.testFormArrayGroupInput.setValue('next test value 2'); - (model.get(index).get(0) as DynamicFormValueControlModel).valueUpdates.next('next test value 1'); - (model.get(index + step).get(0) as DynamicFormValueControlModel).valueUpdates.next('next test value 2'); + (model.get(index).get(0) as DynamicFormValueControlModel).valueUpdates.next('next test value 1'); + (model.get(index + step).get(0) as DynamicFormValueControlModel).valueUpdates.next('next test value 2'); service.moveFormArrayGroup(index, step, formArray, model); @@ -795,8 +795,8 @@ describe('FormBuilderService test suite', () => { expect((formArray.at(index) as FormGroup).controls.testFormArrayGroupInput.value).toEqual('next test value 2'); expect((formArray.at(index + step) as FormGroup).controls.testFormArrayGroupInput.value).toEqual('next test value 1'); - expect((model.get(index).get(0) as DynamicFormValueControlModel).value).toEqual('next test value 2'); - expect((model.get(index + step).get(0) as DynamicFormValueControlModel).value).toEqual('next test value 1'); + expect((model.get(index).get(0) as DynamicFormValueControlModel).value).toEqual('next test value 2'); + expect((model.get(index + step).get(0) as DynamicFormValueControlModel).value).toEqual('next test value 1'); }); it('should throw when form array group is to be moved out of bounds', () => { diff --git a/src/app/shared/host-window.service.spec.ts b/src/app/shared/host-window.service.spec.ts index b7dc58757b..e4f0aa9d35 100644 --- a/src/app/shared/host-window.service.spec.ts +++ b/src/app/shared/host-window.service.spec.ts @@ -1,8 +1,7 @@ import { Store } from '@ngrx/store'; import { cold, hot } from 'jasmine-marbles'; -import { Observable } from 'rxjs'; +import { of as observableOf } from 'rxjs'; import { AppState } from '../app.reducer'; -import { HostWindowState } from './host-window.reducer'; import { GridBreakpoint, HostWindowService, WidthCategory } from './host-window.service'; @@ -13,7 +12,7 @@ describe('HostWindowService', () => { describe('', () => { beforeEach(() => { const _initialState = { hostWindow: { width: 1600, height: 770 } }; - store = new Store(Observable.of(_initialState), undefined, undefined); + store = new Store(observableOf(_initialState), undefined, undefined); service = new HostWindowService(store); }); @@ -49,7 +48,7 @@ describe('HostWindowService', () => { describe('', () => { beforeEach(() => { const _initialState = { hostWindow: { width: 1100, height: 770 } }; - store = new Store(Observable.of(_initialState), undefined, undefined); + store = new Store(observableOf(_initialState), undefined, undefined); service = new HostWindowService(store); }); @@ -85,7 +84,7 @@ describe('HostWindowService', () => { describe('', () => { beforeEach(() => { const _initialState = { hostWindow: { width: 800, height: 770 } }; - store = new Store(Observable.of(_initialState), undefined, undefined); + store = new Store(observableOf(_initialState), undefined, undefined); service = new HostWindowService(store); }); @@ -121,7 +120,7 @@ describe('HostWindowService', () => { describe('', () => { beforeEach(() => { const _initialState = { hostWindow: { width: 600, height: 770 } }; - store = new Store(Observable.of(_initialState), undefined, undefined); + store = new Store(observableOf(_initialState), undefined, undefined); service = new HostWindowService(store); }); @@ -157,7 +156,7 @@ describe('HostWindowService', () => { describe('', () => { beforeEach(() => { const _initialState = { hostWindow: { width: 400, height: 770 } }; - store = new Store(Observable.of(_initialState), undefined, undefined); + store = new Store(observableOf(_initialState), undefined, undefined); service = new HostWindowService(store); }); diff --git a/src/app/shared/host-window.service.ts b/src/app/shared/host-window.service.ts index 9023a4e719..09ac7c7995 100644 --- a/src/app/shared/host-window.service.ts +++ b/src/app/shared/host-window.service.ts @@ -99,8 +99,10 @@ export class HostWindowService { isXsOrSm(): Observable { return observableCombineLatest( this.isXs(), - this.isSm(), - ((isXs, isSm) => isXs || isSm) - ).pipe(distinctUntilChanged()); + this.isSm() + ).pipe( + map(([isXs, isSm]) => isXs || isSm), + distinctUntilChanged() + ); } } diff --git a/src/app/shared/notifications/notifications.service.spec.ts b/src/app/shared/notifications/notifications.service.spec.ts index e2820629c6..f59f48f92d 100644 --- a/src/app/shared/notifications/notifications.service.spec.ts +++ b/src/app/shared/notifications/notifications.service.spec.ts @@ -4,9 +4,13 @@ import { NotificationsBoardComponent } from './notifications-board/notifications import { NotificationComponent } from './notification/notification.component'; import { Store, StoreModule } from '@ngrx/store'; import { notificationsReducer } from './notifications.reducers'; -import { Observable } from 'rxjs'; +import { of as observableOf } from 'rxjs'; import 'rxjs/add/observable/of'; -import { NewNotificationAction, RemoveAllNotificationsAction, RemoveNotificationAction } from './notifications.actions'; +import { + NewNotificationAction, + RemoveAllNotificationsAction, + RemoveNotificationAction +} from './notifications.actions'; import { Notification } from './models/notification.model'; import { NotificationType } from './models/notification-type'; import { GlobalConfig } from '../../../config/global-config.interface'; @@ -14,7 +18,7 @@ import { GlobalConfig } from '../../../config/global-config.interface'; describe('NotificationsService test', () => { const store: Store = jasmine.createSpyObj('store', { dispatch: {}, - select: Observable.of(true) + select: observableOf(true) }); let service; let envConfig: GlobalConfig; @@ -43,25 +47,25 @@ describe('NotificationsService test', () => { }); it('Success method should dispatch NewNotificationAction with proper parameter', () => { - const notification = service.success('Title', Observable.of('Content')); + const notification = service.success('Title', observableOf('Content')); expect(notification.type).toBe(NotificationType.Success); expect(store.dispatch).toHaveBeenCalledWith(new NewNotificationAction(notification)); }); it('Warning method should dispatch NewNotificationAction with proper parameter', () => { - const notification = service.warning('Title', Observable.of('Content')); + const notification = service.warning('Title', observableOf('Content')); expect(notification.type).toBe(NotificationType.Warning); expect(store.dispatch).toHaveBeenCalledWith(new NewNotificationAction(notification)); }); it('Info method should dispatch NewNotificationAction with proper parameter', () => { - const notification = service.info('Title', Observable.of('Content')); + const notification = service.info('Title', observableOf('Content')); expect(notification.type).toBe(NotificationType.Info); expect(store.dispatch).toHaveBeenCalledWith(new NewNotificationAction(notification)); }); it('Error method should dispatch NewNotificationAction with proper parameter', () => { - const notification = service.error('Title', Observable.of('Content')); + const notification = service.error('Title', observableOf('Content')); expect(notification.type).toBe(NotificationType.Error); expect(store.dispatch).toHaveBeenCalledWith(new NewNotificationAction(notification)); }); diff --git a/src/app/shared/object-collection/object-collection.component.spec.ts b/src/app/shared/object-collection/object-collection.component.spec.ts index 336cb13474..66767ff78e 100644 --- a/src/app/shared/object-collection/object-collection.component.spec.ts +++ b/src/app/shared/object-collection/object-collection.component.spec.ts @@ -3,7 +3,7 @@ import { By } from '@angular/platform-browser'; import { async, ComponentFixture, TestBed } from '@angular/core/testing'; import { NO_ERRORS_SCHEMA } from '@angular/core'; import { ActivatedRoute, Router } from '@angular/router'; -import { Observable } from 'rxjs'; +import { of as observableOf } from 'rxjs'; import { RouterStub } from '../testing/router-stub'; import { ViewMode } from '../../core/shared/view-mode.model'; @@ -14,7 +14,7 @@ describe('ObjectCollectionComponent', () => { const queryParam = 'test query'; const scopeParam = '7669c72a-3f2a-451f-a3b9-9210e7a4c02f'; const activatedRouteStub = { - queryParams: Observable.of({ + queryParams: observableOf({ query: queryParam, scope: scopeParam }) diff --git a/src/app/shared/object-grid/item-grid-element/item-grid-element.component.spec.ts b/src/app/shared/object-grid/item-grid-element/item-grid-element.component.spec.ts index 245235e725..f2aa594296 100644 --- a/src/app/shared/object-grid/item-grid-element/item-grid-element.component.spec.ts +++ b/src/app/shared/object-grid/item-grid-element/item-grid-element.component.spec.ts @@ -4,13 +4,13 @@ import { ChangeDetectionStrategy, NO_ERRORS_SCHEMA } from '@angular/core'; import { By } from '@angular/platform-browser'; import { TruncatePipe } from '../../utils/truncate.pipe'; import { Item } from '../../../core/shared/item.model'; -import { Observable } from 'rxjs'; +import { of as observableOf } from 'rxjs'; let itemGridElementComponent: ItemGridElementComponent; let fixture: ComponentFixture; const mockItemWithAuthorAndDate: Item = Object.assign(new Item(), { - bitstreams: Observable.of({}), + bitstreams: observableOf({}), metadata: [ { key: 'dc.contributor.author', @@ -24,7 +24,7 @@ const mockItemWithAuthorAndDate: Item = Object.assign(new Item(), { }] }); const mockItemWithoutAuthorAndDate: Item = Object.assign(new Item(), { - bitstreams: Observable.of({}), + bitstreams: observableOf({}), metadata: [ { key: 'dc.title', diff --git a/src/app/shared/object-grid/object-grid.component.ts b/src/app/shared/object-grid/object-grid.component.ts index c5ded101b3..e539ca5714 100644 --- a/src/app/shared/object-grid/object-grid.component.ts +++ b/src/app/shared/object-grid/object-grid.component.ts @@ -1,7 +1,6 @@ +import { combineLatest as observableCombineLatest, BehaviorSubject, Observable } from 'rxjs'; -import {combineLatest as observableCombineLatest, BehaviorSubject , Observable } from 'rxjs'; - -import {startWith, distinctUntilChanged, map } from 'rxjs/operators'; +import { startWith, distinctUntilChanged, map } from 'rxjs/operators'; import { ChangeDetectionStrategy, Component, @@ -26,7 +25,7 @@ import { PaginationComponentOptions } from '../pagination/pagination-component-o changeDetection: ChangeDetectionStrategy.Default, encapsulation: ViewEncapsulation.Emulated, selector: 'ds-object-grid', - styleUrls: [ './object-grid.component.scss' ], + styleUrls: ['./object-grid.component.scss'], templateUrl: './object-grid.component.html', animations: [fadeIn] }) @@ -38,9 +37,11 @@ export class ObjectGridComponent implements OnInit { @Input() hideGear = false; @Input() hidePagerWhenSinglePage = true; private _objects$: BehaviorSubject>>; + @Input() set objects(objects: RemoteData>) { this._objects$.next(objects); } + get objects() { return this._objects$.getValue(); } @@ -111,26 +112,25 @@ export class ObjectGridComponent implements OnInit { this.columns$ = observableCombineLatest( nbColumns$, - this._objects$, - (nbColumns, objects) => { - if (hasValue(objects) && hasValue(objects.payload) && hasValue(objects.payload.page)) { - const page = objects.payload.page; + this._objects$).pipe(map(([nbColumns, objects]) => { + if (hasValue(objects) && hasValue(objects.payload) && hasValue(objects.payload.page)) { + const page = objects.payload.page; - const result = []; + const result = []; - page.forEach((obj: ListableObject, i: number) => { - const colNb = i % nbColumns; - let col = result[colNb]; - if (hasNoValue(col)) { - col = []; - } - result[colNb] = [...col, obj]; - }); - return result; - } else { - return []; - } - }); + page.forEach((obj: ListableObject, i: number) => { + const colNb = i % nbColumns; + let col = result[colNb]; + if (hasNoValue(col)) { + col = []; + } + result[colNb] = [...col, obj]; + }); + return result; + } else { + return []; + } + })); } onPageChange(event) { diff --git a/src/app/shared/object-grid/search-result-grid-element/collection-search-result/collection-search-result-grid-element.component.spec.ts b/src/app/shared/object-grid/search-result-grid-element/collection-search-result/collection-search-result-grid-element.component.spec.ts index 88c1fab8cd..8e6ff0696f 100644 --- a/src/app/shared/object-grid/search-result-grid-element/collection-search-result/collection-search-result-grid-element.component.spec.ts +++ b/src/app/shared/object-grid/search-result-grid-element/collection-search-result/collection-search-result-grid-element.component.spec.ts @@ -1,6 +1,6 @@ import { CollectionSearchResultGridElementComponent } from './collection-search-result-grid-element.component'; import { async, ComponentFixture, TestBed } from '@angular/core/testing'; -import { Observable } from 'rxjs'; +import { of as observableOf } from 'rxjs'; import { ChangeDetectionStrategy, NO_ERRORS_SCHEMA } from '@angular/core'; import { By } from '@angular/platform-browser'; import { TruncatePipe } from '../../../utils/truncate.pipe'; @@ -12,7 +12,7 @@ let collectionSearchResultGridElementComponent: CollectionSearchResultGridElemen let fixture: ComponentFixture; const truncatableServiceStub: any = { - isCollapsed: (id: number) => Observable.of(true), + isCollapsed: (id: number) => observableOf(true), }; const mockCollectionWithAbstract: CollectionSearchResult = new CollectionSearchResult(); diff --git a/src/app/shared/object-grid/search-result-grid-element/community-search-result/community-search-result-grid-element.component.spec.ts b/src/app/shared/object-grid/search-result-grid-element/community-search-result/community-search-result-grid-element.component.spec.ts index 06612b8a3f..df8fdf026d 100644 --- a/src/app/shared/object-grid/search-result-grid-element/community-search-result/community-search-result-grid-element.component.spec.ts +++ b/src/app/shared/object-grid/search-result-grid-element/community-search-result/community-search-result-grid-element.component.spec.ts @@ -1,6 +1,6 @@ import { CommunitySearchResultGridElementComponent } from './community-search-result-grid-element.component'; import { async, ComponentFixture, TestBed } from '@angular/core/testing'; -import { Observable } from 'rxjs'; +import { of as observableOf } from 'rxjs'; import { ChangeDetectionStrategy, NO_ERRORS_SCHEMA } from '@angular/core'; import { By } from '@angular/platform-browser'; import { TruncatePipe } from '../../../utils/truncate.pipe'; @@ -12,7 +12,7 @@ let communitySearchResultGridElementComponent: CommunitySearchResultGridElementC let fixture: ComponentFixture; const truncatableServiceStub: any = { - isCollapsed: (id: number) => Observable.of(true), + isCollapsed: (id: number) => observableOf(true), }; const mockCommunityWithAbstract: CommunitySearchResult = new CommunitySearchResult(); diff --git a/src/app/shared/object-grid/search-result-grid-element/item-search-result/item-search-result-grid-element.component.spec.ts b/src/app/shared/object-grid/search-result-grid-element/item-search-result/item-search-result-grid-element.component.spec.ts index 839ec9271b..ecc218f11d 100644 --- a/src/app/shared/object-grid/search-result-grid-element/item-search-result/item-search-result-grid-element.component.spec.ts +++ b/src/app/shared/object-grid/search-result-grid-element/item-search-result/item-search-result-grid-element.component.spec.ts @@ -1,7 +1,7 @@ import { ItemSearchResultGridElementComponent } from './item-search-result-grid-element.component'; import { async, ComponentFixture, TestBed } from '@angular/core/testing'; -import { Observable } from 'rxjs'; -import { NO_ERRORS_SCHEMA, ChangeDetectionStrategy } from '@angular/core'; +import { of as observableOf } from 'rxjs'; +import { ChangeDetectionStrategy, NO_ERRORS_SCHEMA } from '@angular/core'; import { By } from '@angular/platform-browser'; import { TruncatePipe } from '../../../utils/truncate.pipe'; import { Item } from '../../../../core/shared/item.model'; @@ -13,13 +13,13 @@ let itemSearchResultGridElementComponent: ItemSearchResultGridElementComponent; let fixture: ComponentFixture; const truncatableServiceStub: any = { - isCollapsed: (id: number) => Observable.of(true), + isCollapsed: (id: number) => observableOf(true), }; const mockItemWithAuthorAndDate: ItemSearchResult = new ItemSearchResult(); mockItemWithAuthorAndDate.hitHighlights = []; mockItemWithAuthorAndDate.dspaceObject = Object.assign(new Item(), { - bitstreams: Observable.of({}), + bitstreams: observableOf({}), metadata: [ { key: 'dc.contributor.author', @@ -36,7 +36,7 @@ mockItemWithAuthorAndDate.dspaceObject = Object.assign(new Item(), { const mockItemWithoutAuthorAndDate: ItemSearchResult = new ItemSearchResult(); mockItemWithoutAuthorAndDate.hitHighlights = []; mockItemWithoutAuthorAndDate.dspaceObject = Object.assign(new Item(), { - bitstreams: Observable.of({}), + bitstreams: observableOf({}), metadata: [ { key: 'dc.title', diff --git a/src/app/shared/object-grid/wrapper-grid-element/wrapper-grid-element.component.spec.ts b/src/app/shared/object-grid/wrapper-grid-element/wrapper-grid-element.component.spec.ts index cf98f7268c..0a78c97209 100644 --- a/src/app/shared/object-grid/wrapper-grid-element/wrapper-grid-element.component.spec.ts +++ b/src/app/shared/object-grid/wrapper-grid-element/wrapper-grid-element.component.spec.ts @@ -1,6 +1,6 @@ import { WrapperGridElementComponent } from './wrapper-grid-element.component'; import { async, ComponentFixture, TestBed } from '@angular/core/testing'; -import { Observable } from 'rxjs'; +import { of as observableOf } from 'rxjs'; import { ActivatedRoute, Router } from '@angular/router'; import { RouterStub } from '../../testing/router-stub'; import { NO_ERRORS_SCHEMA } from '@angular/core'; @@ -11,7 +11,7 @@ let fixture: ComponentFixture; const queryParam = 'test query'; const scopeParam = '7669c72a-3f2a-451f-a3b9-9210e7a4c02f'; const activatedRouteStub = { - queryParams: Observable.of({ + queryParams: observableOf({ query: queryParam, scope: scopeParam }) diff --git a/src/app/shared/object-list/item-list-element/item-list-element.component.spec.ts b/src/app/shared/object-list/item-list-element/item-list-element.component.spec.ts index 1e77f56505..64108fd5b0 100644 --- a/src/app/shared/object-list/item-list-element/item-list-element.component.spec.ts +++ b/src/app/shared/object-list/item-list-element/item-list-element.component.spec.ts @@ -4,13 +4,13 @@ import { ChangeDetectionStrategy, NO_ERRORS_SCHEMA } from '@angular/core'; import { By } from '@angular/platform-browser'; import { TruncatePipe } from '../../utils/truncate.pipe'; import { Item } from '../../../core/shared/item.model'; -import { Observable } from 'rxjs'; +import { of as observableOf } from 'rxjs'; let itemListElementComponent: ItemListElementComponent; let fixture: ComponentFixture; const mockItemWithAuthorAndDate: Item = Object.assign(new Item(), { - bitstreams: Observable.of({}), + bitstreams: observableOf({}), metadata: [ { key: 'dc.contributor.author', @@ -24,7 +24,7 @@ const mockItemWithAuthorAndDate: Item = Object.assign(new Item(), { }] }); const mockItemWithoutAuthorAndDate: Item = Object.assign(new Item(), { - bitstreams: Observable.of({}), + bitstreams: observableOf({}), metadata: [ { key: 'dc.title', diff --git a/src/app/shared/object-list/search-result-list-element/collection-search-result/collection-search-result-list-element.component.spec.ts b/src/app/shared/object-list/search-result-list-element/collection-search-result/collection-search-result-list-element.component.spec.ts index fa73f8df3f..2ffaf38b53 100644 --- a/src/app/shared/object-list/search-result-list-element/collection-search-result/collection-search-result-list-element.component.spec.ts +++ b/src/app/shared/object-list/search-result-list-element/collection-search-result/collection-search-result-list-element.component.spec.ts @@ -1,6 +1,6 @@ import { CollectionSearchResultListElementComponent } from './collection-search-result-list-element.component'; import { async, ComponentFixture, TestBed } from '@angular/core/testing'; -import { Observable } from 'rxjs'; +import { of as observableOf } from 'rxjs'; import { ChangeDetectionStrategy, NO_ERRORS_SCHEMA } from '@angular/core'; import { By } from '@angular/platform-browser'; import { TruncatePipe } from '../../../utils/truncate.pipe'; @@ -12,7 +12,7 @@ let collectionSearchResultListElementComponent: CollectionSearchResultListElemen let fixture: ComponentFixture; const truncatableServiceStub: any = { - isCollapsed: (id: number) => Observable.of(true), + isCollapsed: (id: number) => observableOf(true), }; const mockCollectionWithAbstract: CollectionSearchResult = new CollectionSearchResult(); diff --git a/src/app/shared/object-list/search-result-list-element/community-search-result/community-search-result-list-element.component.spec.ts b/src/app/shared/object-list/search-result-list-element/community-search-result/community-search-result-list-element.component.spec.ts index 8551d7b908..70877d0744 100644 --- a/src/app/shared/object-list/search-result-list-element/community-search-result/community-search-result-list-element.component.spec.ts +++ b/src/app/shared/object-list/search-result-list-element/community-search-result/community-search-result-list-element.component.spec.ts @@ -1,6 +1,6 @@ import { CommunitySearchResultListElementComponent } from './community-search-result-list-element.component'; import { async, ComponentFixture, TestBed } from '@angular/core/testing'; -import { Observable } from 'rxjs'; +import { of as observableOf } from 'rxjs'; import { ChangeDetectionStrategy, NO_ERRORS_SCHEMA } from '@angular/core'; import { By } from '@angular/platform-browser'; import { TruncatePipe } from '../../../utils/truncate.pipe'; @@ -12,7 +12,7 @@ let communitySearchResultListElementComponent: CommunitySearchResultListElementC let fixture: ComponentFixture; const truncatableServiceStub: any = { - isCollapsed: (id: number) => Observable.of(true), + isCollapsed: (id: number) => observableOf(true), }; const mockCommunityWithAbstract: CommunitySearchResult = new CommunitySearchResult(); diff --git a/src/app/shared/object-list/search-result-list-element/item-search-result/item-search-result-list-element.component.spec.ts b/src/app/shared/object-list/search-result-list-element/item-search-result/item-search-result-list-element.component.spec.ts index 674620eef5..bdc8ebcecf 100644 --- a/src/app/shared/object-list/search-result-list-element/item-search-result/item-search-result-list-element.component.spec.ts +++ b/src/app/shared/object-list/search-result-list-element/item-search-result/item-search-result-list-element.component.spec.ts @@ -1,7 +1,7 @@ import { ItemSearchResultListElementComponent } from './item-search-result-list-element.component'; import { async, ComponentFixture, TestBed } from '@angular/core/testing'; -import { Observable } from 'rxjs'; -import { NO_ERRORS_SCHEMA, ChangeDetectionStrategy } from '@angular/core'; +import { of as observableOf } from 'rxjs'; +import { ChangeDetectionStrategy, NO_ERRORS_SCHEMA } from '@angular/core'; import { By } from '@angular/platform-browser'; import { TruncatePipe } from '../../../utils/truncate.pipe'; import { Item } from '../../../../core/shared/item.model'; @@ -13,13 +13,13 @@ let itemSearchResultListElementComponent: ItemSearchResultListElementComponent; let fixture: ComponentFixture; const truncatableServiceStub: any = { - isCollapsed: (id: number) => Observable.of(true), + isCollapsed: (id: number) => observableOf(true), }; const mockItemWithAuthorAndDate: ItemSearchResult = new ItemSearchResult(); mockItemWithAuthorAndDate.hitHighlights = []; mockItemWithAuthorAndDate.dspaceObject = Object.assign(new Item(), { - bitstreams: Observable.of({}), + bitstreams: observableOf({}), metadata: [ { key: 'dc.contributor.author', @@ -36,7 +36,7 @@ mockItemWithAuthorAndDate.dspaceObject = Object.assign(new Item(), { const mockItemWithoutAuthorAndDate: ItemSearchResult = new ItemSearchResult(); mockItemWithoutAuthorAndDate.hitHighlights = []; mockItemWithoutAuthorAndDate.dspaceObject = Object.assign(new Item(), { - bitstreams: Observable.of({}), + bitstreams: observableOf({}), metadata: [ { key: 'dc.title', diff --git a/src/app/shared/pagination/pagination.component.ts b/src/app/shared/pagination/pagination.component.ts index 0dc1892e47..0f2907a7bf 100644 --- a/src/app/shared/pagination/pagination.component.ts +++ b/src/app/shared/pagination/pagination.component.ts @@ -18,7 +18,6 @@ import { PaginationComponentOptions } from './pagination-component-options.model import { SortDirection, SortOptions } from '../../core/cache/models/sort-options.model'; import { hasValue, isNotEmpty } from '../empty.util'; import { PageInfo } from '../../core/shared/page-info.model'; -import { isNumeric } from 'tslint'; /** * The default pagination controls component. @@ -419,7 +418,7 @@ export class PaginationComponent implements OnDestroy, OnInit { */ private validatePage(page: any): number { let result = this.currentPage; - if (isNumeric(page)) { + if (!isNaN(page)) { result = +page; } return result; diff --git a/src/app/shared/services/route.service.spec.ts b/src/app/shared/services/route.service.spec.ts index 3d0f31573d..65109a2d28 100644 --- a/src/app/shared/services/route.service.spec.ts +++ b/src/app/shared/services/route.service.spec.ts @@ -1,7 +1,7 @@ import { RouteService } from './route.service'; import { async, TestBed } from '@angular/core/testing'; import { ActivatedRoute, convertToParamMap, Params } from '@angular/router'; -import { Observable } from 'rxjs'; +import { of as observableOf } from 'rxjs'; describe('RouteService', () => { let service: RouteService; @@ -24,8 +24,8 @@ describe('RouteService', () => { { provide: ActivatedRoute, useValue: { - queryParams: Observable.of(paramObject), - queryParamMap: Observable.of(convertToParamMap(paramObject)) + queryParams: observableOf(paramObject), + queryParamMap: observableOf(convertToParamMap(paramObject)) }, }, ] diff --git a/src/app/shared/services/route.service.ts b/src/app/shared/services/route.service.ts index 8565379007..d72367c977 100644 --- a/src/app/shared/services/route.service.ts +++ b/src/app/shared/services/route.service.ts @@ -1,5 +1,4 @@ - -import {distinctUntilChanged, map} from 'rxjs/operators'; +import { distinctUntilChanged, map } from 'rxjs/operators'; import { Injectable } from '@angular/core'; import { Observable } from 'rxjs'; import { @@ -15,32 +14,44 @@ export class RouteService { } getQueryParameterValues(paramName: string): Observable { - return this.route.queryParamMap.pipe(map((map) => [...map.getAll(paramName)]),distinctUntilChanged(),); + return this.route.queryParamMap.pipe( + map((params) => [...params.getAll(paramName)]), + distinctUntilChanged() + ); } getQueryParameterValue(paramName: string): Observable { - return this.route.queryParamMap.pipe(map((map) => map.get(paramName)),distinctUntilChanged(),); + return this.route.queryParamMap.pipe( + map((params) => params.get(paramName)), + distinctUntilChanged() + ); } hasQueryParam(paramName: string): Observable { - return this.route.queryParamMap.pipe(map((map) => map.has(paramName)),distinctUntilChanged(),); + return this.route.queryParamMap.pipe( + map((params) => params.has(paramName)), + distinctUntilChanged() + ); } hasQueryParamWithValue(paramName: string, paramValue: string): Observable { - return this.route.queryParamMap.pipe(map((map) => map.getAll(paramName).indexOf(paramValue) > -1),distinctUntilChanged(),); + return this.route.queryParamMap.pipe( + map((params) => params.getAll(paramName).indexOf(paramValue) > -1), + distinctUntilChanged() + ); } getQueryParamsWithPrefix(prefix: string): Observable { return this.route.queryParamMap.pipe( - map((map) => { - const params = {}; - map.keys - .filter((key) => key.startsWith(prefix)) - .forEach((key) => { - params[key] = [...map.getAll(key)]; - }); - return params; - }), + map((qparams) => { + const params = {}; + qparams.keys + .filter((key) => key.startsWith(prefix)) + .forEach((key) => { + params[key] = [...qparams.getAll(key)]; + }); + return params; + }), distinctUntilChanged((a, b) => JSON.stringify(a) === JSON.stringify(b)),); } } diff --git a/src/app/shared/truncatable/truncatable-part/truncatable-part.component.spec.ts b/src/app/shared/truncatable/truncatable-part/truncatable-part.component.spec.ts index bc9dc6dabf..ea6633056b 100644 --- a/src/app/shared/truncatable/truncatable-part/truncatable-part.component.spec.ts +++ b/src/app/shared/truncatable/truncatable-part/truncatable-part.component.spec.ts @@ -1,5 +1,5 @@ import { async, ComponentFixture, TestBed } from '@angular/core/testing'; -import { Observable } from 'rxjs'; +import { of as observableOf } from 'rxjs'; import { TruncatablePartComponent } from './truncatable-part.component'; import { TruncatableService } from '../truncatable.service'; import { ChangeDetectionStrategy, NO_ERRORS_SCHEMA } from '@angular/core'; @@ -15,9 +15,9 @@ describe('TruncatablePartComponent', () => { const truncatableServiceStub: any = { isCollapsed: (id: string) => { if (id === id1) { - return Observable.of(true) + return observableOf(true) } else { - return Observable.of(false); + return observableOf(false); } } }; diff --git a/src/app/shared/truncatable/truncatable.component.spec.ts b/src/app/shared/truncatable/truncatable.component.spec.ts index a9de30461e..d083c27d07 100644 --- a/src/app/shared/truncatable/truncatable.component.spec.ts +++ b/src/app/shared/truncatable/truncatable.component.spec.ts @@ -1,5 +1,5 @@ import { async, ComponentFixture, TestBed } from '@angular/core/testing'; -import { Observable } from 'rxjs'; +import { of as observableOf } from 'rxjs'; import { TruncatableComponent } from './truncatable.component'; import { TruncatableService } from './truncatable.service'; import { ChangeDetectionStrategy, NO_ERRORS_SCHEMA } from '@angular/core'; @@ -14,9 +14,9 @@ describe('TruncatableComponent', () => { /* tslint:disable:no-empty */ isCollapsed: (id: string) => { if (id === '1') { - return Observable.of(true) + return observableOf(true) } else { - return Observable.of(false); + return observableOf(false); } }, expand: (id: string) => { diff --git a/src/app/shared/truncatable/truncatable.service.spec.ts b/src/app/shared/truncatable/truncatable.service.spec.ts index 60982c9a4f..250cc4ba53 100644 --- a/src/app/shared/truncatable/truncatable.service.spec.ts +++ b/src/app/shared/truncatable/truncatable.service.spec.ts @@ -1,9 +1,9 @@ import { Store } from '@ngrx/store'; import { async, TestBed } from '@angular/core/testing'; -import { Observable } from 'rxjs'; import { TruncatableService } from './truncatable.service'; import { TruncatableCollapseAction, TruncatableExpandAction } from './truncatable.actions'; import { TruncatablesState } from './truncatable.reducer'; +import { of as observableOf } from 'rxjs'; describe('TruncatableService', () => { const id1 = '123'; @@ -13,7 +13,7 @@ describe('TruncatableService', () => { /* tslint:disable:no-empty */ dispatch: {}, /* tslint:enable:no-empty */ - select: Observable.of(true) + select: observableOf(true) }); beforeEach(async(() => { TestBed.configureTestingModule({ diff --git a/webpack.config.js b/webpack.config.js index c867ce48ea..47b36f8fb8 100644 --- a/webpack.config.js +++ b/webpack.config.js @@ -8,23 +8,23 @@ const { getAotPlugin } = require('./webpack/webpack.aot'); -module.exports = function(options) { - options = options || {}; - if (options.aot) { - console.log(`Running build for ${options.client ? 'client' : 'server'} with AoT Compilation`) +module.exports = function(env, options) { + env = env || {}; + if (env.aot) { + console.log(`Running build for ${env.client ? 'client' : 'server'} with AoT Compilation`) } - let serverPartial = getServerWebpackPartial(options.aot); + let serverPartial = getServerWebpackPartial(env.aot); let serverConfig = webpackMerge({}, commonPartial, serverPartial, { plugins: [ - getAotPlugin('server', !!options.aot) + getAotPlugin('server', !!env.aot) ] }); let clientConfig = webpackMerge({}, commonPartial, clientPartial, { plugins: [ - getAotPlugin('client', !!options.aot) + getAotPlugin('client', !!env.aot) ] }); @@ -35,13 +35,13 @@ module.exports = function(options) { const configs = []; - if (!options.aot) { + if (!env.aot) { configs.push(clientConfig, serverConfig); - } else if (options.client) { + } else if (env.client) { configs.push(clientConfig); - } else if (options.server) { + } else if (env.server) { configs.push(serverConfig); } return configs; -} +}; diff --git a/webpack/webpack.common.js b/webpack/webpack.common.js index d2ba6b8776..8d46668e71 100644 --- a/webpack/webpack.common.js +++ b/webpack/webpack.common.js @@ -1,104 +1,104 @@ const CopyWebpackPlugin = require('copy-webpack-plugin'); const { - root, - join + root, + join } = require('./helpers'); module.exports = { - mode: 'development', - devtool: 'source-map', - resolve: { - extensions: ['.ts', '.js', '.json'] - }, - output: { - path: root('dist') - }, - watchOptions: { - aggregateTimeout: 50, - }, - module: { - rules: [{ - test: /\.ts$/, - loader: '@ngtools/webpack' - }, - { - test: /\.css$/, - use: [{ - loader: 'to-string-loader', - options: { - sourceMap: true + mode: 'development', + devtool: 'source-map', + resolve: { + extensions: ['.ts', '.js', '.json'] + }, + output: { + path: root('dist') + }, + watchOptions: { + aggregateTimeout: 50, + }, + node: { + fs: "empty", + module: "empty" + }, + module: { + rules: [{ + test: /\.ts$/, + loader: '@ngtools/webpack' + }, + { + test: /\.css$/, + use: [{ + loader: 'to-string-loader', + options: { + sourceMap: true + } + }, + { + loader: 'css-loader', + options: { + sourceMap: true + } + }, + { + loader: 'postcss-loader', + options: { + sourceMap: true + } + } + ] + }, + { + test: /\.scss$/, + exclude: /node_modules/, + use: [{ + loader: 'to-string-loader', + options: { + sourceMap: true + } + }, { + loader: 'raw-loader', + options: { + sourceMap: true + } + }, + { + loader: 'postcss-loader', + options: { + sourceMap: true + } + }, + { + loader: 'resolve-url-loader', + options: { + sourceMap: true + } + }, + { + loader: 'sass-loader', + options: { + sourceMap: true + } + } + ] + }, + { + test: /\.html$/, + loader: 'raw-loader' } - }, - { - loader: 'css-loader', - options: { - sourceMap: true - } - }, - { - loader: 'postcss-loader', - options: { - sourceMap: true - } - } ] - }, - { - test: /\.scss$/, - exclude: /node_modules/, - use: [{ - loader: 'to-string-loader', - options: { - sourceMap: true - } - }, { - loader: 'raw-loader', - options: { - sourceMap: true - } - }, - { - loader: 'postcss-loader', - options: { - sourceMap: true - } - }, - { - loader: 'resolve-url-loader', - options: { - sourceMap: true - } - }, - { - loader: 'sass-loader', - options: { - sourceMap: true - } - } - ] - }, - { - test: /\.html$/, - loader: 'raw-loader' - }, - { - test: /\.json$/, - loader: 'json-loader' - } + }, + plugins: [ + new CopyWebpackPlugin([{ + from: join(__dirname, '..', 'node_modules', 'font-awesome', 'fonts'), + to: join('assets', 'fonts') + }, { + from: join(__dirname, '..', 'resources', 'images'), + to: join('assets', 'images') + }, { + from: join(__dirname, '..', 'resources', 'i18n'), + to: join('assets', 'i18n') + }]) ] - }, - plugins: [ - new CopyWebpackPlugin([{ - from: join(__dirname, '..', 'node_modules', 'font-awesome', 'fonts'), - to: join('assets', 'fonts') - }, { - from: join(__dirname, '..', 'resources', 'images'), - to: join('assets', 'images') - }, { - from: join(__dirname, '..', 'resources', 'i18n'), - to: join('assets', 'i18n') - }]) - ] }; diff --git a/webpack/webpack.prod.js b/webpack/webpack.prod.js index ab2c6a7585..30b279aa50 100644 --- a/webpack/webpack.prod.js +++ b/webpack/webpack.prod.js @@ -11,9 +11,11 @@ module.exports = { mode: 'production', recordsOutputPath: root('webpack.records.json'), plugins: [ - new webpack.DefinePlugin({ - 'process.env.NODE_ENV': JSON.stringify('production'), - 'process.env.AOT': true + new webpack.EnvironmentPlugin({ + 'process.env': { + 'NODE_ENV': JSON.stringify('production'), + 'AOT': true + } }), // Loader options diff --git a/webpack/webpack.test.js b/webpack/webpack.test.js index 210c33e66c..d635e8196b 100644 --- a/webpack/webpack.test.js +++ b/webpack/webpack.test.js @@ -178,17 +178,6 @@ module.exports = function (options) { exclude: [root('src/index.html')] }, - /** - * Json loader support for *.json files. - * - * See: https://github.com/webpack/json-loader - */ - { - test: /\.json$/, - loader: 'json-loader', - exclude: [root('src/index.html')] - }, - /** * Instruments JS files with Istanbul for subsequent code coverage reporting. * Instrument only testing sources. @@ -288,4 +277,4 @@ module.exports = function (options) { } }; -} +}; diff --git a/yarn.lock b/yarn.lock index 7e479f9404..4268851786 100644 --- a/yarn.lock +++ b/yarn.lock @@ -12,20 +12,20 @@ source-map "^0.5.6" "@angular/animations@^6.1.4": - version "6.1.4" - resolved "https://registry.yarnpkg.com/@angular/animations/-/animations-6.1.4.tgz#ca17acd62b9328404671a569fbf3065472527174" + version "6.1.6" + resolved "https://registry.yarnpkg.com/@angular/animations/-/animations-6.1.6.tgz#25a9cd87303aec5556c20631d087447de2330e87" dependencies: tslib "^1.9.0" "@angular/common@^6.1.4": - version "6.1.4" - resolved "https://registry.yarnpkg.com/@angular/common/-/common-6.1.4.tgz#825de5b1fb98db5a1d3d2253ad7181bb25477551" + version "6.1.6" + resolved "https://registry.yarnpkg.com/@angular/common/-/common-6.1.6.tgz#16597d89dddd72a606d3cc7125ffa30a87f5ee09" dependencies: tslib "^1.9.0" "@angular/compiler-cli@^6.1.4": - version "6.1.4" - resolved "https://registry.yarnpkg.com/@angular/compiler-cli/-/compiler-cli-6.1.4.tgz#65f4c4382bb180d22905db57e28a4ca728b7bf8c" + version "6.1.6" + resolved "https://registry.yarnpkg.com/@angular/compiler-cli/-/compiler-cli-6.1.6.tgz#cccebfaf66af3b7c19dd528732b945ce378bd65f" dependencies: chokidar "^1.4.2" minimist "^1.2.0" @@ -33,52 +33,52 @@ tsickle "^0.32.1" "@angular/compiler@^6.1.4": - version "6.1.4" - resolved "https://registry.yarnpkg.com/@angular/compiler/-/compiler-6.1.4.tgz#479e792ce012dc8481f1d87b919fcddb11c8eee0" + version "6.1.6" + resolved "https://registry.yarnpkg.com/@angular/compiler/-/compiler-6.1.6.tgz#2c858fe78ad1ca5bb3c886bd638bbb144af36e06" dependencies: tslib "^1.9.0" "@angular/core@^6.1.4": - version "6.1.4" - resolved "https://registry.yarnpkg.com/@angular/core/-/core-6.1.4.tgz#2602ecc031bbb4ad968a7db78786017e92d19b98" + version "6.1.6" + resolved "https://registry.yarnpkg.com/@angular/core/-/core-6.1.6.tgz#130758ad49cad5f6f075693f6496bbc7d510db3b" dependencies: tslib "^1.9.0" "@angular/forms@^6.1.4": - version "6.1.4" - resolved "https://registry.yarnpkg.com/@angular/forms/-/forms-6.1.4.tgz#d0b83f9cd4cb35f58ee67766d17aae0cbd7de561" + version "6.1.6" + resolved "https://registry.yarnpkg.com/@angular/forms/-/forms-6.1.6.tgz#1c4936993f2dbcee516cb547a534da3c70f84b76" dependencies: tslib "^1.9.0" "@angular/http@^6.1.4": - version "6.1.4" - resolved "https://registry.yarnpkg.com/@angular/http/-/http-6.1.4.tgz#0ab24a51075daaba60a4241200c44dcfcd87da5e" + version "6.1.6" + resolved "https://registry.yarnpkg.com/@angular/http/-/http-6.1.6.tgz#4e4b74a9746b14ebd5fd0071a5a3299e945ba2ad" dependencies: tslib "^1.9.0" "@angular/platform-browser-dynamic@^6.1.4": - version "6.1.4" - resolved "https://registry.yarnpkg.com/@angular/platform-browser-dynamic/-/platform-browser-dynamic-6.1.4.tgz#1af3549decadfb8e73513d917eaa5479184c39ea" + version "6.1.6" + resolved "https://registry.yarnpkg.com/@angular/platform-browser-dynamic/-/platform-browser-dynamic-6.1.6.tgz#49c2048d61b6d0958b2f0deb68cebe638b2f7f63" dependencies: tslib "^1.9.0" "@angular/platform-browser@^6.1.4": - version "6.1.4" - resolved "https://registry.yarnpkg.com/@angular/platform-browser/-/platform-browser-6.1.4.tgz#a5763f549f2073ba30b9d8baf8512c8076e8d58b" + version "6.1.6" + resolved "https://registry.yarnpkg.com/@angular/platform-browser/-/platform-browser-6.1.6.tgz#9a9498aa455978e974436000ddde8af9f64eef13" dependencies: tslib "^1.9.0" "@angular/platform-server@^6.1.4": - version "6.1.4" - resolved "https://registry.yarnpkg.com/@angular/platform-server/-/platform-server-6.1.4.tgz#df9fb37ad58605159f2aa1f777c6260491858c3f" + version "6.1.6" + resolved "https://registry.yarnpkg.com/@angular/platform-server/-/platform-server-6.1.6.tgz#a3c817421826bd1afa1a1bad9859bb3fa1fbf24c" dependencies: domino "^2.0.1" tslib "^1.9.0" xhr2 "^0.1.4" "@angular/router@^6.1.4": - version "6.1.4" - resolved "https://registry.yarnpkg.com/@angular/router/-/router-6.1.4.tgz#ec6d7400baea46386e3bbcf3e3acb0135f368fac" + version "6.1.6" + resolved "https://registry.yarnpkg.com/@angular/router/-/router-6.1.6.tgz#d280e014e5b4399d9631ac9cfd3dfde0cf3f76ed" dependencies: tslib "^1.9.0" @@ -86,6 +86,20 @@ version "1.0.1" resolved "https://registry.yarnpkg.com/@angularclass/bootloader/-/bootloader-1.0.1.tgz#75de7cf3901b445900a419c2aeca44181d465060" +"@babel/code-frame@^7.0.0": + version "7.0.0" + resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.0.0.tgz#06e2ab19bdb535385559aabb5ba59729482800f8" + dependencies: + "@babel/highlight" "^7.0.0" + +"@babel/highlight@^7.0.0": + version "7.0.0" + resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.0.0.tgz#f710c38c8d458e6dd9a201afb637fcb781ce99e4" + dependencies: + chalk "^2.0.0" + esutils "^2.0.2" + js-tokens "^4.0.0" + "@mrmlnc/readdir-enhanced@^2.2.1": version "2.2.1" resolved "https://registry.yarnpkg.com/@mrmlnc/readdir-enhanced/-/readdir-enhanced-2.2.1.tgz#524af240d1a360527b730475ecfa1344aa540dde" @@ -185,7 +199,7 @@ version "0.1.1" resolved "https://registry.yarnpkg.com/@types/deep-freeze/-/deep-freeze-0.1.1.tgz#0e1ee6ceee06f51baeb663deec0bb7780bd72827" -"@types/estree@*": +"@types/estree@*", "@types/estree@0.0.39": version "0.0.39" resolved "https://registry.yarnpkg.com/@types/estree/-/estree-0.0.39.tgz#e177e699ee1b8c22d23174caaa7422644389509f" @@ -193,7 +207,7 @@ version "1.2.0" resolved "https://registry.yarnpkg.com/@types/events/-/events-1.2.0.tgz#81a6731ce4df43619e5c8c945383b3e62a89ea86" -"@types/express-serve-static-core@*": +"@types/express-serve-static-core@*", "@types/express-serve-static-core@4.16.0": version "4.16.0" resolved "https://registry.yarnpkg.com/@types/express-serve-static-core/-/express-serve-static-core-4.16.0.tgz#fdfe777594ddc1fe8eb8eccce52e261b496e43e7" dependencies: @@ -201,13 +215,6 @@ "@types/node" "*" "@types/range-parser" "*" -"@types/express-serve-static-core@4.11.1": - version "4.11.1" - resolved "https://registry.yarnpkg.com/@types/express-serve-static-core/-/express-serve-static-core-4.11.1.tgz#f6f7212382d59b19d696677bcaa48a37280f5d45" - dependencies: - "@types/events" "*" - "@types/node" "*" - "@types/express@*", "@types/express@^4.11.1": version "4.16.0" resolved "https://registry.yarnpkg.com/@types/express/-/express-4.16.0.tgz#6d8bc42ccaa6f35cf29a2b7c3333cb47b5a32a19" @@ -267,17 +274,17 @@ resolved "https://registry.yarnpkg.com/@types/minimatch/-/minimatch-2.0.29.tgz#5002e14f75e2d71e564281df0431c8c1b4a2a36a" "@types/node@*": - version "10.9.2" - resolved "https://registry.yarnpkg.com/@types/node/-/node-10.9.2.tgz#f0ab8dced5cd6c56b26765e1c0d9e4fdcc9f2a00" + version "10.9.3" + resolved "https://registry.yarnpkg.com/@types/node/-/node-10.9.3.tgz#85f288502503ade0b3bfc049fe1777b05d0327d5" + +"@types/node@^10.9.4": + version "10.9.4" + resolved "https://registry.yarnpkg.com/@types/node/-/node-10.9.4.tgz#0f4cb2dc7c1de6096055357f70179043c33e9897" "@types/node@^6.0.46": version "6.0.116" resolved "https://registry.yarnpkg.com/@types/node/-/node-6.0.116.tgz#2f9cd62b4ecc4927e3942e2655c182eecf5b45f1" -"@types/node@^9.4.6": - version "9.6.30" - resolved "https://registry.yarnpkg.com/@types/node/-/node-9.6.30.tgz#1ecf83eaf7ac2d0dada7a9d61a1e4e7a6183ac06" - "@types/q@^0.0.32": version "0.0.32" resolved "https://registry.yarnpkg.com/@types/q/-/q-0.0.32.tgz#bd284e57c84f1325da702babfc82a5328190c0c5" @@ -290,20 +297,13 @@ version "3.0.10" resolved "https://registry.yarnpkg.com/@types/selenium-webdriver/-/selenium-webdriver-3.0.10.tgz#e98cc6f05b4b436277671c784ee2f9d05a634f9b" -"@types/serve-static@*": +"@types/serve-static@*", "@types/serve-static@1.13.2": version "1.13.2" resolved "https://registry.yarnpkg.com/@types/serve-static/-/serve-static-1.13.2.tgz#f5ac4d7a6420a99a6a45af4719f4dcd8cd907a48" dependencies: "@types/express-serve-static-core" "*" "@types/mime" "*" -"@types/serve-static@1.13.1": - version "1.13.1" - resolved "https://registry.yarnpkg.com/@types/serve-static/-/serve-static-1.13.1.tgz#1d2801fa635d274cd97d4ec07e26b21b44127492" - dependencies: - "@types/express-serve-static-core" "*" - "@types/mime" "*" - "@types/shelljs@0.7.0": version "0.7.0" resolved "https://registry.yarnpkg.com/@types/shelljs/-/shelljs-0.7.0.tgz#229c157c6bc1e67d6b990e6c5e18dbd2ff58cff0" @@ -323,8 +323,8 @@ resolved "https://registry.yarnpkg.com/@types/tapable/-/tapable-1.0.2.tgz#e13182e1b69871a422d7863e11a4a6f5b814a4bd" "@types/uuid@^3.4.3": - version "3.4.3" - resolved "https://registry.yarnpkg.com/@types/uuid/-/uuid-3.4.3.tgz#121ace265f5569ce40f4f6d0ff78a338c732a754" + version "3.4.4" + resolved "https://registry.yarnpkg.com/@types/uuid/-/uuid-3.4.4.tgz#7af69360fa65ef0decb41fd150bf4ca5c0cefdf5" dependencies: "@types/node" "*" @@ -468,31 +468,6 @@ "@webassemblyjs/wast-parser" "1.5.13" long "^3.2.0" -"@webpack-contrib/config-loader@^1.2.0": - version "1.2.1" - resolved "https://registry.yarnpkg.com/@webpack-contrib/config-loader/-/config-loader-1.2.1.tgz#5b3dd474e207437939d294d200c68b7b00008e04" - dependencies: - "@webpack-contrib/schema-utils" "^1.0.0-beta.0" - chalk "^2.1.0" - cosmiconfig "^5.0.2" - is-plain-obj "^1.1.0" - loud-rejection "^1.6.0" - merge-options "^1.0.1" - minimist "^1.2.0" - resolve "^1.6.0" - webpack-log "^1.1.2" - -"@webpack-contrib/schema-utils@^1.0.0-beta.0": - version "1.0.0-beta.0" - resolved "https://registry.yarnpkg.com/@webpack-contrib/schema-utils/-/schema-utils-1.0.0-beta.0.tgz#bf9638c9464d177b48209e84209e23bee2eb4f65" - dependencies: - ajv "^6.1.0" - ajv-keywords "^3.1.0" - chalk "^2.3.2" - strip-ansi "^4.0.0" - text-table "^0.2.0" - webpack-log "^1.1.2" - JSONStream@^1.0.3: version "1.3.4" resolved "https://registry.yarnpkg.com/JSONStream/-/JSONStream-1.3.4.tgz#615bb2adb0cd34c8f4c447b5f6512fa1d8f16a2e" @@ -529,11 +504,7 @@ acorn-node@^1.2.0, acorn-node@^1.3.0, acorn-node@^1.5.2: acorn-dynamic-import "^3.0.0" xtend "^4.0.1" -acorn@^4.0.1: - version "4.0.13" - resolved "https://registry.yarnpkg.com/acorn/-/acorn-4.0.13.tgz#105495ae5361d697bd195c825192e1ad7f253787" - -acorn@^5.0.0, acorn@^5.2.1, acorn@^5.3.0, acorn@^5.6.2, acorn@^5.7.1: +acorn@^5.0.0, acorn@^5.2.1, acorn@^5.3.0, acorn@^5.5.0, acorn@^5.6.2, acorn@^5.7.1: version "5.7.2" resolved "https://registry.yarnpkg.com/acorn/-/acorn-5.7.2.tgz#91fa871883485d06708800318404e72bfb26dcc5" @@ -543,7 +514,7 @@ addressparser@1.0.1: adjust-sourcemap-loader@^1.1.0: version "1.2.0" - resolved "https://registry.yarnpkg.com/adjust-sourcemap-loader/-/adjust-sourcemap-loader-1.2.0.tgz#e33fde95e50db9f2a802e3647e311d2fc5000c69" + resolved "http://registry.npmjs.org/adjust-sourcemap-loader/-/adjust-sourcemap-loader-1.2.0.tgz#e33fde95e50db9f2a802e3647e311d2fc5000c69" dependencies: assert "^1.3.0" camelcase "^1.2.1" @@ -567,6 +538,10 @@ agent-base@4, agent-base@^4.1.0, agent-base@^4.2.0, agent-base@~4.2.0: dependencies: es6-promisify "^5.0.0" +ajv-errors@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/ajv-errors/-/ajv-errors-1.0.0.tgz#ecf021fa108fd17dfb5e6b383f2dd233e31ffc59" + ajv-keywords@^3.1.0: version "3.2.0" resolved "https://registry.yarnpkg.com/ajv-keywords/-/ajv-keywords-3.2.0.tgz#e86b819c602cf8821ad637413698f1dec021847a" @@ -606,10 +581,6 @@ align-text@^0.1.1, align-text@^0.1.3: longest "^1.0.1" repeat-string "^1.5.2" -alphanum-sort@^1.0.1, alphanum-sort@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/alphanum-sort/-/alphanum-sort-1.0.2.tgz#97a1119649b211ad33691d9f9f486a8ec9fbe0a3" - amdefine@>=0.0.4, amdefine@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/amdefine/-/amdefine-1.0.1.tgz#4a5282ac164729e93619bcfd3ad151f817ce91f5" @@ -645,8 +616,8 @@ angular2-text-mask@9.0.0: text-mask-core "^5.0.0" angulartics2@^6.2.0: - version "6.2.0" - resolved "https://registry.yarnpkg.com/angulartics2/-/angulartics2-6.2.0.tgz#52eab311be74c9d055632e385988645c233a2c0f" + version "6.3.0" + resolved "https://registry.yarnpkg.com/angulartics2/-/angulartics2-6.3.0.tgz#85107238fe021e1e1e5cb492c5979aed829a1240" dependencies: tslib "^1.9.0" @@ -670,6 +641,10 @@ ansi-escapes@^1.1.0: version "1.4.0" resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-1.4.0.tgz#d3a8a83b319aa67793662b13e761c7911422306e" +ansi-escapes@^3.0.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-3.1.0.tgz#f73207bb81207d75fd6c83f125af26eea378ca30" + ansi-gray@^0.1.1: version "0.1.1" resolved "https://registry.yarnpkg.com/ansi-gray/-/ansi-gray-0.1.1.tgz#2962cf54ec9792c48510a3deb524436861ef7251" @@ -930,17 +905,6 @@ atob@^2.1.1: version "2.1.2" resolved "https://registry.yarnpkg.com/atob/-/atob-2.1.2.tgz#6d9517eb9e030d2436666651e86bd9f6f13533c9" -autoprefixer@^6.3.1: - version "6.7.7" - resolved "https://registry.yarnpkg.com/autoprefixer/-/autoprefixer-6.7.7.tgz#1dbd1c835658e35ce3f9984099db00585c782014" - dependencies: - browserslist "^1.7.6" - caniuse-db "^1.0.30000634" - normalize-range "^0.1.2" - num2fraction "^1.2.2" - postcss "^5.2.16" - postcss-value-parser "^3.2.3" - autoprefixer@^7.1.1: version "7.2.6" resolved "https://registry.yarnpkg.com/autoprefixer/-/autoprefixer-7.2.6.tgz#256672f86f7c735da849c4f07d008abb056067dc" @@ -952,29 +916,29 @@ autoprefixer@^7.1.1: postcss "^6.0.17" postcss-value-parser "^3.2.3" -autoprefixer@^8.0.0: - version "8.6.5" - resolved "https://registry.yarnpkg.com/autoprefixer/-/autoprefixer-8.6.5.tgz#343f3d193ed568b3208e00117a1b96eb691d4ee9" +autoprefixer@^9.1.3: + version "9.1.3" + resolved "https://registry.yarnpkg.com/autoprefixer/-/autoprefixer-9.1.3.tgz#bd5940ccb9d1bfa3508308659915f0a14394c8d5" dependencies: - browserslist "^3.2.8" - caniuse-lite "^1.0.30000864" + browserslist "^4.0.2" + caniuse-lite "^1.0.30000878" normalize-range "^0.1.2" num2fraction "^1.2.2" - postcss "^6.0.23" + postcss "^7.0.2" postcss-value-parser "^3.2.3" -awesome-typescript-loader@3.4.1: - version "3.4.1" - resolved "https://registry.yarnpkg.com/awesome-typescript-loader/-/awesome-typescript-loader-3.4.1.tgz#22fa49800f0619ec18ab15383aef93b95378dea9" +awesome-typescript-loader@5.2.0: + version "5.2.0" + resolved "https://registry.yarnpkg.com/awesome-typescript-loader/-/awesome-typescript-loader-5.2.0.tgz#d7bccf4823c45096ec24da4c12a1507d276ba15a" dependencies: - colors "^1.1.2" - enhanced-resolve "3.3.0" + chalk "^2.4.1" + enhanced-resolve "^4.0.0" loader-utils "^1.1.0" - lodash "^4.17.4" - micromatch "^3.0.3" + lodash "^4.17.5" + micromatch "^3.1.9" mkdirp "^0.5.1" - object-assign "^4.1.1" - source-map-support "^0.4.15" + source-map-support "^0.5.3" + webpack-log "^1.2.0" aws-sign2@~0.6.0: version "0.6.0" @@ -990,7 +954,7 @@ aws4@^1.2.1, aws4@^1.6.0, aws4@^1.8.0: axios@^0.15.3: version "0.15.3" - resolved "https://registry.yarnpkg.com/axios/-/axios-0.15.3.tgz#2c9d638b2e191a08ea1d6cc988eadd6ba5bdc053" + resolved "http://registry.npmjs.org/axios/-/axios-0.15.3.tgz#2c9d638b2e191a08ea1d6cc988eadd6ba5bdc053" dependencies: follow-redirects "1.0.0" @@ -1439,13 +1403,6 @@ browserify@^14.5.0: vm-browserify "~0.0.1" xtend "^4.0.0" -browserslist@^1.3.6, browserslist@^1.5.2, browserslist@^1.7.6: - version "1.7.7" - resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-1.7.7.tgz#0bd76704258be829b2398bb50e4b62d1a166b0b9" - dependencies: - caniuse-db "^1.0.30000639" - electron-to-chromium "^1.2.7" - browserslist@^2.0.0, browserslist@^2.11.3: version "2.11.3" resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-2.11.3.tgz#fe36167aed1bbcde4827ebfe71347a2cc70b99b2" @@ -1453,12 +1410,13 @@ browserslist@^2.0.0, browserslist@^2.11.3: caniuse-lite "^1.0.30000792" electron-to-chromium "^1.3.30" -browserslist@^3.2.8: - version "3.2.8" - resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-3.2.8.tgz#b0005361d6471f0f5952797a76fc985f1f978fc6" +browserslist@^4.0.2: + version "4.1.0" + resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.1.0.tgz#81cbb8e52dfa09918f93c6e051d779cb7360785d" dependencies: - caniuse-lite "^1.0.30000844" - electron-to-chromium "^1.3.47" + caniuse-lite "^1.0.30000878" + electron-to-chromium "^1.3.61" + node-releases "^1.0.0-alpha.11" browserstack@^1.5.1: version "1.5.1" @@ -1481,7 +1439,7 @@ buffer-crc32@^0.2.1: version "0.2.13" resolved "https://registry.yarnpkg.com/buffer-crc32/-/buffer-crc32-0.2.13.tgz#0d333e3f00eac50aa1454abd30ef8c2a5d9a7242" -buffer-es6@^4.9.1: +buffer-es6@^4.9.3: version "4.9.3" resolved "https://registry.yarnpkg.com/buffer-es6/-/buffer-es6-4.9.3.tgz#f26347b82df76fd37e18bcb5288c4970cfd5c404" @@ -1606,14 +1564,6 @@ camelcase-keys@^2.0.0: camelcase "^2.0.0" map-obj "^1.0.0" -camelcase-keys@^4.0.0: - version "4.2.0" - resolved "https://registry.yarnpkg.com/camelcase-keys/-/camelcase-keys-4.2.0.tgz#a2aa5fb1af688758259c32c141426d78923b9b77" - dependencies: - camelcase "^4.1.0" - map-obj "^2.0.0" - quick-lru "^1.0.0" - camelcase@^1.0.2, camelcase@^1.2.1: version "1.2.1" resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-1.2.1.tgz#9bb5304d2e0b56698b2c758b08a3eaa9daa58a39" @@ -1630,19 +1580,6 @@ camelcase@^4.0.0, camelcase@^4.1.0: version "4.1.0" resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-4.1.0.tgz#d545635be1e33c542649c69173e5de6acfae34dd" -camelcase@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-5.0.0.tgz#03295527d58bd3cd4aa75363f35b2e8d97be2f42" - -caniuse-api@^1.5.2: - version "1.6.1" - resolved "https://registry.yarnpkg.com/caniuse-api/-/caniuse-api-1.6.1.tgz#b534e7c734c4f81ec5fbe8aca2ad24354b962c6c" - dependencies: - browserslist "^1.3.6" - caniuse-db "^1.0.30000529" - lodash.memoize "^4.1.2" - lodash.uniq "^4.5.0" - caniuse-api@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/caniuse-api/-/caniuse-api-2.0.0.tgz#b1ddb5a5966b16f48dc4998444d4bbc6c7d9d834" @@ -1652,13 +1589,9 @@ caniuse-api@^2.0.0: lodash.memoize "^4.1.2" lodash.uniq "^4.5.0" -caniuse-db@^1.0.30000529, caniuse-db@^1.0.30000634, caniuse-db@^1.0.30000639: - version "1.0.30000878" - resolved "https://registry.yarnpkg.com/caniuse-db/-/caniuse-db-1.0.30000878.tgz#0d0c6d8500c3aea21441fad059bce4b8f3f509df" - -caniuse-lite@^1.0.0, caniuse-lite@^1.0.30000697, caniuse-lite@^1.0.30000792, caniuse-lite@^1.0.30000805, caniuse-lite@^1.0.30000844, caniuse-lite@^1.0.30000864: - version "1.0.30000878" - resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30000878.tgz#c644c39588dd42d3498e952234c372e5a40a4123" +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" capture-stack-trace@^1.0.0: version "1.0.0" @@ -1687,7 +1620,7 @@ cerialize@0.1.18: chalk@1.1.3, chalk@^1.0.0, chalk@^1.1.1, chalk@^1.1.3: version "1.1.3" - resolved "https://registry.yarnpkg.com/chalk/-/chalk-1.1.3.tgz#a8115c55e4a702fe4d150abd3872822a7e09fc98" + resolved "http://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz#a8115c55e4a702fe4d150abd3872822a7e09fc98" dependencies: ansi-styles "^2.2.1" escape-string-regexp "^1.0.2" @@ -1695,7 +1628,7 @@ chalk@1.1.3, chalk@^1.0.0, chalk@^1.1.1, chalk@^1.1.3: strip-ansi "^3.0.0" supports-color "^2.0.0" -chalk@^2.0.1, chalk@^2.1.0, chalk@^2.3.0, chalk@^2.3.1, chalk@^2.3.2, chalk@^2.4.1: +chalk@^2.0.0, chalk@^2.0.1, chalk@^2.1.0, chalk@^2.3.0, chalk@^2.4.1: version "2.4.1" resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.1.tgz#18c49ab16a037b6eb0152cc83e3471338215b66e" dependencies: @@ -1707,6 +1640,10 @@ chardet@^0.4.0: version "0.4.2" resolved "https://registry.yarnpkg.com/chardet/-/chardet-0.4.2.tgz#b5473b33dc97c424e5d98dc87d55d4d8a29c8bf2" +chardet@^0.7.0: + version "0.7.0" + resolved "https://registry.yarnpkg.com/chardet/-/chardet-0.7.0.tgz#90094849f0937f2eedc2425d0d28a9e5f0cbad9e" + charenc@~0.0.1: version "0.0.2" resolved "https://registry.yarnpkg.com/charenc/-/charenc-0.0.2.tgz#c0a1d2f3a7092e03774bfa83f14c0fc5790a8667" @@ -1774,12 +1711,6 @@ circular-json@^0.5.4: version "0.5.5" resolved "https://registry.yarnpkg.com/circular-json/-/circular-json-0.5.5.tgz#64182ef359042d37cd8e767fc9de878b1e9447d3" -clap@^1.0.9: - version "1.2.3" - resolved "https://registry.yarnpkg.com/clap/-/clap-1.2.3.tgz#4f36745b32008492557f46412d66d50cb99bce51" - dependencies: - chalk "^1.1.3" - class-utils@^0.3.5: version "0.3.6" resolved "https://registry.yarnpkg.com/class-utils/-/class-utils-0.3.6.tgz#f93369ae8b9a7ce02fd41faad0ca83033190c463" @@ -1805,10 +1736,6 @@ cli-cursor@^2.1.0: dependencies: restore-cursor "^2.0.0" -cli-spinners@^1.1.0: - version "1.3.1" - resolved "https://registry.yarnpkg.com/cli-spinners/-/cli-spinners-1.3.1.tgz#002c1990912d0d59580c93bd36c056de99e4259a" - cli-width@^2.0.0: version "2.2.0" resolved "https://registry.yarnpkg.com/cli-width/-/cli-width-2.2.0.tgz#ff19ede8a9a5e579324147b0c11f0fbcbabed639" @@ -1858,12 +1785,6 @@ co@^4.6.0: version "4.6.0" resolved "https://registry.yarnpkg.com/co/-/co-4.6.0.tgz#6ea6bdf3d853ae54ccb8e47bfa0bf3f9031fb184" -coa@~1.0.1: - version "1.0.4" - resolved "https://registry.yarnpkg.com/coa/-/coa-1.0.4.tgz#a9ef153660d6a86a8bdec0289a5c684d217432fd" - dependencies: - 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" @@ -1887,16 +1808,12 @@ collection-visit@^1.0.0: object-visit "^1.0.0" color-convert@^1.3.0, color-convert@^1.8.2, color-convert@^1.9.0, color-convert@^1.9.1: - version "1.9.2" - resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-1.9.2.tgz#49881b8fba67df12a96bdf3f56c0aab9e7913147" + version "1.9.3" + resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-1.9.3.tgz#bb71850690e1f136567de629d2d5471deda4c1e8" dependencies: - color-name "1.1.1" + color-name "1.1.3" -color-name@1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.1.tgz#4b1415304cf50028ea81643643bd82ea05803689" - -color-name@^1.0.0: +color-name@1.1.3, color-name@^1.0.0: version "1.1.3" resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.3.tgz#a7d0558bd89c42f795dd42328f740831ca53bc25" @@ -1939,23 +1856,15 @@ color@^2.0.1: color-convert "^1.9.1" color-string "^1.5.2" -colormin@^1.0.5: - version "1.1.2" - resolved "https://registry.yarnpkg.com/colormin/-/colormin-1.1.2.tgz#ea2f7420a72b96881a38aae59ec124a6f7298133" - dependencies: - color "^0.11.0" - css-color-names "0.0.4" - has "^1.0.1" - colors@1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/colors/-/colors-1.0.3.tgz#0433f44d809680fdeb60ed260f1b0c262e82a40b" -colors@1.1.2, colors@~1.1.2: +colors@1.1.2: version "1.1.2" resolved "https://registry.yarnpkg.com/colors/-/colors-1.1.2.tgz#168a4701756b6a7f51a12ce0c97bfa28c084ed63" -colors@^1.1.0, colors@^1.1.2: +colors@^1.1.0: version "1.3.2" resolved "https://registry.yarnpkg.com/colors/-/colors-1.3.2.tgz#2df8ff573dfbf255af562f8ce7181d6b971a359b" @@ -2020,8 +1929,8 @@ compressible@~2.0.11, compressible@~2.0.14: mime-db ">= 1.34.0 < 2" compression-webpack-plugin@^1.1.6: - version "1.1.11" - resolved "https://registry.yarnpkg.com/compression-webpack-plugin/-/compression-webpack-plugin-1.1.11.tgz#8384c7a6ead1d2e2efb190bdfcdcf35878ed8266" + version "1.1.12" + resolved "https://registry.yarnpkg.com/compression-webpack-plugin/-/compression-webpack-plugin-1.1.12.tgz#becd2aec620ace96bb3fe9a42a55cf48acc8b4d4" dependencies: cacache "^10.0.1" find-cache-dir "^1.0.0" @@ -2216,14 +2125,6 @@ cosmiconfig@^4.0.0: parse-json "^4.0.0" require-from-string "^2.0.1" -cosmiconfig@^5.0.2: - version "5.0.6" - resolved "https://registry.yarnpkg.com/cosmiconfig/-/cosmiconfig-5.0.6.tgz#dca6cf680a0bd03589aff684700858c81abeeb39" - dependencies: - is-directory "^0.3.1" - js-yaml "^3.9.0" - 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" @@ -2300,6 +2201,16 @@ cross-spawn@^5.0.1, cross-spawn@^5.1.0: shebang-command "^1.2.0" which "^1.2.9" +cross-spawn@^6.0.0, cross-spawn@^6.0.5: + version "6.0.5" + resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-6.0.5.tgz#4a5ec7c64dfae22c3a14124dbacdee846d80cbc4" + dependencies: + nice-try "^1.0.4" + path-key "^2.0.1" + semver "^5.5.0" + shebang-command "^1.2.0" + which "^1.2.9" + crypt@~0.0.1: version "0.0.2" resolved "https://registry.yarnpkg.com/crypt/-/crypt-0.0.2.tgz#88d7ff7ec0dfb86f713dc87bbb42d044d3e6c41b" @@ -2345,22 +2256,16 @@ css-color-function@~1.3.3: debug "^3.1.0" rgb "~0.1.0" -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" - -css-loader@0.28.9: - version "0.28.9" - resolved "https://registry.yarnpkg.com/css-loader/-/css-loader-0.28.9.tgz#68064b85f4e271d7ce4c48a58300928e535d1c95" +css-loader@1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/css-loader/-/css-loader-1.0.0.tgz#9f46aaa5ca41dbe31860e3b62b8e23c42916bf56" dependencies: babel-code-frame "^6.26.0" css-selector-tokenizer "^0.7.0" - cssnano "^3.10.0" icss-utils "^2.1.0" loader-utils "^1.0.2" lodash.camelcase "^4.3.0" - object-assign "^4.1.1" - postcss "^5.0.6" + postcss "^6.0.23" postcss-modules-extract-imports "^1.2.0" postcss-modules-local-by-default "^1.2.0" postcss-modules-scope "^1.1.0" @@ -2412,50 +2317,6 @@ cssesc@^0.1.0: version "0.1.0" resolved "https://registry.yarnpkg.com/cssesc/-/cssesc-0.1.0.tgz#c814903e45623371a0477b40109aaafbeeaddbb4" -cssnano@^3.10.0: - version "3.10.0" - resolved "https://registry.yarnpkg.com/cssnano/-/cssnano-3.10.0.tgz#4f38f6cea2b9b17fa01490f23f1dc68ea65c1c38" - dependencies: - autoprefixer "^6.3.1" - decamelize "^1.1.2" - defined "^1.0.0" - has "^1.0.1" - object-assign "^4.0.1" - postcss "^5.0.14" - postcss-calc "^5.2.0" - postcss-colormin "^2.1.8" - postcss-convert-values "^2.3.4" - postcss-discard-comments "^2.0.4" - postcss-discard-duplicates "^2.0.1" - postcss-discard-empty "^2.0.1" - postcss-discard-overridden "^0.1.1" - postcss-discard-unused "^2.2.1" - postcss-filter-plugins "^2.0.0" - postcss-merge-idents "^2.1.5" - postcss-merge-longhand "^2.0.1" - postcss-merge-rules "^2.0.3" - postcss-minify-font-values "^1.0.2" - postcss-minify-gradients "^1.0.1" - postcss-minify-params "^1.0.4" - postcss-minify-selectors "^2.0.4" - postcss-normalize-charset "^1.1.0" - postcss-normalize-url "^3.0.7" - postcss-ordered-values "^2.1.0" - postcss-reduce-idents "^2.2.2" - postcss-reduce-initial "^1.0.0" - postcss-reduce-transforms "^1.0.3" - postcss-svgo "^2.1.1" - postcss-unique-selectors "^2.0.2" - postcss-value-parser "^3.2.3" - postcss-zindex "^2.0.1" - -csso@~2.3.1: - version "2.3.2" - resolved "https://registry.yarnpkg.com/csso/-/csso-2.3.2.tgz#ddd52c587033f49e94b71fc55569f252e8ff5f85" - dependencies: - clap "^1.0.9" - source-map "^0.5.3" - currently-unhandled@^0.4.1: version "0.4.1" resolved "https://registry.yarnpkg.com/currently-unhandled/-/currently-unhandled-0.4.1.tgz#988df33feab191ef799a61369dd76c17adf957ea" @@ -2513,14 +2374,7 @@ debug@3.1.0, debug@^3.1.0, debug@~3.1.0: dependencies: ms "2.0.0" -decamelize-keys@^1.0.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/decamelize-keys/-/decamelize-keys-1.1.0.tgz#d171a87933252807eb3cb61dc1c1445d078df2d9" - dependencies: - decamelize "^1.1.0" - map-obj "^1.0.0" - -decamelize@^1.0.0, decamelize@^1.1.0, decamelize@^1.1.1, decamelize@^1.1.2: +decamelize@^1.0.0, decamelize@^1.1.1, decamelize@^1.1.2: version "1.2.0" resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-1.2.0.tgz#f6534d15148269b20352e7bee26f501f9a191290" @@ -2554,11 +2408,12 @@ deep-is@~0.1.3: version "0.1.3" resolved "https://registry.yarnpkg.com/deep-is/-/deep-is-0.1.3.tgz#b369d6fb5dbc13eecf524f91b070feedc357cf34" -defaults@^1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/defaults/-/defaults-1.0.3.tgz#c656051e9817d9ff08ed881477f3fe4019f3ef7d" +default-gateway@^2.6.0: + version "2.7.2" + resolved "https://registry.yarnpkg.com/default-gateway/-/default-gateway-2.7.2.tgz#b7ef339e5e024b045467af403d50348db4642d0f" dependencies: - clone "^1.0.2" + execa "^0.10.0" + ip-regex "^2.1.0" define-properties@^1.1.2: version "1.1.3" @@ -2829,8 +2684,8 @@ ecc-jsbn@~0.1.1: safer-buffer "^2.1.0" ecstatic@^3.0.0: - version "3.2.1" - resolved "https://registry.yarnpkg.com/ecstatic/-/ecstatic-3.2.1.tgz#1196a74d63d71d28dea807ed2b6183062671a206" + version "3.2.2" + resolved "https://registry.yarnpkg.com/ecstatic/-/ecstatic-3.2.2.tgz#4cc37c80ea88c021ca7cde66a15606ceaa9348e7" dependencies: he "^1.1.1" mime "^1.6.0" @@ -2845,9 +2700,9 @@ ejs@^2.5.7: version "2.6.1" resolved "https://registry.yarnpkg.com/ejs/-/ejs-2.6.1.tgz#498ec0d495655abc6f23cd61868d926464071aa0" -electron-to-chromium@^1.2.7, electron-to-chromium@^1.3.30, electron-to-chromium@^1.3.47: - version "1.3.61" - resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.61.tgz#a8ac295b28d0f03d85e37326fd16b6b6b17a1795" +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" elliptic@^6.0.0: version "6.4.1" @@ -2920,15 +2775,6 @@ engine.io@~3.1.0: optionalDependencies: uws "~9.14.0" -enhanced-resolve@3.3.0: - version "3.3.0" - resolved "https://registry.yarnpkg.com/enhanced-resolve/-/enhanced-resolve-3.3.0.tgz#950964ecc7f0332a42321b673b38dc8ff15535b3" - dependencies: - graceful-fs "^4.1.2" - memory-fs "^0.4.0" - object-assign "^4.0.1" - tapable "^0.2.5" - enhanced-resolve@^4.0.0, enhanced-resolve@^4.1.0: version "4.1.0" resolved "https://registry.yarnpkg.com/enhanced-resolve/-/enhanced-resolve-4.1.0.tgz#41c7e0bfdfe74ac1ffe1e57ad6a5c6c9f3742a7f" @@ -2957,7 +2803,7 @@ error-ex@^1.2.0, error-ex@^1.3.1: dependencies: is-arrayish "^0.2.1" -es-abstract@^1.4.3, es-abstract@^1.5.1, es-abstract@^1.6.1: +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" dependencies: @@ -3049,7 +2895,7 @@ eslint-scope@^4.0.0: esrecurse "^4.1.0" estraverse "^4.1.1" -esprima@2.7.x, esprima@^2.6.0, esprima@^2.7.1: +esprima@2.7.x, esprima@^2.7.1: version "2.7.3" resolved "https://registry.yarnpkg.com/esprima/-/esprima-2.7.3.tgz#96e3b70d5779f6ad49cd032673d1c312767ba581" @@ -3075,11 +2921,7 @@ estraverse@^4.1.0, estraverse@^4.1.1, estraverse@^4.2.0: version "4.2.0" resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-4.2.0.tgz#0dee3fed31fcd469618ce7342099fc1afa0bdb13" -estree-walker@^0.2.1: - version "0.2.1" - resolved "https://registry.yarnpkg.com/estree-walker/-/estree-walker-0.2.1.tgz#bdafe8095383d8414d5dc2ecf4c9173b6db9412e" - -estree-walker@^0.5.0, estree-walker@^0.5.2: +estree-walker@^0.5.1, estree-walker@^0.5.2: version "0.5.2" resolved "https://registry.yarnpkg.com/estree-walker/-/estree-walker-0.5.2.tgz#d3850be7529c9580d815600b53126515e146dd39" @@ -3124,6 +2966,18 @@ evp_bytestokey@^1.0.0, evp_bytestokey@^1.0.3: md5.js "^1.3.4" safe-buffer "^5.1.1" +execa@^0.10.0: + version "0.10.0" + resolved "https://registry.yarnpkg.com/execa/-/execa-0.10.0.tgz#ff456a8f53f90f8eccc71a96d11bdfc7f082cb50" + dependencies: + cross-spawn "^6.0.0" + get-stream "^3.0.0" + is-stream "^1.1.0" + npm-run-path "^2.0.0" + p-finally "^1.0.0" + signal-exit "^3.0.0" + strip-eof "^1.0.0" + execa@^0.7.0: version "0.7.0" resolved "https://registry.yarnpkg.com/execa/-/execa-0.7.0.tgz#944becd34cc41ee32a63a9faf27ad5a65fc59777" @@ -3301,6 +3155,14 @@ external-editor@^2.0.1: iconv-lite "^0.4.17" tmp "^0.0.33" +external-editor@^3.0.0: + version "3.0.3" + resolved "https://registry.yarnpkg.com/external-editor/-/external-editor-3.0.3.tgz#5866db29a97826dbe4bf3afd24070ead9ea43a27" + dependencies: + chardet "^0.7.0" + iconv-lite "^0.4.24" + tmp "^0.0.33" + extglob@^0.3.1: version "0.3.2" resolved "https://registry.yarnpkg.com/extglob/-/extglob-0.3.2.tgz#2e18ff3d2f49ab2765cec9023f011daa8d8349a1" @@ -3470,7 +3332,7 @@ find-up@^1.0.0: path-exists "^2.0.0" pinkie-promise "^2.0.0" -find-up@^2.0.0, find-up@^2.1.0: +find-up@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/find-up/-/find-up-2.1.0.tgz#45d1b7e506c717ddd482775a2b77920a3c0c57a7" dependencies: @@ -3658,7 +3520,7 @@ ftp@~0.3.10: readable-stream "1.1.x" xregexp "2.0.0" -function-bind@^1.0.2, function-bind@^1.1.0, function-bind@^1.1.1: +function-bind@^1.0.2, function-bind@^1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.1.tgz#a56899d3ea3c9bab874bb9773b7c5ede92f4895d" @@ -3783,6 +3645,10 @@ global-dirs@^0.1.0: dependencies: ini "^1.3.4" +global-modules-path@^2.1.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/global-modules-path/-/global-modules-path-2.3.0.tgz#b0e2bac6beac39745f7db5c59d26a36a0b94f7dc" + globals@^9.18.0: version "9.18.0" resolved "https://registry.yarnpkg.com/globals/-/globals-9.18.0.tgz#aa3896b3e69b487f17e31ed2143d69a8e30c2d8a" @@ -4108,10 +3974,6 @@ hpack.js@^2.1.6: readable-stream "^2.0.1" wbuf "^1.1.0" -html-comment-regex@^1.1.0: - version "1.1.1" - resolved "https://registry.yarnpkg.com/html-comment-regex/-/html-comment-regex-1.1.1.tgz#668b93776eaae55ebde8f3ad464b307a4963625e" - html-entities@^1.2.0: version "1.2.1" resolved "https://registry.yarnpkg.com/html-entities/-/html-entities-1.2.1.tgz#0df29351f0721163515dfb9e5543e5f6eed5162f" @@ -4188,7 +4050,7 @@ http-proxy-agent@^2.1.0: http-proxy-middleware@~0.18.0: version "0.18.0" - resolved "https://registry.yarnpkg.com/http-proxy-middleware/-/http-proxy-middleware-0.18.0.tgz#0987e6bb5a5606e5a69168d8f967a87f15dd8aab" + resolved "http://registry.npmjs.org/http-proxy-middleware/-/http-proxy-middleware-0.18.0.tgz#0987e6bb5a5606e5a69168d8f967a87f15dd8aab" dependencies: http-proxy "^1.16.2" is-glob "^4.0.0" @@ -4272,7 +4134,7 @@ iconv-lite@0.4.23: dependencies: safer-buffer ">= 2.1.2 < 3" -iconv-lite@^0.4.17, iconv-lite@^0.4.4, iconv-lite@~0.4.13: +iconv-lite@^0.4.17, iconv-lite@^0.4.24, iconv-lite@^0.4.4, iconv-lite@~0.4.13: version "0.4.24" resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.24.tgz#2022b4b25fbddc21d2f524974a474aafe733908b" dependencies: @@ -4337,12 +4199,12 @@ import-local@^1.0.0: pkg-dir "^2.0.0" resolve-cwd "^2.0.0" -imports-loader@0.7.1: - version "0.7.1" - resolved "https://registry.yarnpkg.com/imports-loader/-/imports-loader-0.7.1.tgz#f204b5f34702a32c1db7d48d89d5e867a0441253" +imports-loader@0.8.0: + version "0.8.0" + resolved "https://registry.yarnpkg.com/imports-loader/-/imports-loader-0.8.0.tgz#030ea51b8ca05977c40a3abfd9b4088fe0be9a69" dependencies: loader-utils "^1.0.2" - source-map "^0.5.6" + source-map "^0.6.1" imurmurhash@^0.1.4: version "0.1.4" @@ -4358,10 +4220,6 @@ indent-string@^2.1.0: dependencies: repeating "^2.0.0" -indent-string@^3.0.0: - version "3.2.0" - resolved "https://registry.yarnpkg.com/indent-string/-/indent-string-3.2.0.tgz#4a5fd6d27cc332f37e5419a504dbb837105c9289" - indexes-of@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/indexes-of/-/indexes-of-1.0.1.tgz#f30f716c8e2bd346c7b67d3df3915566a7c05607" @@ -4421,6 +4279,24 @@ inquirer@3.0.6: strip-ansi "^3.0.0" through "^2.3.6" +inquirer@^6.0.0: + version "6.2.0" + resolved "https://registry.yarnpkg.com/inquirer/-/inquirer-6.2.0.tgz#51adcd776f661369dc1e894859c2560a224abdd8" + dependencies: + ansi-escapes "^3.0.0" + chalk "^2.0.0" + cli-cursor "^2.1.0" + cli-width "^2.0.0" + external-editor "^3.0.0" + figures "^2.0.0" + lodash "^4.17.10" + mute-stream "0.0.7" + run-async "^2.2.0" + rxjs "^6.1.0" + string-width "^2.1.0" + strip-ansi "^4.0.0" + through "^2.3.6" + insert-module-globals@^7.0.0: version "7.2.0" resolved "https://registry.yarnpkg.com/insert-module-globals/-/insert-module-globals-7.2.0.tgz#ec87e5b42728479e327bd5c5c71611ddfb4752ba" @@ -4436,13 +4312,14 @@ insert-module-globals@^7.0.0: undeclared-identifiers "^1.1.2" xtend "^4.0.0" -internal-ip@1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/internal-ip/-/internal-ip-1.2.0.tgz#ae9fbf93b984878785d50a8de1b356956058cf5c" +internal-ip@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/internal-ip/-/internal-ip-3.0.1.tgz#df5c99876e1d2eb2ea2d74f520e3f669a00ece27" dependencies: - meow "^3.3.0" + default-gateway "^2.6.0" + ipaddr.js "^1.5.2" -interpret@^1.0.0: +interpret@^1.0.0, interpret@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/interpret/-/interpret-1.1.0.tgz#7ed1b1410c6a0e0f78cf95d3b8440c63f78b8614" @@ -4456,6 +4333,10 @@ invert-kv@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/invert-kv/-/invert-kv-1.0.0.tgz#104a8e4aaca6d3d8cd157a8ef8bfab2d7a3ffdb6" +ip-regex@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/ip-regex/-/ip-regex-2.1.0.tgz#fa78bf5d2e6913c911ce9f819ee5146bb6d844e9" + ip@^1.1.0, ip@^1.1.2, ip@^1.1.4, ip@^1.1.5: version "1.1.5" resolved "https://registry.yarnpkg.com/ip/-/ip-1.1.5.tgz#bdded70114290828c0a039e72ef25f5aaec4354a" @@ -4464,13 +4345,9 @@ ipaddr.js@1.8.0: version "1.8.0" resolved "https://registry.yarnpkg.com/ipaddr.js/-/ipaddr.js-1.8.0.tgz#eaa33d6ddd7ace8f7f6fe0c9ca0440e706738b1e" -irregular-plurals@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/irregular-plurals/-/irregular-plurals-2.0.0.tgz#39d40f05b00f656d0b7fa471230dd3b714af2872" - -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" +ipaddr.js@^1.5.2: + version "1.8.1" + resolved "https://registry.yarnpkg.com/ipaddr.js/-/ipaddr.js-1.8.1.tgz#fa4b79fa47fd3def5e3b159825161c0a519c9427" is-accessor-descriptor@^0.1.6: version "0.1.6" @@ -4685,10 +4562,6 @@ is-path-inside@^1.0.0: dependencies: path-is-inside "^1.0.1" -is-plain-obj@^1.0.0, is-plain-obj@^1.1, is-plain-obj@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/is-plain-obj/-/is-plain-obj-1.1.0.tgz#71a50c8429dfca773c92a390a4a03b39fcd51d3e" - is-plain-object@^2.0.1, is-plain-object@^2.0.3, is-plain-object@^2.0.4: version "2.0.4" resolved "https://registry.yarnpkg.com/is-plain-object/-/is-plain-object-2.0.4.tgz#2c163b3fafb1b606d9d17928f05c2a1c38e07677" @@ -4729,12 +4602,6 @@ 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@^2.0.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/is-svg/-/is-svg-2.1.0.tgz#cf61090da0d9efbcab8722deba6f032208dbb0e9" - 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" @@ -4881,15 +4748,21 @@ jasminewd2@^2.1.0: version "2.2.0" resolved "https://registry.yarnpkg.com/jasminewd2/-/jasminewd2-2.2.0.tgz#e37cf0b17f199cce23bea71b2039395246b4ec4e" -js-base64@^2.1.8, js-base64@^2.1.9: - version "2.4.8" - resolved "https://registry.yarnpkg.com/js-base64/-/js-base64-2.4.8.tgz#57a9b130888f956834aa40c5b165ba59c758f033" +jest-worker@^23.2.0: + version "23.2.0" + resolved "https://registry.yarnpkg.com/jest-worker/-/jest-worker-23.2.0.tgz#faf706a8da36fae60eb26957257fa7b5d8ea02b9" + dependencies: + merge-stream "^1.0.1" + +js-base64@^2.1.8: + version "2.4.9" + resolved "https://registry.yarnpkg.com/js-base64/-/js-base64-2.4.9.tgz#748911fb04f48a60c4771b375cac45a80df11c03" js-cookie@2.2.0: version "2.2.0" resolved "https://registry.yarnpkg.com/js-cookie/-/js-cookie-2.2.0.tgz#1b2c279a6eece380a12168b92485265b35b1effb" -"js-tokens@^3.0.0 || ^4.0.0": +"js-tokens@^3.0.0 || ^4.0.0", js-tokens@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499" @@ -4904,13 +4777,6 @@ js-yaml@3.x, js-yaml@^3.4.3, 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.7.0: - version "3.7.0" - resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.7.0.tgz#5c967ddd837a9bfdca5f2de84253abe8a1c03b80" - dependencies: - argparse "^1.0.7" - esprima "^2.6.0" - js.clone@0.0.3: version "0.0.3" resolved "https://registry.yarnpkg.com/js.clone/-/js.clone-0.0.3.tgz#f378d2bf501fcf648074fd91893f4718236bb79c" @@ -4927,10 +4793,6 @@ jsesc@~0.5.0: version "0.5.0" resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-0.5.0.tgz#e7dee66e35d6fc16f710fe91d5cf69f70f08911d" -json-loader@0.5.7: - version "0.5.7" - resolved "https://registry.yarnpkg.com/json-loader/-/json-loader-0.5.7.tgz#dca14a70235ff82f0ac9a3abeb60d337a365185d" - json-parse-better-errors@^1.0.1, json-parse-better-errors@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz#bb867cfb3450e69107c131d1c514bab3dc8bcaa9" @@ -5267,7 +5129,7 @@ loader-runner@^2.3.0: version "2.3.0" resolved "https://registry.yarnpkg.com/loader-runner/-/loader-runner-2.3.0.tgz#f482aea82d543e07921700d5a46ef26fdac6b8a2" -loader-utils@^0.2.15, loader-utils@^0.2.16, loader-utils@~0.2.2: +loader-utils@^0.2.15, loader-utils@^0.2.16: version "0.2.17" resolved "https://registry.yarnpkg.com/loader-utils/-/loader-utils-0.2.17.tgz#f86e6374d43205a6e6c60e9196f17c0299bfb348" dependencies: @@ -5474,13 +5336,13 @@ lodash@4.17.10, lodash@^4.0.0, lodash@^4.0.1, lodash@^4.13.1, lodash@^4.15.0, lo lodash@^3.8.0: version "3.10.1" - resolved "https://registry.yarnpkg.com/lodash/-/lodash-3.10.1.tgz#5bf45e8e49ba4189e17d482789dfd15bd140b7b6" + resolved "http://registry.npmjs.org/lodash/-/lodash-3.10.1.tgz#5bf45e8e49ba4189e17d482789dfd15bd140b7b6" log-driver@^1.2.5: version "1.2.7" resolved "https://registry.yarnpkg.com/log-driver/-/log-driver-1.2.7.tgz#63b95021f0702fedfa2c9bb0a24e7797d71871d8" -log-symbols@^2.0.0, log-symbols@^2.1.0, log-symbols@^2.2.0: +log-symbols@^2.0.0, log-symbols@^2.1.0: version "2.2.0" resolved "https://registry.yarnpkg.com/log-symbols/-/log-symbols-2.2.0.tgz#5740e1c5d6f0dfda4ad9323b5332107ef6b4c40a" dependencies: @@ -5564,12 +5426,6 @@ lru-cache@4.1.x, lru-cache@^4.0.1, lru-cache@^4.1.1, lru-cache@^4.1.2: pseudomap "^1.0.2" yallist "^2.1.2" -magic-string@^0.16.0: - version "0.16.0" - resolved "https://registry.yarnpkg.com/magic-string/-/magic-string-0.16.0.tgz#970ebb0da7193301285fb1aa650f39bdd81eb45a" - dependencies: - vlq "^0.2.1" - magic-string@^0.22.4: version "0.22.5" resolved "https://registry.yarnpkg.com/magic-string/-/magic-string-0.22.5.tgz#8e9cf5afddf44385c1da5bc2a6a0dbd10b03657e" @@ -5619,10 +5475,6 @@ map-obj@^1.0.0, map-obj@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/map-obj/-/map-obj-1.0.1.tgz#d933ceb9205d82bdcf4886f6742bdc2b4dea146d" -map-obj@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/map-obj/-/map-obj-2.0.0.tgz#a65cd29087a92598b8791257a523e021222ac1f9" - map-stream@~0.1.0: version "0.1.0" resolved "https://registry.yarnpkg.com/map-stream/-/map-stream-0.1.0.tgz#e56aa94c4c8055a16404a0674b78f215f7c8e194" @@ -5660,10 +5512,6 @@ md5@^2.2.1: crypt "~0.0.1" is-buffer "~1.1.1" -meant@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/meant/-/meant-1.0.1.tgz#66044fea2f23230ec806fb515efea29c44d2115d" - media-typer@0.3.0: version "0.3.0" resolved "https://registry.yarnpkg.com/media-typer/-/media-typer-0.3.0.tgz#8710d7af0aa626f8fffa1ce00168545263255748" @@ -5700,29 +5548,15 @@ meow@^3.3.0, meow@^3.7.0: redent "^1.0.0" trim-newlines "^1.0.0" -meow@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/meow/-/meow-5.0.0.tgz#dfc73d63a9afc714a5e371760eb5c88b91078aa4" - dependencies: - camelcase-keys "^4.0.0" - decamelize-keys "^1.0.0" - loud-rejection "^1.0.0" - minimist-options "^3.0.1" - normalize-package-data "^2.3.4" - read-pkg-up "^3.0.0" - redent "^2.0.0" - trim-newlines "^2.0.0" - yargs-parser "^10.0.0" - merge-descriptors@1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/merge-descriptors/-/merge-descriptors-1.0.1.tgz#b00aaa556dd8b44568150ec9d1b953f3f90cbb61" -merge-options@^1.0.0, merge-options@^1.0.1: +merge-stream@^1.0.1: version "1.0.1" - resolved "https://registry.yarnpkg.com/merge-options/-/merge-options-1.0.1.tgz#2a64b24457becd4e4dc608283247e94ce589aa32" + resolved "https://registry.yarnpkg.com/merge-stream/-/merge-stream-1.0.1.tgz#4041202d508a342ba00174008df0c251b8c135e1" dependencies: - is-plain-obj "^1.1" + readable-stream "^2.0.1" merge2@^1.2.1: version "1.2.2" @@ -5754,7 +5588,7 @@ micromatch@^2.1.5, micromatch@^2.3.11: parse-glob "^3.0.4" regex-cache "^0.4.2" -micromatch@^3.0.3, micromatch@^3.1.10, micromatch@^3.1.4, micromatch@^3.1.8, micromatch@^3.1.9: +micromatch@^3.1.10, micromatch@^3.1.4, micromatch@^3.1.8, micromatch@^3.1.9: version "3.1.10" resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-3.1.10.tgz#70859bc95c9840952f359a068a3fc49f9ecfac23" dependencies: @@ -5819,13 +5653,6 @@ minimalistic-crypto-utils@^1.0.0, minimalistic-crypto-utils@^1.0.1: dependencies: brace-expansion "^1.1.7" -minimist-options@^3.0.1: - version "3.0.2" - resolved "https://registry.yarnpkg.com/minimist-options/-/minimist-options-3.0.2.tgz#fba4c8191339e13ecf4d61beb03f070103f3d954" - dependencies: - arrify "^1.0.1" - is-plain-obj "^1.1.0" - minimist@0.0.8: version "0.0.8" resolved "https://registry.yarnpkg.com/minimist/-/minimist-0.0.8.tgz#857fcabfc3397d2625b8228262e86aa7a011b05d" @@ -5884,9 +5711,9 @@ 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.1, mkdirp@0.5.x, "mkdirp@>=0.5 0", mkdirp@^0.5.0, mkdirp@^0.5.1, mkdirp@~0.5.0: version "0.5.1" - resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.1.tgz#30057438eac6cf7f8c4767f38648d6697d75c903" + resolved "http://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz#30057438eac6cf7f8c4767f38648d6697d75c903" dependencies: minimist "0.0.8" @@ -6038,6 +5865,10 @@ ngx-pagination@3.0.3: version "3.0.3" resolved "https://registry.yarnpkg.com/ngx-pagination/-/ngx-pagination-3.0.3.tgz#314145263613738d8c544da36cd8dacc5aa89a6f" +nice-try@^1.0.4: + version "1.0.5" + resolved "https://registry.yarnpkg.com/nice-try/-/nice-try-1.0.5.tgz#a3378a7696ce7d223e88fc9b764bd7ef1089e366" + no-case@^2.2.0: version "2.3.2" resolved "https://registry.yarnpkg.com/no-case/-/no-case-2.3.2.tgz#60b813396be39b3f1288a4c1ed5d1e7d28b464ac" @@ -6046,7 +5877,7 @@ no-case@^2.2.0: node-fetch@1.6.3: version "1.6.3" - resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-1.6.3.tgz#dc234edd6489982d58e8f0db4f695029abcd8c04" + resolved "http://registry.npmjs.org/node-fetch/-/node-fetch-1.6.3.tgz#dc234edd6489982d58e8f0db4f695029abcd8c04" dependencies: encoding "^0.1.11" is-stream "^1.0.1" @@ -6115,6 +5946,12 @@ node-pre-gyp@^0.10.0: semver "^5.3.0" tar "^4" +node-releases@^1.0.0-alpha.11: + version "1.0.0-alpha.11" + resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-1.0.0-alpha.11.tgz#73c810acc2e5b741a17ddfbb39dfca9ab9359d8a" + dependencies: + semver "^5.3.0" + node-sass@^4.7.2: version "4.9.3" resolved "https://registry.yarnpkg.com/node-sass/-/node-sass-4.9.3.tgz#f407cf3d66f78308bb1e346b24fa428703196224" @@ -6193,8 +6030,8 @@ nodemailer@^2.5.0: socks "1.1.9" nodemon@^1.15.0: - version "1.18.3" - resolved "https://registry.yarnpkg.com/nodemon/-/nodemon-1.18.3.tgz#46e681ee0dd1b590562e03019b4c5df234f906f9" + version "1.18.4" + resolved "https://registry.yarnpkg.com/nodemon/-/nodemon-1.18.4.tgz#873f65fdb53220eb166180cf106b1354ac5d714d" dependencies: chokidar "^2.0.2" debug "^3.1.0" @@ -6245,15 +6082,6 @@ 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@^1.4.0: - version "1.9.1" - resolved "https://registry.yarnpkg.com/normalize-url/-/normalize-url-1.9.1.tgz#2cc0d66b31ea23036458436e3620d85954c66c3c" - dependencies: - object-assign "^4.0.1" - prepend-http "^1.0.0" - query-string "^4.1.0" - sort-keys "^1.0.0" - nouislider@^11.0.0: version "11.1.0" resolved "https://registry.yarnpkg.com/nouislider/-/nouislider-11.1.0.tgz#1768eb5b854917325d41b96f2dc4eb3757d73381" @@ -6387,15 +6215,6 @@ object.pick@^1.3.0: dependencies: isobject "^3.0.1" -object.values@^1.0.4: - version "1.0.4" - resolved "https://registry.yarnpkg.com/object.values/-/object.values-1.0.4.tgz#e524da09b4f66ff05df457546ec72ac99f13069a" - dependencies: - define-properties "^1.1.2" - es-abstract "^1.6.1" - function-bind "^1.1.0" - has "^1.0.1" - obuf@^1.0.0, obuf@^1.1.1: version "1.1.2" resolved "https://registry.yarnpkg.com/obuf/-/obuf-1.1.2.tgz#09bea3343d41859ebd446292d11c9d4db619084e" @@ -6438,8 +6257,8 @@ opencollective@^1.0.3: opn "4.0.2" opener@^1.4.3: - version "1.5.0" - resolved "https://registry.yarnpkg.com/opener/-/opener-1.5.0.tgz#24222fb4ad423ba21f5bf38855cebe44220f6531" + version "1.5.1" + resolved "https://registry.yarnpkg.com/opener/-/opener-1.5.1.tgz#6d2f0e77f1a0af0032aca716c2c1fbb8e7e8abed" opener@~1.4.0: version "1.4.3" @@ -6452,7 +6271,7 @@ opn@4.0.2: object-assign "^4.0.1" pinkie-promise "^2.0.0" -opn@^5.1.0, opn@^5.3.0: +opn@^5.1.0: version "5.3.0" resolved "https://registry.yarnpkg.com/opn/-/opn-5.3.0.tgz#64871565c863875f052cfdf53d3e3cb5adb53b1c" dependencies: @@ -6476,17 +6295,6 @@ optionator@^0.8.1: type-check "~0.3.2" wordwrap "~1.0.0" -ora@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/ora/-/ora-2.1.0.tgz#6caf2830eb924941861ec53a173799e008b51e5b" - dependencies: - chalk "^2.3.1" - cli-cursor "^2.1.0" - cli-spinners "^1.1.0" - log-symbols "^2.2.0" - strip-ansi "^4.0.0" - wcwidth "^1.0.1" - original@>=0.0.5: version "1.0.2" resolved "https://registry.yarnpkg.com/original/-/original-1.0.2.tgz#e442a61cffe1c5fd20a65f3261c26663b303f25f" @@ -6708,7 +6516,7 @@ path-is-inside@^1.0.1: version "1.0.2" resolved "https://registry.yarnpkg.com/path-is-inside/-/path-is-inside-1.0.2.tgz#365417dede44430d1c11af61027facf074bdfc53" -path-key@^2.0.0: +path-key@^2.0.0, path-key@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/path-key/-/path-key-2.0.1.tgz#411cadb574c5a140d3a4b1910d40d80cc9f40b40" @@ -6840,12 +6648,6 @@ plugin-error@^0.1.2: arr-union "^2.0.1" extend-shallow "^1.1.2" -plur@^3.0.0: - version "3.0.1" - resolved "https://registry.yarnpkg.com/plur/-/plur-3.0.1.tgz#268652d605f816699b42b86248de73c9acd06a7c" - dependencies: - irregular-plurals "^2.0.0" - portfinder@^1.0.13, portfinder@^1.0.9: version "1.0.17" resolved "https://registry.yarnpkg.com/portfinder/-/portfinder-1.0.17.tgz#a8a1691143e46c4735edefcf4fbcccedad26456a" @@ -6873,14 +6675,6 @@ postcss-attribute-case-insensitive@^2.0.0: postcss "^6.0.0" postcss-selector-parser "^2.2.3" -postcss-calc@^5.2.0: - version "5.3.1" - resolved "https://registry.yarnpkg.com/postcss-calc/-/postcss-calc-5.3.1.tgz#77bae7ca928ad85716e2fda42f261bf7c1d65b5e" - dependencies: - postcss "^5.0.2" - postcss-message-helpers "^2.0.0" - reduce-css-calc "^1.2.6" - postcss-calc@^6.0.0: version "6.0.1" resolved "https://registry.yarnpkg.com/postcss-calc/-/postcss-calc-6.0.1.tgz#3d24171bbf6e7629d422a436ebfe6dd9511f4330" @@ -6972,21 +6766,6 @@ postcss-color-rgba-fallback@^3.0.0: postcss-value-parser "^3.3.0" rgb-hex "^2.1.0" -postcss-colormin@^2.1.8: - version "2.2.2" - resolved "https://registry.yarnpkg.com/postcss-colormin/-/postcss-colormin-2.2.2.tgz#6631417d5f0e909a3d7ec26b24c8a8d1e4f96e4b" - dependencies: - colormin "^1.0.5" - postcss "^5.0.13" - postcss-value-parser "^3.2.3" - -postcss-convert-values@^2.3.4: - version "2.6.1" - resolved "https://registry.yarnpkg.com/postcss-convert-values/-/postcss-convert-values-2.6.1.tgz#bbd8593c5c1fd2e3d1c322bb925dcae8dae4d62d" - dependencies: - postcss "^5.0.11" - postcss-value-parser "^3.1.2" - postcss-cssnext@3.1.0: version "3.1.0" resolved "https://registry.yarnpkg.com/postcss-cssnext/-/postcss-cssnext-3.1.0.tgz#927dc29341a938254cde38ea60a923b9dfedead9" @@ -7043,43 +6822,6 @@ postcss-custom-selectors@^4.0.1: postcss "^6.0.1" postcss-selector-matches "^3.0.0" -postcss-discard-comments@^2.0.4: - version "2.0.4" - resolved "https://registry.yarnpkg.com/postcss-discard-comments/-/postcss-discard-comments-2.0.4.tgz#befe89fafd5b3dace5ccce51b76b81514be00e3d" - dependencies: - postcss "^5.0.14" - -postcss-discard-duplicates@^2.0.1: - version "2.1.0" - resolved "https://registry.yarnpkg.com/postcss-discard-duplicates/-/postcss-discard-duplicates-2.1.0.tgz#b9abf27b88ac188158a5eb12abcae20263b91932" - dependencies: - postcss "^5.0.4" - -postcss-discard-empty@^2.0.1: - version "2.1.0" - resolved "https://registry.yarnpkg.com/postcss-discard-empty/-/postcss-discard-empty-2.1.0.tgz#d2b4bd9d5ced5ebd8dcade7640c7d7cd7f4f92b5" - dependencies: - postcss "^5.0.14" - -postcss-discard-overridden@^0.1.1: - version "0.1.1" - resolved "https://registry.yarnpkg.com/postcss-discard-overridden/-/postcss-discard-overridden-0.1.1.tgz#8b1eaf554f686fb288cd874c55667b0aa3668d58" - dependencies: - postcss "^5.0.16" - -postcss-discard-unused@^2.2.1: - version "2.2.3" - resolved "https://registry.yarnpkg.com/postcss-discard-unused/-/postcss-discard-unused-2.2.3.tgz#bce30b2cc591ffc634322b5fb3464b6d934f4433" - dependencies: - postcss "^5.0.14" - uniqs "^2.0.0" - -postcss-filter-plugins@^2.0.0: - version "2.0.3" - resolved "https://registry.yarnpkg.com/postcss-filter-plugins/-/postcss-filter-plugins-2.0.3.tgz#82245fdf82337041645e477114d8e593aa18b8ec" - dependencies: - postcss "^5.0.4" - 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" @@ -7155,67 +6897,10 @@ 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-idents@^2.1.5: - version "2.1.7" - resolved "https://registry.yarnpkg.com/postcss-merge-idents/-/postcss-merge-idents-2.1.7.tgz#4c5530313c08e1d5b3bbf3d2bbc747e278eea270" - dependencies: - has "^1.0.1" - postcss "^5.0.10" - postcss-value-parser "^3.1.1" - -postcss-merge-longhand@^2.0.1: - version "2.0.2" - resolved "https://registry.yarnpkg.com/postcss-merge-longhand/-/postcss-merge-longhand-2.0.2.tgz#23d90cd127b0a77994915332739034a1a4f3d658" - dependencies: - postcss "^5.0.4" - -postcss-merge-rules@^2.0.3: - version "2.1.2" - resolved "https://registry.yarnpkg.com/postcss-merge-rules/-/postcss-merge-rules-2.1.2.tgz#d1df5dfaa7b1acc3be553f0e9e10e87c61b5f721" - dependencies: - browserslist "^1.5.2" - caniuse-api "^1.5.2" - postcss "^5.0.4" - postcss-selector-parser "^2.2.2" - 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@^1.0.2: - version "1.0.5" - resolved "https://registry.yarnpkg.com/postcss-minify-font-values/-/postcss-minify-font-values-1.0.5.tgz#4b58edb56641eba7c8474ab3526cafd7bbdecb69" - dependencies: - object-assign "^4.0.1" - postcss "^5.0.4" - postcss-value-parser "^3.0.2" - -postcss-minify-gradients@^1.0.1: - version "1.0.5" - resolved "https://registry.yarnpkg.com/postcss-minify-gradients/-/postcss-minify-gradients-1.0.5.tgz#5dbda11373703f83cfb4a3ea3881d8d75ff5e6e1" - dependencies: - postcss "^5.0.12" - postcss-value-parser "^3.3.0" - -postcss-minify-params@^1.0.4: - version "1.2.2" - resolved "https://registry.yarnpkg.com/postcss-minify-params/-/postcss-minify-params-1.2.2.tgz#ad2ce071373b943b3d930a3fa59a358c28d6f1f3" - dependencies: - alphanum-sort "^1.0.1" - postcss "^5.0.2" - postcss-value-parser "^3.0.2" - uniqs "^2.0.0" - -postcss-minify-selectors@^2.0.4: - version "2.1.1" - resolved "https://registry.yarnpkg.com/postcss-minify-selectors/-/postcss-minify-selectors-2.1.1.tgz#b2c6a98c0072cf91b932d1a496508114311735bf" - dependencies: - alphanum-sort "^1.0.2" - has "^1.0.1" - postcss "^5.0.14" - postcss-selector-parser "^2.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" @@ -7249,28 +6934,6 @@ postcss-nesting@^4.0.1: dependencies: postcss "^6.0.11" -postcss-normalize-charset@^1.1.0: - version "1.1.1" - resolved "https://registry.yarnpkg.com/postcss-normalize-charset/-/postcss-normalize-charset-1.1.1.tgz#ef9ee71212d7fe759c78ed162f61ed62b5cb93f1" - dependencies: - postcss "^5.0.5" - -postcss-normalize-url@^3.0.7: - version "3.0.8" - resolved "https://registry.yarnpkg.com/postcss-normalize-url/-/postcss-normalize-url-3.0.8.tgz#108f74b3f2fcdaf891a2ffa3ea4592279fc78222" - dependencies: - is-absolute-url "^2.0.0" - normalize-url "^1.4.0" - postcss "^5.0.14" - postcss-value-parser "^3.2.3" - -postcss-ordered-values@^2.1.0: - version "2.2.3" - resolved "https://registry.yarnpkg.com/postcss-ordered-values/-/postcss-ordered-values-2.2.3.tgz#eec6c2a67b6c412a8db2042e77fe8da43f95c11d" - dependencies: - postcss "^5.0.4" - postcss-value-parser "^3.0.1" - 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" @@ -7284,27 +6947,6 @@ postcss-pseudoelements@^5.0.0: dependencies: postcss "^6.0.0" -postcss-reduce-idents@^2.2.2: - version "2.4.0" - resolved "https://registry.yarnpkg.com/postcss-reduce-idents/-/postcss-reduce-idents-2.4.0.tgz#c2c6d20cc958284f6abfbe63f7609bf409059ad3" - dependencies: - postcss "^5.0.4" - postcss-value-parser "^3.0.2" - -postcss-reduce-initial@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/postcss-reduce-initial/-/postcss-reduce-initial-1.0.1.tgz#68f80695f045d08263a879ad240df8dd64f644ea" - dependencies: - postcss "^5.0.4" - -postcss-reduce-transforms@^1.0.3: - version "1.0.4" - resolved "https://registry.yarnpkg.com/postcss-reduce-transforms/-/postcss-reduce-transforms-1.0.4.tgz#ff76f4d8212437b31c298a42d2e1444025771ae1" - dependencies: - has "^1.0.1" - postcss "^5.0.8" - postcss-value-parser "^3.0.1" - 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" @@ -7353,7 +6995,7 @@ postcss-selector-not@^3.0.1: balanced-match "^0.4.2" postcss "^6.0.1" -postcss-selector-parser@^2.0.0, postcss-selector-parser@^2.2.2, postcss-selector-parser@^2.2.3: +postcss-selector-parser@^2.2.2, postcss-selector-parser@^2.2.3: version "2.2.3" resolved "https://registry.yarnpkg.com/postcss-selector-parser/-/postcss-selector-parser-2.2.3.tgz#f9437788606c3c9acee16ffe8d8b16297f27bb90" dependencies: @@ -7377,24 +7019,7 @@ postcss-smart-import@0.7.6: resolve "^1.5.0" sugarss "^1.0.1" -postcss-svgo@^2.1.1: - version "2.1.6" - resolved "https://registry.yarnpkg.com/postcss-svgo/-/postcss-svgo-2.1.6.tgz#b6df18aa613b666e133f08adb5219c2684ac108d" - dependencies: - is-svg "^2.0.0" - postcss "^5.0.14" - postcss-value-parser "^3.2.3" - svgo "^0.7.0" - -postcss-unique-selectors@^2.0.2: - version "2.0.2" - resolved "https://registry.yarnpkg.com/postcss-unique-selectors/-/postcss-unique-selectors-2.0.2.tgz#981d57d29ddcb33e7b1dfe1fd43b8649f933ca1d" - dependencies: - alphanum-sort "^1.0.1" - postcss "^5.0.4" - uniqs "^2.0.0" - -postcss-value-parser@^3.0.1, postcss-value-parser@^3.0.2, postcss-value-parser@^3.1.1, postcss-value-parser@^3.1.2, postcss-value-parser@^3.2.3, postcss-value-parser@^3.3.0: +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" @@ -7406,23 +7031,6 @@ postcss-values-parser@^1.5.0: indexes-of "^1.0.1" uniq "^1.0.1" -postcss-zindex@^2.0.1: - version "2.2.0" - resolved "https://registry.yarnpkg.com/postcss-zindex/-/postcss-zindex-2.2.0.tgz#d2109ddc055b91af67fc4cb3b025946639d2af22" - dependencies: - has "^1.0.1" - postcss "^5.0.4" - uniqs "^2.0.0" - -postcss@^5.0.10, postcss@^5.0.11, postcss@^5.0.12, postcss@^5.0.13, postcss@^5.0.14, postcss@^5.0.16, postcss@^5.0.2, postcss@^5.0.4, postcss@^5.0.5, postcss@^5.0.6, postcss@^5.0.8, postcss@^5.2.16: - version "5.2.18" - resolved "https://registry.yarnpkg.com/postcss/-/postcss-5.2.18.tgz#badfa1497d46244f6390f58b319830d9107853c5" - dependencies: - chalk "^1.1.3" - js-base64 "^2.1.9" - source-map "^0.5.6" - supports-color "^3.2.3" - postcss@^6.0, postcss@^6.0.0, postcss@^6.0.1, postcss@^6.0.11, postcss@^6.0.14, postcss@^6.0.17, postcss@^6.0.18, postcss@^6.0.22, postcss@^6.0.23, postcss@^6.0.5, postcss@^6.0.6, postcss@^6.0.8: version "6.0.23" resolved "https://registry.yarnpkg.com/postcss/-/postcss-6.0.23.tgz#61c82cc328ac60e677645f979054eb98bc0e3324" @@ -7431,11 +7039,19 @@ postcss@^6.0, postcss@^6.0.0, postcss@^6.0.1, postcss@^6.0.11, postcss@^6.0.14, source-map "^0.6.1" supports-color "^5.4.0" +postcss@^7.0.2: + version "7.0.2" + resolved "https://registry.yarnpkg.com/postcss/-/postcss-7.0.2.tgz#7b5a109de356804e27f95a960bef0e4d5bc9bb18" + dependencies: + chalk "^2.4.1" + source-map "^0.6.1" + supports-color "^5.4.0" + prelude-ls@~1.1.2: version "1.1.2" resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.1.2.tgz#21932a549f5e52ffd9a827f570e04be62a97da54" -prepend-http@^1.0.0, prepend-http@^1.0.1: +prepend-http@^1.0.1: version "1.0.4" resolved "https://registry.yarnpkg.com/prepend-http/-/prepend-http-1.0.4.tgz#d4f4562b0ce3696e41ac52d0e002e57a635dc6dc" @@ -7443,10 +7059,6 @@ preserve@^0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/preserve/-/preserve-0.2.0.tgz#815ed1f6ebc65926f865b310c0713bcb3315ce4b" -pretty-bytes@^5.0.0: - version "5.1.0" - resolved "https://registry.yarnpkg.com/pretty-bytes/-/pretty-bytes-5.1.0.tgz#6237ecfbdc6525beaef4de722cc60a58ae0e6c6d" - pretty-error@^2.0.2: version "2.1.1" resolved "https://registry.yarnpkg.com/pretty-error/-/pretty-error-2.1.1.tgz#5f4f87c8f91e5ae3f3ba87ab4cf5e03b1a17f1a3" @@ -7458,7 +7070,7 @@ pretty-hrtime@^1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/pretty-hrtime/-/pretty-hrtime-1.0.3.tgz#b7e3ea42435a4c9b2759d99e0f201eb195802ee1" -process-es6@^0.11.3: +process-es6@^0.11.6: version "0.11.6" resolved "https://registry.yarnpkg.com/process-es6/-/process-es6-0.11.6.tgz#c6bb389f9a951f82bd4eb169600105bd2ff9c778" @@ -7617,7 +7229,7 @@ q@1.4.1: version "1.4.1" resolved "https://registry.yarnpkg.com/q/-/q-1.4.1.tgz#55705bcd93c5f3673530c2c2cbc0c2b3addc286e" -q@^1.1.2, q@^1.4.1: +q@^1.4.1: version "1.5.1" resolved "https://registry.yarnpkg.com/q/-/q-1.5.1.tgz#7e32f75b41381291d04611f1bf14109ac00651d7" @@ -7641,13 +7253,6 @@ qs@~6.2.0: version "6.2.3" resolved "https://registry.yarnpkg.com/qs/-/qs-6.2.3.tgz#1cfcb25c10a9b2b483053ff39f5dfc9233908cfe" -query-string@^4.1.0: - version "4.3.4" - resolved "https://registry.yarnpkg.com/query-string/-/query-string-4.3.4.tgz#bbb693b9ca915c232515b228b1a02b609043dbeb" - dependencies: - object-assign "^4.1.0" - strict-uri-encode "^1.0.0" - querystring-es3@^0.2.0, querystring-es3@~0.2.0: version "0.2.1" resolved "https://registry.yarnpkg.com/querystring-es3/-/querystring-es3-0.2.1.tgz#9ec61f79049875707d69414596fd907a4d711e73" @@ -7660,10 +7265,6 @@ querystringify@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/querystringify/-/querystringify-2.0.0.tgz#fa3ed6e68eb15159457c89b37bc6472833195755" -quick-lru@^1.0.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/quick-lru/-/quick-lru-1.1.0.tgz#4360b17c61136ad38078397ff11416e186dcfbb8" - random-bytes@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/random-bytes/-/random-bytes-1.0.0.tgz#4f68a1dc0ae58bd3fb95848c30324db75d64360b" @@ -7743,13 +7344,6 @@ read-pkg-up@^1.0.1: find-up "^1.0.0" read-pkg "^1.0.0" -read-pkg-up@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/read-pkg-up/-/read-pkg-up-3.0.0.tgz#3ed496685dba0f8fe118d0691dc51f4a1ff96f07" - dependencies: - find-up "^2.0.0" - read-pkg "^3.0.0" - read-pkg@^1.0.0: version "1.1.0" resolved "https://registry.yarnpkg.com/read-pkg/-/read-pkg-1.1.0.tgz#f5ffaa5ecd29cb31c0474bca7d756b6bb29e3f28" @@ -7829,13 +7423,6 @@ redent@^1.0.0: indent-string "^2.1.0" strip-indent "^1.0.1" -redent@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/redent/-/redent-2.0.0.tgz#c1b2007b42d57eb1389079b3c8333639d5e1ccaa" - dependencies: - indent-string "^3.0.0" - strip-indent "^2.0.0" - redis-commands@^1.2.0: version "1.3.5" resolved "https://registry.yarnpkg.com/redis-commands/-/redis-commands-1.3.5.tgz#4495889414f1e886261180b1442e7295602d83a2" @@ -7852,7 +7439,7 @@ redis@^2.7.1: redis-commands "^1.2.0" redis-parser "^2.6.0" -reduce-css-calc@^1.2.6, reduce-css-calc@^1.2.7: +reduce-css-calc@^1.2.7: version "1.3.0" resolved "https://registry.yarnpkg.com/reduce-css-calc/-/reduce-css-calc-1.3.0.tgz#747c914e049614a4c9cfbba629871ad1d2927716" dependencies: @@ -8007,7 +7594,7 @@ request-progress@^2.0.1: request@2.75.x: version "2.75.0" - resolved "https://registry.yarnpkg.com/request/-/request-2.75.0.tgz#d2b8268a286da13eaa5d01adf5d18cc90f657d93" + resolved "http://registry.npmjs.org/request/-/request-2.75.0.tgz#d2b8268a286da13eaa5d01adf5d18cc90f657d93" dependencies: aws-sign2 "~0.6.0" aws4 "^1.2.1" @@ -8033,7 +7620,7 @@ request@2.75.x: request@2.85.0: version "2.85.0" - resolved "https://registry.yarnpkg.com/request/-/request-2.85.0.tgz#5a03615a47c61420b3eb99b7dba204f83603e1fa" + resolved "http://registry.npmjs.org/request/-/request-2.85.0.tgz#5a03615a47c61420b3eb99b7dba204f83603e1fa" dependencies: aws-sign2 "~0.7.0" aws4 "^1.6.0" @@ -8149,7 +7736,7 @@ resolve-from@^3.0.0: resolve-url-loader@^2.3.0: version "2.3.0" - resolved "https://registry.yarnpkg.com/resolve-url-loader/-/resolve-url-loader-2.3.0.tgz#e1b37034d48f22f8cfb9f04c026faaa070fdaf26" + resolved "http://registry.npmjs.org/resolve-url-loader/-/resolve-url-loader-2.3.0.tgz#e1b37034d48f22f8cfb9f04c026faaa070fdaf26" dependencies: adjust-sourcemap-loader "^1.1.0" camelcase "^4.1.0" @@ -8169,7 +7756,7 @@ resolve@1.1.7, resolve@1.1.x: version "1.1.7" resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.1.7.tgz#203114d82ad2c5ed9e8e0411b3932875e889e97b" -resolve@^1.1.3, resolve@^1.1.4, resolve@^1.1.6, resolve@^1.3.2, resolve@^1.4.0, resolve@^1.5.0, resolve@^1.6.0: +resolve@^1.1.3, resolve@^1.1.4, resolve@^1.1.6, resolve@^1.3.2, resolve@^1.5.0: version "1.8.1" resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.8.1.tgz#82f1ec19a423ac1fbd080b0bab06ba36e84a7a26" dependencies: @@ -8224,26 +7811,25 @@ ripemd160@^2.0.0, ripemd160@^2.0.1: hash-base "^3.0.0" inherits "^2.0.1" -rollup-plugin-commonjs@^8.3.0: - version "8.4.1" - resolved "https://registry.yarnpkg.com/rollup-plugin-commonjs/-/rollup-plugin-commonjs-8.4.1.tgz#5c9cea2b2c3de322f5fbccd147e07ed5e502d7a0" +rollup-plugin-commonjs@^9.1.6: + version "9.1.6" + resolved "https://registry.yarnpkg.com/rollup-plugin-commonjs/-/rollup-plugin-commonjs-9.1.6.tgz#ad553813c922b71467152794b98f2fd0f195b8a5" dependencies: - acorn "^5.2.1" - estree-walker "^0.5.0" + estree-walker "^0.5.1" magic-string "^0.22.4" - resolve "^1.4.0" + resolve "^1.5.0" rollup-pluginutils "^2.0.1" -rollup-plugin-node-globals@1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/rollup-plugin-node-globals/-/rollup-plugin-node-globals-1.1.0.tgz#7efd8d611d132737829e804e9f51f50962af451f" +rollup-plugin-node-globals@1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/rollup-plugin-node-globals/-/rollup-plugin-node-globals-1.2.1.tgz#2bd8309c19a0390b54cfac19a3bc13eabf3e5541" dependencies: - acorn "^4.0.1" - buffer-es6 "^4.9.1" - estree-walker "^0.2.1" - magic-string "^0.16.0" - process-es6 "^0.11.3" - rollup-pluginutils "^1.5.2" + acorn "^5.5.0" + buffer-es6 "^4.9.3" + estree-walker "^0.5.1" + magic-string "^0.22.4" + process-es6 "^0.11.6" + rollup-pluginutils "^2.0.1" rollup-plugin-node-resolve@^3.0.3: version "3.3.0" @@ -8253,18 +7839,13 @@ rollup-plugin-node-resolve@^3.0.3: is-module "^1.0.0" resolve "^1.1.6" -rollup-plugin-uglify@3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/rollup-plugin-uglify/-/rollup-plugin-uglify-3.0.0.tgz#a34eca24617709c6bf1778e9653baafa06099b86" +rollup-plugin-terser@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/rollup-plugin-terser/-/rollup-plugin-terser-2.0.2.tgz#1b59d67c80fc0d499cdc29a6991944b2d671ea03" dependencies: - uglify-es "^3.3.7" - -rollup-pluginutils@^1.5.2: - version "1.5.2" - resolved "https://registry.yarnpkg.com/rollup-pluginutils/-/rollup-pluginutils-1.5.2.tgz#1e156e778f94b7255bfa1b3d0178be8f5c552408" - dependencies: - estree-walker "^0.2.1" - minimatch "^3.0.2" + "@babel/code-frame" "^7.0.0" + jest-worker "^23.2.0" + terser "^3.8.2" rollup-pluginutils@^2.0.1: version "2.3.1" @@ -8273,9 +7854,12 @@ rollup-pluginutils@^2.0.1: estree-walker "^0.5.2" micromatch "^2.3.11" -rollup@^0.56.0: - version "0.56.5" - resolved "https://registry.yarnpkg.com/rollup/-/rollup-0.56.5.tgz#40fe3cf0cd1659d469baad11f4d5b6336c14ce84" +rollup@^0.65.0: + version "0.65.0" + resolved "https://registry.yarnpkg.com/rollup/-/rollup-0.65.0.tgz#280db1252169b68fc3043028346b337dde453fba" + dependencies: + "@types/estree" "0.0.39" + "@types/node" "*" run-async@^2.2.0: version "2.3.0" @@ -8299,6 +7883,12 @@ rxjs@^6.0.0, rxjs@^6.2.2: dependencies: tslib "^1.9.0" +rxjs@^6.1.0: + version "6.3.0" + resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-6.3.0.tgz#e55b05ad4bdf351db4b45756638dfa368260a8a3" + dependencies: + tslib "^1.9.0" + safe-buffer@5.1.1: version "5.1.1" resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.1.tgz#893312af69b2123def71f57889001671eeb2c853" @@ -8342,7 +7932,7 @@ saucelabs@^1.5.0: dependencies: https-proxy-agent "^2.2.1" -sax@>=0.6.0, sax@^1.2.4, sax@~1.2.1: +sax@>=0.6.0, sax@^1.2.4: version "1.2.4" resolved "https://registry.yarnpkg.com/sax/-/sax-1.2.4.tgz#2816234e2378bddc4e5354fab5caa895df7100d9" @@ -8359,6 +7949,14 @@ schema-utils@^0.4.0, schema-utils@^0.4.4, schema-utils@^0.4.5: ajv "^6.1.0" ajv-keywords "^3.1.0" +schema-utils@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/schema-utils/-/schema-utils-1.0.0.tgz#0b79a93204d7b600d4b2850d1f66c2a34951c770" + dependencies: + ajv "^6.1.0" + ajv-errors "^1.0.0" + ajv-keywords "^3.1.0" + script-ext-html-webpack-plugin@2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/script-ext-html-webpack-plugin/-/script-ext-html-webpack-plugin-2.0.1.tgz#90ac3d77f1892ad9054c3752f0e4673607f6d9a3" @@ -8741,12 +8339,6 @@ socks@~2.2.0: ip "^1.1.5" smart-buffer "^4.0.1" -sort-keys@^1.0.0: - version "1.1.2" - resolved "https://registry.yarnpkg.com/sort-keys/-/sort-keys-1.1.2.tgz#441b6d4d346798f1b4e49e8920adfba0e543f9ad" - dependencies: - is-plain-obj "^1.0.0" - sortablejs@1.7.0: version "1.7.0" resolved "https://registry.yarnpkg.com/sortablejs/-/sortablejs-1.7.0.tgz#80a2b2370abd568e1cec8c271131ef30a904fa28" @@ -8755,13 +8347,12 @@ source-list-map@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/source-list-map/-/source-list-map-2.0.0.tgz#aaa47403f7b245a92fbc97ea08f250d6087ed085" -source-map-loader@0.2.3: - version "0.2.3" - resolved "https://registry.yarnpkg.com/source-map-loader/-/source-map-loader-0.2.3.tgz#d4b0c8cd47d54edce3e6bfa0f523f452b5b0e521" +source-map-loader@0.2.4: + version "0.2.4" + resolved "https://registry.yarnpkg.com/source-map-loader/-/source-map-loader-0.2.4.tgz#c18b0dc6e23bf66f6792437557c569a11e072271" dependencies: async "^2.5.0" - loader-utils "~0.2.2" - source-map "~0.6.1" + loader-utils "^1.1.0" source-map-resolve@^0.5.0, source-map-resolve@^0.5.1: version "0.5.2" @@ -8773,19 +8364,19 @@ source-map-resolve@^0.5.0, source-map-resolve@^0.5.1: source-map-url "^0.4.0" urix "^0.1.0" -source-map-support@^0.4.15, source-map-support@~0.4.0: - version "0.4.18" - resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.4.18.tgz#0286a6de8be42641338594e97ccea75f0a2c585f" - dependencies: - source-map "^0.5.6" - -source-map-support@^0.5.0: +source-map-support@^0.5.0, source-map-support@^0.5.3, source-map-support@~0.5.6: version "0.5.9" resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.9.tgz#41bc953b2534267ea2d605bccfa7bfa3111ced5f" dependencies: buffer-from "^1.0.0" source-map "^0.6.0" +source-map-support@~0.4.0: + version "0.4.18" + resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.4.18.tgz#0286a6de8be42641338594e97ccea75f0a2c585f" + dependencies: + source-map "^0.5.6" + source-map-url@^0.4.0: version "0.4.0" resolved "https://registry.yarnpkg.com/source-map-url/-/source-map-url-0.4.0.tgz#3e935d7ddd73631b97659956d55128e87b5084a3" @@ -8794,9 +8385,9 @@ source-map@0.5.0: version "0.5.0" resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.5.0.tgz#0fe96503ac86a5adb5de63f4e412ae4872cdbe86" -source-map@0.6.1, source-map@^0.6.0, source-map@^0.6.1, source-map@~0.6.0, source-map@~0.6.1: - version "0.6.1" - resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263" +source-map@0.7.3: + version "0.7.3" + resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.7.3.tgz#5302f8169031735226544092e64981f751750383" source-map@^0.1.38: version "0.1.43" @@ -8810,10 +8401,14 @@ source-map@^0.4.2, source-map@^0.4.4: dependencies: amdefine ">=0.0.4" -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, source-map@~0.5.3: +source-map@^0.5.1, source-map@^0.5.6, source-map@^0.5.7, source-map@~0.5.1, source-map@~0.5.3: version "0.5.7" resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.5.7.tgz#8a039d2d1021d22d1ea14c80d8ea468ba2ef3fcc" +source-map@^0.6.0, source-map@^0.6.1, source-map@~0.6.0, source-map@~0.6.1: + version "0.6.1" + resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263" + source-map@~0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.2.0.tgz#dab73fbcfc2ba819b4de03bd6f6eaa48164b3f9d" @@ -8992,10 +8587,6 @@ streamroller@0.7.0: mkdirp "^0.5.1" readable-stream "^2.3.0" -strict-uri-encode@^1.0.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/strict-uri-encode/-/strict-uri-encode-1.1.0.tgz#279b225df1d582b1f54e65addd4352e18faa0713" - string-replace-loader@2.1.1: version "2.1.1" resolved "https://registry.yarnpkg.com/string-replace-loader/-/string-replace-loader-2.1.1.tgz#b72e7b57b6ef04efe615aff0ad989b5c14ca63d1" @@ -9011,7 +8602,7 @@ string-width@^1.0.1, string-width@^1.0.2: is-fullwidth-code-point "^1.0.0" strip-ansi "^3.0.0" -"string-width@^1.0.2 || 2", string-width@^2.0.0, string-width@^2.1.1: +"string-width@^1.0.2 || 2", string-width@^2.0.0, string-width@^2.1.0, string-width@^2.1.1: version "2.1.1" resolved "https://registry.yarnpkg.com/string-width/-/string-width-2.1.1.tgz#ab93f27a8dc13d28cac815c462143a6d9012ae9e" dependencies: @@ -9078,10 +8669,6 @@ strip-indent@^1.0.1: dependencies: get-stdin "^4.0.1" -strip-indent@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/strip-indent/-/strip-indent-2.0.0.tgz#5ef8db295d01e6ed6cbf7aab96998d7822527b68" - 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" @@ -9102,7 +8689,7 @@ supports-color@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-2.0.0.tgz#535d045ce6b6363fa40117084629995e9df324c7" -supports-color@^3.1.0, supports-color@^3.2.3: +supports-color@^3.1.0: version "3.2.3" resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-3.2.3.tgz#65ac0504b3954171d8a64946b2ae3cbb8a5f54f6" dependencies: @@ -9114,28 +8701,12 @@ supports-color@^5.1.0, supports-color@^5.2.0, supports-color@^5.3.0, supports-co dependencies: has-flag "^3.0.0" -svgo@^0.7.0: - version "0.7.2" - resolved "https://registry.yarnpkg.com/svgo/-/svgo-0.7.2.tgz#9f5772413952135c6fefbf40afe6a4faa88b4bb5" - dependencies: - coa "~1.0.1" - colors "~1.1.2" - csso "~2.3.1" - js-yaml "~3.7.0" - mkdirp "~0.5.1" - sax "~1.2.1" - whet.extend "~0.9.9" - syntax-error@^1.1.1: version "1.4.0" resolved "https://registry.yarnpkg.com/syntax-error/-/syntax-error-1.4.0.tgz#2d9d4ff5c064acb711594a3e3b95054ad51d907c" dependencies: acorn-node "^1.2.0" -tapable@^0.2.5: - version "0.2.8" - resolved "https://registry.yarnpkg.com/tapable/-/tapable-0.2.8.tgz#99372a5c999bf2df160afc0d74bed4f47948cd22" - tapable@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/tapable/-/tapable-1.0.0.tgz#cbb639d9002eed9c6b5975eb20598d7936f1f9f2" @@ -9178,6 +8749,14 @@ term-size@^1.2.0: dependencies: execa "^0.7.0" +terser@^3.8.2: + version "3.8.2" + resolved "https://registry.yarnpkg.com/terser/-/terser-3.8.2.tgz#48b880f949f8d038aca4dfd00a37c53d96ecf9fb" + dependencies: + commander "~2.17.1" + source-map "~0.6.1" + source-map-support "~0.5.6" + text-mask-core@5.0.1: version "5.0.1" resolved "https://registry.yarnpkg.com/text-mask-core/-/text-mask-core-5.0.1.tgz#86db742bdfe3b4c383bb51a3b4ca342c86110639" @@ -9186,10 +8765,6 @@ text-mask-core@^5.0.0: version "5.1.2" resolved "https://registry.yarnpkg.com/text-mask-core/-/text-mask-core-5.1.2.tgz#80dd5ebe04825757e46619e691407a9f8b3c1b6f" -text-table@^0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/text-table/-/text-table-0.2.0.tgz#7f5ee823ae805207c00af2df4a84ec3fcfa570b4" - throttleit@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/throttleit/-/throttleit-1.0.0.tgz#9e785836daf46743145a5984b6268d828528ac6c" @@ -9244,10 +8819,6 @@ timespan@2.3.x: version "2.3.0" resolved "https://registry.yarnpkg.com/timespan/-/timespan-2.3.0.tgz#4902ce040bd13d845c8f59b27e9d59bad6f39929" -titleize@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/titleize/-/titleize-1.0.1.tgz#21bc24fcca658eadc6d3bd3c38f2bd173769b4c5" - tmp@0.0.30: version "0.0.30" resolved "https://registry.yarnpkg.com/tmp/-/tmp-0.0.30.tgz#72419d4a8be7d6ce75148fd8b324e593a711c2ed" @@ -9331,10 +8902,6 @@ trim-newlines@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/trim-newlines/-/trim-newlines-1.0.0.tgz#5887966bb582a4503a41eb524f7d35011815a613" -trim-newlines@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/trim-newlines/-/trim-newlines-2.0.0.tgz#b403d0b91be50c331dfc4b82eeceb22c3de16d20" - trim-right@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/trim-right/-/trim-right-1.0.1.tgz#cb2e1203067e0c8de1f614094b9fe45704ea6003" @@ -9395,9 +8962,9 @@ tslib@^1.8.0, tslib@^1.8.1, tslib@^1.9.0: version "1.9.3" resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.9.3.tgz#d7e4dd79245d85428c4d7e4822a79917954ca286" -tslint@5.9.1: - version "5.9.1" - resolved "https://registry.yarnpkg.com/tslint/-/tslint-5.9.1.tgz#1255f87a3ff57eb0b0e1f0e610a8b4748046c9ae" +tslint@5.11.0: + version "5.11.0" + resolved "https://registry.yarnpkg.com/tslint/-/tslint-5.11.0.tgz#98f30c02eae3cde7006201e4c33cb08b48581eed" dependencies: babel-code-frame "^6.22.0" builtin-modules "^1.1.1" @@ -9410,13 +8977,13 @@ tslint@5.9.1: resolve "^1.3.2" semver "^5.3.0" tslib "^1.8.0" - tsutils "^2.12.1" + tsutils "^2.27.2" tsscmp@~1.0.0: version "1.0.6" resolved "https://registry.yarnpkg.com/tsscmp/-/tsscmp-1.0.6.tgz#85b99583ac3589ec4bfef825b5000aa911d605eb" -tsutils@^2.12.1: +tsutils@^2.27.2: version "2.29.0" resolved "https://registry.yarnpkg.com/tsutils/-/tsutils-2.29.0.tgz#32b488501467acbedd4b85498673a0812aca0b99" dependencies: @@ -9495,7 +9062,7 @@ typescript@^2.5.0, typescript@^2.9.1: version "2.9.2" resolved "https://registry.yarnpkg.com/typescript/-/typescript-2.9.2.tgz#1cbf61d05d6b96269244eb6a3bce4bd914e0f00c" -uglify-es@^3.3.4, uglify-es@^3.3.7: +uglify-es@^3.3.4: version "3.3.9" resolved "https://registry.yarnpkg.com/uglify-es/-/uglify-es-3.3.9.tgz#0c1c4f0700bed8dbc124cdb304d2592ca203e677" dependencies: @@ -9587,10 +9154,6 @@ 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" - unique-filename@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/unique-filename/-/unique-filename-1.1.0.tgz#d05f2fe4032560871f30e93cbe735eea201514f3" @@ -9785,10 +9348,6 @@ 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" - verror@1.10.0: version "1.10.0" resolved "https://registry.yarnpkg.com/verror/-/verror-1.10.0.tgz#3a105ca17053af55d6e270c1f8288682e18da400" @@ -9809,7 +9368,7 @@ vinyl@^0.5.0: clone-stats "^0.0.1" replace-ext "0.0.1" -vlq@^0.2.1, vlq@^0.2.2: +vlq@^0.2.2: version "0.2.3" resolved "https://registry.yarnpkg.com/vlq/-/vlq-0.2.3.tgz#8f3e4328cf63b1540c0d67e1b2778386f8975b26" @@ -9837,12 +9396,6 @@ wbuf@^1.1.0, wbuf@^1.7.2: dependencies: minimalistic-assert "^1.0.0" -wcwidth@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/wcwidth/-/wcwidth-1.0.1.tgz#f0b0dcf915bc5ff1528afadb2c0e17b532da2fe8" - dependencies: - defaults "^1.0.3" - wd@^1.0.0: version "1.10.3" resolved "https://registry.yarnpkg.com/wd/-/wd-1.10.3.tgz#395ac7eb58a98e556369f8f8e5f845d91fb152a3" @@ -9899,37 +9452,21 @@ webpack-bundle-analyzer@^2.13.1: opener "^1.4.3" ws "^4.0.0" -webpack-command@^0.4.1: - version "0.4.1" - resolved "https://registry.yarnpkg.com/webpack-command/-/webpack-command-0.4.1.tgz#3f88aae87c28292ed0a97293615a2e962a1c66f4" +webpack-cli@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/webpack-cli/-/webpack-cli-3.1.0.tgz#d71a83687dcfeb758fdceeb0fe042f96bcf62994" dependencies: - "@webpack-contrib/config-loader" "^1.2.0" - "@webpack-contrib/schema-utils" "^1.0.0-beta.0" - camelcase "^5.0.0" - chalk "^2.3.2" - debug "^3.1.0" - decamelize "^2.0.0" + chalk "^2.4.1" + cross-spawn "^6.0.5" enhanced-resolve "^4.0.0" + global-modules-path "^2.1.0" import-local "^1.0.0" - isobject "^3.0.1" + inquirer "^6.0.0" + interpret "^1.1.0" loader-utils "^1.1.0" - log-symbols "^2.2.0" - loud-rejection "^1.6.0" - meant "^1.0.1" - meow "^5.0.0" - merge-options "^1.0.0" - object.values "^1.0.4" - opn "^5.3.0" - ora "^2.1.0" - plur "^3.0.0" - pretty-bytes "^5.0.0" - strip-ansi "^4.0.0" - text-table "^0.2.0" - titleize "^1.0.1" - update-notifier "^2.3.0" + supports-color "^5.4.0" v8-compile-cache "^2.0.0" - webpack-log "^1.1.2" - wordwrap "^1.0.0" + yargs "^12.0.1" webpack-dev-middleware@3.2.0: version "3.2.0" @@ -9956,8 +9493,8 @@ webpack-dev-middleware@^2.0.6: webpack-log "^1.0.1" webpack-dev-server@^3.1.5: - version "3.1.6" - resolved "https://registry.yarnpkg.com/webpack-dev-server/-/webpack-dev-server-3.1.6.tgz#8617503768b1131fd539cf43c3e2e63bd34c1521" + version "3.1.7" + resolved "https://registry.yarnpkg.com/webpack-dev-server/-/webpack-dev-server-3.1.7.tgz#cbf8071cc092d9493732aee4f062f0e065994854" dependencies: ansi-html "0.0.7" bonjour "^3.5.0" @@ -9970,12 +9507,13 @@ webpack-dev-server@^3.1.5: html-entities "^1.2.0" http-proxy-middleware "~0.18.0" import-local "^1.0.0" - internal-ip "1.2.0" + internal-ip "^3.0.1" ip "^1.1.5" killable "^1.0.0" loglevel "^1.4.1" opn "^5.1.0" portfinder "^1.0.9" + schema-utils "^1.0.0" selfsigned "^1.9.1" serve-index "^1.7.2" sockjs "0.3.19" @@ -9987,7 +9525,7 @@ webpack-dev-server@^3.1.5: webpack-log "^2.0.0" yargs "12.0.1" -webpack-log@^1.0.1, webpack-log@^1.1.2: +webpack-log@^1.0.1, webpack-log@^1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/webpack-log/-/webpack-log-1.2.0.tgz#a4b34cda6b22b518dbb0ab32e567962d5c72a43d" dependencies: @@ -10014,8 +9552,8 @@ webpack-node-externals@1.7.2: resolved "https://registry.yarnpkg.com/webpack-node-externals/-/webpack-node-externals-1.7.2.tgz#6e1ee79ac67c070402ba700ef033a9b8d52ac4e3" webpack-sources@^1.0.1, webpack-sources@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/webpack-sources/-/webpack-sources-1.1.0.tgz#a101ebae59d6507354d71d8013950a3a8b7a5a54" + version "1.2.0" + resolved "https://registry.yarnpkg.com/webpack-sources/-/webpack-sources-1.2.0.tgz#18181e0d013fce096faf6f8e6d41eeffffdceac2" dependencies: source-list-map "^2.0.0" source-map "~0.6.1" @@ -10065,10 +9603,6 @@ when@^3.7.7: version "3.7.8" resolved "https://registry.yarnpkg.com/when/-/when-3.7.8.tgz#c7130b6a7ea04693e842cdc9e7a1f2aa39a39f82" -whet.extend@~0.9.9: - version "0.9.9" - resolved "https://registry.yarnpkg.com/whet.extend/-/whet.extend-0.9.9.tgz#f877d5bf648c97e5aa542fadc16d6a259b9c11a1" - which-module@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/which-module/-/which-module-1.0.0.tgz#bba63ca861948994ff307736089e3b96026c2a4f" @@ -10206,7 +9740,7 @@ yallist@^3.0.0, yallist@^3.0.2: version "3.0.2" resolved "https://registry.yarnpkg.com/yallist/-/yallist-3.0.2.tgz#8452b4bb7e83c7c188d8041c1a837c773d6d8bb9" -yargs-parser@^10.0.0, yargs-parser@^10.1.0: +yargs-parser@^10.1.0: version "10.1.0" resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-10.1.0.tgz#7202265b89f7e9e9f2e5765e0fe735a905edbaa8" dependencies: @@ -10224,7 +9758,7 @@ yargs-parser@^9.0.2: dependencies: camelcase "^4.1.0" -yargs@12.0.1: +yargs@12.0.1, yargs@^12.0.1: version "12.0.1" resolved "https://registry.yarnpkg.com/yargs/-/yargs-12.0.1.tgz#6432e56123bb4e7c3562115401e98374060261c2" dependencies: From 75a398547433ac8889db4005dd63c8dfcdec0d4f Mon Sep 17 00:00:00 2001 From: lotte Date: Fri, 31 Aug 2018 16:13:25 +0200 Subject: [PATCH 10/48] fixed production mode --- webpack.config.js | 3 +-- webpack/webpack.prod.js | 2 +- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/webpack.config.js b/webpack.config.js index 47b36f8fb8..8f02f3ce8a 100644 --- a/webpack.config.js +++ b/webpack.config.js @@ -27,8 +27,7 @@ module.exports = function(env, options) { getAotPlugin('client', !!env.aot) ] }); - - if (options.mode === 'production') { + if (env.production) { serverConfig = webpackMerge({}, serverConfig, prodPartial); clientConfig = webpackMerge({}, clientConfig, prodPartial); } diff --git a/webpack/webpack.prod.js b/webpack/webpack.prod.js index 30b279aa50..9b15b464e3 100644 --- a/webpack/webpack.prod.js +++ b/webpack/webpack.prod.js @@ -42,7 +42,7 @@ module.exports = { ], optimization: { - minimize: [ + minimizer: [ new UglifyJsPlugin({ uglifyOptions: { beautify: false, From 14f5c97ecc2f8aabaf85ba72f90e01e50e827a62 Mon Sep 17 00:00:00 2001 From: lotte Date: Thu, 6 Sep 2018 11:55:13 +0200 Subject: [PATCH 11/48] another intermediate commit --- angular.json | 13 + package.json | 35 +- .../+login-page/login-page.component.spec.ts | 1 - .../+search-page/search-options.model.spec.ts | 1 - .../search-sidebar.service.spec.ts | 3 +- src/app/core/auth/auth.service.spec.ts | 3 +- .../core/cache/object-cache.service.spec.ts | 31 +- .../core/cache/response-cache.service.spec.ts | 33 +- src/app/core/config/config.service.spec.ts | 4 +- src/app/core/config/config.service.ts | 30 +- src/app/core/data/comcol-data.service.ts | 49 +- src/app/core/data/request.service.spec.ts | 73 +- src/app/core/data/request.service.ts | 32 +- src/app/core/data/test.spec.ts | 37 + src/app/header/header.component.spec.ts | 14 +- src/app/shared/chips/chips.component.spec.ts | 1 - .../ds-dynamic-form-control.component.html | 424 +---- .../ds-dynamic-form-control.component.spec.ts | 184 +-- .../ds-dynamic-form-control.component.ts | 94 +- .../date-picker/date-picker.component.spec.ts | 9 +- .../date-picker/date-picker.component.ts | 21 +- .../dynamic-group.component.spec.ts | 261 ++-- .../dynamic-group/dynamic-group.components.ts | 26 +- .../list/dynamic-list.component.spec.ts | 11 +- .../models/list/dynamic-list.component.ts | 21 +- .../lookup/dynamic-lookup.component.spec.ts | 13 +- .../models/lookup/dynamic-lookup.component.ts | 15 +- ...amic-scrollable-dropdown.component.spec.ts | 9 +- .../dynamic-scrollable-dropdown.component.ts | 17 +- .../models/tag/dynamic-tag.component.spec.ts | 9 +- .../models/tag/dynamic-tag.component.ts | 15 +- .../dynamic-typeahead.component.spec.ts | 11 +- .../typeahead/dynamic-typeahead.component.ts | 14 +- .../form/builder/form-builder.service.spec.ts | 5 +- src/app/shared/form/form.component.spec.ts | 30 +- src/app/shared/form/form.reducer.ts | 2 + src/app/shared/form/form.service.spec.ts | 9 +- .../shared/mocks/mock-form-builder-service.ts | 18 + src/app/shared/mocks/mock-form-service.ts | 12 + src/app/shared/mocks/mock-store.ts | 15 +- .../notifications.service.spec.ts | 1 - .../number-picker.component.spec.ts | 1 - webpack/webpack.test.js | 2 +- yarn.lock | 1389 ++++------------- 44 files changed, 1004 insertions(+), 1994 deletions(-) create mode 100644 angular.json create mode 100644 src/app/core/data/test.spec.ts create mode 100644 src/app/shared/mocks/mock-form-builder-service.ts create mode 100644 src/app/shared/mocks/mock-form-service.ts diff --git a/angular.json b/angular.json new file mode 100644 index 0000000000..336738fd6e --- /dev/null +++ b/angular.json @@ -0,0 +1,13 @@ +{ + "$schema": "./node_modules/@angular/cli/lib/config/schema.json", + "version": 1, + "cli": { + "defaultCollection": "@ngrx/schematics" + }, + "projects": { + "core": { + "root": "", + "projectType": "application" + } + } +} \ No newline at end of file diff --git a/package.json b/package.json index 3ba25572b0..dca2420c62 100644 --- a/package.json +++ b/package.json @@ -41,14 +41,14 @@ "server:watch": "nodemon dist/server.js", "server:watch:debug": "nodemon --debug dist/server.js", "webpack:watch": "webpack -w --mode development", - "watch": "yarn run build && npm-run-all -p webpack:watch server:watch", - "watch:debug": "yarn run build && npm-run-all -p webpack:watch server:watch:debug", + "watch": "yarn run build && npm-run-all -p webpack:watch server:watch --mode development", + "watch:debug": "yarn run build && npm-run-all -p webpack:watch server:watch:debug --mode development", "predebug": "yarn run build", "predebug:server": "yarn run build", "debug": "node --debug-brk dist/server.js", "debug:server": "node-nightly --inspect --debug-brk dist/server.js", - "debug:build": "node-nightly --inspect --debug-brk node_modules/webpack/bin/webpack.js", - "debug:build:prod": "node-nightly --inspect --debug-brk node_modules/webpack/bin/webpack.js --env.aot --env.client --env.server -p", + "debug:build": "node-nightly --inspect --debug-brk node_modules/webpack/bin/webpack.js --mode development", + "debug:build:prod": "node-nightly --inspect --debug-brk node_modules/webpack/bin/webpack.js --env.aot --env.client --env.server --mode production", "ci": "yarn run lint && yarn run build:aot && yarn run test:headless && npm-run-all -p -r server e2e", "protractor": "node node_modules/protractor/bin/protractor", "pree2e": "yarn run webdriver:update", @@ -64,6 +64,7 @@ }, "dependencies": { "@angular/animations": "^6.1.4", + "@angular/cli": "^6.1.5", "@angular/common": "^6.1.4", "@angular/core": "^6.1.4", "@angular/forms": "^6.1.4", @@ -105,6 +106,7 @@ "methods": "1.1.2", "moment": "^2.22.1", "morgan": "1.9.0", + "ng-mocks": "^6.2.1", "ng2-file-upload": "1.2.1", "ng2-nouislider": "^1.7.11", "ngx-bootstrap": "^3.0.1", @@ -114,7 +116,7 @@ "nouislider": "^11.0.0", "pem": "1.12.3", "reflect-metadata": "0.1.12", - "rxjs": "^6.2.2", + "rxjs": "6.2.2", "sortablejs": "1.7.0", "text-mask-core": "5.0.1", "ts-md5": "^1.2.4", @@ -126,8 +128,11 @@ "devDependencies": { "@angular/compiler": "^6.1.4", "@angular/compiler-cli": "^6.1.4", + "@ngrx/entity": "^6.1.0", + "@ngrx/schematics": "^6.1.0", "@ngrx/store-devtools": "^6.1.0", "@ngtools/webpack": "^6.1.5", + "@schematics/angular": "^0.7.5", "@types/acorn": "^4.0.3", "@types/cookie-parser": "1.4.1", "@types/deep-freeze": "0.1.1", @@ -160,14 +165,14 @@ "imports-loader": "0.8.0", "istanbul-instrumenter-loader": "3.0.1", "jasmine-core": "^3.2.1", - "jasmine-marbles": "0.3.0", + "jasmine-marbles": "0.3.1", "jasmine-spec-reporter": "4.2.1", - "karma": "2.0.0", + "karma": "3.0.0", "karma-chrome-launcher": "2.2.0", "karma-cli": "1.0.1", - "karma-coverage": "1.1.1", + "karma-coverage": "1.1.2", "karma-istanbul-preprocessor": "0.0.2", - "karma-jasmine": "1.1.1", + "karma-jasmine": "1.1.2", "karma-mocha-reporter": "2.2.5", "karma-phantomjs-launcher": "1.0.4", "karma-remap-coverage": "^0.1.5", @@ -178,12 +183,12 @@ "ngrx-store-freeze": "^0.2.4", "node-sass": "^4.7.2", "nodemon": "^1.15.0", - "npm-run-all": "4.1.2", - "postcss": "^6.0.18", - "postcss-apply": "0.8.0", - "postcss-cli": "^5.0.0", + "npm-run-all": "4.1.3", + "postcss": "^7.0.2", + "postcss-apply": "0.11.0", + "postcss-cli": "^6.0.0", "postcss-cssnext": "3.1.0", - "postcss-loader": "^2.1.0", + "postcss-loader": "^3.0.0", "postcss-responsive-type": "1.0.0", "postcss-smart-import": "0.7.6", "protractor": "^5.3.0", @@ -196,7 +201,7 @@ "rollup-plugin-node-globals": "1.2.1", "rollup-plugin-node-resolve": "^3.0.3", "rollup-plugin-terser": "^2.0.2", - "sass-loader": "6.0.6", + "sass-loader": "7.1.0", "script-ext-html-webpack-plugin": "2.0.1", "source-map": "0.7.3", "source-map-loader": "0.2.4", diff --git a/src/app/+login-page/login-page.component.spec.ts b/src/app/+login-page/login-page.component.spec.ts index a0cb44d0d4..234435a410 100644 --- a/src/app/+login-page/login-page.component.spec.ts +++ b/src/app/+login-page/login-page.component.spec.ts @@ -4,7 +4,6 @@ import { async, ComponentFixture, TestBed } from '@angular/core/testing'; import { Store } from '@ngrx/store'; import { TranslateModule } from '@ngx-translate/core'; import { of as observableOf } from 'rxjs'; -import 'rxjs/add/observable/of'; import { LoginPageComponent } from './login-page.component'; diff --git a/src/app/+search-page/search-options.model.spec.ts b/src/app/+search-page/search-options.model.spec.ts index a624664637..a0ef2b31dd 100644 --- a/src/app/+search-page/search-options.model.spec.ts +++ b/src/app/+search-page/search-options.model.spec.ts @@ -1,4 +1,3 @@ -import 'rxjs/add/observable/of'; import { PaginatedSearchOptions } from './paginated-search-options.model'; import { SearchOptions } from './search-options.model'; import { SearchFilter } from './search-filter.model'; diff --git a/src/app/+search-page/search-sidebar/search-sidebar.service.spec.ts b/src/app/+search-page/search-sidebar/search-sidebar.service.spec.ts index 41d2bb2aaa..0cccf9ea40 100644 --- a/src/app/+search-page/search-sidebar/search-sidebar.service.spec.ts +++ b/src/app/+search-page/search-sidebar/search-sidebar.service.spec.ts @@ -3,7 +3,6 @@ import { SearchSidebarService } from './search-sidebar.service'; import { AppState } from '../../app.reducer'; import { async, TestBed } from '@angular/core/testing'; import { of as observableOf } from 'rxjs'; -import 'rxjs/add/observable/of'; import { SearchSidebarCollapseAction, SearchSidebarExpandAction } from './search-sidebar.actions'; import { HostWindowService } from '../../shared/host-window.service'; @@ -13,7 +12,7 @@ describe('SearchSidebarService', () => { /* tslint:disable:no-empty */ dispatch: {}, /* tslint:enable:no-empty */ - select: observableOf(true) + pipe: observableOf(true) }); const windowService = jasmine.createSpyObj('hostWindowService', { diff --git a/src/app/core/auth/auth.service.spec.ts b/src/app/core/auth/auth.service.spec.ts index 0b10f38e74..47110fd203 100644 --- a/src/app/core/auth/auth.service.spec.ts +++ b/src/app/core/auth/auth.service.spec.ts @@ -4,7 +4,6 @@ import { ActivatedRoute, Router } from '@angular/router'; import { Store, StoreModule } from '@ngrx/store'; import { REQUEST } from '@nguniversal/express-engine/tokens'; -import 'rxjs/add/observable/of'; import { of as observableOf } from 'rxjs'; import { authReducer, AuthState } from './auth.reducer'; @@ -27,7 +26,7 @@ describe('AuthService test', () => { const mockStore: Store = jasmine.createSpyObj('store', { dispatch: {}, - select: observableOf(true) + pipe: observableOf(true) }); let authService: AuthService; const authRequest = new AuthRequestServiceStub(); diff --git a/src/app/core/cache/object-cache.service.spec.ts b/src/app/core/cache/object-cache.service.spec.ts index 763d0c195f..38d51f09b3 100644 --- a/src/app/core/cache/object-cache.service.spec.ts +++ b/src/app/core/cache/object-cache.service.spec.ts @@ -7,6 +7,7 @@ import { CoreState } from '../core.reducers'; import { ResourceType } from '../shared/resource-type'; import { NormalizedItem } from './models/normalized-item.model'; import { first } from 'rxjs/operators'; +import * as ngrx from '@ngrx/store'; describe('ObjectCacheService', () => { let service: ObjectCacheService; @@ -52,7 +53,11 @@ describe('ObjectCacheService', () => { describe('getBySelfLink', () => { it('should return an observable of the cached object with the specified self link and type', () => { - spyOn(store, 'select').and.returnValue(observableOf(cacheEntry)); + spyOnProperty(ngrx, 'select').and.callFake(() => { + return () => { + return () => observableOf(cacheEntry); + }; + }); // due to the implementation of spyOn above, this subscribe will be synchronous service.getBySelfLink(selfLink).pipe(first()).subscribe((o) => { @@ -64,7 +69,11 @@ describe('ObjectCacheService', () => { }); it('should not return a cached object that has exceeded its time to live', () => { - spyOn(store, 'select').and.returnValue(observableOf(invalidCacheEntry)); + spyOnProperty(ngrx, 'select').and.callFake(() => { + return () => { + return () => observableOf(invalidCacheEntry); + }; + }); let getObsHasFired = false; const subscription = service.getBySelfLink(selfLink).subscribe((o) => getObsHasFired = true); @@ -88,19 +97,31 @@ describe('ObjectCacheService', () => { describe('has', () => { it('should return true if the object with the supplied self link is cached and still valid', () => { - spyOn(store, 'select').and.returnValue(observableOf(cacheEntry)); + spyOnProperty(ngrx, 'select').and.callFake(() => { + return () => { + return () => observableOf(cacheEntry); + }; + }); expect(service.hasBySelfLink(selfLink)).toBe(true); }); it("should return false if the object with the supplied self link isn't cached", () => { - spyOn(store, 'select').and.returnValue(observableOf(undefined)); + spyOnProperty(ngrx, 'select').and.callFake(() => { + return () => { + return () => observableOf(undefined); + }; + }); expect(service.hasBySelfLink(selfLink)).toBe(false); }); it('should return false if the object with the supplied self link is cached but has exceeded its time to live', () => { - spyOn(store, 'select').and.returnValue(observableOf(invalidCacheEntry)); + spyOnProperty(ngrx, 'select').and.callFake(() => { + return () => { + return () => observableOf(invalidCacheEntry); + }; + }); expect(service.hasBySelfLink(selfLink)).toBe(false); }); diff --git a/src/app/core/cache/response-cache.service.spec.ts b/src/app/core/cache/response-cache.service.spec.ts index 9063fbf5a6..4fcd926343 100644 --- a/src/app/core/cache/response-cache.service.spec.ts +++ b/src/app/core/cache/response-cache.service.spec.ts @@ -6,6 +6,8 @@ import { CoreState } from '../core.reducers'; import { RestResponse } from './response-cache.models'; import { ResponseCacheEntry } from './response-cache.reducer'; import { first } from 'rxjs/operators'; +import * as ngrx from '@ngrx/store' +import { cold } from 'jasmine-marbles'; describe('ResponseCacheService', () => { let service: ResponseCacheService; @@ -41,10 +43,11 @@ describe('ResponseCacheService', () => { describe('get', () => { it('should return an observable of the cached request with the specified key', () => { - spyOn(store, 'select').and.callFake((...args: any[]) => { - return observableOf(validCacheEntry(keys[1])); + spyOnProperty(ngrx, 'select').and.callFake(() => { + return () => { + return () => observableOf(validCacheEntry(keys[1])); + }; }); - let testObj: ResponseCacheEntry; service.get(keys[1]).pipe(first()).subscribe((entry) => { testObj = entry; @@ -53,8 +56,10 @@ describe('ResponseCacheService', () => { }); it('should not return a cached request that has exceeded its time to live', () => { - spyOn(store, 'select').and.callFake((...args: any[]) => { - return observableOf(invalidCacheEntry(keys[1])); + spyOnProperty(ngrx, 'select').and.callFake(() => { + return () => { + return () => observableOf(invalidCacheEntry(keys[1])); + }; }); let getObsHasFired = false; @@ -66,17 +71,29 @@ describe('ResponseCacheService', () => { describe('has', () => { it('should return true if the request with the supplied key is cached and still valid', () => { - spyOn(store, 'select').and.returnValue(observableOf(validCacheEntry(keys[1]))); + spyOnProperty(ngrx, 'select').and.callFake(() => { + return () => { + return () => observableOf(validCacheEntry(keys[1])); + }; + }); expect(service.has(keys[1])).toBe(true); }); it('should return false if the request with the supplied key isn\'t cached', () => { - spyOn(store, 'select').and.returnValue(observableOf(undefined)); + spyOnProperty(ngrx, 'select').and.callFake(() => { + return () => { + return () => observableOf(undefined); + }; + }); expect(service.has(keys[1])).toBe(false); }); it('should return false if the request with the supplied key is cached but has exceeded its time to live', () => { - spyOn(store, 'select').and.returnValue(observableOf(invalidCacheEntry(keys[1]))); + spyOnProperty(ngrx, 'select').and.callFake(() => { + return () => { + return () => observableOf(invalidCacheEntry(keys[1])); + }; + }); expect(service.has(keys[1])).toBe(false); }); }); diff --git a/src/app/core/config/config.service.spec.ts b/src/app/core/config/config.service.spec.ts index 2cf00713c2..46c8fd1859 100644 --- a/src/app/core/config/config.service.spec.ts +++ b/src/app/core/config/config.service.spec.ts @@ -56,11 +56,11 @@ describe('ConfigService', () => { } beforeEach(() => { + scheduler = getTestScheduler(); responseCache = initMockResponseCacheService(true); requestService = getMockRequestService(); - service = initTestService(); - scheduler = getTestScheduler(); halService = new HALEndpointServiceStub(configEndpoint); + service = initTestService(); }); describe('getConfigByHref', () => { diff --git a/src/app/core/config/config.service.ts b/src/app/core/config/config.service.ts index 2199deedcf..872bc57c2b 100644 --- a/src/app/core/config/config.service.ts +++ b/src/app/core/config/config.service.ts @@ -1,4 +1,4 @@ -import { Observable, of as observableOf, throwError as observableThrowError } from 'rxjs'; +import { Observable, of as observableOf, throwError as observableThrowError, merge as observableMerge } from 'rxjs'; import { distinctUntilChanged, filter, map, mergeMap, tap } from 'rxjs/operators'; import { RequestService } from '../data/request.service'; import { ResponseCacheService } from '../cache/response-cache.service'; @@ -18,18 +18,17 @@ export abstract class ConfigService { protected abstract halService: HALEndpointService; protected getConfig(request: RestRequest): Observable { - return this.responseCache.get(request.href).pipe( - map((entry: ResponseCacheEntry) => entry.response), - mergeMap((response) => { - if (response.isSuccessful && isNotEmpty(response) && isNotEmpty((response as ConfigSuccessResponse).configDefinition)) { - const configResponse = response as ConfigSuccessResponse; - return observableOf(new ConfigData(configResponse.pageInfo, configResponse.configDefinition)); - } else if (!response.isSuccessful) { - return observableThrowError(new Error(`Couldn't retrieve the config`)); - } - }), - distinctUntilChanged() + const responses = this.responseCache.get(request.href).pipe(map((entry: ResponseCacheEntry) => entry.response)); + const errorResponses = responses.pipe( + filter((response) => !response.isSuccessful), + mergeMap(() => observableThrowError(new Error(`Couldn't retrieve the config`))) ); + const successResponses = responses.pipe( + filter((response) => response.isSuccessful && isNotEmpty(response) && isNotEmpty((response as ConfigSuccessResponse).configDefinition)), + map((response: ConfigSuccessResponse) => new ConfigData(response.pageInfo, response.configDefinition)) + ); + return observableMerge(errorResponses, successResponses); + } protected getConfigByNameHref(endpoint, resourceName): string { @@ -73,7 +72,7 @@ export abstract class ConfigService { map((endpointURL: string) => new ConfigRequest(this.requestService.generateRequestId(), endpointURL)), tap((request: RestRequest) => this.requestService.configure(request)), mergeMap((request: RestRequest) => this.getConfig(request)), - distinctUntilChanged(),); + distinctUntilChanged()); } public getConfigByHref(href: string): Observable { @@ -91,10 +90,11 @@ export abstract class ConfigService { map((endpointURL: string) => new ConfigRequest(this.requestService.generateRequestId(), endpointURL)), tap((request: RestRequest) => this.requestService.configure(request)), mergeMap((request: RestRequest) => this.getConfig(request)), - distinctUntilChanged(),); + distinctUntilChanged()); } public getConfigBySearch(options: FindAllOptions = {}): Observable { + console.log(this.halService.getEndpoint(this.linkPath)); return this.halService.getEndpoint(this.linkPath).pipe( map((endpoint: string) => this.getConfigSearchHref(endpoint, options)), filter((href: string) => isNotEmpty(href)), @@ -102,7 +102,7 @@ export abstract class ConfigService { map((endpointURL: string) => new ConfigRequest(this.requestService.generateRequestId(), endpointURL)), tap((request: RestRequest) => this.requestService.configure(request)), mergeMap((request: RestRequest) => this.getConfig(request)), - distinctUntilChanged(),); + distinctUntilChanged()); } } diff --git a/src/app/core/data/comcol-data.service.ts b/src/app/core/data/comcol-data.service.ts index de3955eb14..c59ecbb3e3 100644 --- a/src/app/core/data/comcol-data.service.ts +++ b/src/app/core/data/comcol-data.service.ts @@ -1,4 +1,4 @@ -import { Observable, throwError as observableThrowError } from 'rxjs'; +import { Observable, throwError as observableThrowError, merge as observableMerge } from 'rxjs'; import { distinctUntilChanged, filter, first, map, mergeMap, tap } from 'rxjs/operators'; import { isEmpty, isNotEmpty } from '../../shared/empty.util'; import { NormalizedCommunity } from '../cache/models/normalized-community.model'; @@ -10,6 +10,7 @@ import { DataService } from './data.service'; import { FindByIDRequest } from './request.models'; import { NormalizedObject } from '../cache/models/normalized-object.model'; import { HALEndpointService } from '../shared/hal-endpoint.service'; +import { DSOSuccessResponse } from '../cache/response-cache.models'; export abstract class ComColDataService extends DataService { protected abstract cds: CommunityDataService; @@ -38,23 +39,39 @@ export abstract class ComColDataService this.responseCache.get(href)), + // map((entry: ResponseCacheEntry) => entry.response), + // mergeMap((response) => { + // if (response.isSuccessful) { + // const community$: Observable = this.objectCache.getByUUID(scopeID); + // return community$.pipe( + // map((community) => community._links[this.linkPath]), + // filter((href) => isNotEmpty(href)), + // distinctUntilChanged() + // ); + // } else if (!response.isSuccessful) { + // return observableThrowError(new Error(`The Community with scope ${scopeID} couldn't be retrieved`)) + // } + // }), + // distinctUntilChanged() + // ); + const responses = scopeCommunityHrefObs.pipe( mergeMap((href: string) => this.responseCache.get(href)), - map((entry: ResponseCacheEntry) => entry.response), - mergeMap((response) => { - if (response.isSuccessful) { - const community$: Observable = this.objectCache.getByUUID(scopeID); - return community$.pipe( - map((community) => community._links[this.linkPath]), - filter((href) => isNotEmpty(href)), - distinctUntilChanged() - ); - } else if (!response.isSuccessful) { - return observableThrowError(new Error(`The Community with scope ${scopeID} couldn't be retrieved`)) - } - }), - distinctUntilChanged() + map((entry: ResponseCacheEntry) => entry.response)); + const errorResponses = responses.pipe( + filter((response) => !response.isSuccessful), + mergeMap(() => observableThrowError(new Error(`The Community with scope ${scopeID} couldn't be retrieved`))) ); + const successResponses = responses.pipe( + filter((response) => response.isSuccessful), + mergeMap(() => this.objectCache.getByUUID(scopeID)), + map((nc: NormalizedCommunity) => nc._links[this.linkPath]), + filter((href) => isNotEmpty(href)) + ); + + + return observableMerge(errorResponses, successResponses).pipe(distinctUntilChanged()); } } } diff --git a/src/app/core/data/request.service.spec.ts b/src/app/core/data/request.service.spec.ts index 92dd2c126b..39f29a9beb 100644 --- a/src/app/core/data/request.service.spec.ts +++ b/src/app/core/data/request.service.spec.ts @@ -1,15 +1,14 @@ -import { Store } from '@ngrx/store'; -import { cold, hot } from 'jasmine-marbles'; +import { cold, getTestScheduler, hot } from 'jasmine-marbles'; import { of as observableOf } from 'rxjs'; import { getMockObjectCacheService } from '../../shared/mocks/mock-object-cache.service'; import { getMockResponseCacheService } from '../../shared/mocks/mock-response-cache.service'; -import { getMockStore } from '../../shared/mocks/mock-store'; import { defaultUUID, getMockUUIDService } from '../../shared/mocks/mock-uuid.service'; import { ObjectCacheService } from '../cache/object-cache.service'; import { ResponseCacheService } from '../cache/response-cache.service'; import { CoreState } from '../core.reducers'; import { UUIDService } from '../shared/uuid.service'; import { RequestConfigureAction, RequestExecuteAction } from './request.actions'; +import * as ngrx from '@ngrx/store'; import { DeleteRequest, GetRequest, @@ -21,8 +20,12 @@ 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'; describe('RequestService', () => { + let scheduler: TestScheduler; let service: RequestService; let serviceAsAny: any; let objectCache: ObjectCacheService; @@ -39,8 +42,10 @@ describe('RequestService', () => { const testOptionsRequest = new OptionsRequest(testUUID, testHref); const testHeadRequest = new HeadRequest(testUUID, testHref); const testPatchRequest = new PatchRequest(testUUID, testHref); - + let selectSpy; beforeEach(() => { + scheduler = getTestScheduler(); + objectCache = getMockObjectCacheService(); (objectCache.hasBySelfLink as any).and.returnValue(false); @@ -50,8 +55,13 @@ describe('RequestService', () => { uuidService = getMockUUIDService(); - store = getMockStore(); - (store.pipe as any).and.returnValue(observableOf(undefined)); + store = new Store(new BehaviorSubject({}), new ActionsSubject(), null); + selectSpy = spyOnProperty(ngrx, 'select') + selectSpy.and.callFake(() => { + return () => { + return () => cold('a', { a: undefined }); + }; + }); service = new RequestService( objectCache, @@ -134,11 +144,15 @@ describe('RequestService', () => { describe('getByUUID', () => { describe('if the request with the specified UUID exists in the store', () => { beforeEach(() => { - (store.pipe as any).and.returnValues(hot('a', { - a: { - completed: true - } - })); + selectSpy.and.callFake(() => { + return () => { + return () => hot('a', { + a: { + completed: true + } + }); + }; + }); }); it('should return an Observable of the RequestEntry', () => { @@ -155,9 +169,11 @@ describe('RequestService', () => { describe('if the request with the specified UUID doesn\'t exist in the store', () => { beforeEach(() => { - (store.pipe as any).and.returnValues(hot('a', { - a: undefined - })); + selectSpy.and.callFake(() => { + return () => { + return () => hot('a', { a: undefined }); + }; + }); }); it('should return an Observable of undefined', () => { @@ -175,9 +191,11 @@ describe('RequestService', () => { describe('getByHref', () => { describe('when the request with the specified href exists in the store', () => { beforeEach(() => { - (store.pipe as any).and.returnValues(hot('a', { - a: testUUID - })); + selectSpy.and.callFake(() => { + return () => { + return () => hot('a', { a: testUUID }); + }; + }); spyOn(service, 'getByUUID').and.returnValue(cold('b', { b: { completed: true @@ -199,9 +217,11 @@ describe('RequestService', () => { describe('when the request with the specified href doesn\'t exist in the store', () => { beforeEach(() => { - (store.pipe as any).and.returnValues(hot('a', { - a: undefined - })); + selectSpy.and.callFake(() => { + return () => { + return () => hot('a', { a: undefined }); + }; + }); spyOn(service, 'getByUUID').and.returnValue(cold('b', { b: undefined })); @@ -241,7 +261,8 @@ describe('RequestService', () => { }); it('should dispatch the request', () => { - service.configure(request); + scheduler.schedule(() => service.configure(request)); + scheduler.flush(); expect(serviceAsAny.dispatchRequest).toHaveBeenCalledWith(request); }); }); @@ -398,6 +419,10 @@ describe('RequestService', () => { }); describe('dispatchRequest', () => { + beforeEach(() => { + spyOn(store, 'dispatch'); + }); + it('should dispatch a RequestConfigureAction', () => { const request = testGetRequest; serviceAsAny.dispatchRequest(request); @@ -428,7 +453,11 @@ describe('RequestService', () => { describe('when the request is added to the store', () => { it('should stop tracking the request', () => { - (store.pipe as any).and.returnValues(observableOf({ request })); + selectSpy.and.callFake(() => { + return () => { + return () => observableOf({ request }); + }; + }); serviceAsAny.trackRequestsOnTheirWayToTheStore(request); expect(serviceAsAny.requestsOnTheirWayToTheStore.includes(request.href)).toBeFalsy(); }); diff --git a/src/app/core/data/request.service.ts b/src/app/core/data/request.service.ts index 92eb4b55e7..101825e3db 100644 --- a/src/app/core/data/request.service.ts +++ b/src/app/core/data/request.service.ts @@ -1,12 +1,12 @@ -import { Observable } from 'rxjs'; -import { filter, first, map, mergeMap, take } from 'rxjs/operators'; +import { Observable, merge as observableMerge } from 'rxjs'; +import { filter, first, map, mergeMap, partition, take } from 'rxjs/operators'; import { Injectable } from '@angular/core'; import { MemoizedSelector, select, Store } from '@ngrx/store'; import { hasValue } from '../../shared/empty.util'; import { CacheableObject } from '../cache/object-cache.reducer'; import { ObjectCacheService } from '../cache/object-cache.service'; -import { DSOSuccessResponse } from '../cache/response-cache.models'; +import { DSOSuccessResponse, RestResponse } from '../cache/response-cache.models'; import { ResponseCacheEntry } from '../cache/response-cache.reducer'; import { ResponseCacheService } from '../cache/response-cache.service'; import { coreSelector, CoreState } from '../core.reducers'; @@ -82,17 +82,21 @@ export class RequestService { private isCachedOrPending(request: GetRequest) { let isCached = this.objectCache.hasBySelfLink(request.href); if (!isCached && this.responseCache.has(request.href)) { - this.responseCache.get(request.href).pipe( - first(), - map((entry: ResponseCacheEntry) => { - const response = entry.response; - if (response.isSuccessful && hasValue((response as DSOSuccessResponse).resourceSelfLinks)) { - return (response as DSOSuccessResponse).resourceSelfLinks.every((selfLink) => this.objectCache.hasBySelfLink(selfLink)) - } else { - return true; - } - }) - ).subscribe((c) => isCached = c); + const responses = this.responseCache.get(request.href).pipe( + take(1), + map((entry: ResponseCacheEntry) => entry.response) + ); + + 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; diff --git a/src/app/core/data/test.spec.ts b/src/app/core/data/test.spec.ts new file mode 100644 index 0000000000..3659c66e11 --- /dev/null +++ b/src/app/core/data/test.spec.ts @@ -0,0 +1,37 @@ +import { select } from '@ngrx/store'; +import * as ngrx from '@ngrx/store'; +import { cold, hot } from 'jasmine-marbles'; +import { Observable } from 'rxjs'; +import { count, take } from 'rxjs/operators'; + +class TestClass { + selectSomething(input$: Observable) { + return input$.pipe( + select('something'), + take(1) + ) + } +} +describe('mockSelect', () => { + let testClass; + beforeEach(() => { + spyOnProperty(ngrx, 'select').and.callFake(() => { + return () => { + return () => cold('a', { a: 'bingo!' }); + }; + }); + + testClass = new TestClass(); + }); + + it('should mock select', () => { + const input$ = hot('a', { a: '' }); + const expected$ = hot('(b|)', { b: 'bingo!' }); + const result$ = testClass.selectSomething(input$); + result$.pipe(count()).subscribe((t) => console.log('resykts', t)); + expected$.pipe(count()).subscribe((t) => console.log('expected', t)); + result$.subscribe((v) => console.log('result$', v)); + expected$.subscribe((v) => console.log('expected$', v)); + expect(result$).toBeObservable(expected$) + }); +}) \ No newline at end of file diff --git a/src/app/header/header.component.spec.ts b/src/app/header/header.component.spec.ts index 1cd0b6c33f..7636748614 100644 --- a/src/app/header/header.component.spec.ts +++ b/src/app/header/header.component.spec.ts @@ -19,7 +19,7 @@ import { HostWindowServiceStub } from '../shared/testing/host-window-service-stu import { RouterStub } from '../shared/testing/router-stub'; import { Router } from '@angular/router'; import { NoopAnimationsModule } from '@angular/platform-browser/animations'; - +import * as ngrx from '@ngrx/store'; let comp: HeaderComponent; let fixture: ComponentFixture; let store: Store; @@ -72,7 +72,11 @@ describe('HeaderComponent', () => { beforeEach(() => { menu = fixture.debugElement.query(By.css('#collapsingNav')).nativeElement; - spyOn(store, 'select').and.returnValue(observableOf({ navCollapsed: true })); + spyOnProperty(ngrx, 'select').and.callFake(() => { + return () => { + return () => observableOf({ navCollapsed: true }) + }; + }); fixture.detectChanges(); }); @@ -87,7 +91,11 @@ describe('HeaderComponent', () => { beforeEach(() => { menu = fixture.debugElement.query(By.css('#collapsingNav')).nativeElement; - spyOn(store, 'select').and.returnValue(observableOf(false)); + spyOnProperty(ngrx, 'select').and.callFake(() => { + return () => { + return () => observableOf(false) + }; + }); fixture.detectChanges(); }); diff --git a/src/app/shared/chips/chips.component.spec.ts b/src/app/shared/chips/chips.component.spec.ts index 44092ce7d8..7a9461dfd7 100644 --- a/src/app/shared/chips/chips.component.spec.ts +++ b/src/app/shared/chips/chips.component.spec.ts @@ -1,7 +1,6 @@ // Load the implementations that should be tested import { ChangeDetectorRef, Component, CUSTOM_ELEMENTS_SCHEMA } from '@angular/core'; import { async, ComponentFixture, fakeAsync, inject, TestBed, tick, } from '@angular/core/testing'; -import 'rxjs/add/observable/of'; import { Chips } from './models/chips.model'; import { UploaderService } from '../uploader/uploader.service'; diff --git a/src/app/shared/form/builder/ds-dynamic-form-ui/ds-dynamic-form-control.component.html b/src/app/shared/form/builder/ds-dynamic-form-ui/ds-dynamic-form-control.component.html index db5bc92574..d838a90f20 100644 --- a/src/app/shared/form/builder/ds-dynamic-form-ui/ds-dynamic-form-control.component.html +++ b/src/app/shared/form/builder/ds-dynamic-form-ui/ds-dynamic-form-control.component.html @@ -12,429 +12,7 @@
- - - -
- -
- - - - -
-
- - - - - - -
- - -
- - -
- -
- - -
- - -
- -
-
- - -
- - -
- - -
- -
- -
- - - - - -
- -
- - - - -
- - -
- - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- {{ message | translate:model.validators }} -
- -
- - - - - - - - - - - - - - - - - - - - - - - - - +
diff --git a/src/app/shared/form/builder/ds-dynamic-form-ui/ds-dynamic-form-control.component.spec.ts b/src/app/shared/form/builder/ds-dynamic-form-ui/ds-dynamic-form-control.component.spec.ts index c44f996102..ab98476cc3 100644 --- a/src/app/shared/form/builder/ds-dynamic-form-ui/ds-dynamic-form-control.component.spec.ts +++ b/src/app/shared/form/builder/ds-dynamic-form-ui/ds-dynamic-form-control.component.spec.ts @@ -25,7 +25,7 @@ import { DynamicTextAreaModel, DynamicTimePickerModel } from '@ng-dynamic-forms/core'; -import { DsDynamicFormControlComponent, NGBootstrapFormControlType } from './ds-dynamic-form-control.component'; +import { DsDynamicFormControlComponent } from './ds-dynamic-form-control.component'; import { TranslateModule } from '@ngx-translate/core'; import { SharedModule } from '../../../shared.module'; import { DynamicDsDatePickerModel } from './models/date-picker/date-picker.model'; @@ -39,6 +39,27 @@ import { DynamicTagModel } from './models/tag/dynamic-tag.model'; import { DynamicTypeaheadModel } from './models/typeahead/dynamic-typeahead.model'; import { DynamicQualdropModel } from './models/ds-dynamic-qualdrop.model'; import { DynamicLookupNameModel } from './models/lookup/dynamic-lookup-name.model'; +import { BrowserDynamicTestingModule } from '@angular/platform-browser-dynamic/testing'; +import { + DynamicNGBootstrapCalendarComponent, + DynamicNGBootstrapCheckboxComponent, + DynamicNGBootstrapCheckboxGroupComponent, + DynamicNGBootstrapDatePickerComponent, + DynamicNGBootstrapFormArrayComponent, + DynamicNGBootstrapFormGroupComponent, + DynamicNGBootstrapInputComponent, + DynamicNGBootstrapRadioGroupComponent, + DynamicNGBootstrapSelectComponent, + DynamicNGBootstrapTextAreaComponent, + DynamicNGBootstrapTimePickerComponent +} from '@ng-dynamic-forms/ui-ng-bootstrap'; +import { DsDynamicTypeaheadComponent } from './models/typeahead/dynamic-typeahead.component'; +import { DsDynamicScrollableDropdownComponent } from './models/scrollable-dropdown/dynamic-scrollable-dropdown.component'; +import { DsDynamicTagComponent } from './models/tag/dynamic-tag.component'; +import { DsDynamicListComponent } from './models/list/dynamic-list.component'; +import { DsDynamicGroupComponent } from './models/dynamic-group/dynamic-group.components'; +import { DsDatePickerComponent } from './models/date-picker/date-picker.component'; +import { DsDynamicLookupComponent } from './models/lookup/dynamic-lookup.component'; describe('DsDynamicFormControlComponent test suite', () => { @@ -49,27 +70,42 @@ describe('DsDynamicFormControlComponent test suite', () => { scope: 'c1c16450-d56f-41bc-bb81-27f1d1eb5c23' }; const formModel = [ - new DynamicCheckboxModel({id: 'checkbox'}), - new DynamicCheckboxGroupModel({id: 'checkboxGroup', group: []}), - new DynamicColorPickerModel({id: 'colorpicker'}), - new DynamicDatePickerModel({id: 'datepicker'}), - new DynamicEditorModel({id: 'editor'}), - new DynamicFileUploadModel({id: 'upload', url: ''}), - new DynamicFormArrayModel({id: 'formArray', groupFactory: () => []}), - new DynamicFormGroupModel({id: 'formGroup', group: []}), - new DynamicInputModel({id: 'input', maxLength: 51}), - new DynamicRadioGroupModel({id: 'radioGroup'}), - new DynamicRatingModel({id: 'rating'}), - new DynamicSelectModel({id: 'select', options: [{value: 'One'}, {value: 'Two'}], value: 'One'}), - new DynamicSliderModel({id: 'slider'}), - new DynamicSwitchModel({id: 'switch'}), - new DynamicTextAreaModel({id: 'textarea'}), - new DynamicTimePickerModel({id: 'timepicker'}), - new DynamicTypeaheadModel({id: 'typeahead'}), - new DynamicScrollableDropdownModel({id: 'scrollableDropdown', authorityOptions: authorityOptions}), - new DynamicTagModel({id: 'tag'}), - new DynamicListCheckboxGroupModel({id: 'checkboxList', authorityOptions: authorityOptions, repeatable: true}), - new DynamicListRadioGroupModel({id: 'radioList', authorityOptions: authorityOptions, repeatable: false}), + new DynamicCheckboxModel({ id: 'checkbox' }), + new DynamicCheckboxGroupModel({ id: 'checkboxGroup', group: [] }), + new DynamicColorPickerModel({ id: 'colorpicker' }), + new DynamicDatePickerModel({ id: 'datepicker' }), + new DynamicEditorModel({ id: 'editor' }), + new DynamicFileUploadModel({ id: 'upload', url: '' }), + new DynamicFormArrayModel({ id: 'formArray', groupFactory: () => [] }), + new DynamicFormGroupModel({ id: 'formGroup', group: [] }), + new DynamicInputModel({ id: 'input', maxLength: 51 }), + new DynamicRadioGroupModel({ id: 'radioGroup' }), + new DynamicRatingModel({ id: 'rating' }), + new DynamicSelectModel({ + id: 'select', + options: [{ value: 'One' }, { value: 'Two' }], + value: 'One' + }), + new DynamicSliderModel({ id: 'slider' }), + new DynamicSwitchModel({ id: 'switch' }), + new DynamicTextAreaModel({ id: 'textarea' }), + new DynamicTimePickerModel({ id: 'timepicker' }), + new DynamicTypeaheadModel({ id: 'typeahead' }), + new DynamicScrollableDropdownModel({ + id: 'scrollableDropdown', + authorityOptions: authorityOptions + }), + new DynamicTagModel({ id: 'tag' }), + new DynamicListCheckboxGroupModel({ + id: 'checkboxList', + authorityOptions: authorityOptions, + repeatable: true + }), + new DynamicListRadioGroupModel({ + id: 'radioList', + authorityOptions: authorityOptions, + repeatable: false + }), new DynamicGroupModel({ id: 'relationGroup', formConfiguration: [], @@ -79,10 +115,10 @@ describe('DsDynamicFormControlComponent test suite', () => { scopeUUID: '', submissionScope: '' }), - new DynamicDsDatePickerModel({id: 'datepicker'}), - new DynamicLookupModel({id: 'lookup'}), - new DynamicLookupNameModel({id: 'lookupName'}), - new DynamicQualdropModel({id: 'combobox', readOnly: false}) + new DynamicDsDatePickerModel({ id: 'datepicker' }), + new DynamicLookupModel({ id: 'lookup' }), + new DynamicLookupNameModel({ id: 'lookupName' }), + new DynamicQualdropModel({ id: 'combobox', readOnly: false }) ]; const testModel = formModel[8]; let formGroup: FormGroup; @@ -93,6 +129,13 @@ describe('DsDynamicFormControlComponent test suite', () => { beforeEach(async(() => { + TestBed.overrideModule(BrowserDynamicTestingModule, { + + set: { + entryComponents: [DynamicNGBootstrapInputComponent] + } + }); + TestBed.configureTestingModule({ imports: [ @@ -102,8 +145,9 @@ describe('DsDynamicFormControlComponent test suite', () => { DynamicFormsCoreModule.forRoot(), SharedModule, TranslateModule.forRoot(), - TextMaskModule, + TextMaskModule ], + providers: [DsDynamicFormControlComponent, DynamicFormService], schemas: [CUSTOM_ELEMENTS_SCHEMA] }).compileComponents().then(() => { @@ -128,12 +172,11 @@ describe('DsDynamicFormControlComponent test suite', () => { }); fixture.detectChanges(); - + console.log(fixture.componentInstance.componentViewContainerRef); testElement = debugElement.query(By.css(`input[id='${testModel.id}']`)); })); it('should initialize correctly', () => { - expect(component.context).toBeNull(); expect(component.control instanceof FormControl).toBe(true); expect(component.group instanceof FormGroup).toBe(true); @@ -149,15 +192,7 @@ describe('DsDynamicFormControlComponent test suite', () => { expect(component.change).toBeDefined(); expect(component.focus).toBeDefined(); - expect(component.onChange).toBeDefined(); - expect(component.onBlur).toBeDefined(); - expect(component.onFocus).toBeDefined(); - - expect(component.isValid).toBe(true); - expect(component.isInvalid).toBe(false); - expect(component.showErrorMessages).toBe(false); - - expect(component.type).toBe(NGBootstrapFormControlType.Input); + expect(component.componentType).toBe(DynamicNGBootstrapInputComponent); }); it('should have an input element', () => { @@ -219,63 +254,36 @@ describe('DsDynamicFormControlComponent test suite', () => { expect(component.onModelDisabledUpdates).toHaveBeenCalled(); }); - it('should determine correct form control type', () => { - + it('should map a form control model to a form control component', () => { const testFn = DsDynamicFormControlComponent.getFormControlType; - - expect(testFn(formModel[0])).toEqual(NGBootstrapFormControlType.Checkbox); - - expect(testFn(formModel[1])).toEqual(NGBootstrapFormControlType.CheckboxGroup); - + expect(testFn(formModel[0])).toBe(DynamicNGBootstrapCheckboxComponent); + expect(testFn(formModel[1])).toBe(DynamicNGBootstrapCheckboxGroupComponent); expect(testFn(formModel[2])).toBeNull(); - - expect(testFn(formModel[3])).toEqual(NGBootstrapFormControlType.DatePicker); - + expect(testFn(formModel[3])).toBe(DynamicNGBootstrapDatePickerComponent); (formModel[3] as DynamicDatePickerModel).inline = true; - expect(testFn(formModel[3])).toEqual(NGBootstrapFormControlType.Calendar); - + expect(testFn(formModel[3])).toBe(DynamicNGBootstrapCalendarComponent); expect(testFn(formModel[4])).toBeNull(); - expect(testFn(formModel[5])).toBeNull(); - - expect(testFn(formModel[6])).toEqual(NGBootstrapFormControlType.Array); - - expect(testFn(formModel[7])).toEqual(NGBootstrapFormControlType.Group); - - expect(testFn(formModel[8])).toEqual(NGBootstrapFormControlType.Input); - - expect(testFn(formModel[9])).toEqual(NGBootstrapFormControlType.RadioGroup); - + expect(testFn(formModel[6])).toBe(DynamicNGBootstrapFormArrayComponent); + expect(testFn(formModel[7])).toBe(DynamicNGBootstrapFormGroupComponent); + expect(testFn(formModel[8])).toBe(DynamicNGBootstrapInputComponent); + expect(testFn(formModel[9])).toBe(DynamicNGBootstrapRadioGroupComponent); expect(testFn(formModel[10])).toBeNull(); - - expect(testFn(formModel[11])).toEqual(NGBootstrapFormControlType.Select); - + expect(testFn(formModel[11])).toBe(DynamicNGBootstrapSelectComponent); expect(testFn(formModel[12])).toBeNull(); - expect(testFn(formModel[13])).toBeNull(); - - expect(testFn(formModel[14])).toEqual(NGBootstrapFormControlType.TextArea); - - expect(testFn(formModel[15])).toEqual(NGBootstrapFormControlType.TimePicker); - - expect(testFn(formModel[16])).toEqual(NGBootstrapFormControlType.TypeAhead); - - expect(testFn(formModel[17])).toEqual(NGBootstrapFormControlType.ScrollableDropdown); - - expect(testFn(formModel[18])).toEqual(NGBootstrapFormControlType.Tag); - - expect(testFn(formModel[19])).toEqual(NGBootstrapFormControlType.List); - - expect(testFn(formModel[20])).toEqual(NGBootstrapFormControlType.List); - - expect(testFn(formModel[21])).toEqual(NGBootstrapFormControlType.Relation); - - expect(testFn(formModel[22])).toEqual(NGBootstrapFormControlType.Date); - - expect(testFn(formModel[23])).toEqual(NGBootstrapFormControlType.Lookup); - - expect(testFn(formModel[24])).toEqual(NGBootstrapFormControlType.LookupName); - - expect(testFn(formModel[25])).toEqual(NGBootstrapFormControlType.Group); + expect(testFn(formModel[14])).toBe(DynamicNGBootstrapTextAreaComponent); + expect(testFn(formModel[15])).toBe(DynamicNGBootstrapTimePickerComponent); + expect(testFn(formModel[16])).toBe(DsDynamicTypeaheadComponent); + expect(testFn(formModel[17])).toBe(DsDynamicScrollableDropdownComponent); + expect(testFn(formModel[18])).toBe(DsDynamicTagComponent); + expect(testFn(formModel[19])).toBe(DsDynamicListComponent); + expect(testFn(formModel[20])).toBe(DsDynamicListComponent); + expect(testFn(formModel[21])).toBe(DsDynamicGroupComponent); + expect(testFn(formModel[22])).toBe(DsDatePickerComponent); + expect(testFn(formModel[23])).toBe(DsDynamicLookupComponent); + expect(testFn(formModel[24])).toBe(DsDynamicLookupComponent); + expect(testFn(formModel[25])).toBe(DynamicNGBootstrapFormGroupComponent); }); + }); diff --git a/src/app/shared/form/builder/ds-dynamic-form-ui/ds-dynamic-form-control.component.ts b/src/app/shared/form/builder/ds-dynamic-form-ui/ds-dynamic-form-control.component.ts index 25d1be6585..a5d6b923df 100644 --- a/src/app/shared/form/builder/ds-dynamic-form-ui/ds-dynamic-form-control.component.ts +++ b/src/app/shared/form/builder/ds-dynamic-form-ui/ds-dynamic-form-control.component.ts @@ -6,7 +6,7 @@ import { OnChanges, Output, QueryList, - SimpleChanges, Type + SimpleChanges, Type, ViewChild, ViewContainerRef } from '@angular/core'; import { FormGroup } from '@angular/forms'; import { @@ -39,29 +39,26 @@ import { DynamicListCheckboxGroupModel } from './models/list/dynamic-list-checkb import { DynamicListRadioGroupModel } from './models/list/dynamic-list-radio-group.model'; import { isNotEmpty } from '../../../empty.util'; import { DYNAMIC_FORM_CONTROL_TYPE_LOOKUP_NAME } from './models/lookup/dynamic-lookup-name.model'; - -export const enum NGBootstrapFormControlType { - - Array = 1, // 'ARRAY', - Calendar = 2, // 'CALENDAR', - Checkbox = 3, // 'CHECKBOX', - CheckboxGroup = 4, // 'CHECKBOX_GROUP', - DatePicker = 5, // 'DATEPICKER', - Group = 6, // 'GROUP', - Input = 7, // 'INPUT', - RadioGroup = 8, // 'RADIO_GROUP', - Select = 9, // 'SELECT', - TextArea = 10, // 'TEXTAREA', - TimePicker = 11, // 'TIMEPICKER' - TypeAhead = 12, // 'TYPEAHEAD' - ScrollableDropdown = 13, // 'SCROLLABLE_DROPDOWN' - Tag = 14, // 'TAG' - List = 15, // 'TYPELIST' - Relation = 16, // 'RELATION' - Date = 17, // 'DATE' - Lookup = 18, // LOOKUP - LookupName = 19, // LOOKUP_NAME -} +import { DsDynamicTagComponent } from './models/tag/dynamic-tag.component'; +import { + DynamicNGBootstrapCalendarComponent, + DynamicNGBootstrapCheckboxComponent, + DynamicNGBootstrapCheckboxGroupComponent, + DynamicNGBootstrapDatePickerComponent, + DynamicNGBootstrapFormArrayComponent, + DynamicNGBootstrapFormGroupComponent, + DynamicNGBootstrapInputComponent, + DynamicNGBootstrapRadioGroupComponent, + DynamicNGBootstrapSelectComponent, + DynamicNGBootstrapTextAreaComponent, + DynamicNGBootstrapTimePickerComponent +} from '@ng-dynamic-forms/ui-ng-bootstrap'; +import { DsDatePickerComponent } from './models/date-picker/date-picker.component'; +import { DsDynamicListComponent } from './models/list/dynamic-list.component'; +import { DsDynamicTypeaheadComponent } from './models/typeahead/dynamic-typeahead.component'; +import { DsDynamicScrollableDropdownComponent } from './models/scrollable-dropdown/dynamic-scrollable-dropdown.component'; +import { DsDynamicGroupComponent } from './models/dynamic-group/dynamic-group.components'; +import { DsDynamicLookupComponent } from './models/lookup/dynamic-lookup.component'; @Component({ selector: 'ds-dynamic-form-control', @@ -88,67 +85,68 @@ export class DsDynamicFormControlComponent extends DynamicFormControlContainerCo @Output('dfChange') change: EventEmitter = new EventEmitter(); @Output('dfFocus') focus: EventEmitter = new EventEmitter(); /* tslint:enable:no-output-rename */ + @ViewChild('componentViewContainer', {read: ViewContainerRef}) componentViewContainerRef: ViewContainerRef; - type: NGBootstrapFormControlType | null; + get componentType(): Type | null { + return this.layoutService.getCustomComponentType(this.model) || DsDynamicFormControlComponent.getFormControlType(this.model); + } - readonly componentType: Type | null; - - static getFormControlType(model: DynamicFormControlModel): NGBootstrapFormControlType | null { + static getFormControlType(model: DynamicFormControlModel): Type | null { switch (model.type) { case DYNAMIC_FORM_CONTROL_TYPE_ARRAY: - return NGBootstrapFormControlType.Array; + return DynamicNGBootstrapFormArrayComponent; case DYNAMIC_FORM_CONTROL_TYPE_CHECKBOX: - return NGBootstrapFormControlType.Checkbox; + return DynamicNGBootstrapCheckboxComponent; case DYNAMIC_FORM_CONTROL_TYPE_CHECKBOX_GROUP: - return (model instanceof DynamicListCheckboxGroupModel) ? NGBootstrapFormControlType.List : NGBootstrapFormControlType.CheckboxGroup; + return (model instanceof DynamicListCheckboxGroupModel) ? DsDynamicListComponent : DynamicNGBootstrapCheckboxGroupComponent; case DYNAMIC_FORM_CONTROL_TYPE_DATEPICKER: const datepickerModel = model as DynamicDatePickerModel; - return datepickerModel.inline ? NGBootstrapFormControlType.Calendar : NGBootstrapFormControlType.DatePicker; + return datepickerModel.inline ? DynamicNGBootstrapCalendarComponent : DynamicNGBootstrapDatePickerComponent; case DYNAMIC_FORM_CONTROL_TYPE_GROUP: - return NGBootstrapFormControlType.Group; + return DynamicNGBootstrapFormGroupComponent; case DYNAMIC_FORM_CONTROL_TYPE_INPUT: - return NGBootstrapFormControlType.Input; + return DynamicNGBootstrapInputComponent; case DYNAMIC_FORM_CONTROL_TYPE_RADIO_GROUP: - return (model instanceof DynamicListRadioGroupModel) ? NGBootstrapFormControlType.List : NGBootstrapFormControlType.RadioGroup; + return (model instanceof DynamicListRadioGroupModel) ? DsDynamicListComponent : DynamicNGBootstrapRadioGroupComponent; case DYNAMIC_FORM_CONTROL_TYPE_SELECT: - return NGBootstrapFormControlType.Select; + return DynamicNGBootstrapSelectComponent; case DYNAMIC_FORM_CONTROL_TYPE_TEXTAREA: - return NGBootstrapFormControlType.TextArea; + return DynamicNGBootstrapTextAreaComponent; case DYNAMIC_FORM_CONTROL_TYPE_TIMEPICKER: - return NGBootstrapFormControlType.TimePicker; + return DynamicNGBootstrapTimePickerComponent; case DYNAMIC_FORM_CONTROL_TYPE_TYPEAHEAD: - return NGBootstrapFormControlType.TypeAhead; + return DsDynamicTypeaheadComponent; case DYNAMIC_FORM_CONTROL_TYPE_SCROLLABLE_DROPDOWN: - return NGBootstrapFormControlType.ScrollableDropdown; + return DsDynamicScrollableDropdownComponent; case DYNAMIC_FORM_CONTROL_TYPE_TAG: - return NGBootstrapFormControlType.Tag; + return DsDynamicTagComponent; case DYNAMIC_FORM_CONTROL_TYPE_RELATION_GROUP: - return NGBootstrapFormControlType.Relation; + return DsDynamicGroupComponent; case DYNAMIC_FORM_CONTROL_TYPE_DSDATEPICKER: - return NGBootstrapFormControlType.Date; + return DsDatePickerComponent; case DYNAMIC_FORM_CONTROL_TYPE_LOOKUP: - return NGBootstrapFormControlType.Lookup; + return DsDynamicLookupComponent; case DYNAMIC_FORM_CONTROL_TYPE_LOOKUP_NAME: - return NGBootstrapFormControlType.LookupName; + return DsDynamicLookupComponent; default: return null; @@ -163,11 +161,7 @@ export class DsDynamicFormControlComponent extends DynamicFormControlContainerCo ngOnChanges(changes: SimpleChanges) { if (changes) { - // super.ngOnChanges(changes); - } - - if (changes.model) { - this.type = DsDynamicFormControlComponent.getFormControlType(this.model); + super.ngOnChanges(changes); } } diff --git a/src/app/shared/form/builder/ds-dynamic-form-ui/models/date-picker/date-picker.component.spec.ts b/src/app/shared/form/builder/ds-dynamic-form-ui/models/date-picker/date-picker.component.spec.ts index 02f1415e99..d11dbf664b 100644 --- a/src/app/shared/form/builder/ds-dynamic-form-ui/models/date-picker/date-picker.component.spec.ts +++ b/src/app/shared/form/builder/ds-dynamic-form-ui/models/date-picker/date-picker.component.spec.ts @@ -4,7 +4,7 @@ import { async, ComponentFixture, inject, TestBed, } from '@angular/core/testing import { FormControl, FormGroup } from '@angular/forms'; import { NgbModule } from '@ng-bootstrap/ng-bootstrap'; -import { DynamicFormValidationService } from '@ng-dynamic-forms/core'; +import { DynamicFormLayoutService, DynamicFormValidationService } from '@ng-dynamic-forms/core'; import { DsDatePickerComponent } from './date-picker.component'; import { DynamicDsDatePickerModel } from './date-picker.model'; @@ -52,10 +52,8 @@ describe('DsDatePickerComponent test suite', () => { providers: [ ChangeDetectorRef, DsDatePickerComponent, - DynamicFormValidationService, - FormBuilderService, - FormComponent, - FormService + {provide: DynamicFormLayoutService, useValue: {}}, + {provide: DynamicFormValidationService, useValue: {}} ], schemas: [CUSTOM_ELEMENTS_SCHEMA] }); @@ -70,7 +68,6 @@ describe('DsDatePickerComponent test suite', () => { [bindId]='bindId' [group]='group' [model]='model' - [showErrorMessages]='showErrorMessages' (blur)='onBlur($event)' (change)='onValueChange($event)' (focus)='onFocus($event)'>`; diff --git a/src/app/shared/form/builder/ds-dynamic-form-ui/models/date-picker/date-picker.component.ts b/src/app/shared/form/builder/ds-dynamic-form-ui/models/date-picker/date-picker.component.ts index 741d86fab9..6cac65ff65 100644 --- a/src/app/shared/form/builder/ds-dynamic-form-ui/models/date-picker/date-picker.component.ts +++ b/src/app/shared/form/builder/ds-dynamic-form-ui/models/date-picker/date-picker.component.ts @@ -1,7 +1,12 @@ -import { Component, EventEmitter, Inject, Input, OnInit, Output } from '@angular/core'; -import { FormControl, FormGroup } from '@angular/forms'; +import { Component, EventEmitter, Input, OnInit, Output } from '@angular/core'; +import { FormGroup } from '@angular/forms'; import { DynamicDsDatePickerModel } from './date-picker.model'; -import { hasNoValue, hasValue, isNotEmpty } from '../../../../../empty.util'; +import { hasValue } from '../../../../../empty.util'; +import { + DynamicFormControlComponent, + DynamicFormLayoutService, + DynamicFormValidationService +} from '@ng-dynamic-forms/core'; export const DS_DATE_PICKER_SEPARATOR = '-'; @@ -11,11 +16,11 @@ export const DS_DATE_PICKER_SEPARATOR = '-'; templateUrl: './date-picker.component.html', }) -export class DsDatePickerComponent implements OnInit { +export class DsDatePickerComponent extends DynamicFormControlComponent implements OnInit { @Input() bindId = true; @Input() group: FormGroup; @Input() model: DynamicDsDatePickerModel; - @Input() showErrorMessages = false; + // @Input() showErrorMessages = false; // @Input() // minDate; // @Input() @@ -49,6 +54,12 @@ export class DsDatePickerComponent implements OnInit { disabledMonth = true; disabledDay = true; + constructor(protected layoutService: DynamicFormLayoutService, + protected validationService: DynamicFormValidationService + ) { + super(layoutService, validationService); + } + ngOnInit() { const now = new Date(); this.initialYear = now.getFullYear(); diff --git a/src/app/shared/form/builder/ds-dynamic-form-ui/models/dynamic-group/dynamic-group.component.spec.ts b/src/app/shared/form/builder/ds-dynamic-form-ui/models/dynamic-group/dynamic-group.component.spec.ts index 94c2faba95..a3205e69c6 100644 --- a/src/app/shared/form/builder/ds-dynamic-form-ui/models/dynamic-group/dynamic-group.component.spec.ts +++ b/src/app/shared/form/builder/ds-dynamic-form-ui/models/dynamic-group/dynamic-group.component.spec.ts @@ -3,8 +3,6 @@ import { ChangeDetectorRef, Component, CUSTOM_ELEMENTS_SCHEMA } from '@angular/c import { async, ComponentFixture, inject, TestBed, } from '@angular/core/testing'; import { FormControl, FormGroup, FormsModule, ReactiveFormsModule } from '@angular/forms'; -import { DynamicFormValidationService } from '@ng-dynamic-forms/core'; -import { Store } from '@ngrx/store'; import { TranslateModule } from '@ngx-translate/core'; import { of as observableOf } from 'rxjs'; import { NgbModule } from '@ng-bootstrap/ng-bootstrap'; @@ -20,12 +18,15 @@ import { FormBuilderService } from '../../../form-builder.service'; import { FormService } from '../../../../form.service'; import { GLOBAL_CONFIG } from '../../../../../../../config'; import { FormComponent } from '../../../../form.component'; -import { AppState } from '../../../../../../app.reducer'; import { BrowserAnimationsModule } from '@angular/platform-browser/animations'; import { Chips } from '../../../../../chips/models/chips.model'; import { FormFieldMetadataValueObject } from '../../../models/form-field-metadata-value.model'; import { DsDynamicInputModel } from '../ds-dynamic-input.model'; import { createTestComponent } from '../../../../../testing/utils'; +import { getMockFormBuilderService } from '../../../../../mocks/mock-form-builder-service'; +import { getMockFormService } from '../../../../../mocks/mock-form-service'; +import { MockComponent } from 'ng-mocks'; +import { DynamicFormLayoutService, DynamicFormValidationService } from '@ng-dynamic-forms/core'; export const FORM_GROUP_TEST_MODEL_CONFIG = { disabled: false, @@ -90,18 +91,13 @@ describe('DsDynamicGroupComponent test suite', () => { let groupComp: DsDynamicGroupComponent; let testFixture: ComponentFixture; let groupFixture: ComponentFixture; - let modelValue: any; + // let modelValue: any; let html; let control1: FormControl; let model1: DsDynamicInputModel; let control2: FormControl; let model2: DsDynamicInputModel; - const store: Store = jasmine.createSpyObj('store', { - dispatch: {}, - select: observableOf(true) - }); - // async beforeEach beforeEach(async(() => { @@ -114,19 +110,18 @@ describe('DsDynamicGroupComponent test suite', () => { TranslateModule.forRoot() ], declarations: [ - FormComponent, + MockComponent(FormComponent), DsDynamicGroupComponent, TestComponent, ], // declare the test component providers: [ ChangeDetectorRef, DsDynamicGroupComponent, - DynamicFormValidationService, - FormBuilderService, - FormComponent, - FormService, + {provide: FormBuilderService, useValue: getMockFormBuilderService()}, + {provide: FormService, useValue: getMockFormService()}, {provide: GLOBAL_CONFIG, useValue: config}, - {provide: Store, useValue: store}, + {provide: DynamicFormLayoutService, useValue: {}}, + {provide: DynamicFormValidationService, useValue: {}} ], schemas: [CUSTOM_ELEMENTS_SCHEMA] }); @@ -140,7 +135,6 @@ describe('DsDynamicGroupComponent test suite', () => { `; @@ -163,7 +157,6 @@ describe('DsDynamicGroupComponent test suite', () => { groupComp.formId = 'testForm'; groupComp.group = FORM_GROUP_TEST_GROUP; groupComp.model = new DynamicGroupModel(FORM_GROUP_TEST_MODEL_CONFIG); - groupComp.showErrorMessages = false; groupFixture.detectChanges(); control1 = service.getFormControlById('dc_contributor_author', (groupComp as any).formRef.formGroup, groupComp.formModel) as FormControl; @@ -179,123 +172,123 @@ describe('DsDynamicGroupComponent test suite', () => { groupComp = null; }); - it('should init component properly', inject([FormBuilderService], (service: FormBuilderService) => { - const formConfig = {rows: groupComp.model.formConfiguration} as SubmissionFormsModel; - const formModel = service.modelFromConfiguration(formConfig, groupComp.model.scopeUUID, {}, groupComp.model.submissionScope, groupComp.model.readOnly); - const chips = new Chips([], 'value', 'dc.contributor.author'); - - expect(groupComp.formCollapsed).toEqual(observableOf(false)); - expect(groupComp.formModel.length).toEqual(formModel.length); - expect(groupComp.chips.getChipsItems()).toEqual(chips.getChipsItems()); - })); - - it('should save a new chips item', () => { - control1.setValue('test author'); - (model1 as any).value = new FormFieldMetadataValueObject('test author'); - control2.setValue('test affiliation'); - (model2 as any).value = new FormFieldMetadataValueObject('test affiliation'); - modelValue = [{ - 'dc.contributor.author': new FormFieldMetadataValueObject('test author'), - 'local.contributor.affiliation': new FormFieldMetadataValueObject('test affiliation') - }]; - groupFixture.detectChanges(); - - const buttons = groupFixture.debugElement.nativeElement.querySelectorAll('button'); - const btnEl = buttons[0]; - btnEl.click(); - - expect(groupComp.chips.getChipsItems()).toEqual(modelValue); - expect(groupComp.formCollapsed).toEqual(observableOf(true)); - }); - - it('should clear form inputs', () => { - control1.setValue('test author'); - (model1 as any).value = new FormFieldMetadataValueObject('test author'); - control2.setValue('test affiliation'); - (model2 as any).value = new FormFieldMetadataValueObject('test affiliation'); - - groupFixture.detectChanges(); - - const buttons = groupFixture.debugElement.nativeElement.querySelectorAll('button'); - const btnEl = buttons[2]; - btnEl.click(); - - expect(control1.value).toBeNull(); - expect(control2.value).toBeNull(); - expect(groupComp.formCollapsed).toEqual(observableOf(false)); - }); - }); - - describe('when init model value is not empty', () => { - beforeEach(() => { - - groupFixture = TestBed.createComponent(DsDynamicGroupComponent); - groupComp = groupFixture.componentInstance; // FormComponent test instance - groupComp.formId = 'testForm'; - groupComp.group = FORM_GROUP_TEST_GROUP; - groupComp.model = new DynamicGroupModel(FORM_GROUP_TEST_MODEL_CONFIG); - modelValue = [{ - 'dc.contributor.author': new FormFieldMetadataValueObject('test author'), - 'local.contributor.affiliation': new FormFieldMetadataValueObject('test affiliation') - }]; - groupComp.model.value = modelValue; - groupComp.showErrorMessages = false; - groupFixture.detectChanges(); - - }); - - afterEach(() => { - groupFixture.destroy(); - groupComp = null; - }); - - it('should init component properly', inject([FormBuilderService], (service: FormBuilderService) => { - const formConfig = {rows: groupComp.model.formConfiguration} as SubmissionFormsModel; - const formModel = service.modelFromConfiguration(formConfig, groupComp.model.scopeUUID, {}, groupComp.model.submissionScope, groupComp.model.readOnly); - const chips = new Chips(modelValue, 'value', 'dc.contributor.author'); - - expect(groupComp.formCollapsed).toEqual(observableOf(true)); - expect(groupComp.formModel.length).toEqual(formModel.length); - expect(groupComp.chips.getChipsItems()).toEqual(chips.getChipsItems()); - })); - - it('should modify existing chips item', inject([FormBuilderService], (service: FormBuilderService) => { - groupComp.onChipSelected(0); - groupFixture.detectChanges(); - - control1 = service.getFormControlById('dc_contributor_author', (groupComp as any).formRef.formGroup, groupComp.formModel) as FormControl; - model1 = service.findById('dc_contributor_author', groupComp.formModel) as DsDynamicInputModel; - - control1.setValue('test author modify'); - (model1 as any).value = new FormFieldMetadataValueObject('test author modify'); - - modelValue = [{ - 'dc.contributor.author': new FormFieldMetadataValueObject('test author modify'), - 'local.contributor.affiliation': new FormFieldMetadataValueObject('test affiliation') - }]; - groupFixture.detectChanges(); - - const buttons = groupFixture.debugElement.nativeElement.querySelectorAll('button'); - const btnEl = buttons[0]; - btnEl.click(); - - groupFixture.detectChanges(); - - expect(groupComp.chips.getChipsItems()).toEqual(modelValue); - expect(groupComp.formCollapsed).toEqual(observableOf(true)); - })); - - it('should delete existing chips item', () => { - groupComp.onChipSelected(0); - groupFixture.detectChanges(); - - const buttons = groupFixture.debugElement.nativeElement.querySelectorAll('button'); - const btnEl = buttons[1]; - btnEl.click(); - - expect(groupComp.chips.getChipsItems()).toEqual([]); - expect(groupComp.formCollapsed).toEqual(observableOf(false)); - }); + // it('should init component properly', inject([FormBuilderService], (service: FormBuilderService) => { + // const formConfig = {rows: groupComp.model.formConfiguration} as SubmissionFormsModel; + // const formModel = service.modelFromConfiguration(formConfig, groupComp.model.scopeUUID, {}, groupComp.model.submissionScope, groupComp.model.readOnly); + // const chips = new Chips([], 'value', 'dc.contributor.author'); + // + // expect(groupComp.formCollapsed).toEqual(observableOf(false)); + // expect(groupComp.formModel.length).toEqual(formModel.length); + // expect(groupComp.chips.getChipsItems()).toEqual(chips.getChipsItems()); + // })); + // + // it('should save a new chips item', () => { + // control1.setValue('test author'); + // (model1 as any).value = new FormFieldMetadataValueObject('test author'); + // control2.setValue('test affiliation'); + // (model2 as any).value = new FormFieldMetadataValueObject('test affiliation'); + // modelValue = [{ + // 'dc.contributor.author': new FormFieldMetadataValueObject('test author'), + // 'local.contributor.affiliation': new FormFieldMetadataValueObject('test affiliation') + // }]; + // groupFixture.detectChanges(); + // + // const buttons = groupFixture.debugElement.nativeElement.querySelectorAll('button'); + // const btnEl = buttons[0]; + // btnEl.click(); + // + // expect(groupComp.chips.getChipsItems()).toEqual(modelValue); + // expect(groupComp.formCollapsed).toEqual(observableOf(true)); + // }); + // + // it('should clear form inputs', () => { + // control1.setValue('test author'); + // (model1 as any).value = new FormFieldMetadataValueObject('test author'); + // control2.setValue('test affiliation'); + // (model2 as any).value = new FormFieldMetadataValueObject('test affiliation'); + // + // groupFixture.detectChanges(); + // + // const buttons = groupFixture.debugElement.nativeElement.querySelectorAll('button'); + // const btnEl = buttons[2]; + // btnEl.click(); + // + // expect(control1.value).toBeNull(); + // expect(control2.value).toBeNull(); + // expect(groupComp.formCollapsed).toEqual(observableOf(false)); + // }); + // }); + // + // describe('when init model value is not empty', () => { + // beforeEach(() => { + // + // groupFixture = TestBed.createComponent(DsDynamicGroupComponent); + // groupComp = groupFixture.componentInstance; // FormComponent test instance + // groupComp.formId = 'testForm'; + // groupComp.group = FORM_GROUP_TEST_GROUP; + // groupComp.model = new DynamicGroupModel(FORM_GROUP_TEST_MODEL_CONFIG); + // modelValue = [{ + // 'dc.contributor.author': new FormFieldMetadataValueObject('test author'), + // 'local.contributor.affiliation': new FormFieldMetadataValueObject('test affiliation') + // }]; + // groupComp.model.value = modelValue; + // groupComp.showErrorMessages = false; + // groupFixture.detectChanges(); + // + // }); + // + // afterEach(() => { + // groupFixture.destroy(); + // groupComp = null; + // }); + // + // it('should init component properly', inject([FormBuilderService], (service: FormBuilderService) => { + // const formConfig = {rows: groupComp.model.formConfiguration} as SubmissionFormsModel; + // const formModel = service.modelFromConfiguration(formConfig, groupComp.model.scopeUUID, {}, groupComp.model.submissionScope, groupComp.model.readOnly); + // const chips = new Chips(modelValue, 'value', 'dc.contributor.author'); + // + // expect(groupComp.formCollapsed).toEqual(observableOf(true)); + // expect(groupComp.formModel.length).toEqual(formModel.length); + // expect(groupComp.chips.getChipsItems()).toEqual(chips.getChipsItems()); + // })); + // + // it('should modify existing chips item', inject([FormBuilderService], (service: FormBuilderService) => { + // groupComp.onChipSelected(0); + // groupFixture.detectChanges(); + // + // control1 = service.getFormControlById('dc_contributor_author', (groupComp as any).formRef.formGroup, groupComp.formModel) as FormControl; + // model1 = service.findById('dc_contributor_author', groupComp.formModel) as DsDynamicInputModel; + // + // control1.setValue('test author modify'); + // (model1 as any).value = new FormFieldMetadataValueObject('test author modify'); + // + // modelValue = [{ + // 'dc.contributor.author': new FormFieldMetadataValueObject('test author modify'), + // 'local.contributor.affiliation': new FormFieldMetadataValueObject('test affiliation') + // }]; + // groupFixture.detectChanges(); + // + // const buttons = groupFixture.debugElement.nativeElement.querySelectorAll('button'); + // const btnEl = buttons[0]; + // btnEl.click(); + // + // groupFixture.detectChanges(); + // + // expect(groupComp.chips.getChipsItems()).toEqual(modelValue); + // expect(groupComp.formCollapsed).toEqual(observableOf(true)); + // })); + // + // it('should delete existing chips item', () => { + // groupComp.onChipSelected(0); + // groupFixture.detectChanges(); + // + // const buttons = groupFixture.debugElement.nativeElement.querySelectorAll('button'); + // const btnEl = buttons[1]; + // btnEl.click(); + // + // expect(groupComp.chips.getChipsItems()).toEqual([]); + // expect(groupComp.formCollapsed).toEqual(observableOf(false)); + // }); }); }); diff --git a/src/app/shared/form/builder/ds-dynamic-form-ui/models/dynamic-group/dynamic-group.components.ts b/src/app/shared/form/builder/ds-dynamic-form-ui/models/dynamic-group/dynamic-group.components.ts index 4857063540..fa3350e43c 100644 --- a/src/app/shared/form/builder/ds-dynamic-form-ui/models/dynamic-group/dynamic-group.components.ts +++ b/src/app/shared/form/builder/ds-dynamic-form-ui/models/dynamic-group/dynamic-group.components.ts @@ -1,4 +1,4 @@ -import {of as observableOf, Observable , Subscription } from 'rxjs'; +import { of as observableOf, Subscription } from 'rxjs'; import { ChangeDetectorRef, Component, @@ -10,7 +10,14 @@ import { Output, ViewChild } from '@angular/core'; -import { DynamicFormControlModel, DynamicFormGroupModel, DynamicInputModel } from '@ng-dynamic-forms/core'; +import { + DynamicFormControlComponent, + DynamicFormControlModel, + DynamicFormGroupModel, + DynamicFormLayoutService, + DynamicFormValidationService, + DynamicInputModel +} from '@ng-dynamic-forms/core'; import { isEqual } from 'lodash'; import { DynamicGroupModel, PLACEHOLDER_PARENT_METADATA } from './dynamic-group.model'; @@ -26,8 +33,6 @@ import { GlobalConfig } from '../../../../../../../config/global-config.interfac import { GLOBAL_CONFIG } from '../../../../../../../config'; import { FormGroup } from '@angular/forms'; import { hasOnlyEmptyProperties } from '../../../../../object.util'; -import { FormFieldMetadataValueObject } from '../../../models/form-field-metadata-value.model'; -import { AuthorityValueModel } from '../../../../../../core/integration/models/authority-value.model'; @Component({ selector: 'ds-dynamic-group', @@ -35,12 +40,12 @@ import { AuthorityValueModel } from '../../../../../../core/integration/models/a templateUrl: './dynamic-group.component.html', animations: [shrinkInOut] }) -export class DsDynamicGroupComponent implements OnDestroy, OnInit { +export class DsDynamicGroupComponent extends DynamicFormControlComponent implements OnDestroy, OnInit { @Input() formId: string; @Input() group: FormGroup; @Input() model: DynamicGroupModel; - @Input() showErrorMessages = false; + // @Input() showErrorMessages = false; @Output() blur: EventEmitter = new EventEmitter(); @Output() change: EventEmitter = new EventEmitter(); @@ -59,11 +64,16 @@ export class DsDynamicGroupComponent implements OnDestroy, OnInit { constructor(@Inject(GLOBAL_CONFIG) protected EnvConfig: GlobalConfig, private formBuilderService: FormBuilderService, private formService: FormService, - private cdr: ChangeDetectorRef) { + private cdr: ChangeDetectorRef, + protected layoutService: DynamicFormLayoutService, + protected validationService: DynamicFormValidationService + ) { + super(layoutService, validationService); + } ngOnInit() { - const config = {rows: this.model.formConfiguration} as SubmissionFormsModel; + const config = { rows: this.model.formConfiguration } as SubmissionFormsModel; if (!this.model.isEmpty()) { this.formCollapsed = observableOf(true); } diff --git a/src/app/shared/form/builder/ds-dynamic-form-ui/models/list/dynamic-list.component.spec.ts b/src/app/shared/form/builder/ds-dynamic-form-ui/models/list/dynamic-list.component.spec.ts index 6a765eba4a..adfd087033 100644 --- a/src/app/shared/form/builder/ds-dynamic-form-ui/models/list/dynamic-list.component.spec.ts +++ b/src/app/shared/form/builder/ds-dynamic-form-ui/models/list/dynamic-list.component.spec.ts @@ -9,7 +9,12 @@ import { DsDynamicListComponent } from './dynamic-list.component'; import { DynamicListCheckboxGroupModel } from './dynamic-list-checkbox-group.model'; import { AuthorityOptions } from '../../../../../../core/integration/models/authority-options.model'; import { FormBuilderService } from '../../../form-builder.service'; -import { DynamicFormControlLayout, DynamicFormsCoreModule, DynamicFormValidationService } from '@ng-dynamic-forms/core'; +import { + DynamicFormControlLayout, + DynamicFormLayoutService, + DynamicFormsCoreModule, + DynamicFormValidationService +} from '@ng-dynamic-forms/core'; import { DynamicFormsNGBootstrapUIModule } from '@ng-dynamic-forms/ui-ng-bootstrap'; import { AuthorityService } from '../../../../../../core/integration/authority.service'; import { AuthorityServiceStub } from '../../../../../testing/authority-service-stub'; @@ -90,12 +95,13 @@ describe('DsDynamicListComponent test suite', () => { TestComponent, ], // declare the test component providers: [ - AuthorityService, ChangeDetectorRef, DsDynamicListComponent, DynamicFormValidationService, FormBuilderService, {provide: AuthorityService, useValue: authorityServiceStub}, + {provide: DynamicFormLayoutService, useValue: {}}, + {provide: DynamicFormValidationService, useValue: {}} ], schemas: [CUSTOM_ELEMENTS_SCHEMA] }); @@ -110,7 +116,6 @@ describe('DsDynamicListComponent test suite', () => { [bindId]="bindId" [group]="group" [model]="model" - [showErrorMessages]="showErrorMessages" (blur)="onBlur($event)" (change)="onValueChange($event)" (focus)="onFocus($event)">`; diff --git a/src/app/shared/form/builder/ds-dynamic-form-ui/models/list/dynamic-list.component.ts b/src/app/shared/form/builder/ds-dynamic-form-ui/models/list/dynamic-list.component.ts index 15b60235ce..f5285ffa87 100644 --- a/src/app/shared/form/builder/ds-dynamic-form-ui/models/list/dynamic-list.component.ts +++ b/src/app/shared/form/builder/ds-dynamic-form-ui/models/list/dynamic-list.component.ts @@ -7,7 +7,11 @@ import { IntegrationSearchOptions } from '../../../../../../core/integration/mod import { hasValue, isNotEmpty } from '../../../../../empty.util'; import { DynamicListCheckboxGroupModel } from './dynamic-list-checkbox-group.model'; import { FormBuilderService } from '../../../form-builder.service'; -import { DynamicCheckboxModel } from '@ng-dynamic-forms/core'; +import { + DynamicCheckboxModel, + DynamicFormControlComponent, DynamicFormLayoutService, + DynamicFormValidationService +} from '@ng-dynamic-forms/core'; import { AuthorityValueModel } from '../../../../../../core/integration/models/authority-value.model'; import { DynamicListRadioGroupModel } from './dynamic-list-radio-group.model'; import { IntegrationData } from '../../../../../../core/integration/integration-data'; @@ -25,11 +29,11 @@ export interface ListItem { templateUrl: './dynamic-list.component.html' }) -export class DsDynamicListComponent implements OnInit { +export class DsDynamicListComponent extends DynamicFormControlComponent implements OnInit { @Input() bindId = true; @Input() group: FormGroup; @Input() model: DynamicListCheckboxGroupModel | DynamicListRadioGroupModel; - @Input() showErrorMessages = false; + // @Input() showErrorMessages = false; @Output() blur: EventEmitter = new EventEmitter(); @Output() change: EventEmitter = new EventEmitter(); @@ -41,7 +45,11 @@ export class DsDynamicListComponent implements OnInit { constructor(private authorityService: AuthorityService, private cdr: ChangeDetectorRef, - private formBuilderService: FormBuilderService) { + private formBuilderService: FormBuilderService, + protected layoutService: DynamicFormLayoutService, + protected validationService: DynamicFormValidationService + ) { + super(layoutService, validationService); } ngOnInit() { @@ -110,7 +118,10 @@ export class DsDynamicListComponent implements OnInit { if (this.model.repeatable) { this.formBuilderService.addFormGroupControl(listGroup, (this.model as DynamicListCheckboxGroupModel), new DynamicCheckboxModel(item)); } else { - (this.model as DynamicListRadioGroupModel).options.push({label: item.label, value: option}); + (this.model as DynamicListRadioGroupModel).options.push({ + label: item.label, + value: option + }); } tempList.push(item); itemsPerGroup++; diff --git a/src/app/shared/form/builder/ds-dynamic-form-ui/models/lookup/dynamic-lookup.component.spec.ts b/src/app/shared/form/builder/ds-dynamic-form-ui/models/lookup/dynamic-lookup.component.spec.ts index ce45453bee..6ea627a1f9 100644 --- a/src/app/shared/form/builder/ds-dynamic-form-ui/models/lookup/dynamic-lookup.component.spec.ts +++ b/src/app/shared/form/builder/ds-dynamic-form-ui/models/lookup/dynamic-lookup.component.spec.ts @@ -6,7 +6,11 @@ import { async, ComponentFixture, fakeAsync, inject, TestBed, tick, } from '@ang import { NgbModule } from '@ng-bootstrap/ng-bootstrap'; import { AuthorityOptions } from '../../../../../../core/integration/models/authority-options.model'; -import { DynamicFormsCoreModule, DynamicFormValidationService } from '@ng-dynamic-forms/core'; +import { + DynamicFormLayoutService, + DynamicFormsCoreModule, + DynamicFormValidationService +} from '@ng-dynamic-forms/core'; import { DynamicFormsNGBootstrapUIModule } from '@ng-dynamic-forms/ui-ng-bootstrap'; import { AuthorityService } from '../../../../../../core/integration/authority.service'; import { AuthorityServiceStub } from '../../../../../testing/authority-service-stub'; @@ -102,11 +106,9 @@ describe('Dynamic Lookup component', () => { providers: [ ChangeDetectorRef, DsDynamicLookupComponent, - DynamicFormValidationService, - FormBuilderService, - FormComponent, - FormService, {provide: AuthorityService, useValue: authorityServiceStub}, + {provide: DynamicFormLayoutService, useValue: {}}, + {provide: DynamicFormValidationService, useValue: {}} ], schemas: [CUSTOM_ELEMENTS_SCHEMA] }); @@ -121,7 +123,6 @@ describe('Dynamic Lookup component', () => { [bindId]="bindId" [group]="group" [model]="model" - [showErrorMessages]="showErrorMessages" (blur)="onBlur($event)" (change)="onValueChange($event)" (focus)="onFocus($event)">`; diff --git a/src/app/shared/form/builder/ds-dynamic-form-ui/models/lookup/dynamic-lookup.component.ts b/src/app/shared/form/builder/ds-dynamic-form-ui/models/lookup/dynamic-lookup.component.ts index b184b4f4db..abe14dfb49 100644 --- a/src/app/shared/form/builder/ds-dynamic-form-ui/models/lookup/dynamic-lookup.component.ts +++ b/src/app/shared/form/builder/ds-dynamic-form-ui/models/lookup/dynamic-lookup.component.ts @@ -13,17 +13,22 @@ import { Subscription } from 'rxjs'; import { FormFieldMetadataValueObject } from '../../../models/form-field-metadata-value.model'; import { AuthorityValueModel } from '../../../../../../core/integration/models/authority-value.model'; import { DynamicLookupNameModel } from './dynamic-lookup-name.model'; +import { + DynamicFormControlComponent, + DynamicFormLayoutService, + DynamicFormValidationService +} from '@ng-dynamic-forms/core'; @Component({ selector: 'ds-dynamic-lookup', styleUrls: ['./dynamic-lookup.component.scss'], templateUrl: './dynamic-lookup.component.html' }) -export class DsDynamicLookupComponent implements OnDestroy, OnInit { +export class DsDynamicLookupComponent extends DynamicFormControlComponent implements OnDestroy, OnInit { @Input() bindId = true; @Input() group: FormGroup; @Input() model: DynamicLookupModel | DynamicLookupNameModel; - @Input() showErrorMessages = false; + // @Input() showErrorMessages = false; @Output() blur: EventEmitter = new EventEmitter(); @Output() change: EventEmitter = new EventEmitter(); @@ -39,7 +44,11 @@ export class DsDynamicLookupComponent implements OnDestroy, OnInit { protected sub: Subscription; constructor(private authorityService: AuthorityService, - private cdr: ChangeDetectorRef) { + private cdr: ChangeDetectorRef, + protected layoutService: DynamicFormLayoutService, + protected validationService: DynamicFormValidationService + ) { + super(layoutService, validationService); } ngOnInit() { diff --git a/src/app/shared/form/builder/ds-dynamic-form-ui/models/scrollable-dropdown/dynamic-scrollable-dropdown.component.spec.ts b/src/app/shared/form/builder/ds-dynamic-form-ui/models/scrollable-dropdown/dynamic-scrollable-dropdown.component.spec.ts index 49cdb5d890..6902530956 100644 --- a/src/app/shared/form/builder/ds-dynamic-form-ui/models/scrollable-dropdown/dynamic-scrollable-dropdown.component.spec.ts +++ b/src/app/shared/form/builder/ds-dynamic-form-ui/models/scrollable-dropdown/dynamic-scrollable-dropdown.component.spec.ts @@ -6,7 +6,11 @@ import { async, ComponentFixture, fakeAsync, inject, TestBed, tick, } from '@ang import { NgbModule } from '@ng-bootstrap/ng-bootstrap'; import { AuthorityOptions } from '../../../../../../core/integration/models/authority-options.model'; -import { DynamicFormsCoreModule } from '@ng-dynamic-forms/core'; +import { + DynamicFormLayoutService, + DynamicFormsCoreModule, + DynamicFormValidationService +} from '@ng-dynamic-forms/core'; import { DynamicFormsNGBootstrapUIModule } from '@ng-dynamic-forms/ui-ng-bootstrap'; import { AuthorityService } from '../../../../../../core/integration/authority.service'; import { AuthorityServiceStub } from '../../../../../testing/authority-service-stub'; @@ -77,6 +81,8 @@ describe('Dynamic Dynamic Scrollable Dropdown component', () => { ChangeDetectorRef, DsDynamicScrollableDropdownComponent, {provide: AuthorityService, useValue: authorityServiceStub}, + {provide: DynamicFormLayoutService, useValue: {}}, + {provide: DynamicFormValidationService, useValue: {}} ], schemas: [CUSTOM_ELEMENTS_SCHEMA] }); @@ -90,7 +96,6 @@ describe('Dynamic Dynamic Scrollable Dropdown component', () => { `; diff --git a/src/app/shared/form/builder/ds-dynamic-form-ui/models/scrollable-dropdown/dynamic-scrollable-dropdown.component.ts b/src/app/shared/form/builder/ds-dynamic-form-ui/models/scrollable-dropdown/dynamic-scrollable-dropdown.component.ts index 8a1bf21b64..4b259b6cce 100644 --- a/src/app/shared/form/builder/ds-dynamic-form-ui/models/scrollable-dropdown/dynamic-scrollable-dropdown.component.ts +++ b/src/app/shared/form/builder/ds-dynamic-form-ui/models/scrollable-dropdown/dynamic-scrollable-dropdown.component.ts @@ -11,17 +11,22 @@ import { IntegrationSearchOptions } from '../../../../../../core/integration/mod import { IntegrationData } from '../../../../../../core/integration/integration-data'; import { AuthorityValueModel } from '../../../../../../core/integration/models/authority-value.model'; import { NgbDropdown } from '@ng-bootstrap/ng-bootstrap'; +import { + DynamicFormControlComponent, + DynamicFormLayoutService, + DynamicFormValidationService +} from '@ng-dynamic-forms/core'; @Component({ selector: 'ds-dynamic-scrollable-dropdown', styleUrls: ['./dynamic-scrollable-dropdown.component.scss'], templateUrl: './dynamic-scrollable-dropdown.component.html' }) -export class DsDynamicScrollableDropdownComponent implements OnInit { +export class DsDynamicScrollableDropdownComponent extends DynamicFormControlComponent implements OnInit { @Input() bindId = true; @Input() group: FormGroup; @Input() model: DynamicScrollableDropdownModel; - @Input() showErrorMessages = false; + // @Input() showErrorMessages = false; @Output() blur: EventEmitter = new EventEmitter(); @Output() change: EventEmitter = new EventEmitter(); @@ -33,7 +38,13 @@ export class DsDynamicScrollableDropdownComponent implements OnInit { protected searchOptions: IntegrationSearchOptions; - constructor(private authorityService: AuthorityService, private cdr: ChangeDetectorRef) {} + constructor(private authorityService: AuthorityService, + private cdr: ChangeDetectorRef, + protected layoutService: DynamicFormLayoutService, + protected validationService: DynamicFormValidationService + ) { + super(layoutService, validationService); + } ngOnInit() { this.searchOptions = new IntegrationSearchOptions( diff --git a/src/app/shared/form/builder/ds-dynamic-form-ui/models/tag/dynamic-tag.component.spec.ts b/src/app/shared/form/builder/ds-dynamic-form-ui/models/tag/dynamic-tag.component.spec.ts index fc5bb8082d..5a6ec1c277 100644 --- a/src/app/shared/form/builder/ds-dynamic-form-ui/models/tag/dynamic-tag.component.spec.ts +++ b/src/app/shared/form/builder/ds-dynamic-form-ui/models/tag/dynamic-tag.component.spec.ts @@ -4,7 +4,11 @@ import { FormControl, FormGroup, FormsModule, ReactiveFormsModule } from '@angul import { async, ComponentFixture, fakeAsync, flush, inject, TestBed, } from '@angular/core/testing'; import { of as observableOf } from 'rxjs'; -import { DynamicFormsCoreModule } from '@ng-dynamic-forms/core'; +import { + DynamicFormLayoutService, + DynamicFormsCoreModule, + DynamicFormValidationService +} from '@ng-dynamic-forms/core'; import { DynamicFormsNGBootstrapUIModule } from '@ng-dynamic-forms/ui-ng-bootstrap'; import { NgbModule, NgbTypeaheadSelectItemEvent } from '@ng-bootstrap/ng-bootstrap'; @@ -86,6 +90,8 @@ describe('DsDynamicTagComponent test suite', () => { DsDynamicTagComponent, {provide: AuthorityService, useValue: authorityServiceStub}, {provide: GLOBAL_CONFIG, useValue: {} as GlobalConfig}, + {provide: DynamicFormLayoutService, useValue: {}}, + {provide: DynamicFormValidationService, useValue: {}} ], schemas: [CUSTOM_ELEMENTS_SCHEMA] }); @@ -99,7 +105,6 @@ describe('DsDynamicTagComponent test suite', () => { `; diff --git a/src/app/shared/form/builder/ds-dynamic-form-ui/models/tag/dynamic-tag.component.ts b/src/app/shared/form/builder/ds-dynamic-form-ui/models/tag/dynamic-tag.component.ts index 1ccbd21f5c..ce8d85b5e4 100644 --- a/src/app/shared/form/builder/ds-dynamic-form-ui/models/tag/dynamic-tag.component.ts +++ b/src/app/shared/form/builder/ds-dynamic-form-ui/models/tag/dynamic-tag.component.ts @@ -14,17 +14,22 @@ import { hasValue, isNotEmpty } from '../../../../../empty.util'; import { isEqual } from 'lodash'; import { GlobalConfig } from '../../../../../../../config/global-config.interface'; import { GLOBAL_CONFIG } from '../../../../../../../config'; +import { + DynamicFormControlComponent, + DynamicFormLayoutService, + DynamicFormValidationService +} from '@ng-dynamic-forms/core'; @Component({ selector: 'ds-dynamic-tag', styleUrls: ['./dynamic-tag.component.scss'], templateUrl: './dynamic-tag.component.html' }) -export class DsDynamicTagComponent implements OnInit { +export class DsDynamicTagComponent extends DynamicFormControlComponent implements OnInit { @Input() bindId = true; @Input() group: FormGroup; @Input() model: DynamicTagModel; - @Input() showErrorMessages = false; + // @Input() showErrorMessages = false; @Output() blur: EventEmitter = new EventEmitter(); @Output() change: EventEmitter = new EventEmitter(); @@ -72,7 +77,11 @@ export class DsDynamicTagComponent implements OnInit { constructor(@Inject(GLOBAL_CONFIG) protected EnvConfig: GlobalConfig, private authorityService: AuthorityService, - private cdr: ChangeDetectorRef) { + private cdr: ChangeDetectorRef, + protected layoutService: DynamicFormLayoutService, + protected validationService: DynamicFormValidationService + ) { + super(layoutService, validationService); } ngOnInit() { diff --git a/src/app/shared/form/builder/ds-dynamic-form-ui/models/typeahead/dynamic-typeahead.component.spec.ts b/src/app/shared/form/builder/ds-dynamic-form-ui/models/typeahead/dynamic-typeahead.component.spec.ts index daaf5c47d6..eb50ae732f 100644 --- a/src/app/shared/form/builder/ds-dynamic-form-ui/models/typeahead/dynamic-typeahead.component.spec.ts +++ b/src/app/shared/form/builder/ds-dynamic-form-ui/models/typeahead/dynamic-typeahead.component.spec.ts @@ -4,10 +4,13 @@ import { FormControl, FormGroup, FormsModule, ReactiveFormsModule } from '@angul import { async, ComponentFixture, fakeAsync, inject, TestBed, } from '@angular/core/testing'; import { By } from '@angular/platform-browser'; import { of as observableOf } from 'rxjs'; -import 'rxjs/add/observable/of'; import { AuthorityOptions } from '../../../../../../core/integration/models/authority-options.model'; -import { DynamicFormsCoreModule } from '@ng-dynamic-forms/core'; +import { + DynamicFormLayoutService, + DynamicFormsCoreModule, + DynamicFormValidationService +} from '@ng-dynamic-forms/core'; import { DynamicFormsNGBootstrapUIModule } from '@ng-dynamic-forms/ui-ng-bootstrap'; import { AuthorityService } from '../../../../../../core/integration/authority.service'; import { AuthorityServiceStub } from '../../../../../testing/authority-service-stub'; @@ -70,7 +73,8 @@ describe('DsDynamicTypeaheadComponent test suite', () => { ChangeDetectorRef, DsDynamicTypeaheadComponent, {provide: AuthorityService, useValue: authorityServiceStub}, - {provide: GLOBAL_CONFIG, useValue: {} as GlobalConfig}, + {provide: DynamicFormLayoutService, useValue: {}}, + {provide: DynamicFormValidationService, useValue: {}} ], schemas: [CUSTOM_ELEMENTS_SCHEMA] }); @@ -84,7 +88,6 @@ describe('DsDynamicTypeaheadComponent test suite', () => { `; diff --git a/src/app/shared/form/builder/ds-dynamic-form-ui/models/typeahead/dynamic-typeahead.component.ts b/src/app/shared/form/builder/ds-dynamic-form-ui/models/typeahead/dynamic-typeahead.component.ts index 01285e1228..482820931f 100644 --- a/src/app/shared/form/builder/ds-dynamic-form-ui/models/typeahead/dynamic-typeahead.component.ts +++ b/src/app/shared/form/builder/ds-dynamic-form-ui/models/typeahead/dynamic-typeahead.component.ts @@ -11,13 +11,18 @@ import { DynamicTypeaheadModel } from './dynamic-typeahead.model'; import { IntegrationSearchOptions } from '../../../../../../core/integration/models/integration-options.model'; import { isEmpty, isNotEmpty } from '../../../../../empty.util'; import { FormFieldMetadataValueObject } from '../../../models/form-field-metadata-value.model'; +import { + DynamicFormControlComponent, + DynamicFormLayoutService, + DynamicFormValidationService +} from '@ng-dynamic-forms/core'; @Component({ selector: 'ds-dynamic-typeahead', styleUrls: ['./dynamic-typeahead.component.scss'], templateUrl: './dynamic-typeahead.component.html' }) -export class DsDynamicTypeaheadComponent implements OnInit { +export class DsDynamicTypeaheadComponent extends DynamicFormControlComponent implements OnInit { @Input() bindId = true; @Input() group: FormGroup; @Input() model: DynamicTypeaheadModel; @@ -67,7 +72,12 @@ export class DsDynamicTypeaheadComponent implements OnInit { tap(() => this.changeSearchingStatus(false)), merge(this.hideSearchingWhenUnsubscribed),); - constructor(private authorityService: AuthorityService, private cdr: ChangeDetectorRef) { + constructor(private authorityService: AuthorityService, + private cdr: ChangeDetectorRef, + protected layoutService: DynamicFormLayoutService, + protected validationService: DynamicFormValidationService + ) { + super(layoutService, validationService); } ngOnInit() { diff --git a/src/app/shared/form/builder/form-builder.service.spec.ts b/src/app/shared/form/builder/form-builder.service.spec.ts index c06273a564..8b414edc9e 100644 --- a/src/app/shared/form/builder/form-builder.service.spec.ts +++ b/src/app/shared/form/builder/form-builder.service.spec.ts @@ -49,6 +49,7 @@ import { FormFieldMetadataValueObject } from './models/form-field-metadata-value import { DynamicConcatModel } from './ds-dynamic-form-ui/models/ds-dynamic-concat.model'; import { DynamicLookupNameModel } from './ds-dynamic-form-ui/models/lookup/dynamic-lookup-name.model'; import { DynamicRowArrayModel } from './ds-dynamic-form-ui/models/ds-dynamic-row-array-model'; +import { getMockFormBuilderService } from '../../mocks/mock-form-builder-service'; describe('FormBuilderService test suite', () => { @@ -69,9 +70,7 @@ describe('FormBuilderService test suite', () => { TestBed.configureTestingModule({ imports: [ReactiveFormsModule], providers: [ - FormBuilderService, - DynamicFormService, - DynamicFormValidationService, + {provide: FormBuilderService, useValue: getMockFormBuilderService()}, {provide: NG_VALIDATORS, useValue: testValidator, multi: true}, {provide: NG_ASYNC_VALIDATORS, useValue: testAsyncValidator, multi: true} ] diff --git a/src/app/shared/form/form.component.spec.ts b/src/app/shared/form/form.component.spec.ts index 53cc1d7736..3c204fa255 100644 --- a/src/app/shared/form/form.component.spec.ts +++ b/src/app/shared/form/form.component.spec.ts @@ -3,15 +3,14 @@ import { async, ComponentFixture, inject, TestBed, } from '@angular/core/testing import { CommonModule } from '@angular/common'; import { BrowserModule } from '@angular/platform-browser'; import { FormsModule, ReactiveFormsModule } from '@angular/forms'; -import 'rxjs/add/observable/of'; import { DynamicFormArrayModel, DynamicFormControlEvent, DynamicFormControlModel, - DynamicFormValidationService, DynamicInputModel } from '@ng-dynamic-forms/core'; -import { Store } from '@ngrx/store'; +import { ActionsSubject, Store } from '@ngrx/store'; +import { of as observableOf } from 'rxjs'; import { NgbModule } from '@ng-bootstrap/ng-bootstrap'; import { TranslateModule } from '@ngx-translate/core'; @@ -19,11 +18,12 @@ import { FormComponent } from './form.component'; import { FormService } from './form.service'; import { FormBuilderService } from './builder/form-builder.service'; import { FormState } from './form.reducer'; -import { FormChangeAction, FormStatusChangeAction } from './form.actions'; -import { MockStore } from '../testing/mock-store'; +import { FormAddError, FormChangeAction, FormStatusChangeAction } from './form.actions'; import { FormFieldMetadataValueObject } from './builder/models/form-field-metadata-value.model'; import { GLOBAL_CONFIG } from '../../../config'; import { createTestComponent } from '../testing/utils'; +import { getMockFormService } from '../mocks/mock-form-service'; +import { getMockFormBuilderService } from '../mocks/mock-form-builder-service'; export const TEST_FORM_MODEL = [ @@ -93,7 +93,7 @@ export const TEST_FORM_MODEL_WITH_ARRAY = [ }) ]; -describe('FormComponent test suite', () => { +fdescribe('FormComponent test suite', () => { let testComp: TestComponent; let formComp: FormComponent; let testFixture: ComponentFixture; @@ -122,7 +122,7 @@ describe('FormComponent test suite', () => { }; let html; - const store: MockStore = new MockStore(formState); + const store = new Store(observableOf({}), new ActionsSubject(), undefined); // async beforeEach beforeEach(async(() => { @@ -142,10 +142,9 @@ describe('FormComponent test suite', () => { ], // declare the test component providers: [ ChangeDetectorRef, - DynamicFormValidationService, - FormBuilderService, + {provide: FormBuilderService, useValue: getMockFormBuilderService()}, FormComponent, - FormService, + {provide: FormService, useValue: getMockFormService()}, {provide: GLOBAL_CONFIG, useValue: config}, { provide: Store, useValue: store @@ -200,18 +199,17 @@ describe('FormComponent test suite', () => { }); - it('should display form errors when errors are added to the state', () => { - const errors = [{ + fit('should display form errors when errors are added to the state', () => { + const error = { fieldId: 'dc_title', fieldIndex: 0, message: 'error.validation.required' - }]; + }; - formState.testForm.errors = errors; - store.nextState(formState); + store.dispatch(new FormAddError(formComp.formId, error.fieldId, error.fieldIndex, error.message)); formFixture.detectChanges(); - expect((formComp as any).formErrors).toEqual(errors); + expect((formComp as any).formErrors[0]).toEqual(error); }); diff --git a/src/app/shared/form/form.reducer.ts b/src/app/shared/form/form.reducer.ts index 1d44375c0d..1a5d2da30b 100644 --- a/src/app/shared/form/form.reducer.ts +++ b/src/app/shared/form/form.reducer.ts @@ -30,6 +30,7 @@ export interface FormState { const initialState: FormState = Object.create(null); export function formReducer(state = initialState, action: FormAction): FormState { + console.log('TEST'); switch (action.type) { case FormActionTypes.FORM_INIT: { @@ -67,6 +68,7 @@ export function formReducer(state = initialState, action: FormAction): FormState } function addFormErrors(state: FormState, action: FormAddError) { + console.log(state); const formId = action.payload.formId; if (hasValue(state[formId])) { const error: FormError = { diff --git a/src/app/shared/form/form.service.spec.ts b/src/app/shared/form/form.service.spec.ts index 06125c9034..adc868c308 100644 --- a/src/app/shared/form/form.service.spec.ts +++ b/src/app/shared/form/form.service.spec.ts @@ -3,7 +3,8 @@ import { async, inject, TestBed } from '@angular/core/testing'; import { FormGroup } from '@angular/forms'; import { - DynamicFormControlModel, DynamicFormGroupModel, + DynamicFormControlModel, + DynamicFormGroupModel, DynamicFormService, DynamicFormValidationService, DynamicInputModel @@ -13,7 +14,7 @@ import { FormService } from './form.service'; import { FormBuilderService } from './builder/form-builder.service'; import { AppState } from '../../app.reducer'; import { formReducer } from './form.reducer'; -import { GlobalConfig } from '../../../config/global-config.interface'; +import { getMockFormBuilderService } from '../mocks/mock-form-builder-service'; describe('FormService test suite', () => { const config = { @@ -93,9 +94,7 @@ describe('FormService test suite', () => { StoreModule.forRoot({formReducer}) ], providers: [ - DynamicFormService, - DynamicFormValidationService, - FormBuilderService, + {provide: FormBuilderService, useValue: getMockFormBuilderService()}, ] }).compileComponents(); })); diff --git a/src/app/shared/mocks/mock-form-builder-service.ts b/src/app/shared/mocks/mock-form-builder-service.ts new file mode 100644 index 0000000000..89a4051f35 --- /dev/null +++ b/src/app/shared/mocks/mock-form-builder-service.ts @@ -0,0 +1,18 @@ +import { FormBuilderService } from '../form/builder/form-builder.service'; +import { FormControl, FormGroup } from '@angular/forms'; + +export function getMockFormBuilderService(): FormBuilderService { + return jasmine.createSpyObj('FormService', { + modelFromConfiguration: [], + createFormGroup: new FormGroup({}), + getValueFromModel: {}, + getFormControlById: new FormControl(), + findById: {}, + getPath: ['test', 'path'], + clearAllModelsValue : {}, + insertFormArrayGroup: {}, + isQualdrop: false + + }); + +} diff --git a/src/app/shared/mocks/mock-form-service.ts b/src/app/shared/mocks/mock-form-service.ts new file mode 100644 index 0000000000..0ab3fbffcc --- /dev/null +++ b/src/app/shared/mocks/mock-form-service.ts @@ -0,0 +1,12 @@ +import { FormService } from '../form/form.service'; + +export function getMockFormService( + id$: string = 'random_id' +): FormService { + return jasmine.createSpyObj('FormService', { + getUniqueId: id$, + resetForm: {}, + validateAllFormFields: {} + }); + +} diff --git a/src/app/shared/mocks/mock-store.ts b/src/app/shared/mocks/mock-store.ts index c27133c586..7a6ca772f2 100644 --- a/src/app/shared/mocks/mock-store.ts +++ b/src/app/shared/mocks/mock-store.ts @@ -1,15 +1,4 @@ import { Store } from '@ngrx/store'; -import { Observable } from 'rxjs'; +import { of as observableOf } from 'rxjs'; + -export function getMockStore(): Store { - return jasmine.createSpyObj('store', [ - 'select', - 'dispatch', - 'lift', - 'next', - 'error', - 'complete', - 'addReducer', - 'removeReducer' - ]); -} diff --git a/src/app/shared/notifications/notifications.service.spec.ts b/src/app/shared/notifications/notifications.service.spec.ts index f59f48f92d..a9f354dc4d 100644 --- a/src/app/shared/notifications/notifications.service.spec.ts +++ b/src/app/shared/notifications/notifications.service.spec.ts @@ -5,7 +5,6 @@ import { NotificationComponent } from './notification/notification.component'; import { Store, StoreModule } from '@ngrx/store'; import { notificationsReducer } from './notifications.reducers'; import { of as observableOf } from 'rxjs'; -import 'rxjs/add/observable/of'; import { NewNotificationAction, RemoveAllNotificationsAction, diff --git a/src/app/shared/number-picker/number-picker.component.spec.ts b/src/app/shared/number-picker/number-picker.component.spec.ts index 3f6ae441f8..3703be97df 100644 --- a/src/app/shared/number-picker/number-picker.component.spec.ts +++ b/src/app/shared/number-picker/number-picker.component.spec.ts @@ -156,7 +156,6 @@ class TestComponent { public max = 100; public min = 0; public initValue = 0; - public showErrorMessages = false; public size = 4; public value; diff --git a/webpack/webpack.test.js b/webpack/webpack.test.js index d635e8196b..3c3c46b84c 100644 --- a/webpack/webpack.test.js +++ b/webpack/webpack.test.js @@ -22,7 +22,7 @@ const ENV = process.env.ENV = process.env.NODE_ENV = 'test'; */ module.exports = function (options) { return { - + mode: 'development', /** * Source map for Karma from the help of karma-sourcemap-loader & karma-webpack * diff --git a/yarn.lock b/yarn.lock index 4268851786..6129ef4e7e 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2,6 +2,13 @@ # yarn lockfile v1 +"@angular-devkit/architect@0.7.5": + version "0.7.5" + resolved "https://registry.yarnpkg.com/@angular-devkit/architect/-/architect-0.7.5.tgz#e2d856b671fe8b0615db1efc144a7f75b55fb6e1" + dependencies: + "@angular-devkit/core" "0.7.5" + rxjs "^6.0.0" + "@angular-devkit/core@0.7.5": version "0.7.5" resolved "https://registry.yarnpkg.com/@angular-devkit/core/-/core-0.7.5.tgz#49f7854ccadf3ddda8d0ea4359543a1cbdc6854d" @@ -11,12 +18,34 @@ rxjs "^6.0.0" source-map "^0.5.6" +"@angular-devkit/schematics@0.7.5": + version "0.7.5" + resolved "https://registry.yarnpkg.com/@angular-devkit/schematics/-/schematics-0.7.5.tgz#f46b121f29cb40ad6095285d27a515114a56c5d6" + dependencies: + "@angular-devkit/core" "0.7.5" + rxjs "^6.0.0" + "@angular/animations@^6.1.4": version "6.1.6" resolved "https://registry.yarnpkg.com/@angular/animations/-/animations-6.1.6.tgz#25a9cd87303aec5556c20631d087447de2330e87" dependencies: tslib "^1.9.0" +"@angular/cli@^6.1.5": + version "6.1.5" + resolved "https://registry.yarnpkg.com/@angular/cli/-/cli-6.1.5.tgz#312c062631285ff06fd07ecde8afe22cdef5a0e1" + dependencies: + "@angular-devkit/architect" "0.7.5" + "@angular-devkit/core" "0.7.5" + "@angular-devkit/schematics" "0.7.5" + "@schematics/angular" "0.7.5" + "@schematics/update" "0.7.5" + opn "^5.3.0" + rxjs "^6.0.0" + semver "^5.1.0" + symbol-observable "^1.2.0" + yargs-parser "^10.0.0" + "@angular/common@^6.1.4": version "6.1.6" resolved "https://registry.yarnpkg.com/@angular/common/-/common-6.1.6.tgz#16597d89dddd72a606d3cc7125ffa30a87f5ee09" @@ -123,10 +152,18 @@ version "6.1.0" resolved "https://registry.yarnpkg.com/@ngrx/effects/-/effects-6.1.0.tgz#3c1e1ab1e5a86c6d9c29d4f3771e42cc9bd8576c" +"@ngrx/entity@^6.1.0": + version "6.1.0" + resolved "https://registry.yarnpkg.com/@ngrx/entity/-/entity-6.1.0.tgz#9ea34beef25e458b45638095875b2548d484df9f" + "@ngrx/router-store@^6.1.0": version "6.1.0" resolved "https://registry.yarnpkg.com/@ngrx/router-store/-/router-store-6.1.0.tgz#a225de3fbb262429561d722e139dde7efdcf0cea" +"@ngrx/schematics@^6.1.0": + version "6.1.0" + resolved "https://registry.yarnpkg.com/@ngrx/schematics/-/schematics-6.1.0.tgz#4e784da5502829700895ca87d4cc5da93bf3ec84" + "@ngrx/store-devtools@^6.1.0": version "6.1.0" resolved "https://registry.yarnpkg.com/@ngrx/store-devtools/-/store-devtools-6.1.0.tgz#cf65a3149628dc37badd094204484dde9ba14200" @@ -170,6 +207,25 @@ version "1.1.1" resolved "https://registry.yarnpkg.com/@nodelib/fs.stat/-/fs.stat-1.1.1.tgz#53f349bb986ab273d601175aa1b25a655ab90ee3" +"@schematics/angular@0.7.5", "@schematics/angular@^0.7.5": + version "0.7.5" + resolved "https://registry.yarnpkg.com/@schematics/angular/-/angular-0.7.5.tgz#ccb5ce587161b24042195e100be556ae19b3b7f6" + dependencies: + "@angular-devkit/core" "0.7.5" + "@angular-devkit/schematics" "0.7.5" + typescript ">=2.6.2 <2.10" + +"@schematics/update@0.7.5": + version "0.7.5" + resolved "https://registry.yarnpkg.com/@schematics/update/-/update-0.7.5.tgz#c9cc68c4464ea4e29a2f3a7254172df768c86ac4" + dependencies: + "@angular-devkit/core" "0.7.5" + "@angular-devkit/schematics" "0.7.5" + npm-registry-client "^8.5.1" + rxjs "^6.0.0" + semver "^5.3.0" + semver-intersect "^1.1.2" + "@types/acorn@^4.0.3": version "4.0.3" resolved "https://registry.yarnpkg.com/@types/acorn/-/acorn-4.0.3.tgz#d1f3e738dde52536f9aad3d3380d14e448820afd" @@ -468,13 +524,6 @@ "@webassemblyjs/wast-parser" "1.5.13" long "^3.2.0" -JSONStream@^1.0.3: - version "1.3.4" - resolved "https://registry.yarnpkg.com/JSONStream/-/JSONStream-1.3.4.tgz#615bb2adb0cd34c8f4c447b5f6512fa1d8f16a2e" - dependencies: - jsonparse "^1.2.0" - through ">=2.2.7 <3" - abbrev@1: version "1.1.1" resolved "https://registry.yarnpkg.com/abbrev/-/abbrev-1.1.1.tgz#f8f2c887ad10bf67f634f005b6987fed3179aac8" @@ -496,22 +545,10 @@ acorn-dynamic-import@^3.0.0: dependencies: acorn "^5.0.0" -acorn-node@^1.2.0, acorn-node@^1.3.0, acorn-node@^1.5.2: - version "1.5.2" - resolved "https://registry.yarnpkg.com/acorn-node/-/acorn-node-1.5.2.tgz#2ca723df19d997b05824b69f6c7fb091fc42c322" - dependencies: - acorn "^5.7.1" - acorn-dynamic-import "^3.0.0" - xtend "^4.0.1" - -acorn@^5.0.0, acorn@^5.2.1, acorn@^5.3.0, acorn@^5.5.0, acorn@^5.6.2, acorn@^5.7.1: +acorn@^5.0.0, acorn@^5.3.0, acorn@^5.5.0, acorn@^5.6.2: version "5.7.2" resolved "https://registry.yarnpkg.com/acorn/-/acorn-5.7.2.tgz#91fa871883485d06708800318404e72bfb26dcc5" -addressparser@1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/addressparser/-/addressparser-1.0.1.tgz#47afbe1a2a9262191db6838e4fd1d39b40821746" - adjust-sourcemap-loader@^1.1.0: version "1.2.0" resolved "http://registry.npmjs.org/adjust-sourcemap-loader/-/adjust-sourcemap-loader-1.2.0.tgz#e33fde95e50db9f2a802e3647e311d2fc5000c69" @@ -532,7 +569,7 @@ after@0.8.2: version "0.8.2" resolved "https://registry.yarnpkg.com/after/-/after-0.8.2.tgz#fedb394f9f0e02aa9768e702bda23b505fae7e1f" -agent-base@4, agent-base@^4.1.0, agent-base@^4.2.0, agent-base@~4.2.0: +agent-base@^4.1.0: version "4.2.1" resolved "https://registry.yarnpkg.com/agent-base/-/agent-base-4.2.1.tgz#d89e5999f797875674c07d87f260fc41e83e8ca9" dependencies: @@ -585,16 +622,6 @@ amdefine@>=0.0.4, amdefine@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/amdefine/-/amdefine-1.0.1.tgz#4a5282ac164729e93619bcfd3ad151f817ce91f5" -amqplib@^0.5.2: - version "0.5.2" - resolved "https://registry.yarnpkg.com/amqplib/-/amqplib-0.5.2.tgz#d2d7313c7ffaa4d10bcf1e6252de4591b6cc7b63" - dependencies: - bitsyntax "~0.0.4" - bluebird "^3.4.6" - buffer-more-ints "0.0.2" - readable-stream "1.x >=1.1.9" - safe-buffer "^5.0.1" - angular-idle-preload@3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/angular-idle-preload/-/angular-idle-preload-3.0.0.tgz#decace34d9fac1cb00000727a6dc5caafdb84e4d" @@ -851,11 +878,7 @@ assert-plus@1.0.0, assert-plus@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/assert-plus/-/assert-plus-1.0.0.tgz#f12e0f3c5d77b0b1cdd9146942e4e96c1e4dd525" -assert-plus@^0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/assert-plus/-/assert-plus-0.2.0.tgz#d74e1b87e7affc0db8aadb7021f3fe48101ab234" - -assert@^1.1.1, assert@^1.3.0, assert@^1.4.0: +assert@^1.1.1, assert@^1.3.0: version "1.4.1" resolved "https://registry.yarnpkg.com/assert/-/assert-1.4.1.tgz#99912d591836b5a6f5b345c0f07eefc08fc65d91" dependencies: @@ -865,10 +888,6 @@ assign-symbols@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/assign-symbols/-/assign-symbols-1.0.0.tgz#59667f41fadd4f20ccbc2bb96b8d4f7f78ec0367" -ast-types@0.x.x: - version "0.11.5" - resolved "https://registry.yarnpkg.com/ast-types/-/ast-types-0.11.5.tgz#9890825d660c03c28339f315e9fa0a360e31ec28" - async-each@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/async-each/-/async-each-1.0.1.tgz#19d386a1d9edc6e7c1c85d388aedbcc56d33602d" @@ -891,7 +910,7 @@ async@2.0.1: dependencies: lodash "^4.8.0" -async@^2.0.0, async@^2.1.5, async@^2.5.0, async@~2.6.0: +async@^2.0.0, async@^2.5.0: version "2.6.1" resolved "https://registry.yarnpkg.com/async/-/async-2.6.1.tgz#b245a23ca71930044ec53fa46aa00a3e87c6a610" dependencies: @@ -940,24 +959,14 @@ awesome-typescript-loader@5.2.0: source-map-support "^0.5.3" webpack-log "^1.2.0" -aws-sign2@~0.6.0: - version "0.6.0" - resolved "https://registry.yarnpkg.com/aws-sign2/-/aws-sign2-0.6.0.tgz#14342dd38dbcc94d0e5b87d763cd63612c0e794f" - aws-sign2@~0.7.0: version "0.7.0" resolved "https://registry.yarnpkg.com/aws-sign2/-/aws-sign2-0.7.0.tgz#b46e890934a9591f2d2f6f86d7e6a9f1b3fe76a8" -aws4@^1.2.1, aws4@^1.6.0, aws4@^1.8.0: +aws4@^1.6.0, aws4@^1.8.0: version "1.8.0" resolved "https://registry.yarnpkg.com/aws4/-/aws4-1.8.0.tgz#f0e003d9ca9e7f59c7a508945d7b2ef9a04a542f" -axios@^0.15.3: - version "0.15.3" - resolved "http://registry.npmjs.org/axios/-/axios-0.15.3.tgz#2c9d638b2e191a08ea1d6cc988eadd6ba5bdc053" - dependencies: - follow-redirects "1.0.0" - babel-code-frame@^6.22.0, babel-code-frame@^6.26.0: version "6.26.0" resolved "https://registry.yarnpkg.com/babel-code-frame/-/babel-code-frame-6.26.0.tgz#63fd43f7dc1e3bb7ce35947db8fe369a3f58c74b" @@ -1119,12 +1128,6 @@ binary-extensions@^1.0.0: version "1.11.0" resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-1.11.0.tgz#46aa1751fb6a2f93ee5e689bb1087d4b14c6c205" -bitsyntax@~0.0.4: - version "0.0.4" - resolved "https://registry.yarnpkg.com/bitsyntax/-/bitsyntax-0.0.4.tgz#eb10cc6f82b8c490e3e85698f07e83d46e0cba82" - dependencies: - buffer-more-ints "0.0.2" - bl@^1.0.0: version "1.2.2" resolved "https://registry.yarnpkg.com/bl/-/bl-1.2.2.tgz#a160911717103c07410cef63ef51b397c025af9c" @@ -1132,12 +1135,6 @@ bl@^1.0.0: readable-stream "^2.3.5" safe-buffer "^5.1.1" -bl@~1.1.2: - version "1.1.2" - resolved "https://registry.yarnpkg.com/bl/-/bl-1.1.2.tgz#fdca871a99713aa00d19e3bbba41c44787a65398" - dependencies: - readable-stream "~2.0.5" - blob@0.0.4: version "0.0.4" resolved "https://registry.yarnpkg.com/blob/-/blob-0.0.4.tgz#bcf13052ca54463f30f9fc7e95b9a47630a94921" @@ -1154,7 +1151,7 @@ blocking-proxy@^1.0.0: dependencies: minimist "^1.2.0" -bluebird@^3.3.0, bluebird@^3.4.6, bluebird@^3.5.1: +bluebird@^3.3.0, bluebird@^3.5.1: version "3.5.1" resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-3.5.1.tgz#d9551f9de98f1fcda1e683d17ee91a0602ee2eb9" @@ -1207,12 +1204,6 @@ boolbase@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/boolbase/-/boolbase-1.0.0.tgz#68dff5fbe60c51eb37725ea9e3ed310dcc1e776e" -boom@2.x.x: - version "2.10.1" - resolved "https://registry.yarnpkg.com/boom/-/boom-2.10.1.tgz#39c8918ceff5799f83f9492a848f625add0c766f" - dependencies: - hoek "2.x.x" - boom@4.x.x: version "4.3.1" resolved "https://registry.yarnpkg.com/boom/-/boom-4.3.1.tgz#4f8a3005cb4a7e3889f749030fd25b96e01d2e31" @@ -1281,23 +1272,6 @@ brorand@^1.0.1: version "1.1.0" resolved "https://registry.yarnpkg.com/brorand/-/brorand-1.1.0.tgz#12c25efe40a45e3c323eb8675a0a0ce57b22371f" -browser-pack@^6.0.1: - version "6.1.0" - resolved "https://registry.yarnpkg.com/browser-pack/-/browser-pack-6.1.0.tgz#c34ba10d0b9ce162b5af227c7131c92c2ecd5774" - dependencies: - JSONStream "^1.0.3" - combine-source-map "~0.8.0" - defined "^1.0.0" - safe-buffer "^5.1.1" - through2 "^2.0.0" - umd "^3.0.0" - -browser-resolve@^1.11.0, browser-resolve@^1.7.0: - version "1.11.3" - resolved "https://registry.yarnpkg.com/browser-resolve/-/browser-resolve-1.11.3.tgz#9b7cbb3d0f510e4cb86bdbd796124d28b5890af6" - dependencies: - resolve "1.1.7" - browserify-aes@^1.0.0, browserify-aes@^1.0.4: version "1.2.0" resolved "https://registry.yarnpkg.com/browserify-aes/-/browserify-aes-1.2.0.tgz#326734642f403dabc3003209853bb70ad428ef48" @@ -1345,64 +1319,12 @@ browserify-sign@^4.0.0: inherits "^2.0.1" parse-asn1 "^5.0.0" -browserify-zlib@^0.2.0, browserify-zlib@~0.2.0: +browserify-zlib@^0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/browserify-zlib/-/browserify-zlib-0.2.0.tgz#2869459d9aa3be245fe8fe2ca1f46e2e7f54d73f" dependencies: pako "~1.0.5" -browserify@^14.5.0: - version "14.5.0" - resolved "https://registry.yarnpkg.com/browserify/-/browserify-14.5.0.tgz#0bbbce521acd6e4d1d54d8e9365008efb85a9cc5" - dependencies: - JSONStream "^1.0.3" - assert "^1.4.0" - browser-pack "^6.0.1" - browser-resolve "^1.11.0" - browserify-zlib "~0.2.0" - buffer "^5.0.2" - cached-path-relative "^1.0.0" - concat-stream "~1.5.1" - console-browserify "^1.1.0" - constants-browserify "~1.0.0" - crypto-browserify "^3.0.0" - defined "^1.0.0" - deps-sort "^2.0.0" - domain-browser "~1.1.0" - duplexer2 "~0.1.2" - events "~1.1.0" - glob "^7.1.0" - has "^1.0.0" - htmlescape "^1.1.0" - https-browserify "^1.0.0" - inherits "~2.0.1" - insert-module-globals "^7.0.0" - labeled-stream-splicer "^2.0.0" - module-deps "^4.0.8" - os-browserify "~0.3.0" - parents "^1.0.1" - path-browserify "~0.0.0" - process "~0.11.0" - punycode "^1.3.2" - querystring-es3 "~0.2.0" - read-only-stream "^2.0.0" - readable-stream "^2.0.2" - resolve "^1.1.4" - shasum "^1.0.0" - shell-quote "^1.6.1" - stream-browserify "^2.0.0" - stream-http "^2.0.0" - string_decoder "~1.0.0" - subarg "^1.0.0" - syntax-error "^1.1.1" - through2 "^2.0.0" - timers-browserify "^1.0.1" - tty-browserify "~0.0.0" - url "~0.11.0" - util "~0.10.1" - vm-browserify "~0.0.1" - xtend "^4.0.0" - browserslist@^2.0.0, browserslist@^2.11.3: version "2.11.3" resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-2.11.3.tgz#fe36167aed1bbcde4827ebfe71347a2cc70b99b2" @@ -1455,10 +1377,6 @@ buffer-indexof@^1.0.0: version "1.1.1" resolved "https://registry.yarnpkg.com/buffer-indexof/-/buffer-indexof-1.1.1.tgz#52fabcc6a606d1a00302802648ef68f639da268c" -buffer-more-ints@0.0.2: - version "0.0.2" - resolved "https://registry.yarnpkg.com/buffer-more-ints/-/buffer-more-ints-0.0.2.tgz#26b3885d10fa13db7fc01aae3aab870199e0124c" - buffer-xor@^1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/buffer-xor/-/buffer-xor-1.0.3.tgz#26e61ed1422fb70dd42e6e36729ed51d855fe8d9" @@ -1471,25 +1389,13 @@ buffer@^4.3.0: ieee754 "^1.1.4" isarray "^1.0.0" -buffer@^5.0.2, buffer@^5.1.0: +buffer@^5.1.0: version "5.2.0" resolved "https://registry.yarnpkg.com/buffer/-/buffer-5.2.0.tgz#53cf98241100099e9eeae20ee6d51d21b16e541e" dependencies: base64-js "^1.0.2" ieee754 "^1.1.4" -buildmail@4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/buildmail/-/buildmail-4.0.1.tgz#877f7738b78729871c9a105e3b837d2be11a7a72" - dependencies: - addressparser "1.0.1" - libbase64 "0.1.0" - libmime "3.0.0" - libqp "1.1.0" - nodemailer-fetch "1.6.0" - nodemailer-shared "1.1.0" - punycode "1.4.1" - builtin-modules@^1.0.0, builtin-modules@^1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/builtin-modules/-/builtin-modules-1.1.1.tgz#270f076c5a72c02f5b65a47df94c5fe3a278892f" @@ -1502,6 +1408,10 @@ builtin-status-codes@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/builtin-status-codes/-/builtin-status-codes-3.0.0.tgz#85982878e21b98e1c66425e03d0174788f569ee8" +builtins@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/builtins/-/builtins-1.0.3.tgz#cb94faeb61c8696451db36534e1422f94f0aee88" + bytes@3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/bytes/-/bytes-3.0.0.tgz#d32815404d689699f85a4ea4fa8755dd13a96048" @@ -1538,10 +1448,6 @@ cache-base@^1.0.1: union-value "^1.0.0" unset-value "^1.0.0" -cached-path-relative@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/cached-path-relative/-/cached-path-relative-1.0.1.tgz#d09c4b52800aa4c078e2dd81a869aac90d2e54e7" - 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" @@ -1597,10 +1503,6 @@ 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" -caseless@~0.11.0: - version "0.11.0" - resolved "https://registry.yarnpkg.com/caseless/-/caseless-0.11.0.tgz#715b96ea9841593cc33067923f5ec60ebda4f7d7" - caseless@~0.12.0: version "0.12.0" resolved "https://registry.yarnpkg.com/caseless/-/caseless-0.12.0.tgz#1b681c21ff84033c826543090689420d187151dc" @@ -1652,7 +1554,7 @@ check-types@^7.3.0: version "7.4.0" resolved "https://registry.yarnpkg.com/check-types/-/check-types-7.4.0.tgz#0378ec1b9616ec71f774931a3c6516fad8c152f4" -chokidar@^1.4.1, chokidar@^1.4.2: +chokidar@^1.4.2: version "1.7.0" resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-1.7.0.tgz#798e689778151c8076b4b360e5edd28cda2bb468" dependencies: @@ -1707,7 +1609,7 @@ cipher-base@^1.0.0, cipher-base@^1.0.1, cipher-base@^1.0.3: inherits "^2.0.1" safe-buffer "^5.0.1" -circular-json@^0.5.4: +circular-json@^0.5.5: version "0.5.5" resolved "https://registry.yarnpkg.com/circular-json/-/circular-json-0.5.5.tgz#64182ef359042d37cd8e767fc9de878b1e9447d3" @@ -1764,14 +1666,14 @@ cliui@^4.0.0: strip-ansi "^4.0.0" wrap-ansi "^2.0.0" -clone-deep@^0.3.0: - version "0.3.0" - resolved "https://registry.yarnpkg.com/clone-deep/-/clone-deep-0.3.0.tgz#348c61ae9cdbe0edfe053d91ff4cc521d790ede8" +clone-deep@^2.0.1: + version "2.0.2" + resolved "https://registry.yarnpkg.com/clone-deep/-/clone-deep-2.0.2.tgz#00db3a1e173656730d1188c3d6aced6d7ea97713" dependencies: for-own "^1.0.0" - is-plain-object "^2.0.1" - kind-of "^3.2.2" - shallow-clone "^0.1.2" + is-plain-object "^2.0.4" + kind-of "^6.0.0" + shallow-clone "^1.0.0" clone-stats@^0.0.1: version "0.0.1" @@ -1874,22 +1776,13 @@ combine-lists@^1.0.0: dependencies: lodash "^4.5.0" -combine-source-map@^0.8.0, combine-source-map@~0.8.0: - version "0.8.0" - resolved "https://registry.yarnpkg.com/combine-source-map/-/combine-source-map-0.8.0.tgz#a58d0df042c186fcf822a8e8015f5450d2d79a8b" - dependencies: - convert-source-map "~1.1.0" - inline-source-map "~0.6.0" - lodash.memoize "~3.0.3" - source-map "~0.5.3" - -combined-stream@1.0.6, combined-stream@^1.0.5, combined-stream@~1.0.5, combined-stream@~1.0.6: +combined-stream@1.0.6, combined-stream@~1.0.5, combined-stream@~1.0.6: version "1.0.6" resolved "https://registry.yarnpkg.com/combined-stream/-/combined-stream-1.0.6.tgz#723e7df6e801ac5613113a7e445a9b69cb632818" dependencies: delayed-stream "~1.0.0" -commander@2.17.x, commander@^2.12.1, commander@^2.13.0, commander@^2.9.0, commander@~2.17.1: +commander@2.17.x, commander@^2.12.1, commander@^2.13.0, commander@~2.17.1: version "2.17.1" resolved "https://registry.yarnpkg.com/commander/-/commander-2.17.1.tgz#bd77ab7de6de94205ceacc72f1716d29f20a77bf" @@ -1966,7 +1859,7 @@ concat-map@0.0.1: version "0.0.1" resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" -concat-stream@1.6.2, concat-stream@^1.5.0, concat-stream@^1.6.1: +concat-stream@1.6.2, concat-stream@^1.5.0, concat-stream@^1.5.2: version "1.6.2" resolved "https://registry.yarnpkg.com/concat-stream/-/concat-stream-1.6.2.tgz#904bdf194cd3122fc675c77fc4ac3d4ff0fd1a34" dependencies: @@ -1975,14 +1868,6 @@ concat-stream@1.6.2, concat-stream@^1.5.0, concat-stream@^1.6.1: readable-stream "^2.2.2" typedarray "^0.0.6" -concat-stream@~1.5.0, concat-stream@~1.5.1: - version "1.5.2" - resolved "https://registry.yarnpkg.com/concat-stream/-/concat-stream-1.5.2.tgz#708978624d856af41a5a741defdd261da752c266" - dependencies: - inherits "~2.0.1" - readable-stream "~2.0.0" - typedarray "~0.0.5" - configstore@^3.0.0: version "3.1.2" resolved "https://registry.yarnpkg.com/configstore/-/configstore-3.1.2.tgz#c6f25defaeef26df12dd33414b001fe81a543f8f" @@ -2017,7 +1902,7 @@ console-control-strings@^1.0.0, console-control-strings@~1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/console-control-strings/-/console-control-strings-1.1.0.tgz#3d7cf4464db6446ea644bf4b39507f9851008e8e" -constants-browserify@^1.0.0, constants-browserify@~1.0.0: +constants-browserify@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/constants-browserify/-/constants-browserify-1.0.0.tgz#c20b96d8c617748aaf1c16021760cd27fcb8cb75" @@ -2037,10 +1922,6 @@ convert-source-map@^1.5.0, convert-source-map@^1.5.1: version "1.5.1" resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-1.5.1.tgz#b8278097b9bc229365de5c62cf5fcaed8b5599e5" -convert-source-map@~1.1.0: - version "1.1.3" - resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-1.1.3.tgz#4829c877e9fe49b3161f3bf3673888e204699860" - cookie-parser@1.4.3: version "1.4.3" resolved "https://registry.yarnpkg.com/cookie-parser/-/cookie-parser-1.4.3.tgz#0fe31fa19d000b95f4aadf1f53fdc2b8a203baa5" @@ -2104,18 +1985,6 @@ corser@~2.0.0: version "2.0.1" resolved "https://registry.yarnpkg.com/corser/-/corser-2.0.1.tgz#8eda252ecaab5840dcd975ceb90d9370c819ff87" -cosmiconfig@^2.1.0, cosmiconfig@^2.1.1: - version "2.2.2" - resolved "https://registry.yarnpkg.com/cosmiconfig/-/cosmiconfig-2.2.2.tgz#6173cebd56fac042c1f4390edf7af6c07c7cb892" - dependencies: - is-directory "^0.3.1" - js-yaml "^3.4.3" - minimist "^1.2.0" - object-assign "^4.1.0" - os-homedir "^1.0.1" - parse-json "^2.2.0" - require-from-string "^1.1.0" - cosmiconfig@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/cosmiconfig/-/cosmiconfig-4.0.0.tgz#760391549580bbd2df1e562bc177b13c290972dc" @@ -2193,7 +2062,7 @@ cross-spawn@^3.0.0: lru-cache "^4.0.1" which "^1.2.9" -cross-spawn@^5.0.1, cross-spawn@^5.1.0: +cross-spawn@^5.0.1: version "5.1.0" resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-5.1.0.tgz#e8bd0efee58fcff6f8f94510a0a554bbfa235449" dependencies: @@ -2201,7 +2070,7 @@ cross-spawn@^5.0.1, cross-spawn@^5.1.0: shebang-command "^1.2.0" which "^1.2.9" -cross-spawn@^6.0.0, cross-spawn@^6.0.5: +cross-spawn@^6.0.0, cross-spawn@^6.0.4, cross-spawn@^6.0.5: version "6.0.5" resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-6.0.5.tgz#4a5ec7c64dfae22c3a14124dbacdee846d80cbc4" dependencies: @@ -2215,19 +2084,13 @@ crypt@~0.0.1: version "0.0.2" resolved "https://registry.yarnpkg.com/crypt/-/crypt-0.0.2.tgz#88d7ff7ec0dfb86f713dc87bbb42d044d3e6c41b" -cryptiles@2.x.x: - version "2.0.5" - resolved "https://registry.yarnpkg.com/cryptiles/-/cryptiles-2.0.5.tgz#3bdfecdc608147c1c67202fa291e7dca59eaa3b8" - dependencies: - boom "2.x.x" - cryptiles@3.x.x: version "3.1.2" resolved "https://registry.yarnpkg.com/cryptiles/-/cryptiles-3.1.2.tgz#a89fbb220f5ce25ec56e8c4aa8a4fd7b5b0d29fe" dependencies: boom "5.x.x" -crypto-browserify@^3.0.0, crypto-browserify@^3.11.0: +crypto-browserify@^3.11.0: version "3.12.0" resolved "https://registry.yarnpkg.com/crypto-browserify/-/crypto-browserify-3.12.0.tgz#396cf9f3137f03e4b8e532c58f698254e00f80ec" dependencies: @@ -2343,10 +2206,6 @@ dashdash@^1.12.0: dependencies: assert-plus "^1.0.0" -data-uri-to-buffer@1: - version "1.2.0" - resolved "https://registry.yarnpkg.com/data-uri-to-buffer/-/data-uri-to-buffer-1.2.0.tgz#77163ea9c20d8641b4707e8f18abdf9a78f34835" - date-format@^1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/date-format/-/date-format-1.2.0.tgz#615e828e233dd1ab9bb9ae0950e0ceccfa6ecad8" @@ -2362,13 +2221,13 @@ dateformat@^1.0.11, dateformat@^1.0.6: get-stdin "^4.0.1" meow "^3.3.0" -debug@2, debug@2.6.9, debug@^2.1.2, debug@^2.2.0, debug@^2.3.3, debug@^2.6.6, debug@^2.6.8, debug@~2.6.4, debug@~2.6.6: +debug@2.6.9, debug@^2.1.2, debug@^2.2.0, debug@^2.3.3, debug@^2.6.6, debug@^2.6.8: version "2.6.9" resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f" dependencies: ms "2.0.0" -debug@3.1.0, debug@^3.1.0, debug@~3.1.0: +debug@^3.1.0, debug@~3.1.0: version "3.1.0" resolved "https://registry.yarnpkg.com/debug/-/debug-3.1.0.tgz#5bb5a0672628b64149566ba16819e61518c67261" dependencies: @@ -2440,18 +2299,6 @@ define-property@^2.0.2: is-descriptor "^1.0.2" isobject "^3.0.1" -defined@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/defined/-/defined-1.0.0.tgz#c98d9bcef75674188e110969151199e39b1fa693" - -degenerator@^1.0.4: - version "1.0.4" - resolved "https://registry.yarnpkg.com/degenerator/-/degenerator-1.0.4.tgz#fcf490a37ece266464d9cc431ab98c5819ced095" - dependencies: - ast-types "0.x.x" - escodegen "1.x.x" - esprima "3.x.x" - del@^2.2.0: version "2.2.2" resolved "https://registry.yarnpkg.com/del/-/del-2.2.2.tgz#c12c981d067846c84bcaf862cff930d907ffd1a8" @@ -2495,15 +2342,6 @@ dependency-graph@^0.7.0: version "0.7.1" resolved "https://registry.yarnpkg.com/dependency-graph/-/dependency-graph-0.7.1.tgz#0da960213843d8961d444da58da438bad39343a7" -deps-sort@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/deps-sort/-/deps-sort-2.0.0.tgz#091724902e84658260eb910748cccd1af6e21fb5" - dependencies: - JSONStream "^1.0.3" - shasum "^1.0.0" - subarg "^1.0.0" - through2 "^2.0.0" - des.js@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/des.js/-/des.js-1.0.0.tgz#c074d2e2aa6a8a9a07dbd61f9a15c2cd83ec8ecc" @@ -2529,13 +2367,6 @@ detect-node@^2.0.3: version "2.0.3" resolved "https://registry.yarnpkg.com/detect-node/-/detect-node-2.0.3.tgz#a2033c09cc8e158d37748fbde7507832bd6ce127" -detective@^4.0.0: - version "4.7.1" - resolved "https://registry.yarnpkg.com/detective/-/detective-4.7.1.tgz#0eca7314338442febb6d65da54c10bb1c82b246e" - dependencies: - acorn "^5.2.1" - defined "^1.0.0" - di@^0.0.1: version "0.0.1" resolved "https://registry.yarnpkg.com/di/-/di-0.0.1.tgz#806649326ceaa7caa3306d75d985ea2748ba913c" @@ -2602,10 +2433,6 @@ domain-browser@^1.1.1: version "1.2.0" resolved "https://registry.yarnpkg.com/domain-browser/-/domain-browser-1.2.0.tgz#3d31f50191a6749dd1375a7f522e823d42e54eda" -domain-browser@~1.1.0: - version "1.1.7" - resolved "https://registry.yarnpkg.com/domain-browser/-/domain-browser-1.1.7.tgz#867aa4b093faa05f1de08c06f4d7b21fdf8698bc" - domelementtype@1: version "1.3.0" resolved "https://registry.yarnpkg.com/domelementtype/-/domelementtype-1.3.0.tgz#b17aed82e8ab59e52dd9c19b1756e0fc187204c2" @@ -2643,22 +2470,12 @@ dot-prop@^4.1.0: dependencies: is-obj "^1.0.0" -double-ended-queue@^2.1.0-0: - version "2.1.0-0" - resolved "https://registry.yarnpkg.com/double-ended-queue/-/double-ended-queue-2.1.0-0.tgz#103d3527fd31528f40188130c841efdd78264e5c" - duplexer2@0.0.2: version "0.0.2" resolved "https://registry.yarnpkg.com/duplexer2/-/duplexer2-0.0.2.tgz#c614dcf67e2fb14995a91711e5a617e8a60a31db" dependencies: readable-stream "~1.1.9" -duplexer2@^0.1.2, duplexer2@~0.1.0, duplexer2@~0.1.2: - version "0.1.4" - resolved "https://registry.yarnpkg.com/duplexer2/-/duplexer2-0.1.4.tgz#8b12dab878c0d69e3e7891051662a32fc6bddcc1" - dependencies: - readable-stream "^2.0.2" - duplexer3@^0.1.4: version "0.1.4" resolved "https://registry.yarnpkg.com/duplexer3/-/duplexer3-0.1.4.tgz#ee01dd1cac0ed3cbc7fdbea37dc0a8f1ce002ce2" @@ -2736,9 +2553,9 @@ end-of-stream@^1.0.0, end-of-stream@^1.1.0: dependencies: once "^1.4.0" -engine.io-client@~3.1.0: - version "3.1.6" - resolved "https://registry.yarnpkg.com/engine.io-client/-/engine.io-client-3.1.6.tgz#5bdeb130f8b94a50ac5cbeb72583e7a4a063ddfd" +engine.io-client@~3.2.0: + version "3.2.1" + resolved "https://registry.yarnpkg.com/engine.io-client/-/engine.io-client-3.2.1.tgz#6f54c0475de487158a1a7c77d10178708b6add36" dependencies: component-emitter "1.2.1" component-inherit "0.0.3" @@ -2762,9 +2579,9 @@ engine.io-parser@~2.1.0, engine.io-parser@~2.1.1: blob "0.0.4" has-binary2 "~1.0.2" -engine.io@~3.1.0: - version "3.1.5" - resolved "https://registry.yarnpkg.com/engine.io/-/engine.io-3.1.5.tgz#0e7ef9d690eb0b35597f1d4ad02a26ca2dba3845" +engine.io@~3.2.0: + version "3.2.0" + resolved "https://registry.yarnpkg.com/engine.io/-/engine.io-3.2.0.tgz#54332506f42f2edc71690d2f2a42349359f3bf7d" dependencies: accepts "~1.3.4" base64id "1.0.0" @@ -2772,8 +2589,6 @@ engine.io@~3.1.0: debug "~3.1.0" engine.io-parser "~2.1.0" ws "~3.3.1" - optionalDependencies: - uws "~9.14.0" enhanced-resolve@^4.0.0, enhanced-resolve@^4.1.0: version "4.1.0" @@ -2877,17 +2692,6 @@ escodegen@1.8.x: optionalDependencies: source-map "~0.2.0" -escodegen@1.x.x: - version "1.11.0" - resolved "https://registry.yarnpkg.com/escodegen/-/escodegen-1.11.0.tgz#b27a9389481d5bfd5bec76f7bb1eb3f8f4556589" - dependencies: - esprima "^3.1.3" - estraverse "^4.2.0" - esutils "^2.0.2" - optionator "^0.8.1" - optionalDependencies: - source-map "~0.6.1" - eslint-scope@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-4.0.0.tgz#50bf3071e9338bcdc43331794a0cb533f0136172" @@ -2899,10 +2703,6 @@ esprima@2.7.x, esprima@^2.7.1: version "2.7.3" resolved "https://registry.yarnpkg.com/esprima/-/esprima-2.7.3.tgz#96e3b70d5779f6ad49cd032673d1c312767ba581" -esprima@3.x.x, esprima@^3.1.3: - version "3.1.3" - resolved "https://registry.yarnpkg.com/esprima/-/esprima-3.1.3.tgz#fdca51cee6133895e3c88d535ce49dbff62a4633" - esprima@^4.0.0: version "4.0.1" resolved "https://registry.yarnpkg.com/esprima/-/esprima-4.0.1.tgz#13b04cdb3e6c5d19df91ab6987a8695619b0aa71" @@ -2917,7 +2717,7 @@ estraverse@^1.9.1: version "1.9.3" resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-1.9.3.tgz#af67f2dc922582415950926091a4005d29c9bb44" -estraverse@^4.1.0, estraverse@^4.1.1, estraverse@^4.2.0: +estraverse@^4.1.0, estraverse@^4.1.1: version "4.2.0" resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-4.2.0.tgz#0dee3fed31fcd469618ce7342099fc1afa0bdb13" @@ -2949,7 +2749,7 @@ eventemitter3@^3.0.0: version "3.1.0" resolved "https://registry.yarnpkg.com/eventemitter3/-/eventemitter3-3.1.0.tgz#090b4d6cdbd645ed10bf750d4b5407942d7ba163" -events@^1.0.0, events@~1.1.0: +events@^1.0.0: version "1.1.1" resolved "https://registry.yarnpkg.com/events/-/events-1.1.1.tgz#9ebdb7635ad099c70dcc4c2a1f5004288e8bd924" @@ -3143,7 +2943,7 @@ extend-shallow@^3.0.0, extend-shallow@^3.0.2: assign-symbols "^1.0.0" is-extendable "^1.0.1" -extend@3, extend@^3.0.0, extend@~3.0.0, extend@~3.0.1, extend@~3.0.2: +extend@^3.0.0, extend@~3.0.1, extend@~3.0.2: version "3.0.2" resolved "https://registry.yarnpkg.com/extend/-/extend-3.0.2.tgz#f8b1136b4071fbd8eb140aff858b1019ec2915fa" @@ -3262,10 +3062,6 @@ figures@^2.0.0: dependencies: escape-string-regexp "^1.0.5" -file-uri-to-path@1: - version "1.0.0" - resolved "https://registry.yarnpkg.com/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz#553a7b8446ff6f684359c445f1e37a05dacc33dd" - filename-regex@^2.0.0: version "2.0.1" resolved "https://registry.yarnpkg.com/filename-regex/-/filename-regex-2.0.1.tgz#c1c4b9bee3e09725ddb106b75c1e301fe2f18b26" @@ -3355,12 +3151,6 @@ flush-write-stream@^1.0.0: inherits "^2.0.1" readable-stream "^2.0.4" -follow-redirects@1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.0.0.tgz#8e34298cbd2e176f254effec75a1c78cc849fd37" - dependencies: - debug "^2.2.0" - follow-redirects@^1.0.0: version "1.5.7" resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.5.7.tgz#a39e4804dacb90202bca76a9e2ac10433ca6a69a" @@ -3395,15 +3185,7 @@ forever-agent@~0.6.1: version "0.6.1" resolved "https://registry.yarnpkg.com/forever-agent/-/forever-agent-0.6.1.tgz#fbc71f0c41adeb37f96c577ad1ed42d8fdacca91" -form-data@~2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/form-data/-/form-data-2.0.0.tgz#6f0aebadcc5da16c13e1ecc11137d85f9b883b25" - dependencies: - asynckit "^0.4.0" - combined-stream "^1.0.5" - mime-types "^2.1.11" - -form-data@~2.3.0, form-data@~2.3.1, form-data@~2.3.2: +form-data@~2.3.1, form-data@~2.3.2: version "2.3.2" resolved "https://registry.yarnpkg.com/form-data/-/form-data-2.3.2.tgz#4970498be604c20c005d4f5c23aecd21d6b49099" dependencies: @@ -3470,9 +3252,9 @@ fs-extra@^4.0.0: jsonfile "^4.0.0" universalify "^0.1.0" -fs-extra@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-5.0.0.tgz#414d0110cdd06705734d055652c5411260c31abd" +fs-extra@^7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-7.0.0.tgz#8cc3f47ce07ef7b3593a11b9fb245f7e34c041d6" dependencies: graceful-fs "^4.1.2" jsonfile "^4.0.0" @@ -3513,13 +3295,6 @@ fstream@^1.0.0, fstream@^1.0.2: mkdirp ">=0.5 0" rimraf "2" -ftp@~0.3.10: - version "0.3.10" - resolved "https://registry.yarnpkg.com/ftp/-/ftp-0.3.10.tgz#9197d861ad8142f3e63d5a83bfe4c59f7330885d" - dependencies: - readable-stream "1.1.x" - xregexp "2.0.0" - function-bind@^1.0.2, function-bind@^1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.1.tgz#a56899d3ea3c9bab874bb9773b7c5ede92f4895d" @@ -3543,20 +3318,6 @@ gaze@^1.0.0: dependencies: globule "^1.0.0" -generate-function@^2.0.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/generate-function/-/generate-function-2.2.0.tgz#1aeac896147293d27bce65eb295ce5f3f094a292" - -generate-object-property@^1.1.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/generate-object-property/-/generate-object-property-1.2.0.tgz#9c0e1c40308ce804f4783618b937fa88f99d50d0" - dependencies: - is-property "^1.0.0" - -get-assigned-identifiers@^1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/get-assigned-identifiers/-/get-assigned-identifiers-1.2.0.tgz#6dbf411de648cbaf8d9169ebb0d2d576191e2ff1" - get-caller-file@^1.0.1: version "1.0.3" resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-1.0.3.tgz#f978fa4c90d1dfe7ff2d6beda2a515e713bdcf4a" @@ -3573,17 +3334,6 @@ get-stream@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-3.0.0.tgz#8e943d1358dc37555054ecbe2edb05aa174ede14" -get-uri@^2.0.0: - version "2.0.2" - resolved "https://registry.yarnpkg.com/get-uri/-/get-uri-2.0.2.tgz#5c795e71326f6ca1286f2fc82575cd2bab2af578" - dependencies: - data-uri-to-buffer "1" - debug "2" - extend "3" - file-uri-to-path "1" - ftp "~0.3.10" - readable-stream "2" - get-value@^2.0.3, get-value@^2.0.6: version "2.0.6" resolved "https://registry.yarnpkg.com/get-value/-/get-value-2.0.6.tgz#dc15ca1c672387ca76bd37ac0a395ba2042a2c28" @@ -3628,7 +3378,7 @@ glob@^5.0.15: once "^1.3.0" path-is-absolute "^1.0.0" -glob@^7.0.0, glob@^7.0.3, glob@^7.0.5, glob@^7.0.6, glob@^7.1.0, glob@^7.1.1, glob@^7.1.2, glob@~7.1.1: +glob@^7.0.0, glob@^7.0.3, glob@^7.0.5, glob@^7.0.6, glob@^7.1.1, glob@^7.1.2, glob@~7.1.1: version "7.1.3" resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.3.tgz#3960832d3f1574108342dafd3a67b332c0969df1" dependencies: @@ -3791,15 +3541,6 @@ har-schema@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/har-schema/-/har-schema-2.0.0.tgz#a94c2224ebcac04782a0d9035521f24735b7ec92" -har-validator@~2.0.6: - version "2.0.6" - resolved "https://registry.yarnpkg.com/har-validator/-/har-validator-2.0.6.tgz#cdcbc08188265ad119b6a5a7c8ab70eecfb5d27d" - dependencies: - chalk "^1.1.1" - commander "^2.9.0" - is-my-json-valid "^2.12.4" - pinkie-promise "^2.0.0" - har-validator@~5.0.3: version "5.0.3" resolved "https://registry.yarnpkg.com/har-validator/-/har-validator-5.0.3.tgz#ba402c266194f15956ef15e0fcf242993f6a7dfd" @@ -3879,7 +3620,7 @@ has-values@^1.0.0: is-number "^3.0.0" kind-of "^4.0.0" -has@^1.0.0, has@^1.0.1: +has@^1.0.1: version "1.0.3" resolved "https://registry.yarnpkg.com/has/-/has-1.0.3.tgz#722d7cbfc1f6aa8241f16dd814e011e1f41e8796" dependencies: @@ -3906,15 +3647,6 @@ hasha@^2.2.0: is-stream "^1.0.1" pinkie-promise "^2.0.0" -hawk@~3.1.3: - version "3.1.3" - resolved "https://registry.yarnpkg.com/hawk/-/hawk-3.1.3.tgz#078444bd7c1640b0fe540d2c9b73d59678e8e1c4" - dependencies: - boom "2.x.x" - cryptiles "2.x.x" - hoek "2.x.x" - sntp "1.x.x" - hawk@~6.0.2: version "6.0.2" resolved "https://registry.yarnpkg.com/hawk/-/hawk-6.0.2.tgz#af4d914eb065f9b5ce4d9d11c1cb2126eecc3038" @@ -3932,13 +3664,6 @@ highlight.js@^9.0.0: version "9.12.0" resolved "https://registry.yarnpkg.com/highlight.js/-/highlight.js-9.12.0.tgz#e6d9dbe57cbefe60751f02af336195870c90c01e" -hipchat-notifier@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/hipchat-notifier/-/hipchat-notifier-1.1.0.tgz#b6d249755437c191082367799d3ba9a0f23b231e" - dependencies: - lodash "^4.0.0" - request "^2.0.0" - hmac-drbg@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/hmac-drbg/-/hmac-drbg-1.0.1.tgz#d2745701025a6c775a6c545793ed502fc0c649a1" @@ -3947,10 +3672,6 @@ hmac-drbg@^1.0.0: minimalistic-assert "^1.0.0" minimalistic-crypto-utils "^1.0.1" -hoek@2.x.x: - version "2.16.3" - resolved "https://registry.yarnpkg.com/hoek/-/hoek-2.16.3.tgz#20bb7403d3cea398e91dc4710a8ff1b8274a25ed" - hoek@4.x.x: version "4.2.1" resolved "https://registry.yarnpkg.com/hoek/-/hoek-4.2.1.tgz#9634502aa12c445dd5a7c5734b572bb8738aacbb" @@ -3961,7 +3682,7 @@ homedir-polyfill@^1.0.1: dependencies: parse-passwd "^1.0.0" -hosted-git-info@^2.1.4: +hosted-git-info@^2.1.4, hosted-git-info@^2.6.0: version "2.7.1" resolved "https://registry.yarnpkg.com/hosted-git-info/-/hosted-git-info-2.7.1.tgz#97f236977bd6e125408930ff6de3eec6281ec047" @@ -4002,10 +3723,6 @@ html-webpack-plugin@^4.0.0-alpha: tapable "^1.0.0" util.promisify "1.0.0" -htmlescape@^1.1.0: - version "1.1.1" - resolved "https://registry.yarnpkg.com/htmlescape/-/htmlescape-1.1.1.tgz#3a03edc2214bca3b66424a3e7959349509cb0351" - htmlparser2@~3.3.0: version "3.3.0" resolved "https://registry.yarnpkg.com/htmlparser2/-/htmlparser2-3.3.0.tgz#cc70d05a59f6542e43f0e685c982e14c924a9efe" @@ -4041,13 +3758,6 @@ http-parser-js@>=0.4.0: version "0.4.13" resolved "https://registry.yarnpkg.com/http-parser-js/-/http-parser-js-0.4.13.tgz#3bd6d6fde6e3172c9334c3b33b6c193d80fe1137" -http-proxy-agent@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/http-proxy-agent/-/http-proxy-agent-2.1.0.tgz#e4821beef5b2142a2026bd73926fe537631c5405" - dependencies: - agent-base "4" - debug "3.1.0" - http-proxy-middleware@~0.18.0: version "0.18.0" resolved "http://registry.npmjs.org/http-proxy-middleware/-/http-proxy-middleware-0.18.0.tgz#0987e6bb5a5606e5a69168d8f967a87f15dd8aab" @@ -4078,14 +3788,6 @@ http-server@0.11.1: portfinder "^1.0.13" union "~0.4.3" -http-signature@~1.1.0: - version "1.1.1" - resolved "https://registry.yarnpkg.com/http-signature/-/http-signature-1.1.1.tgz#df72e267066cd0ac67fb76adf8e134a8fbcf91bf" - dependencies: - assert-plus "^0.2.0" - jsprim "^1.2.2" - sshpk "^1.7.0" - http-signature@~1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/http-signature/-/http-signature-1.2.0.tgz#9aecd925114772f3d95b65a60abb8f7c18fbace1" @@ -4094,17 +3796,6 @@ http-signature@~1.2.0: jsprim "^1.2.2" sshpk "^1.7.0" -httpntlm@1.6.1: - version "1.6.1" - resolved "https://registry.yarnpkg.com/httpntlm/-/httpntlm-1.6.1.tgz#ad01527143a2e8773cfae6a96f58656bb52a34b2" - dependencies: - httpreq ">=0.4.22" - underscore "~1.7.0" - -httpreq@>=0.4.22: - version "0.4.24" - resolved "https://registry.yarnpkg.com/httpreq/-/httpreq-0.4.24.tgz#4335ffd82cd969668a39465c929ac61d6393627f" - https-browserify@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/https-browserify/-/https-browserify-1.0.0.tgz#ec06c10e0a34c0f2faf199f7fd7fc78fffd03c73" @@ -4120,10 +3811,6 @@ https@1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/https/-/https-1.0.0.tgz#3c37c7ae1a8eeb966904a2ad1e975a194b7ed3a4" -iconv-lite@0.4.15: - version "0.4.15" - resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.15.tgz#fe265a218ac6a57cfe854927e9d04c19825eddeb" - iconv-lite@0.4.19: version "0.4.19" resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.19.tgz#f7468f60135f5e5dad3399c0a81be9a1603a082b" @@ -4228,14 +3915,6 @@ indexof@0.0.1: version "0.0.1" resolved "https://registry.yarnpkg.com/indexof/-/indexof-0.0.1.tgz#82dc336d232b9062179d05ab3293a66059fd435d" -inflection@~1.12.0: - version "1.12.0" - resolved "https://registry.yarnpkg.com/inflection/-/inflection-1.12.0.tgz#a200935656d6f5f6bc4dc7502e1aecb703228416" - -inflection@~1.3.0: - version "1.3.8" - resolved "https://registry.yarnpkg.com/inflection/-/inflection-1.3.8.tgz#cbd160da9f75b14c3cc63578d4f396784bf3014e" - inflight@^1.0.4: version "1.0.6" resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9" @@ -4255,12 +3934,6 @@ ini@^1.3.4, ini@~1.3.0: version "1.3.5" resolved "https://registry.yarnpkg.com/ini/-/ini-1.3.5.tgz#eee25f56db1c9ec6085e0c22778083f596abf927" -inline-source-map@~0.6.0: - version "0.6.2" - resolved "https://registry.yarnpkg.com/inline-source-map/-/inline-source-map-0.6.2.tgz#f9393471c18a79d1724f863fa38b586370ade2a5" - dependencies: - source-map "~0.5.3" - inquirer@3.0.6: version "3.0.6" resolved "https://registry.yarnpkg.com/inquirer/-/inquirer-3.0.6.tgz#e04aaa9d05b7a3cb9b0f407d04375f0447190347" @@ -4297,21 +3970,6 @@ inquirer@^6.0.0: strip-ansi "^4.0.0" through "^2.3.6" -insert-module-globals@^7.0.0: - version "7.2.0" - resolved "https://registry.yarnpkg.com/insert-module-globals/-/insert-module-globals-7.2.0.tgz#ec87e5b42728479e327bd5c5c71611ddfb4752ba" - dependencies: - JSONStream "^1.0.3" - acorn-node "^1.5.2" - combine-source-map "^0.8.0" - concat-stream "^1.6.1" - is-buffer "^1.1.0" - path-is-absolute "^1.0.1" - process "~0.11.0" - through2 "^2.0.0" - undeclared-identifiers "^1.1.2" - xtend "^4.0.0" - internal-ip@^3.0.1: version "3.0.1" resolved "https://registry.yarnpkg.com/internal-ip/-/internal-ip-3.0.1.tgz#df5c99876e1d2eb2ea2d74f520e3f669a00ece27" @@ -4337,7 +3995,7 @@ ip-regex@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/ip-regex/-/ip-regex-2.1.0.tgz#fa78bf5d2e6913c911ce9f819ee5146bb6d844e9" -ip@^1.1.0, ip@^1.1.2, ip@^1.1.4, ip@^1.1.5: +ip@^1.1.0, ip@^1.1.5: version "1.1.5" resolved "https://registry.yarnpkg.com/ip/-/ip-1.1.5.tgz#bdded70114290828c0a039e72ef25f5aaec4354a" @@ -4375,7 +4033,7 @@ is-binary-path@^1.0.0: dependencies: binary-extensions "^1.0.0" -is-buffer@^1.0.2, is-buffer@^1.1.0, is-buffer@^1.1.5, is-buffer@~1.1.1: +is-buffer@^1.1.5, is-buffer@~1.1.1: version "1.1.6" resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-1.1.6.tgz#efaa2ea9daa0d7ab2ea13a97b2b8ad51fefbe8be" @@ -4504,20 +4162,6 @@ is-module@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/is-module/-/is-module-1.0.0.tgz#3258fb69f78c14d5b815d664336b4cffb6441591" -is-my-ip-valid@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/is-my-ip-valid/-/is-my-ip-valid-1.0.0.tgz#7b351b8e8edd4d3995d4d066680e664d94696824" - -is-my-json-valid@^2.12.4: - version "2.19.0" - resolved "https://registry.yarnpkg.com/is-my-json-valid/-/is-my-json-valid-2.19.0.tgz#8fd6e40363cd06b963fa877d444bfb5eddc62175" - dependencies: - generate-function "^2.0.0" - generate-object-property "^1.1.0" - is-my-ip-valid "^1.0.0" - jsonpointer "^4.0.0" - xtend "^4.0.0" - is-npm@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/is-npm/-/is-npm-1.0.0.tgz#f2fb63a65e4905b406c86072765a1a4dc793b9f4" @@ -4580,10 +4224,6 @@ is-promise@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/is-promise/-/is-promise-2.1.0.tgz#79a2a9ece7f096e80f36d2b2f3bc16c1ff4bf3fa" -is-property@^1.0.0: - version "1.0.2" - resolved "https://registry.yarnpkg.com/is-property/-/is-property-1.0.2.tgz#57fe1c4e48474edd65b09911f26b1cd4095dda84" - is-redirect@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/is-redirect/-/is-redirect-1.0.0.tgz#1d03dded53bd8db0f30c26e4f95d36fc7c87dc24" @@ -4634,10 +4274,6 @@ isarray@2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/isarray/-/isarray-2.0.1.tgz#a37d94ed9cda2d59865c9f76fe596ee1f338741e" -isarray@^2.0.4: - version "2.0.4" - resolved "https://registry.yarnpkg.com/isarray/-/isarray-2.0.4.tgz#38e7bcbb0f3ba1b7933c86ba1894ddfc3781bbb7" - isbinaryfile@^3.0.0: version "3.0.3" resolved "https://registry.yarnpkg.com/isbinaryfile/-/isbinaryfile-3.0.3.tgz#5d6def3edebf6e8ca8cae9c30183a804b5f8be80" @@ -4724,9 +4360,9 @@ jasmine-diff@^0.1.3: dependencies: diff "^3.2.0" -jasmine-marbles@0.3.0: - version "0.3.0" - resolved "https://registry.yarnpkg.com/jasmine-marbles/-/jasmine-marbles-0.3.0.tgz#1e0c75ee68d44d00267dde60021de0800314f8d7" +jasmine-marbles@0.3.1: + version "0.3.1" + resolved "https://registry.yarnpkg.com/jasmine-marbles/-/jasmine-marbles-0.3.1.tgz#ef65edecb41b8dd62fc6bda40448222042e32043" dependencies: lodash "^4.5.0" @@ -4770,7 +4406,7 @@ js-tokens@^3.0.2: version "3.0.2" resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-3.0.2.tgz#9866df395102130e38f7f996bceb65443209c25b" -js-yaml@3.x, js-yaml@^3.4.3, js-yaml@^3.6.1, js-yaml@^3.7.0, js-yaml@^3.9.0: +js-yaml@3.x, js-yaml@^3.6.1, js-yaml@^3.7.0, js-yaml@^3.9.0: version "3.12.0" resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.12.0.tgz#eaed656ec8344f10f527c6bfa1b6e2244de167d1" dependencies: @@ -4809,13 +4445,7 @@ json-schema@0.2.3: version "0.2.3" resolved "https://registry.yarnpkg.com/json-schema/-/json-schema-0.2.3.tgz#b480c892e59a2f05954ce727bd3f2a4e882f9e13" -json-stable-stringify@~0.0.0: - version "0.0.1" - resolved "https://registry.yarnpkg.com/json-stable-stringify/-/json-stable-stringify-0.0.1.tgz#611c23e814db375527df851193db59dd2af27f45" - dependencies: - jsonify "~0.0.0" - -json-stringify-safe@5.0.x, json-stringify-safe@~5.0.1: +json-stringify-safe@~5.0.1: version "5.0.1" resolved "https://registry.yarnpkg.com/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz#1296a2d58fd45f19a0f6ce01d65701e2c735b6eb" @@ -4843,14 +4473,6 @@ jsonify@~0.0.0: version "0.0.0" resolved "https://registry.yarnpkg.com/jsonify/-/jsonify-0.0.0.tgz#2c74b6ee41d93ca51b7b5aaee8f503631d252a73" -jsonparse@^1.2.0: - version "1.3.1" - resolved "https://registry.yarnpkg.com/jsonparse/-/jsonparse-1.3.1.tgz#3f4dae4a91fac315f71062f8521cc239f1366280" - -jsonpointer@^4.0.0: - version "4.0.1" - resolved "https://registry.yarnpkg.com/jsonpointer/-/jsonpointer-4.0.1.tgz#4fd92cb34e0e9db3c89c8622ecf51f9b978c6cb9" - jsonschema@1.2.2: version "1.2.2" resolved "https://registry.yarnpkg.com/jsonschema/-/jsonschema-1.2.2.tgz#83ab9c63d65bf4d596f91d81195e78772f6452bc" @@ -4891,13 +4513,13 @@ karma-cli@1.0.1: dependencies: resolve "^1.1.6" -karma-coverage@1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/karma-coverage/-/karma-coverage-1.1.1.tgz#5aff8b39cf6994dc22de4c84362c76001b637cf6" +karma-coverage@1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/karma-coverage/-/karma-coverage-1.1.2.tgz#cc09dceb589a83101aca5fe70c287645ef387689" dependencies: dateformat "^1.0.6" istanbul "^0.4.0" - lodash "^3.8.0" + lodash "^4.17.0" minimatch "^3.0.0" source-map "^0.5.1" @@ -4907,9 +4529,9 @@ karma-istanbul-preprocessor@0.0.2: dependencies: istanbul "^0.4.3" -karma-jasmine@1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/karma-jasmine/-/karma-jasmine-1.1.1.tgz#6fe840e75a11600c9d91e84b33c458e1c46a3529" +karma-jasmine@1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/karma-jasmine/-/karma-jasmine-1.1.2.tgz#394f2b25ffb4a644b9ada6f22d443e2fd08886c3" karma-mocha-reporter@2.2.5: version "2.2.5" @@ -4953,7 +4575,7 @@ karma-webdriver-launcher@1.0.5: karma-webpack@3.0.0: version "3.0.0" - resolved "https://registry.yarnpkg.com/karma-webpack/-/karma-webpack-3.0.0.tgz#bf009c5b73c667c11c015717e9e520f581317c44" + resolved "http://registry.npmjs.org/karma-webpack/-/karma-webpack-3.0.0.tgz#bf009c5b73c667c11c015717e9e520f581317c44" dependencies: async "^2.0.0" babel-runtime "^6.0.0" @@ -4962,14 +4584,13 @@ karma-webpack@3.0.0: source-map "^0.5.6" webpack-dev-middleware "^2.0.6" -karma@2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/karma/-/karma-2.0.0.tgz#a02698dd7f0f05ff5eb66ab8f65582490b512e58" +karma@3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/karma/-/karma-3.0.0.tgz#6da83461a8a28d8224575c3b5b874e271b4730c3" dependencies: bluebird "^3.3.0" body-parser "^1.16.1" - browserify "^14.5.0" - chokidar "^1.4.1" + chokidar "^2.0.3" colors "^1.1.0" combine-lists "^1.0.0" connect "^3.6.0" @@ -4982,18 +4603,18 @@ karma@2.0.0: http-proxy "^1.13.0" isbinaryfile "^3.0.0" lodash "^4.17.4" - log4js "^2.3.9" - mime "^1.3.4" + log4js "^3.0.0" + mime "^2.3.1" minimatch "^3.0.2" optimist "^0.6.1" qjobs "^1.1.4" range-parser "^1.2.0" rimraf "^2.6.0" safe-buffer "^5.0.1" - socket.io "2.0.4" + socket.io "2.1.1" source-map "^0.6.1" tmp "0.0.33" - useragent "^2.1.12" + useragent "2.2.1" kew@^0.7.0: version "0.7.0" @@ -5007,13 +4628,7 @@ kind-of@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-1.1.0.tgz#140a3d2d41a36d2efcfa9377b62c24f8495a5c44" -kind-of@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-2.0.1.tgz#018ec7a4ce7e3a86cb9141be519d24c8faa981b5" - dependencies: - is-buffer "^1.0.2" - -kind-of@^3.0.2, kind-of@^3.0.3, kind-of@^3.2.0, kind-of@^3.2.2: +kind-of@^3.0.2, kind-of@^3.0.3, kind-of@^3.2.0: version "3.2.2" resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-3.2.2.tgz#31ea21a734bab9bbb0f32466d893aea51e4a3c64" dependencies: @@ -5039,24 +4654,12 @@ klaw@^1.0.0: optionalDependencies: graceful-fs "^4.1.9" -labeled-stream-splicer@^2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/labeled-stream-splicer/-/labeled-stream-splicer-2.0.1.tgz#9cffa32fd99e1612fd1d86a8db962416d5292926" - dependencies: - inherits "^2.0.1" - isarray "^2.0.4" - stream-splicer "^2.0.0" - latest-version@^3.0.0: version "3.1.0" resolved "https://registry.yarnpkg.com/latest-version/-/latest-version-3.1.0.tgz#a205383fea322b33b5ae3b18abee0dc2f356ee15" dependencies: package-json "^4.0.0" -lazy-cache@^0.2.3: - version "0.2.7" - resolved "https://registry.yarnpkg.com/lazy-cache/-/lazy-cache-0.2.7.tgz#7feddf2dcb6edb77d11ef1d117ab5ffdf0ab1b65" - lazy-cache@^1.0.3: version "1.0.4" resolved "https://registry.yarnpkg.com/lazy-cache/-/lazy-cache-1.0.4.tgz#a1d78fc3a50474cb80845d3b3b6e1da49a446e8e" @@ -5084,22 +4687,6 @@ levn@~0.3.0: prelude-ls "~1.1.2" type-check "~0.3.2" -libbase64@0.1.0: - version "0.1.0" - resolved "https://registry.yarnpkg.com/libbase64/-/libbase64-0.1.0.tgz#62351a839563ac5ff5bd26f12f60e9830bb751e6" - -libmime@3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/libmime/-/libmime-3.0.0.tgz#51a1a9e7448ecbd32cda54421675bb21bc093da6" - dependencies: - iconv-lite "0.4.15" - libbase64 "0.1.0" - libqp "1.1.0" - -libqp@1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/libqp/-/libqp-1.1.0.tgz#f5e6e06ad74b794fb5b5b66988bf728ef1dedbe8" - lie@~3.1.0: version "3.1.1" resolved "https://registry.yarnpkg.com/lie/-/lie-3.1.1.tgz#9a436b2cc7746ca59de7a41fa469b3efb76bd87e" @@ -5276,10 +4863,6 @@ lodash.memoize@^4.1.2: version "4.1.2" resolved "https://registry.yarnpkg.com/lodash.memoize/-/lodash.memoize-4.1.2.tgz#bcc6c49a42a2840ed997f323eada5ecd182e0bfe" -lodash.memoize@~3.0.3: - version "3.0.4" - resolved "https://registry.yarnpkg.com/lodash.memoize/-/lodash.memoize-3.0.4.tgz#2dcbd2c287cbc0a55cc42328bd0c736150d53e3f" - lodash.mergewith@^4.6.0: version "4.6.1" resolved "https://registry.yarnpkg.com/lodash.mergewith/-/lodash.mergewith-4.6.1.tgz#639057e726c3afbdb3e7d42741caa8d6e4335927" @@ -5330,14 +4913,10 @@ lodash.uniq@^4.5.0: version "4.5.0" resolved "https://registry.yarnpkg.com/lodash.uniq/-/lodash.uniq-4.5.0.tgz#d0225373aeb652adc1bc82e4945339a842754773" -lodash@4.17.10, lodash@^4.0.0, lodash@^4.0.1, lodash@^4.13.1, lodash@^4.15.0, lodash@^4.17.10, lodash@^4.17.4, lodash@^4.17.5, lodash@^4.3.0, lodash@^4.5.0, lodash@^4.8.0, lodash@~4.17.10: +lodash@4.17.10, lodash@^4.0.0, lodash@^4.0.1, lodash@^4.13.1, lodash@^4.17.0, lodash@^4.17.10, lodash@^4.17.4, lodash@^4.17.5, lodash@^4.3.0, lodash@^4.5.0, lodash@^4.8.0, lodash@~4.17.10: version "4.17.10" resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.10.tgz#1b7793cf7259ea38fb3661d4d38b3260af8ae4e7" -lodash@^3.8.0: - version "3.10.1" - resolved "http://registry.npmjs.org/lodash/-/lodash-3.10.1.tgz#5bf45e8e49ba4189e17d482789dfd15bd140b7b6" - log-driver@^1.2.5: version "1.2.7" resolved "https://registry.yarnpkg.com/log-driver/-/log-driver-1.2.7.tgz#63b95021f0702fedfa2c9bb0a24e7797d71871d8" @@ -5348,32 +4927,15 @@ log-symbols@^2.0.0, log-symbols@^2.1.0: dependencies: chalk "^2.0.1" -log4js@^2.3.9: - version "2.11.0" - resolved "https://registry.yarnpkg.com/log4js/-/log4js-2.11.0.tgz#bf3902eff65c6923d9ce9cfbd2db54160e34005a" +log4js@^3.0.0: + version "3.0.5" + resolved "https://registry.yarnpkg.com/log4js/-/log4js-3.0.5.tgz#b80146bfebad68b430d4f3569556d8a6edfef303" dependencies: - circular-json "^0.5.4" + circular-json "^0.5.5" date-format "^1.2.0" debug "^3.1.0" - semver "^5.5.0" + rfdc "^1.1.2" streamroller "0.7.0" - optionalDependencies: - amqplib "^0.5.2" - axios "^0.15.3" - hipchat-notifier "^1.1.0" - loggly "^1.1.0" - mailgun-js "^0.18.0" - nodemailer "^2.5.0" - redis "^2.7.1" - slack-node "~0.2.0" - -loggly@^1.1.0: - version "1.1.1" - resolved "https://registry.yarnpkg.com/loggly/-/loggly-1.1.1.tgz#0a0fc1d3fa3a5ec44fdc7b897beba2a4695cebee" - dependencies: - json-stringify-safe "5.0.x" - request "2.75.x" - timespan "2.3.x" loglevel@^1.4.1: version "1.6.1" @@ -5419,7 +4981,11 @@ lowercase-keys@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/lowercase-keys/-/lowercase-keys-1.0.1.tgz#6f9e30b47084d971a7c820ff15a6c5167b74c26f" -lru-cache@4.1.x, lru-cache@^4.0.1, lru-cache@^4.1.1, lru-cache@^4.1.2: +lru-cache@2.2.x: + version "2.2.4" + resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-2.2.4.tgz#6c658619becf14031d0d0b594b16042ce4dc063d" + +lru-cache@^4.0.1, lru-cache@^4.1.1: version "4.1.3" resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-4.1.3.tgz#a1175cf3496dfc8436c156c334b4955992bce69c" dependencies: @@ -5432,27 +4998,6 @@ magic-string@^0.22.4: dependencies: vlq "^0.2.2" -mailcomposer@4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/mailcomposer/-/mailcomposer-4.0.1.tgz#0e1c44b2a07cf740ee17dc149ba009f19cadfeb4" - dependencies: - buildmail "4.0.1" - libmime "3.0.0" - -mailgun-js@^0.18.0: - version "0.18.1" - resolved "https://registry.yarnpkg.com/mailgun-js/-/mailgun-js-0.18.1.tgz#ee39aa18d7bb598a5ce9ede84afb681defc8a6b0" - dependencies: - async "~2.6.0" - debug "~3.1.0" - form-data "~2.3.0" - inflection "~1.12.0" - is-stream "^1.1.0" - path-proxy "~1.0.0" - promisify-call "^2.0.2" - proxy-agent "~3.0.0" - tsscmp "~1.0.0" - make-dir@^1.0.0: version "1.3.0" resolved "https://registry.yarnpkg.com/make-dir/-/make-dir-1.3.0.tgz#79c1033b80515bd6d24ec9933e860ca75ee27f0c" @@ -5617,7 +5162,7 @@ miller-rabin@^4.0.0: version "1.36.0" resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.36.0.tgz#5020478db3c7fe93aad7bbcc4dcf869c43363397" -mime-types@^2.1.11, mime-types@^2.1.12, mime-types@~2.1.17, mime-types@~2.1.18, mime-types@~2.1.19, mime-types@~2.1.7: +mime-types@^2.1.12, mime-types@~2.1.17, mime-types@~2.1.18, mime-types@~2.1.19: version "2.1.20" resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.20.tgz#930cb719d571e903738520f8470911548ca2cc19" dependencies: @@ -5627,7 +5172,7 @@ mime@1.4.1: version "1.4.1" resolved "https://registry.yarnpkg.com/mime/-/mime-1.4.1.tgz#121f9ebc49e3766f311a76e1fa1c8003c4b03aa6" -mime@^1.3.4, mime@^1.6.0: +mime@^1.6.0: version "1.6.0" resolved "https://registry.yarnpkg.com/mime/-/mime-1.6.0.tgz#32cd9e5c64553bd58d19a568af452acff04981b1" @@ -5717,26 +5262,6 @@ mkdirp@0.5.1, mkdirp@0.5.x, "mkdirp@>=0.5 0", mkdirp@^0.5.0, mkdirp@^0.5.1, mkdi dependencies: minimist "0.0.8" -module-deps@^4.0.8: - version "4.1.1" - resolved "https://registry.yarnpkg.com/module-deps/-/module-deps-4.1.1.tgz#23215833f1da13fd606ccb8087b44852dcb821fd" - dependencies: - JSONStream "^1.0.3" - browser-resolve "^1.7.0" - cached-path-relative "^1.0.0" - concat-stream "~1.5.0" - defined "^1.0.0" - detective "^4.0.0" - duplexer2 "^0.1.2" - inherits "^2.0.1" - parents "^1.0.0" - readable-stream "^2.0.2" - resolve "^1.1.3" - stream-combiner2 "^1.1.1" - subarg "^1.0.0" - through2 "^2.0.0" - xtend "^4.0.0" - moment@^2.22.1: version "2.22.2" resolved "https://registry.yarnpkg.com/moment/-/moment-2.22.2.tgz#3c257f9839fc0e93ff53149632239eb90783ff66" @@ -5823,14 +5348,14 @@ neo-async@^2.5.0: version "2.5.2" resolved "https://registry.yarnpkg.com/neo-async/-/neo-async-2.5.2.tgz#489105ce7bc54e709d736b195f82135048c50fcc" -netmask@^1.0.6: - version "1.0.6" - resolved "https://registry.yarnpkg.com/netmask/-/netmask-1.0.6.tgz#20297e89d86f6f6400f250d9f4f6b4c1945fcd35" - next-tick@1: version "1.0.0" resolved "https://registry.yarnpkg.com/next-tick/-/next-tick-1.0.0.tgz#ca86d1fe8828169b0120208e3dc8424b9db8342c" +ng-mocks@^6.2.1: + version "6.2.1" + resolved "https://registry.yarnpkg.com/ng-mocks/-/ng-mocks-6.2.1.tgz#4655336de88eefec80032563b1ee968457d2dc9b" + ng2-file-upload@1.2.1: version "1.2.1" resolved "https://registry.yarnpkg.com/ng2-file-upload/-/ng2-file-upload-1.2.1.tgz#5563c5dfd6f43fbfbe815c206e343464a0a6a197" @@ -5976,59 +5501,6 @@ node-sass@^4.7.2: stdout-stream "^1.4.0" "true-case-path" "^1.0.2" -node-uuid@~1.4.7: - version "1.4.8" - resolved "https://registry.yarnpkg.com/node-uuid/-/node-uuid-1.4.8.tgz#b040eb0923968afabf8d32fb1f17f1167fdab907" - -nodemailer-direct-transport@3.3.2: - version "3.3.2" - resolved "https://registry.yarnpkg.com/nodemailer-direct-transport/-/nodemailer-direct-transport-3.3.2.tgz#e96fafb90358560947e569017d97e60738a50a86" - dependencies: - nodemailer-shared "1.1.0" - smtp-connection "2.12.0" - -nodemailer-fetch@1.6.0: - version "1.6.0" - resolved "https://registry.yarnpkg.com/nodemailer-fetch/-/nodemailer-fetch-1.6.0.tgz#79c4908a1c0f5f375b73fe888da9828f6dc963a4" - -nodemailer-shared@1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/nodemailer-shared/-/nodemailer-shared-1.1.0.tgz#cf5994e2fd268d00f5cf0fa767a08169edb07ec0" - dependencies: - nodemailer-fetch "1.6.0" - -nodemailer-smtp-pool@2.8.2: - version "2.8.2" - resolved "https://registry.yarnpkg.com/nodemailer-smtp-pool/-/nodemailer-smtp-pool-2.8.2.tgz#2eb94d6cf85780b1b4725ce853b9cbd5e8da8c72" - dependencies: - nodemailer-shared "1.1.0" - nodemailer-wellknown "0.1.10" - smtp-connection "2.12.0" - -nodemailer-smtp-transport@2.7.2: - version "2.7.2" - resolved "https://registry.yarnpkg.com/nodemailer-smtp-transport/-/nodemailer-smtp-transport-2.7.2.tgz#03d71c76314f14ac7dbc7bf033a6a6d16d67fb77" - dependencies: - nodemailer-shared "1.1.0" - nodemailer-wellknown "0.1.10" - smtp-connection "2.12.0" - -nodemailer-wellknown@0.1.10: - version "0.1.10" - resolved "https://registry.yarnpkg.com/nodemailer-wellknown/-/nodemailer-wellknown-0.1.10.tgz#586db8101db30cb4438eb546737a41aad0cf13d5" - -nodemailer@^2.5.0: - version "2.7.2" - resolved "https://registry.yarnpkg.com/nodemailer/-/nodemailer-2.7.2.tgz#f242e649aeeae39b6c7ed740ef7b061c404d30f9" - dependencies: - libmime "3.0.0" - mailcomposer "4.0.1" - nodemailer-direct-transport "3.3.2" - nodemailer-shared "1.1.0" - nodemailer-smtp-pool "2.8.2" - nodemailer-smtp-transport "2.7.2" - socks "1.1.9" - nodemon@^1.15.0: version "1.18.4" resolved "https://registry.yarnpkg.com/nodemon/-/nodemon-1.18.4.tgz#873f65fdb53220eb166180cf106b1354ac5d714d" @@ -6063,7 +5535,7 @@ nopt@~1.0.10: dependencies: abbrev "1" -normalize-package-data@^2.3.2, normalize-package-data@^2.3.4: +normalize-package-data@^2.3.2, normalize-package-data@^2.3.4, "normalize-package-data@~1.0.1 || ^2.0.0": version "2.4.0" resolved "https://registry.yarnpkg.com/normalize-package-data/-/normalize-package-data-2.4.0.tgz#12f95a307d58352075a04907b84ac8be98ac012f" dependencies: @@ -6090,6 +5562,15 @@ npm-bundled@^1.0.1: version "1.0.5" resolved "https://registry.yarnpkg.com/npm-bundled/-/npm-bundled-1.0.5.tgz#3c1732b7ba936b3a10325aef616467c0ccbcc979" +"npm-package-arg@^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0": + version "6.1.0" + resolved "https://registry.yarnpkg.com/npm-package-arg/-/npm-package-arg-6.1.0.tgz#15ae1e2758a5027efb4c250554b85a737db7fcc1" + dependencies: + hosted-git-info "^2.6.0" + osenv "^0.1.5" + semver "^5.5.0" + validate-npm-package-name "^3.0.0" + npm-packlist@^1.1.6: version "1.1.11" resolved "https://registry.yarnpkg.com/npm-packlist/-/npm-packlist-1.1.11.tgz#84e8c683cbe7867d34b1d357d893ce29e28a02de" @@ -6097,13 +5578,31 @@ npm-packlist@^1.1.6: ignore-walk "^3.0.1" npm-bundled "^1.0.1" -npm-run-all@4.1.2: - version "4.1.2" - resolved "https://registry.yarnpkg.com/npm-run-all/-/npm-run-all-4.1.2.tgz#90d62d078792d20669139e718621186656cea056" +npm-registry-client@^8.5.1: + version "8.6.0" + resolved "https://registry.yarnpkg.com/npm-registry-client/-/npm-registry-client-8.6.0.tgz#7f1529f91450732e89f8518e0f21459deea3e4c4" + dependencies: + concat-stream "^1.5.2" + graceful-fs "^4.1.6" + normalize-package-data "~1.0.1 || ^2.0.0" + npm-package-arg "^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0" + once "^1.3.3" + request "^2.74.0" + retry "^0.10.0" + safe-buffer "^5.1.1" + semver "2 >=2.2.1 || 3.x || 4 || 5" + slide "^1.1.3" + ssri "^5.2.4" + optionalDependencies: + npmlog "2 || ^3.1.0 || ^4.0.0" + +npm-run-all@4.1.3: + version "4.1.3" + resolved "https://registry.yarnpkg.com/npm-run-all/-/npm-run-all-4.1.3.tgz#49f15b55a66bb4101664ce270cb18e7103f8f185" dependencies: ansi-styles "^3.2.0" chalk "^2.1.0" - cross-spawn "^5.1.0" + cross-spawn "^6.0.4" memorystream "^0.3.1" minimatch "^3.0.4" ps-tree "^1.1.0" @@ -6117,7 +5616,7 @@ npm-run-path@^2.0.0: dependencies: path-key "^2.0.0" -"npmlog@0 || 1 || 2 || 3 || 4", npmlog@^4.0.0, npmlog@^4.0.2: +"npmlog@0 || 1 || 2 || 3 || 4", "npmlog@2 || ^3.1.0 || ^4.0.0", npmlog@^4.0.0, npmlog@^4.0.2: version "4.1.2" resolved "https://registry.yarnpkg.com/npmlog/-/npmlog-4.1.2.tgz#08a7f2a8bf734604779a9efa4ad5cc717abb954b" dependencies: @@ -6144,7 +5643,7 @@ number-is-nan@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/number-is-nan/-/number-is-nan-1.0.1.tgz#097b602b53422a522c1afb8790318336941a011d" -oauth-sign@~0.8.1, oauth-sign@~0.8.2: +oauth-sign@~0.8.2: version "0.8.2" resolved "https://registry.yarnpkg.com/oauth-sign/-/oauth-sign-0.8.2.tgz#46a6ab7f0aead8deae9ec0565780b7d4efeb9d43" @@ -6229,7 +5728,7 @@ on-headers@~1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/on-headers/-/on-headers-1.0.1.tgz#928f5d0f470d49342651ea6794b0857c100693f7" -once@1.x, once@^1.3.0, once@^1.3.1, once@^1.4.0: +once@1.x, once@^1.3.0, once@^1.3.1, once@^1.3.3, once@^1.4.0: version "1.4.0" resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" dependencies: @@ -6271,7 +5770,7 @@ opn@4.0.2: object-assign "^4.0.1" pinkie-promise "^2.0.0" -opn@^5.1.0: +opn@^5.1.0, opn@^5.3.0: version "5.3.0" resolved "https://registry.yarnpkg.com/opn/-/opn-5.3.0.tgz#64871565c863875f052cfdf53d3e3cb5adb53b1c" dependencies: @@ -6301,11 +5800,11 @@ original@>=0.0.5: dependencies: url-parse "^1.4.3" -os-browserify@^0.3.0, os-browserify@~0.3.0: +os-browserify@^0.3.0: version "0.3.0" resolved "https://registry.yarnpkg.com/os-browserify/-/os-browserify-0.3.0.tgz#854373c7f5c2315914fc9bfc6bd8238fdda1ec27" -os-homedir@^1.0.0, os-homedir@^1.0.1: +os-homedir@^1.0.0: version "1.0.2" resolved "https://registry.yarnpkg.com/os-homedir/-/os-homedir-1.0.2.tgz#ffbc4988336e0e833de0c168c7ef152121aa7fb3" @@ -6327,7 +5826,7 @@ os-tmpdir@^1.0.0, os-tmpdir@^1.0.1, os-tmpdir@~1.0.1, os-tmpdir@~1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/os-tmpdir/-/os-tmpdir-1.0.2.tgz#bbe67406c79aa85c5cfec766fe5734555dfa1274" -osenv@0, osenv@^0.1.4: +osenv@0, osenv@^0.1.4, osenv@^0.1.5: version "0.1.5" resolved "https://registry.yarnpkg.com/osenv/-/osenv-0.1.5.tgz#85cdfafaeb28e8677f416e287592b5f3f49ea410" dependencies: @@ -6374,29 +5873,6 @@ p-try@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/p-try/-/p-try-2.0.0.tgz#85080bb87c64688fa47996fe8f7dfbe8211760b1" -pac-proxy-agent@^2.0.1: - version "2.0.2" - resolved "https://registry.yarnpkg.com/pac-proxy-agent/-/pac-proxy-agent-2.0.2.tgz#90d9f6730ab0f4d2607dcdcd4d3d641aa26c3896" - dependencies: - agent-base "^4.2.0" - debug "^3.1.0" - get-uri "^2.0.0" - http-proxy-agent "^2.1.0" - https-proxy-agent "^2.2.1" - pac-resolver "^3.0.0" - raw-body "^2.2.0" - socks-proxy-agent "^3.0.0" - -pac-resolver@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/pac-resolver/-/pac-resolver-3.0.0.tgz#6aea30787db0a891704deb7800a722a7615a6f26" - dependencies: - co "^4.6.0" - degenerator "^1.0.4" - ip "^1.1.5" - netmask "^1.0.6" - thunkify "^2.1.2" - package-json@^4.0.0: version "4.0.1" resolved "https://registry.yarnpkg.com/package-json/-/package-json-4.0.1.tgz#8869a0401253661c4c4ca3da6c2121ed555f5eed" @@ -6424,12 +5900,6 @@ param-case@2.1.x: dependencies: no-case "^2.2.0" -parents@^1.0.0, parents@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/parents/-/parents-1.0.1.tgz#fedd4d2bf193a77745fe71e371d73c3307d9c751" - dependencies: - path-platform "~0.11.15" - parse-asn1@^5.0.0: version "5.1.1" resolved "https://registry.yarnpkg.com/parse-asn1/-/parse-asn1-5.1.1.tgz#f6bf293818332bd0dab54efb16087724745e6ca8" @@ -6490,10 +5960,6 @@ path-browserify@0.0.0: version "0.0.0" resolved "https://registry.yarnpkg.com/path-browserify/-/path-browserify-0.0.0.tgz#a0b870729aae214005b7d5032ec2cbbb0fb4451a" -path-browserify@~0.0.0: - version "0.0.1" - resolved "https://registry.yarnpkg.com/path-browserify/-/path-browserify-0.0.1.tgz#e6c4ddd7ed3aa27c68a20cc4e50e1a4ee83bbc4a" - path-dirname@^1.0.0: version "1.0.2" resolved "https://registry.yarnpkg.com/path-dirname/-/path-dirname-1.0.2.tgz#cc33d24d525e099a5388c0336c6e32b9160609e0" @@ -6508,7 +5974,7 @@ path-exists@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-3.0.0.tgz#ce0ebeaa5f78cb18925ea7d810d7b59b010fd515" -path-is-absolute@^1.0.0, path-is-absolute@^1.0.1: +path-is-absolute@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" @@ -6524,16 +5990,6 @@ path-parse@^1.0.5: version "1.0.6" resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.6.tgz#d62dbb5679405d72c4737ec58600e9ddcf06d24c" -path-platform@~0.11.15: - version "0.11.15" - resolved "https://registry.yarnpkg.com/path-platform/-/path-platform-0.11.15.tgz#e864217f74c36850f0852b78dc7bf7d4a5721bf2" - -path-proxy@~1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/path-proxy/-/path-proxy-1.0.0.tgz#18e8a36859fc9d2f1a53b48dee138543c020de5e" - dependencies: - inflection "~1.3.0" - path-to-regexp@0.1.7: version "0.1.7" resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-0.1.7.tgz#df604178005f522f15eb4490e7247a1bfaa67f8c" @@ -6660,7 +6116,15 @@ posix-character-classes@^0.1.0: version "0.1.1" resolved "https://registry.yarnpkg.com/posix-character-classes/-/posix-character-classes-0.1.1.tgz#01eac0fe3b5af71a2a6c02feabb8c1fef7e00eab" -postcss-apply@0.8.0, postcss-apply@^0.8.0: +postcss-apply@0.11.0: + version "0.11.0" + resolved "https://registry.yarnpkg.com/postcss-apply/-/postcss-apply-0.11.0.tgz#4bef9b443e4bfeeec5b094c7008bfe25dca5f40d" + dependencies: + babel-runtime "^6.26.0" + balanced-match "^1.0.0" + postcss "^7.0.2" + +postcss-apply@^0.8.0: version "0.8.0" resolved "https://registry.yarnpkg.com/postcss-apply/-/postcss-apply-0.8.0.tgz#14e544bbb5cb6f1c1e048857965d79ae066b1343" dependencies: @@ -6684,22 +6148,22 @@ postcss-calc@^6.0.0: postcss-selector-parser "^2.2.2" reduce-css-calc "^2.0.0" -postcss-cli@^5.0.0: - version "5.0.1" - resolved "https://registry.yarnpkg.com/postcss-cli/-/postcss-cli-5.0.1.tgz#95f309fffbee3273c161704e2b9f58d5a4993cf1" +postcss-cli@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/postcss-cli/-/postcss-cli-6.0.0.tgz#688e3750735a7bc21ea6e2f0e427f5f873c16f0b" dependencies: chalk "^2.1.0" chokidar "^2.0.0" dependency-graph "^0.7.0" - fs-extra "^5.0.0" + fs-extra "^7.0.0" get-stdin "^6.0.0" globby "^8.0.0" - postcss "^6.0.1" - postcss-load-config "^1.1.0" + postcss "^7.0.0" + postcss-load-config "^2.0.0" postcss-reporter "^5.0.0" pretty-hrtime "^1.0.3" read-cache "^1.0.0" - yargs "^11.0.0" + yargs "^12.0.1" postcss-color-function@^4.0.0: version "4.0.1" @@ -6848,15 +6312,6 @@ postcss-initial@^2.0.0: lodash.template "^4.2.4" postcss "^6.0.1" -postcss-load-config@^1.1.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/postcss-load-config/-/postcss-load-config-1.2.0.tgz#539e9afc9ddc8620121ebf9d8c3673e0ce50d28a" - dependencies: - cosmiconfig "^2.1.0" - object-assign "^4.1.0" - postcss-load-options "^1.2.0" - postcss-load-plugins "^2.3.0" - postcss-load-config@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/postcss-load-config/-/postcss-load-config-2.0.0.tgz#f1312ddbf5912cd747177083c5ef7a19d62ee484" @@ -6864,28 +6319,14 @@ postcss-load-config@^2.0.0: cosmiconfig "^4.0.0" import-cwd "^2.0.0" -postcss-load-options@^1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/postcss-load-options/-/postcss-load-options-1.2.0.tgz#b098b1559ddac2df04bc0bb375f99a5cfe2b6d8c" - dependencies: - cosmiconfig "^2.1.0" - object-assign "^4.1.0" - -postcss-load-plugins@^2.3.0: - version "2.3.0" - resolved "https://registry.yarnpkg.com/postcss-load-plugins/-/postcss-load-plugins-2.3.0.tgz#745768116599aca2f009fad426b00175049d8d92" - dependencies: - cosmiconfig "^2.1.1" - object-assign "^4.1.0" - -postcss-loader@^2.1.0: - version "2.1.6" - resolved "https://registry.yarnpkg.com/postcss-loader/-/postcss-loader-2.1.6.tgz#1d7dd7b17c6ba234b9bed5af13e0bea40a42d740" +postcss-loader@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/postcss-loader/-/postcss-loader-3.0.0.tgz#6b97943e47c72d845fa9e03f273773d4e8dd6c2d" dependencies: loader-utils "^1.1.0" - postcss "^6.0.0" + postcss "^7.0.0" postcss-load-config "^2.0.0" - schema-utils "^0.4.0" + schema-utils "^1.0.0" postcss-media-minmax@^3.0.0: version "3.0.0" @@ -7039,7 +6480,7 @@ postcss@^6.0, postcss@^6.0.0, postcss@^6.0.1, postcss@^6.0.11, postcss@^6.0.14, source-map "^0.6.1" supports-color "^5.4.0" -postcss@^7.0.2: +postcss@^7.0.0, postcss@^7.0.2: version "7.0.2" resolved "https://registry.yarnpkg.com/postcss/-/postcss-7.0.2.tgz#7b5a109de356804e27f95a960bef0e4d5bc9bb18" dependencies: @@ -7082,7 +6523,7 @@ process-nextick-args@~2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-2.0.0.tgz#a37d732f4271b4ab1ad070d35508e8290788ffaa" -process@^0.11.10, process@~0.11.0: +process@^0.11.10: version "0.11.10" resolved "https://registry.yarnpkg.com/process/-/process-0.11.10.tgz#7332300e840161bda3e69a1d1d91a7d4bc16f182" @@ -7104,12 +6545,6 @@ promise-inflight@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/promise-inflight/-/promise-inflight-1.0.1.tgz#98472870bf228132fcbdd868129bad12c3c029e3" -promisify-call@^2.0.2: - version "2.0.4" - resolved "https://registry.yarnpkg.com/promisify-call/-/promisify-call-2.0.4.tgz#d48c2d45652ccccd52801ddecbd533a6d4bd5fba" - dependencies: - with-callback "^1.0.2" - protractor-istanbul-plugin@2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/protractor-istanbul-plugin/-/protractor-istanbul-plugin-2.0.0.tgz#f6271d2a5d6382488e86ff9fb7770f46a8b2c5e2" @@ -7147,23 +6582,6 @@ proxy-addr@~2.0.2, proxy-addr@~2.0.3: forwarded "~0.1.2" ipaddr.js "1.8.0" -proxy-agent@~3.0.0: - version "3.0.1" - resolved "https://registry.yarnpkg.com/proxy-agent/-/proxy-agent-3.0.1.tgz#4fb7b61b1476d0fe8e3a3384d90e2460bbded3f9" - dependencies: - agent-base "^4.2.0" - debug "^3.1.0" - http-proxy-agent "^2.1.0" - https-proxy-agent "^2.2.1" - lru-cache "^4.1.2" - pac-proxy-agent "^2.0.1" - proxy-from-env "^1.0.0" - socks-proxy-agent "^4.0.1" - -proxy-from-env@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/proxy-from-env/-/proxy-from-env-1.0.0.tgz#33c50398f70ea7eb96d21f7b817630a55791c7ee" - prr@~1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/prr/-/prr-1.0.1.tgz#d3fc114ba06995a45ec6893f484ceb1d78f5f476" @@ -7217,7 +6635,7 @@ punycode@1.3.2: version "1.3.2" resolved "https://registry.yarnpkg.com/punycode/-/punycode-1.3.2.tgz#9653a036fb7c1ee42342f2325cceefea3926c48d" -punycode@1.4.1, punycode@^1.2.4, punycode@^1.3.2, punycode@^1.4.1: +punycode@^1.2.4, punycode@^1.4.1: version "1.4.1" resolved "https://registry.yarnpkg.com/punycode/-/punycode-1.4.1.tgz#c0d5a63b2718800ad8e1eb0fa5269c84dd41845e" @@ -7249,11 +6667,7 @@ qs@~2.3.3: version "2.3.3" resolved "https://registry.yarnpkg.com/qs/-/qs-2.3.3.tgz#e9e85adbe75da0bbe4c8e0476a086290f863b404" -qs@~6.2.0: - version "6.2.3" - resolved "https://registry.yarnpkg.com/qs/-/qs-6.2.3.tgz#1cfcb25c10a9b2b483053ff39f5dfc9233908cfe" - -querystring-es3@^0.2.0, querystring-es3@~0.2.0: +querystring-es3@^0.2.0: version "0.2.1" resolved "https://registry.yarnpkg.com/querystring-es3/-/querystring-es3-0.2.1.tgz#9ec61f79049875707d69414596fd907a4d711e73" @@ -7303,7 +6717,7 @@ raw-body@2.3.2: iconv-lite "0.4.19" unpipe "1.0.0" -raw-body@2.3.3, raw-body@^2.2.0: +raw-body@2.3.3: version "2.3.3" resolved "https://registry.yarnpkg.com/raw-body/-/raw-body-2.3.3.tgz#1b324ece6b5706e153855bc1148c65bb7f6ea0c3" dependencies: @@ -7331,12 +6745,6 @@ read-cache@^1.0.0: dependencies: pify "^2.3.0" -read-only-stream@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/read-only-stream/-/read-only-stream-2.0.0.tgz#2724fd6a8113d73764ac288d4386270c1dbf17f0" - dependencies: - readable-stream "^2.0.2" - read-pkg-up@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/read-pkg-up/-/read-pkg-up-1.0.1.tgz#9d63c13276c065918d57f002a57f40a1b643fb02" @@ -7360,7 +6768,7 @@ read-pkg@^3.0.0: normalize-package-data "^2.3.2" path-type "^3.0.0" -"readable-stream@1 || 2", readable-stream@2, readable-stream@^2.0.0, readable-stream@^2.0.1, readable-stream@^2.0.2, readable-stream@^2.0.4, readable-stream@^2.0.5, readable-stream@^2.0.6, readable-stream@^2.1.5, readable-stream@^2.2.2, readable-stream@^2.2.9, readable-stream@^2.3.0, readable-stream@^2.3.3, readable-stream@^2.3.5, readable-stream@^2.3.6: +"readable-stream@1 || 2", readable-stream@^2.0.0, readable-stream@^2.0.1, readable-stream@^2.0.2, readable-stream@^2.0.4, readable-stream@^2.0.5, readable-stream@^2.0.6, readable-stream@^2.1.5, readable-stream@^2.2.2, readable-stream@^2.2.9, readable-stream@^2.3.0, readable-stream@^2.3.3, readable-stream@^2.3.5, readable-stream@^2.3.6: version "2.3.6" resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.6.tgz#b11c27d88b8ff1fbe070643cf94b0c79ae1b0aaf" dependencies: @@ -7381,7 +6789,7 @@ readable-stream@1.0: isarray "0.0.1" string_decoder "~0.10.x" -readable-stream@1.1.x, "readable-stream@1.x >=1.1.9", readable-stream@~1.1.9: +readable-stream@~1.1.9: version "1.1.14" resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-1.1.14.tgz#7cf4c54ef648e3813084c636dd2079e166c081d9" dependencies: @@ -7390,7 +6798,7 @@ readable-stream@1.1.x, "readable-stream@1.x >=1.1.9", readable-stream@~1.1.9: isarray "0.0.1" string_decoder "~0.10.x" -readable-stream@~2.0.0, readable-stream@~2.0.5, readable-stream@~2.0.6: +readable-stream@~2.0.0, readable-stream@~2.0.6: version "2.0.6" resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.0.6.tgz#8f90341e68a53ccc928788dacfcd11b36eb9b78e" dependencies: @@ -7423,22 +6831,6 @@ redent@^1.0.0: indent-string "^2.1.0" strip-indent "^1.0.1" -redis-commands@^1.2.0: - version "1.3.5" - resolved "https://registry.yarnpkg.com/redis-commands/-/redis-commands-1.3.5.tgz#4495889414f1e886261180b1442e7295602d83a2" - -redis-parser@^2.6.0: - version "2.6.0" - resolved "https://registry.yarnpkg.com/redis-parser/-/redis-parser-2.6.0.tgz#52ed09dacac108f1a631c07e9b69941e7a19504b" - -redis@^2.7.1: - version "2.8.0" - resolved "https://registry.yarnpkg.com/redis/-/redis-2.8.0.tgz#202288e3f58c49f6079d97af7a10e1303ae14b02" - dependencies: - double-ended-queue "^2.1.0-0" - redis-commands "^1.2.0" - redis-parser "^2.6.0" - reduce-css-calc@^1.2.7: version "1.3.0" resolved "https://registry.yarnpkg.com/reduce-css-calc/-/reduce-css-calc-1.3.0.tgz#747c914e049614a4c9cfbba629871ad1d2927716" @@ -7592,32 +6984,6 @@ request-progress@^2.0.1: dependencies: throttleit "^1.0.0" -request@2.75.x: - version "2.75.0" - resolved "http://registry.npmjs.org/request/-/request-2.75.0.tgz#d2b8268a286da13eaa5d01adf5d18cc90f657d93" - dependencies: - aws-sign2 "~0.6.0" - aws4 "^1.2.1" - bl "~1.1.2" - caseless "~0.11.0" - combined-stream "~1.0.5" - extend "~3.0.0" - forever-agent "~0.6.1" - form-data "~2.0.0" - har-validator "~2.0.6" - hawk "~3.1.3" - http-signature "~1.1.0" - is-typedarray "~1.0.0" - isstream "~0.1.2" - json-stringify-safe "~5.0.1" - mime-types "~2.1.7" - node-uuid "~1.4.7" - oauth-sign "~0.8.1" - qs "~6.2.0" - stringstream "~0.0.4" - tough-cookie "~2.3.0" - tunnel-agent "~0.4.1" - request@2.85.0: version "2.85.0" resolved "http://registry.npmjs.org/request/-/request-2.85.0.tgz#5a03615a47c61420b3eb99b7dba204f83603e1fa" @@ -7670,7 +7036,7 @@ request@2.87.0: tunnel-agent "^0.6.0" uuid "^3.1.0" -request@^2.0.0, request@^2.74.0, request@^2.79.0, request@^2.81.0, request@^2.87.0: +request@^2.74.0, request@^2.79.0, request@^2.81.0, request@^2.87.0: version "2.88.0" resolved "https://registry.yarnpkg.com/request/-/request-2.88.0.tgz#9c2fca4f7d35b592efe57c7f0a55e81052124fef" dependencies: @@ -7695,23 +7061,10 @@ request@^2.0.0, request@^2.74.0, request@^2.79.0, request@^2.81.0, request@^2.87 tunnel-agent "^0.6.0" uuid "^3.3.2" -requestretry@^1.2.2: - version "1.13.0" - resolved "https://registry.yarnpkg.com/requestretry/-/requestretry-1.13.0.tgz#213ec1006eeb750e8b8ce54176283d15a8d55d94" - dependencies: - extend "^3.0.0" - lodash "^4.15.0" - request "^2.74.0" - when "^3.7.7" - require-directory@^2.1.1: version "2.1.1" resolved "https://registry.yarnpkg.com/require-directory/-/require-directory-2.1.1.tgz#8c64ad5fd30dab1c976e2344ffe7f792a6a6df42" -require-from-string@^1.1.0: - version "1.2.1" - resolved "https://registry.yarnpkg.com/require-from-string/-/require-from-string-1.2.1.tgz#529c9ccef27380adfec9a2f965b649bbee636418" - require-from-string@^2.0.1: version "2.0.2" resolved "https://registry.yarnpkg.com/require-from-string/-/require-from-string-2.0.2.tgz#89a7fdd938261267318eafe14f9c32e598c36909" @@ -7752,11 +7105,11 @@ resolve-url@^0.2.1: version "0.2.1" resolved "https://registry.yarnpkg.com/resolve-url/-/resolve-url-0.2.1.tgz#2c637fe77c893afd2a663fe21aa9080068e2052a" -resolve@1.1.7, resolve@1.1.x: +resolve@1.1.x: version "1.1.7" resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.1.7.tgz#203114d82ad2c5ed9e8e0411b3932875e889e97b" -resolve@^1.1.3, resolve@^1.1.4, resolve@^1.1.6, resolve@^1.3.2, resolve@^1.5.0: +resolve@^1.1.6, resolve@^1.3.2, resolve@^1.5.0: version "1.8.1" resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.8.1.tgz#82f1ec19a423ac1fbd080b0bab06ba36e84a7a26" dependencies: @@ -7773,6 +7126,10 @@ ret@~0.1.10: version "0.1.15" resolved "https://registry.yarnpkg.com/ret/-/ret-0.1.15.tgz#b8a4825d5bdb1fc3f6f53c2bc33f81388681c7bc" +retry@^0.10.0: + version "0.10.1" + resolved "https://registry.yarnpkg.com/retry/-/retry-0.10.1.tgz#e76388d217992c252750241d3d3956fed98d8ff4" + rework-visit@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/rework-visit/-/rework-visit-1.0.0.tgz#9945b2803f219e2f7aca00adb8bc9f640f842c9a" @@ -7784,6 +7141,10 @@ rework@^1.0.1: convert-source-map "^0.3.3" css "^2.0.0" +rfdc@^1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/rfdc/-/rfdc-1.1.2.tgz#e6e72d74f5dc39de8f538f65e00c36c18018e349" + rgb-hex@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/rgb-hex/-/rgb-hex-2.1.0.tgz#c773c5fe2268a25578d92539a82a7a5ce53beda6" @@ -7877,18 +7238,12 @@ rx@^4.1.0: version "4.1.0" resolved "https://registry.yarnpkg.com/rx/-/rx-4.1.0.tgz#a5f13ff79ef3b740fe30aa803fb09f98805d4782" -rxjs@^6.0.0, rxjs@^6.2.2: +rxjs@6.2.2, rxjs@^6.0.0, rxjs@^6.1.0: version "6.2.2" resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-6.2.2.tgz#eb75fa3c186ff5289907d06483a77884586e1cf9" dependencies: tslib "^1.9.0" -rxjs@^6.1.0: - version "6.3.0" - resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-6.3.0.tgz#e55b05ad4bdf351db4b45756638dfa368260a8a3" - dependencies: - tslib "^1.9.0" - safe-buffer@5.1.1: version "5.1.1" resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.1.tgz#893312af69b2123def71f57889001671eeb2c853" @@ -7916,15 +7271,16 @@ sass-graph@^2.2.4: scss-tokenizer "^0.2.3" yargs "^7.0.0" -sass-loader@6.0.6: - version "6.0.6" - resolved "https://registry.yarnpkg.com/sass-loader/-/sass-loader-6.0.6.tgz#e9d5e6c1f155faa32a4b26d7a9b7107c225e40f9" +sass-loader@7.1.0: + version "7.1.0" + resolved "https://registry.yarnpkg.com/sass-loader/-/sass-loader-7.1.0.tgz#16fd5138cb8b424bf8a759528a1972d72aad069d" dependencies: - async "^2.1.5" - clone-deep "^0.3.0" + clone-deep "^2.0.1" loader-utils "^1.0.1" lodash.tail "^4.1.1" + neo-async "^2.5.0" pify "^3.0.0" + semver "^5.5.0" saucelabs@^1.5.0: version "1.5.0" @@ -7942,7 +7298,7 @@ schema-utils@^0.3.0: dependencies: ajv "^5.0.0" -schema-utils@^0.4.0, schema-utils@^0.4.4, schema-utils@^0.4.5: +schema-utils@^0.4.4, schema-utils@^0.4.5: version "0.4.7" resolved "https://registry.yarnpkg.com/schema-utils/-/schema-utils-0.4.7.tgz#ba74f597d2be2ea880131746ee17d0a093c68187" dependencies: @@ -8001,7 +7357,13 @@ semver-dsl@^1.0.1: dependencies: semver "^5.3.0" -"semver@2 || 3 || 4 || 5", semver@^5.0.3, semver@^5.1.0, semver@^5.3.0, semver@^5.5.0: +semver-intersect@^1.1.2: + version "1.4.0" + resolved "https://registry.yarnpkg.com/semver-intersect/-/semver-intersect-1.4.0.tgz#bdd9c06bedcdd2fedb8cd352c3c43ee8c61321f3" + dependencies: + semver "^5.0.0" + +"semver@2 >=2.2.1 || 3.x || 4 || 5", "semver@2 || 3 || 4 || 5", semver@^5.0.0, semver@^5.0.3, semver@^5.1.0, semver@^5.3.0, semver@^5.5.0: version "5.5.1" resolved "https://registry.yarnpkg.com/semver/-/semver-5.5.1.tgz#7dfdd8814bdb7cabc7be0fb1d734cfb66c940477" @@ -8117,29 +7479,21 @@ setprototypeof@1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/setprototypeof/-/setprototypeof-1.1.0.tgz#d0bd85536887b6fe7c0d818cb962d9d91c54e656" -sha.js@^2.4.0, sha.js@^2.4.8, sha.js@~2.4.4: +sha.js@^2.4.0, sha.js@^2.4.8: version "2.4.11" resolved "https://registry.yarnpkg.com/sha.js/-/sha.js-2.4.11.tgz#37a5cf0b81ecbc6943de109ba2960d1b26584ae7" dependencies: inherits "^2.0.1" safe-buffer "^5.0.1" -shallow-clone@^0.1.2: - version "0.1.2" - resolved "https://registry.yarnpkg.com/shallow-clone/-/shallow-clone-0.1.2.tgz#5909e874ba77106d73ac414cfec1ffca87d97060" +shallow-clone@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/shallow-clone/-/shallow-clone-1.0.0.tgz#4480cd06e882ef68b2ad88a3ea54832e2c48b571" dependencies: is-extendable "^0.1.1" - kind-of "^2.0.1" - lazy-cache "^0.2.3" + kind-of "^5.0.0" mixin-object "^2.0.1" -shasum@^1.0.0: - version "1.0.2" - resolved "https://registry.yarnpkg.com/shasum/-/shasum-1.0.2.tgz#e7012310d8f417f4deb5712150e5678b87ae565f" - dependencies: - json-stable-stringify "~0.0.0" - sha.js "~2.4.4" - shebang-command@^1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-1.2.0.tgz#44aac65b695b03398968c39f363fee5deafdf1ea" @@ -8171,40 +7525,19 @@ signal-exit@^3.0.0, signal-exit@^3.0.2: version "3.0.2" resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.2.tgz#b5fdc08f1287ea1178628e415e25132b73646c6d" -simple-concat@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/simple-concat/-/simple-concat-1.0.0.tgz#7344cbb8b6e26fb27d66b2fc86f9f6d5997521c6" - simple-swizzle@^0.2.2: version "0.2.2" resolved "https://registry.yarnpkg.com/simple-swizzle/-/simple-swizzle-0.2.2.tgz#a4da6b635ffcccca33f70d17cb92592de95e557a" dependencies: is-arrayish "^0.3.1" -slack-node@~0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/slack-node/-/slack-node-0.2.0.tgz#de4b8dddaa8b793f61dbd2938104fdabf37dfa30" - dependencies: - requestretry "^1.2.2" - slash@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/slash/-/slash-1.0.0.tgz#c41f2f6c39fc16d1cd17ad4b5d896114ae470d55" -smart-buffer@^1.0.13, smart-buffer@^1.0.4: - version "1.1.15" - resolved "https://registry.yarnpkg.com/smart-buffer/-/smart-buffer-1.1.15.tgz#7f114b5b65fab3e2a35aa775bb12f0d1c649bf16" - -smart-buffer@^4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/smart-buffer/-/smart-buffer-4.0.1.tgz#07ea1ca8d4db24eb4cac86537d7d18995221ace3" - -smtp-connection@2.12.0: - version "2.12.0" - resolved "https://registry.yarnpkg.com/smtp-connection/-/smtp-connection-2.12.0.tgz#d76ef9127cb23c2259edb1e8349c2e8d5e2d74c1" - dependencies: - httpntlm "1.6.1" - nodemailer-shared "1.1.0" +slide@^1.1.3: + version "1.1.6" + resolved "https://registry.yarnpkg.com/slide/-/slide-1.1.6.tgz#56eb027d65b4d2dce6cb2e2d32c4d4afc9e1d707" snapdragon-node@^2.0.1: version "2.1.1" @@ -8233,12 +7566,6 @@ snapdragon@^0.8.1: source-map-resolve "^0.5.0" use "^3.1.0" -sntp@1.x.x: - version "1.0.9" - resolved "https://registry.yarnpkg.com/sntp/-/sntp-1.0.9.tgz#6541184cc90aeea6c6e7b35e2659082443c66198" - dependencies: - hoek "2.x.x" - sntp@2.x.x: version "2.1.0" resolved "https://registry.yarnpkg.com/sntp/-/sntp-2.1.0.tgz#2c6cec14fedc2222739caf9b5c3d85d1cc5a2cc8" @@ -8249,42 +7576,43 @@ socket.io-adapter@~1.1.0: version "1.1.1" resolved "https://registry.yarnpkg.com/socket.io-adapter/-/socket.io-adapter-1.1.1.tgz#2a805e8a14d6372124dd9159ad4502f8cb07f06b" -socket.io-client@2.0.4: - version "2.0.4" - resolved "https://registry.yarnpkg.com/socket.io-client/-/socket.io-client-2.0.4.tgz#0918a552406dc5e540b380dcd97afc4a64332f8e" +socket.io-client@2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/socket.io-client/-/socket.io-client-2.1.1.tgz#dcb38103436ab4578ddb026638ae2f21b623671f" dependencies: backo2 "1.0.2" base64-arraybuffer "0.1.5" component-bind "1.0.0" component-emitter "1.2.1" - debug "~2.6.4" - engine.io-client "~3.1.0" + debug "~3.1.0" + engine.io-client "~3.2.0" + has-binary2 "~1.0.2" has-cors "1.1.0" indexof "0.0.1" object-component "0.0.3" parseqs "0.0.5" parseuri "0.0.5" - socket.io-parser "~3.1.1" + socket.io-parser "~3.2.0" to-array "0.1.4" -socket.io-parser@~3.1.1: - version "3.1.3" - resolved "https://registry.yarnpkg.com/socket.io-parser/-/socket.io-parser-3.1.3.tgz#ed2da5ee79f10955036e3da413bfd7f1e4d86c8e" +socket.io-parser@~3.2.0: + version "3.2.0" + resolved "https://registry.yarnpkg.com/socket.io-parser/-/socket.io-parser-3.2.0.tgz#e7c6228b6aa1f814e6148aea325b51aa9499e077" dependencies: component-emitter "1.2.1" debug "~3.1.0" - has-binary2 "~1.0.2" isarray "2.0.1" -socket.io@2.0.4: - version "2.0.4" - resolved "https://registry.yarnpkg.com/socket.io/-/socket.io-2.0.4.tgz#c1a4590ceff87ecf13c72652f046f716b29e6014" +socket.io@2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/socket.io/-/socket.io-2.1.1.tgz#a069c5feabee3e6b214a75b40ce0652e1cfb9980" dependencies: - debug "~2.6.6" - engine.io "~3.1.0" + debug "~3.1.0" + engine.io "~3.2.0" + has-binary2 "~1.0.2" socket.io-adapter "~1.1.0" - socket.io-client "2.0.4" - socket.io-parser "~3.1.1" + socket.io-client "2.1.1" + socket.io-parser "~3.2.0" sockjs-client@1.1.5: version "1.1.5" @@ -8304,41 +7632,6 @@ sockjs@0.3.19: faye-websocket "^0.10.0" uuid "^3.0.1" -socks-proxy-agent@^3.0.0: - version "3.0.1" - resolved "https://registry.yarnpkg.com/socks-proxy-agent/-/socks-proxy-agent-3.0.1.tgz#2eae7cf8e2a82d34565761539a7f9718c5617659" - dependencies: - agent-base "^4.1.0" - socks "^1.1.10" - -socks-proxy-agent@^4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/socks-proxy-agent/-/socks-proxy-agent-4.0.1.tgz#5936bf8b707a993079c6f37db2091821bffa6473" - dependencies: - agent-base "~4.2.0" - socks "~2.2.0" - -socks@1.1.9: - version "1.1.9" - resolved "https://registry.yarnpkg.com/socks/-/socks-1.1.9.tgz#628d7e4d04912435445ac0b6e459376cb3e6d691" - dependencies: - ip "^1.1.2" - smart-buffer "^1.0.4" - -socks@^1.1.10: - version "1.1.10" - resolved "https://registry.yarnpkg.com/socks/-/socks-1.1.10.tgz#5b8b7fc7c8f341c53ed056e929b7bf4de8ba7b5a" - dependencies: - ip "^1.1.4" - smart-buffer "^1.0.13" - -socks@~2.2.0: - version "2.2.1" - resolved "https://registry.yarnpkg.com/socks/-/socks-2.2.1.tgz#68ad678b3642fbc5d99c64c165bc561eab0215f9" - dependencies: - ip "^1.1.5" - smart-buffer "^4.0.1" - sortablejs@1.7.0: version "1.7.0" resolved "https://registry.yarnpkg.com/sortablejs/-/sortablejs-1.7.0.tgz#80a2b2370abd568e1cec8c271131ef30a904fa28" @@ -8401,7 +7694,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.3: +source-map@^0.5.1, 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" @@ -8530,20 +7823,13 @@ stdout-stream@^1.4.0: dependencies: readable-stream "^2.0.1" -stream-browserify@^2.0.0, stream-browserify@^2.0.1: +stream-browserify@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/stream-browserify/-/stream-browserify-2.0.1.tgz#66266ee5f9bdb9940a4e4514cafb43bb71e5c9db" dependencies: inherits "~2.0.1" readable-stream "^2.0.2" -stream-combiner2@^1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/stream-combiner2/-/stream-combiner2-1.1.1.tgz#fb4d8a1420ea362764e21ad4780397bebcb41cbe" - dependencies: - duplexer2 "~0.1.0" - readable-stream "^2.0.2" - stream-combiner@~0.0.4: version "0.0.4" resolved "https://registry.yarnpkg.com/stream-combiner/-/stream-combiner-0.0.4.tgz#4d5e433c185261dde623ca3f44c586bcf5c4ad14" @@ -8557,7 +7843,7 @@ stream-each@^1.1.0: end-of-stream "^1.1.0" stream-shift "^1.0.0" -stream-http@^2.0.0, stream-http@^2.7.2: +stream-http@^2.7.2: version "2.8.3" resolved "https://registry.yarnpkg.com/stream-http/-/stream-http-2.8.3.tgz#b2d242469288a5a27ec4fe8933acf623de6514fc" dependencies: @@ -8571,13 +7857,6 @@ stream-shift@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/stream-shift/-/stream-shift-1.0.0.tgz#d5c752825e5367e786f78e18e445ea223a155952" -stream-splicer@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/stream-splicer/-/stream-splicer-2.0.0.tgz#1b63be438a133e4b671cc1935197600175910d83" - dependencies: - inherits "^2.0.1" - readable-stream "^2.0.2" - streamroller@0.7.0: version "0.7.0" resolved "https://registry.yarnpkg.com/streamroller/-/streamroller-0.7.0.tgz#a1d1b7cf83d39afb0d63049a5acbf93493bdf64b" @@ -8627,13 +7906,7 @@ string_decoder@~0.10.x: version "0.10.31" resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-0.10.31.tgz#62e203bc41766c6c28c9fc84301dab1c5310fa94" -string_decoder@~1.0.0: - version "1.0.3" - resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.0.3.tgz#0fc67d7c141825de94282dd536bec6b9bce860ab" - dependencies: - safe-buffer "~5.1.0" - -stringstream@~0.0.4, stringstream@~0.0.5: +stringstream@~0.0.5: version "0.0.6" resolved "https://registry.yarnpkg.com/stringstream/-/stringstream-0.0.6.tgz#7880225b0d4ad10e30927d167a1d6f2fd3b33a72" @@ -8673,12 +7946,6 @@ 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" -subarg@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/subarg/-/subarg-1.0.0.tgz#f62cf17581e996b48fc965699f54c06ae268b8d2" - dependencies: - minimist "^1.1.0" - sugarss@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/sugarss/-/sugarss-1.0.1.tgz#be826d9003e0f247735f92365dc3fd7f1bae9e44" @@ -8701,11 +7968,9 @@ supports-color@^5.1.0, supports-color@^5.2.0, supports-color@^5.3.0, supports-co dependencies: has-flag "^3.0.0" -syntax-error@^1.1.1: - version "1.4.0" - resolved "https://registry.yarnpkg.com/syntax-error/-/syntax-error-1.4.0.tgz#2d9d4ff5c064acb711594a3e3b95054ad51d907c" - dependencies: - acorn-node "^1.2.0" +symbol-observable@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/symbol-observable/-/symbol-observable-1.2.0.tgz#c22688aed4eab3cdc2dfeacbb561660560a00804" tapable@^1.0.0: version "1.0.0" @@ -8783,14 +8048,10 @@ through2@^2.0.0: readable-stream "^2.1.5" xtend "~4.0.1" -through@2, "through@>=2.2.7 <3", through@X.X.X, through@^2.3.6, through@~2.3, through@~2.3.1: +through@2, through@X.X.X, through@^2.3.6, through@~2.3, through@~2.3.1: version "2.3.8" resolved "https://registry.yarnpkg.com/through/-/through-2.3.8.tgz#0dd4c9ffaabc357960b1b724115d7e0e86a2e1f5" -thunkify@^2.1.2: - version "2.1.2" - resolved "https://registry.yarnpkg.com/thunkify/-/thunkify-2.1.2.tgz#faa0e9d230c51acc95ca13a361ac05ca7e04553d" - thunky@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/thunky/-/thunky-1.0.2.tgz#a862e018e3fb1ea2ec3fce5d55605cf57f247371" @@ -8803,22 +8064,12 @@ timed-out@^4.0.0: version "4.0.1" resolved "https://registry.yarnpkg.com/timed-out/-/timed-out-4.0.1.tgz#f32eacac5a175bea25d7fab565ab3ed8741ef56f" -timers-browserify@^1.0.1: - version "1.4.2" - resolved "https://registry.yarnpkg.com/timers-browserify/-/timers-browserify-1.4.2.tgz#c9c58b575be8407375cb5e2462dacee74359f41d" - dependencies: - process "~0.11.0" - timers-browserify@^2.0.4: version "2.0.10" resolved "https://registry.yarnpkg.com/timers-browserify/-/timers-browserify-2.0.10.tgz#1d28e3d2aadf1d5a5996c4e9f95601cd053480ae" dependencies: setimmediate "^1.0.4" -timespan@2.3.x: - version "2.3.0" - resolved "https://registry.yarnpkg.com/timespan/-/timespan-2.3.0.tgz#4902ce040bd13d845c8f59b27e9d59bad6f39929" - tmp@0.0.30: version "0.0.30" resolved "https://registry.yarnpkg.com/tmp/-/tmp-0.0.30.tgz#72419d4a8be7d6ce75148fd8b324e593a711c2ed" @@ -8881,7 +8132,7 @@ touch@^3.1.0: dependencies: nopt "~1.0.10" -tough-cookie@~2.3.0, tough-cookie@~2.3.3: +tough-cookie@~2.3.3: version "2.3.4" resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-2.3.4.tgz#ec60cee38ac675063ffc97a5c18970578ee83655" dependencies: @@ -8979,10 +8230,6 @@ tslint@5.11.0: tslib "^1.8.0" tsutils "^2.27.2" -tsscmp@~1.0.0: - version "1.0.6" - resolved "https://registry.yarnpkg.com/tsscmp/-/tsscmp-1.0.6.tgz#85b99583ac3589ec4bfef825b5000aa911d605eb" - tsutils@^2.27.2: version "2.29.0" resolved "https://registry.yarnpkg.com/tsutils/-/tsutils-2.29.0.tgz#32b488501467acbedd4b85498673a0812aca0b99" @@ -8993,20 +8240,12 @@ tty-browserify@0.0.0: version "0.0.0" resolved "https://registry.yarnpkg.com/tty-browserify/-/tty-browserify-0.0.0.tgz#a157ba402da24e9bf957f9aa69d524eed42901a6" -tty-browserify@~0.0.0: - version "0.0.1" - resolved "https://registry.yarnpkg.com/tty-browserify/-/tty-browserify-0.0.1.tgz#3f05251ee17904dfd0677546670db9651682b811" - tunnel-agent@^0.6.0: version "0.6.0" resolved "https://registry.yarnpkg.com/tunnel-agent/-/tunnel-agent-0.6.0.tgz#27a5dea06b36b04a0a9966774b290868f0fc40fd" dependencies: safe-buffer "^5.0.1" -tunnel-agent@~0.4.1: - version "0.4.3" - resolved "https://registry.yarnpkg.com/tunnel-agent/-/tunnel-agent-0.4.3.tgz#6373db76909fe570e08d73583365ed828a74eeeb" - tweetnacl@^0.14.3, tweetnacl@~0.14.0: version "0.14.5" resolved "https://registry.yarnpkg.com/tweetnacl/-/tweetnacl-0.14.5.tgz#5ae68177f192d4456269d108afa93ff8743f4f64" @@ -9024,7 +8263,7 @@ type-is@~1.6.15, type-is@~1.6.16: media-typer "0.3.0" mime-types "~2.1.18" -typedarray@^0.0.6, typedarray@~0.0.5: +typedarray@^0.0.6: version "0.0.6" resolved "https://registry.yarnpkg.com/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777" @@ -9058,7 +8297,7 @@ typescript@2.4.1: version "2.4.1" resolved "https://registry.yarnpkg.com/typescript/-/typescript-2.4.1.tgz#c3ccb16ddaa0b2314de031e7e6fee89e5ba346bc" -typescript@^2.5.0, typescript@^2.9.1: +"typescript@>=2.6.2 <2.10", typescript@^2.5.0, typescript@^2.9.1: version "2.9.2" resolved "https://registry.yarnpkg.com/typescript/-/typescript-2.9.2.tgz#1cbf61d05d6b96269244eb6a3bce4bd914e0f00c" @@ -9112,29 +8351,12 @@ ultron@~1.1.0: version "1.1.1" resolved "https://registry.yarnpkg.com/ultron/-/ultron-1.1.1.tgz#9fe1536a10a664a65266a1e3ccf85fd36302bc9c" -umd@^3.0.0: - version "3.0.3" - resolved "https://registry.yarnpkg.com/umd/-/umd-3.0.3.tgz#aa9fe653c42b9097678489c01000acb69f0b26cf" - -undeclared-identifiers@^1.1.2: - version "1.1.2" - resolved "https://registry.yarnpkg.com/undeclared-identifiers/-/undeclared-identifiers-1.1.2.tgz#7d850a98887cff4bd0bf64999c014d08ed6d1acc" - dependencies: - acorn-node "^1.3.0" - get-assigned-identifiers "^1.2.0" - simple-concat "^1.0.0" - xtend "^4.0.1" - undefsafe@^2.0.2: version "2.0.2" resolved "https://registry.yarnpkg.com/undefsafe/-/undefsafe-2.0.2.tgz#225f6b9e0337663e0d8e7cfd686fc2836ccace76" dependencies: debug "^2.2.0" -underscore@~1.7.0: - version "1.7.0" - resolved "https://registry.yarnpkg.com/underscore/-/underscore-1.7.0.tgz#6bbaf0877500d36be34ecaa584e0db9fef035209" - union-value@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/union-value/-/union-value-1.0.0.tgz#5c71c34cb5bad5dcebe3ea0cd08207ba5aa1aea4" @@ -9258,7 +8480,7 @@ url-parse@^1.1.8, url-parse@^1.4.3: querystringify "^2.0.0" requires-port "^1.0.0" -url@^0.11.0, url@~0.11.0: +url@^0.11.0: version "0.11.0" resolved "https://registry.yarnpkg.com/url/-/url-0.11.0.tgz#3838e97cfc60521eb73c525a8e55bfdd9e2e28f1" dependencies: @@ -9269,11 +8491,11 @@ use@^3.1.0: version "3.1.1" resolved "https://registry.yarnpkg.com/use/-/use-3.1.1.tgz#d50c8cac79a19fbc20f2911f56eb973f4e10070f" -useragent@^2.1.12: - version "2.3.0" - resolved "https://registry.yarnpkg.com/useragent/-/useragent-2.3.0.tgz#217f943ad540cb2128658ab23fc960f6a88c9972" +useragent@2.2.1: + version "2.2.1" + resolved "https://registry.yarnpkg.com/useragent/-/useragent-2.2.1.tgz#cf593ef4f2d175875e8bb658ea92e18a4fd06d8e" dependencies: - lru-cache "4.1.x" + lru-cache "2.2.x" tmp "0.0.x" util-deprecate@~1.0.1: @@ -9293,7 +8515,7 @@ util@0.10.3: dependencies: inherits "2.0.1" -util@^0.10.3, util@~0.10.1: +util@^0.10.3: version "0.10.4" resolved "https://registry.yarnpkg.com/util/-/util-0.10.4.tgz#3aa0125bfe668a4672de58857d3ace27ecb76901" dependencies: @@ -9319,10 +8541,6 @@ uuid@^3.0.1, uuid@^3.1.0, uuid@^3.2.1, uuid@^3.3.2: version "3.3.2" resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.3.2.tgz#1b4af4955eb3077c501c23872fc6513811587131" -uws@~9.14.0: - version "9.14.0" - resolved "https://registry.yarnpkg.com/uws/-/uws-9.14.0.tgz#fac8386befc33a7a3705cbd58dc47b430ca4dd95" - v8-compile-cache@^2.0.0: version "2.0.2" resolved "https://registry.yarnpkg.com/v8-compile-cache/-/v8-compile-cache-2.0.2.tgz#a428b28bb26790734c4fc8bc9fa106fccebf6a6c" @@ -9340,6 +8558,12 @@ validate-npm-package-license@^3.0.1: spdx-correct "^3.0.0" spdx-expression-parse "^3.0.0" +validate-npm-package-name@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/validate-npm-package-name/-/validate-npm-package-name-3.0.0.tgz#5fa912d81eb7d0c74afc140de7317f0ca7df437e" + dependencies: + builtins "^1.0.3" + vargs@0.1.0: version "0.1.0" resolved "https://registry.yarnpkg.com/vargs/-/vargs-0.1.0.tgz#6b6184da6520cc3204ce1b407cac26d92609ebff" @@ -9372,7 +8596,7 @@ vlq@^0.2.2: version "0.2.3" resolved "https://registry.yarnpkg.com/vlq/-/vlq-0.2.3.tgz#8f3e4328cf63b1540c0d67e1b2778386f8975b26" -vm-browserify@0.0.4, vm-browserify@~0.0.1: +vm-browserify@0.0.4: version "0.0.4" resolved "https://registry.yarnpkg.com/vm-browserify/-/vm-browserify-0.0.4.tgz#5d7ea45bbef9e4a6ff65f95438e0a87c357d5a73" dependencies: @@ -9599,10 +8823,6 @@ websocket-extensions@>=0.1.1: version "0.1.3" resolved "https://registry.yarnpkg.com/websocket-extensions/-/websocket-extensions-0.1.3.tgz#5d2ff22977003ec687a4b87073dfbbac146ccf29" -when@^3.7.7: - version "3.7.8" - resolved "https://registry.yarnpkg.com/when/-/when-3.7.8.tgz#c7130b6a7ea04693e842cdc9e7a1f2aa39a39f82" - which-module@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/which-module/-/which-module-1.0.0.tgz#bba63ca861948994ff307736089e3b96026c2a4f" @@ -9633,10 +8853,6 @@ window-size@0.1.0: version "0.1.0" resolved "https://registry.yarnpkg.com/window-size/-/window-size-0.1.0.tgz#5438cd2ea93b202efa3a19fe8887aee7c94f9c9d" -with-callback@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/with-callback/-/with-callback-1.0.2.tgz#a09629b9a920028d721404fb435bdcff5c91bc21" - wordwrap@0.0.2: version "0.0.2" resolved "https://registry.yarnpkg.com/wordwrap/-/wordwrap-0.0.2.tgz#b79669bb42ecb409f83d583cad52ca17eaa1643f" @@ -9712,15 +8928,11 @@ xmlhttprequest-ssl@~1.5.4: version "1.5.5" resolved "https://registry.yarnpkg.com/xmlhttprequest-ssl/-/xmlhttprequest-ssl-1.5.5.tgz#c2876b06168aadc40e57d97e81191ac8f4398b3e" -xregexp@2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/xregexp/-/xregexp-2.0.0.tgz#52a63e56ca0b84a7f3a5f3d61872f126ad7a5943" - xregexp@4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/xregexp/-/xregexp-4.0.0.tgz#e698189de49dd2a18cc5687b05e17c8e43943020" -xtend@^4.0.0, xtend@^4.0.1, xtend@~4.0.0, xtend@~4.0.1: +xtend@^4.0.0, xtend@~4.0.0, xtend@~4.0.1: version "4.0.1" resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.1.tgz#a5c6d532be656e23db820efb943a1f04998d63af" @@ -9740,7 +8952,7 @@ yallist@^3.0.0, yallist@^3.0.2: version "3.0.2" resolved "https://registry.yarnpkg.com/yallist/-/yallist-3.0.2.tgz#8452b4bb7e83c7c188d8041c1a837c773d6d8bb9" -yargs-parser@^10.1.0: +yargs-parser@^10.0.0, yargs-parser@^10.1.0: version "10.1.0" resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-10.1.0.tgz#7202265b89f7e9e9f2e5765e0fe735a905edbaa8" dependencies: @@ -9752,12 +8964,6 @@ yargs-parser@^5.0.0: dependencies: camelcase "^3.0.0" -yargs-parser@^9.0.2: - version "9.0.2" - resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-9.0.2.tgz#9ccf6a43460fe4ed40a9bb68f48d43b8a68cc077" - dependencies: - camelcase "^4.1.0" - yargs@12.0.1, yargs@^12.0.1: version "12.0.1" resolved "https://registry.yarnpkg.com/yargs/-/yargs-12.0.1.tgz#6432e56123bb4e7c3562115401e98374060261c2" @@ -9775,23 +8981,6 @@ yargs@12.0.1, yargs@^12.0.1: y18n "^3.2.1 || ^4.0.0" yargs-parser "^10.1.0" -yargs@^11.0.0: - version "11.1.0" - resolved "https://registry.yarnpkg.com/yargs/-/yargs-11.1.0.tgz#90b869934ed6e871115ea2ff58b03f4724ed2d77" - dependencies: - cliui "^4.0.0" - decamelize "^1.1.1" - find-up "^2.1.0" - get-caller-file "^1.0.1" - os-locale "^2.0.0" - require-directory "^2.1.1" - require-main-filename "^1.0.1" - set-blocking "^2.0.0" - string-width "^2.0.0" - which-module "^2.0.0" - y18n "^3.2.1" - yargs-parser "^9.0.2" - yargs@^7.0.0: version "7.1.0" resolved "https://registry.yarnpkg.com/yargs/-/yargs-7.1.0.tgz#6ba318eb16961727f5d284f8ea003e8d6154d0c8" From d7582edfa19a762eb2b3ff0ebf3dbfe957055c70 Mon Sep 17 00:00:00 2001 From: Kristof De Langhe Date: Fri, 7 Sep 2018 11:24:37 +0200 Subject: [PATCH 12/48] BrowseItemsResponseParsingService TypeDocs --- src/app/core/data/browse-items-response-parsing-service.ts | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/app/core/data/browse-items-response-parsing-service.ts b/src/app/core/data/browse-items-response-parsing-service.ts index 6e3c7b4723..e513ad0898 100644 --- a/src/app/core/data/browse-items-response-parsing-service.ts +++ b/src/app/core/data/browse-items-response-parsing-service.ts @@ -16,6 +16,9 @@ import { RestRequest } from './request.models'; import { Item } from '../shared/item.model'; import { DSpaceObject } from '../shared/dspace-object.model'; +/** + * A ResponseParsingService used to parse DSpaceRESTV2Response coming from the REST API to Browse Items (DSpaceObject[]) + */ @Injectable() export class BrowseItemsResponseParsingService extends BaseResponseParsingService implements ResponseParsingService { From cb20a31379be97d7533bf334c8e5f91b9b86f3fc Mon Sep 17 00:00:00 2001 From: Kristof De Langhe Date: Fri, 7 Sep 2018 12:05:22 +0200 Subject: [PATCH 13/48] Fixed Browse-By-Title sort direction --- .../+browse-by-title-page/browse-by-title-page.component.ts | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/app/+browse-by/+browse-by-title-page/browse-by-title-page.component.ts b/src/app/+browse-by/+browse-by-title-page/browse-by-title-page.component.ts index 3205091952..1759264e2a 100644 --- a/src/app/+browse-by/+browse-by-title-page/browse-by-title-page.component.ts +++ b/src/app/+browse-by/+browse-by-title-page/browse-by-title-page.component.ts @@ -54,14 +54,15 @@ export class BrowseByTitlePageComponent implements OnInit { .subscribe((params) => { const page = +params.page || this.paginationConfig.currentPage; const pageSize = +params.pageSize || this.paginationConfig.pageSize; - const sortDirection = +params.page || this.sortConfig.direction; + const sortDirection = params.sortDirection || this.sortConfig.direction; + const sortField = params.sortField || this.sortConfig.field; const pagination = Object.assign({}, this.paginationConfig, { currentPage: page, pageSize: pageSize } ); const sort = Object.assign({}, this.sortConfig, - { direction: sortDirection, field: params.sortField } + { direction: sortDirection, field: sortField } ); this.updatePage({ pagination: pagination, From 14fd58dd21644061c974c02857ad516183672879 Mon Sep 17 00:00:00 2001 From: lotte Date: Fri, 7 Sep 2018 13:48:00 +0200 Subject: [PATCH 14/48] issues with form component tests --- src/app/shared/form/form.component.spec.ts | 507 ++++++++++----------- src/app/shared/form/form.component.ts | 88 ++-- src/app/shared/form/form.service.ts | 32 +- src/app/shared/mocks/mock-form-service.ts | 15 +- src/app/shared/testing/mock-store.ts | 5 +- src/modules/app/server-app.module.ts | 5 +- 6 files changed, 348 insertions(+), 304 deletions(-) diff --git a/src/app/shared/form/form.component.spec.ts b/src/app/shared/form/form.component.spec.ts index 3c204fa255..17d0b82b22 100644 --- a/src/app/shared/form/form.component.spec.ts +++ b/src/app/shared/form/form.component.spec.ts @@ -1,24 +1,21 @@ import { ChangeDetectorRef, Component, CUSTOM_ELEMENTS_SCHEMA } from '@angular/core'; import { async, ComponentFixture, inject, TestBed, } from '@angular/core/testing'; import { CommonModule } from '@angular/common'; -import { BrowserModule } from '@angular/platform-browser'; -import { FormsModule, ReactiveFormsModule } from '@angular/forms'; +import { BrowserModule, By } from '@angular/platform-browser'; +import { FormControl, FormsModule, ReactiveFormsModule, Validators } from '@angular/forms'; import { DynamicFormArrayModel, DynamicFormControlEvent, DynamicFormControlModel, DynamicInputModel } from '@ng-dynamic-forms/core'; -import { ActionsSubject, Store } from '@ngrx/store'; -import { of as observableOf } from 'rxjs'; import { NgbModule } from '@ng-bootstrap/ng-bootstrap'; import { TranslateModule } from '@ngx-translate/core'; - +import { of as observableOf } from 'rxjs'; import { FormComponent } from './form.component'; import { FormService } from './form.service'; import { FormBuilderService } from './builder/form-builder.service'; -import { FormState } from './form.reducer'; -import { FormAddError, FormChangeAction, FormStatusChangeAction } from './form.actions'; +import { FormAddError, FormChangeAction } from './form.actions'; import { FormFieldMetadataValueObject } from './builder/models/form-field-metadata-value.model'; import { GLOBAL_CONFIG } from '../../../config'; import { createTestComponent } from '../testing/utils'; @@ -26,7 +23,6 @@ import { getMockFormService } from '../mocks/mock-form-service'; import { getMockFormBuilderService } from '../mocks/mock-form-builder-service'; export const TEST_FORM_MODEL = [ - new DynamicInputModel( { id: 'dc_title', @@ -93,11 +89,12 @@ export const TEST_FORM_MODEL_WITH_ARRAY = [ }) ]; -fdescribe('FormComponent test suite', () => { +describe('FormComponent test suite', () => { let testComp: TestComponent; let formComp: FormComponent; let testFixture: ComponentFixture; let formFixture: ComponentFixture; + let dynamicForm; const config = { form: { @@ -107,23 +104,10 @@ fdescribe('FormComponent test suite', () => { } } } as any; - const formState: FormState = { - testForm: { - data: { - dc_title: null, - dc_title_alternative: null, - dc_publisher: null, - dc_identifier_citation: null, - dc_identifier_issn: null - }, - valid: false, - errors: [] - } - }; + let html; - - const store = new Store(observableOf({}), new ActionsSubject(), undefined); - + let formService; + let formBuilderService; // async beforeEach beforeEach(async(() => { @@ -142,21 +126,19 @@ fdescribe('FormComponent test suite', () => { ], // declare the test component providers: [ ChangeDetectorRef, - {provide: FormBuilderService, useValue: getMockFormBuilderService()}, FormComponent, - {provide: FormService, useValue: getMockFormService()}, - {provide: GLOBAL_CONFIG, useValue: config}, - { - provide: Store, useValue: store - } + { provide: FormBuilderService, useValue: getMockFormBuilderService() }, + { provide: FormService, useValue: getMockFormService() }, + { provide: GLOBAL_CONFIG, useValue: config } ], schemas: [CUSTOM_ELEMENTS_SCHEMA] }); - + formService = TestBed.get(FormService); + formBuilderService = TestBed.get(FormBuilderService); })); describe('', () => { - // synchronous beforeEach + // // synchronous beforeEach beforeEach(() => { html = ` { }); it('should create FormComponent', inject([FormComponent], (app: FormComponent) => { - expect(app).toBeDefined(); })); }); @@ -183,236 +164,246 @@ fdescribe('FormComponent test suite', () => { formComp.formModel = TEST_FORM_MODEL; formComp.displaySubmit = false; formFixture.detectChanges(); - spyOn(store, 'dispatch'); + dynamicForm = formFixture.debugElement.query(By.css('ds-dynamic-form')); + formBuilderService.findById.and.returnValue(TEST_FORM_MODEL); }); afterEach(() => { formFixture.destroy(); formComp = null; }); - - it('should dispatch a FormStatusChangeAction when Form group status changes', () => { - const control = formComp.formGroup.get(['dc_title']); - control.setValue('Test Title'); - - expect(store.dispatch).toHaveBeenCalledWith(new FormStatusChangeAction('testForm', formComp.formGroup.valid)); - - }); - - fit('should display form errors when errors are added to the state', () => { - const error = { - fieldId: 'dc_title', - fieldIndex: 0, - message: 'error.validation.required' - }; - - store.dispatch(new FormAddError(formComp.formId, error.fieldId, error.fieldIndex, error.message)); - formFixture.detectChanges(); - - expect((formComp as any).formErrors[0]).toEqual(error); - - }); - - it('should remove form errors when errors are empty in the state', () => { - (formComp as any).formErrors = [{ - fieldId: 'dc_title', - message: 'error.validation.required' - }]; - const errors = []; - - formState.testForm.errors = errors; - store.nextState(formState); - formFixture.detectChanges(); - - expect((formComp as any).formErrors).toEqual(errors); - - }); - - it('should dispatch FormChangeAction on form change', inject([FormBuilderService], (service: FormBuilderService) => { - const event = { - $event: new FormFieldMetadataValueObject('Test Title'), - context: null, - control: formComp.formGroup.get('dc_title'), - group: formComp.formGroup, - model: formComp.formModel[0], - type: 'change' - } as DynamicFormControlEvent; - - spyOn(formComp.change, 'emit'); - - formComp.onChange(event); - - expect(store.dispatch).toHaveBeenCalledWith(new FormChangeAction('testForm', service.getValueFromModel(formComp.formModel))); - expect(formComp.change.emit).toHaveBeenCalled(); - })); - - it('should emit change on form change', inject([FormBuilderService], (service: FormBuilderService) => { - const event = { - $event: new FormFieldMetadataValueObject('Test Title'), - context: null, - control: formComp.formGroup.get('dc_title'), - group: formComp.formGroup, - model: formComp.formModel[0], - type: 'change' - } as DynamicFormControlEvent; - - spyOn(formComp.change, 'emit'); - - formComp.onChange(event); - - expect(formComp.change.emit).toHaveBeenCalled(); - })); - - it('should not emit change Event on form change when emitChange is false', inject([FormBuilderService], (service: FormBuilderService) => { - const event = { - $event: new FormFieldMetadataValueObject('Test Title'), - context: null, - control: formComp.formGroup.get('dc_title'), - group: formComp.formGroup, - model: formComp.formModel[0], - type: 'change' - } as DynamicFormControlEvent; - - formComp.emitChange = false; - spyOn(formComp.change, 'emit'); - - formComp.onChange(event); - - expect(formComp.change.emit).not.toHaveBeenCalled(); - })); - - it('should emit blur Event on blur', () => { - const event = { - $event: new FocusEvent('blur'), - context: null, - control: formComp.formGroup.get('dc_title'), - group: formComp.formGroup, - model: formComp.formModel[0], - type: 'blur' - } as DynamicFormControlEvent; - - spyOn(formComp.blur, 'emit'); - - formComp.onBlur(event); - - expect(formComp.blur.emit).toHaveBeenCalled(); - }); - - it('should emit focus Event on focus', () => { - const event = { - $event: new FocusEvent('focus'), - context: null, - control: formComp.formGroup.get('dc_title'), - group: formComp.formGroup, - model: formComp.formModel[0], - type: 'focus' - } as DynamicFormControlEvent; - - spyOn(formComp.focus, 'emit'); - - formComp.onFocus(event); - - expect(formComp.focus.emit).toHaveBeenCalled(); - }); - - it('should return Observable of form status', () => { - - const control = formComp.formGroup.get(['dc_title']); - control.setValue('Test Title'); - formState.testForm.valid = true; - store.nextState(formState); - formFixture.detectChanges(); - - formComp.isValid().subscribe((valid) => { - expect(valid).toBe(true); - }); - }); - - it('should emit submit Event on form submit whether the form is valid', () => { - - const control = formComp.formGroup.get(['dc_title']); - control.setValue('Test Title'); - formState.testForm.valid = true; - spyOn(formComp.submit, 'emit'); - - store.nextState(formState); - formFixture.detectChanges(); - - formComp.onSubmit(); - expect(formComp.submit.emit).toHaveBeenCalled(); - }); - - it('should not emit submit Event on form submit whether the form is not valid', () => { - - spyOn((formComp as any).formService, 'validateAllFormFields'); - - store.nextState(formState); - formFixture.detectChanges(); - - formComp.onSubmit(); - expect((formComp as any).formService.validateAllFormFields).toHaveBeenCalled(); - }); - - it('should reset form group', () => { - - spyOn(formComp.formGroup, 'reset'); - - formComp.reset(); - - expect(formComp.formGroup.reset).toHaveBeenCalled(); - }); - }); - - describe('', () => { - beforeEach(() => { - - formFixture = TestBed.createComponent(FormComponent); - formComp = formFixture.componentInstance; // FormComponent test instance - formComp.formId = 'testFormArray'; - formComp.formModel = TEST_FORM_MODEL_WITH_ARRAY; - formComp.displaySubmit = false; - formFixture.detectChanges(); - spyOn(store, 'dispatch'); - }); - - afterEach(() => { - formFixture.destroy(); - formComp = null; - }); - - it('should return ReadOnly property from array item', inject([FormBuilderService], (service: FormBuilderService) => { - const readOnly = formComp.isItemReadOnly(formComp.formModel[0] as DynamicFormArrayModel, 0); - - expect(readOnly).toBe(false); - })); - - it('should dispatch FormChangeAction when an item has been added to an array', inject([FormBuilderService], (service: FormBuilderService) => { - formComp.insertItem(new Event('click'), formComp.formModel[0] as DynamicFormArrayModel, 1); - - expect(store.dispatch).toHaveBeenCalledWith(new FormChangeAction('testFormArray', service.getValueFromModel(formComp.formModel))); - })); - - it('should emit addArrayItem Event when an item has been added to an array', inject([FormBuilderService], (service: FormBuilderService) => { - spyOn(formComp.addArrayItem, 'emit'); - - formComp.insertItem(new Event('click'), formComp.formModel[0] as DynamicFormArrayModel, 1); - - expect(formComp.addArrayItem.emit).toHaveBeenCalled(); - })); - - it('should dispatch FormChangeAction when an item has been removed from an array', inject([FormBuilderService], (service: FormBuilderService) => { - formComp.removeItem(new Event('click'), formComp.formModel[0] as DynamicFormArrayModel, 1); - - expect(store.dispatch).toHaveBeenCalledWith(new FormChangeAction('testFormArray', service.getValueFromModel(formComp.formModel))); - })); - - it('should emit removeArrayItem Event when an item has been removed from an array', inject([FormBuilderService], (service: FormBuilderService) => { - spyOn(formComp.removeArrayItem, 'emit'); - - formComp.removeItem(new Event('click'), formComp.formModel[0] as DynamicFormArrayModel, 1); - - expect(formComp.removeArrayItem.emit).toHaveBeenCalled(); - })); + // + // it('should dispatch a FormStatusChangeAction when Form group status changes', () => { + // // spyOn(formComp, 'onChange'); + // const control = new FormControl('', Validators.required); + // const event = { + // $event: new FormFieldMetadataValueObject('Test Title'), + // context: null, + // control: control, + // group: formComp.formGroup, + // model: formComp.formModel[0], + // type: 'change' + // } as DynamicFormControlEvent; + // dynamicForm.componentInstance.change.emit(event); + // + // // expect(formComp.onChange).toHaveBeenCalledWith('testForm', formComp.formGroup.valid); + // formComp.onChange(event); + // // const control = new FormControl('', Validators.required); + // formComp.formGroup.addControl('dc_title', control); + // control.setValue('Test Title'); + // + // expect(formService.changeForm).toHaveBeenCalledWith('testForm', formComp.formGroup.valid); + // }); + // + // it('should display form errors when errors are added to the state', () => { + // + // const error = {formComp.formId, 'dc_title', 0, 'error.validation.required'; + // formService.getFormErrors().next([error]); + // formFixture.detectChanges(); + // + // expect((formComp as any).formErrors).toEqual([error]); + // + // }); + // + // fit('should remove form errors when errors are empty in the state', () => { + // (formComp as any).formErrors = [{ + // fieldId: 'dc_title', + // message: 'error.validation.required' + // }]; + // const errors = []; + // + // formService.getFormErrors().next([]); + // formFixture.detectChanges(); + // + // expect((formComp as any).formErrors).toEqual(errors); + // + // }); + // + // it('should dispatch FormChangeAction on form change', inject([FormBuilderService], (service: FormBuilderService) => { + // const event = { + // $event: new FormFieldMetadataValueObject('Test Title'), + // context: null, + // control: formComp.formGroup.get('dc_title'), + // group: formComp.formGroup, + // model: formComp.formModel[0], + // type: 'change' + // } as DynamicFormControlEvent; + // + // spyOn(formComp.change, 'emit'); + // + // formComp.onChange(event); + // + // expect(store.dispatch).toHaveBeenCalledWith(new FormChangeAction('testForm', service.getValueFromModel(formComp.formModel))); + // expect(formComp.change.emit).toHaveBeenCalled(); + // })); + // + // it('should emit change on form change', inject([FormBuilderService], (service: FormBuilderService) => { + // const event = { + // $event: new FormFieldMetadataValueObject('Test Title'), + // context: null, + // control: formComp.formGroup.get('dc_title'), + // group: formComp.formGroup, + // model: formComp.formModel[0], + // type: 'change' + // } as DynamicFormControlEvent; + // + // spyOn(formComp.change, 'emit'); + // + // formComp.onChange(event); + // + // expect(formComp.change.emit).toHaveBeenCalled(); + // })); + // + // it('should not emit change Event on form change when emitChange is false', inject([FormBuilderService], (service: FormBuilderService) => { + // const event = { + // $event: new FormFieldMetadataValueObject('Test Title'), + // context: null, + // control: formComp.formGroup.get('dc_title'), + // group: formComp.formGroup, + // model: formComp.formModel[0], + // type: 'change' + // } as DynamicFormControlEvent; + // + // formComp.emitChange = false; + // spyOn(formComp.change, 'emit'); + // + // formComp.onChange(event); + // + // expect(formComp.change.emit).not.toHaveBeenCalled(); + // })); + // + // it('should emit blur Event on blur', () => { + // const event = { + // $event: new FocusEvent('blur'), + // context: null, + // control: formComp.formGroup.get('dc_title'), + // group: formComp.formGroup, + // model: formComp.formModel[0], + // type: 'blur' + // } as DynamicFormControlEvent; + // + // spyOn(formComp.blur, 'emit'); + // + // formComp.onBlur(event); + // + // expect(formComp.blur.emit).toHaveBeenCalled(); + // }); + // + // it('should emit focus Event on focus', () => { + // const event = { + // $event: new FocusEvent('focus'), + // context: null, + // control: formComp.formGroup.get('dc_title'), + // group: formComp.formGroup, + // model: formComp.formModel[0], + // type: 'focus' + // } as DynamicFormControlEvent; + // + // spyOn(formComp.focus, 'emit'); + // + // formComp.onFocus(event); + // + // expect(formComp.focus.emit).toHaveBeenCalled(); + // }); + // + // it('should return Observable of form status', () => { + // + // const control = formComp.formGroup.get(['dc_title']); + // control.setValue('Test Title'); + // formState.testForm.valid = true; + // store.nextState(formState); + // formFixture.detectChanges(); + // + // formComp.isValid().subscribe((valid) => { + // expect(valid).toBe(true); + // }); + // }); + // + // it('should emit submit Event on form submit whether the form is valid', () => { + // + // const control = formComp.formGroup.get(['dc_title']); + // control.setValue('Test Title'); + // formState.testForm.valid = true; + // spyOn(formComp.submit, 'emit'); + // + // store.nextState(formState); + // formFixture.detectChanges(); + // + // formComp.onSubmit(); + // expect(formComp.submit.emit).toHaveBeenCalled(); + // }); + // + // it('should not emit submit Event on form submit whether the form is not valid', () => { + // + // spyOn((formComp as any).formService, 'validateAllFormFields'); + // + // store.nextState(formState); + // formFixture.detectChanges(); + // + // formComp.onSubmit(); + // expect((formComp as any).formService.validateAllFormFields).toHaveBeenCalled(); + // }); + // + // it('should reset form group', () => { + // + // spyOn(formComp.formGroup, 'reset'); + // + // formComp.reset(); + // + // expect(formComp.formGroup.reset).toHaveBeenCalled(); + // }); + // }); + // + // describe('', () => { + // beforeEach(() => { + // + // formFixture = TestBed.createComponent(FormComponent); + // formComp = formFixture.componentInstance; // FormComponent test instance + // formComp.formId = 'testFormArray'; + // formComp.formModel = TEST_FORM_MODEL_WITH_ARRAY; + // formComp.displaySubmit = false; + // formFixture.detectChanges(); + // spyOn(store, 'dispatch'); + // }); + // + // afterEach(() => { + // formFixture.destroy(); + // formComp = null; + // }); + // + // it('should return ReadOnly property from array item', inject([FormBuilderService], (service: FormBuilderService) => { + // const readOnly = formComp.isItemReadOnly(formComp.formModel[0] as DynamicFormArrayModel, 0); + // + // expect(readOnly).toBe(false); + // })); + // + // it('should dispatch FormChangeAction when an item has been added to an array', inject([FormBuilderService], (service: FormBuilderService) => { + // formComp.insertItem(new Event('click'), formComp.formModel[0] as DynamicFormArrayModel, 1); + // + // expect(store.dispatch).toHaveBeenCalledWith(new FormChangeAction('testFormArray', service.getValueFromModel(formComp.formModel))); + // })); + // + // it('should emit addArrayItem Event when an item has been added to an array', inject([FormBuilderService], (service: FormBuilderService) => { + // spyOn(formComp.addArrayItem, 'emit'); + // + // formComp.insertItem(new Event('click'), formComp.formModel[0] as DynamicFormArrayModel, 1); + // + // expect(formComp.addArrayItem.emit).toHaveBeenCalled(); + // })); + // + // it('should dispatch FormChangeAction when an item has been removed from an array', inject([FormBuilderService], (service: FormBuilderService) => { + // formComp.removeItem(new Event('click'), formComp.formModel[0] as DynamicFormArrayModel, 1); + // + // expect(store.dispatch).toHaveBeenCalledWith(new FormChangeAction('testFormArray', service.getValueFromModel(formComp.formModel))); + // })); + // + // it('should emit removeArrayItem Event when an item has been removed from an array', inject([FormBuilderService], (service: FormBuilderService) => { + // spyOn(formComp.removeArrayItem, 'emit'); + // + // formComp.removeItem(new Event('click'), formComp.formModel[0] as DynamicFormArrayModel, 1); + // + // expect(formComp.removeArrayItem.emit).toHaveBeenCalled(); + // })); }) }); diff --git a/src/app/shared/form/form.component.ts b/src/app/shared/form/form.component.ts index a8e5ccc499..7814b85be0 100644 --- a/src/app/shared/form/form.component.ts +++ b/src/app/shared/form/form.component.ts @@ -1,6 +1,13 @@ - -import {distinctUntilChanged, map, filter} from 'rxjs/operators'; -import { ChangeDetectorRef, Component, EventEmitter, Input, OnDestroy, OnInit, Output } from '@angular/core'; +import { distinctUntilChanged, filter, map } from 'rxjs/operators'; +import { + ChangeDetectorRef, + Component, + EventEmitter, + Input, + OnDestroy, + OnInit, + Output +} from '@angular/core'; import { AbstractControl, FormArray, FormControl, FormGroup } from '@angular/forms'; import { @@ -10,22 +17,11 @@ import { DynamicFormGroupModel, DynamicFormLayout, } from '@ng-dynamic-forms/core'; -import { select, Store } from '@ngrx/store'; import { findIndex } from 'lodash'; - -import { AppState } from '../../app.reducer'; -import { - FormChangeAction, - FormInitAction, - FormRemoveAction, - FormRemoveErrorAction, - FormStatusChangeAction -} from './form.actions'; import { FormBuilderService } from './builder/form-builder.service'; -import { Observable , Subscription } from 'rxjs'; +import { Observable, Subscription } from 'rxjs'; import { hasValue, isNotEmpty, isNotNull, isNull } from '../empty.util'; import { FormService } from './form.service'; -import { formObjectFromIdSelector } from './selectors'; import { FormEntry, FormError } from './form.reducer'; /** @@ -92,8 +88,7 @@ export class FormComponent implements OnDestroy, OnInit { constructor(private formService: FormService, protected changeDetectorRef: ChangeDetectorRef, - private formBuilderService: FormBuilderService, - private store: Store) { + private formBuilderService: FormBuilderService) { } /** @@ -132,13 +127,14 @@ export class FormComponent implements OnDestroy, OnInit { ngOnInit() { if (!this.formGroup) { this.formGroup = this.formBuilderService.createFormGroup(this.formModel); + } else { this.formModel.forEach((model) => { this.formBuilderService.addFormGroupControl(this.formGroup, this.parentFormModel, model); }); } - this.store.dispatch(new FormInitAction(this.formId, this.formBuilderService.getValueFromModel(this.formModel), this.getFormGroupValidStatus())); + this.formService.initForm(this.formId, this.formModel, this.getFormGroupValidStatus()); // TODO: take a look to the following method: // this.keepSync(); @@ -148,46 +144,61 @@ export class FormComponent implements OnDestroy, OnInit { this.subs.push(this.formGroup.statusChanges.pipe( filter((currentStatus) => this.formValid !== this.getFormGroupValidStatus())) .subscribe((currentStatus) => { - // Dispatch a FormStatusChangeAction if the form status has changed - this.store.dispatch(new FormStatusChangeAction(this.formId, this.getFormGroupValidStatus())); + this.formService.setStatusChanged(this.formId, this.getFormGroupValidStatus()); this.formValid = this.getFormGroupValidStatus(); })); this.subs.push( - this.store.pipe( - select(formObjectFromIdSelector(this.formId)), + this.formService.getForm(this.formId).pipe( filter((formState: FormEntry) => !!formState && (isNotEmpty(formState.errors) || isNotEmpty(this.formErrors))), map((formState) => formState.errors), - distinctUntilChanged(),) - // .delay(100) // this terrible delay is here to prevent the detection change error + distinctUntilChanged()) + // .delay(100) // this terrible delay is here to prevent the detection change error .subscribe((errors: FormError[]) => { - const {formGroup, formModel} = this; + const { formGroup, formModel } = this; errors - .filter((error: FormError) => findIndex(this.formErrors, {fieldId: error.fieldId, fieldIndex: error.fieldIndex}) === -1) + .filter((error: FormError) => findIndex(this.formErrors, { + fieldId: error.fieldId, + fieldIndex: error.fieldIndex + }) === -1) .forEach((error: FormError) => { - const {fieldId} = error; - const {fieldIndex} = error; + const { fieldId } = error; + const { fieldIndex } = error; let field: AbstractControl; if (!!this.parentFormModel) { field = this.formBuilderService.getFormControlById(fieldId, formGroup.parent as FormGroup, formModel, fieldIndex); } else { field = this.formBuilderService.getFormControlById(fieldId, formGroup, formModel, fieldIndex); } + console.log('1', error); if (field) { + console.log('2',error); + const model: DynamicFormControlModel = this.formBuilderService.findById(fieldId, formModel); + console.log('4',error); + this.formService.addErrorToField(field, model, error.message); // this.formService.validateAllFormFields(formGroup); + console.log('5',error); + this.changeDetectorRef.detectChanges(); + } + console.log('4',error); + }); + console.log(errors); this.formErrors - .filter((error: FormError) => findIndex(errors, {fieldId: error.fieldId, fieldIndex: error.fieldIndex}) === -1) + .filter((error: FormError) => findIndex(errors, { + fieldId: error.fieldId, + fieldIndex: error.fieldIndex + }) === -1) .forEach((error: FormError) => { - const {fieldId} = error; - const {fieldIndex} = error; + const { fieldId } = error; + const { fieldIndex } = error; let field: AbstractControl; if (!!this.parentFormModel) { field = this.formBuilderService.getFormControlById(fieldId, formGroup.parent as FormGroup, formModel, fieldIndex); @@ -200,7 +211,7 @@ export class FormComponent implements OnDestroy, OnInit { this.formService.removeErrorFromField(field, model, error.message); } }); - + console.log(this.formErrors); this.formErrors = errors; this.changeDetectorRef.detectChanges(); }) @@ -214,7 +225,7 @@ export class FormComponent implements OnDestroy, OnInit { this.subs .filter((sub) => hasValue(sub)) .forEach((sub) => sub.unsubscribe()); - this.store.dispatch(new FormRemoveAction(this.formId)); + this.formService.removeForm(this.formId) } /** @@ -245,9 +256,8 @@ export class FormComponent implements OnDestroy, OnInit { } onChange(event: DynamicFormControlEvent): void { - const action: FormChangeAction = new FormChangeAction(this.formId, this.formBuilderService.getValueFromModel(this.formModel)); - this.store.dispatch(action); + this.formService.changeForm(this.formId, this.formModel); this.formGroup.markAsPristine(); if (this.emitChange) { @@ -257,7 +267,7 @@ export class FormComponent implements OnDestroy, OnInit { const control: FormControl = event.control; const fieldIndex: number = (event.context && event.context.index) ? event.context.index : 0; if (control.valid) { - this.store.dispatch(new FormRemoveErrorAction(this.formId, event.model.id, fieldIndex)); + this.formService.removeError(this.formId, event.model.id, fieldIndex); } } @@ -290,14 +300,14 @@ export class FormComponent implements OnDestroy, OnInit { const formArrayControl = this.formGroup.get(this.formBuilderService.getPath(arrayContext)) as FormArray; this.removeArrayItem.emit(this.getEvent($event, arrayContext, index, 'remove')); this.formBuilderService.removeFormArrayGroup(index, formArrayControl, arrayContext); - this.store.dispatch(new FormChangeAction(this.formId, this.formBuilderService.getValueFromModel(this.formModel))); + this.formService.changeForm(this.formId, this.formModel); } insertItem($event, arrayContext: DynamicFormArrayModel, index: number): void { const formArrayControl = this.formGroup.get(this.formBuilderService.getPath(arrayContext)) as FormArray; this.formBuilderService.insertFormArrayGroup(index, formArrayControl, arrayContext); this.addArrayItem.emit(this.getEvent($event, arrayContext, index, 'add')); - this.store.dispatch(new FormChangeAction(this.formId, this.formBuilderService.getValueFromModel(this.formModel))); + this.formService.changeForm(this.formId, this.formModel); } protected getEvent($event: any, arrayContext: DynamicFormArrayModel, index: number, type: string): DynamicFormControlEvent { @@ -314,6 +324,6 @@ export class FormComponent implements OnDestroy, OnInit { } const model = context.group[0] as DynamicFormControlModel; const control = group.controls[index] as FormControl; - return {$event, context, control, group, model, type}; + return { $event, context, control, group, model, type }; } } diff --git a/src/app/shared/form/form.service.ts b/src/app/shared/form/form.service.ts index f17da20db4..ae5ba9f278 100644 --- a/src/app/shared/form/form.service.ts +++ b/src/app/shared/form/form.service.ts @@ -10,8 +10,14 @@ import { FormBuilderService } from './builder/form-builder.service'; import { DynamicFormControlModel } from '@ng-dynamic-forms/core'; import { isEmpty, isNotUndefined } from '../empty.util'; import { uniqueId } from 'lodash'; -import { FormChangeAction } from './form.actions'; +import { + FormChangeAction, + FormInitAction, + FormRemoveAction, FormRemoveErrorAction, + FormStatusChangeAction +} from './form.actions'; import { GLOBAL_CONFIG, GlobalConfig } from '../../../config'; +import { FormEntry } from './form.reducer'; @Injectable() export class FormService { @@ -142,4 +148,28 @@ export class FormService { } return (this.config.form.validatorMap.hasOwnProperty(validator)) ? this.config.form.validatorMap[validator] : validator; } + + public initForm(formId: string, model: DynamicFormControlModel[], valid: boolean) { + this.store.dispatch(new FormInitAction(formId, this.formBuilderService.getValueFromModel(model), valid)) + } + + public setStatusChanged(formId: string, valid: boolean) { + this.store.dispatch(new FormStatusChangeAction(formId, valid)) + } + + public getForm(formId: string): Observable { + return this.store.pipe(select(formObjectFromIdSelector(formId))); + } + + public removeForm(formId: string) { + this.store.dispatch(new FormRemoveAction(formId)); + } + + public changeForm(formId: string, model: DynamicFormControlModel[]) { + this.store.dispatch(new FormChangeAction(formId, this.formBuilderService.getValueFromModel(model))); + } + + public removeError(formId: string, eventModelId: string, fieldIndex: number) { + this.store.dispatch(new FormRemoveErrorAction(formId, eventModelId, fieldIndex)); + } } diff --git a/src/app/shared/mocks/mock-form-service.ts b/src/app/shared/mocks/mock-form-service.ts index 0ab3fbffcc..e92be02fcc 100644 --- a/src/app/shared/mocks/mock-form-service.ts +++ b/src/app/shared/mocks/mock-form-service.ts @@ -1,12 +1,23 @@ import { FormService } from '../form/form.service'; +import { BehaviorSubject } from 'rxjs/internal/BehaviorSubject'; +import { map } from 'rxjs/operators'; export function getMockFormService( - id$: string = 'random_id' + id$: string = 'random_id', + errors = new BehaviorSubject([]) ): FormService { return jasmine.createSpyObj('FormService', { getUniqueId: id$, resetForm: {}, - validateAllFormFields: {} + validateAllFormFields: {}, + getForm: errors.pipe(map((err) => { return {data: {}, valid: true, errors: err} })), + removeForm: undefined, + removeError: undefined, + changeForm: undefined, + setStatusChanged: undefined, + initForm: undefined, + getFormErrors: errors, + addErrorToField: undefined }); } diff --git a/src/app/shared/testing/mock-store.ts b/src/app/shared/testing/mock-store.ts index fd47c71ae0..5223852c59 100644 --- a/src/app/shared/testing/mock-store.ts +++ b/src/app/shared/testing/mock-store.ts @@ -1,7 +1,6 @@ - -import {map} from 'rxjs/operators'; +import { map } from 'rxjs/operators'; import { Action } from '@ngrx/store'; -import { Observable , BehaviorSubject } from 'rxjs'; +import { BehaviorSubject, Observable } from 'rxjs'; export class MockStore extends BehaviorSubject { diff --git a/src/modules/app/server-app.module.ts b/src/modules/app/server-app.module.ts index 18f9865660..0e927f87f4 100644 --- a/src/modules/app/server-app.module.ts +++ b/src/modules/app/server-app.module.ts @@ -49,7 +49,10 @@ export function createTranslateLoader() { AppModule ], providers: [ - { provide: Angulartics2GoogleAnalytics, useClass: AngularticsMock }, + { + provide: Angulartics2GoogleAnalytics, + useClass: AngularticsMock + }, { provide: AuthService, useClass: ServerAuthService From acb5f5197d693697ddfa4762e1c89569822f5706 Mon Sep 17 00:00:00 2001 From: lotte Date: Tue, 11 Sep 2018 16:05:21 +0200 Subject: [PATCH 15/48] patching changes --- package.json | 5 +-- src/app/core/cache/object-cache.actions.ts | 31 +++++++++++++++-- src/app/core/cache/object-cache.reducer.ts | 32 ++++++++++++++++-- src/app/core/cache/object-cache.service.ts | 39 +++++++++++++++++++--- src/app/shared/form/form.reducer.ts | 1 - yarn.lock | 6 ++++ 6 files changed, 102 insertions(+), 12 deletions(-) diff --git a/package.json b/package.json index dca2420c62..c725029a12 100644 --- a/package.json +++ b/package.json @@ -41,8 +41,8 @@ "server:watch": "nodemon dist/server.js", "server:watch:debug": "nodemon --debug dist/server.js", "webpack:watch": "webpack -w --mode development", - "watch": "yarn run build && npm-run-all -p webpack:watch server:watch --mode development", - "watch:debug": "yarn run build && npm-run-all -p webpack:watch server:watch:debug --mode development", + "watch": "yarn run build && npm-run-all -p webpack:watch server:watch", + "watch:debug": "yarn run build && npm-run-all -p webpack:watch server:watch:debug", "predebug": "yarn run build", "predebug:server": "yarn run build", "debug": "node --debug-brk dist/server.js", @@ -96,6 +96,7 @@ "core-js": "2.5.3", "express": "4.16.2", "express-session": "1.15.6", + "fast-json-patch": "^2.0.7", "font-awesome": "4.7.0", "http-server": "0.11.1", "https": "1.0.0", diff --git a/src/app/core/cache/object-cache.actions.ts b/src/app/core/cache/object-cache.actions.ts index a136b04248..957c0f7269 100644 --- a/src/app/core/cache/object-cache.actions.ts +++ b/src/app/core/cache/object-cache.actions.ts @@ -2,6 +2,7 @@ import { Action } from '@ngrx/store'; import { type } from '../../shared/ngrx/type'; import { CacheableObject } from './object-cache.reducer'; +import { Operation } from 'fast-json-patch'; /** * The list of ObjectCacheAction type definitions @@ -9,7 +10,8 @@ import { CacheableObject } from './object-cache.reducer'; export const ObjectCacheActionTypes = { ADD: type('dspace/core/cache/object/ADD'), REMOVE: type('dspace/core/cache/object/REMOVE'), - RESET_TIMESTAMPS: type('dspace/core/cache/object/RESET_TIMESTAMPS') + RESET_TIMESTAMPS: type('dspace/core/cache/object/RESET_TIMESTAMPS'), + PATCH: type('dspace/core/cache/object/PATCH') }; /* tslint:disable:max-classes-per-file */ @@ -79,6 +81,30 @@ export class ResetObjectCacheTimestampsAction implements Action { this.payload = newTimestamp; } } + +/** + * An ngrx action to add new operations to a specified cached objects + */ +export class PatchObjectCacheAction implements Action { + type = ObjectCacheActionTypes.PATCH; + payload: { + uuid: string, + operations: Operation[] + }; + + /** + * Create a new PatchObjectCacheAction + * + * @param uuid + * the uuid of the object that should be updated + * @param operations + * the list of operations to add + */ + constructor(uuid: string, operations: Operation[]) { + this.payload = { uuid, operations }; + } +} + /* tslint:enable:max-classes-per-file */ /** @@ -87,4 +113,5 @@ export class ResetObjectCacheTimestampsAction implements Action { export type ObjectCacheAction = AddToObjectCacheAction | RemoveFromObjectCacheAction - | ResetObjectCacheTimestampsAction; + | ResetObjectCacheTimestampsAction + | PatchObjectCacheAction; diff --git a/src/app/core/cache/object-cache.reducer.ts b/src/app/core/cache/object-cache.reducer.ts index 3a1830e14a..5cc4b0551a 100644 --- a/src/app/core/cache/object-cache.reducer.ts +++ b/src/app/core/cache/object-cache.reducer.ts @@ -1,10 +1,11 @@ import { ObjectCacheAction, ObjectCacheActionTypes, AddToObjectCacheAction, - RemoveFromObjectCacheAction, ResetObjectCacheTimestampsAction + RemoveFromObjectCacheAction, ResetObjectCacheTimestampsAction, PatchObjectCacheAction } from './object-cache.actions'; -import { hasValue } from '../../shared/empty.util'; +import { hasValue, isNotEmpty } from '../../shared/empty.util'; import { CacheEntry } from './cache-entry'; import { ResourceType } from '../shared/resource-type'; +import { Operation } from 'fast-json-patch'; export enum DirtyType { Created = 'Created', @@ -36,6 +37,7 @@ export class ObjectCacheEntry implements CacheEntry { timeAdded: number; msToLive: number; requestHref: string; + operations: Operation[]; } /** @@ -76,6 +78,9 @@ export function objectCacheReducer(state = initialState, action: ObjectCacheActi return resetObjectCacheTimestamps(state, action as ResetObjectCacheTimestampsAction) } + case ObjectCacheActionTypes.PATCH: { + return patchObjectCache(state, action as PatchObjectCacheAction); + } default: { return state; } @@ -98,7 +103,8 @@ function addToObjectCache(state: ObjectCacheState, action: AddToObjectCacheActio data: action.payload.objectToCache, timeAdded: action.payload.timeAdded, msToLive: action.payload.msToLive, - requestHref: action.payload.requestHref + requestHref: action.payload.requestHref, + operations: [] } }); } @@ -143,3 +149,23 @@ function resetObjectCacheTimestamps(state: ObjectCacheState, action: ResetObject }); return newState; } + +/** + * Add the list of patch operations to a cached object + * + * @param state + * the current state + * @param action + * a PatchObjectCacheAction + * @return ObjectCacheState + * the new state, with the new operations added to the state of the specified ObjectCacheEntry + */ +function patchObjectCache(state: ObjectCacheState, action: PatchObjectCacheAction): ObjectCacheState { + const uuid = action.payload.uuid; + const operations = action.payload.operations; + const newState = Object.assign({}, state); + if (hasValue(newState[uuid])) { + newState[uuid].operations = state[uuid].operations.concat(operations); + } + return newState; +} diff --git a/src/app/core/cache/object-cache.service.ts b/src/app/core/cache/object-cache.service.ts index dbe241ffb3..d9b3077d55 100644 --- a/src/app/core/cache/object-cache.service.ts +++ b/src/app/core/cache/object-cache.service.ts @@ -1,18 +1,23 @@ import { combineLatest as observableCombineLatest, Observable } from 'rxjs'; -import { distinctUntilChanged, filter, first, map, mergeMap, take } from 'rxjs/operators'; +import { distinctUntilChanged, filter, first, map, mergeMap, take, tap } from 'rxjs/operators'; import { Injectable } from '@angular/core'; import { MemoizedSelector, select, Store } from '@ngrx/store'; import { IndexName } from '../index/index.reducer'; import { CacheableObject, ObjectCacheEntry } from './object-cache.reducer'; -import { AddToObjectCacheAction, RemoveFromObjectCacheAction } from './object-cache.actions'; -import { hasNoValue } from '../../shared/empty.util'; +import { + AddToObjectCacheAction, + PatchObjectCacheAction, + RemoveFromObjectCacheAction +} from './object-cache.actions'; +import { hasNoValue, isNotEmpty } from '../../shared/empty.util'; import { GenericConstructor } from '../shared/generic-constructor'; import { coreSelector, CoreState } from '../core.reducers'; import { pathSelector } from '../shared/selectors'; import { NormalizedObjectFactory } from './models/normalized-object-factory'; import { NormalizedObject } from './models/normalized-object.model'; +import { applyPatch, Operation } from 'fast-json-patch'; function selfLinkFromUuidSelector(uuid: string): MemoizedSelector { return pathSelector(coreSelector, 'index', IndexName.OBJECT, uuid); @@ -85,7 +90,11 @@ export class ObjectCacheService { map((entry: ObjectCacheEntry) => { const type: GenericConstructor = NormalizedObjectFactory.getConstructor(entry.data.type); return Object.assign(new type(), entry.data) as T - })); + }), + // map((entry: ObjectCacheEntry) => + // applyPatch(entry.data, entry.operations).newDocument + // ) + ); } private getEntry(selfLink: string): Observable { @@ -195,4 +204,26 @@ export class ObjectCacheService { } } + /** + * Add operations to a the existing list of operations for an ObjectCacheEntry + * @param {string} uuid + * the uuid of the ObjectCacheEntry + * @param {Operation[]} patch + * list of operations to perform + */ + private addOperations(uuid: string, patch: Operation[]) { + this.store.dispatch(new PatchObjectCacheAction(uuid, patch)); + } + + /** + * Check whether there are any unperformed operations for an ObjectCacheEntry + * + * @param entry + * the entry to check + * @return boolean + * false if the entry is there are no operations left in the ObjectCacheEntry, true otherwise + */ + private isDirty(entry: ObjectCacheEntry): boolean { + return isNotEmpty(entry.operations); + } } diff --git a/src/app/shared/form/form.reducer.ts b/src/app/shared/form/form.reducer.ts index 1a5d2da30b..eea5f99f20 100644 --- a/src/app/shared/form/form.reducer.ts +++ b/src/app/shared/form/form.reducer.ts @@ -30,7 +30,6 @@ export interface FormState { const initialState: FormState = Object.create(null); export function formReducer(state = initialState, action: FormAction): FormState { - console.log('TEST'); switch (action.type) { case FormActionTypes.FORM_INIT: { diff --git a/yarn.lock b/yarn.lock index 6129ef4e7e..b834144eb8 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3026,6 +3026,12 @@ fast-glob@^2.0.2: merge2 "^1.2.1" micromatch "^3.1.10" +fast-json-patch@^2.0.7: + version "2.0.7" + resolved "https://registry.yarnpkg.com/fast-json-patch/-/fast-json-patch-2.0.7.tgz#55864b08b1e50381d2f37fd472bb2e18fe54a733" + dependencies: + deep-equal "^1.0.1" + fast-json-stable-stringify@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz#d5142c0caee6b1189f87d3a76111064f86c8bbf2" From caf9194f3627b69a391b235b71b14d5e387cb511 Mon Sep 17 00:00:00 2001 From: lotte Date: Wed, 12 Sep 2018 11:38:08 +0200 Subject: [PATCH 16/48] Fixes for authentication (awaiting fixes in EPerson REST endpoint) --- src/app/core/auth/auth-object-factory.ts | 8 +++--- .../auth-response-parsing.service.spec.ts | 19 +++++++++---- .../auth/auth-response-parsing.service.ts | 9 +++--- src/app/core/auth/auth.effects.spec.ts | 1 - src/app/core/auth/auth.service.spec.ts | 10 +++++-- src/app/core/auth/auth.service.ts | 28 ++++++++++++++----- src/app/core/auth/models/auth-status.model.ts | 5 ++-- .../models/normalized-auth-status.model.ts | 22 +++++++++------ src/app/core/auth/server-auth.service.ts | 11 ++++---- .../cache/models/normalized-object-factory.ts | 8 ++++++ src/app/core/data/data.service.ts | 7 +++-- .../eperson/models/NormalizedEperson.model.ts | 2 +- .../eperson/models/NormalizedGroup.model.ts | 3 +- .../auth-nav-menu/auth-nav-menu.component.ts | 1 + .../mocks/mock-remote-data-build.service.ts | 4 ++- .../testing/auth-request-service-stub.ts | 5 ++-- src/app/shared/testing/auth-service-stub.ts | 3 +- 17 files changed, 96 insertions(+), 50 deletions(-) diff --git a/src/app/core/auth/auth-object-factory.ts b/src/app/core/auth/auth-object-factory.ts index c3e70eaaac..02330ca5b3 100644 --- a/src/app/core/auth/auth-object-factory.ts +++ b/src/app/core/auth/auth-object-factory.ts @@ -1,14 +1,14 @@ import { AuthType } from './auth-type'; import { GenericConstructor } from '../shared/generic-constructor'; import { NormalizedAuthStatus } from './models/normalized-auth-status.model'; -import { NormalizedDSpaceObject } from '../cache/models/normalized-dspace-object.model'; -import { NormalizedEpersonModel } from '../eperson/models/NormalizedEperson.model'; +import { NormalizedEperson } from '../eperson/models/NormalizedEperson.model'; +import { NormalizedObject } from '../cache/models/normalized-object.model'; export class AuthObjectFactory { - public static getConstructor(type): GenericConstructor { + public static getConstructor(type): GenericConstructor { switch (type) { case AuthType.Eperson: { - return NormalizedEpersonModel + return NormalizedEperson } case AuthType.Status: { diff --git a/src/app/core/auth/auth-response-parsing.service.spec.ts b/src/app/core/auth/auth-response-parsing.service.spec.ts index f7d899a9bc..f6dd87e99a 100644 --- a/src/app/core/auth/auth-response-parsing.service.spec.ts +++ b/src/app/core/auth/auth-response-parsing.service.spec.ts @@ -8,12 +8,13 @@ import { CoreState } from '../core.reducers'; import { AuthStatus } from './models/auth-status.model'; import { AuthResponseParsingService } from './auth-response-parsing.service'; import { AuthGetRequest, AuthPostRequest } from '../data/request.models'; +import { getMockStore } from '../../shared/mocks/mock-store'; -describe('ConfigResponseParsingService', () => { +describe('AuthResponseParsingService', () => { let service: AuthResponseParsingService; - const EnvConfig = {} as GlobalConfig; - const store = {} as Store; + const EnvConfig = {cache: {msToLive: 1000}} as GlobalConfig; + const store = getMockStore() as Store; const objectCacheService = new ObjectCacheService(store); beforeEach(() => { @@ -86,13 +87,19 @@ describe('ConfigResponseParsingService', () => { type: 'eperson', uuid: '4dc70ab5-cd73-492f-b007-3179d2d9296b', _links: { - self: 'https://hasselt-dspace.dev01.4science.it/dspace-spring-rest/api/eperson/epersons/4dc70ab5-cd73-492f-b007-3179d2d9296b' + self: { + href: 'https://hasselt-dspace.dev01.4science.it/dspace-spring-rest/api/eperson/epersons/4dc70ab5-cd73-492f-b007-3179d2d9296b' + } } } }, _links: { - eperson: 'https://hasselt-dspace.dev01.4science.it/dspace-spring-rest/api/eperson/epersons/4dc70ab5-cd73-492f-b007-3179d2d9296b', - self: 'https://hasselt-dspace.dev01.4science.it/dspace-spring-rest/api/authn/status' + eperson: { + href: 'https://hasselt-dspace.dev01.4science.it/dspace-spring-rest/api/eperson/epersons/4dc70ab5-cd73-492f-b007-3179d2d9296b' + }, + self: { + href: 'https://hasselt-dspace.dev01.4science.it/dspace-spring-rest/api/authn/status' + } } }, statusCode: '200' diff --git a/src/app/core/auth/auth-response-parsing.service.ts b/src/app/core/auth/auth-response-parsing.service.ts index 80c1b2eeca..8efa36f9e2 100644 --- a/src/app/core/auth/auth-response-parsing.service.ts +++ b/src/app/core/auth/auth-response-parsing.service.ts @@ -12,22 +12,23 @@ import { ResponseParsingService } from '../data/parsing.service'; import { RestRequest } from '../data/request.models'; import { AuthType } from './auth-type'; import { AuthStatus } from './models/auth-status.model'; +import { NormalizedAuthStatus } from './models/normalized-auth-status.model'; @Injectable() export class AuthResponseParsingService extends BaseResponseParsingService implements ResponseParsingService { protected objectFactory = AuthObjectFactory; - protected toCache = false; + protected toCache = true; constructor(@Inject(GLOBAL_CONFIG) protected EnvConfig: GlobalConfig, - protected objectCache: ObjectCacheService,) { + protected objectCache: ObjectCacheService) { super(); } parse(request: RestRequest, data: DSpaceRESTV2Response): RestResponse { if (isNotEmpty(data.payload) && isNotEmpty(data.payload._links) && (data.statusCode === '200' || data.statusCode === 'OK')) { - const response = this.process(data.payload, request.href); - return new AuthStatusResponse(response[Object.keys(response)[0]][0], data.statusCode); + const response = this.process(data.payload, request.href); + return new AuthStatusResponse(response, data.statusCode); } else { return new AuthStatusResponse(data.payload as AuthStatus, data.statusCode); } diff --git a/src/app/core/auth/auth.effects.spec.ts b/src/app/core/auth/auth.effects.spec.ts index 3b569e523f..b862ae77fe 100644 --- a/src/app/core/auth/auth.effects.spec.ts +++ b/src/app/core/auth/auth.effects.spec.ts @@ -30,7 +30,6 @@ import { EpersonMock } from '../../shared/testing/eperson-mock'; describe('AuthEffects', () => { let authEffects: AuthEffects; let actions: Observable; - const authServiceStub = new AuthServiceStub(); const store: Store = jasmine.createSpyObj('store', { /* tslint:disable:no-empty */ diff --git a/src/app/core/auth/auth.service.spec.ts b/src/app/core/auth/auth.service.spec.ts index b54f65078e..b238bef033 100644 --- a/src/app/core/auth/auth.service.spec.ts +++ b/src/app/core/auth/auth.service.spec.ts @@ -22,6 +22,8 @@ import { Eperson } from '../eperson/models/eperson.model'; import { EpersonMock } from '../../shared/testing/eperson-mock'; import { AppState } from '../../app.reducer'; import { ClientCookieService } from '../../shared/services/client-cookie.service'; +import { RemoteDataBuildService } from '../cache/builders/remote-data-build.service'; +import { getMockRemoteDataBuildService } from '../../shared/mocks/mock-remote-data-build.service'; describe('AuthService test', () => { @@ -44,7 +46,7 @@ describe('AuthService test', () => { authToken: token, user: EpersonMock }; - + const rdbService = getMockRemoteDataBuildService(); describe('', () => { beforeEach(() => { @@ -61,6 +63,7 @@ describe('AuthService test', () => { {provide: Router, useValue: routerStub}, {provide: ActivatedRoute, useValue: routeStub}, {provide: Store, useValue: mockStore}, + {provide: RemoteDataBuildService, useValue: rdbService}, CookieService, AuthService ], @@ -121,6 +124,7 @@ describe('AuthService test', () => { {provide: AuthRequestService, useValue: authRequest}, {provide: REQUEST, useValue: {}}, {provide: Router, useValue: routerStub}, + {provide: RemoteDataBuildService, useValue: rdbService}, CookieService ] }).compileComponents(); @@ -132,7 +136,7 @@ describe('AuthService test', () => { (state as any).core = Object.create({}); (state as any).core.auth = authenticatedState; }); - authService = new AuthService({}, window, authReqService, router, cookieService, store); + authService = new AuthService({}, window, authReqService, router, cookieService, store, rdbService); })); it('should return true when user is logged in', () => { @@ -191,7 +195,7 @@ describe('AuthService test', () => { (state as any).core = Object.create({}); (state as any).core.auth = authenticatedState; }); - authService = new AuthService({}, window, authReqService, router, cookieService, store); + authService = new AuthService({}, window, authReqService, router, cookieService, store, rdbService); storage = (authService as any).storage; spyOn(storage, 'get'); spyOn(storage, 'remove'); diff --git a/src/app/core/auth/auth.service.ts b/src/app/core/auth/auth.service.ts index 2848b54b50..f19651e0dd 100644 --- a/src/app/core/auth/auth.service.ts +++ b/src/app/core/auth/auth.service.ts @@ -7,7 +7,7 @@ import { RouterReducerState } from '@ngrx/router-store'; import { Store } from '@ngrx/store'; import { CookieAttributes } from 'js-cookie'; import { Observable } from 'rxjs/Observable'; -import { map, withLatestFrom } from 'rxjs/operators'; +import { map, switchMap, withLatestFrom } from 'rxjs/operators'; import { Eperson } from '../eperson/models/eperson.model'; import { AuthRequestService } from './auth-request.service'; @@ -17,11 +17,18 @@ import { AuthStatus } from './models/auth-status.model'; import { AuthTokenInfo, TOKENITEM } from './models/auth-token-info.model'; import { isEmpty, isNotEmpty, isNotNull, isNotUndefined } from '../../shared/empty.util'; import { CookieService } from '../../shared/services/cookie.service'; -import { getAuthenticationToken, getRedirectUrl, isAuthenticated, isTokenRefreshing } from './selectors'; +import { + getAuthenticationToken, + getRedirectUrl, + isAuthenticated, + isTokenRefreshing +} from './selectors'; import { AppState, routerStateSelector } from '../../app.reducer'; import { ResetAuthenticationMessagesAction, SetRedirectUrlAction } from './auth.actions'; import { NativeWindowRef, NativeWindowService } from '../../shared/services/window.service'; import { Base64EncodeUrl } from '../../shared/utils/encode-decode.util'; +import { RemoteDataBuildService } from '../cache/builders/remote-data-build.service'; +import { NormalizedEperson } from '../eperson/models/NormalizedEperson.model'; export const LOGIN_ROUTE = '/login'; export const LOGOUT_ROUTE = '/logout'; @@ -45,7 +52,9 @@ export class AuthService { protected authRequestService: AuthRequestService, protected router: Router, protected storage: CookieService, - protected store: Store) { + protected store: Store, + protected rdbService: RemoteDataBuildService + ) { this.store.select(isAuthenticated) .startWith(false) .subscribe((authenticated: boolean) => this._authenticated = authenticated); @@ -123,14 +132,19 @@ export class AuthService { headers = headers.append('Accept', 'application/json'); headers = headers.append('Authorization', `Bearer ${token.accessToken}`); options.headers = headers; - return this.authRequestService.getRequest('status', options) - .map((status: AuthStatus) => { + return this.authRequestService.getRequest('status', options).pipe( + switchMap((status: AuthStatus) => { + if (status.authenticated) { - return status.eperson[0]; + + // TODO this should be cleaned up, AuthStatus could be parsed by the RemoteDataService as a whole... + const person$ = this.rdbService.buildSingle(status.eperson.toString()); + // person$.subscribe(() => console.log('test')); + return person$.pipe(map((eperson) => eperson.payload)); } else { throw(new Error('Not authenticated')); } - }); + })) } /** diff --git a/src/app/core/auth/models/auth-status.model.ts b/src/app/core/auth/models/auth-status.model.ts index 22c9d14718..bf90b82bf6 100644 --- a/src/app/core/auth/models/auth-status.model.ts +++ b/src/app/core/auth/models/auth-status.model.ts @@ -1,7 +1,8 @@ import { AuthError } from './auth-error.model'; import { AuthTokenInfo } from './auth-token-info.model'; -import { DSpaceObject } from '../../shared/dspace-object.model'; import { Eperson } from '../../eperson/models/eperson.model'; +import { RemoteData } from '../../data/remote-data'; +import { Observable } from 'rxjs/Observable'; export class AuthStatus { @@ -13,7 +14,7 @@ export class AuthStatus { error?: AuthError; - eperson: Eperson[]; + eperson: Observable>; token?: AuthTokenInfo; diff --git a/src/app/core/auth/models/normalized-auth-status.model.ts b/src/app/core/auth/models/normalized-auth-status.model.ts index 19952f7c70..f7f6ab5a9e 100644 --- a/src/app/core/auth/models/normalized-auth-status.model.ts +++ b/src/app/core/auth/models/normalized-auth-status.model.ts @@ -1,12 +1,18 @@ import { AuthStatus } from './auth-status.model'; import { autoserialize, autoserializeAs, inheritSerialization } from 'cerialize'; -import { mapsTo } from '../../cache/builders/build-decorators'; -import { NormalizedDSpaceObject } from '../../cache/models/normalized-dspace-object.model'; -import { Eperson } from '../../eperson/models/eperson.model'; +import { mapsTo, relationship } from '../../cache/builders/build-decorators'; +import { ResourceType } from '../../shared/resource-type'; +import { NormalizedObject } from '../../cache/models/normalized-object.model'; +import { IDToUUIDSerializer } from '../../cache/id-to-uuid-serializer'; @mapsTo(AuthStatus) -@inheritSerialization(NormalizedDSpaceObject) -export class NormalizedAuthStatus extends NormalizedDSpaceObject { +@inheritSerialization(NormalizedObject) +export class NormalizedAuthStatus extends NormalizedObject { + @autoserialize + id: string; + + @autoserializeAs(new IDToUUIDSerializer('auth-status'), 'id') + uuid: string; /** * True if REST API is up and running, should never return false @@ -20,7 +26,7 @@ export class NormalizedAuthStatus extends NormalizedDSpaceObject { @autoserialize authenticated: boolean; - @autoserializeAs(Eperson) - eperson: Eperson[]; - + @relationship(ResourceType.Eperson, false) + @autoserialize + eperson: string; } diff --git a/src/app/core/auth/server-auth.service.ts b/src/app/core/auth/server-auth.service.ts index 96ee2e355a..833df4b9d2 100644 --- a/src/app/core/auth/server-auth.service.ts +++ b/src/app/core/auth/server-auth.service.ts @@ -1,3 +1,4 @@ +import {first, map} from 'rxjs/operators'; import { Injectable } from '@angular/core'; import { Observable } from 'rxjs/Observable'; @@ -32,14 +33,14 @@ export class ServerAuthService extends AuthService { headers = headers.append('X-Forwarded-For', clientIp); options.headers = headers; - return this.authRequestService.getRequest('status', options) - .map((status: AuthStatus) => { + return this.authRequestService.getRequest('status', options).pipe( + map((status: AuthStatus) => { if (status.authenticated) { return status.eperson[0]; } else { throw(new Error('Not authenticated')); } - }); + })); } /** @@ -53,8 +54,8 @@ export class ServerAuthService extends AuthService { * Redirect to the route navigated before the login */ public redirectToPreviousUrl() { - this.getRedirectUrl() - .first() + this.getRedirectUrl().pipe( + first()) .subscribe((redirectUrl) => { if (isNotEmpty(redirectUrl)) { // override the route reuse strategy diff --git a/src/app/core/cache/models/normalized-object-factory.ts b/src/app/core/cache/models/normalized-object-factory.ts index df67a1f2ce..fc35dffca8 100644 --- a/src/app/core/cache/models/normalized-object-factory.ts +++ b/src/app/core/cache/models/normalized-object-factory.ts @@ -8,6 +8,8 @@ import { ResourceType } from '../../shared/resource-type'; import { NormalizedObject } from './normalized-object.model'; import { NormalizedBitstreamFormat } from './normalized-bitstream-format.model'; import { NormalizedResourcePolicy } from './normalized-resource-policy.model'; +import { NormalizedEperson } from '../../eperson/models/NormalizedEperson.model'; +import { NormalizedGroup } from '../../eperson/models/NormalizedGroup.model'; export class NormalizedObjectFactory { public static getConstructor(type: ResourceType): GenericConstructor { @@ -33,6 +35,12 @@ export class NormalizedObjectFactory { case ResourceType.ResourcePolicy: { return NormalizedResourcePolicy } + case ResourceType.Eperson: { + return NormalizedEperson + } + case ResourceType.Group: { + return NormalizedGroup + } default: { return undefined; } diff --git a/src/app/core/data/data.service.ts b/src/app/core/data/data.service.ts index c7588a5231..c6b2c51134 100644 --- a/src/app/core/data/data.service.ts +++ b/src/app/core/data/data.service.ts @@ -1,3 +1,4 @@ +import { filter, take } from 'rxjs/operators'; import { Store } from '@ngrx/store'; import { Observable } from 'rxjs/Observable'; import { hasValue, isNotEmpty } from '../../shared/empty.util'; @@ -60,9 +61,9 @@ export abstract class DataService const hrefObs = this.halService.getEndpoint(this.linkPath).filter((href: string) => isNotEmpty(href)) .flatMap((endpoint: string) => this.getFindAllHref(endpoint, options)); - hrefObs - .filter((href: string) => hasValue(href)) - .take(1) + hrefObs.pipe( + filter((href: string) => hasValue(href)), + take(1)) .subscribe((href: string) => { const request = new FindAllRequest(this.requestService.generateRequestId(), href, options); this.requestService.configure(request); diff --git a/src/app/core/eperson/models/NormalizedEperson.model.ts b/src/app/core/eperson/models/NormalizedEperson.model.ts index 0c0b2490d6..bdcd069eb8 100644 --- a/src/app/core/eperson/models/NormalizedEperson.model.ts +++ b/src/app/core/eperson/models/NormalizedEperson.model.ts @@ -8,7 +8,7 @@ import { ResourceType } from '../../shared/resource-type'; @mapsTo(Eperson) @inheritSerialization(NormalizedDSpaceObject) -export class NormalizedEpersonModel extends NormalizedDSpaceObject implements CacheableObject, ListableObject { +export class NormalizedEperson extends NormalizedDSpaceObject implements CacheableObject, ListableObject { @autoserialize public handle: string; diff --git a/src/app/core/eperson/models/NormalizedGroup.model.ts b/src/app/core/eperson/models/NormalizedGroup.model.ts index 24f7da8eab..be5995d9c5 100644 --- a/src/app/core/eperson/models/NormalizedGroup.model.ts +++ b/src/app/core/eperson/models/NormalizedGroup.model.ts @@ -2,13 +2,12 @@ import { autoserialize, inheritSerialization } from 'cerialize'; import { CacheableObject } from '../../cache/object-cache.reducer'; import { ListableObject } from '../../../shared/object-collection/shared/listable-object.model'; import { NormalizedDSpaceObject } from '../../cache/models/normalized-dspace-object.model'; -import { Eperson } from './eperson.model'; import { mapsTo } from '../../cache/builders/build-decorators'; import { Group } from './group.model'; @mapsTo(Group) @inheritSerialization(NormalizedDSpaceObject) -export class NormalizedGroupModel extends NormalizedDSpaceObject implements CacheableObject, ListableObject { +export class NormalizedGroup extends NormalizedDSpaceObject implements CacheableObject, ListableObject { @autoserialize public handle: string; diff --git a/src/app/shared/auth-nav-menu/auth-nav-menu.component.ts b/src/app/shared/auth-nav-menu/auth-nav-menu.component.ts index 1c376258fb..05dfd2d872 100644 --- a/src/app/shared/auth-nav-menu/auth-nav-menu.component.ts +++ b/src/app/shared/auth-nav-menu/auth-nav-menu.component.ts @@ -10,6 +10,7 @@ import { isNotUndefined } from '../empty.util'; import { getAuthenticatedUser, isAuthenticated, isAuthenticationLoading } from '../../core/auth/selectors'; import { Eperson } from '../../core/eperson/models/eperson.model'; import { LOGIN_ROUTE, LOGOUT_ROUTE } from '../../core/auth/auth.service'; +import { RemoteData } from '../../core/data/remote-data'; @Component({ selector: 'ds-auth-nav-menu', diff --git a/src/app/shared/mocks/mock-remote-data-build.service.ts b/src/app/shared/mocks/mock-remote-data-build.service.ts index c10032eb94..8f93fe2d96 100644 --- a/src/app/shared/mocks/mock-remote-data-build.service.ts +++ b/src/app/shared/mocks/mock-remote-data-build.service.ts @@ -5,6 +5,7 @@ import { ResponseCacheEntry } from '../../core/cache/response-cache.reducer'; import { RemoteData } from '../../core/data/remote-data'; import { RequestEntry } from '../../core/data/request.reducer'; import { hasValue } from '../empty.util'; +import { NormalizedObject } from '../../core/cache/models/normalized-object.model'; export function getMockRemoteDataBuildService(toRemoteDataObservable$?: Observable>): RemoteDataBuildService { return { @@ -17,7 +18,8 @@ export function getMockRemoteDataBuildService(toRemoteDataObservable$?: Observab payload } as RemoteData))) } - } + }, + buildSingle: (href$: string | Observable) => Observable.of(new RemoteData(false, false, true, undefined, {})) } as RemoteDataBuildService; } diff --git a/src/app/shared/testing/auth-request-service-stub.ts b/src/app/shared/testing/auth-request-service-stub.ts index 2c47068af4..4f525463c5 100644 --- a/src/app/shared/testing/auth-request-service-stub.ts +++ b/src/app/shared/testing/auth-request-service-stub.ts @@ -5,6 +5,7 @@ import { AuthTokenInfo } from '../../core/auth/models/auth-token-info.model'; import { Eperson } from '../../core/eperson/models/eperson.model'; import { isNotEmpty } from '../empty.util'; import { EpersonMock } from './eperson-mock'; +import { RemoteData } from '../../core/data/remote-data'; export class AuthRequestServiceStub { protected mockUser: Eperson = EpersonMock; @@ -26,7 +27,7 @@ export class AuthRequestServiceStub { if (this.validateToken(token)) { authStatusStub.authenticated = true; authStatusStub.token = this.mockTokenInfo; - authStatusStub.eperson = [this.mockUser]; + authStatusStub.eperson = Observable.of(new RemoteData(false, false, true, undefined, this.mockUser)); } else { authStatusStub.authenticated = false; } @@ -45,7 +46,7 @@ export class AuthRequestServiceStub { if (this.validateToken(token)) { authStatusStub.authenticated = true; authStatusStub.token = this.mockTokenInfo; - authStatusStub.eperson = [this.mockUser]; + authStatusStub.eperson = Observable.of(new RemoteData(false, false, true, undefined, this.mockUser)); } else { authStatusStub.authenticated = false; } diff --git a/src/app/shared/testing/auth-service-stub.ts b/src/app/shared/testing/auth-service-stub.ts index c7d5556910..07157c8623 100644 --- a/src/app/shared/testing/auth-service-stub.ts +++ b/src/app/shared/testing/auth-service-stub.ts @@ -3,6 +3,7 @@ import { Observable } from 'rxjs/Observable'; import { AuthTokenInfo } from '../../core/auth/models/auth-token-info.model'; import { EpersonMock } from './eperson-mock'; import { Eperson } from '../../core/eperson/models/eperson.model'; +import { RemoteData } from '../../core/data/remote-data'; export class AuthServiceStub { @@ -19,7 +20,7 @@ export class AuthServiceStub { authStatus.okay = true; authStatus.authenticated = true; authStatus.token = this.token; - authStatus.eperson = [EpersonMock]; + authStatus.eperson = Observable.of(new RemoteData(false, false, true, undefined, EpersonMock)); return Observable.of(authStatus); } else { console.log('error'); From 1f336f29fdf6941d8f35ddb94a0a7715008cfafc Mon Sep 17 00:00:00 2001 From: lotte Date: Wed, 12 Sep 2018 16:11:04 +0200 Subject: [PATCH 17/48] small fixes for authentication --- src/app/core/auth/auth-object-factory.ts | 7 ++--- src/app/core/auth/auth-type.ts | 2 +- src/app/core/auth/auth.actions.ts | 14 +++++----- src/app/core/auth/auth.effects.spec.ts | 4 +-- src/app/core/auth/auth.effects.ts | 6 ++--- src/app/core/auth/auth.reducer.spec.ts | 26 +++++++++---------- src/app/core/auth/auth.reducer.ts | 4 +-- src/app/core/auth/auth.service.spec.ts | 10 +++---- src/app/core/auth/auth.service.ts | 14 +++++----- src/app/core/auth/models/auth-status.model.ts | 4 +-- .../models/normalized-auth-status.model.ts | 2 +- src/app/core/auth/server-auth.service.ts | 20 +++++++++----- .../cache/models/normalized-object-factory.ts | 8 +++--- .../data/base-response-parsing.service.ts | 22 ++++++++++++++++ src/app/core/eperson/models/eperson.model.ts | 2 +- ...n.model.ts => normalized-eperson.model.ts} | 6 ++--- ...oup.model.ts => normalized-group.model.ts} | 0 src/app/core/shared/resource-type.ts | 2 +- .../auth-nav-menu.component.spec.ts | 5 ++-- .../auth-nav-menu/auth-nav-menu.component.ts | 4 +-- .../shared/log-in/log-in.component.spec.ts | 8 +++--- .../shared/log-out/log-out.component.spec.ts | 8 +++--- .../testing/auth-request-service-stub.ts | 10 +++---- src/app/shared/testing/auth-service-stub.ts | 10 +++---- src/app/shared/testing/eperson-mock.ts | 4 +-- 25 files changed, 115 insertions(+), 87 deletions(-) rename src/app/core/eperson/models/{NormalizedEperson.model.ts => normalized-eperson.model.ts} (88%) rename src/app/core/eperson/models/{NormalizedGroup.model.ts => normalized-group.model.ts} (100%) diff --git a/src/app/core/auth/auth-object-factory.ts b/src/app/core/auth/auth-object-factory.ts index 02330ca5b3..b6df1fac34 100644 --- a/src/app/core/auth/auth-object-factory.ts +++ b/src/app/core/auth/auth-object-factory.ts @@ -1,14 +1,15 @@ import { AuthType } from './auth-type'; import { GenericConstructor } from '../shared/generic-constructor'; import { NormalizedAuthStatus } from './models/normalized-auth-status.model'; -import { NormalizedEperson } from '../eperson/models/NormalizedEperson.model'; +import { NormalizedEPerson } from '../eperson/models/normalized-eperson.model'; import { NormalizedObject } from '../cache/models/normalized-object.model'; +import { EPerson } from '../eperson/models/eperson.model'; export class AuthObjectFactory { public static getConstructor(type): GenericConstructor { switch (type) { - case AuthType.Eperson: { - return NormalizedEperson + case AuthType.EPerson: { + return NormalizedEPerson } case AuthType.Status: { diff --git a/src/app/core/auth/auth-type.ts b/src/app/core/auth/auth-type.ts index b8879ae445..9a248da91f 100644 --- a/src/app/core/auth/auth-type.ts +++ b/src/app/core/auth/auth-type.ts @@ -1,4 +1,4 @@ export enum AuthType { - Eperson = 'eperson', + EPerson = 'eperson', Status = 'status' } diff --git a/src/app/core/auth/auth.actions.ts b/src/app/core/auth/auth.actions.ts index 207e8fae70..d0969d38d4 100644 --- a/src/app/core/auth/auth.actions.ts +++ b/src/app/core/auth/auth.actions.ts @@ -5,7 +5,7 @@ import { Action } from '@ngrx/store'; import { type } from '../../shared/ngrx/type'; // import models -import { Eperson } from '../eperson/models/eperson.model'; +import { EPerson } from '../eperson/models/eperson.model'; import { AuthTokenInfo } from './models/auth-token-info.model'; export const AuthActionTypes = { @@ -76,10 +76,10 @@ export class AuthenticatedSuccessAction implements Action { payload: { authenticated: boolean; authToken: AuthTokenInfo; - user: Eperson + user: EPerson }; - constructor(authenticated: boolean, authToken: AuthTokenInfo, user: Eperson) { + constructor(authenticated: boolean, authToken: AuthTokenInfo, user: EPerson) { this.payload = { authenticated, authToken, user }; } } @@ -250,9 +250,9 @@ export class RefreshTokenErrorAction implements Action { */ export class RegistrationAction implements Action { public type: string = AuthActionTypes.REGISTRATION; - payload: Eperson; + payload: EPerson; - constructor(user: Eperson) { + constructor(user: EPerson) { this.payload = user; } } @@ -278,9 +278,9 @@ export class RegistrationErrorAction implements Action { */ export class RegistrationSuccessAction implements Action { public type: string = AuthActionTypes.REGISTRATION_SUCCESS; - payload: Eperson; + payload: EPerson; - constructor(user: Eperson) { + constructor(user: EPerson) { this.payload = user; } } diff --git a/src/app/core/auth/auth.effects.spec.ts b/src/app/core/auth/auth.effects.spec.ts index b862ae77fe..d75b407516 100644 --- a/src/app/core/auth/auth.effects.spec.ts +++ b/src/app/core/auth/auth.effects.spec.ts @@ -25,7 +25,7 @@ import { AuthServiceStub } from '../../shared/testing/auth-service-stub'; import { AuthService } from './auth.service'; import { TruncatablesState } from '../../shared/truncatable/truncatable.reducer'; -import { EpersonMock } from '../../shared/testing/eperson-mock'; +import { EPersonMock } from '../../shared/testing/eperson-mock'; describe('AuthEffects', () => { let authEffects: AuthEffects; @@ -104,7 +104,7 @@ describe('AuthEffects', () => { it('should return a AUTHENTICATED_SUCCESS action in response to a AUTHENTICATED action', () => { actions = hot('--a-', {a: {type: AuthActionTypes.AUTHENTICATED, payload: token}}); - const expected = cold('--b-', {b: new AuthenticatedSuccessAction(true, token, EpersonMock)}); + const expected = cold('--b-', {b: new AuthenticatedSuccessAction(true, token, EPersonMock)}); expect(authEffects.authenticated$).toBeObservable(expected); }); diff --git a/src/app/core/auth/auth.effects.ts b/src/app/core/auth/auth.effects.ts index e2d6c80b5e..82def702eb 100644 --- a/src/app/core/auth/auth.effects.ts +++ b/src/app/core/auth/auth.effects.ts @@ -28,7 +28,7 @@ import { RegistrationErrorAction, RegistrationSuccessAction } from './auth.actions'; -import { Eperson } from '../eperson/models/eperson.model'; +import { EPerson } from '../eperson/models/eperson.model'; import { AuthStatus } from './models/auth-status.model'; import { AuthTokenInfo } from './models/auth-token-info.model'; import { AppState } from '../../app.reducer'; @@ -63,7 +63,7 @@ export class AuthEffects { .ofType(AuthActionTypes.AUTHENTICATED) .switchMap((action: AuthenticatedAction) => { return this.authService.authenticatedUser(action.payload) - .map((user: Eperson) => new AuthenticatedSuccessAction((user !== null), action.payload, user)) + .map((user: EPerson) => new AuthenticatedSuccessAction((user !== null), action.payload, user)) .catch((error) => Observable.of(new AuthenticatedErrorAction(error))); }); @@ -88,7 +88,7 @@ export class AuthEffects { .debounceTime(500) // to remove when functionality is implemented .switchMap((action: RegistrationAction) => { return this.authService.create(action.payload) - .map((user: Eperson) => new RegistrationSuccessAction(user)) + .map((user: EPerson) => new RegistrationSuccessAction(user)) .catch((error) => Observable.of(new RegistrationErrorAction(error))); }); diff --git a/src/app/core/auth/auth.reducer.spec.ts b/src/app/core/auth/auth.reducer.spec.ts index f148f3ac8d..ca2ba00036 100644 --- a/src/app/core/auth/auth.reducer.spec.ts +++ b/src/app/core/auth/auth.reducer.spec.ts @@ -21,7 +21,7 @@ import { SetRedirectUrlAction } from './auth.actions'; import { AuthTokenInfo } from './models/auth-token-info.model'; -import { EpersonMock } from '../../shared/testing/eperson-mock'; +import { EPersonMock } from '../../shared/testing/eperson-mock'; describe('authReducer', () => { @@ -107,7 +107,7 @@ describe('authReducer', () => { loading: true, info: undefined }; - const action = new AuthenticatedSuccessAction(true, mockTokenInfo, EpersonMock); + const action = new AuthenticatedSuccessAction(true, mockTokenInfo, EPersonMock); const newState = authReducer(initialState, action); state = { authenticated: true, @@ -116,7 +116,7 @@ describe('authReducer', () => { error: undefined, loading: false, info: undefined, - user: EpersonMock + user: EPersonMock }; expect(newState).toEqual(state); }); @@ -182,7 +182,7 @@ describe('authReducer', () => { error: undefined, loading: false, info: undefined, - user: EpersonMock + user: EPersonMock }; const action = new LogOutAction(); @@ -199,7 +199,7 @@ describe('authReducer', () => { error: undefined, loading: false, info: undefined, - user: EpersonMock + user: EPersonMock }; const action = new LogOutSuccessAction(); @@ -225,7 +225,7 @@ describe('authReducer', () => { error: undefined, loading: false, info: undefined, - user: EpersonMock + user: EPersonMock }; const action = new LogOutErrorAction(mockError); @@ -237,7 +237,7 @@ describe('authReducer', () => { error: 'Test error message', loading: false, info: undefined, - user: EpersonMock + user: EPersonMock }; expect(newState).toEqual(state); }); @@ -250,7 +250,7 @@ describe('authReducer', () => { error: undefined, loading: false, info: undefined, - user: EpersonMock + user: EPersonMock }; const newTokenInfo = new AuthTokenInfo('Refreshed token'); const action = new RefreshTokenAction(newTokenInfo); @@ -262,7 +262,7 @@ describe('authReducer', () => { error: undefined, loading: false, info: undefined, - user: EpersonMock, + user: EPersonMock, refreshing: true }; expect(newState).toEqual(state); @@ -276,7 +276,7 @@ describe('authReducer', () => { error: undefined, loading: false, info: undefined, - user: EpersonMock, + user: EPersonMock, refreshing: true }; const newTokenInfo = new AuthTokenInfo('Refreshed token'); @@ -289,7 +289,7 @@ describe('authReducer', () => { error: undefined, loading: false, info: undefined, - user: EpersonMock, + user: EPersonMock, refreshing: false }; expect(newState).toEqual(state); @@ -303,7 +303,7 @@ describe('authReducer', () => { error: undefined, loading: false, info: undefined, - user: EpersonMock, + user: EPersonMock, refreshing: true }; const action = new RefreshTokenErrorAction(); @@ -329,7 +329,7 @@ describe('authReducer', () => { error: undefined, loading: false, info: undefined, - user: EpersonMock + user: EPersonMock }; state = { diff --git a/src/app/core/auth/auth.reducer.ts b/src/app/core/auth/auth.reducer.ts index 0c5e36ce91..98827d842e 100644 --- a/src/app/core/auth/auth.reducer.ts +++ b/src/app/core/auth/auth.reducer.ts @@ -12,7 +12,7 @@ import { SetRedirectUrlAction } from './auth.actions'; // import models -import { Eperson } from '../eperson/models/eperson.model'; +import { EPerson } from '../eperson/models/eperson.model'; import { AuthTokenInfo } from './models/auth-token-info.model'; /** @@ -46,7 +46,7 @@ export interface AuthState { refreshing?: boolean; // the authenticated user - user?: Eperson; + user?: EPerson; } /** diff --git a/src/app/core/auth/auth.service.spec.ts b/src/app/core/auth/auth.service.spec.ts index b238bef033..c943a815e7 100644 --- a/src/app/core/auth/auth.service.spec.ts +++ b/src/app/core/auth/auth.service.spec.ts @@ -18,8 +18,8 @@ import { AuthRequestServiceStub } from '../../shared/testing/auth-request-servic import { AuthRequestService } from './auth-request.service'; import { AuthStatus } from './models/auth-status.model'; import { AuthTokenInfo } from './models/auth-token-info.model'; -import { Eperson } from '../eperson/models/eperson.model'; -import { EpersonMock } from '../../shared/testing/eperson-mock'; +import { EPerson } from '../eperson/models/eperson.model'; +import { EPersonMock } from '../../shared/testing/eperson-mock'; import { AppState } from '../../app.reducer'; import { ClientCookieService } from '../../shared/services/client-cookie.service'; import { RemoteDataBuildService } from '../cache/builders/remote-data-build.service'; @@ -44,7 +44,7 @@ describe('AuthService test', () => { loaded: true, loading: false, authToken: token, - user: EpersonMock + user: EPersonMock }; const rdbService = getMockRemoteDataBuildService(); describe('', () => { @@ -82,7 +82,7 @@ describe('AuthService test', () => { }); it('should return the authenticated user object when user token is valid', () => { - authService.authenticatedUser(new AuthTokenInfo('test_token')).subscribe((user: Eperson) => { + authService.authenticatedUser(new AuthTokenInfo('test_token')).subscribe((user: EPerson) => { expect(user).toBeDefined(); }); }); @@ -188,7 +188,7 @@ describe('AuthService test', () => { loaded: true, loading: false, authToken: expiredToken, - user: EpersonMock + user: EPersonMock }; store .subscribe((state) => { diff --git a/src/app/core/auth/auth.service.ts b/src/app/core/auth/auth.service.ts index f19651e0dd..ea73ff9e1b 100644 --- a/src/app/core/auth/auth.service.ts +++ b/src/app/core/auth/auth.service.ts @@ -9,7 +9,7 @@ import { CookieAttributes } from 'js-cookie'; import { Observable } from 'rxjs/Observable'; import { map, switchMap, withLatestFrom } from 'rxjs/operators'; -import { Eperson } from '../eperson/models/eperson.model'; +import { EPerson } from '../eperson/models/eperson.model'; import { AuthRequestService } from './auth-request.service'; import { HttpOptions } from '../dspace-rest-v2/dspace-rest-v2.service'; @@ -28,7 +28,7 @@ import { ResetAuthenticationMessagesAction, SetRedirectUrlAction } from './auth. import { NativeWindowRef, NativeWindowService } from '../../shared/services/window.service'; import { Base64EncodeUrl } from '../../shared/utils/encode-decode.util'; import { RemoteDataBuildService } from '../cache/builders/remote-data-build.service'; -import { NormalizedEperson } from '../eperson/models/NormalizedEperson.model'; +import { NormalizedEPerson } from '../eperson/models/normalized-eperson.model'; export const LOGIN_ROUTE = '/login'; export const LOGOUT_ROUTE = '/logout'; @@ -107,7 +107,7 @@ export class AuthService { if (status.authenticated) { return status; } else { - throw(new Error('Invalid email or password')); + Observable.throw(new Error('Invalid email or password')); } }) @@ -125,7 +125,7 @@ export class AuthService { * Returns the authenticated user * @returns {User} */ - public authenticatedUser(token: AuthTokenInfo): Observable { + public authenticatedUser(token: AuthTokenInfo): Observable { // Determine if the user has an existing auth session on the server const options: HttpOptions = Object.create({}); let headers = new HttpHeaders(); @@ -136,10 +136,8 @@ export class AuthService { switchMap((status: AuthStatus) => { if (status.authenticated) { - // TODO this should be cleaned up, AuthStatus could be parsed by the RemoteDataService as a whole... - const person$ = this.rdbService.buildSingle(status.eperson.toString()); - // person$.subscribe(() => console.log('test')); + const person$ = this.rdbService.buildSingle(status.eperson.toString()); return person$.pipe(map((eperson) => eperson.payload)); } else { throw(new Error('Not authenticated')); @@ -202,7 +200,7 @@ export class AuthService { * Create a new user * @returns {User} */ - public create(user: Eperson): Observable { + public create(user: EPerson): Observable { // Normally you would do an HTTP request to POST the user // details and then return the new user object // but, let's just return the new user for this example. diff --git a/src/app/core/auth/models/auth-status.model.ts b/src/app/core/auth/models/auth-status.model.ts index bf90b82bf6..b8ccf9ed6d 100644 --- a/src/app/core/auth/models/auth-status.model.ts +++ b/src/app/core/auth/models/auth-status.model.ts @@ -1,6 +1,6 @@ import { AuthError } from './auth-error.model'; import { AuthTokenInfo } from './auth-token-info.model'; -import { Eperson } from '../../eperson/models/eperson.model'; +import { EPerson } from '../../eperson/models/eperson.model'; import { RemoteData } from '../../data/remote-data'; import { Observable } from 'rxjs/Observable'; @@ -14,7 +14,7 @@ export class AuthStatus { error?: AuthError; - eperson: Observable>; + eperson: Observable>; token?: AuthTokenInfo; diff --git a/src/app/core/auth/models/normalized-auth-status.model.ts b/src/app/core/auth/models/normalized-auth-status.model.ts index f7f6ab5a9e..b8dd2aa23e 100644 --- a/src/app/core/auth/models/normalized-auth-status.model.ts +++ b/src/app/core/auth/models/normalized-auth-status.model.ts @@ -26,7 +26,7 @@ export class NormalizedAuthStatus extends NormalizedObject { @autoserialize authenticated: boolean; - @relationship(ResourceType.Eperson, false) + @relationship(ResourceType.EPerson, false) @autoserialize eperson: string; } diff --git a/src/app/core/auth/server-auth.service.ts b/src/app/core/auth/server-auth.service.ts index 833df4b9d2..8d1bf1673c 100644 --- a/src/app/core/auth/server-auth.service.ts +++ b/src/app/core/auth/server-auth.service.ts @@ -1,4 +1,4 @@ -import {first, map} from 'rxjs/operators'; +import { first, map, switchMap } from 'rxjs/operators'; import { Injectable } from '@angular/core'; import { Observable } from 'rxjs/Observable'; @@ -9,7 +9,8 @@ import { isNotEmpty } from '../../shared/empty.util'; import { AuthService } from './auth.service'; import { AuthTokenInfo } from './models/auth-token-info.model'; import { CheckAuthenticationTokenAction } from './auth.actions'; -import { Eperson } from '../eperson/models/eperson.model'; +import { EPerson } from '../eperson/models/eperson.model'; +import { NormalizedEPerson } from '../eperson/models/normalized-eperson.model'; /** * The auth service. @@ -21,7 +22,7 @@ export class ServerAuthService extends AuthService { * Returns the authenticated user * @returns {User} */ - public authenticatedUser(token: AuthTokenInfo): Observable { + public authenticatedUser(token: AuthTokenInfo): Observable { // Determine if the user has an existing auth session on the server const options: HttpOptions = Object.create({}); let headers = new HttpHeaders(); @@ -34,13 +35,18 @@ export class ServerAuthService extends AuthService { options.headers = headers; return this.authRequestService.getRequest('status', options).pipe( - map((status: AuthStatus) => { + switchMap((status: AuthStatus) => { + if (status.authenticated) { - return status.eperson[0]; + + // TODO this should be cleaned up, AuthStatus could be parsed by the RemoteDataService as a whole... + const person$ = this.rdbService.buildSingle(status.eperson.toString()); + // person$.subscribe(() => console.log('test')); + return person$.pipe(map((eperson) => eperson.payload)); } else { - throw(new Error('Not authenticated')); + Observable.throw(new Error('Not authenticated')); } - })); + })) } /** diff --git a/src/app/core/cache/models/normalized-object-factory.ts b/src/app/core/cache/models/normalized-object-factory.ts index fc35dffca8..5c5ebf50aa 100644 --- a/src/app/core/cache/models/normalized-object-factory.ts +++ b/src/app/core/cache/models/normalized-object-factory.ts @@ -8,8 +8,8 @@ import { ResourceType } from '../../shared/resource-type'; import { NormalizedObject } from './normalized-object.model'; import { NormalizedBitstreamFormat } from './normalized-bitstream-format.model'; import { NormalizedResourcePolicy } from './normalized-resource-policy.model'; -import { NormalizedEperson } from '../../eperson/models/NormalizedEperson.model'; -import { NormalizedGroup } from '../../eperson/models/NormalizedGroup.model'; +import { NormalizedEPerson } from '../../eperson/models/normalized-eperson.model'; +import { NormalizedGroup } from '../../eperson/models/normalized-group.model'; export class NormalizedObjectFactory { public static getConstructor(type: ResourceType): GenericConstructor { @@ -35,8 +35,8 @@ export class NormalizedObjectFactory { case ResourceType.ResourcePolicy: { return NormalizedResourcePolicy } - case ResourceType.Eperson: { - return NormalizedEperson + case ResourceType.EPerson: { + return NormalizedEPerson } case ResourceType.Group: { return NormalizedGroup diff --git a/src/app/core/data/base-response-parsing.service.ts b/src/app/core/data/base-response-parsing.service.ts index 050b3c2da5..bdd18f8a61 100644 --- a/src/app/core/data/base-response-parsing.service.ts +++ b/src/app/core/data/base-response-parsing.service.ts @@ -7,6 +7,8 @@ import { GlobalConfig } from '../../../config/global-config.interface'; import { GenericConstructor } from '../shared/generic-constructor'; import { PaginatedList } from './paginated-list'; import { NormalizedObject } from '../cache/models/normalized-object.model'; +import { ResourceType } from '../shared/resource-type'; +import { RESTURLCombiner } from '../url-combiner/rest-url-combiner'; function isObjectLevel(halObj: any) { return isNotEmpty(halObj._links) && hasValue(halObj._links.self); @@ -34,6 +36,7 @@ export abstract class BaseResponseParsingService { } else if (Array.isArray(data)) { return this.processArray(data, requestHref); } else if (isObjectLevel(data)) { + data = this.fixBadEPersonRestResponse(data); const object = this.deserialize(data); if (isNotEmpty(data._embedded)) { Object @@ -53,6 +56,7 @@ export abstract class BaseResponseParsingService { } }); } + this.cache(object, requestHref); return object; } @@ -145,4 +149,22 @@ export abstract class BaseResponseParsingService { } return obj[keys[0]]; } + + /* TODO remove when REST response for epersons is fixed */ + private fixBadEPersonRestResponse(obj: any): any { + if (obj.type === ResourceType.EPerson) { + const groups = obj.groups; + const normGroups = []; + if (isNotEmpty(groups)) { + groups.forEach((group) => { + const parts = ['eperson', 'groups', group.uuid]; + const href = new RESTURLCombiner(this.EnvConfig, ...parts).toString(); + normGroups.push(href); + } + ) + } + return Object.assign({}, obj, { groups: normGroups }); + } + return obj; + } } diff --git a/src/app/core/eperson/models/eperson.model.ts b/src/app/core/eperson/models/eperson.model.ts index 373fb42792..45d26761b0 100644 --- a/src/app/core/eperson/models/eperson.model.ts +++ b/src/app/core/eperson/models/eperson.model.ts @@ -1,7 +1,7 @@ import { DSpaceObject } from '../../shared/dspace-object.model'; import { Group } from './group.model'; -export class Eperson extends DSpaceObject { +export class EPerson extends DSpaceObject { public handle: string; diff --git a/src/app/core/eperson/models/NormalizedEperson.model.ts b/src/app/core/eperson/models/normalized-eperson.model.ts similarity index 88% rename from src/app/core/eperson/models/NormalizedEperson.model.ts rename to src/app/core/eperson/models/normalized-eperson.model.ts index bdcd069eb8..9d0fa428e9 100644 --- a/src/app/core/eperson/models/NormalizedEperson.model.ts +++ b/src/app/core/eperson/models/normalized-eperson.model.ts @@ -2,13 +2,13 @@ import { autoserialize, inheritSerialization } from 'cerialize'; import { CacheableObject } from '../../cache/object-cache.reducer'; import { ListableObject } from '../../../shared/object-collection/shared/listable-object.model'; import { NormalizedDSpaceObject } from '../../cache/models/normalized-dspace-object.model'; -import { Eperson } from './eperson.model'; +import { EPerson } from './eperson.model'; import { mapsTo, relationship } from '../../cache/builders/build-decorators'; import { ResourceType } from '../../shared/resource-type'; -@mapsTo(Eperson) +@mapsTo(EPerson) @inheritSerialization(NormalizedDSpaceObject) -export class NormalizedEperson extends NormalizedDSpaceObject implements CacheableObject, ListableObject { +export class NormalizedEPerson extends NormalizedDSpaceObject implements CacheableObject, ListableObject { @autoserialize public handle: string; diff --git a/src/app/core/eperson/models/NormalizedGroup.model.ts b/src/app/core/eperson/models/normalized-group.model.ts similarity index 100% rename from src/app/core/eperson/models/NormalizedGroup.model.ts rename to src/app/core/eperson/models/normalized-group.model.ts diff --git a/src/app/core/shared/resource-type.ts b/src/app/core/shared/resource-type.ts index 71053f628b..e67f3339de 100644 --- a/src/app/core/shared/resource-type.ts +++ b/src/app/core/shared/resource-type.ts @@ -6,7 +6,7 @@ export enum ResourceType { Item = 'item', Collection = 'collection', Community = 'community', - Eperson = 'eperson', + EPerson = 'eperson', Group = 'group', ResourcePolicy = 'resourcePolicy' } diff --git a/src/app/shared/auth-nav-menu/auth-nav-menu.component.spec.ts b/src/app/shared/auth-nav-menu/auth-nav-menu.component.spec.ts index 8b9f7c8775..1c59c02346 100644 --- a/src/app/shared/auth-nav-menu/auth-nav-menu.component.spec.ts +++ b/src/app/shared/auth-nav-menu/auth-nav-menu.component.spec.ts @@ -5,7 +5,7 @@ import { By } from '@angular/platform-browser'; import { Store, StoreModule } from '@ngrx/store'; import { authReducer, AuthState } from '../../core/auth/auth.reducer'; -import { EpersonMock } from '../testing/eperson-mock'; +import { EPersonMock } from '../testing/eperson-mock'; import { TranslateModule } from '@ngx-translate/core'; import { AppState } from '../../app.reducer'; import { AuthNavMenuComponent } from './auth-nav-menu.component'; @@ -13,6 +13,7 @@ import { HostWindowServiceStub } from '../testing/host-window-service-stub'; import { HostWindowService } from '../host-window.service'; import { NoopAnimationsModule } from '@angular/platform-browser/animations'; import { AuthTokenInfo } from '../../core/auth/models/auth-token-info.model'; +import { EPerson } from '../../core/eperson/models/eperson.model'; describe('AuthNavMenuComponent', () => { @@ -31,7 +32,7 @@ describe('AuthNavMenuComponent', () => { loaded: true, loading: false, authToken: new AuthTokenInfo('test_token'), - user: EpersonMock + user: EPersonMock }; let routerState = { url: '/home' diff --git a/src/app/shared/auth-nav-menu/auth-nav-menu.component.ts b/src/app/shared/auth-nav-menu/auth-nav-menu.component.ts index 05dfd2d872..887729a7af 100644 --- a/src/app/shared/auth-nav-menu/auth-nav-menu.component.ts +++ b/src/app/shared/auth-nav-menu/auth-nav-menu.component.ts @@ -8,7 +8,7 @@ import { HostWindowService } from '../host-window.service'; import { AppState, routerStateSelector } from '../../app.reducer'; import { isNotUndefined } from '../empty.util'; import { getAuthenticatedUser, isAuthenticated, isAuthenticationLoading } from '../../core/auth/selectors'; -import { Eperson } from '../../core/eperson/models/eperson.model'; +import { EPerson } from '../../core/eperson/models/eperson.model'; import { LOGIN_ROUTE, LOGOUT_ROUTE } from '../../core/auth/auth.service'; import { RemoteData } from '../../core/data/remote-data'; @@ -35,7 +35,7 @@ export class AuthNavMenuComponent implements OnInit { public showAuth = Observable.of(false); - public user: Observable; + public user: Observable; constructor(private store: Store, private windowService: HostWindowService) { diff --git a/src/app/shared/log-in/log-in.component.spec.ts b/src/app/shared/log-in/log-in.component.spec.ts index dc4a0be1c6..dd2aea35d5 100644 --- a/src/app/shared/log-in/log-in.component.spec.ts +++ b/src/app/shared/log-in/log-in.component.spec.ts @@ -7,8 +7,8 @@ import { Store, StoreModule } from '@ngrx/store'; import { LogInComponent } from './log-in.component'; import { authReducer } from '../../core/auth/auth.reducer'; -import { EpersonMock } from '../testing/eperson-mock'; -import { Eperson } from '../../core/eperson/models/eperson.model'; +import { EPersonMock } from '../testing/eperson-mock'; +import { EPerson } from '../../core/eperson/models/eperson.model'; import { TranslateModule } from '@ngx-translate/core'; import { AuthService } from '../../core/auth/auth.service'; import { AuthServiceStub } from '../testing/auth-service-stub'; @@ -19,7 +19,7 @@ describe('LogInComponent', () => { let component: LogInComponent; let fixture: ComponentFixture; let page: Page; - let user: Eperson; + let user: EPerson; const authState = { authenticated: false, @@ -28,7 +28,7 @@ describe('LogInComponent', () => { }; beforeEach(() => { - user = EpersonMock; + user = EPersonMock; }); beforeEach(async(() => { diff --git a/src/app/shared/log-out/log-out.component.spec.ts b/src/app/shared/log-out/log-out.component.spec.ts index ad609f0aea..94780ead5a 100644 --- a/src/app/shared/log-out/log-out.component.spec.ts +++ b/src/app/shared/log-out/log-out.component.spec.ts @@ -5,8 +5,8 @@ import { FormsModule, ReactiveFormsModule } from '@angular/forms'; import { Store, StoreModule } from '@ngrx/store'; import { authReducer } from '../../core/auth/auth.reducer'; -import { EpersonMock } from '../testing/eperson-mock'; -import { Eperson } from '../../core/eperson/models/eperson.model'; +import { EPersonMock } from '../testing/eperson-mock'; +import { EPerson } from '../../core/eperson/models/eperson.model'; import { TranslateModule } from '@ngx-translate/core'; import { Router } from '@angular/router'; import { AppState } from '../../app.reducer'; @@ -18,7 +18,7 @@ describe('LogOutComponent', () => { let component: LogOutComponent; let fixture: ComponentFixture; let page: Page; - let user: Eperson; + let user: EPerson; const authState = { authenticated: false, @@ -28,7 +28,7 @@ describe('LogOutComponent', () => { const routerStub = new RouterStub(); beforeEach(() => { - user = EpersonMock; + user = EPersonMock; }); beforeEach(async(() => { diff --git a/src/app/shared/testing/auth-request-service-stub.ts b/src/app/shared/testing/auth-request-service-stub.ts index 4f525463c5..576b8c2ddf 100644 --- a/src/app/shared/testing/auth-request-service-stub.ts +++ b/src/app/shared/testing/auth-request-service-stub.ts @@ -2,13 +2,13 @@ import { Observable } from 'rxjs/Observable'; import { HttpOptions } from '../../core/dspace-rest-v2/dspace-rest-v2.service'; import { AuthStatus } from '../../core/auth/models/auth-status.model'; import { AuthTokenInfo } from '../../core/auth/models/auth-token-info.model'; -import { Eperson } from '../../core/eperson/models/eperson.model'; +import { EPerson } from '../../core/eperson/models/eperson.model'; import { isNotEmpty } from '../empty.util'; -import { EpersonMock } from './eperson-mock'; +import { EPersonMock } from './eperson-mock'; import { RemoteData } from '../../core/data/remote-data'; export class AuthRequestServiceStub { - protected mockUser: Eperson = EpersonMock; + protected mockUser: EPerson = EPersonMock; protected mockTokenInfo = new AuthTokenInfo('test_token'); public postToEndpoint(method: string, body: any, options?: HttpOptions): Observable { @@ -27,7 +27,7 @@ export class AuthRequestServiceStub { if (this.validateToken(token)) { authStatusStub.authenticated = true; authStatusStub.token = this.mockTokenInfo; - authStatusStub.eperson = Observable.of(new RemoteData(false, false, true, undefined, this.mockUser)); + authStatusStub.eperson = Observable.of(new RemoteData(false, false, true, undefined, this.mockUser)); } else { authStatusStub.authenticated = false; } @@ -46,7 +46,7 @@ export class AuthRequestServiceStub { if (this.validateToken(token)) { authStatusStub.authenticated = true; authStatusStub.token = this.mockTokenInfo; - authStatusStub.eperson = Observable.of(new RemoteData(false, false, true, undefined, this.mockUser)); + authStatusStub.eperson = Observable.of(new RemoteData(false, false, true, undefined, this.mockUser)); } else { authStatusStub.authenticated = false; } diff --git a/src/app/shared/testing/auth-service-stub.ts b/src/app/shared/testing/auth-service-stub.ts index 07157c8623..d6c20c9520 100644 --- a/src/app/shared/testing/auth-service-stub.ts +++ b/src/app/shared/testing/auth-service-stub.ts @@ -1,8 +1,8 @@ import { AuthStatus } from '../../core/auth/models/auth-status.model'; import { Observable } from 'rxjs/Observable'; import { AuthTokenInfo } from '../../core/auth/models/auth-token-info.model'; -import { EpersonMock } from './eperson-mock'; -import { Eperson } from '../../core/eperson/models/eperson.model'; +import { EPersonMock } from './eperson-mock'; +import { EPerson } from '../../core/eperson/models/eperson.model'; import { RemoteData } from '../../core/data/remote-data'; export class AuthServiceStub { @@ -20,7 +20,7 @@ export class AuthServiceStub { authStatus.okay = true; authStatus.authenticated = true; authStatus.token = this.token; - authStatus.eperson = Observable.of(new RemoteData(false, false, true, undefined, EpersonMock)); + authStatus.eperson = Observable.of(new RemoteData(false, false, true, undefined, EPersonMock)); return Observable.of(authStatus); } else { console.log('error'); @@ -28,9 +28,9 @@ export class AuthServiceStub { } } - public authenticatedUser(token: AuthTokenInfo): Observable { + public authenticatedUser(token: AuthTokenInfo): Observable { if (token.accessToken === 'token_test') { - return Observable.of(EpersonMock); + return Observable.of(EPersonMock); } else { throw(new Error('Message Error test')); } diff --git a/src/app/shared/testing/eperson-mock.ts b/src/app/shared/testing/eperson-mock.ts index 9cf938fcf2..f163a490b9 100644 --- a/src/app/shared/testing/eperson-mock.ts +++ b/src/app/shared/testing/eperson-mock.ts @@ -1,6 +1,6 @@ -import { Eperson } from '../../core/eperson/models/eperson.model'; +import { EPerson } from '../../core/eperson/models/eperson.model'; -export const EpersonMock: Eperson = Object.assign(new Eperson(),{ +export const EPersonMock: EPerson = Object.assign(new EPerson(),{ handle: null, groups: [], netid: 'test@test.com', From 17ad62c172dfffeba9d397fc374d4b4f95aa83e2 Mon Sep 17 00:00:00 2001 From: lotte Date: Fri, 14 Sep 2018 09:26:30 +0200 Subject: [PATCH 18/48] implementation of server synchronization --- config/environment.default.js | 7 +- src/app/core/cache/object-cache.actions.ts | 50 +++++++--- src/app/core/cache/object-cache.reducer.ts | 63 ++++++++++--- src/app/core/cache/object-cache.service.ts | 47 +++++++--- src/app/core/cache/response-cache.service.ts | 2 +- .../core/cache/server-sync-buffer.actions.ts | 83 +++++++++++++++++ .../core/cache/server-sync-buffer.effects.ts | 55 +++++++++++ .../core/cache/server-sync-buffer.reducer.ts | 92 +++++++++++++++++++ src/app/core/core.reducers.ts | 11 ++- src/config/auto-sync-config.interface.ts | 12 +++ src/config/cache-config.interface.ts | 4 +- 11 files changed, 378 insertions(+), 48 deletions(-) create mode 100644 src/app/core/cache/server-sync-buffer.actions.ts create mode 100644 src/app/core/cache/server-sync-buffer.effects.ts create mode 100644 src/app/core/cache/server-sync-buffer.reducer.ts create mode 100644 src/config/auto-sync-config.interface.ts diff --git a/config/environment.default.js b/config/environment.default.js index 22a70f3513..32edd1391d 100644 --- a/config/environment.default.js +++ b/config/environment.default.js @@ -20,7 +20,12 @@ module.exports = { // NOTE: how long should objects be cached for by default msToLive: 15 * 60 * 1000, // 15 minutes // msToLive: 1000, // 15 minutes - control: 'max-age=60' // revalidate browser + control: 'max-age=60', // revalidate browser + autoSync: { + defaultTime: 0, + maxBufferSize: 100, + timePerMethod: {'Patch': 30} //time in seconds + } }, // Form settings form: { diff --git a/src/app/core/cache/object-cache.actions.ts b/src/app/core/cache/object-cache.actions.ts index 957c0f7269..024a0e7061 100644 --- a/src/app/core/cache/object-cache.actions.ts +++ b/src/app/core/cache/object-cache.actions.ts @@ -11,7 +11,8 @@ export const ObjectCacheActionTypes = { ADD: type('dspace/core/cache/object/ADD'), REMOVE: type('dspace/core/cache/object/REMOVE'), RESET_TIMESTAMPS: type('dspace/core/cache/object/RESET_TIMESTAMPS'), - PATCH: type('dspace/core/cache/object/PATCH') + ADD_PATCH: type('dspace/core/cache/object/ADD_PATCH'), + APPLY_PATCH: type('dspace/core/cache/object/APPLY_PATCH') }; /* tslint:disable:max-classes-per-file */ @@ -56,11 +57,11 @@ export class RemoveFromObjectCacheAction implements Action { /** * Create a new RemoveFromObjectCacheAction * - * @param uuid - * the UUID of the object to remove + * @param href + * the unique href of the object to remove */ - constructor(uuid: string) { - this.payload = uuid; + constructor(href: string) { + this.payload = href; } } @@ -83,25 +84,43 @@ export class ResetObjectCacheTimestampsAction implements Action { } /** - * An ngrx action to add new operations to a specified cached objects + * An ngrx action to add new operations to a specified cached object */ -export class PatchObjectCacheAction implements Action { - type = ObjectCacheActionTypes.PATCH; +export class AddPatchObjectCacheAction implements Action { + type = ObjectCacheActionTypes.ADD_PATCH; payload: { - uuid: string, + href: string, operations: Operation[] }; /** - * Create a new PatchObjectCacheAction + * Create a new AddPatchObjectCacheAction * - * @param uuid - * the uuid of the object that should be updated + * @param href + * the unique href of the object that should be updated * @param operations * the list of operations to add */ - constructor(uuid: string, operations: Operation[]) { - this.payload = { uuid, operations }; + constructor(href: string, operations: Operation[]) { + this.payload = { href, operations }; + } +} + +/** + * An ngrx action to apply all existing operations to a specified cached object + */ +export class ApplyPatchObjectCacheAction implements Action { + type = ObjectCacheActionTypes.APPLY_PATCH; + payload: string; + + /** + * Create a new ApplyPatchObjectCacheAction + * + * @param href + * the unique href of the object that should be updated + */ + constructor(href: string) { + this.payload = href; } } @@ -114,4 +133,5 @@ export type ObjectCacheAction = AddToObjectCacheAction | RemoveFromObjectCacheAction | ResetObjectCacheTimestampsAction - | PatchObjectCacheAction; + | AddPatchObjectCacheAction + | ApplyPatchObjectCacheAction; diff --git a/src/app/core/cache/object-cache.reducer.ts b/src/app/core/cache/object-cache.reducer.ts index 5cc4b0551a..cd0a927c34 100644 --- a/src/app/core/cache/object-cache.reducer.ts +++ b/src/app/core/cache/object-cache.reducer.ts @@ -1,11 +1,15 @@ import { - ObjectCacheAction, ObjectCacheActionTypes, AddToObjectCacheAction, - RemoveFromObjectCacheAction, ResetObjectCacheTimestampsAction, PatchObjectCacheAction + ObjectCacheAction, + ObjectCacheActionTypes, + AddToObjectCacheAction, + RemoveFromObjectCacheAction, + ResetObjectCacheTimestampsAction, + AddPatchObjectCacheAction, ApplyPatchObjectCacheAction } from './object-cache.actions'; import { hasValue, isNotEmpty } from '../../shared/empty.util'; import { CacheEntry } from './cache-entry'; import { ResourceType } from '../shared/resource-type'; -import { Operation } from 'fast-json-patch'; +import { applyPatch, Operation } from 'fast-json-patch'; export enum DirtyType { Created = 'Created', @@ -13,7 +17,11 @@ export enum DirtyType { Deleted = 'Deleted' } -/** +export interface Patch { + uuid?: string; + operations: Operation[]; +} +/**conca * An interface to represent objects that can be cached * * A cacheable object should have a self link @@ -37,7 +45,8 @@ export class ObjectCacheEntry implements CacheEntry { timeAdded: number; msToLive: number; requestHref: string; - operations: Operation[]; + patches: Patch[] = []; + isDirty: boolean; } /** @@ -78,9 +87,14 @@ export function objectCacheReducer(state = initialState, action: ObjectCacheActi return resetObjectCacheTimestamps(state, action as ResetObjectCacheTimestampsAction) } - case ObjectCacheActionTypes.PATCH: { - return patchObjectCache(state, action as PatchObjectCacheAction); + case ObjectCacheActionTypes.ADD_PATCH: { + return addPatchObjectCache(state, action as AddPatchObjectCacheAction); } + + case ObjectCacheActionTypes.APPLY_PATCH: { + return applyPatchObjectCache(state, action as ApplyPatchObjectCacheAction); + } + default: { return state; } @@ -104,7 +118,7 @@ function addToObjectCache(state: ObjectCacheState, action: AddToObjectCacheActio timeAdded: action.payload.timeAdded, msToLive: action.payload.msToLive, requestHref: action.payload.requestHref, - operations: [] + isDirty: false } }); } @@ -156,16 +170,41 @@ function resetObjectCacheTimestamps(state: ObjectCacheState, action: ResetObject * @param state * the current state * @param action - * a PatchObjectCacheAction + * an AddPatchObjectCacheAction * @return ObjectCacheState * the new state, with the new operations added to the state of the specified ObjectCacheEntry */ -function patchObjectCache(state: ObjectCacheState, action: PatchObjectCacheAction): ObjectCacheState { - const uuid = action.payload.uuid; +function addPatchObjectCache(state: ObjectCacheState, action: AddPatchObjectCacheAction): ObjectCacheState { + const uuid = action.payload.href; const operations = action.payload.operations; const newState = Object.assign({}, state); if (hasValue(newState[uuid])) { - newState[uuid].operations = state[uuid].operations.concat(operations); + const patches = newState[uuid].patches; + newState[uuid].patches = [...patches, {operations} as Patch]; + newState[uuid].isDirty = true; + } + return newState; +} + +/** + * Apply the list of patch operations to a cached object + * + * @param state + * the current state + * @param action + * an ApplyPatchObjectCacheAction + * @return ObjectCacheState + * the new state, with the new operations applied to the state of the specified ObjectCacheEntry + */ +function applyPatchObjectCache(state: ObjectCacheState, action: ApplyPatchObjectCacheAction): ObjectCacheState { + const uuid = action.payload; + const newState = Object.assign({}, state); + if (hasValue(newState[uuid])) { + // flatten two dimensional array + const flatPatch: Operation[] = [].concat(...newState[uuid].patches); + const newData = applyPatch( newState[uuid].data, flatPatch); + newState[uuid].data = newData.newDocument; + newState[uuid].patches = []; } return newState; } diff --git a/src/app/core/cache/object-cache.service.ts b/src/app/core/cache/object-cache.service.ts index d9b3077d55..d7bf59500c 100644 --- a/src/app/core/cache/object-cache.service.ts +++ b/src/app/core/cache/object-cache.service.ts @@ -7,8 +7,8 @@ import { IndexName } from '../index/index.reducer'; import { CacheableObject, ObjectCacheEntry } from './object-cache.reducer'; import { - AddToObjectCacheAction, - PatchObjectCacheAction, + AddPatchObjectCacheAction, + AddToObjectCacheAction, ApplyPatchObjectCacheAction, RemoveFromObjectCacheAction } from './object-cache.actions'; import { hasNoValue, isNotEmpty } from '../../shared/empty.util'; @@ -18,13 +18,15 @@ import { pathSelector } from '../shared/selectors'; import { NormalizedObjectFactory } from './models/normalized-object-factory'; import { NormalizedObject } from './models/normalized-object.model'; import { applyPatch, Operation } from 'fast-json-patch'; +import { RestRequestMethod } from '../data/request.models'; +import { AddToSSBAction } from './server-sync-buffer.actions'; function selfLinkFromUuidSelector(uuid: string): MemoizedSelector { return pathSelector(coreSelector, 'index', IndexName.OBJECT, uuid); } function entryFromSelfLinkSelector(selfLink: string): MemoizedSelector { - return pathSelector(coreSelector, 'data/object', selfLink); + return pathSelector(coreSelector, 'cache/object', selfLink); } /** @@ -52,10 +54,10 @@ export class ObjectCacheService { } /** - * Remove the object with the supplied UUID from the cache + * Remove the object with the supplied href from the cache * - * @param uuid - * The UUID of the object to be removed + * @param href + * The unique href of the object to be removed */ remove(uuid: string): void { this.store.dispatch(new RemoveFromObjectCacheAction(uuid)); @@ -87,13 +89,17 @@ export class ObjectCacheService { getBySelfLink(selfLink: string): Observable { return this.getEntry(selfLink).pipe( + map((entry: ObjectCacheEntry) => { + // flatten two dimensional array + const flatPatch: Operation[] = [].concat(...entry.patches); + const patchedData = applyPatch(entry.data, flatPatch).newDocument; + return Object.assign({}, entry, { data: patchedData }); + } + ), map((entry: ObjectCacheEntry) => { const type: GenericConstructor = NormalizedObjectFactory.getConstructor(entry.data.type); return Object.assign(new type(), entry.data) as T - }), - // map((entry: ObjectCacheEntry) => - // applyPatch(entry.data, entry.operations).newDocument - // ) + }) ); } @@ -205,14 +211,16 @@ export class ObjectCacheService { } /** - * Add operations to a the existing list of operations for an ObjectCacheEntry + * Add operations to the existing list of operations for an ObjectCacheEntry + * Makes sure the ServerSyncBuffer for this ObjectCacheEntry is updated * @param {string} uuid * the uuid of the ObjectCacheEntry * @param {Operation[]} patch * list of operations to perform */ - private addOperations(uuid: string, patch: Operation[]) { - this.store.dispatch(new PatchObjectCacheAction(uuid, patch)); + private addPatch(uuid: string, patch: Operation[]) { + this.store.dispatch(new AddPatchObjectCacheAction(uuid, patch)); + this.store.dispatch(new AddToSSBAction(uuid, RestRequestMethod.Patch)); } /** @@ -224,6 +232,17 @@ export class ObjectCacheService { * false if the entry is there are no operations left in the ObjectCacheEntry, true otherwise */ private isDirty(entry: ObjectCacheEntry): boolean { - return isNotEmpty(entry.operations); + return isNotEmpty(entry.patches); } + + /** + * Apply the existing operations on an ObjectCacheEntry in the store + * NB: this does not make any server side changes + * @param {string} uuid + * the uuid of the ObjectCacheEntry + */ + private applyPatchesToCachedObject(uuid: string) { + this.store.dispatch(new ApplyPatchObjectCacheAction(uuid)); + } + } diff --git a/src/app/core/cache/response-cache.service.ts b/src/app/core/cache/response-cache.service.ts index 21430d451c..973d3620ff 100644 --- a/src/app/core/cache/response-cache.service.ts +++ b/src/app/core/cache/response-cache.service.ts @@ -12,7 +12,7 @@ import { coreSelector, CoreState } from '../core.reducers'; import { pathSelector } from '../shared/selectors'; function entryFromKeySelector(key: string): MemoizedSelector { - return pathSelector(coreSelector, 'data/response', key); + return pathSelector(coreSelector, 'cache/response', key); } /** diff --git a/src/app/core/cache/server-sync-buffer.actions.ts b/src/app/core/cache/server-sync-buffer.actions.ts new file mode 100644 index 0000000000..9189af4471 --- /dev/null +++ b/src/app/core/cache/server-sync-buffer.actions.ts @@ -0,0 +1,83 @@ +import { Action } from '@ngrx/store'; + +import { type } from '../../shared/ngrx/type'; +import { CacheableObject } from './object-cache.reducer'; +import { Operation } from 'fast-json-patch'; +import { RestRequest, RestRequestMethod } from '../data/request.models'; + +/** + * The list of ServerSyncBufferAction type definitions + */ +export const ServerSyncBufferActionTypes = { + ADD: type('dspace/core/cache/syncbuffer/ADD'), + COMMIT: type('dspace/core/cache/syncbuffer/COMMIT'), + EMPTY: type('dspace/core/cache/syncbuffer/EMPTY'), +}; + +/* tslint:disable:max-classes-per-file */ + +/** + * An ngrx action to add a new cached object to the server's sync buffer + */ +export class AddToSSBAction implements Action { + type = ServerSyncBufferActionTypes.ADD; + payload: { + href: string, + method: RestRequestMethod + }; + + /** + * Create a new AddToSSBAction + * + * @param href + * the unique href of the cached object entry that should be updated + */ + constructor(href: string, method: RestRequestMethod) { + this.payload = { href, method }; + } +} + +/** + * An ngrx action to commit everything (for a certain method, when specified) in the ServerSyncBuffer to the server + */ +export class CommitSSBAction implements Action { + type = ServerSyncBufferActionTypes.COMMIT; + payload?: RestRequestMethod; + + /** + * Create a new CommitSSBAction + * + * @param method + * an optional method for which the ServerSyncBuffer should send its entries to the server + */ + constructor(method?: RestRequestMethod) { + this.payload = method; + } +} +/** + * An ngrx action to remove everything (for a certain method, when specified) from the ServerSyncBuffer to the server + */ +export class EmptySSBAction implements Action { + type = ServerSyncBufferActionTypes.EMPTY; + payload?: RestRequestMethod; + + /** + * Create a new EmptySSBAction + * + * @param method + * an optional method for which the ServerSyncBuffer should remove its entries + */ + constructor(method?: RestRequestMethod) { + this.payload = method; + } +} + +/* tslint:enable:max-classes-per-file */ + +/** + * A type to encompass all ServerSyncBufferActions + */ +export type ServerSyncBufferAction + = AddToSSBAction + | CommitSSBAction + | EmptySSBAction diff --git a/src/app/core/cache/server-sync-buffer.effects.ts b/src/app/core/cache/server-sync-buffer.effects.ts new file mode 100644 index 0000000000..517c9837c2 --- /dev/null +++ b/src/app/core/cache/server-sync-buffer.effects.ts @@ -0,0 +1,55 @@ +import { delay, exhaustMap, filter, first, map } from 'rxjs/operators'; +import { Inject, Injectable } from '@angular/core'; +import { Actions, Effect, ofType } from '@ngrx/effects'; +import { + AddToSSBAction, + CommitSSBAction, + EmptySSBAction, + ServerSyncBufferActionTypes +} from './server-sync-buffer.actions'; +import { GLOBAL_CONFIG } from '../../../config'; +import { GlobalConfig } from '../../../config/global-config.interface'; +import { CoreState } from '../core.reducers'; +import { select, Store } from '@ngrx/store'; +import { ServerSyncBufferEntry, ServerSyncBufferState } from './server-sync-buffer.reducer'; +import { of as observableOf } from 'rxjs'; +import { RequestService } from '../data/request.service'; +import { PutRequest } from '../data/request.models'; + +@Injectable() +export class ObjectCacheEffects { + @Effect() setTimeoutForServerSync = this.actions$ + .pipe(ofType(ServerSyncBufferActionTypes.ADD), + exhaustMap((action: AddToSSBAction) => { + const autoSyncConfig = this.EnvConfig.cache.autoSync; + const timeoutInSeconds = autoSyncConfig.timePerMethod[action.type] || autoSyncConfig.defaultTime; + return observableOf(new CommitSSBAction(action.payload.method)).pipe(delay( timeoutInSeconds * 1000)) + }) + ); + + @Effect() commitServerSyncBuffer = this.actions$ + .pipe(ofType(ServerSyncBufferActionTypes.COMMIT), + map((action: CommitSSBAction) => { + this.store.pipe( + select(serverSyncBufferSelector), + first() + ).subscribe((bufferState: ServerSyncBufferState) => { + bufferState.buffer + .filter((entry: ServerSyncBufferEntry) => entry.method === action.payload) + .forEach((entry: ServerSyncBufferEntry) => { + this.requestService.configure(new PutRequest(this.requestService.generateRequestId(), ,)) + }) + }); + return new EmptySSBAction(action.payload); + }) + ); + + constructor(private actions$: Actions, + private store: Store, + private requestService: RequestService, + @Inject(GLOBAL_CONFIG) private EnvConfig: GlobalConfig) { + + } +} + +export const serverSyncBufferSelector = (state: CoreState) => state['cache/syncbuffer']; diff --git a/src/app/core/cache/server-sync-buffer.reducer.ts b/src/app/core/cache/server-sync-buffer.reducer.ts new file mode 100644 index 0000000000..1fabe5a50a --- /dev/null +++ b/src/app/core/cache/server-sync-buffer.reducer.ts @@ -0,0 +1,92 @@ +import { RestRequestMethod } from '../data/request.models'; +import { hasNoValue, hasValue } from '../../shared/empty.util'; +import { + AddToSSBAction, + EmptySSBAction, + ServerSyncBufferAction, + ServerSyncBufferActionTypes +} from './server-sync-buffer.actions'; + +/** + * An entry in the ServerSyncBufferState + * href: unique href of an ObjectCacheEntry + * method: RestRequestMethod type + */ +export class ServerSyncBufferEntry { + href: string; + method: RestRequestMethod; +} + +/** + * The ServerSyncBuffer State + * + * Consists list of ServerSyncBufferState + */ +export interface ServerSyncBufferState { + buffer: ServerSyncBufferEntry[]; +} + +// Object.create(null) ensures the object has no default js properties (e.g. `__proto__`) +const initialState: ServerSyncBufferState = { buffer: [] }; + +/** + * The ServerSyncBuffer Reducer + * + * @param state + * the current state + * @param action + * the action to perform on the state + * @return ServerSyncBufferState + * the new state + */ +export function serverSyncBufferReducer(state = initialState, action: ServerSyncBufferAction): ServerSyncBufferState { + switch (action.type) { + + case ServerSyncBufferActionTypes.ADD: { + return addToServerSyncQueue(state, action as AddToSSBAction) + } + + case ServerSyncBufferActionTypes.EMPTY: { + return emptyServerSyncQueue(state, action as EmptySSBAction); + } + default: { + return state; + } + } +} + +/** + * Add a new entry to the buffer with a specified method + * + * @param state + * the current state + * @param action + * an AddToSSBAction + * @return ServerSyncBufferState + * the new state, with a new entry added to the buffer + */ +function addToServerSyncQueue(state: ServerSyncBufferState, action: AddToSSBAction): ServerSyncBufferState { + const actionEntry = action.payload as ServerSyncBufferEntry; + if (hasNoValue(state.buffer.find((entry) => entry.href === actionEntry.href && entry.method === actionEntry.method))) { + return Object.assign({}, state, { buffer: state.buffer.concat(actionEntry) }); + } +} + +/** + * Remove all ServerSyncBuffers entry from the buffer with a specified method + * If no method is specified, empty the whole buffer + * + * @param state + * the current state + * @param action + * an AddToSSBAction + * @return ServerSyncBufferState + * the new state, with a new entry added to the buffer + */ +function emptyServerSyncQueue(state: ServerSyncBufferState, action: EmptySSBAction): ServerSyncBufferState { + let newBuffer = []; + if (hasValue(action.payload)) { + newBuffer = state.buffer.filter((entry) => entry.method !== action.payload); + } + return Object.assign({}, state, { buffer: newBuffer }); +} diff --git a/src/app/core/core.reducers.ts b/src/app/core/core.reducers.ts index c764a2acff..6905eb1300 100644 --- a/src/app/core/core.reducers.ts +++ b/src/app/core/core.reducers.ts @@ -5,18 +5,21 @@ import { objectCacheReducer, ObjectCacheState } from './cache/object-cache.reduc import { indexReducer, IndexState } from './index/index.reducer'; import { requestReducer, RequestState } from './data/request.reducer'; import { authReducer, AuthState } from './auth/auth.reducer'; +import { serverSyncBufferReducer, ServerSyncBufferState } from './cache/server-sync-buffer.reducer'; export interface CoreState { - 'data/object': ObjectCacheState, - 'data/response': ResponseCacheState, + 'cache/object': ObjectCacheState, + 'cache/response': ResponseCacheState, + 'cache/syncbuffer': ServerSyncBufferState, 'data/request': RequestState, 'index': IndexState, 'auth': AuthState, } export const coreReducers: ActionReducerMap = { - 'data/object': objectCacheReducer, - 'data/response': responseCacheReducer, + 'cache/object': objectCacheReducer, + 'cache/response': responseCacheReducer, + 'cache/syncbuffer': serverSyncBufferReducer, 'data/request': requestReducer, 'index': indexReducer, 'auth': authReducer diff --git a/src/config/auto-sync-config.interface.ts b/src/config/auto-sync-config.interface.ts new file mode 100644 index 0000000000..4ad74005bf --- /dev/null +++ b/src/config/auto-sync-config.interface.ts @@ -0,0 +1,12 @@ +import { RestRequestMethod } from '../app/core/data/request.models'; + +/* enum indices */ +type TimePerMethod = { + [method in RestRequestMethod]: number; +}; + +export interface AutoSyncConfig { + defaultTime: number; + timePerMethod: TimePerMethod; + maxBufferSize: number; +}; diff --git a/src/config/cache-config.interface.ts b/src/config/cache-config.interface.ts index f8a2c88640..3e9334e300 100644 --- a/src/config/cache-config.interface.ts +++ b/src/config/cache-config.interface.ts @@ -1,6 +1,8 @@ import { Config } from './config.interface'; +import { AutoSyncConfig } from './auto-sync-config.interface'; export interface CacheConfig extends Config { msToLive: number, - control: string + control: string, + autoSync: AutoSyncConfig } From 2b1d4cd12a6c16e10ddd06d6e269bfd31a21b45c Mon Sep 17 00:00:00 2001 From: lotte Date: Fri, 14 Sep 2018 11:42:55 +0200 Subject: [PATCH 19/48] Fixed logout issue --- src/app/core/auth/auth.interceptor.ts | 2 +- src/app/core/auth/auth.service.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/app/core/auth/auth.interceptor.ts b/src/app/core/auth/auth.interceptor.ts index 651e2fd096..f38abb90bc 100644 --- a/src/app/core/auth/auth.interceptor.ts +++ b/src/app/core/auth/auth.interceptor.ts @@ -35,7 +35,7 @@ export class AuthInterceptor implements HttpInterceptor { } private isSuccess(response: HttpResponseBase): boolean { - return response.status === 200; + return (response.status === 200 || response.status === 204); } private isAuthRequest(http: HttpRequest | HttpResponseBase): boolean { diff --git a/src/app/core/auth/auth.service.ts b/src/app/core/auth/auth.service.ts index ea73ff9e1b..f8fc863ee9 100644 --- a/src/app/core/auth/auth.service.ts +++ b/src/app/core/auth/auth.service.ts @@ -140,7 +140,7 @@ export class AuthService { const person$ = this.rdbService.buildSingle(status.eperson.toString()); return person$.pipe(map((eperson) => eperson.payload)); } else { - throw(new Error('Not authenticated')); + Observable.throw(new Error('Not authenticated')); } })) } From 97669d0c346b11055ae322069960d65364e989b2 Mon Sep 17 00:00:00 2001 From: lotte Date: Mon, 17 Sep 2018 10:20:12 +0200 Subject: [PATCH 20/48] upgrade ngrx to fix store devtools bug --- package.json | 6 +++--- yarn.lock | 32 ++++++++++++++++---------------- 2 files changed, 19 insertions(+), 19 deletions(-) diff --git a/package.json b/package.json index 0936b27ea4..e1ff94b428 100644 --- a/package.json +++ b/package.json @@ -90,8 +90,8 @@ "@ngx-translate/http-loader": "2.0.1", "@nicky-lenaers/ngx-scroll-to": "^0.6.0", "angular-idle-preload": "2.0.4", - "angular2-moment": "^1.9.0", "angular-sortablejs": "^2.5.0", + "angular2-moment": "^1.9.0", "angular2-text-mask": "8.0.4", "angulartics2": "^5.2.0", "body-parser": "1.18.2", @@ -99,7 +99,7 @@ "cerialize": "0.1.18", "compression": "1.7.1", "cookie-parser": "1.4.3", - "core-js": "2.5.3", + "core-js": "^2.5.7", "express": "4.16.2", "express-session": "1.15.6", "font-awesome": "4.7.0", @@ -112,8 +112,8 @@ "methods": "1.1.2", "moment": "^2.22.1", "morgan": "1.9.0", - "ng2-nouislider": "^1.7.11", "ng2-file-upload": "1.2.1", + "ng2-nouislider": "^1.7.11", "ngx-infinite-scroll": "0.8.2", "ngx-pagination": "3.0.3", "nouislider": "^11.0.0", diff --git a/yarn.lock b/yarn.lock index 344093d446..5caaac6090 100644 --- a/yarn.lock +++ b/yarn.lock @@ -90,20 +90,20 @@ resolved "https://registry.yarnpkg.com/@ng-dynamic-forms/ui-ng-bootstrap/-/ui-ng-bootstrap-5.4.7.tgz#66d037a226da96fe84c4dbac98e4dba859c551f8" "@ngrx/effects@^5.1.0": - version "5.1.0" - resolved "https://registry.yarnpkg.com/@ngrx/effects/-/effects-5.1.0.tgz#cef84576b2d0333f19188aedfe156fd301bff70a" + version "5.2.0" + resolved "https://registry.yarnpkg.com/@ngrx/effects/-/effects-5.2.0.tgz#aa762b69cb6fd4644d724a1cecd265caa42baf09" "@ngrx/router-store@^5.0.1": - version "5.0.1" - resolved "https://registry.yarnpkg.com/@ngrx/router-store/-/router-store-5.0.1.tgz#db872327bb958a2ebf296734c97de68672ec628a" + version "5.2.0" + resolved "https://registry.yarnpkg.com/@ngrx/router-store/-/router-store-5.2.0.tgz#bf4b174ce19a36eba8211fc1ddeaf1e35ae74368" "@ngrx/store-devtools@^5.1.0": - version "5.1.0" - resolved "https://registry.yarnpkg.com/@ngrx/store-devtools/-/store-devtools-5.1.0.tgz#7df8a6da652cc792000ad058ca4072a32e3629b1" + version "5.2.0" + resolved "https://registry.yarnpkg.com/@ngrx/store-devtools/-/store-devtools-5.2.0.tgz#2fff916a9aa349375826772b359dbb64b9e5d622" "@ngrx/store@^5.1.0": - version "5.1.0" - resolved "https://registry.yarnpkg.com/@ngrx/store/-/store-5.1.0.tgz#d957131e62041deede043524fd300db9fa835d68" + version "5.2.0" + resolved "https://registry.yarnpkg.com/@ngrx/store/-/store-5.2.0.tgz#627ed74c9cd95462930485d912a557117b23903e" "@ngtools/webpack@^1.10.0": version "1.10.0" @@ -437,16 +437,16 @@ angular-idle-preload@2.0.4: version "2.0.4" resolved "https://registry.yarnpkg.com/angular-idle-preload/-/angular-idle-preload-2.0.4.tgz#7b177c0f52918c090e5c345480b922297cd59a0d" +angular-sortablejs@^2.5.0: + version "2.5.2" + resolved "https://registry.yarnpkg.com/angular-sortablejs/-/angular-sortablejs-2.5.2.tgz#ffd651e47cc93a191db4c023f617db3789fd9af5" + angular2-moment@^1.9.0: version "1.9.0" resolved "https://registry.yarnpkg.com/angular2-moment/-/angular2-moment-1.9.0.tgz#d198a4d9bc825f61de19106ac7ea07a78569f5a1" dependencies: moment "^2.19.3" -angular-sortablejs@^2.5.0: - version "2.5.2" - resolved "https://registry.yarnpkg.com/angular-sortablejs/-/angular-sortablejs-2.5.2.tgz#ffd651e47cc93a191db4c023f617db3789fd9af5" - angular2-template-loader@0.6.2: version "0.6.2" resolved "https://registry.yarnpkg.com/angular2-template-loader/-/angular2-template-loader-0.6.2.tgz#c0d44e90fff0fac95e8b23f043acda7fd1c51d7c" @@ -1963,14 +1963,14 @@ copy-webpack-plugin@^4.4.1: p-limit "^1.0.0" serialize-javascript "^1.4.0" -core-js@2.5.3: - version "2.5.3" - resolved "https://registry.yarnpkg.com/core-js/-/core-js-2.5.3.tgz#8acc38345824f16d8365b7c9b4259168e8ed603e" - core-js@^2.2.0, core-js@^2.4.0: version "2.5.1" resolved "https://registry.yarnpkg.com/core-js/-/core-js-2.5.1.tgz#ae6874dc66937789b80754ff5428df66819ca50b" +core-js@^2.5.7: + version "2.5.7" + resolved "https://registry.yarnpkg.com/core-js/-/core-js-2.5.7.tgz#f972608ff0cead68b841a16a932d0b183791814e" + core-js@~2.3.0: version "2.3.0" resolved "https://registry.yarnpkg.com/core-js/-/core-js-2.3.0.tgz#fab83fbb0b2d8dc85fa636c4b9d34c75420c6d65" From e96eeeaa835fd9197d6d88d8543e9856fd3cb70b Mon Sep 17 00:00:00 2001 From: lotte Date: Tue, 18 Sep 2018 16:29:55 +0200 Subject: [PATCH 21/48] fixed redirect after login --- .../search-filters.component.ts | 1 - src/app/core/auth/auth.service.ts | 16 +++++++------ src/app/core/auth/server-auth.service.ts | 4 +++- src/app/header/header.component.spec.ts | 6 +++-- .../auth-nav-menu.component.spec.ts | 4 +++- .../auth-nav-menu/auth-nav-menu.component.ts | 23 +++++++++++++++---- 6 files changed, 37 insertions(+), 17 deletions(-) diff --git a/src/app/+search-page/search-filters/search-filters.component.ts b/src/app/+search-page/search-filters/search-filters.component.ts index f4b63c332f..1da4e5860d 100644 --- a/src/app/+search-page/search-filters/search-filters.component.ts +++ b/src/app/+search-page/search-filters/search-filters.component.ts @@ -56,7 +56,6 @@ export class SearchFiltersComponent { * @returns {Observable} Emits true whenever a given filter config should be shown */ isActive(filter: SearchFilterConfig): Observable { - // console.log(filter.name); return this.filterService.getSelectedValuesForFilter(filter) .flatMap((isActive) => { if (isNotEmpty(isActive)) { diff --git a/src/app/core/auth/auth.service.ts b/src/app/core/auth/auth.service.ts index f8fc863ee9..f69dd2b58f 100644 --- a/src/app/core/auth/auth.service.ts +++ b/src/app/core/auth/auth.service.ts @@ -54,7 +54,7 @@ export class AuthService { protected storage: CookieService, protected store: Store, protected rdbService: RemoteDataBuildService - ) { + ) { this.store.select(isAuthenticated) .startWith(false) .subscribe((authenticated: boolean) => this._authenticated = authenticated); @@ -107,7 +107,7 @@ export class AuthService { if (status.authenticated) { return status; } else { - Observable.throw(new Error('Invalid email or password')); + throw(new Error('Invalid email or password')); } }) @@ -140,7 +140,7 @@ export class AuthService { const person$ = this.rdbService.buildSingle(status.eperson.toString()); return person$.pipe(map((eperson) => eperson.payload)); } else { - Observable.throw(new Error('Not authenticated')); + throw(new Error('Not authenticated')); } })) } @@ -216,7 +216,7 @@ export class AuthService { // Send a request that sign end the session let headers = new HttpHeaders(); headers = headers.append('Content-Type', 'application/x-www-form-urlencoded'); - const options: HttpOptions = Object.create({headers, responseType: 'text'}); + const options: HttpOptions = Object.create({ headers, responseType: 'text' }); return this.authRequestService.getRequest('logout', options) .map((status: AuthStatus) => { if (!status.authenticated) { @@ -225,7 +225,6 @@ export class AuthService { throw(new Error('auth.errors.invalid-user')); } }) - } /** @@ -246,6 +245,7 @@ export class AuthService { public getToken(): AuthTokenInfo { let token: AuthTokenInfo; this.store.select(getAuthenticationToken) + .first() .subscribe((authTokenInfo: AuthTokenInfo) => { // Retrieve authentication token info and check if is valid token = authTokenInfo || null; @@ -291,7 +291,7 @@ export class AuthService { // Set the cookie expire date const expires = new Date(expireDate); - const options: CookieAttributes = {expires: expires}; + const options: CookieAttributes = { expires: expires }; // Save cookie with the token return this.storage.set(TOKENITEM, token, options); @@ -349,8 +349,10 @@ export class AuthService { this.router.navigated = false; const url = decodeURIComponent(redirectUrl); this.router.navigateByUrl(url); + this._window.nativeWindow.location.href = url; } else { this.router.navigate(['/']); + this._window.nativeWindow.location.href = '/'; } }) @@ -386,7 +388,7 @@ export class AuthService { // Set the cookie expire date const expires = new Date(expireDate); - const options: CookieAttributes = {expires: expires}; + const options: CookieAttributes = { expires: expires }; this.storage.set(REDIRECT_COOKIE, url, options); this.store.dispatch(new SetRedirectUrlAction(isNotUndefined(url) ? url : '')); } diff --git a/src/app/core/auth/server-auth.service.ts b/src/app/core/auth/server-auth.service.ts index 8d1bf1673c..18eba2e92d 100644 --- a/src/app/core/auth/server-auth.service.ts +++ b/src/app/core/auth/server-auth.service.ts @@ -44,7 +44,7 @@ export class ServerAuthService extends AuthService { // person$.subscribe(() => console.log('test')); return person$.pipe(map((eperson) => eperson.payload)); } else { - Observable.throw(new Error('Not authenticated')); + throw(new Error('Not authenticated')); } })) } @@ -71,8 +71,10 @@ export class ServerAuthService extends AuthService { this.router.navigated = false; const url = decodeURIComponent(redirectUrl); this.router.navigateByUrl(url); + this._window.nativeWindow.location.href = url; } else { this.router.navigate(['/']); + this._window.nativeWindow.location.href = '/'; } }) diff --git a/src/app/header/header.component.spec.ts b/src/app/header/header.component.spec.ts index 87fa2995d6..9d0dd04e40 100644 --- a/src/app/header/header.component.spec.ts +++ b/src/app/header/header.component.spec.ts @@ -19,6 +19,7 @@ import { HostWindowServiceStub } from '../shared/testing/host-window-service-stu import { RouterStub } from '../shared/testing/router-stub'; import { Router } from '@angular/router'; import { NoopAnimationsModule } from '@angular/platform-browser/animations'; +import { NO_ERRORS_SCHEMA } from '@angular/core'; let comp: HeaderComponent; let fixture: ComponentFixture; @@ -35,11 +36,12 @@ describe('HeaderComponent', () => { NgbCollapseModule.forRoot(), NoopAnimationsModule, ReactiveFormsModule], - declarations: [HeaderComponent, AuthNavMenuComponent, LoadingComponent, LogInComponent, LogOutComponent], + declarations: [HeaderComponent], providers: [ { provide: HostWindowService, useValue: new HostWindowServiceStub(800) }, { provide: Router, useClass: RouterStub }, - ] + ], + schemas: [NO_ERRORS_SCHEMA] }) .compileComponents(); // compile template and css })); diff --git a/src/app/shared/auth-nav-menu/auth-nav-menu.component.spec.ts b/src/app/shared/auth-nav-menu/auth-nav-menu.component.spec.ts index 1c59c02346..a036590ed5 100644 --- a/src/app/shared/auth-nav-menu/auth-nav-menu.component.spec.ts +++ b/src/app/shared/auth-nav-menu/auth-nav-menu.component.spec.ts @@ -13,7 +13,7 @@ import { HostWindowServiceStub } from '../testing/host-window-service-stub'; import { HostWindowService } from '../host-window.service'; import { NoopAnimationsModule } from '@angular/platform-browser/animations'; import { AuthTokenInfo } from '../../core/auth/models/auth-token-info.model'; -import { EPerson } from '../../core/eperson/models/eperson.model'; +import { AuthService } from '../../core/auth/auth.service'; describe('AuthNavMenuComponent', () => { @@ -54,6 +54,7 @@ describe('AuthNavMenuComponent', () => { ], providers: [ {provide: HostWindowService, useValue: window}, + {provide: AuthService, useValue: {setRedirectUrl: () => {}}} ], schemas: [ CUSTOM_ELEMENTS_SCHEMA @@ -223,6 +224,7 @@ describe('AuthNavMenuComponent', () => { ], providers: [ {provide: HostWindowService, useValue: window}, + {provide: AuthService, useValue: {setRedirectUrl: () => {}}} ], schemas: [ CUSTOM_ELEMENTS_SCHEMA diff --git a/src/app/shared/auth-nav-menu/auth-nav-menu.component.ts b/src/app/shared/auth-nav-menu/auth-nav-menu.component.ts index 887729a7af..c657071987 100644 --- a/src/app/shared/auth-nav-menu/auth-nav-menu.component.ts +++ b/src/app/shared/auth-nav-menu/auth-nav-menu.component.ts @@ -7,10 +7,14 @@ import { fadeInOut, fadeOut } from '../animations/fade'; import { HostWindowService } from '../host-window.service'; import { AppState, routerStateSelector } from '../../app.reducer'; import { isNotUndefined } from '../empty.util'; -import { getAuthenticatedUser, isAuthenticated, isAuthenticationLoading } from '../../core/auth/selectors'; +import { + getAuthenticatedUser, + isAuthenticated, + isAuthenticationLoading +} from '../../core/auth/selectors'; import { EPerson } from '../../core/eperson/models/eperson.model'; -import { LOGIN_ROUTE, LOGOUT_ROUTE } from '../../core/auth/auth.service'; -import { RemoteData } from '../../core/data/remote-data'; +import { AuthService, LOGIN_ROUTE, LOGOUT_ROUTE } from '../../core/auth/auth.service'; +import { Subscription } from 'rxjs/Subscription'; @Component({ selector: 'ds-auth-nav-menu', @@ -37,8 +41,12 @@ export class AuthNavMenuComponent implements OnInit { public user: Observable; + public sub: Subscription; + constructor(private store: Store, - private windowService: HostWindowService) { + private windowService: HostWindowService, + private authService: AuthService + ) { this.isXsOrSm$ = this.windowService.isXsOrSm(); } @@ -54,7 +62,12 @@ export class AuthNavMenuComponent implements OnInit { this.showAuth = this.store.select(routerStateSelector) .filter((router: RouterReducerState) => isNotUndefined(router) && isNotUndefined(router.state)) .map((router: RouterReducerState) => { - return !router.state.url.startsWith(LOGIN_ROUTE) && !router.state.url.startsWith(LOGOUT_ROUTE); + const url = router.state.url; + const show = !router.state.url.startsWith(LOGIN_ROUTE) && !router.state.url.startsWith(LOGOUT_ROUTE); + if (show) { + this.authService.setRedirectUrl(url); + } + return show; }); } } From e959542e2d708bb1f97673892f4844a0e4efce4a Mon Sep 17 00:00:00 2001 From: lotte Date: Wed, 19 Sep 2018 13:10:23 +0200 Subject: [PATCH 22/48] implemented applying of a patch --- .../auth/auth-response-parsing.service.ts | 2 +- .../core/cache/object-cache.reducer.spec.ts | 8 +- src/app/core/cache/object-cache.reducer.ts | 4 +- src/app/core/cache/object-cache.service.ts | 3 +- .../core/cache/server-sync-buffer.effects.ts | 70 ++++-- .../data/base-response-parsing.service.ts | 1 - src/app/core/data/collection-data.service.ts | 4 +- src/app/core/data/comcol-data.service.spec.ts | 4 +- src/app/core/data/community-data.service.ts | 4 +- src/app/core/data/data.service.spec.ts | 208 +++++++++--------- src/app/core/data/data.service.ts | 13 ++ .../data/dspace-object-data.service.spec.ts | 6 +- .../core/data/dspace-object-data.service.ts | 9 +- src/app/core/data/item-data.service.spec.ts | 5 +- src/app/core/data/item-data.service.ts | 4 +- src/app/core/data/request.service.ts | 5 + .../ds-dynamic-form-control.component.html | 4 +- src/app/shared/mocks/mock-form-service.ts | 7 +- .../number-picker/number-picker.component.ts | 2 +- tslint.json | 10 +- 20 files changed, 226 insertions(+), 147 deletions(-) diff --git a/src/app/core/auth/auth-response-parsing.service.ts b/src/app/core/auth/auth-response-parsing.service.ts index 80c1b2eeca..337bb0fd0a 100644 --- a/src/app/core/auth/auth-response-parsing.service.ts +++ b/src/app/core/auth/auth-response-parsing.service.ts @@ -20,7 +20,7 @@ export class AuthResponseParsingService extends BaseResponseParsingService imple protected toCache = false; constructor(@Inject(GLOBAL_CONFIG) protected EnvConfig: GlobalConfig, - protected objectCache: ObjectCacheService,) { + protected objectCache: ObjectCacheService) { super(); } diff --git a/src/app/core/cache/object-cache.reducer.spec.ts b/src/app/core/cache/object-cache.reducer.spec.ts index 2c059c4dd3..ce41f96bd4 100644 --- a/src/app/core/cache/object-cache.reducer.spec.ts +++ b/src/app/core/cache/object-cache.reducer.spec.ts @@ -26,7 +26,9 @@ describe('objectCacheReducer', () => { }, timeAdded: new Date().getTime(), msToLive: 900000, - requestHref: selfLink1 + requestHref: selfLink1, + patches: [], + isDirty: false }, [selfLink2]: { data: { @@ -35,7 +37,9 @@ describe('objectCacheReducer', () => { }, timeAdded: new Date().getTime(), msToLive: 900000, - requestHref: selfLink2 + requestHref: selfLink2, + patches: [], + isDirty: false } }; deepFreeze(testState); diff --git a/src/app/core/cache/object-cache.reducer.ts b/src/app/core/cache/object-cache.reducer.ts index cd0a927c34..adea46bc57 100644 --- a/src/app/core/cache/object-cache.reducer.ts +++ b/src/app/core/cache/object-cache.reducer.ts @@ -112,13 +112,15 @@ export function objectCacheReducer(state = initialState, action: ObjectCacheActi * the new state, with the object added, or overwritten. */ function addToObjectCache(state: ObjectCacheState, action: AddToObjectCacheAction): ObjectCacheState { + const existing = state[action.payload.objectToCache.self]; return Object.assign({}, state, { [action.payload.objectToCache.self]: { data: action.payload.objectToCache, timeAdded: action.payload.timeAdded, msToLive: action.payload.msToLive, requestHref: action.payload.requestHref, - isDirty: false + isDirty: false, + patches: (hasValue(existing) ? existing.patches : []) } }); } diff --git a/src/app/core/cache/object-cache.service.ts b/src/app/core/cache/object-cache.service.ts index d7bf59500c..f6b295afb4 100644 --- a/src/app/core/cache/object-cache.service.ts +++ b/src/app/core/cache/object-cache.service.ts @@ -90,7 +90,6 @@ export class ObjectCacheService { getBySelfLink(selfLink: string): Observable { return this.getEntry(selfLink).pipe( map((entry: ObjectCacheEntry) => { - // flatten two dimensional array const flatPatch: Operation[] = [].concat(...entry.patches); const patchedData = applyPatch(entry.data, flatPatch).newDocument; return Object.assign({}, entry, { data: patchedData }); @@ -218,7 +217,7 @@ export class ObjectCacheService { * @param {Operation[]} patch * list of operations to perform */ - private addPatch(uuid: string, patch: Operation[]) { + public addPatch(uuid: string, patch: Operation[]) { this.store.dispatch(new AddPatchObjectCacheAction(uuid, patch)); this.store.dispatch(new AddToSSBAction(uuid, RestRequestMethod.Patch)); } diff --git a/src/app/core/cache/server-sync-buffer.effects.ts b/src/app/core/cache/server-sync-buffer.effects.ts index 517c9837c2..d6c1941e86 100644 --- a/src/app/core/cache/server-sync-buffer.effects.ts +++ b/src/app/core/cache/server-sync-buffer.effects.ts @@ -1,4 +1,4 @@ -import { delay, exhaustMap, filter, first, map } from 'rxjs/operators'; +import { delay, exhaustMap, first, map, switchMap, tap } from 'rxjs/operators'; import { Inject, Injectable } from '@angular/core'; import { Actions, Effect, ofType } from '@ngrx/effects'; import { @@ -10,43 +10,77 @@ import { import { GLOBAL_CONFIG } from '../../../config'; import { GlobalConfig } from '../../../config/global-config.interface'; import { CoreState } from '../core.reducers'; -import { select, Store } from '@ngrx/store'; +import { Action, select, Store } from '@ngrx/store'; import { ServerSyncBufferEntry, ServerSyncBufferState } from './server-sync-buffer.reducer'; -import { of as observableOf } from 'rxjs'; +import { of as observableOf, combineLatest as observableCombineLatest } from 'rxjs'; import { RequestService } from '../data/request.service'; -import { PutRequest } from '../data/request.models'; +import { PutRequest, RestRequestMethod } from '../data/request.models'; +import { ObjectCacheService } from './object-cache.service'; +import { ApplyPatchObjectCacheAction } from './object-cache.actions'; +import { DSpaceRESTv2Serializer } from '../dspace-rest-v2/dspace-rest-v2.serializer'; +import { GenericConstructor } from '../shared/generic-constructor'; +import { hasValue } from '../../shared/empty.util'; +import { Observable } from 'rxjs/internal/Observable'; @Injectable() export class ObjectCacheEffects { @Effect() setTimeoutForServerSync = this.actions$ - .pipe(ofType(ServerSyncBufferActionTypes.ADD), + .pipe( + ofType(ServerSyncBufferActionTypes.ADD), exhaustMap((action: AddToSSBAction) => { const autoSyncConfig = this.EnvConfig.cache.autoSync; const timeoutInSeconds = autoSyncConfig.timePerMethod[action.type] || autoSyncConfig.defaultTime; - return observableOf(new CommitSSBAction(action.payload.method)).pipe(delay( timeoutInSeconds * 1000)) + return observableOf(new CommitSSBAction(action.payload.method)).pipe(delay(timeoutInSeconds * 1000)) }) ); @Effect() commitServerSyncBuffer = this.actions$ - .pipe(ofType(ServerSyncBufferActionTypes.COMMIT), - map((action: CommitSSBAction) => { - this.store.pipe( + .pipe( + ofType(ServerSyncBufferActionTypes.COMMIT), + switchMap((action: CommitSSBAction) => { + return this.store.pipe( select(serverSyncBufferSelector), - first() - ).subscribe((bufferState: ServerSyncBufferState) => { - bufferState.buffer - .filter((entry: ServerSyncBufferEntry) => entry.method === action.payload) - .forEach((entry: ServerSyncBufferEntry) => { - this.requestService.configure(new PutRequest(this.requestService.generateRequestId(), ,)) - }) - }); - return new EmptySSBAction(action.payload); + map((bufferState: ServerSyncBufferState) => { + const actions: Array> = bufferState.buffer + .filter((entry: ServerSyncBufferEntry) => { + /* If there's a request method, filter + If there's no filter, commit everything */ + if (hasValue(action.payload)) { + return entry.method === action.payload; + } + return true; + }) + .map((entry: ServerSyncBufferEntry) => { + if (entry.method === RestRequestMethod.Patch) { + return this.applyPatch(entry.href); + } else { + /* TODO other request stuff */ + } + }); + /* Add extra action to array, to make sure the ServerSyncBuffer is emptied afterwards */ + return observableCombineLatest(actions).pipe( + map((array) => array.push(new EmptySSBAction(action.payload))) + ); + }) + ) }) ); + private applyPatch(href: string): Observable { + const patchObject = this.objectCache.getBySelfLink(href); + return patchObject.pipe( + map((object) => { + const serializedObject = new DSpaceRESTv2Serializer(object.constructor as GenericConstructor<{}>).serialize(object); + this.requestService.configure(new PutRequest(this.requestService.generateRequestId(), href, serializedObject)); + return new ApplyPatchObjectCacheAction(href) + }) + ) + } + constructor(private actions$: Actions, private store: Store, private requestService: RequestService, + private objectCache: ObjectCacheService, @Inject(GLOBAL_CONFIG) private EnvConfig: GlobalConfig) { } diff --git a/src/app/core/data/base-response-parsing.service.ts b/src/app/core/data/base-response-parsing.service.ts index 050b3c2da5..374a1ea0a9 100644 --- a/src/app/core/data/base-response-parsing.service.ts +++ b/src/app/core/data/base-response-parsing.service.ts @@ -25,7 +25,6 @@ export abstract class BaseResponseParsingService { protected abstract toCache: boolean; protected process(data: any, requestHref: string): any { - if (isNotEmpty(data)) { if (hasNoValue(data) || (typeof data !== 'object')) { return data; diff --git a/src/app/core/data/collection-data.service.ts b/src/app/core/data/collection-data.service.ts index 7d1e463dbe..2642c4b5e6 100644 --- a/src/app/core/data/collection-data.service.ts +++ b/src/app/core/data/collection-data.service.ts @@ -22,8 +22,8 @@ export class CollectionDataService extends ComColDataService, protected cds: CommunityDataService, - protected objectCache: ObjectCacheService, - protected halService: HALEndpointService + protected halService: HALEndpointService, + protected objectCache: ObjectCacheService ) { super(); } diff --git a/src/app/core/data/comcol-data.service.spec.ts b/src/app/core/data/comcol-data.service.spec.ts index eb2e1bd1cf..ff05d73fff 100644 --- a/src/app/core/data/comcol-data.service.spec.ts +++ b/src/app/core/data/comcol-data.service.spec.ts @@ -29,8 +29,8 @@ class TestService extends ComColDataService { protected store: Store, protected EnvConfig: GlobalConfig, protected cds: CommunityDataService, - protected objectCache: ObjectCacheService, protected halService: HALEndpointService, + protected objectCache: ObjectCacheService, protected linkPath: string ) { super(); @@ -92,8 +92,8 @@ describe('ComColDataService', () => { store, EnvConfig, cds, - objectCache, halService, + objectCache, LINK_NAME ); } diff --git a/src/app/core/data/community-data.service.ts b/src/app/core/data/community-data.service.ts index b8e8bd5ce0..a9163fd6b9 100644 --- a/src/app/core/data/community-data.service.ts +++ b/src/app/core/data/community-data.service.ts @@ -29,8 +29,8 @@ export class CommunityDataService extends ComColDataService, - protected objectCache: ObjectCacheService, - protected halService: HALEndpointService + protected halService: HALEndpointService, + protected objectCache: ObjectCacheService ) { super(); } diff --git a/src/app/core/data/data.service.spec.ts b/src/app/core/data/data.service.spec.ts index add84818de..1bb051a9a6 100644 --- a/src/app/core/data/data.service.spec.ts +++ b/src/app/core/data/data.service.spec.ts @@ -9,6 +9,7 @@ import { HALEndpointService } from '../shared/hal-endpoint.service'; import { Observable } from 'rxjs'; import { FindAllOptions } from './request.models'; import { SortOptions, SortDirection } from '../cache/models/sort-options.model'; +import { ObjectCacheService } from '../cache/object-cache.service'; const LINK_NAME = 'test' @@ -17,117 +18,122 @@ class NormalizedTestObject extends NormalizedObject { } class TestService extends DataService { - constructor( - protected responseCache: ResponseCacheService, - protected requestService: RequestService, - protected rdbService: RemoteDataBuildService, - protected store: Store, - protected linkPath: string, - protected halService: HALEndpointService - ) { - super(); - } + constructor( + protected responseCache: ResponseCacheService, + protected requestService: RequestService, + protected rdbService: RemoteDataBuildService, + protected store: Store, + protected linkPath: string, + protected halService: HALEndpointService, + protected objectCache: ObjectCacheService + ) { + super(); + } - public getScopedEndpoint(scope: string): Observable { - throw new Error('getScopedEndpoint is abstract in DataService'); - } + public getScopedEndpoint(scope: string): Observable { + throw new Error('getScopedEndpoint is abstract in DataService'); + } } describe('DataService', () => { - let service: TestService; - let options: FindAllOptions; - const responseCache = {} as ResponseCacheService; - const requestService = {} as RequestService; - const halService = {} as HALEndpointService; - const rdbService = {} as RemoteDataBuildService; - const store = {} as Store; - const endpoint = 'https://rest.api/core'; + let service: TestService; + let options: FindAllOptions; + const responseCache = {} as ResponseCacheService; + const requestService = {} as RequestService; + const halService = {} as HALEndpointService; + const rdbService = {} as RemoteDataBuildService; + const objectCache = {} as ObjectCacheService; + const store = {} as Store; + const endpoint = 'https://rest.api/core'; - function initTestService(): TestService { - return new TestService( - responseCache, - requestService, - rdbService, - store, - LINK_NAME, - halService - ); - } + function initTestService(): TestService { + return new TestService( + responseCache, + requestService, + rdbService, + store, + LINK_NAME, + halService, + objectCache + ); + } - service = initTestService(); + service = initTestService(); - describe('getFindAllHref', () => { + describe('getFindAllHref', () => { - it('should return an observable with the endpoint', () => { - options = {}; + it('should return an observable with the endpoint', () => { + options = {}; - (service as any).getFindAllHref(endpoint).subscribe((value) => { - expect(value).toBe(endpoint); - } - ); - }); - - // getScopedEndpoint is not implemented in abstract DataService - it('should throw error if scopeID provided in options', () => { - options = { scopeID: 'somevalue' }; - - expect(() => { (service as any).getFindAllHref(endpoint, options) }) - .toThrowError('getScopedEndpoint is abstract in DataService'); - }); - - it('should include page in href if currentPage provided in options', () => { - options = { currentPage: 2 }; - const expected = `${endpoint}?page=${options.currentPage - 1}`; - - (service as any).getFindAllHref(endpoint, options).subscribe((value) => { - expect(value).toBe(expected); - }); - }); - - it('should include size in href if elementsPerPage provided in options', () => { - options = { elementsPerPage: 5 }; - const expected = `${endpoint}?size=${options.elementsPerPage}`; - - (service as any).getFindAllHref(endpoint, options).subscribe((value) => { - expect(value).toBe(expected); - }); - }); - - it('should include sort href if SortOptions provided in options', () => { - const sortOptions = new SortOptions('field1', SortDirection.ASC); - options = { sort: sortOptions}; - const expected = `${endpoint}?sort=${sortOptions.field},${sortOptions.direction}`; - - (service as any).getFindAllHref(endpoint, options).subscribe((value) => { - expect(value).toBe(expected); - }); - }); - - it('should include startsWith in href if startsWith provided in options', () => { - options = { startsWith: 'ab' }; - const expected = `${endpoint}?startsWith=${options.startsWith}`; - - (service as any).getFindAllHref(endpoint, options).subscribe((value) => { - expect(value).toBe(expected); - }); - }); - - it('should include all provided options in href', () => { - const sortOptions = new SortOptions('field1', SortDirection.DESC) - options = { - currentPage: 6, - elementsPerPage: 10, - sort: sortOptions, - startsWith: 'ab' - } - const expected = `${endpoint}?page=${options.currentPage - 1}&size=${options.elementsPerPage}` + - `&sort=${sortOptions.field},${sortOptions.direction}&startsWith=${options.startsWith}`; - - (service as any).getFindAllHref(endpoint, options).subscribe((value) => { - expect(value).toBe(expected); - }); - }) + (service as any).getFindAllHref(endpoint).subscribe((value) => { + expect(value).toBe(endpoint); + } + ); }); + // getScopedEndpoint is not implemented in abstract DataService + it('should throw error if scopeID provided in options', () => { + options = { scopeID: 'somevalue' }; + + expect(() => { + (service as any).getFindAllHref(endpoint, options) + }) + .toThrowError('getScopedEndpoint is abstract in DataService'); + }); + + it('should include page in href if currentPage provided in options', () => { + options = { currentPage: 2 }; + const expected = `${endpoint}?page=${options.currentPage - 1}`; + + (service as any).getFindAllHref(endpoint, options).subscribe((value) => { + expect(value).toBe(expected); + }); + }); + + it('should include size in href if elementsPerPage provided in options', () => { + options = { elementsPerPage: 5 }; + const expected = `${endpoint}?size=${options.elementsPerPage}`; + + (service as any).getFindAllHref(endpoint, options).subscribe((value) => { + expect(value).toBe(expected); + }); + }); + + it('should include sort href if SortOptions provided in options', () => { + const sortOptions = new SortOptions('field1', SortDirection.ASC); + options = { sort: sortOptions }; + const expected = `${endpoint}?sort=${sortOptions.field},${sortOptions.direction}`; + + (service as any).getFindAllHref(endpoint, options).subscribe((value) => { + expect(value).toBe(expected); + }); + }); + + it('should include startsWith in href if startsWith provided in options', () => { + options = { startsWith: 'ab' }; + const expected = `${endpoint}?startsWith=${options.startsWith}`; + + (service as any).getFindAllHref(endpoint, options).subscribe((value) => { + expect(value).toBe(expected); + }); + }); + + it('should include all provided options in href', () => { + const sortOptions = new SortOptions('field1', SortDirection.DESC) + options = { + currentPage: 6, + elementsPerPage: 10, + sort: sortOptions, + startsWith: 'ab' + } + const expected = `${endpoint}?page=${options.currentPage - 1}&size=${options.elementsPerPage}` + + `&sort=${sortOptions.field},${sortOptions.direction}&startsWith=${options.startsWith}`; + + (service as any).getFindAllHref(endpoint, options).subscribe((value) => { + expect(value).toBe(expected); + }); + }) + }); + }); diff --git a/src/app/core/data/data.service.ts b/src/app/core/data/data.service.ts index 1d0703bb47..f58868d2ce 100644 --- a/src/app/core/data/data.service.ts +++ b/src/app/core/data/data.service.ts @@ -14,6 +14,9 @@ import { RemoteData } from './remote-data'; import { FindAllOptions, FindAllRequest, FindByIDRequest, GetRequest } from './request.models'; import { RequestService } from './request.service'; import { NormalizedObject } from '../cache/models/normalized-object.model'; +import { compare, Operation } from 'fast-json-patch'; +import { ObjectCacheService } from '../cache/object-cache.service'; +import { DSpaceObject } from '../shared/dspace-object.model'; export abstract class DataService { protected abstract responseCache: ResponseCacheService; @@ -22,6 +25,7 @@ export abstract class DataService protected abstract store: Store; protected abstract linkPath: string; protected abstract halService: HALEndpointService; + protected abstract objectCache: ObjectCacheService; public abstract getScopedEndpoint(scope: string): Observable @@ -97,6 +101,15 @@ export abstract class DataService return this.rdbService.buildSingle(href); } + patch(href: string, operations: Operation[]) { + this.objectCache.addPatch(href, operations); + } + + update(object: DSpaceObject) { + const oldVersion = this.objectCache.getBySelfLink(object.self); + const operations = compare(oldVersion, object); + this.objectCache.addPatch(object.self, operations); + } // TODO implement, after the structure of the REST server's POST response is finalized // create(dso: DSpaceObject): Observable> { // const postHrefObs = this.getEndpoint(); diff --git a/src/app/core/data/dspace-object-data.service.spec.ts b/src/app/core/data/dspace-object-data.service.spec.ts index ef767c5d2d..cdddcb7ce6 100644 --- a/src/app/core/data/dspace-object-data.service.spec.ts +++ b/src/app/core/data/dspace-object-data.service.spec.ts @@ -6,6 +6,7 @@ import { HALEndpointService } from '../shared/hal-endpoint.service'; import { FindByIDRequest } from './request.models'; import { RequestService } from './request.service'; import { DSpaceObjectDataService } from './dspace-object-data.service'; +import { ObjectCacheService } from '../cache/object-cache.service'; describe('DSpaceObjectDataService', () => { let scheduler: TestScheduler; @@ -13,6 +14,7 @@ describe('DSpaceObjectDataService', () => { let halService: HALEndpointService; let requestService: RequestService; let rdbService: RemoteDataBuildService; + let objectCache: ObjectCacheService; const testObject = { uuid: '9b4f22f4-164a-49db-8817-3316b6ee5746' } as DSpaceObject; @@ -37,11 +39,13 @@ describe('DSpaceObjectDataService', () => { } }) }); + objectCache = {} as ObjectCacheService; service = new DSpaceObjectDataService( requestService, rdbService, - halService + halService, + objectCache ) }); diff --git a/src/app/core/data/dspace-object-data.service.ts b/src/app/core/data/dspace-object-data.service.ts index 09eea8a95f..5b92b1beef 100644 --- a/src/app/core/data/dspace-object-data.service.ts +++ b/src/app/core/data/dspace-object-data.service.ts @@ -10,6 +10,7 @@ import { HALEndpointService } from '../shared/hal-endpoint.service'; import { DataService } from './data.service'; import { RemoteData } from './remote-data'; import { RequestService } from './request.service'; +import { ObjectCacheService } from '../cache/object-cache.service'; /* tslint:disable:max-classes-per-file */ class DataServiceImpl extends DataService { @@ -20,7 +21,8 @@ class DataServiceImpl extends DataService protected requestService: RequestService, protected rdbService: RemoteDataBuildService, protected store: Store, - protected halService: HALEndpointService) { + protected halService: HALEndpointService, + protected objectCache: ObjectCacheService) { super(); } @@ -41,8 +43,9 @@ export class DSpaceObjectDataService { constructor( protected requestService: RequestService, protected rdbService: RemoteDataBuildService, - protected halService: HALEndpointService) { - this.dataService = new DataServiceImpl(null, requestService, rdbService, null, halService); + protected halService: HALEndpointService, + protected objectCache: ObjectCacheService) { + this.dataService = new DataServiceImpl(null, requestService, rdbService, null, halService, objectCache); } findById(uuid: string): Observable> { diff --git a/src/app/core/data/item-data.service.spec.ts b/src/app/core/data/item-data.service.spec.ts index 0a233d086c..df0be98f7a 100644 --- a/src/app/core/data/item-data.service.spec.ts +++ b/src/app/core/data/item-data.service.spec.ts @@ -8,6 +8,7 @@ import { CoreState } from '../core.reducers'; import { ItemDataService } from './item-data.service'; import { RequestService } from './request.service'; import { HALEndpointService } from '../shared/hal-endpoint.service'; +import { ObjectCacheService } from '../cache/object-cache.service'; describe('ItemDataService', () => { let scheduler: TestScheduler; @@ -16,6 +17,7 @@ describe('ItemDataService', () => { const requestService = {} as RequestService; const responseCache = {} as ResponseCacheService; const rdbService = {} as RemoteDataBuildService; + const objectCache = {} as ObjectCacheService; const store = {} as Store; const halEndpointService = {} as HALEndpointService; @@ -42,7 +44,8 @@ describe('ItemDataService', () => { rdbService, store, bs, - halEndpointService + halEndpointService, + objectCache ); } diff --git a/src/app/core/data/item-data.service.ts b/src/app/core/data/item-data.service.ts index dead4e5f48..7a0a28729c 100644 --- a/src/app/core/data/item-data.service.ts +++ b/src/app/core/data/item-data.service.ts @@ -17,6 +17,7 @@ import { URLCombiner } from '../url-combiner/url-combiner'; import { DataService } from './data.service'; import { RequestService } from './request.service'; import { HALEndpointService } from '../shared/hal-endpoint.service'; +import { ObjectCacheService } from '../cache/object-cache.service'; @Injectable() export class ItemDataService extends DataService { @@ -28,7 +29,8 @@ export class ItemDataService extends DataService { protected rdbService: RemoteDataBuildService, protected store: Store, private bs: BrowseService, - protected halService: HALEndpointService) { + protected halService: HALEndpointService, + protected objectCache: ObjectCacheService) { super(); } diff --git a/src/app/core/data/request.service.ts b/src/app/core/data/request.service.ts index 101825e3db..e944bcb19f 100644 --- a/src/app/core/data/request.service.ts +++ b/src/app/core/data/request.service.ts @@ -17,6 +17,7 @@ import { RequestConfigureAction, RequestExecuteAction } from './request.actions' import { GetRequest, RestRequest, RestRequestMethod } from './request.models'; import { RequestEntry } from './request.reducer'; +import { CommitSSBAction } from '../cache/server-sync-buffer.actions'; @Injectable() export class RequestService { @@ -123,4 +124,8 @@ export class RequestService { this.requestsOnTheirWayToTheStore = this.requestsOnTheirWayToTheStore.filter((pendingHref: string) => pendingHref !== request.href) }); } + + commit(method?: RestRequestMethod) { + this.store.dispatch(new CommitSSBAction(method)) + } } diff --git a/src/app/shared/form/builder/ds-dynamic-form-ui/ds-dynamic-form-control.component.html b/src/app/shared/form/builder/ds-dynamic-form-ui/ds-dynamic-form-control.component.html index d838a90f20..750ef721c2 100644 --- a/src/app/shared/form/builder/ds-dynamic-form-ui/ds-dynamic-form-control.component.html +++ b/src/app/shared/form/builder/ds-dynamic-form-ui/ds-dynamic-form-control.component.html @@ -1,8 +1,8 @@ -
- diff --git a/src/app/shared/mocks/mock-form-service.ts b/src/app/shared/mocks/mock-form-service.ts index e92be02fcc..1f340f6df6 100644 --- a/src/app/shared/mocks/mock-form-service.ts +++ b/src/app/shared/mocks/mock-form-service.ts @@ -10,7 +10,12 @@ export function getMockFormService( getUniqueId: id$, resetForm: {}, validateAllFormFields: {}, - getForm: errors.pipe(map((err) => { return {data: {}, valid: true, errors: err} })), + getForm: errors.pipe( + map((err) => { + return { data: {}, valid: true, errors: err } + } + ) + ), removeForm: undefined, removeError: undefined, changeForm: undefined, diff --git a/src/app/shared/number-picker/number-picker.component.ts b/src/app/shared/number-picker/number-picker.component.ts index 0bc47e9438..bf3a7e9e7a 100644 --- a/src/app/shared/number-picker/number-picker.component.ts +++ b/src/app/shared/number-picker/number-picker.component.ts @@ -99,7 +99,7 @@ export class NumberPickerComponent implements OnInit, ControlValueAccessor { update(event) { try { - const i = Number.parseInt(event.target.value); + const i = Number.parseInt(event.target.value, 10); if (i >= this.min && i <= this.max) { this.value = i; diff --git a/tslint.json b/tslint.json index cd7ffadac9..b4f905d324 100644 --- a/tslint.json +++ b/tslint.json @@ -151,10 +151,10 @@ "use-input-property-decorator": true, "use-life-cycle-interface": false, "use-output-property-decorator": true, - "use-pipe-transform-interface": true, - "rxjs-collapse-imports": true, - "rxjs-pipeable-operators-only": true, - "rxjs-no-static-observable-methods": true, - "rxjs-proper-imports": true + "use-pipe-transform-interface": true +// "rxjs-collapse-imports": true, +// "rxjs-pipeable-operators-only": true, +// "rxjs-no-static-observable-methods": true, +// "rxjs-proper-imports": true } } From c6f55e424bec85b1ed92419cdd09ec049357e81d Mon Sep 17 00:00:00 2001 From: lotte Date: Wed, 19 Sep 2018 15:32:14 +0200 Subject: [PATCH 23/48] Finished patch support --- src/app/core/auth/auth.interceptor.spec.ts | 10 ++--- src/app/core/cache/object-cache.service.ts | 11 ++++-- .../core/cache/server-sync-buffer.actions.ts | 6 +-- .../core/cache/server-sync-buffer.effects.ts | 12 +++--- .../core/cache/server-sync-buffer.reducer.ts | 2 +- src/app/core/core.effects.ts | 4 +- src/app/core/data/data.service.ts | 2 +- src/app/core/data/request.models.ts | 38 +++++-------------- src/app/core/data/request.service.ts | 5 ++- src/app/core/data/rest-request-method.ts | 18 +++++++++ .../dspace-rest-v2/dspace-rest-v2.service.ts | 2 +- src/app/core/index/index.effects.ts | 4 +- src/config/auto-sync-config.interface.ts | 3 +- src/config/cache-config.interface.ts | 2 +- 14 files changed, 61 insertions(+), 58 deletions(-) create mode 100644 src/app/core/data/rest-request-method.ts diff --git a/src/app/core/auth/auth.interceptor.spec.ts b/src/app/core/auth/auth.interceptor.spec.ts index 89c9ed1951..4505ca7896 100644 --- a/src/app/core/auth/auth.interceptor.spec.ts +++ b/src/app/core/auth/auth.interceptor.spec.ts @@ -9,10 +9,10 @@ import { of as observableOf } from 'rxjs'; import { AuthInterceptor } from './auth.interceptor'; import { AuthService } from './auth.service'; import { DSpaceRESTv2Service } from '../dspace-rest-v2/dspace-rest-v2.service'; -import { RestRequestMethod } from '../data/request.models'; import { RouterStub } from '../../shared/testing/router-stub'; import { TruncatablesState } from '../../shared/truncatable/truncatable.reducer'; import { AuthServiceStub } from '../../shared/testing/auth-service-stub'; +import { RestRequestMethod } from '../data//rest-request-method'; describe(`AuthInterceptor`, () => { let service: DSpaceRESTv2Service; @@ -49,7 +49,7 @@ describe(`AuthInterceptor`, () => { describe('when has a valid token', () => { it('should not add an Authorization header when we’re sending a HTTP request to \'authn\' endpoint', () => { - service.request(RestRequestMethod.Post, 'dspace-spring-rest/api/authn/login', 'password=password&user=user').subscribe((response) => { + service.request(RestRequestMethod.POST, 'dspace-spring-rest/api/authn/login', 'password=password&user=user').subscribe((response) => { expect(response).toBeTruthy(); }); @@ -60,7 +60,7 @@ describe(`AuthInterceptor`, () => { }); it('should add an Authorization header when we’re sending a HTTP request to \'authn\' endpoint', () => { - service.request(RestRequestMethod.Post, 'dspace-spring-rest/api/submission/workspaceitems', 'test').subscribe((response) => { + service.request(RestRequestMethod.POST, 'dspace-spring-rest/api/submission/workspaceitems', 'test').subscribe((response) => { expect(response).toBeTruthy(); }); @@ -85,11 +85,11 @@ describe(`AuthInterceptor`, () => { it('should redirect to login', () => { - service.request(RestRequestMethod.Post, 'dspace-spring-rest/api/submission/workspaceitems', 'password=password&user=user').subscribe((response) => { + service.request(RestRequestMethod.POST, 'dspace-spring-rest/api/submission/workspaceitems', 'password=password&user=user').subscribe((response) => { expect(response).toBeTruthy(); }); - service.request(RestRequestMethod.Post, 'dspace-spring-rest/api/submission/workspaceitems', 'password=password&user=user'); + service.request(RestRequestMethod.POST, 'dspace-spring-rest/api/submission/workspaceitems', 'password=password&user=user'); httpMock.expectNone('dspace-spring-rest/api/submission/workspaceitems'); }); diff --git a/src/app/core/cache/object-cache.service.ts b/src/app/core/cache/object-cache.service.ts index f6b295afb4..5db2d73d4e 100644 --- a/src/app/core/cache/object-cache.service.ts +++ b/src/app/core/cache/object-cache.service.ts @@ -1,6 +1,6 @@ import { combineLatest as observableCombineLatest, Observable } from 'rxjs'; -import { distinctUntilChanged, filter, first, map, mergeMap, take, tap } from 'rxjs/operators'; +import { distinctUntilChanged, filter, first, map, mergeMap } from 'rxjs/operators'; import { Injectable } from '@angular/core'; import { MemoizedSelector, select, Store } from '@ngrx/store'; import { IndexName } from '../index/index.reducer'; @@ -8,7 +8,8 @@ import { IndexName } from '../index/index.reducer'; import { CacheableObject, ObjectCacheEntry } from './object-cache.reducer'; import { AddPatchObjectCacheAction, - AddToObjectCacheAction, ApplyPatchObjectCacheAction, + AddToObjectCacheAction, + ApplyPatchObjectCacheAction, RemoveFromObjectCacheAction } from './object-cache.actions'; import { hasNoValue, isNotEmpty } from '../../shared/empty.util'; @@ -18,8 +19,8 @@ import { pathSelector } from '../shared/selectors'; import { NormalizedObjectFactory } from './models/normalized-object-factory'; import { NormalizedObject } from './models/normalized-object.model'; import { applyPatch, Operation } from 'fast-json-patch'; -import { RestRequestMethod } from '../data/request.models'; import { AddToSSBAction } from './server-sync-buffer.actions'; +import { RestRequestMethod } from '../data//rest-request-method'; function selfLinkFromUuidSelector(uuid: string): MemoizedSelector { return pathSelector(coreSelector, 'index', IndexName.OBJECT, uuid); @@ -209,6 +210,8 @@ export class ObjectCacheService { } } + + /** * Add operations to the existing list of operations for an ObjectCacheEntry * Makes sure the ServerSyncBuffer for this ObjectCacheEntry is updated @@ -219,7 +222,7 @@ export class ObjectCacheService { */ public addPatch(uuid: string, patch: Operation[]) { this.store.dispatch(new AddPatchObjectCacheAction(uuid, patch)); - this.store.dispatch(new AddToSSBAction(uuid, RestRequestMethod.Patch)); + this.store.dispatch(new AddToSSBAction(uuid, RestRequestMethod.PATCH)); } /** diff --git a/src/app/core/cache/server-sync-buffer.actions.ts b/src/app/core/cache/server-sync-buffer.actions.ts index 9189af4471..b164a41fd9 100644 --- a/src/app/core/cache/server-sync-buffer.actions.ts +++ b/src/app/core/cache/server-sync-buffer.actions.ts @@ -1,9 +1,7 @@ import { Action } from '@ngrx/store'; import { type } from '../../shared/ngrx/type'; -import { CacheableObject } from './object-cache.reducer'; -import { Operation } from 'fast-json-patch'; -import { RestRequest, RestRequestMethod } from '../data/request.models'; +import { RestRequestMethod } from '../data//rest-request-method'; /** * The list of ServerSyncBufferAction type definitions @@ -33,7 +31,7 @@ export class AddToSSBAction implements Action { * the unique href of the cached object entry that should be updated */ constructor(href: string, method: RestRequestMethod) { - this.payload = { href, method }; + this.payload = { href, method: undefined }; } } diff --git a/src/app/core/cache/server-sync-buffer.effects.ts b/src/app/core/cache/server-sync-buffer.effects.ts index d6c1941e86..e5ee2cf28e 100644 --- a/src/app/core/cache/server-sync-buffer.effects.ts +++ b/src/app/core/cache/server-sync-buffer.effects.ts @@ -14,22 +14,24 @@ import { Action, select, Store } from '@ngrx/store'; import { ServerSyncBufferEntry, ServerSyncBufferState } from './server-sync-buffer.reducer'; import { of as observableOf, combineLatest as observableCombineLatest } from 'rxjs'; import { RequestService } from '../data/request.service'; -import { PutRequest, RestRequestMethod } from '../data/request.models'; +import { PutRequest } from '../data/request.models'; import { ObjectCacheService } from './object-cache.service'; import { ApplyPatchObjectCacheAction } from './object-cache.actions'; import { DSpaceRESTv2Serializer } from '../dspace-rest-v2/dspace-rest-v2.serializer'; import { GenericConstructor } from '../shared/generic-constructor'; import { hasValue } from '../../shared/empty.util'; import { Observable } from 'rxjs/internal/Observable'; +import { RestRequestMethod } from '../data//rest-request-method'; @Injectable() -export class ObjectCacheEffects { +export class ServerSyncBufferEffects { @Effect() setTimeoutForServerSync = this.actions$ .pipe( ofType(ServerSyncBufferActionTypes.ADD), exhaustMap((action: AddToSSBAction) => { - const autoSyncConfig = this.EnvConfig.cache.autoSync; - const timeoutInSeconds = autoSyncConfig.timePerMethod[action.type] || autoSyncConfig.defaultTime; + // const autoSyncConfig = this.EnvConfig.cache.autoSync; + // const timeoutInSeconds = autoSyncConfig.timePerMethod[action.type] || autoSyncConfig.defaultTime; + const timeoutInSeconds = 0; return observableOf(new CommitSSBAction(action.payload.method)).pipe(delay(timeoutInSeconds * 1000)) }) ); @@ -51,7 +53,7 @@ export class ObjectCacheEffects { return true; }) .map((entry: ServerSyncBufferEntry) => { - if (entry.method === RestRequestMethod.Patch) { + if (entry.method === RestRequestMethod.PATCH) { return this.applyPatch(entry.href); } else { /* TODO other request stuff */ diff --git a/src/app/core/cache/server-sync-buffer.reducer.ts b/src/app/core/cache/server-sync-buffer.reducer.ts index 1fabe5a50a..3354afcd42 100644 --- a/src/app/core/cache/server-sync-buffer.reducer.ts +++ b/src/app/core/cache/server-sync-buffer.reducer.ts @@ -1,4 +1,3 @@ -import { RestRequestMethod } from '../data/request.models'; import { hasNoValue, hasValue } from '../../shared/empty.util'; import { AddToSSBAction, @@ -6,6 +5,7 @@ import { ServerSyncBufferAction, ServerSyncBufferActionTypes } from './server-sync-buffer.actions'; +import { RestRequestMethod } from '../data//rest-request-method'; /** * An entry in the ServerSyncBufferState diff --git a/src/app/core/core.effects.ts b/src/app/core/core.effects.ts index bc534a36b0..881f01aed0 100644 --- a/src/app/core/core.effects.ts +++ b/src/app/core/core.effects.ts @@ -4,11 +4,13 @@ import { ResponseCacheEffects } from './cache/response-cache.effects'; import { UUIDIndexEffects } from './index/index.effects'; import { RequestEffects } from './data/request.effects'; import { AuthEffects } from './auth/auth.effects'; +import { ServerSyncBufferEffects } from './cache/server-sync-buffer.effects'; export const coreEffects = [ ResponseCacheEffects, RequestEffects, ObjectCacheEffects, UUIDIndexEffects, - AuthEffects + AuthEffects, + ServerSyncBufferEffects ]; diff --git a/src/app/core/data/data.service.ts b/src/app/core/data/data.service.ts index f58868d2ce..5af4b7d09a 100644 --- a/src/app/core/data/data.service.ts +++ b/src/app/core/data/data.service.ts @@ -121,7 +121,7 @@ export abstract class DataService // .filter((href: string) => hasValue(href)) // .take(1) // .subscribe((href: string) => { - // const request = new RestRequest(this.requestService.generateRequestId(), href, RestRequestMethod.Post, dso); + // const request = new RestRequest(this.requestService.generateRequestId(), href, RestRequestMethod.POST, dso); // this.requestService.configure(request); // }); // diff --git a/src/app/core/data/request.models.ts b/src/app/core/data/request.models.ts index ce45d5b41c..42c4dd4eff 100644 --- a/src/app/core/data/request.models.ts +++ b/src/app/core/data/request.models.ts @@ -1,7 +1,5 @@ import { SortOptions } from '../cache/models/sort-options.model'; import { GenericConstructor } from '../shared/generic-constructor'; -import { GlobalConfig } from '../../../config/global-config.interface'; -import { RESTURLCombiner } from '../url-combiner/rest-url-combiner'; import { BrowseEntriesResponseParsingService } from './browse-entries-response-parsing.service'; import { DSOResponseParsingService } from './dso-response-parsing.service'; import { ResponseParsingService } from './parsing.service'; @@ -10,35 +8,17 @@ import { BrowseResponseParsingService } from './browse-response-parsing.service' import { ConfigResponseParsingService } from './config-response-parsing.service'; import { AuthResponseParsingService } from '../auth/auth-response-parsing.service'; import { HttpOptions } from '../dspace-rest-v2/dspace-rest-v2.service'; -import { HttpHeaders } from '@angular/common/http'; import { IntegrationResponseParsingService } from '../integration/integration-response-parsing.service'; +import { RestRequestMethod } from './/rest-request-method'; /* tslint:disable:max-classes-per-file */ -/** - * Represents a Request Method. - * - * I didn't reuse the RequestMethod enum in @angular/http because - * it uses numbers. The string values here are more clear when - * debugging. - * - * The ones commented out are still unsupported in the rest of the codebase - */ -export enum RestRequestMethod { - Get = 'GET', - Post = 'POST', - Put = 'PUT', - Delete = 'DELETE', - Options = 'OPTIONS', - Head = 'HEAD', - Patch = 'PATCH' -} export abstract class RestRequest { constructor( public uuid: string, public href: string, - public method: RestRequestMethod = RestRequestMethod.Get, + public method: RestRequestMethod = RestRequestMethod.GET, public body?: any, public options?: HttpOptions ) { @@ -56,7 +36,7 @@ export class GetRequest extends RestRequest { public body?: any, public options?: HttpOptions ) { - super(uuid, href, RestRequestMethod.Get, body) + super(uuid, href, RestRequestMethod.GET, body) } } @@ -67,7 +47,7 @@ export class PostRequest extends RestRequest { public body?: any, public options?: HttpOptions ) { - super(uuid, href, RestRequestMethod.Post, body) + super(uuid, href, RestRequestMethod.POST, body) } } @@ -78,7 +58,7 @@ export class PutRequest extends RestRequest { public body?: any, public options?: HttpOptions ) { - super(uuid, href, RestRequestMethod.Put, body) + super(uuid, href, RestRequestMethod.PUT, body) } } @@ -89,7 +69,7 @@ export class DeleteRequest extends RestRequest { public body?: any, public options?: HttpOptions ) { - super(uuid, href, RestRequestMethod.Delete, body) + super(uuid, href, RestRequestMethod.DELETE, body) } } @@ -100,7 +80,7 @@ export class OptionsRequest extends RestRequest { public body?: any, public options?: HttpOptions ) { - super(uuid, href, RestRequestMethod.Options, body) + super(uuid, href, RestRequestMethod.OPTIONS, body) } } @@ -111,7 +91,7 @@ export class HeadRequest extends RestRequest { public body?: any, public options?: HttpOptions ) { - super(uuid, href, RestRequestMethod.Head, body) + super(uuid, href, RestRequestMethod.HEAD, body) } } @@ -122,7 +102,7 @@ export class PatchRequest extends RestRequest { public body?: any, public options?: HttpOptions ) { - super(uuid, href, RestRequestMethod.Patch, body) + super(uuid, href, RestRequestMethod.PATCH, body) } } diff --git a/src/app/core/data/request.service.ts b/src/app/core/data/request.service.ts index e944bcb19f..8728c223ea 100644 --- a/src/app/core/data/request.service.ts +++ b/src/app/core/data/request.service.ts @@ -14,10 +14,11 @@ import { IndexName } from '../index/index.reducer'; import { pathSelector } from '../shared/selectors'; import { UUIDService } from '../shared/uuid.service'; import { RequestConfigureAction, RequestExecuteAction } from './request.actions'; -import { GetRequest, RestRequest, RestRequestMethod } from './request.models'; +import { GetRequest, RestRequest } from './request.models'; import { RequestEntry } from './request.reducer'; import { CommitSSBAction } from '../cache/server-sync-buffer.actions'; +import { RestRequestMethod } from './/rest-request-method'; @Injectable() export class RequestService { @@ -71,7 +72,7 @@ export class RequestService { // TODO to review "overrideRequest" param when https://github.com/DSpace/dspace-angular/issues/217 will be fixed configure(request: RestRequest, forceBypassCache: boolean = false): void { - const isGetRequest = request.method === RestRequestMethod.Get; + const isGetRequest = request.method === RestRequestMethod.GET; if (!isGetRequest || !this.isCachedOrPending(request) || forceBypassCache) { this.dispatchRequest(request); if (isGetRequest && !forceBypassCache) { diff --git a/src/app/core/data/rest-request-method.ts b/src/app/core/data/rest-request-method.ts new file mode 100644 index 0000000000..03ae7ad0c4 --- /dev/null +++ b/src/app/core/data/rest-request-method.ts @@ -0,0 +1,18 @@ +/** + * Represents a Request Method. + * + * I didn't reuse the RequestMethod enum in @angular/http because + * it uses numbers. The string values here are more clear when + * debugging. + * + * The ones commented out are still unsupported in the rest of the codebase + */ +export enum RestRequestMethod { + GET = 'GET', + POST = 'POST', + PUT = 'PUT', + DELETE = 'DELETE', + OPTIONS = 'OPTIONS', + HEAD = 'HEAD', + PATCH = 'PATCH' +} diff --git a/src/app/core/dspace-rest-v2/dspace-rest-v2.service.ts b/src/app/core/dspace-rest-v2/dspace-rest-v2.service.ts index 1570613c17..c8ce76a554 100644 --- a/src/app/core/dspace-rest-v2/dspace-rest-v2.service.ts +++ b/src/app/core/dspace-rest-v2/dspace-rest-v2.service.ts @@ -3,10 +3,10 @@ import {catchError, map} from 'rxjs/operators'; import { Injectable } from '@angular/core'; import { Request } from '@angular/http'; import { HttpClient, HttpHeaders, HttpParams, HttpResponse } from '@angular/common/http' -import { RestRequestMethod } from '../data/request.models'; import { DSpaceRESTV2Response } from './dspace-rest-v2-response.model'; import { HttpObserve } from '@angular/common/http/src/client'; +import { RestRequestMethod } from '../data//rest-request-method'; export interface HttpOptions { body?: any; diff --git a/src/app/core/index/index.effects.ts b/src/app/core/index/index.effects.ts index de1ba681a2..0d783767a6 100644 --- a/src/app/core/index/index.effects.ts +++ b/src/app/core/index/index.effects.ts @@ -7,10 +7,10 @@ import { RemoveFromObjectCacheAction } from '../cache/object-cache.actions'; import { RequestActionTypes, RequestConfigureAction } from '../data/request.actions'; -import { RestRequestMethod } from '../data/request.models'; import { AddToIndexAction, RemoveFromIndexByValueAction } from './index.actions'; import { hasValue } from '../../shared/empty.util'; import { IndexName } from './index.reducer'; +import { RestRequestMethod } from '../data//rest-request-method'; @Injectable() export class UUIDIndexEffects { @@ -42,7 +42,7 @@ export class UUIDIndexEffects { @Effect() addRequest$ = this.actions$ .pipe( ofType(RequestActionTypes.CONFIGURE), - filter((action: RequestConfigureAction) => action.payload.method === RestRequestMethod.Get), + filter((action: RequestConfigureAction) => action.payload.method === RestRequestMethod.GET), map((action: RequestConfigureAction) => { return new AddToIndexAction( IndexName.REQUEST, diff --git a/src/config/auto-sync-config.interface.ts b/src/config/auto-sync-config.interface.ts index 4ad74005bf..d7c5ce83c5 100644 --- a/src/config/auto-sync-config.interface.ts +++ b/src/config/auto-sync-config.interface.ts @@ -1,6 +1,5 @@ -import { RestRequestMethod } from '../app/core/data/request.models'; +import { RestRequestMethod } from '../app/core/data//rest-request-method'; -/* enum indices */ type TimePerMethod = { [method in RestRequestMethod]: number; }; diff --git a/src/config/cache-config.interface.ts b/src/config/cache-config.interface.ts index 3e9334e300..b8651ed107 100644 --- a/src/config/cache-config.interface.ts +++ b/src/config/cache-config.interface.ts @@ -4,5 +4,5 @@ import { AutoSyncConfig } from './auto-sync-config.interface'; export interface CacheConfig extends Config { msToLive: number, control: string, - autoSync: AutoSyncConfig + // autoSync: AutoSyncConfig } From bae69aef9761ee957fc81d3191125b90aa4e9b11 Mon Sep 17 00:00:00 2001 From: lotte Date: Wed, 19 Sep 2018 15:34:14 +0200 Subject: [PATCH 24/48] Small fix --- src/app/core/auth/auth.interceptor.spec.ts | 2 +- src/app/core/cache/object-cache.service.ts | 2 +- src/app/core/cache/server-sync-buffer.actions.ts | 2 +- src/app/core/cache/server-sync-buffer.effects.ts | 2 +- src/app/core/cache/server-sync-buffer.reducer.ts | 2 +- src/app/core/data/request.models.ts | 2 +- src/app/core/data/request.service.ts | 2 +- src/app/core/dspace-rest-v2/dspace-rest-v2.service.ts | 3 +-- src/app/core/index/index.effects.ts | 2 +- src/config/auto-sync-config.interface.ts | 2 +- 10 files changed, 10 insertions(+), 11 deletions(-) diff --git a/src/app/core/auth/auth.interceptor.spec.ts b/src/app/core/auth/auth.interceptor.spec.ts index 4505ca7896..72b0cc2616 100644 --- a/src/app/core/auth/auth.interceptor.spec.ts +++ b/src/app/core/auth/auth.interceptor.spec.ts @@ -12,7 +12,7 @@ import { DSpaceRESTv2Service } from '../dspace-rest-v2/dspace-rest-v2.service'; import { RouterStub } from '../../shared/testing/router-stub'; import { TruncatablesState } from '../../shared/truncatable/truncatable.reducer'; import { AuthServiceStub } from '../../shared/testing/auth-service-stub'; -import { RestRequestMethod } from '../data//rest-request-method'; +import { RestRequestMethod } from '../data/rest-request-method'; describe(`AuthInterceptor`, () => { let service: DSpaceRESTv2Service; diff --git a/src/app/core/cache/object-cache.service.ts b/src/app/core/cache/object-cache.service.ts index 5db2d73d4e..5b0d818dd9 100644 --- a/src/app/core/cache/object-cache.service.ts +++ b/src/app/core/cache/object-cache.service.ts @@ -20,7 +20,7 @@ import { NormalizedObjectFactory } from './models/normalized-object-factory'; import { NormalizedObject } from './models/normalized-object.model'; import { applyPatch, Operation } from 'fast-json-patch'; import { AddToSSBAction } from './server-sync-buffer.actions'; -import { RestRequestMethod } from '../data//rest-request-method'; +import { RestRequestMethod } from '../data/rest-request-method'; function selfLinkFromUuidSelector(uuid: string): MemoizedSelector { return pathSelector(coreSelector, 'index', IndexName.OBJECT, uuid); diff --git a/src/app/core/cache/server-sync-buffer.actions.ts b/src/app/core/cache/server-sync-buffer.actions.ts index b164a41fd9..2399db7c4d 100644 --- a/src/app/core/cache/server-sync-buffer.actions.ts +++ b/src/app/core/cache/server-sync-buffer.actions.ts @@ -1,7 +1,7 @@ import { Action } from '@ngrx/store'; import { type } from '../../shared/ngrx/type'; -import { RestRequestMethod } from '../data//rest-request-method'; +import { RestRequestMethod } from '../data/rest-request-method'; /** * The list of ServerSyncBufferAction type definitions diff --git a/src/app/core/cache/server-sync-buffer.effects.ts b/src/app/core/cache/server-sync-buffer.effects.ts index e5ee2cf28e..8847b1d655 100644 --- a/src/app/core/cache/server-sync-buffer.effects.ts +++ b/src/app/core/cache/server-sync-buffer.effects.ts @@ -21,7 +21,7 @@ import { DSpaceRESTv2Serializer } from '../dspace-rest-v2/dspace-rest-v2.seriali import { GenericConstructor } from '../shared/generic-constructor'; import { hasValue } from '../../shared/empty.util'; import { Observable } from 'rxjs/internal/Observable'; -import { RestRequestMethod } from '../data//rest-request-method'; +import { RestRequestMethod } from '../data/rest-request-method'; @Injectable() export class ServerSyncBufferEffects { diff --git a/src/app/core/cache/server-sync-buffer.reducer.ts b/src/app/core/cache/server-sync-buffer.reducer.ts index 3354afcd42..3e3715d186 100644 --- a/src/app/core/cache/server-sync-buffer.reducer.ts +++ b/src/app/core/cache/server-sync-buffer.reducer.ts @@ -5,7 +5,7 @@ import { ServerSyncBufferAction, ServerSyncBufferActionTypes } from './server-sync-buffer.actions'; -import { RestRequestMethod } from '../data//rest-request-method'; +import { RestRequestMethod } from '../data/rest-request-method'; /** * An entry in the ServerSyncBufferState diff --git a/src/app/core/data/request.models.ts b/src/app/core/data/request.models.ts index 42c4dd4eff..75f1aac581 100644 --- a/src/app/core/data/request.models.ts +++ b/src/app/core/data/request.models.ts @@ -9,7 +9,7 @@ import { ConfigResponseParsingService } from './config-response-parsing.service' import { AuthResponseParsingService } from '../auth/auth-response-parsing.service'; import { HttpOptions } from '../dspace-rest-v2/dspace-rest-v2.service'; import { IntegrationResponseParsingService } from '../integration/integration-response-parsing.service'; -import { RestRequestMethod } from './/rest-request-method'; +import { RestRequestMethod } from './rest-request-method'; /* tslint:disable:max-classes-per-file */ diff --git a/src/app/core/data/request.service.ts b/src/app/core/data/request.service.ts index 8728c223ea..71d0189816 100644 --- a/src/app/core/data/request.service.ts +++ b/src/app/core/data/request.service.ts @@ -18,7 +18,7 @@ import { 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 { RestRequestMethod } from './rest-request-method'; @Injectable() export class RequestService { diff --git a/src/app/core/dspace-rest-v2/dspace-rest-v2.service.ts b/src/app/core/dspace-rest-v2/dspace-rest-v2.service.ts index c8ce76a554..7173e5ba0d 100644 --- a/src/app/core/dspace-rest-v2/dspace-rest-v2.service.ts +++ b/src/app/core/dspace-rest-v2/dspace-rest-v2.service.ts @@ -1,12 +1,11 @@ import {throwError as observableThrowError, Observable } from 'rxjs'; import {catchError, map} from 'rxjs/operators'; import { Injectable } from '@angular/core'; -import { Request } from '@angular/http'; import { HttpClient, HttpHeaders, HttpParams, HttpResponse } from '@angular/common/http' import { DSpaceRESTV2Response } from './dspace-rest-v2-response.model'; import { HttpObserve } from '@angular/common/http/src/client'; -import { RestRequestMethod } from '../data//rest-request-method'; +import { RestRequestMethod } from '../data/rest-request-method'; export interface HttpOptions { body?: any; diff --git a/src/app/core/index/index.effects.ts b/src/app/core/index/index.effects.ts index 0d783767a6..b152f8488d 100644 --- a/src/app/core/index/index.effects.ts +++ b/src/app/core/index/index.effects.ts @@ -10,7 +10,7 @@ import { RequestActionTypes, RequestConfigureAction } from '../data/request.acti import { AddToIndexAction, RemoveFromIndexByValueAction } from './index.actions'; import { hasValue } from '../../shared/empty.util'; import { IndexName } from './index.reducer'; -import { RestRequestMethod } from '../data//rest-request-method'; +import { RestRequestMethod } from '../data/rest-request-method'; @Injectable() export class UUIDIndexEffects { diff --git a/src/config/auto-sync-config.interface.ts b/src/config/auto-sync-config.interface.ts index d7c5ce83c5..5285916b12 100644 --- a/src/config/auto-sync-config.interface.ts +++ b/src/config/auto-sync-config.interface.ts @@ -1,4 +1,4 @@ -import { RestRequestMethod } from '../app/core/data//rest-request-method'; +import { RestRequestMethod } from '../app/core/data/rest-request-method'; type TimePerMethod = { [method in RestRequestMethod]: number; From a2bcdfbea9104a57a51a852bfc1cda005f84edca Mon Sep 17 00:00:00 2001 From: lotte Date: Thu, 20 Sep 2018 15:24:16 +0200 Subject: [PATCH 25/48] disabled reloads --- src/app/core/auth/auth.service.ts | 7 ++++--- src/app/core/auth/server-auth.service.ts | 2 -- src/app/shared/auth-nav-menu/auth-nav-menu.component.ts | 8 ++------ 3 files changed, 6 insertions(+), 11 deletions(-) diff --git a/src/app/core/auth/auth.service.ts b/src/app/core/auth/auth.service.ts index f69dd2b58f..a7a1237e1c 100644 --- a/src/app/core/auth/auth.service.ts +++ b/src/app/core/auth/auth.service.ts @@ -245,7 +245,6 @@ export class AuthService { public getToken(): AuthTokenInfo { let token: AuthTokenInfo; this.store.select(getAuthenticationToken) - .first() .subscribe((authTokenInfo: AuthTokenInfo) => { // Retrieve authentication token info and check if is valid token = authTokenInfo || null; @@ -349,10 +348,12 @@ export class AuthService { this.router.navigated = false; const url = decodeURIComponent(redirectUrl); this.router.navigateByUrl(url); - this._window.nativeWindow.location.href = url; + /* TODO Reenable hard redirect when REST API can handle x-forwarded-for */ + // this._window.nativeWindow.location.href = url; } else { this.router.navigate(['/']); - this._window.nativeWindow.location.href = '/'; + /* TODO Reenable hard redirect when REST API can handle x-forwarded-for */ + // this._window.nativeWindow.location.href = '/'; } }) diff --git a/src/app/core/auth/server-auth.service.ts b/src/app/core/auth/server-auth.service.ts index 18eba2e92d..9030443a1e 100644 --- a/src/app/core/auth/server-auth.service.ts +++ b/src/app/core/auth/server-auth.service.ts @@ -71,10 +71,8 @@ export class ServerAuthService extends AuthService { this.router.navigated = false; const url = decodeURIComponent(redirectUrl); this.router.navigateByUrl(url); - this._window.nativeWindow.location.href = url; } else { this.router.navigate(['/']); - this._window.nativeWindow.location.href = '/'; } }) diff --git a/src/app/shared/auth-nav-menu/auth-nav-menu.component.ts b/src/app/shared/auth-nav-menu/auth-nav-menu.component.ts index c657071987..f7e1b03c88 100644 --- a/src/app/shared/auth-nav-menu/auth-nav-menu.component.ts +++ b/src/app/shared/auth-nav-menu/auth-nav-menu.component.ts @@ -62,12 +62,8 @@ export class AuthNavMenuComponent implements OnInit { this.showAuth = this.store.select(routerStateSelector) .filter((router: RouterReducerState) => isNotUndefined(router) && isNotUndefined(router.state)) .map((router: RouterReducerState) => { - const url = router.state.url; - const show = !router.state.url.startsWith(LOGIN_ROUTE) && !router.state.url.startsWith(LOGOUT_ROUTE); - if (show) { - this.authService.setRedirectUrl(url); - } - return show; + return !router.state.url.startsWith(LOGIN_ROUTE) && !router.state.url.startsWith(LOGOUT_ROUTE); + }); } } From 7db30e88090104bde234663711eca76a8efd7c05 Mon Sep 17 00:00:00 2001 From: lotte Date: Thu, 20 Sep 2018 15:37:54 +0200 Subject: [PATCH 26/48] fixed tslint error --- .../shared/auth-nav-menu/auth-nav-menu.component.spec.ts | 4 ++-- src/app/shared/auth-nav-menu/auth-nav-menu.component.ts | 8 ++++++-- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/src/app/shared/auth-nav-menu/auth-nav-menu.component.spec.ts b/src/app/shared/auth-nav-menu/auth-nav-menu.component.spec.ts index a036590ed5..e1a82f4a33 100644 --- a/src/app/shared/auth-nav-menu/auth-nav-menu.component.spec.ts +++ b/src/app/shared/auth-nav-menu/auth-nav-menu.component.spec.ts @@ -54,7 +54,7 @@ describe('AuthNavMenuComponent', () => { ], providers: [ {provide: HostWindowService, useValue: window}, - {provide: AuthService, useValue: {setRedirectUrl: () => {}}} + {provide: AuthService, useValue: {setRedirectUrl: () => { /*empty*/ }}} ], schemas: [ CUSTOM_ELEMENTS_SCHEMA @@ -224,7 +224,7 @@ describe('AuthNavMenuComponent', () => { ], providers: [ {provide: HostWindowService, useValue: window}, - {provide: AuthService, useValue: {setRedirectUrl: () => {}}} + {provide: AuthService, useValue: {setRedirectUrl: () => { /*empty*/ }}} ], schemas: [ CUSTOM_ELEMENTS_SCHEMA diff --git a/src/app/shared/auth-nav-menu/auth-nav-menu.component.ts b/src/app/shared/auth-nav-menu/auth-nav-menu.component.ts index f7e1b03c88..c657071987 100644 --- a/src/app/shared/auth-nav-menu/auth-nav-menu.component.ts +++ b/src/app/shared/auth-nav-menu/auth-nav-menu.component.ts @@ -62,8 +62,12 @@ export class AuthNavMenuComponent implements OnInit { this.showAuth = this.store.select(routerStateSelector) .filter((router: RouterReducerState) => isNotUndefined(router) && isNotUndefined(router.state)) .map((router: RouterReducerState) => { - return !router.state.url.startsWith(LOGIN_ROUTE) && !router.state.url.startsWith(LOGOUT_ROUTE); - + const url = router.state.url; + const show = !router.state.url.startsWith(LOGIN_ROUTE) && !router.state.url.startsWith(LOGOUT_ROUTE); + if (show) { + this.authService.setRedirectUrl(url); + } + return show; }); } } From 9029231396601da748ed1ee299357765d9099be9 Mon Sep 17 00:00:00 2001 From: Tim Donohue Date: Fri, 21 Sep 2018 12:02:06 -0500 Subject: [PATCH 27/48] Update version of Bootstrap per CVE-2018-14041 --- package.json | 6 +++--- yarn.lock | 14 +++++++------- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/package.json b/package.json index 0936b27ea4..b058730545 100644 --- a/package.json +++ b/package.json @@ -90,12 +90,12 @@ "@ngx-translate/http-loader": "2.0.1", "@nicky-lenaers/ngx-scroll-to": "^0.6.0", "angular-idle-preload": "2.0.4", - "angular2-moment": "^1.9.0", "angular-sortablejs": "^2.5.0", + "angular2-moment": "^1.9.0", "angular2-text-mask": "8.0.4", "angulartics2": "^5.2.0", "body-parser": "1.18.2", - "bootstrap": "4.1.1", + "bootstrap": "4.1.3", "cerialize": "0.1.18", "compression": "1.7.1", "cookie-parser": "1.4.3", @@ -112,8 +112,8 @@ "methods": "1.1.2", "moment": "^2.22.1", "morgan": "1.9.0", - "ng2-nouislider": "^1.7.11", "ng2-file-upload": "1.2.1", + "ng2-nouislider": "^1.7.11", "ngx-infinite-scroll": "0.8.2", "ngx-pagination": "3.0.3", "nouislider": "^11.0.0", diff --git a/yarn.lock b/yarn.lock index 344093d446..95cf41ac55 100644 --- a/yarn.lock +++ b/yarn.lock @@ -437,16 +437,16 @@ angular-idle-preload@2.0.4: version "2.0.4" resolved "https://registry.yarnpkg.com/angular-idle-preload/-/angular-idle-preload-2.0.4.tgz#7b177c0f52918c090e5c345480b922297cd59a0d" +angular-sortablejs@^2.5.0: + version "2.5.2" + resolved "https://registry.yarnpkg.com/angular-sortablejs/-/angular-sortablejs-2.5.2.tgz#ffd651e47cc93a191db4c023f617db3789fd9af5" + angular2-moment@^1.9.0: version "1.9.0" resolved "https://registry.yarnpkg.com/angular2-moment/-/angular2-moment-1.9.0.tgz#d198a4d9bc825f61de19106ac7ea07a78569f5a1" dependencies: moment "^2.19.3" -angular-sortablejs@^2.5.0: - version "2.5.2" - resolved "https://registry.yarnpkg.com/angular-sortablejs/-/angular-sortablejs-2.5.2.tgz#ffd651e47cc93a191db4c023f617db3789fd9af5" - angular2-template-loader@0.6.2: version "0.6.2" resolved "https://registry.yarnpkg.com/angular2-template-loader/-/angular2-template-loader-0.6.2.tgz#c0d44e90fff0fac95e8b23f043acda7fd1c51d7c" @@ -1070,9 +1070,9 @@ boom@5.x.x: dependencies: hoek "4.x.x" -bootstrap@4.1.1: - version "4.1.1" - resolved "https://registry.yarnpkg.com/bootstrap/-/bootstrap-4.1.1.tgz#3aec85000fa619085da8d2e4983dfd67cf2114cb" +bootstrap@4.1.3: + version "4.1.3" + resolved "https://registry.yarnpkg.com/bootstrap/-/bootstrap-4.1.3.tgz#0eb371af2c8448e8c210411d0cb824a6409a12be" boxen@^1.2.1: version "1.3.0" From 8c05ed86ef8e8a8d1914eeb137197463dedf13b1 Mon Sep 17 00:00:00 2001 From: lotte Date: Wed, 26 Sep 2018 15:31:26 +0200 Subject: [PATCH 28/48] intermediate bug commit --- config/environment.default.js | 2 +- .../community-page.component.html | 20 ++++++++- .../community-page.component.ts | 15 ++++++- .../search-text-filter.component.ts | 4 +- src/app/core/cache/object-cache.reducer.ts | 8 ++-- src/app/core/cache/object-cache.service.ts | 2 +- .../core/cache/server-sync-buffer.actions.ts | 2 +- .../core/cache/server-sync-buffer.effects.ts | 41 ++++++++++++------- src/config/cache-config.interface.ts | 2 +- 9 files changed, 69 insertions(+), 27 deletions(-) diff --git a/config/environment.default.js b/config/environment.default.js index 32edd1391d..42c3fc2452 100644 --- a/config/environment.default.js +++ b/config/environment.default.js @@ -24,7 +24,7 @@ module.exports = { autoSync: { defaultTime: 0, maxBufferSize: 100, - timePerMethod: {'Patch': 30} //time in seconds + timePerMethod: {'PATCH': 3} //time in seconds } }, // Form settings diff --git a/src/app/+community-page/community-page.component.html b/src/app/+community-page/community-page.component.html index 637e37af0c..ce86171370 100644 --- a/src/app/+community-page/community-page.component.html +++ b/src/app/+community-page/community-page.component.html @@ -24,9 +24,25 @@ [content]="communityPayload.copyrightText" [hasInnerHtml]="true"> - +
+
+
+ +
+ +
+ +
+
+
+
+
+
- +
diff --git a/src/app/+community-page/community-page.component.ts b/src/app/+community-page/community-page.component.ts index a6e1d5376c..5a36209c28 100644 --- a/src/app/+community-page/community-page.component.ts +++ b/src/app/+community-page/community-page.component.ts @@ -1,4 +1,4 @@ -import {mergeMap, filter, map} from 'rxjs/operators'; +import { mergeMap, filter, map, first, tap } from 'rxjs/operators'; import { ChangeDetectionStrategy, Component, OnDestroy, OnInit } from '@angular/core'; import { ActivatedRoute } from '@angular/router'; @@ -24,6 +24,9 @@ import { hasValue } from '../shared/empty.util'; export class CommunityPageComponent implements OnInit, OnDestroy { communityRD$: Observable>; logoRD$: Observable>; + href: string; + newname: string; + private subs: Subscription[] = []; constructor( @@ -40,10 +43,20 @@ export class CommunityPageComponent implements OnInit, OnDestroy { map((rd: RemoteData) => rd.payload), filter((community: Community) => hasValue(community)), mergeMap((community: Community) => community.logo)); + + this.communityRD$.pipe(first()).subscribe((crd) => { + this.href = crd.payload.self; + this.newname = crd.payload.name; + }); } ngOnDestroy(): void { this.subs.filter((sub) => hasValue(sub)).forEach((sub) => sub.unsubscribe()); } + patchIt(): void { + console.log('patching it!', this.href, this.newname); + this.communityDataService.patch(this.href, [{ op: 'replace', path: '/name', value: this.newname }]); + } + } diff --git a/src/app/+search-page/search-filters/search-filter/search-text-filter/search-text-filter.component.ts b/src/app/+search-page/search-filters/search-filter/search-text-filter/search-text-filter.component.ts index bb396a6692..fd14d6d3de 100644 --- a/src/app/+search-page/search-filters/search-filter/search-text-filter/search-text-filter.component.ts +++ b/src/app/+search-page/search-filters/search-filter/search-text-filter/search-text-filter.component.ts @@ -1,6 +1,4 @@ -import { animate, state, style, transition, trigger } from '@angular/animations'; -import { Component, HostBinding, OnInit } from '@angular/core'; -import { Observable } from 'rxjs'; +import { Component, OnInit } from '@angular/core'; import { FilterType } from '../../../search-service/filter-type.model'; import { facetLoad, diff --git a/src/app/core/cache/object-cache.reducer.ts b/src/app/core/cache/object-cache.reducer.ts index adea46bc57..f856b57892 100644 --- a/src/app/core/cache/object-cache.reducer.ts +++ b/src/app/core/cache/object-cache.reducer.ts @@ -182,8 +182,10 @@ function addPatchObjectCache(state: ObjectCacheState, action: AddPatchObjectCach const newState = Object.assign({}, state); if (hasValue(newState[uuid])) { const patches = newState[uuid].patches; - newState[uuid].patches = [...patches, {operations} as Patch]; - newState[uuid].isDirty = true; + newState[uuid] = Object.assign({}, newState[uuid], { + patches: [...patches, { operations } as Patch], + isDirty: true + }); } return newState; } @@ -203,7 +205,7 @@ function applyPatchObjectCache(state: ObjectCacheState, action: ApplyPatchObject const newState = Object.assign({}, state); if (hasValue(newState[uuid])) { // flatten two dimensional array - const flatPatch: Operation[] = [].concat(...newState[uuid].patches); + const flatPatch: Operation[] = [].concat(...newState[uuid].patches.map((patch) => patch.operations)); const newData = applyPatch( newState[uuid].data, flatPatch); newState[uuid].data = newData.newDocument; newState[uuid].patches = []; diff --git a/src/app/core/cache/object-cache.service.ts b/src/app/core/cache/object-cache.service.ts index 5b0d818dd9..f60b2de684 100644 --- a/src/app/core/cache/object-cache.service.ts +++ b/src/app/core/cache/object-cache.service.ts @@ -91,7 +91,7 @@ export class ObjectCacheService { getBySelfLink(selfLink: string): Observable { return this.getEntry(selfLink).pipe( map((entry: ObjectCacheEntry) => { - const flatPatch: Operation[] = [].concat(...entry.patches); + const flatPatch: Operation[] = [].concat(...entry.patches.map((patch) => patch.operations)); const patchedData = applyPatch(entry.data, flatPatch).newDocument; return Object.assign({}, entry, { data: patchedData }); } diff --git a/src/app/core/cache/server-sync-buffer.actions.ts b/src/app/core/cache/server-sync-buffer.actions.ts index 2399db7c4d..69eb81b02f 100644 --- a/src/app/core/cache/server-sync-buffer.actions.ts +++ b/src/app/core/cache/server-sync-buffer.actions.ts @@ -31,7 +31,7 @@ export class AddToSSBAction implements Action { * the unique href of the cached object entry that should be updated */ constructor(href: string, method: RestRequestMethod) { - this.payload = { href, method: undefined }; + this.payload = { href, method: method }; } } diff --git a/src/app/core/cache/server-sync-buffer.effects.ts b/src/app/core/cache/server-sync-buffer.effects.ts index 8847b1d655..1211740ffe 100644 --- a/src/app/core/cache/server-sync-buffer.effects.ts +++ b/src/app/core/cache/server-sync-buffer.effects.ts @@ -1,4 +1,4 @@ -import { delay, exhaustMap, first, map, switchMap, tap } from 'rxjs/operators'; +import { delay, exhaustMap, first, map, startWith, switchMap, tap } from 'rxjs/operators'; import { Inject, Injectable } from '@angular/core'; import { Actions, Effect, ofType } from '@ngrx/effects'; import { @@ -9,17 +9,17 @@ import { } from './server-sync-buffer.actions'; import { GLOBAL_CONFIG } from '../../../config'; import { GlobalConfig } from '../../../config/global-config.interface'; -import { CoreState } from '../core.reducers'; -import { Action, select, Store } from '@ngrx/store'; +import { coreSelector, CoreState } from '../core.reducers'; +import { Action, createSelector, MemoizedSelector, select, Store } from '@ngrx/store'; import { ServerSyncBufferEntry, ServerSyncBufferState } from './server-sync-buffer.reducer'; -import { of as observableOf, combineLatest as observableCombineLatest } from 'rxjs'; +import { of as observableOf, combineLatest as observableCombineLatest, empty as observableEmpty } from 'rxjs'; import { RequestService } from '../data/request.service'; import { PutRequest } from '../data/request.models'; import { ObjectCacheService } from './object-cache.service'; import { ApplyPatchObjectCacheAction } from './object-cache.actions'; import { DSpaceRESTv2Serializer } from '../dspace-rest-v2/dspace-rest-v2.serializer'; import { GenericConstructor } from '../shared/generic-constructor'; -import { hasValue } from '../../shared/empty.util'; +import { hasValue, isNotEmpty, isNotUndefined } from '../../shared/empty.util'; import { Observable } from 'rxjs/internal/Observable'; import { RestRequestMethod } from '../data/rest-request-method'; @@ -29,9 +29,8 @@ export class ServerSyncBufferEffects { .pipe( ofType(ServerSyncBufferActionTypes.ADD), exhaustMap((action: AddToSSBAction) => { - // const autoSyncConfig = this.EnvConfig.cache.autoSync; - // const timeoutInSeconds = autoSyncConfig.timePerMethod[action.type] || autoSyncConfig.defaultTime; - const timeoutInSeconds = 0; + const autoSyncConfig = this.EnvConfig.cache.autoSync; + const timeoutInSeconds = autoSyncConfig.timePerMethod[action.payload.method] || autoSyncConfig.defaultTime; return observableOf(new CommitSSBAction(action.payload.method)).pipe(delay(timeoutInSeconds * 1000)) }) ); @@ -41,7 +40,7 @@ export class ServerSyncBufferEffects { ofType(ServerSyncBufferActionTypes.COMMIT), switchMap((action: CommitSSBAction) => { return this.store.pipe( - select(serverSyncBufferSelector), + select(serverSyncBufferSelector()), map((bufferState: ServerSyncBufferState) => { const actions: Array> = bufferState.buffer .filter((entry: ServerSyncBufferEntry) => { @@ -54,29 +53,41 @@ export class ServerSyncBufferEffects { }) .map((entry: ServerSyncBufferEntry) => { if (entry.method === RestRequestMethod.PATCH) { + console.log(this.applyPatch(entry.href)); return this.applyPatch(entry.href); } else { /* TODO other request stuff */ } }); + console.log(actions); /* Add extra action to array, to make sure the ServerSyncBuffer is emptied afterwards */ - return observableCombineLatest(actions).pipe( - map((array) => array.push(new EmptySSBAction(action.payload))) - ); + if (isNotEmpty(actions) && isNotUndefined(actions[0])) { + return observableCombineLatest(...actions).pipe( + map((array) => { + console.log(array); + return array.push(new EmptySSBAction(action.payload)); + }) + ); + } else { + return { type:'NO_ACTION' }; + } }) ) }) ); + private applyPatch(href: string): Observable { const patchObject = this.objectCache.getBySelfLink(href); - return patchObject.pipe( + const test = patchObject.pipe( map((object) => { const serializedObject = new DSpaceRESTv2Serializer(object.constructor as GenericConstructor<{}>).serialize(object); this.requestService.configure(new PutRequest(this.requestService.generateRequestId(), href, serializedObject)); + console.log(new ApplyPatchObjectCacheAction(href)); return new ApplyPatchObjectCacheAction(href) }) ) + return test; } constructor(private actions$: Actions, @@ -88,4 +99,6 @@ export class ServerSyncBufferEffects { } } -export const serverSyncBufferSelector = (state: CoreState) => state['cache/syncbuffer']; +export function serverSyncBufferSelector(): MemoizedSelector { + return createSelector(coreSelector, (state: CoreState) => state['cache/syncbuffer']); +} diff --git a/src/config/cache-config.interface.ts b/src/config/cache-config.interface.ts index b8651ed107..3e9334e300 100644 --- a/src/config/cache-config.interface.ts +++ b/src/config/cache-config.interface.ts @@ -4,5 +4,5 @@ import { AutoSyncConfig } from './auto-sync-config.interface'; export interface CacheConfig extends Config { msToLive: number, control: string, - // autoSync: AutoSyncConfig + autoSync: AutoSyncConfig } From bfc70f4f881d22366410df0e8f47ed629adb8d2d Mon Sep 17 00:00:00 2001 From: lotte Date: Thu, 27 Sep 2018 10:37:40 +0200 Subject: [PATCH 29/48] Added links to issues --- src/app/core/auth/auth.service.ts | 6 ++++-- src/app/core/data/base-response-parsing.service.ts | 3 ++- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/src/app/core/auth/auth.service.ts b/src/app/core/auth/auth.service.ts index a7a1237e1c..5f113b0262 100644 --- a/src/app/core/auth/auth.service.ts +++ b/src/app/core/auth/auth.service.ts @@ -137,6 +137,8 @@ export class AuthService { if (status.authenticated) { // TODO this should be cleaned up, AuthStatus could be parsed by the RemoteDataService as a whole... + // Review when https://jira.duraspace.org/browse/DS-4006 is fixed + // See https://github.com/DSpace/dspace-angular/issues/292 const person$ = this.rdbService.buildSingle(status.eperson.toString()); return person$.pipe(map((eperson) => eperson.payload)); } else { @@ -348,11 +350,11 @@ export class AuthService { this.router.navigated = false; const url = decodeURIComponent(redirectUrl); this.router.navigateByUrl(url); - /* TODO Reenable hard redirect when REST API can handle x-forwarded-for */ + /* TODO Reenable hard redirect when REST API can handle x-forwarded-for, see https://github.com/DSpace/DSpace/pull/2207 */ // this._window.nativeWindow.location.href = url; } else { this.router.navigate(['/']); - /* TODO Reenable hard redirect when REST API can handle x-forwarded-for */ + /* TODO Reenable hard redirect when REST API can handle x-forwarded-for, see https://github.com/DSpace/DSpace/pull/2207 */ // this._window.nativeWindow.location.href = '/'; } }) diff --git a/src/app/core/data/base-response-parsing.service.ts b/src/app/core/data/base-response-parsing.service.ts index bdd18f8a61..fdf5b4eb97 100644 --- a/src/app/core/data/base-response-parsing.service.ts +++ b/src/app/core/data/base-response-parsing.service.ts @@ -150,7 +150,8 @@ export abstract class BaseResponseParsingService { return obj[keys[0]]; } - /* TODO remove when REST response for epersons is fixed */ + // TODO Remove when https://jira.duraspace.org/browse/DS-4006 is fixed + // See https://github.com/DSpace/dspace-angular/issues/292 private fixBadEPersonRestResponse(obj: any): any { if (obj.type === ResourceType.EPerson) { const groups = obj.groups; From 1680f67744832dbb7ee9bbcbf2cdf96ea14048dd Mon Sep 17 00:00:00 2001 From: lotte Date: Thu, 27 Sep 2018 16:56:27 +0200 Subject: [PATCH 30/48] finalized put/patch requests --- .../collection-page.component.html | 14 ++++++++++ .../collection-page.component.ts | 13 ++++++++- .../community-page.component.html | 14 ---------- .../community-page.component.ts | 13 ++------- .../auth-response-parsing.service.spec.ts | 4 +-- src/app/core/auth/auth.service.ts | 1 - src/app/core/auth/models/auth-status.model.ts | 2 +- src/app/core/cache/object-cache.reducer.ts | 8 +++--- src/app/core/cache/object-cache.service.ts | 10 +++---- .../core/cache/server-sync-buffer.effects.ts | 28 ++++++++----------- .../mocks/mock-remote-data-build.service.ts | 7 ++--- src/app/shared/mocks/mock-store.ts | 4 --- src/app/shared/services/route.service.ts | 2 +- .../testing/auth-request-service-stub.ts | 4 +-- 14 files changed, 59 insertions(+), 65 deletions(-) diff --git a/src/app/+collection-page/collection-page.component.html b/src/app/+collection-page/collection-page.component.html index a233163070..90ae0cdf4c 100644 --- a/src/app/+collection-page/collection-page.component.html +++ b/src/app/+collection-page/collection-page.component.html @@ -33,6 +33,20 @@ [content]="collection.license" [title]="'collection.page.license'"> +
+
+
+ +
+ +
+ +
+
+
+
+
diff --git a/src/app/+collection-page/collection-page.component.ts b/src/app/+collection-page/collection-page.component.ts index 59cf83777f..95aa8ddc4a 100644 --- a/src/app/+collection-page/collection-page.component.ts +++ b/src/app/+collection-page/collection-page.component.ts @@ -15,7 +15,7 @@ import { Item } from '../core/shared/item.model'; import { fadeIn, fadeInOut } from '../shared/animations/fade'; import { hasValue, isNotEmpty } from '../shared/empty.util'; import { PaginationComponentOptions } from '../shared/pagination/pagination-component-options.model'; -import { filter, flatMap, map } from 'rxjs/operators'; +import { filter, first, flatMap, map } from 'rxjs/operators'; import { SearchService } from '../+search-page/search-service/search.service'; import { PaginatedSearchOptions } from '../+search-page/paginated-search-options.model'; import { toDSpaceObjectListRD } from '../core/shared/operators'; @@ -39,6 +39,8 @@ export class CollectionPageComponent implements OnInit, OnDestroy { sortConfig: SortOptions; private subs: Subscription[] = []; private collectionId: string; + href: string; + newname: string; constructor( private collectionDataService: CollectionDataService, @@ -77,6 +79,10 @@ export class CollectionPageComponent implements OnInit, OnDestroy { }); }) ); + this.collectionRD$.pipe(first()).subscribe((crd) => { + this.href = crd.payload.self; + this.newname = crd.payload.name; + }); } updatePage(searchOptions) { @@ -109,4 +115,9 @@ export class CollectionPageComponent implements OnInit, OnDestroy { } }) } + + patchIt(): void { + console.log('patching it!', this.href, this.newname); + this.collectionDataService.patch(this.href, [{ op: 'replace', path: '/name', value: this.newname }]); + } } diff --git a/src/app/+community-page/community-page.component.html b/src/app/+community-page/community-page.component.html index ce86171370..1bf322a688 100644 --- a/src/app/+community-page/community-page.component.html +++ b/src/app/+community-page/community-page.component.html @@ -24,20 +24,6 @@ [content]="communityPayload.copyrightText" [hasInnerHtml]="true"> -
-
-
- -
- -
- -
-
-
-
-
diff --git a/src/app/+community-page/community-page.component.ts b/src/app/+community-page/community-page.component.ts index 5a36209c28..ce260aefc0 100644 --- a/src/app/+community-page/community-page.component.ts +++ b/src/app/+community-page/community-page.component.ts @@ -24,8 +24,7 @@ import { hasValue } from '../shared/empty.util'; export class CommunityPageComponent implements OnInit, OnDestroy { communityRD$: Observable>; logoRD$: Observable>; - href: string; - newname: string; + private subs: Subscription[] = []; @@ -44,19 +43,13 @@ export class CommunityPageComponent implements OnInit, OnDestroy { filter((community: Community) => hasValue(community)), mergeMap((community: Community) => community.logo)); - this.communityRD$.pipe(first()).subscribe((crd) => { - this.href = crd.payload.self; - this.newname = crd.payload.name; - }); + } ngOnDestroy(): void { this.subs.filter((sub) => hasValue(sub)).forEach((sub) => sub.unsubscribe()); } - patchIt(): void { - console.log('patching it!', this.href, this.newname); - this.communityDataService.patch(this.href, [{ op: 'replace', path: '/name', value: this.newname }]); - } + } diff --git a/src/app/core/auth/auth-response-parsing.service.spec.ts b/src/app/core/auth/auth-response-parsing.service.spec.ts index f6dd87e99a..4622d885c1 100644 --- a/src/app/core/auth/auth-response-parsing.service.spec.ts +++ b/src/app/core/auth/auth-response-parsing.service.spec.ts @@ -8,13 +8,13 @@ import { CoreState } from '../core.reducers'; import { AuthStatus } from './models/auth-status.model'; import { AuthResponseParsingService } from './auth-response-parsing.service'; import { AuthGetRequest, AuthPostRequest } from '../data/request.models'; -import { getMockStore } from '../../shared/mocks/mock-store'; +// import { getMockStore } from '../../shared/mocks/mock-store'; describe('AuthResponseParsingService', () => { let service: AuthResponseParsingService; const EnvConfig = {cache: {msToLive: 1000}} as GlobalConfig; - const store = getMockStore() as Store; + const store = {} as Store; const objectCacheService = new ObjectCacheService(store); beforeEach(() => { diff --git a/src/app/core/auth/auth.service.ts b/src/app/core/auth/auth.service.ts index ec65e3a060..42178d721d 100644 --- a/src/app/core/auth/auth.service.ts +++ b/src/app/core/auth/auth.service.ts @@ -17,7 +17,6 @@ import { REQUEST } from '@nguniversal/express-engine/tokens'; import { RouterReducerState } from '@ngrx/router-store'; import { select, Store } from '@ngrx/store'; import { CookieAttributes } from 'js-cookie'; -import { Observable } from 'rxjs/Observable'; import { EPerson } from '../eperson/models/eperson.model'; import { AuthRequestService } from './auth-request.service'; diff --git a/src/app/core/auth/models/auth-status.model.ts b/src/app/core/auth/models/auth-status.model.ts index b8ccf9ed6d..4cb4bd530e 100644 --- a/src/app/core/auth/models/auth-status.model.ts +++ b/src/app/core/auth/models/auth-status.model.ts @@ -2,7 +2,7 @@ import { AuthError } from './auth-error.model'; import { AuthTokenInfo } from './auth-token-info.model'; import { EPerson } from '../../eperson/models/eperson.model'; import { RemoteData } from '../../data/remote-data'; -import { Observable } from 'rxjs/Observable'; +import { Observable } from 'rxjs/internal/Observable'; export class AuthStatus { diff --git a/src/app/core/cache/object-cache.reducer.ts b/src/app/core/cache/object-cache.reducer.ts index f856b57892..4424bb2142 100644 --- a/src/app/core/cache/object-cache.reducer.ts +++ b/src/app/core/cache/object-cache.reducer.ts @@ -21,6 +21,7 @@ export interface Patch { uuid?: string; operations: Operation[]; } + /**conca * An interface to represent objects that can be cached * @@ -119,7 +120,7 @@ function addToObjectCache(state: ObjectCacheState, action: AddToObjectCacheActio timeAdded: action.payload.timeAdded, msToLive: action.payload.msToLive, requestHref: action.payload.requestHref, - isDirty: false, + isDirty: (hasValue(existing) ? isNotEmpty(existing.patches) : false), patches: (hasValue(existing) ? existing.patches : []) } }); @@ -206,9 +207,8 @@ function applyPatchObjectCache(state: ObjectCacheState, action: ApplyPatchObject if (hasValue(newState[uuid])) { // flatten two dimensional array const flatPatch: Operation[] = [].concat(...newState[uuid].patches.map((patch) => patch.operations)); - const newData = applyPatch( newState[uuid].data, flatPatch); - newState[uuid].data = newData.newDocument; - newState[uuid].patches = []; + const newData = applyPatch(newState[uuid].data, flatPatch, undefined, false); + newState[uuid] = Object.assign({}, newState[uuid], { data: newData.newDocument, patches: [] }); } return newState; } diff --git a/src/app/core/cache/object-cache.service.ts b/src/app/core/cache/object-cache.service.ts index f60b2de684..909a160068 100644 --- a/src/app/core/cache/object-cache.service.ts +++ b/src/app/core/cache/object-cache.service.ts @@ -1,6 +1,6 @@ import { combineLatest as observableCombineLatest, Observable } from 'rxjs'; -import { distinctUntilChanged, filter, first, map, mergeMap } from 'rxjs/operators'; +import { distinctUntilChanged, filter, first, map, mergeMap, } from 'rxjs/operators'; import { Injectable } from '@angular/core'; import { MemoizedSelector, select, Store } from '@ngrx/store'; import { IndexName } from '../index/index.reducer'; @@ -18,9 +18,10 @@ import { coreSelector, CoreState } from '../core.reducers'; import { pathSelector } from '../shared/selectors'; import { NormalizedObjectFactory } from './models/normalized-object-factory'; import { NormalizedObject } from './models/normalized-object.model'; -import { applyPatch, Operation } from 'fast-json-patch'; +import { applyPatch, applyReducer, Operation } from 'fast-json-patch'; import { AddToSSBAction } from './server-sync-buffer.actions'; import { RestRequestMethod } from '../data/rest-request-method'; +import { ReplaceOperation } from 'fast-json-patch/lib/core'; function selfLinkFromUuidSelector(uuid: string): MemoizedSelector { return pathSelector(coreSelector, 'index', IndexName.OBJECT, uuid); @@ -92,7 +93,7 @@ export class ObjectCacheService { return this.getEntry(selfLink).pipe( map((entry: ObjectCacheEntry) => { const flatPatch: Operation[] = [].concat(...entry.patches.map((patch) => patch.operations)); - const patchedData = applyPatch(entry.data, flatPatch).newDocument; + const patchedData = applyPatch(entry.data, flatPatch, undefined, false).newDocument; return Object.assign({}, entry, { data: patchedData }); } ), @@ -114,7 +115,7 @@ export class ObjectCacheService { getRequestHrefBySelfLink(selfLink: string): Observable { return this.getEntry(selfLink).pipe( map((entry: ObjectCacheEntry) => entry.requestHref), - distinctUntilChanged(),); + distinctUntilChanged()); } getRequestHrefByUUID(uuid: string): Observable { @@ -211,7 +212,6 @@ export class ObjectCacheService { } - /** * Add operations to the existing list of operations for an ObjectCacheEntry * Makes sure the ServerSyncBuffer for this ObjectCacheEntry is updated diff --git a/src/app/core/cache/server-sync-buffer.effects.ts b/src/app/core/cache/server-sync-buffer.effects.ts index 1211740ffe..d5988cb839 100644 --- a/src/app/core/cache/server-sync-buffer.effects.ts +++ b/src/app/core/cache/server-sync-buffer.effects.ts @@ -1,4 +1,4 @@ -import { delay, exhaustMap, first, map, startWith, switchMap, tap } from 'rxjs/operators'; +import { delay, exhaustMap, first, map, switchMap } from 'rxjs/operators'; import { Inject, Injectable } from '@angular/core'; import { Actions, Effect, ofType } from '@ngrx/effects'; import { @@ -12,7 +12,7 @@ import { GlobalConfig } from '../../../config/global-config.interface'; import { coreSelector, CoreState } from '../core.reducers'; import { Action, createSelector, MemoizedSelector, select, Store } from '@ngrx/store'; import { ServerSyncBufferEntry, ServerSyncBufferState } from './server-sync-buffer.reducer'; -import { of as observableOf, combineLatest as observableCombineLatest, empty as observableEmpty } from 'rxjs'; +import { combineLatest as observableCombineLatest, of as observableOf } from 'rxjs'; import { RequestService } from '../data/request.service'; import { PutRequest } from '../data/request.models'; import { ObjectCacheService } from './object-cache.service'; @@ -41,7 +41,7 @@ export class ServerSyncBufferEffects { switchMap((action: CommitSSBAction) => { return this.store.pipe( select(serverSyncBufferSelector()), - map((bufferState: ServerSyncBufferState) => { + switchMap((bufferState: ServerSyncBufferState) => { const actions: Array> = bufferState.buffer .filter((entry: ServerSyncBufferEntry) => { /* If there's a request method, filter @@ -53,41 +53,37 @@ export class ServerSyncBufferEffects { }) .map((entry: ServerSyncBufferEntry) => { if (entry.method === RestRequestMethod.PATCH) { - console.log(this.applyPatch(entry.href)); return this.applyPatch(entry.href); } else { /* TODO other request stuff */ } }); - console.log(actions); + /* Add extra action to array, to make sure the ServerSyncBuffer is emptied afterwards */ if (isNotEmpty(actions) && isNotUndefined(actions[0])) { return observableCombineLatest(...actions).pipe( - map((array) => { - console.log(array); - return array.push(new EmptySSBAction(action.payload)); - }) - ); + switchMap((array) => [...array, new EmptySSBAction(action.payload)]) + ); } else { - return { type:'NO_ACTION' }; + return observableOf({ type: 'NO_ACTION' }); } }) ) }) ); - private applyPatch(href: string): Observable { - const patchObject = this.objectCache.getBySelfLink(href); - const test = patchObject.pipe( + const patchObject = this.objectCache.getBySelfLink(href).pipe(first()); + + return patchObject.pipe( map((object) => { const serializedObject = new DSpaceRESTv2Serializer(object.constructor as GenericConstructor<{}>).serialize(object); + this.requestService.configure(new PutRequest(this.requestService.generateRequestId(), href, serializedObject)); - console.log(new ApplyPatchObjectCacheAction(href)); + return new ApplyPatchObjectCacheAction(href) }) ) - return test; } constructor(private actions$: Actions, diff --git a/src/app/shared/mocks/mock-remote-data-build.service.ts b/src/app/shared/mocks/mock-remote-data-build.service.ts index 7308051c85..33d273e1ef 100644 --- a/src/app/shared/mocks/mock-remote-data-build.service.ts +++ b/src/app/shared/mocks/mock-remote-data-build.service.ts @@ -1,11 +1,10 @@ -import { Observable } from 'rxjs'; -import { map, take } from 'rxjs/operators'; +import { Observable, of as observableOf } from 'rxjs'; +import { map } from 'rxjs/operators'; import { RemoteDataBuildService } from '../../core/cache/builders/remote-data-build.service'; import { ResponseCacheEntry } from '../../core/cache/response-cache.reducer'; import { RemoteData } from '../../core/data/remote-data'; import { RequestEntry } from '../../core/data/request.reducer'; import { hasValue } from '../empty.util'; -import { NormalizedObject } from '../../core/cache/models/normalized-object.model'; export function getMockRemoteDataBuildService(toRemoteDataObservable$?: Observable>): RemoteDataBuildService { return { @@ -19,7 +18,7 @@ export function getMockRemoteDataBuildService(toRemoteDataObservable$?: Observab } as RemoteData))) } }, - buildSingle: (href$: string | Observable) => Observable.of(new RemoteData(false, false, true, undefined, {})) + buildSingle: (href$: string | Observable) => observableOf(new RemoteData(false, false, true, undefined, {})) } as RemoteDataBuildService; } diff --git a/src/app/shared/mocks/mock-store.ts b/src/app/shared/mocks/mock-store.ts index 7a6ca772f2..e69de29bb2 100644 --- a/src/app/shared/mocks/mock-store.ts +++ b/src/app/shared/mocks/mock-store.ts @@ -1,4 +0,0 @@ -import { Store } from '@ngrx/store'; -import { of as observableOf } from 'rxjs'; - - diff --git a/src/app/shared/services/route.service.ts b/src/app/shared/services/route.service.ts index d72367c977..9dd9a0f164 100644 --- a/src/app/shared/services/route.service.ts +++ b/src/app/shared/services/route.service.ts @@ -52,6 +52,6 @@ export class RouteService { }); return params; }), - distinctUntilChanged((a, b) => JSON.stringify(a) === JSON.stringify(b)),); + distinctUntilChanged((a, b) => JSON.stringify(a) === JSON.stringify(b))); } } diff --git a/src/app/shared/testing/auth-request-service-stub.ts b/src/app/shared/testing/auth-request-service-stub.ts index a7ff7dcd53..ae58fd27fa 100644 --- a/src/app/shared/testing/auth-request-service-stub.ts +++ b/src/app/shared/testing/auth-request-service-stub.ts @@ -27,7 +27,7 @@ export class AuthRequestServiceStub { if (this.validateToken(token)) { authStatusStub.authenticated = true; authStatusStub.token = this.mockTokenInfo; - authStatusStub.eperson = Observable.of(new RemoteData(false, false, true, undefined, this.mockUser)); + authStatusStub.eperson = observableOf(new RemoteData(false, false, true, undefined, this.mockUser)); } else { authStatusStub.authenticated = false; } @@ -46,7 +46,7 @@ export class AuthRequestServiceStub { if (this.validateToken(token)) { authStatusStub.authenticated = true; authStatusStub.token = this.mockTokenInfo; - authStatusStub.eperson = Observable.of(new RemoteData(false, false, true, undefined, this.mockUser)); + authStatusStub.eperson = observableOf(new RemoteData(false, false, true, undefined, this.mockUser)); } else { authStatusStub.authenticated = false; } From b308df201d9b09d3516dd6eb913372acb34d8dc7 Mon Sep 17 00:00:00 2001 From: Art Lowel Date: Fri, 28 Sep 2018 16:11:22 +0200 Subject: [PATCH 31/48] add responseMsToLive to requests --- config/environment.default.js | 5 ++++- src/app/core/data/base-response-parsing.service.ts | 2 +- src/app/core/data/request.effects.ts | 2 +- src/app/core/data/request.models.ts | 8 +++++--- src/config/cache-config.interface.ts | 5 ++++- 5 files changed, 15 insertions(+), 7 deletions(-) diff --git a/config/environment.default.js b/config/environment.default.js index a6ef738f41..75be454c88 100644 --- a/config/environment.default.js +++ b/config/environment.default.js @@ -18,7 +18,10 @@ module.exports = { // Caching settings cache: { // NOTE: how long should objects be cached for by default - msToLive: 15 * 60 * 1000, // 15 minutes + msToLive: { + default: 15 * 60 * 1000, // 15 minutes + exportToZip: 5 * 1000 // 5 seconds + }, // msToLive: 1000, // 15 minutes control: 'max-age=60' // revalidate browser }, diff --git a/src/app/core/data/base-response-parsing.service.ts b/src/app/core/data/base-response-parsing.service.ts index fdf5b4eb97..563b965cb1 100644 --- a/src/app/core/data/base-response-parsing.service.ts +++ b/src/app/core/data/base-response-parsing.service.ts @@ -126,7 +126,7 @@ export abstract class BaseResponseParsingService { if (hasNoValue(co) || hasNoValue(co.self)) { throw new Error('The server returned an invalid object'); } - this.objectCache.add(co, this.EnvConfig.cache.msToLive, requestHref); + this.objectCache.add(co, this.EnvConfig.cache.msToLive.default, requestHref); } processPageInfo(payload: any): PageInfo { diff --git a/src/app/core/data/request.effects.ts b/src/app/core/data/request.effects.ts index 5fadd316f4..b7cd685690 100644 --- a/src/app/core/data/request.effects.ts +++ b/src/app/core/data/request.effects.ts @@ -23,7 +23,7 @@ import { catchError, flatMap, map, take, tap } from 'rxjs/operators'; export const addToResponseCacheAndCompleteAction = (request: RestRequest, responseCache: ResponseCacheService, envConfig: GlobalConfig) => (source: Observable): Observable => source.pipe( - tap((response: RestResponse) => responseCache.add(request.href, response, envConfig.cache.msToLive)), + tap((response: RestResponse) => responseCache.add(request.href, response, request.responseMsToLive ? request.responseMsToLive : envConfig.cache.msToLive.default)), map((response: RestResponse) => new RequestCompleteAction(request.uuid)) ); diff --git a/src/app/core/data/request.models.ts b/src/app/core/data/request.models.ts index b87f9cefc8..da2668fbbd 100644 --- a/src/app/core/data/request.models.ts +++ b/src/app/core/data/request.models.ts @@ -41,7 +41,8 @@ export abstract class RestRequest { public href: string, public method: RestRequestMethod = RestRequestMethod.Get, public body?: any, - public options?: HttpOptions + public options?: HttpOptions, + public responseMsToLive?: number ) { } @@ -55,9 +56,10 @@ export class GetRequest extends RestRequest { public uuid: string, public href: string, public body?: any, - public options?: HttpOptions + public options?: HttpOptions, + public responseMsToLive?: number ) { - super(uuid, href, RestRequestMethod.Get, body) + super(uuid, href, RestRequestMethod.Get, body, options, responseMsToLive) } } diff --git a/src/config/cache-config.interface.ts b/src/config/cache-config.interface.ts index f8a2c88640..2ca54e1401 100644 --- a/src/config/cache-config.interface.ts +++ b/src/config/cache-config.interface.ts @@ -1,6 +1,9 @@ import { Config } from './config.interface'; export interface CacheConfig extends Config { - msToLive: number, + msToLive: { + default: number; + exportToZip: number; + }, control: string } From 031c4c0cf5565d1da0c84c7af92182465434a366 Mon Sep 17 00:00:00 2001 From: Bram Luyten Date: Thu, 4 Oct 2018 07:03:49 +0200 Subject: [PATCH 32/48] Dutch translation --- resources/i18n/nl.json | 277 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 277 insertions(+) create mode 100644 resources/i18n/nl.json diff --git a/resources/i18n/nl.json b/resources/i18n/nl.json new file mode 100644 index 0000000000..6c3b1fe401 --- /dev/null +++ b/resources/i18n/nl.json @@ -0,0 +1,277 @@ +{ + "footer": { + "copyright": "copyright © 2002-{{ year }}", + "link.dspace": "DSpace software", + "link.duraspace": "DuraSpace" + }, + "collection": { + "page": { + "news": "Nieuws", + "license": "Licentie", + "browse": { + "recent": { + "head": "Recent toegevoegd" + } + } + } + }, + "community": { + "page": { + "news": "Nieuws", + "license": "Licentie" + }, + "sub-collection-list": { + "head": "Collecties in deze Community" + } + }, + "item": { + "page": { + "author": "Auteur", + "abstract": "Abstract", + "date": "Datum", + "uri": "URI", + "files": "Bestanden", + "collections": "Collecties", + "filesection": { + "download": "Download", + "name": "Naam:", + "format": "Formaat:", + "size": "Grootte:", + "description": "Beschrijving:" + }, + "link": { + "simple": "Eenvoudige item weergave", + "full": "Volledige item weergave" + } + } + }, + "nav": { + "home": "Home", + "login": "Log In", + "logout": "Log Uit" + }, + "pagination": { + "results-per-page": "Resultaten per pagina", + "sort-direction": "Sorteer mogelijkheden", + "showing": { + "label": "Getoonde items ", + "detail": "{{ range }} tot {{ total }}" + } + }, + "sorting": { + "score": { + "DESC": "Relevantie" + }, + "dc.title": { + "ASC": "Oplopend op titel", + "DESC": "Aflopend op titel" + } + }, + "title": "DSpace", + "404": { + "help": "De pagina die u zoekt kan niet gevonden worden. De pagina werd mogelijk verplaatst of verwijderd. U kan onderstaande knop gebruiken om terug naar de homepagina te gaan. ", + "page-not-found": "Pagina niet gevonden", + "link": { + "home-page": "Terug naar de homepagina" + } + }, + "home": { + "title": "DSpace Angular :: Home", + "description": "", + "top-level-communities": { + "head": "Communities in DSpace", + "help": "Selecteer een community om diens collecties te verkennen." + } + }, + "search": { + "title": "DSpace Angular :: Zoek", + "description": "", + "form": { + "search": "Zoek", + "search_dspace": "Zoek in DSpace" + }, + "results": { + "head": "Zoekresultaten", + "no-results": "Er waren geen resultaten voor deze zoekopdracht" + }, + "sidebar": { + "close": "Terug naar de resultaten", + "open": "Zoek Tools", + "results": "resultaten", + "filters": { + "title": "Filters" + }, + "settings": { + "title": "Instellingen", + "sort-by": "Sorteer volgens", + "rpp": "Resultaten per pagina" + } + }, + "view-switch": { + "show-list": "Toon als lijst", + "show-grid": "Toon in raster" + }, + "filters": { + "head": "Filters", + "reset": "Filters verwijderen", + "applied": { + "f.author": "Auteur", + "f.dateIssued.min": "Start datum", + "f.dateIssued.max": "Eind datum", + "f.subject": "Sleutelwoord", + "f.has_content_in_original_bundle": "Heeft bestanden" + }, + "filter": { + "show-more": "Toon meer", + "show-less": "Inklappen", + "author": { + "placeholder": "Auteursnaam", + "head": "Auteur" + }, + "scope": { + "placeholder": "Bereik filter", + "head": "Bereik" + }, + "subject": { + "placeholder": "Onderwerp", + "head": "Onderwerp" + }, + "dateIssued": { + "max": { + "placeholder": "Vroegste Datum" + }, + "min": { + "placeholder": "Laatste Datum" + }, + "head": "Datum" + }, + "has_content_in_original_bundle": { + "head": "Heeft bestanden" + } + } + } + }, + "browse": { + "title": "Verken {{ collection }} volgens {{ field }} {{ value }}" + }, + "admin": { + "registries": { + "metadata": { + "title": "DSpace Angular :: Metadata Register", + "head": "Metadata Register", + "description": "Het metadata register omvat de lijst van alle metadata velden die beschikbaar zijn in het systeem. Deze velden kunnen verspreid zijn over verschillende metadata schema's. Het qualified Dublin Core schema (dc) is een verplicht schema en kan niet worden verwijderd.", + "schemas": { + "table": { + "id": "ID", + "namespace": "Naamruimte", + "name": "Naam" + }, + "no-items": "Er kunnen geen metadata schema's getoond worden." + } + }, + "schema": { + "title": "DSpace Angular :: Metadata Schema Register", + "head": "Metadata Schema", + "description": "Dit is het metadata schema voor \"{{namespace}}\".", + "fields": { + "head": "Schema metadata velden", + "table": { + "field": "Veld", + "scopenote": "Opmerking over bereik" + }, + "no-items": "Er kunnen geen metadata velden getoond worden." + } + }, + "bitstream-formats": { + "title": "DSpace Angular :: Bitstream Formaat Register", + "head": "Bitstream Formaat Register", + "description": "Deze lijst van Bitstream formaten biedt informatie over de formaten die in deze repository zijn toegelaten en op welke manier ze ondersteund worden. De term Bitstream wordt in DSpace gebruikt om een bestand aan te duiden dat samen met metadata onderdeel uitmaakt van een item. De naam bitstream duidt op het feit dat het bestand achterliggend wordt opgeslaan zonder bestandsextensie.", + "formats": { + "table": { + "name": "Naam", + "mimetype": "MIME Type", + "supportLevel": { + "head": "Ondersteuning", + "0": "Onbekend", + "1": "Gekend", + "2": "Ondersteund" + }, + "internal": "intern" + }, + "no-items": "Er kunnen geen bitstream formaten getoond worden." + } + } + } + }, + "loading": { + "default": "Laden...", + "top-level-communities": "Inladen van de Communities op het hoogste niveau...", + "community": "Community wordt ingeladen...", + "collection": "Collectie wordt ingeladen...", + "sub-collections": "De sub-collecties worden ingeladen...", + "recent-submissions": "Recent toegevoegde items worden ingeladen...", + "item": "Item wordt ingeladen...", + "objects": "Laden...", + "search-results": "Zoekresultaten worden ingeladen...", + "browse-by": "Items worden ingeladen..." + }, + "error": { + "default": "Fout", + "top-level-communities": "Fout bij het inladen van communities op het hoogste niveau", + "community": "Fout bij het ophalen van een community", + "collection": "Fout bij het ophalen van een collectie", + "sub-collections": "Fout bij het ophalen van sub-collecties", + "recent-submissions": "Fout bij het ophalen van recent toegevoegde items", + "item": "Fout bij het ophalen van items", + "objects": "Fout bij het ophalen van objecten", + "search-results": "Fout bij het ophalen van zoekresultaten", + "browse-by": "Fout bij het ophalen van items", + "validation": { + "pattern": "Deze invoer is niet toegelaten volgens dit patroon: {{ pattern }}.", + "license": { + "notgranted": "U moet de invoerlicentie goedkeuren om de invoer af te werken. Indien u deze licentie momenteel niet kan of mag goedkeuren, kan u uw werk opslaan en de invoer later afwerken. U kan dit nieuwe item ook verwijderen indien u niet voldoet aan de vereisten van de invoer licentie." + } + } + }, + "form": { + "submit": "Verstuur", + "cancel": "Annuleer", + "search": "Zoek", + "remove": "Verwijder", + "first-name": "Voornaam", + "last-name": "Achternaam", + "loading": "Inladen...", + "no-results": "Geen resultaten gevonden", + "no-value": "Geen waarde ingevoerd", + "group-collapse": "Inklappen", + "group-expand": "Uitklappen", + "group-collapse-help": "Klik hier op in te klappen", + "group-expand-help": "Klik hier om uit te klappen en om meer onderdelen toe te voegen" + }, + "login": { + "title": "Aanmelden", + "form": { + "header": "Gelieve in te loggen in DSpace", + "email": "Email adres", + "forgot-password": "Bent u uw wachtwoord vergeten?", + "new-user": "Nieuwe gebruiker? Gelieve u hier te registreren", + "password": "Wachtwoord", + "submit": "Aanmelden" + } + }, + "logout": { + "title": "Afmelden", + "form": { + "header": "Afmelden in DSpace", + "submit": "Afmelden" + } + }, + "auth": { + "messages": { + "expired": "Uw sessie is vervallen. Gelieve opnieuw aan te melden." + }, + "errors": { + "invalid-user": "Ongeldig email adres of wachtwoord." + } + } +} From b2fef4d60a4036000baa6f83b1651012cb6482f8 Mon Sep 17 00:00:00 2001 From: helix84 Date: Thu, 4 Oct 2018 09:22:46 +0200 Subject: [PATCH 33/48] Create cs.json --- resources/i18n/cs.json | 277 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 277 insertions(+) create mode 100644 resources/i18n/cs.json diff --git a/resources/i18n/cs.json b/resources/i18n/cs.json new file mode 100644 index 0000000000..1fdd02401b --- /dev/null +++ b/resources/i18n/cs.json @@ -0,0 +1,277 @@ +{ + "footer": { + "copyright": "copyright © 2002-{{ year }}", + "link.dspace": "software DSpace", + "link.duraspace": "DuraSpace" + }, + "collection": { + "page": { + "news": "Novinky", + "license": "Licence", + "browse": { + "recent": { + "head": "Poslední příspěvky" + } + } + } + }, + "community": { + "page": { + "news": "Novinky", + "license": "Licence" + }, + "sub-collection-list": { + "head": "Kolekce v této komunitě" + } + }, + "item": { + "page": { + "author": "Autor", + "abstract": "Abstract", + "date": "Datum", + "uri": "URI", + "files": "Soubory", + "collections": "Kolekce", + "filesection": { + "download": "Stáhnout", + "name": "Název:", + "format": "Formát:", + "size": "Velikost:", + "description": "Popis:" + }, + "link": { + "simple": "Minimální záznam", + "full": "Úplný záznam" + } + } + }, + "nav": { + "home": "Domů", + "login": "Přihlásit se", + "logout": "Odhlásit se" + }, + "pagination": { + "results-per-page": "Výsledků na stránku", + "sort-direction": "Seřazení", + "showing": { + "label": "Zobrazují se záznamy ", + "detail": "{{ range }} z {{ total }}" + } + }, + "sorting": { + "score": { + "DESC": "Relevance" + }, + "dc.title": { + "ASC": "Název vzestupně", + "DESC": "Název sestupně" + } + }, + "title": "DSpace", + "404": { + "help": "Nepodařilo se najít stránku, kterou hledáte. Je možné, že stránka byla přesunuta nebo smazána. Pomocí tlačítka níže můžete přejít na domovskou stránku. ", + "page-not-found": "stránka nenalezena", + "link": { + "home-page": "Přejít na domovskou stránku" + } + }, + "home": { + "title": "DSpace Angular :: Domů", + "description": "", + "top-level-communities": { + "head": "Komunity v DSpace", + "help": "Vybráním komunity můžete prohlížet její kolekce." + } + }, + "search": { + "title": "DSpace Angular :: Hledat", + "description": "", + "form": { + "search": "Hledat", + "search_dspace": "Hledat v DSpace" + }, + "results": { + "head": "Výsledky hledání", + "no-results": "Nebyli nalezeny žádné výsledky" + }, + "sidebar": { + "close": "Zpět na výsledky", + "open": "Vyhledávací nástroje", + "results": "výsledky", + "filters": { + "title": "Filtry" + }, + "settings": { + "title": "Nastavení", + "sort-by": "Řadit dle", + "rpp": "Výsledků na stránku" + } + }, + "view-switch": { + "show-list": "Zobrazit seznam", + "show-grid": "Zobrazit mřížku" + }, + "filters": { + "head": "Filtry", + "reset": "Obnovit filtry", + "applied": { + "f.author": "Autor", + "f.dateIssued.min": "Od data", + "f.dateIssued.max": "Do data", + "f.subject": "Předmět", + "f.has_content_in_original_bundle": "Má soubory" + }, + "filter": { + "show-more": "Zobrazit více", + "show-less": "Sbalit", + "author": { + "placeholder": "Jméno autora", + "head": "Autor" + }, + "scope": { + "placeholder": "Filtr rozsahu", + "head": "Rozsah" + }, + "subject": { + "placeholder": "Předmět", + "head": "Předmět" + }, + "dateIssued": { + "max": { + "placeholder": "Datum od" + }, + "min": { + "placeholder": "Datum do" + }, + "head": "Datum" + }, + "has_content_in_original_bundle": { + "head": "Má soubory" + } + } + } + }, + "browse": { + "title": "Prohlížíte {{ collection }} dle {{ field }} {{ value }}" + }, + "admin": { + "registries": { + "metadata": { + "title": "DSpace Angular :: Registr metadat", + "head": "Registr metadat", + "description": "Registr metadat je seznam všech metadatových polí dostupných v repozitáři. Tyto pole mohou být rozdělena do více schémat. DSpace však vyžaduje použití schématu kvalifikový Dublin Core.", + "schemas": { + "table": { + "id": "ID", + "namespace": "Jmenný prostor", + "name": "Název" + }, + "no-items": "Žádná schémata metadat." + } + }, + "schema": { + "title": "DSpace Angular :: Registr schémat metadat", + "head": "Metadata Schema", + "description": "Toto je schéma metadat pro „{{namespace}}“.", + "fields": { + "head": "Pole schématu metadat", + "table": { + "field": "Pole", + "scopenote": "Poznámka o rozsahu" + }, + "no-items": "Žádná metadatová pole." + } + }, + "bitstream-formats": { + "title": "DSpace Angular :: Registr formátů souborů", + "head": "Registr formátů souborů", + "description": "Tento seznam formátů souborů poskytuje informace o známých formátech a o úrovni jejich podpory.", + "formats": { + "table": { + "name": "Název", + "mimetype": "Typ MIME", + "supportLevel": { + "head": "Úroveň podpory", + "0": "Neznámá", + "1": "Známá", + "2": "Podpora" + }, + "internal": "interní" + }, + "no-items": "Žádné formáty souborů." + } + } + } + }, + "loading": { + "default": "Načítá se...", + "top-level-communities": "Načítají se komunity nejvyšší úrovně...", + "community": "Načítá se komunita...", + "collection": "Načítá se kolekce...", + "sub-collections": "Načítají se subkolekce...", + "recent-submissions": "Načítají se poslední příspěvky...", + "item": "Načítá se záznam...", + "objects": "Načítá se...", + "search-results": "Načítají se výsledky hledání...", + "browse-by": "Načítají se záznamy..." + }, + "error": { + "default": "Chyba", + "top-level-communities": "Chyba během stahování komunit nejvyšší úrovně", + "community": "Chyba během stahování komunity", + "collection": "Chyba během stahování kolekce", + "sub-collections": "Chyba během stahování subkolekcí", + "recent-submissions": "Chyba během stahování posledních příspěvků", + "item": "Chyba během stahování záznamu", + "objects": "Chyba během stahování objektů", + "search-results": "Chyba během stahování výsledků hledání", + "browse-by": "Chyba během stahování záznamů", + "validation": { + "pattern": "Tento vstup je omezen dle vzoru: {{ pattern }}.", + "license": { + "notgranted": "Pro dokončení zaslání Musíte udělit licenci. Pokud v tuto chvíli tuto licenci nemůžete udělit, můžete svou práci uložit a později se k svému příspěveku vrátit nebo jej smazat." + } + } + }, + "form": { + "submit": "Odeslat", + "cancel": "Zrušit", + "search": "Hledat", + "remove": "Smazat", + "first-name": "Křestní jméno", + "last-name": "Příjmení", + "loading": "Načítá se...", + "no-results": "Nebyli nalezeny žádné výsledky", + "no-value": "Nebyla zadána hodnota", + "group-collapse": "Sbalit", + "group-expand": "Rozbalit", + "group-collapse-help": "Kliknutím sem sbalíte", + "group-expand-help": "Kliknutím sem rozbalíte a přidáte další prvky" + }, + "login": { + "title": "Přihlásit se", + "form": { + "header": "Prosím, přihlaste se do DSpace", + "email": "E-mailová adresa", + "forgot-password": "Zapomněli jste své heslo?", + "new-user": "Nový uživatel? Zaregistrujte se kliknutím sem.", + "password": "Heslo", + "submit": "Přihlásit se" + } + }, + "logout": { + "title": "Odhlásit se", + "form": { + "header": "Odhlásit se z DSpace", + "submit": "Odhlásit se" + } + }, + "auth": { + "messages": { + "expired": "Vaše relace vypršela. Prosím, znova se přihlaste." + }, + "errors": { + "invalid-user": "Neplatná e-mailová adresa nebo heslo." + } + } +} From a83c6c05dfc479ebead627ec449e1dcf10df498f Mon Sep 17 00:00:00 2001 From: helix84 Date: Thu, 4 Oct 2018 09:25:38 +0200 Subject: [PATCH 34/48] minor fixes in en.json --- resources/i18n/en.json | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/resources/i18n/en.json b/resources/i18n/en.json index c7cb9a5ba7..b6a23068d7 100644 --- a/resources/i18n/en.json +++ b/resources/i18n/en.json @@ -205,7 +205,7 @@ }, "loading": { "default": "Loading...", - "top-level-communities": "Loading top level communities...", + "top-level-communities": "Loading top-level communities...", "community": "Loading community...", "collection": "Loading collection...", "sub-collections": "Loading sub-collections...", @@ -217,7 +217,7 @@ }, "error": { "default": "Error", - "top-level-communities": "Error fetching top level communities", + "top-level-communities": "Error fetching top-level communities", "community": "Error fetching community", "collection": "Error fetching collection", "sub-collections": "Error fetching sub-collections", @@ -246,7 +246,7 @@ "group-collapse": "Collapse", "group-expand": "Expand", "group-collapse-help": "Click here to collapse", - "group-expand-help": "Click here to expand and add more element" + "group-expand-help": "Click here to expand and add more elements" }, "login": { "title": "Login", @@ -271,7 +271,7 @@ "expired": "Your session has expired. Please log in again." }, "errors": { - "invalid-user": "Invalid email or password." + "invalid-user": "Invalid email address or password." } } } From c8ab655b4cea5291e45fb2def5b1c516ee2c251f Mon Sep 17 00:00:00 2001 From: cjuergen Date: Mon, 8 Oct 2018 10:49:59 +0200 Subject: [PATCH 35/48] Initial German Translation --- resources/i18n/de.json | 277 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 277 insertions(+) create mode 100644 resources/i18n/de.json diff --git a/resources/i18n/de.json b/resources/i18n/de.json new file mode 100644 index 0000000000..d6b02ff533 --- /dev/null +++ b/resources/i18n/de.json @@ -0,0 +1,277 @@ +{ + "footer": { + "copyright": "Copyright © 2002-{{ year }}", + "link.dspace": "DSpace Software", + "link.duraspace": "DuraSpace" + }, + "collection": { + "page": { + "news": "Neuigkeiten", + "license": "Lizenz", + "browse": { + "recent": { + "head": "Aktuellste Veröffentlichungen" + } + } + } + }, + "community": { + "page": { + "news": "Neuigkeiten", + "license": "Lizenz" + }, + "sub-collection-list": { + "head": "Sammlungen in diesem Bereich" + } + }, + "item": { + "page": { + "author": "Autor", + "abstract": "Kurzfassung", + "date": "Datum", + "uri": "URI", + "files": "Dateien", + "collections": "Sammlungen", + "filesection": { + "download": "Herunterladen", + "name": "Name:", + "format": "Format:", + "size": "Größe:", + "description": "Beschreibung:" + }, + "link": { + "simple": "Kurzanzeige", + "full": "Vollanzeige" + } + } + }, + "nav": { + "home": "Zur Startseite", + "login": "Anmelden", + "logout": "Abmelden" + }, + "pagination": { + "results-per-page": "Ergebnisse pro Seite", + "sort-direction": "Sortiermöglichkeiten", + "showing": { + "label": "Anzeige der Treffer ", + "detail": "{{ range }} bis {{ total }}" + } + }, + "sorting": { + "score": { + "DESC": "Relevanz" + }, + "dc.title": { + "ASC": "Titel aufsteigend", + "DESC": "Titel absteigend" + } + }, + "title": "DSpace", + "404": { + "help": "Die Seite, die Sie aufrufen wollten, konnte nicht gefunden werden. Sie könnte verschoben oder gelöscht worden sein. Mit dem Link unten kommen Sie zurück zur Startseite. ", + "page-not-found": "Seite nicht gefunden", + "link": { + "home-page": "Zurück zur Startseite" + } + }, + "home": { + "title": "DSpace Angular :: Startseite", + "description": "", + "top-level-communities": { + "head": "Bereiche in DSpace", + "help": "Wählen Sie einen Bereich, um seine Sammlungen einzusehen." + } + }, + "search": { + "title": "DSpace Angular :: Suche", + "description": "", + "form": { + "search": "Suche", + "search_dspace": "DSpace durchsuchen" + }, + "results": { + "head": "Suchergebnisse", + "no-results": "Zu dieser Suche gibt es keine Treffer." + }, + "sidebar": { + "close": "Zurück zu den Ergebnissen", + "open": "Suchwerkzeuge", + "results": "Ergebnisse", + "filters": { + "title": "Filter" + }, + "settings": { + "title": "Einstellungen", + "sort-by": "Sortiere nach", + "rpp": "Treffer pro Seite" + } + }, + "view-switch": { + "show-list": "Zeige als Liste", + "show-grid": "Zeige als Raster" + }, + "filters": { + "head": "Filter", + "reset": "Filter zurücksetzen", + "applied": { + "f.author": "Autor", + "f.dateIssued.min": "Anfangsdatum", + "f.dateIssued.max": "Enddatum", + "f.subject": "Thema", + "f.has_content_in_original_bundle": "Besitzt Dateien" + }, + "filter": { + "show-more": "Zeige mehr", + "show-less": "Zeige weniger", + "author": { + "placeholder": "Autor", + "head": "Autor" + }, + "scope": { + "placeholder": "Bereichsfilter", + "head": "Bereich" + }, + "subject": { + "placeholder": "Schlagwort", + "head": "Schlagwort" + }, + "dateIssued": { + "max": { + "placeholder": "Frühestes Datum" + }, + "min": { + "placeholder": "Ältestes Datum" + }, + "head": "Datum" + }, + "has_content_in_original_bundle": { + "head": "Besitzt Dateien" + } + } + } + }, + "browse": { + "title": "Anzeige {{ collection }} nach {{ field }} {{ value }}" + }, + "admin": { + "registries": { + "metadata": { + "title": "DSpace Angular :: Metadatenreferenzliste", + "head": "Metadatenreferenzliste", + "description": "Die Metadatenreferenzliste beinhaltet alle Metadatenfelder, die zur Verfügung stehen. Die Felder können in unterschiedlichen Schemata enthalten sein. Nichtsdestotrotz benötigt DSpace mindestens qualifiziertes Dublin Core.", + "schemas": { + "table": { + "id": "ID", + "namespace": "Namensraum", + "name": "Name" + }, + "no-items": "Es gbit keine Metadatenschemata." + } + }, + "schema": { + "title": "DSpace Angular :: Referenzliste der Metadatenschemata", + "head": "Metadatenschemata", + "description": "Dies ist das Metadatenschema für \"{{namespace}}\".", + "fields": { + "head": "Felder in diesem Schema", + "table": { + "field": "Feld", + "scopenote": "Gültigkeitsbereich" + }, + "no-items": "Es gibt keine Felder in diesem Schema." + } + }, + "bitstream-formats": { + "title": "DSpace Angular :: Referenzliste der Dateiformate", + "head": "Referenzliste der Dateiformate", + "description": "Diese Liste enhtält die in diesem Repositorium zulässigen Dateiformate und den jeweiligen Unterstützungsgrad.", + "formats": { + "table": { + "name": "Name", + "mimetype": "MIME Type", + "supportLevel": { + "head": "Unterstützungsgrad", + "0": "Unbekannt", + "1": "Bekannt", + "2": "Unterstützt" + }, + "internal": "intern" + }, + "no-items": "Es gibt keine Formate in dieser Referenzliste." + } + } + } + }, + "loading": { + "default": "Am Laden ...", + "top-level-communities": "Die Hauptbereiche werden geladen ...", + "community": "Der Bereich wird geladen ...", + "collection": "Die Sammlung wird geladen ...", + "sub-collections": "Die untergeordneten Sammlungen werden geladen ...", + "recent-submissions": "Die aktuellsten Veröffentlichungen werden geladen ...", + "item": "Die Ressource wird geladen ...", + "objects": "Am Laden ...", + "search-results": "Die Suchergebnisse werden geladen ...", + "browse-by": "Die Ressourcen werden geladen ..." + }, + "error": { + "default": "Fehler", + "top-level-communities": "Fehler beim Laden der Hauptbereiche.", + "community": "Fehler beim Laden des Bereiches.", + "collection": "Fehler beim Laden der Sammlung.", + "sub-collections": "Fehler beim Laden der untergeordneten Sammlungen.", + "recent-submissions": "Fehler beim Laden der aktuellsten Veröffentlichungen.", + "item": "Fehler beim Laden der Ressource.", + "objects": "Fehler beim Laden der Objekte.", + "search-results": "Fehler beim Laden der Suchergebnisse.", + "browse-by": "Fehler beim Laden der Ressourcen", + "validation": { + "pattern": "Die Eingabe kann nur folgendes Muster haben: {{ pattern }}.", + "license": { + "notgranted": "Sie müssen der Lizenz zustimmen, um die Ressource einzureichen. Wenn dies zur Zeit nicht geht, können Sie die Einreichung speichern und später wiederaufnehmen oder löschen." + } + } + }, + "form": { + "submit": "Los", + "cancel": "Abbrechen", + "search": "Suchen", + "remove": "Löschen", + "first-name": "Vorname", + "last-name": "Nachname", + "loading": "Am Laden ...", + "no-results": "Keine Ergebnisse gefunden", + "no-value": "Kein Wert eingegeben", + "group-collapse": "Weniger", + "group-expand": "Mehr", + "group-collapse-help": "Hier klicken, um die Anzeige zu reduzieren", + "group-expand-help": "Hier klicken, um mehr Elemente anzuzeigen" + }, + "login": { + "title": "Einloggen", + "form": { + "header": "Bitte Loggen Sie sich ein.", + "email": "E-Mail-Adresse", + "forgot-password": "Haben Sie Ihr Passwort vergessen?", + "new-user": "Sind Sie neu hier? Klicken Sie hier, um sich zu registrieren.", + "password": "Passwort", + "submit": "Einloggen" + } + }, + "logout": { + "title": "Ausloggen", + "form": { + "header": "Ausloggen aus DSpace", + "submit": "Ausloggen" + } + }, + "auth": { + "messages": { + "expired": "Ihre Sitzung ist abgelaufen, bitte melden Sie sich erneut an." + }, + "errors": { + "invalid-user": "Ungültige E-Mail-Adresse oder Passwort." + } + } +} From 199d8a8cff30e114341e6e7f99fb3fe2034d2108 Mon Sep 17 00:00:00 2001 From: lotte Date: Mon, 8 Oct 2018 12:12:09 +0200 Subject: [PATCH 36/48] commit before merge --- src/app/core/auth/auth.effects.spec.ts | 10 +++++----- .../lookup/dynamic-lookup.component.spec.ts | 2 +- .../models/tag/dynamic-tag.component.spec.ts | 4 ++-- .../form/builder/form-builder.service.spec.ts | 16 ++++++++-------- 4 files changed, 16 insertions(+), 16 deletions(-) diff --git a/src/app/core/auth/auth.effects.spec.ts b/src/app/core/auth/auth.effects.spec.ts index a01a8a2887..a707e13ee0 100644 --- a/src/app/core/auth/auth.effects.spec.ts +++ b/src/app/core/auth/auth.effects.spec.ts @@ -5,7 +5,7 @@ import { Store } from '@ngrx/store'; import { cold, hot } from 'jasmine-marbles'; import { Observable } from 'rxjs'; -import { of as observableOf } from 'rxjs'; +import { of as observableOf, throwError as observableThrow } from 'rxjs'; import { AuthEffects } from './auth.effects'; import { @@ -72,7 +72,7 @@ describe('AuthEffects', () => { describe('when credentials are wrong', () => { it('should return a AUTHENTICATE_ERROR action in response to a AUTHENTICATE action', () => { - spyOn((authEffects as any).authService, 'authenticate').and.returnValue(Observable.throw(new Error('Message Error test'))); + spyOn((authEffects as any).authService, 'authenticate').and.returnValue(observableThrow(new Error('Message Error test'))); actions = hot('--a-', { a: { @@ -113,7 +113,7 @@ describe('AuthEffects', () => { describe('when token is not valid', () => { it('should return a AUTHENTICATED_ERROR action in response to a AUTHENTICATED action', () => { - spyOn((authEffects as any).authService, 'authenticatedUser').and.returnValue(Observable.throw(new Error('Message Error test'))); + spyOn((authEffects as any).authService, 'authenticatedUser').and.returnValue(observableThrow(new Error('Message Error test'))); actions = hot('--a-', {a: {type: AuthActionTypes.AUTHENTICATED, payload: token}}); @@ -165,7 +165,7 @@ describe('AuthEffects', () => { describe('when refresh token failed', () => { it('should return a REFRESH_TOKEN_ERROR action in response to a REFRESH_TOKEN action', () => { - spyOn((authEffects as any).authService, 'refreshAuthenticationToken').and.returnValue(Observable.throw('')); + spyOn((authEffects as any).authService, 'refreshAuthenticationToken').and.returnValue(observableThrow('')); actions = hot('--a-', {a: {type: AuthActionTypes.REFRESH_TOKEN, payload: token}}); @@ -191,7 +191,7 @@ describe('AuthEffects', () => { describe('when refresh token failed', () => { it('should return a REFRESH_TOKEN_ERROR action in response to a LOG_OUT action', () => { - spyOn((authEffects as any).authService, 'logout').and.returnValue(Observable.throw(new Error('Message Error test'))); + spyOn((authEffects as any).authService, 'logout').and.returnValue(observableThrow(new Error('Message Error test'))); actions = hot('--a-', {a: {type: AuthActionTypes.LOG_OUT, payload: token}}); diff --git a/src/app/shared/form/builder/ds-dynamic-form-ui/models/lookup/dynamic-lookup.component.spec.ts b/src/app/shared/form/builder/ds-dynamic-form-ui/models/lookup/dynamic-lookup.component.spec.ts index 6ea627a1f9..a1ab4dfacd 100644 --- a/src/app/shared/form/builder/ds-dynamic-form-ui/models/lookup/dynamic-lookup.component.spec.ts +++ b/src/app/shared/form/builder/ds-dynamic-form-ui/models/lookup/dynamic-lookup.component.spec.ts @@ -191,7 +191,7 @@ describe('Dynamic Lookup component', () => { const btnEl = de[0].nativeElement; const selectedValue = Object.assign(new AuthorityValueModel(), {id: 1, display: 'one', value: 1}); spyOn(lookupComp.change, 'emit'); - + console.log("debugger"); lookupComp.firstInputValue = 'test'; lookupFixture.detectChanges(); btnEl.click(); diff --git a/src/app/shared/form/builder/ds-dynamic-form-ui/models/tag/dynamic-tag.component.spec.ts b/src/app/shared/form/builder/ds-dynamic-form-ui/models/tag/dynamic-tag.component.spec.ts index 5a6ec1c277..656d43bb68 100644 --- a/src/app/shared/form/builder/ds-dynamic-form-ui/models/tag/dynamic-tag.component.spec.ts +++ b/src/app/shared/form/builder/ds-dynamic-form-ui/models/tag/dynamic-tag.component.spec.ts @@ -119,7 +119,7 @@ describe('DsDynamicTagComponent test suite', () => { })); }); - describe('when authorityOptions are setted', () => { + describe('when authorityOptions are set', () => { describe('and init model value is empty', () => { beforeEach(() => { @@ -229,7 +229,7 @@ describe('DsDynamicTagComponent test suite', () => { }); - describe('when authorityOptions are not setted', () => { + describe('when authorityOptions are not set', () => { describe('and init model value is empty', () => { beforeEach(() => { diff --git a/src/app/shared/form/builder/form-builder.service.spec.ts b/src/app/shared/form/builder/form-builder.service.spec.ts index 8b414edc9e..4e9f720e4e 100644 --- a/src/app/shared/form/builder/form-builder.service.spec.ts +++ b/src/app/shared/form/builder/form-builder.service.spec.ts @@ -13,13 +13,10 @@ import { DynamicColorPickerModel, DynamicDatePickerModel, DynamicEditorModel, - DynamicFileUploadModel, DynamicFormArrayGroupModel, + DynamicFileUploadModel, DynamicFormArrayModel, DynamicFormControlModel, - // DynamicFormControlValue, - DynamicFormGroupModel, - DynamicFormService, - DynamicFormValidationService, + DynamicFormGroupModel, DynamicFormValidationService, DynamicFormValueControlModel, DynamicInputModel, DynamicRadioGroupModel, @@ -41,7 +38,10 @@ import { DynamicTypeaheadModel } from './ds-dynamic-form-ui/models/typeahead/dyn import { DynamicListRadioGroupModel } from './ds-dynamic-form-ui/models/list/dynamic-list-radio-group.model'; import { AuthorityOptions } from '../../../core/integration/models/authority-options.model'; import { FormFieldModel } from './models/form-field.model'; -import { FormRowModel, SubmissionFormsModel } from '../../../core/shared/config/config-submission-forms.model'; +import { + FormRowModel, + SubmissionFormsModel +} from '../../../core/shared/config/config-submission-forms.model'; import { FormBuilderService } from './form-builder.service'; import { DynamicRowGroupModel } from './ds-dynamic-form-ui/models/ds-dynamic-row-group-model'; import { DsDynamicInputModel } from './ds-dynamic-form-ui/models/ds-dynamic-input.model'; @@ -49,7 +49,6 @@ import { FormFieldMetadataValueObject } from './models/form-field-metadata-value import { DynamicConcatModel } from './ds-dynamic-form-ui/models/ds-dynamic-concat.model'; import { DynamicLookupNameModel } from './ds-dynamic-form-ui/models/lookup/dynamic-lookup-name.model'; import { DynamicRowArrayModel } from './ds-dynamic-form-ui/models/ds-dynamic-row-array-model'; -import { getMockFormBuilderService } from '../../mocks/mock-form-builder-service'; describe('FormBuilderService test suite', () => { @@ -70,7 +69,8 @@ describe('FormBuilderService test suite', () => { TestBed.configureTestingModule({ imports: [ReactiveFormsModule], providers: [ - {provide: FormBuilderService, useValue: getMockFormBuilderService()}, + {provide: FormBuilderService, useClass: FormBuilderService}, + {provide: DynamicFormValidationService, useValue: {}}, {provide: NG_VALIDATORS, useValue: testValidator, multi: true}, {provide: NG_ASYNC_VALIDATORS, useValue: testAsyncValidator, multi: true} ] From 7c16ccafd35ce5b035b6cd717b971876b8f2e5e7 Mon Sep 17 00:00:00 2001 From: lotte Date: Mon, 8 Oct 2018 12:33:39 +0200 Subject: [PATCH 37/48] rxjs migrate --- .../browse-by-author-page.component.ts | 4 +--- .../+browse-by-title-page/browse-by-title-page.component.ts | 3 +-- src/app/core/auth/auth.interceptor.ts | 4 +--- src/app/core/auth/auth.service.ts | 6 ++---- src/app/core/auth/models/auth-status.model.ts | 2 +- src/app/shared/auth-nav-menu/auth-nav-menu.component.ts | 3 +-- src/app/shared/browse-by/browse-by.component.ts | 2 +- 7 files changed, 8 insertions(+), 16 deletions(-) diff --git a/src/app/+browse-by/+browse-by-author-page/browse-by-author-page.component.ts b/src/app/+browse-by/+browse-by-author-page/browse-by-author-page.component.ts index 1553889741..aa5df99610 100644 --- a/src/app/+browse-by/+browse-by-author-page/browse-by-author-page.component.ts +++ b/src/app/+browse-by/+browse-by-author-page/browse-by-author-page.component.ts @@ -2,13 +2,11 @@ import { Component, OnInit } from '@angular/core'; import { RemoteData } from '../../core/data/remote-data'; import { PaginatedList } from '../../core/data/paginated-list'; import { ItemDataService } from '../../core/data/item-data.service'; -import { Observable } from 'rxjs/Observable'; +import { Observable, Subscription } from 'rxjs'; import { PaginationComponentOptions } from '../../shared/pagination/pagination-component-options.model'; import { SortDirection, SortOptions } from '../../core/cache/models/sort-options.model'; -import { Subscription } from 'rxjs/Subscription'; import { ActivatedRoute } from '@angular/router'; import { hasValue, isNotEmpty } from '../../shared/empty.util'; -import { Metadatum } from '../../core/shared/metadatum.model'; import { BrowseService } from '../../core/browse/browse.service'; import { BrowseEntry } from '../../core/shared/browse-entry.model'; import { Item } from '../../core/shared/item.model'; diff --git a/src/app/+browse-by/+browse-by-title-page/browse-by-title-page.component.ts b/src/app/+browse-by/+browse-by-title-page/browse-by-title-page.component.ts index 1759264e2a..c144ae5b61 100644 --- a/src/app/+browse-by/+browse-by-title-page/browse-by-title-page.component.ts +++ b/src/app/+browse-by/+browse-by-title-page/browse-by-title-page.component.ts @@ -3,11 +3,10 @@ import { RemoteData } from '../../core/data/remote-data'; import { DSpaceObject } from '../../core/shared/dspace-object.model'; import { PaginatedList } from '../../core/data/paginated-list'; import { ItemDataService } from '../../core/data/item-data.service'; -import { Observable } from 'rxjs/Observable'; +import { Observable , Subscription } from 'rxjs'; import { PaginationComponentOptions } from '../../shared/pagination/pagination-component-options.model'; import { SortDirection, SortOptions } from '../../core/cache/models/sort-options.model'; import { Item } from '../../core/shared/item.model'; -import { Subscription } from 'rxjs/Subscription'; import { ActivatedRoute, PRIMARY_OUTLET, UrlSegmentGroup } from '@angular/router'; import { hasValue } from '../../shared/empty.util'; import { Collection } from '../../core/shared/collection.model'; diff --git a/src/app/core/auth/auth.interceptor.ts b/src/app/core/auth/auth.interceptor.ts index 07043d6950..44c8ec088d 100644 --- a/src/app/core/auth/auth.interceptor.ts +++ b/src/app/core/auth/auth.interceptor.ts @@ -1,4 +1,4 @@ -import { of as observableOf, throwError as observableThrowError } from 'rxjs'; +import { of as observableOf, throwError as observableThrowError , Observable } from 'rxjs'; import { catchError, filter, map } from 'rxjs/operators'; import { Injectable, Injector } from '@angular/core'; @@ -12,8 +12,6 @@ import { HttpResponseBase } from '@angular/common/http'; -import { Observable } from 'rxjs'; - import { find } from 'lodash'; diff --git a/src/app/core/auth/auth.service.ts b/src/app/core/auth/auth.service.ts index deb2875bf5..dc2d1ca379 100644 --- a/src/app/core/auth/auth.service.ts +++ b/src/app/core/auth/auth.service.ts @@ -1,4 +1,4 @@ -import { of as observableOf, Observable } from 'rxjs'; +import { of as observableOf, Observable , Observable } from 'rxjs'; import { take, filter, @@ -7,7 +7,7 @@ import { distinctUntilChanged, map, withLatestFrom -} from 'rxjs/operators'; +, map, switchMap, withLatestFrom } from 'rxjs/operators'; import { Inject, Injectable } from '@angular/core'; import { PRIMARY_OUTLET, Router, UrlSegmentGroup, UrlTree } from '@angular/router'; import { HttpHeaders } from '@angular/common/http'; @@ -16,8 +16,6 @@ import { REQUEST } from '@nguniversal/express-engine/tokens'; import { RouterReducerState } from '@ngrx/router-store'; import { select, Store } from '@ngrx/store'; import { CookieAttributes } from 'js-cookie'; -import { Observable } from 'rxjs/Observable'; -import { map, switchMap, withLatestFrom } from 'rxjs/operators'; import { EPerson } from '../eperson/models/eperson.model'; import { AuthRequestService } from './auth-request.service'; diff --git a/src/app/core/auth/models/auth-status.model.ts b/src/app/core/auth/models/auth-status.model.ts index b8ccf9ed6d..37f8d76672 100644 --- a/src/app/core/auth/models/auth-status.model.ts +++ b/src/app/core/auth/models/auth-status.model.ts @@ -2,7 +2,7 @@ import { AuthError } from './auth-error.model'; import { AuthTokenInfo } from './auth-token-info.model'; import { EPerson } from '../../eperson/models/eperson.model'; import { RemoteData } from '../../data/remote-data'; -import { Observable } from 'rxjs/Observable'; +import { Observable } from 'rxjs'; export class AuthStatus { diff --git a/src/app/shared/auth-nav-menu/auth-nav-menu.component.ts b/src/app/shared/auth-nav-menu/auth-nav-menu.component.ts index 6f0f0370bb..5fb6aaaabf 100644 --- a/src/app/shared/auth-nav-menu/auth-nav-menu.component.ts +++ b/src/app/shared/auth-nav-menu/auth-nav-menu.component.ts @@ -1,4 +1,4 @@ -import { of as observableOf, Observable } from 'rxjs'; +import { of as observableOf, Observable , Subscription } from 'rxjs'; import { map, filter } from 'rxjs/operators'; import { Component, OnInit } from '@angular/core'; @@ -16,7 +16,6 @@ import { } from '../../core/auth/selectors'; import { EPerson } from '../../core/eperson/models/eperson.model'; import { AuthService, LOGIN_ROUTE, LOGOUT_ROUTE } from '../../core/auth/auth.service'; -import { Subscription } from 'rxjs/Subscription'; @Component({ selector: 'ds-auth-nav-menu', diff --git a/src/app/shared/browse-by/browse-by.component.ts b/src/app/shared/browse-by/browse-by.component.ts index 062b41a440..94cf81f46e 100644 --- a/src/app/shared/browse-by/browse-by.component.ts +++ b/src/app/shared/browse-by/browse-by.component.ts @@ -4,7 +4,7 @@ import { PaginatedList } from '../../core/data/paginated-list'; import { PaginationComponentOptions } from '../pagination/pagination-component-options.model'; import { SortOptions } from '../../core/cache/models/sort-options.model'; import { fadeIn, fadeInOut } from '../animations/fade'; -import { Observable } from 'rxjs/Observable'; +import { Observable } from 'rxjs'; import { Item } from '../../core/shared/item.model'; import { ListableObject } from '../object-collection/shared/listable-object.model'; From 9c444764a19895acb4bb7c45a5d31adfe346890d Mon Sep 17 00:00:00 2001 From: Antoine Snyers Date: Tue, 9 Oct 2018 15:25:21 +0200 Subject: [PATCH 38/48] Add tests for the MetadataFieldWrapperComponent --- .../metadata-field-wrapper.component.spec.ts | 54 +++++++++++++++++++ 1 file changed, 54 insertions(+) create mode 100644 src/app/+item-page/field-components/metadata-field-wrapper/metadata-field-wrapper.component.spec.ts diff --git a/src/app/+item-page/field-components/metadata-field-wrapper/metadata-field-wrapper.component.spec.ts b/src/app/+item-page/field-components/metadata-field-wrapper/metadata-field-wrapper.component.spec.ts new file mode 100644 index 0000000000..f7cd8f1786 --- /dev/null +++ b/src/app/+item-page/field-components/metadata-field-wrapper/metadata-field-wrapper.component.spec.ts @@ -0,0 +1,54 @@ +import { ComponentFixture, TestBed, async } from '@angular/core/testing'; +import { By } from '@angular/platform-browser'; +import { Component, DebugElement } from '@angular/core'; + +import { MetadataFieldWrapperComponent } from './metadata-field-wrapper.component'; + +@Component({ + selector: 'ds-component-with-content', + template: '\n' + + '
\n' + + '
\n' + + '
' +}) +class ContentComponent {} + +fdescribe('MetadataFieldWrapperComponent', () => { + let component: MetadataFieldWrapperComponent; + let fixture: ComponentFixture; + + beforeEach(async(() => { + TestBed.configureTestingModule({ + declarations: [MetadataFieldWrapperComponent, ContentComponent] + }).compileComponents(); + })); + + beforeEach(() => { + fixture = TestBed.createComponent(MetadataFieldWrapperComponent); + component = fixture.componentInstance; + }); + + const wrapperSelector = '.simple-view-element'; + const labelSelector = '.simple-view-element-header'; + + it('should create', () => { + expect(component).toBeDefined(); + }); + + it('should not show a label when there is no content', () => { + component.label = 'test label'; + fixture.detectChanges(); + const debugLabel = fixture.debugElement.query(By.css(labelSelector)); + expect(debugLabel).toBeNull(); + }); + + it('should show a label when there is content', () => { + const parentFixture = TestBed.createComponent(ContentComponent); + parentFixture.detectChanges(); + const parentComponent = parentFixture.componentInstance; + const parentNative = parentFixture.nativeElement; + const nativeLabel = parentNative.querySelector(labelSelector); + expect(nativeLabel.textContent).toContain('test label'); + }); + +}); From bbe22d9636a305060b1670f2e45ad21e91002b67 Mon Sep 17 00:00:00 2001 From: Antoine Snyers Date: Tue, 9 Oct 2018 12:40:12 +0200 Subject: [PATCH 39/48] Hide metadata labels when there are no values --- .../metadata-field-wrapper.component.html | 8 +++++--- .../metadata-values/metadata-values.component.ts | 3 ++- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/src/app/+item-page/field-components/metadata-field-wrapper/metadata-field-wrapper.component.html b/src/app/+item-page/field-components/metadata-field-wrapper/metadata-field-wrapper.component.html index d926b5330e..084232edf4 100644 --- a/src/app/+item-page/field-components/metadata-field-wrapper/metadata-field-wrapper.component.html +++ b/src/app/+item-page/field-components/metadata-field-wrapper/metadata-field-wrapper.component.html @@ -1,6 +1,8 @@
+
{{ label }}
-
- -
+
+
+ +
diff --git a/src/app/+item-page/field-components/metadata-values/metadata-values.component.ts b/src/app/+item-page/field-components/metadata-values/metadata-values.component.ts index 36499c4721..1c94b56d57 100644 --- a/src/app/+item-page/field-components/metadata-values/metadata-values.component.ts +++ b/src/app/+item-page/field-components/metadata-values/metadata-values.component.ts @@ -1,4 +1,5 @@ import { Component, Input } from '@angular/core'; +import { Metadatum } from '../../../core/shared/metadatum.model'; /** * This component renders the configured 'values' into the ds-metadata-field-wrapper component. @@ -11,7 +12,7 @@ import { Component, Input } from '@angular/core'; }) export class MetadataValuesComponent { - @Input() values: any; + @Input() values: Metadatum[]; @Input() separator: string; From 7ac26843b7c0b7f5ab0ae0658f2fdad035179693 Mon Sep 17 00:00:00 2001 From: Antoine Snyers Date: Tue, 9 Oct 2018 15:37:03 +0200 Subject: [PATCH 40/48] Remove the 'f' in fdescribe --- .../metadata-field-wrapper.component.spec.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/app/+item-page/field-components/metadata-field-wrapper/metadata-field-wrapper.component.spec.ts b/src/app/+item-page/field-components/metadata-field-wrapper/metadata-field-wrapper.component.spec.ts index f7cd8f1786..47e7d6c34e 100644 --- a/src/app/+item-page/field-components/metadata-field-wrapper/metadata-field-wrapper.component.spec.ts +++ b/src/app/+item-page/field-components/metadata-field-wrapper/metadata-field-wrapper.component.spec.ts @@ -13,7 +13,7 @@ import { MetadataFieldWrapperComponent } from './metadata-field-wrapper.componen }) class ContentComponent {} -fdescribe('MetadataFieldWrapperComponent', () => { +describe('MetadataFieldWrapperComponent', () => { let component: MetadataFieldWrapperComponent; let fixture: ComponentFixture; From 3a8f7754fa3420f5eddd88770391dd1c65cdc8bf Mon Sep 17 00:00:00 2001 From: lotte Date: Thu, 11 Oct 2018 12:02:40 +0200 Subject: [PATCH 41/48] 55143: fixed all tests --- package.json | 4 +- .../metadata-registry.component.spec.ts | 2 - .../browse-by-author-page.component.ts | 5 +- .../browse-by-title-page.component.ts | 5 +- .../search-configuration.service.ts | 2 +- src/app/core/auth/auth-request.service.ts | 1 - .../auth-response-parsing.service.spec.ts | 12 +- src/app/core/auth/auth.effects.spec.ts | 14 +- src/app/core/auth/auth.interceptor.ts | 4 +- src/app/core/auth/auth.service.spec.ts | 69 +- src/app/core/auth/auth.service.ts | 13 +- src/app/core/cache/response-cache.models.ts | 2 +- .../browse-response-parsing.service.spec.ts | 250 +++---- src/app/core/data/comcol-data.service.ts | 17 +- src/app/core/data/community-data.service.ts | 2 +- src/app/core/data/data.service.spec.ts | 185 ++--- src/app/core/data/data.service.ts | 8 +- src/app/core/data/item-data.service.ts | 10 +- src/app/core/data/test.spec.ts | 37 - src/app/core/metadata/metadata.service.ts | 17 +- .../auth-nav-menu.component.spec.ts | 94 ++- .../auth-nav-menu/auth-nav-menu.component.ts | 10 +- .../browse-by/browse-by.component.spec.ts | 4 +- .../ds-dynamic-form-control.component.html | 4 +- .../ds-dynamic-form-control.component.spec.ts | 1 - .../date-picker/date-picker.component.ts | 1 - .../models/ds-dynamic-row-array-model.ts | 6 +- .../dynamic-group.component.spec.ts | 386 +++++----- .../dynamic-group/dynamic-group.components.ts | 1 - .../models/list/dynamic-list.component.ts | 1 - .../lookup/dynamic-lookup.component.spec.ts | 472 ++++++++----- .../models/lookup/dynamic-lookup.component.ts | 1 - .../dynamic-scrollable-dropdown.component.ts | 1 - .../models/tag/dynamic-tag.component.spec.ts | 68 +- .../models/tag/dynamic-tag.component.ts | 5 +- .../dynamic-typeahead.component.spec.ts | 60 +- .../typeahead/dynamic-typeahead.component.ts | 1 - .../form/builder/form-builder.service.spec.ts | 2 +- .../form/builder/parsers/field-parser.ts | 2 +- src/app/shared/form/form.component.html | 4 +- src/app/shared/form/form.component.spec.ts | 662 +++++++++--------- src/app/shared/form/form.component.ts | 13 - src/app/shared/form/form.reducer.ts | 2 - src/app/shared/form/form.service.spec.ts | 120 ++-- src/app/shared/log-in/log-in.component.ts | 6 +- .../shared/mocks/mock-form-builder-service.ts | 2 +- src/app/shared/mocks/mock-form-service.ts | 15 +- .../mocks/mock-remote-data-build.service.ts | 5 +- src/app/shared/mocks/mock-store.ts | 4 - .../number-picker/number-picker.component.ts | 2 +- .../testing/auth-request-service-stub.ts | 6 +- src/app/shared/testing/auth-service-stub.ts | 7 +- src/app/shared/utils/debounce.directive.ts | 3 - src/app/store.effects.ts | 3 - src/modules/app/server-app.module.ts | 2 - tslint.json | 10 +- 56 files changed, 1389 insertions(+), 1256 deletions(-) delete mode 100644 src/app/core/data/test.spec.ts delete mode 100644 src/app/shared/mocks/mock-store.ts diff --git a/package.json b/package.json index cc4de4de64..f4ab6e2ff4 100644 --- a/package.json +++ b/package.json @@ -41,8 +41,8 @@ "server:watch": "nodemon dist/server.js", "server:watch:debug": "nodemon --debug dist/server.js", "webpack:watch": "webpack -w --mode development", - "watch": "yarn run build && npm-run-all -p webpack:watch server:watch --mode development", - "watch:debug": "yarn run build && npm-run-all -p webpack:watch server:watch:debug --mode development", + "watch": "yarn run build && npm-run-all -p webpack:watch server:watch", + "watch:debug": "yarn run build && npm-run-all -p webpack:watch server:watch:debug", "predebug": "yarn run build", "predebug:server": "yarn run build", "debug": "node --debug-brk dist/server.js", diff --git a/src/app/+admin/admin-registries/metadata-registry/metadata-registry.component.spec.ts b/src/app/+admin/admin-registries/metadata-registry/metadata-registry.component.spec.ts index dc118a1dea..8b72afa083 100644 --- a/src/app/+admin/admin-registries/metadata-registry/metadata-registry.component.spec.ts +++ b/src/app/+admin/admin-registries/metadata-registry/metadata-registry.component.spec.ts @@ -14,7 +14,6 @@ import { PaginationComponent } from '../../../shared/pagination/pagination.compo import { HostWindowServiceStub } from '../../../shared/testing/host-window-service-stub'; import { HostWindowService } from '../../../shared/host-window.service'; - describe('MetadataRegistryComponent', () => { let comp: MetadataRegistryComponent; let fixture: ComponentFixture; @@ -68,5 +67,4 @@ describe('MetadataRegistryComponent', () => { const mockName: HTMLElement = fixture.debugElement.query(By.css('#metadata-schemas tr:nth-child(2) td:nth-child(3)')).nativeElement; expect(mockName.textContent).toBe('mock'); }); - }); diff --git a/src/app/+browse-by/+browse-by-author-page/browse-by-author-page.component.ts b/src/app/+browse-by/+browse-by-author-page/browse-by-author-page.component.ts index aa5df99610..813ee8a32f 100644 --- a/src/app/+browse-by/+browse-by-author-page/browse-by-author-page.component.ts +++ b/src/app/+browse-by/+browse-by-author-page/browse-by-author-page.component.ts @@ -1,8 +1,9 @@ + +import {combineLatest as observableCombineLatest, Observable, Subscription } from 'rxjs'; import { Component, OnInit } from '@angular/core'; import { RemoteData } from '../../core/data/remote-data'; import { PaginatedList } from '../../core/data/paginated-list'; import { ItemDataService } from '../../core/data/item-data.service'; -import { Observable, Subscription } from 'rxjs'; import { PaginationComponentOptions } from '../../shared/pagination/pagination-component-options.model'; import { SortDirection, SortOptions } from '../../core/cache/models/sort-options.model'; import { ActivatedRoute } from '@angular/router'; @@ -45,7 +46,7 @@ export class BrowseByAuthorPageComponent implements OnInit { sort: this.sortConfig }); this.subs.push( - Observable.combineLatest( + observableCombineLatest( this.route.params, this.route.queryParams, (params, queryParams, ) => { diff --git a/src/app/+browse-by/+browse-by-title-page/browse-by-title-page.component.ts b/src/app/+browse-by/+browse-by-title-page/browse-by-title-page.component.ts index c144ae5b61..e9127dbbab 100644 --- a/src/app/+browse-by/+browse-by-title-page/browse-by-title-page.component.ts +++ b/src/app/+browse-by/+browse-by-title-page/browse-by-title-page.component.ts @@ -1,9 +1,10 @@ + +import {combineLatest as observableCombineLatest, Observable , Subscription } from 'rxjs'; import { Component, OnInit } from '@angular/core'; import { RemoteData } from '../../core/data/remote-data'; import { DSpaceObject } from '../../core/shared/dspace-object.model'; import { PaginatedList } from '../../core/data/paginated-list'; import { ItemDataService } from '../../core/data/item-data.service'; -import { Observable , Subscription } from 'rxjs'; import { PaginationComponentOptions } from '../../shared/pagination/pagination-component-options.model'; import { SortDirection, SortOptions } from '../../core/cache/models/sort-options.model'; import { Item } from '../../core/shared/item.model'; @@ -44,7 +45,7 @@ export class BrowseByTitlePageComponent implements OnInit { sort: this.sortConfig }); this.subs.push( - Observable.combineLatest( + observableCombineLatest( this.route.params, this.route.queryParams, (params, queryParams, ) => { diff --git a/src/app/+search-page/search-service/search-configuration.service.ts b/src/app/+search-page/search-service/search-configuration.service.ts index ab62cc0915..292f26724d 100644 --- a/src/app/+search-page/search-service/search-configuration.service.ts +++ b/src/app/+search-page/search-service/search-configuration.service.ts @@ -159,7 +159,7 @@ export class SearchConfigurationService implements OnDestroy { Object.keys(filterParams).forEach((key) => { if (key.endsWith('.min') || key.endsWith('.max')) { const realKey = key.slice(0, -4); - if (hasNoValue(filters.find((filter) => filter.key === realKey))) { + if (hasNoValue(filters.find((f) => f.key === realKey))) { const min = filterParams[realKey + '.min'] ? filterParams[realKey + '.min'][0] : '*'; const max = filterParams[realKey + '.max'] ? filterParams[realKey + '.max'][0] : '*'; filters.push(new SearchFilter(realKey, ['[' + min + ' TO ' + max + ']'])); diff --git a/src/app/core/auth/auth-request.service.ts b/src/app/core/auth/auth-request.service.ts index 92af4644c6..7cb5fae7e4 100644 --- a/src/app/core/auth/auth-request.service.ts +++ b/src/app/core/auth/auth-request.service.ts @@ -1,5 +1,4 @@ import { Observable, of as observableOf, throwError as observableThrowError } from 'rxjs'; - import { distinctUntilChanged, filter, map, mergeMap, tap } from 'rxjs/operators'; import { Inject, Injectable } from '@angular/core'; import { HALEndpointService } from '../shared/hal-endpoint.service'; diff --git a/src/app/core/auth/auth-response-parsing.service.spec.ts b/src/app/core/auth/auth-response-parsing.service.spec.ts index f6dd87e99a..138d0f1be3 100644 --- a/src/app/core/auth/auth-response-parsing.service.spec.ts +++ b/src/app/core/auth/auth-response-parsing.service.spec.ts @@ -2,20 +2,18 @@ import { AuthStatusResponse } from '../cache/response-cache.models'; import { ObjectCacheService } from '../cache/object-cache.service'; import { GlobalConfig } from '../../../config/global-config.interface'; - -import { Store } from '@ngrx/store'; -import { CoreState } from '../core.reducers'; import { AuthStatus } from './models/auth-status.model'; import { AuthResponseParsingService } from './auth-response-parsing.service'; import { AuthGetRequest, AuthPostRequest } from '../data/request.models'; -import { getMockStore } from '../../shared/mocks/mock-store'; +import { MockStore } from '../../shared/testing/mock-store'; +import { ObjectCacheState } from '../cache/object-cache.reducer'; describe('AuthResponseParsingService', () => { let service: AuthResponseParsingService; - const EnvConfig = {cache: {msToLive: 1000}} as GlobalConfig; - const store = getMockStore() as Store; - const objectCacheService = new ObjectCacheService(store); + const EnvConfig = { cache: { msToLive: 1000 } } as GlobalConfig; + const store = new MockStore({}); + const objectCacheService = new ObjectCacheService(store as any); beforeEach(() => { service = new AuthResponseParsingService(EnvConfig, objectCacheService); diff --git a/src/app/core/auth/auth.effects.spec.ts b/src/app/core/auth/auth.effects.spec.ts index 2820f2d210..0dc8abf860 100644 --- a/src/app/core/auth/auth.effects.spec.ts +++ b/src/app/core/auth/auth.effects.spec.ts @@ -4,8 +4,7 @@ import { provideMockActions } from '@ngrx/effects/testing'; import { Store } from '@ngrx/store'; import { cold, hot } from 'jasmine-marbles'; -import { Observable } from 'rxjs'; -import { of as observableOf, throwError as observableThrow } from 'rxjs'; +import { Observable, of as observableOf, throwError as observableThrow } from 'rxjs'; import { AuthEffects } from './auth.effects'; import { @@ -30,16 +29,21 @@ import { EPersonMock } from '../../shared/testing/eperson-mock'; describe('AuthEffects', () => { let authEffects: AuthEffects; let actions: Observable; - const authServiceStub = new AuthServiceStub(); + let authServiceStub; const store: Store = jasmine.createSpyObj('store', { /* tslint:disable:no-empty */ dispatch: {}, /* tslint:enable:no-empty */ select: observableOf(true) }); - const token = authServiceStub.getToken(); + let token; + function init() { + authServiceStub = new AuthServiceStub(); + token = authServiceStub.getToken(); + } beforeEach(() => { + init(); TestBed.configureTestingModule({ providers: [ AuthEffects, @@ -138,7 +142,7 @@ describe('AuthEffects', () => { describe('when check token failed', () => { it('should return a CHECK_AUTHENTICATION_TOKEN_ERROR action in response to a CHECK_AUTHENTICATION_TOKEN action', () => { - spyOn((authEffects as any).authService, 'hasValidAuthenticationToken').and.returnValue(Observable.throw('')); + spyOn((authEffects as any).authService, 'hasValidAuthenticationToken').and.returnValue(observableThrow('')); actions = hot('--a-', {a: {type: AuthActionTypes.CHECK_AUTHENTICATION_TOKEN, payload: token}}); diff --git a/src/app/core/auth/auth.interceptor.ts b/src/app/core/auth/auth.interceptor.ts index 44c8ec088d..dd9e3fb5e7 100644 --- a/src/app/core/auth/auth.interceptor.ts +++ b/src/app/core/auth/auth.interceptor.ts @@ -1,4 +1,4 @@ -import { of as observableOf, throwError as observableThrowError , Observable } from 'rxjs'; +import { Observable, of as observableOf, throwError as observableThrowError } from 'rxjs'; import { catchError, filter, map } from 'rxjs/operators'; import { Injectable, Injector } from '@angular/core'; @@ -11,8 +11,6 @@ import { HttpResponse, HttpResponseBase } from '@angular/common/http'; - - import { find } from 'lodash'; import { AppState } from '../../app.reducer'; diff --git a/src/app/core/auth/auth.service.spec.ts b/src/app/core/auth/auth.service.spec.ts index bfc21359fb..187db93f3c 100644 --- a/src/app/core/auth/auth.service.spec.ts +++ b/src/app/core/auth/auth.service.spec.ts @@ -31,38 +31,50 @@ describe('AuthService test', () => { pipe: observableOf(true) }); let authService: AuthService; - const authRequest = new AuthRequestServiceStub(); + let authRequest; const window = new NativeWindowRef(); const routerStub = new RouterStub(); - const routeStub = new ActivatedRouteStub(); + let routeStub; let storage: CookieService; - const token: AuthTokenInfo = new AuthTokenInfo('test_token'); - token.expires = Date.now() + (1000 * 60 * 60); - let authenticatedState = { - authenticated: true, - loaded: true, - loading: false, - authToken: token, - user: EPersonMock - }; + let token: AuthTokenInfo; + let authenticatedState; const rdbService = getMockRemoteDataBuildService(); - describe('', () => { + function init() { + token = new AuthTokenInfo('test_token'); + token.expires = Date.now() + (1000 * 60 * 60); + authenticatedState = { + authenticated: true, + loaded: true, + loading: false, + authToken: token, + user: EPersonMock + }; + authRequest = new AuthRequestServiceStub(); + routeStub = new ActivatedRouteStub(); + } + + beforeEach(() => { + init(); + }); + + describe('', () => { beforeEach(() => { + TestBed.configureTestingModule({ imports: [ CommonModule, - StoreModule.forRoot({authReducer}), + StoreModule.forRoot({ authReducer }), ], declarations: [], providers: [ - {provide: AuthRequestService, useValue: authRequest}, - {provide: NativeWindowService, useValue: window}, - {provide: REQUEST, useValue: {}}, - {provide: Router, useValue: routerStub}, - {provide: ActivatedRoute, useValue: routeStub}, + { provide: AuthRequestService, useValue: authRequest }, + { provide: NativeWindowService, useValue: window }, + { provide: REQUEST, useValue: {} }, + { provide: Router, useValue: routerStub }, + { provide: ActivatedRoute, useValue: routeStub }, {provide: Store, useValue: mockStore}, - {provide: RemoteDataBuildService, useValue: rdbService}, + { provide: RemoteDataBuildService, useValue: rdbService }, CookieService, AuthService ], @@ -115,15 +127,16 @@ describe('AuthService test', () => { describe('', () => { beforeEach(async(() => { + init(); TestBed.configureTestingModule({ imports: [ - StoreModule.forRoot({authReducer}) + StoreModule.forRoot({ authReducer }) ], providers: [ - {provide: AuthRequestService, useValue: authRequest}, - {provide: REQUEST, useValue: {}}, - {provide: Router, useValue: routerStub}, - {provide: RemoteDataBuildService, useValue: rdbService}, + { provide: AuthRequestService, useValue: authRequest }, + { provide: REQUEST, useValue: {} }, + { provide: Router, useValue: routerStub }, + { provide: RemoteDataBuildService, useValue: rdbService }, CookieService ] }).compileComponents(); @@ -167,12 +180,12 @@ describe('AuthService test', () => { beforeEach(async(() => { TestBed.configureTestingModule({ imports: [ - StoreModule.forRoot({authReducer}) + StoreModule.forRoot({ authReducer }) ], providers: [ - {provide: AuthRequestService, useValue: authRequest}, - {provide: REQUEST, useValue: {}}, - {provide: Router, useValue: routerStub}, + { provide: AuthRequestService, useValue: authRequest }, + { provide: REQUEST, useValue: {} }, + { provide: Router, useValue: routerStub }, ClientCookieService, CookieService ] diff --git a/src/app/core/auth/auth.service.ts b/src/app/core/auth/auth.service.ts index dc2d1ca379..229c44bcfa 100644 --- a/src/app/core/auth/auth.service.ts +++ b/src/app/core/auth/auth.service.ts @@ -1,13 +1,14 @@ -import { of as observableOf, Observable , Observable } from 'rxjs'; +import { Observable, of as observableOf } from 'rxjs'; import { - take, - filter, - startWith, - first, distinctUntilChanged, + filter, + first, map, + startWith, + switchMap, + take, withLatestFrom -, map, switchMap, withLatestFrom } from 'rxjs/operators'; +} from 'rxjs/operators'; import { Inject, Injectable } from '@angular/core'; import { PRIMARY_OUTLET, Router, UrlSegmentGroup, UrlTree } from '@angular/router'; import { HttpHeaders } from '@angular/common/http'; diff --git a/src/app/core/cache/response-cache.models.ts b/src/app/core/cache/response-cache.models.ts index 9b1b5b89eb..9566dcdc3c 100644 --- a/src/app/core/cache/response-cache.models.ts +++ b/src/app/core/cache/response-cache.models.ts @@ -140,7 +140,7 @@ export class ErrorResponse extends RestResponse { constructor(error: RequestError) { super(false, error.statusText); - console.error(error); + // console.error(error); this.errorMessage = error.message; } } diff --git a/src/app/core/data/browse-response-parsing.service.spec.ts b/src/app/core/data/browse-response-parsing.service.spec.ts index b0fbb1f977..2b1703e38f 100644 --- a/src/app/core/data/browse-response-parsing.service.spec.ts +++ b/src/app/core/data/browse-response-parsing.service.spec.ts @@ -10,134 +10,148 @@ describe('BrowseResponseParsingService', () => { beforeEach(() => { service = new BrowseResponseParsingService(); }); + let validRequest; + let validResponse; + let invalidResponse1; + let invalidResponse2; + let invalidResponse3; + let definitions; describe('parse', () => { - const validRequest = new BrowseEndpointRequest('client/b186e8ce-e99c-4183-bc9a-42b4821bdb78', 'https://rest.api/discover/browses'); + beforeEach(() => { + validRequest = new BrowseEndpointRequest('client/b186e8ce-e99c-4183-bc9a-42b4821bdb78', 'https://rest.api/discover/browses'); - const validResponse = { - payload: { - _embedded: { - browses: [{ - metadataBrowse: false, - sortOptions: [{ name: 'title', metadata: 'dc.title' }, { + validResponse = { + payload: { + _embedded: { + browses: [{ + metadataBrowse: false, + sortOptions: [{ name: 'title', metadata: 'dc.title' }, { + name: 'dateissued', + metadata: 'dc.date.issued' + }, { name: 'dateaccessioned', metadata: 'dc.date.accessioned' }], + order: 'ASC', + type: 'browse', + metadata: ['dc.date.issued'], + _links: { + self: { href: 'https://rest.api/discover/browses/dateissued' }, + items: { href: 'https://rest.api/discover/browses/dateissued/items' } + } + }, { + metadataBrowse: true, + sortOptions: [{ name: 'title', metadata: 'dc.title' }, { + name: 'dateissued', + metadata: 'dc.date.issued' + }, { name: 'dateaccessioned', metadata: 'dc.date.accessioned' }], + order: 'ASC', + type: 'browse', + metadata: ['dc.contributor.*', 'dc.creator'], + _links: { + self: { href: 'https://rest.api/discover/browses/author' }, + entries: { href: 'https://rest.api/discover/browses/author/entries' }, + items: { href: 'https://rest.api/discover/browses/author/items' } + } + }] + }, + _links: { self: { href: 'https://rest.api/discover/browses' } }, + page: { size: 20, totalElements: 2, totalPages: 1, number: 0 } + }, statusCode: '200' + } as DSpaceRESTV2Response; + + invalidResponse1 = { + payload: { + _embedded: { + browse: { + metadataBrowse: false, + sortOptions: [{ name: 'title', metadata: 'dc.title' }, { + name: 'dateissued', + metadata: 'dc.date.issued' + }, { name: 'dateaccessioned', metadata: 'dc.date.accessioned' }], + order: 'ASC', + type: 'browse', + metadata: ['dc.date.issued'], + _links: { + self: { href: 'https://rest.api/discover/browses/dateissued' }, + items: { href: 'https://rest.api/discover/browses/dateissued/items' } + } + } + }, + _links: { self: { href: 'https://rest.api/discover/browses' } }, + page: { size: 20, totalElements: 2, totalPages: 1, number: 0 } + }, statusCode: '200' + } as DSpaceRESTV2Response; + + invalidResponse2 = { + payload: { + _links: { self: { href: 'https://rest.api/discover/browses' } }, + page: { size: 20, totalElements: 2, totalPages: 1, number: 0 } + }, statusCode: '200' + } as DSpaceRESTV2Response; + + invalidResponse3 = { + payload: { + _links: { self: { href: 'https://rest.api/discover/browses' } }, + page: { size: 20, totalElements: 2, totalPages: 1, number: 0 } + }, statusCode: '500' + } as DSpaceRESTV2Response; + + definitions = [ + Object.assign(new BrowseDefinition(), { + metadataBrowse: false, + sortOptions: [ + { + name: 'title', + metadata: 'dc.title' + }, + { name: 'dateissued', metadata: 'dc.date.issued' - }, { name: 'dateaccessioned', metadata: 'dc.date.accessioned' }], - order: 'ASC', - type: 'browse', - metadata: ['dc.date.issued'], - _links: { - self: { href: 'https://rest.api/discover/browses/dateissued' }, - items: { href: 'https://rest.api/discover/browses/dateissued/items' } + }, + { + name: 'dateaccessioned', + metadata: 'dc.date.accessioned' } - }, { - metadataBrowse: true, - sortOptions: [{ name: 'title', metadata: 'dc.title' }, { + ], + defaultSortOrder: 'ASC', + type: 'browse', + metadataKeys: [ + 'dc.date.issued' + ], + _links: { + self: 'https://rest.api/discover/browses/dateissued', + items: 'https://rest.api/discover/browses/dateissued/items' + } + }), + Object.assign(new BrowseDefinition(), { + metadataBrowse: true, + sortOptions: [ + { + name: 'title', + metadata: 'dc.title' + }, + { name: 'dateissued', metadata: 'dc.date.issued' - }, { name: 'dateaccessioned', metadata: 'dc.date.accessioned' }], - order: 'ASC', - type: 'browse', - metadata: ['dc.contributor.*', 'dc.creator'], - _links: { - self: { href: 'https://rest.api/discover/browses/author' }, - entries: { href: 'https://rest.api/discover/browses/author/entries' }, - items: { href: 'https://rest.api/discover/browses/author/items' } - } - }] - }, - _links: { self: { href: 'https://rest.api/discover/browses' } }, - page: { size: 20, totalElements: 2, totalPages: 1, number: 0 } - }, statusCode: '200' - } as DSpaceRESTV2Response; - - const invalidResponse1 = { - payload: { - _embedded: { - browse: { - metadataBrowse: false, - sortOptions: [{ name: 'title', metadata: 'dc.title' }, { - name: 'dateissued', - metadata: 'dc.date.issued' - }, { name: 'dateaccessioned', metadata: 'dc.date.accessioned' }], - order: 'ASC', - type: 'browse', - metadata: ['dc.date.issued'], - _links: { - self: { href: 'https://rest.api/discover/browses/dateissued' }, - items: { href: 'https://rest.api/discover/browses/dateissued/items' } + }, + { + name: 'dateaccessioned', + metadata: 'dc.date.accessioned' } + ], + defaultSortOrder: 'ASC', + type: 'browse', + metadataKeys: [ + 'dc.contributor.*', + 'dc.creator' + ], + _links: { + self: 'https://rest.api/discover/browses/author', + entries: 'https://rest.api/discover/browses/author/entries', + items: 'https://rest.api/discover/browses/author/items' } - }, - _links: { self: { href: 'https://rest.api/discover/browses' } }, - page: { size: 20, totalElements: 2, totalPages: 1, number: 0 } - }, statusCode: '200' - } as DSpaceRESTV2Response; - - const invalidResponse2 = { - payload: { - _links: { self: { href: 'https://rest.api/discover/browses' } }, - page: { size: 20, totalElements: 2, totalPages: 1, number: 0 } - }, statusCode: '200' - } as DSpaceRESTV2Response ; - - const invalidResponse3 = { - payload: { - _links: { self: { href: 'https://rest.api/discover/browses' } }, - page: { size: 20, totalElements: 2, totalPages: 1, number: 0 } - }, statusCode: '500' - } as DSpaceRESTV2Response; - - const definitions = [ - Object.assign(new BrowseDefinition(), { - metadataBrowse: false, - sortOptions: [ - { - name: 'title', - metadata: 'dc.title' - }, - { - name: 'dateissued', - metadata: 'dc.date.issued' - }, - { - name: 'dateaccessioned', - metadata: 'dc.date.accessioned' - } - ], - defaultSortOrder: 'ASC', - type: 'browse', - metadataKeys: [ - 'dc.date.issued' - ], - _links: { } - }), - Object.assign(new BrowseDefinition(), { - metadataBrowse: true, - sortOptions: [ - { - name: 'title', - metadata: 'dc.title' - }, - { - name: 'dateissued', - metadata: 'dc.date.issued' - }, - { - name: 'dateaccessioned', - metadata: 'dc.date.accessioned' - } - ], - defaultSortOrder: 'ASC', - type: 'browse', - metadataKeys: [ - 'dc.contributor.*', - 'dc.creator' - ], - _links: { } - }) - ]; - + }) + ]; + }); it('should return a GenericSuccessResponse if data contains a valid browse endpoint response', () => { const response = service.parse(validRequest, validResponse); expect(response.constructor).toBe(GenericSuccessResponse); diff --git a/src/app/core/data/comcol-data.service.ts b/src/app/core/data/comcol-data.service.ts index 12be32a4f4..c589c5bdc8 100644 --- a/src/app/core/data/comcol-data.service.ts +++ b/src/app/core/data/comcol-data.service.ts @@ -1,5 +1,5 @@ -import { Observable, throwError as observableThrowError, merge as observableMerge } from 'rxjs'; -import { distinctUntilChanged, filter, first, map, mergeMap, tap } from 'rxjs/operators'; +import { distinctUntilChanged, filter, map, mergeMap, take, tap } from 'rxjs/operators'; +import { merge as observableMerge, Observable, throwError as observableThrowError } from 'rxjs'; import { isEmpty, isNotEmpty } from '../../shared/empty.util'; import { NormalizedCommunity } from '../cache/models/normalized-community.model'; import { ObjectCacheService } from '../cache/object-cache.service'; @@ -10,7 +10,6 @@ import { DataService } from './data.service'; import { FindAllOptions, FindByIDRequest } from './request.models'; import { NormalizedObject } from '../cache/models/normalized-object.model'; import { HALEndpointService } from '../shared/hal-endpoint.service'; -import { DSOSuccessResponse } from '../cache/response-cache.models'; export abstract class ComColDataService extends DataService { protected abstract cds: CommunityDataService; @@ -31,14 +30,14 @@ export abstract class ComColDataService this.cds.getFindByIDHref(endpoint, options.scopeID)) - .filter((href: string) => isNotEmpty(href)) - .take(1) - .do((href: string) => { + const scopeCommunityHrefObs = this.cds.getEndpoint().pipe( + mergeMap((endpoint: string) => this.cds.getFindByIDHref(endpoint, options.scopeID)), + filter((href: string) => isNotEmpty(href)), + take(1), + tap((href: string) => { const request = new FindByIDRequest(this.requestService.generateRequestId(), href, options.scopeID); this.requestService.configure(request); - }); + }),); // return scopeCommunityHrefObs.pipe( // mergeMap((href: string) => this.responseCache.get(href)), diff --git a/src/app/core/data/community-data.service.ts b/src/app/core/data/community-data.service.ts index b8e8bd5ce0..6edd7fc23d 100644 --- a/src/app/core/data/community-data.service.ts +++ b/src/app/core/data/community-data.service.ts @@ -41,7 +41,7 @@ export class CommunityDataService extends ComColDataService>> { const hrefObs = this.halService.getEndpoint(this.topLinkPath).pipe(filter((href: string) => isNotEmpty(href)), - mergeMap((endpoint: string) => this.getFindAllHref(endpoint, options)),); + mergeMap((endpoint: string) => this.getFindAllHref(options)),); hrefObs.pipe( filter((href: string) => hasValue(href)), diff --git a/src/app/core/data/data.service.spec.ts b/src/app/core/data/data.service.spec.ts index 1adf108687..d65bad9bbf 100644 --- a/src/app/core/data/data.service.spec.ts +++ b/src/app/core/data/data.service.spec.ts @@ -9,6 +9,7 @@ import { HALEndpointService } from '../shared/hal-endpoint.service'; import { Observable } from 'rxjs'; import { FindAllOptions } from './request.models'; import { SortOptions, SortDirection } from '../cache/models/sort-options.model'; +import { of as observableOf } from 'rxjs'; const endpoint = 'https://rest.api/core'; @@ -17,107 +18,107 @@ class NormalizedTestObject extends NormalizedObject { } class TestService extends DataService { - constructor( - protected responseCache: ResponseCacheService, - protected requestService: RequestService, - protected rdbService: RemoteDataBuildService, - protected store: Store, - protected linkPath: string, - protected halService: HALEndpointService - ) { - super(); - } + constructor( + protected responseCache: ResponseCacheService, + protected requestService: RequestService, + protected rdbService: RemoteDataBuildService, + protected store: Store, + protected linkPath: string, + protected halService: HALEndpointService + ) { + super(); + } - public getBrowseEndpoint(options: FindAllOptions): Observable { - return Observable.of(endpoint); - } + public getBrowseEndpoint(options: FindAllOptions): Observable { + return observableOf(endpoint); + } } describe('DataService', () => { - let service: TestService; - let options: FindAllOptions; - const responseCache = {} as ResponseCacheService; - const requestService = {} as RequestService; - const halService = {} as HALEndpointService; - const rdbService = {} as RemoteDataBuildService; - const store = {} as Store; + let service: TestService; + let options: FindAllOptions; + const responseCache = {} as ResponseCacheService; + const requestService = {} as RequestService; + const halService = {} as HALEndpointService; + const rdbService = {} as RemoteDataBuildService; + const store = {} as Store; - function initTestService(): TestService { - return new TestService( - responseCache, - requestService, - rdbService, - store, - endpoint, - halService - ); - } + function initTestService(): TestService { + return new TestService( + responseCache, + requestService, + rdbService, + store, + endpoint, + halService + ); + } - service = initTestService(); + service = initTestService(); - describe('getFindAllHref', () => { + describe('getFindAllHref', () => { - it('should return an observable with the endpoint', () => { - options = {}; + it('should return an observable with the endpoint', () => { + options = {}; - (service as any).getFindAllHref(options).subscribe((value) => { - expect(value).toBe(endpoint); - } - ); - }); - - it('should include page in href if currentPage provided in options', () => { - options = { currentPage: 2 }; - const expected = `${endpoint}?page=${options.currentPage - 1}`; - - (service as any).getFindAllHref(options).subscribe((value) => { - expect(value).toBe(expected); - }); - }); - - it('should include size in href if elementsPerPage provided in options', () => { - options = { elementsPerPage: 5 }; - const expected = `${endpoint}?size=${options.elementsPerPage}`; - - (service as any).getFindAllHref(options).subscribe((value) => { - expect(value).toBe(expected); - }); - }); - - it('should include sort href if SortOptions provided in options', () => { - const sortOptions = new SortOptions('field1', SortDirection.ASC); - options = { sort: sortOptions}; - const expected = `${endpoint}?sort=${sortOptions.field},${sortOptions.direction}`; - - (service as any).getFindAllHref(options).subscribe((value) => { - expect(value).toBe(expected); - }); - }); - - it('should include startsWith in href if startsWith provided in options', () => { - options = { startsWith: 'ab' }; - const expected = `${endpoint}?startsWith=${options.startsWith}`; - - (service as any).getFindAllHref(options).subscribe((value) => { - expect(value).toBe(expected); - }); - }); - - it('should include all provided options in href', () => { - const sortOptions = new SortOptions('field1', SortDirection.DESC) - options = { - currentPage: 6, - elementsPerPage: 10, - sort: sortOptions, - startsWith: 'ab' - } - const expected = `${endpoint}?page=${options.currentPage - 1}&size=${options.elementsPerPage}` + - `&sort=${sortOptions.field},${sortOptions.direction}&startsWith=${options.startsWith}`; - - (service as any).getFindAllHref(options).subscribe((value) => { - expect(value).toBe(expected); - }); - }) + (service as any).getFindAllHref(options).subscribe((value) => { + expect(value).toBe(endpoint); + } + ); }); + it('should include page in href if currentPage provided in options', () => { + options = { currentPage: 2 }; + const expected = `${endpoint}?page=${options.currentPage - 1}`; + + (service as any).getFindAllHref(options).subscribe((value) => { + expect(value).toBe(expected); + }); + }); + + it('should include size in href if elementsPerPage provided in options', () => { + options = { elementsPerPage: 5 }; + const expected = `${endpoint}?size=${options.elementsPerPage}`; + + (service as any).getFindAllHref(options).subscribe((value) => { + expect(value).toBe(expected); + }); + }); + + it('should include sort href if SortOptions provided in options', () => { + const sortOptions = new SortOptions('field1', SortDirection.ASC); + options = { sort: sortOptions }; + const expected = `${endpoint}?sort=${sortOptions.field},${sortOptions.direction}`; + + (service as any).getFindAllHref(options).subscribe((value) => { + expect(value).toBe(expected); + }); + }); + + it('should include startsWith in href if startsWith provided in options', () => { + options = { startsWith: 'ab' }; + const expected = `${endpoint}?startsWith=${options.startsWith}`; + + (service as any).getFindAllHref(options).subscribe((value) => { + expect(value).toBe(expected); + }); + }); + + it('should include all provided options in href', () => { + const sortOptions = new SortOptions('field1', SortDirection.DESC) + options = { + currentPage: 6, + elementsPerPage: 10, + sort: sortOptions, + startsWith: 'ab' + } + const expected = `${endpoint}?page=${options.currentPage - 1}&size=${options.elementsPerPage}` + + `&sort=${sortOptions.field},${sortOptions.direction}&startsWith=${options.startsWith}`; + + (service as any).getFindAllHref(options).subscribe((value) => { + expect(value).toBe(expected); + }); + }) + }); + }); diff --git a/src/app/core/data/data.service.ts b/src/app/core/data/data.service.ts index a42990f780..f52f61cea1 100644 --- a/src/app/core/data/data.service.ts +++ b/src/app/core/data/data.service.ts @@ -1,5 +1,5 @@ -import { filter, take, first } from 'rxjs/operators'; -import {of as observableOf, Observable } from 'rxjs'; +import { distinctUntilChanged, filter, take, first, map } from 'rxjs/operators'; +import { of as observableOf, Observable } from 'rxjs'; import { Store } from '@ngrx/store'; import { hasValue, isNotEmpty } from '../../shared/empty.util'; import { RemoteDataBuildService } from '../cache/builders/remote-data-build.service'; @@ -12,8 +12,6 @@ import { RemoteData } from './remote-data'; import { FindAllOptions, FindAllRequest, FindByIDRequest, GetRequest } from './request.models'; import { RequestService } from './request.service'; import { NormalizedObject } from '../cache/models/normalized-object.model'; -import { promise } from 'selenium-webdriver'; -import map = promise.map; export abstract class DataService { protected abstract responseCache: ResponseCacheService; @@ -29,7 +27,7 @@ export abstract class DataService let result: Observable; const args = []; - result = this.getBrowseEndpoint(options).distinctUntilChanged(); + result = this.getBrowseEndpoint(options).pipe(distinctUntilChanged()); if (hasValue(options.currentPage) && typeof options.currentPage === 'number') { /* TODO: this is a temporary fix for the pagination start index (0 or 1) discrepancy between the rest and the frontend respectively */ diff --git a/src/app/core/data/item-data.service.ts b/src/app/core/data/item-data.service.ts index 9a6a83952d..89b2eef568 100644 --- a/src/app/core/data/item-data.service.ts +++ b/src/app/core/data/item-data.service.ts @@ -1,3 +1,5 @@ + +import {distinctUntilChanged, map, filter} from 'rxjs/operators'; import { Injectable } from '@angular/core'; import { Store } from '@ngrx/store'; import { Observable } from 'rxjs'; @@ -40,10 +42,10 @@ export class ItemDataService extends DataService { if (options.sort && options.sort.field) { field = options.sort.field; } - return this.bs.getBrowseURLFor(field, this.linkPath) - .filter((href: string) => isNotEmpty(href)) - .map((href: string) => new URLCombiner(href, `?scope=${options.scopeID}`).toString()) - .distinctUntilChanged(); + return this.bs.getBrowseURLFor(field, this.linkPath).pipe( + filter((href: string) => isNotEmpty(href)), + map((href: string) => new URLCombiner(href, `?scope=${options.scopeID}`).toString()), + distinctUntilChanged(),); } } diff --git a/src/app/core/data/test.spec.ts b/src/app/core/data/test.spec.ts deleted file mode 100644 index 3659c66e11..0000000000 --- a/src/app/core/data/test.spec.ts +++ /dev/null @@ -1,37 +0,0 @@ -import { select } from '@ngrx/store'; -import * as ngrx from '@ngrx/store'; -import { cold, hot } from 'jasmine-marbles'; -import { Observable } from 'rxjs'; -import { count, take } from 'rxjs/operators'; - -class TestClass { - selectSomething(input$: Observable) { - return input$.pipe( - select('something'), - take(1) - ) - } -} -describe('mockSelect', () => { - let testClass; - beforeEach(() => { - spyOnProperty(ngrx, 'select').and.callFake(() => { - return () => { - return () => cold('a', { a: 'bingo!' }); - }; - }); - - testClass = new TestClass(); - }); - - it('should mock select', () => { - const input$ = hot('a', { a: '' }); - const expected$ = hot('(b|)', { b: 'bingo!' }); - const result$ = testClass.selectSomething(input$); - result$.pipe(count()).subscribe((t) => console.log('resykts', t)); - expected$.pipe(count()).subscribe((t) => console.log('expected', t)); - result$.subscribe((v) => console.log('result$', v)); - expected$.subscribe((v) => console.log('expected$', v)); - expect(result$).toBeObservable(expected$) - }); -}) \ No newline at end of file diff --git a/src/app/core/metadata/metadata.service.ts b/src/app/core/metadata/metadata.service.ts index 860dd71ce6..ede66f6952 100644 --- a/src/app/core/metadata/metadata.service.ts +++ b/src/app/core/metadata/metadata.service.ts @@ -1,29 +1,18 @@ - -import {distinctUntilKeyChanged, map, filter, first, take} from 'rxjs/operators'; - - - +import { distinctUntilKeyChanged, filter, first, map, take } from 'rxjs/operators'; import { Inject, Injectable } from '@angular/core'; -import { - ActivatedRoute, - Event, - NavigationEnd, - Params, - Router -} from '@angular/router'; +import { ActivatedRoute, NavigationEnd, Router } from '@angular/router'; import { Meta, MetaDefinition, Title } from '@angular/platform-browser'; import { TranslateService } from '@ngx-translate/core'; -import { BehaviorSubject , Observable } from 'rxjs'; +import { BehaviorSubject, Observable } from 'rxjs'; import { RemoteData } from '../data/remote-data'; import { Bitstream } from '../shared/bitstream.model'; import { CacheableObject } from '../cache/object-cache.reducer'; import { DSpaceObject } from '../shared/dspace-object.model'; import { Item } from '../shared/item.model'; -import { Metadatum } from '../shared/metadatum.model'; import { GLOBAL_CONFIG, GlobalConfig } from '../../../config'; import { BitstreamFormat } from '../shared/bitstream-format.model'; diff --git a/src/app/shared/auth-nav-menu/auth-nav-menu.component.spec.ts b/src/app/shared/auth-nav-menu/auth-nav-menu.component.spec.ts index e1a82f4a33..5c5dd11d75 100644 --- a/src/app/shared/auth-nav-menu/auth-nav-menu.component.spec.ts +++ b/src/app/shared/auth-nav-menu/auth-nav-menu.component.spec.ts @@ -22,23 +22,28 @@ describe('AuthNavMenuComponent', () => { let deNavMenuItem: DebugElement; let fixture: ComponentFixture; - const notAuthState: AuthState = { - authenticated: false, - loaded: false, - loading: false - }; - const authState: AuthState = { - authenticated: true, - loaded: true, - loading: false, - authToken: new AuthTokenInfo('test_token'), - user: EPersonMock - }; + let notAuthState: AuthState; + let authState: AuthState; + let routerState = { url: '/home' }; - + function init() { + notAuthState = { + authenticated: false, + loaded: false, + loading: false + }; + authState = { + authenticated: true, + loaded: true, + loading: false, + authToken: new AuthTokenInfo('test_token'), + user: EPersonMock + }; + } describe('when is a not mobile view', () => { + beforeEach(async(() => { const window = new HostWindowServiceStub(800); @@ -53,8 +58,13 @@ describe('AuthNavMenuComponent', () => { AuthNavMenuComponent ], providers: [ - {provide: HostWindowService, useValue: window}, - {provide: AuthService, useValue: {setRedirectUrl: () => { /*empty*/ }}} + { provide: HostWindowService, useValue: window }, + { + provide: AuthService, useValue: { + setRedirectUrl: () => { /*empty*/ + } + } + } ], schemas: [ CUSTOM_ELEMENTS_SCHEMA @@ -64,11 +74,14 @@ describe('AuthNavMenuComponent', () => { })); + beforeEach(() => { + init(); + }); describe('when route is /login and user is not authenticated', () => { - routerState = { - url: '/login' - }; beforeEach(inject([Store], (store: Store) => { + routerState = { + url: '/login' + }; store .subscribe((state) => { (state as any).router = Object.create({}); @@ -91,7 +104,9 @@ describe('AuthNavMenuComponent', () => { const navMenuItemSelector = 'li'; deNavMenuItem = deNavMenu.query(By.css(navMenuItemSelector)); })); - + afterEach(() => { + fixture.destroy(); + }); it('should not render', () => { expect(component).toBeTruthy(); expect(deNavMenu.nativeElement).toBeDefined(); @@ -101,10 +116,10 @@ describe('AuthNavMenuComponent', () => { }); describe('when route is /logout and user is authenticated', () => { - routerState = { - url: '/logout' - }; beforeEach(inject([Store], (store: Store) => { + routerState = { + url: '/logout' + }; store .subscribe((state) => { (state as any).router = Object.create({}); @@ -128,6 +143,10 @@ describe('AuthNavMenuComponent', () => { deNavMenuItem = deNavMenu.query(By.css(navMenuItemSelector)); })); + afterEach(() => { + fixture.destroy(); + }); + it('should not render', () => { expect(component).toBeTruthy(); expect(deNavMenu.nativeElement).toBeDefined(); @@ -166,6 +185,11 @@ describe('AuthNavMenuComponent', () => { deNavMenuItem = deNavMenu.query(By.css(navMenuItemSelector)); })); + afterEach(() => { + fixture.destroy(); + component = null; + }); + it('should render login dropdown menu', () => { const loginDropdownMenu = deNavMenuItem.query(By.css('div[id=loginDropdownMenu]')); expect(loginDropdownMenu.nativeElement).toBeDefined(); @@ -200,6 +224,10 @@ describe('AuthNavMenuComponent', () => { deNavMenuItem = deNavMenu.query(By.css(navMenuItemSelector)); })); + afterEach(() => { + fixture.destroy(); + component = null; + }); it('should render logout dropdown menu', () => { const logoutDropdownMenu = deNavMenuItem.query(By.css('div[id=logoutDropdownMenu]')); expect(logoutDropdownMenu.nativeElement).toBeDefined(); @@ -223,8 +251,13 @@ describe('AuthNavMenuComponent', () => { AuthNavMenuComponent ], providers: [ - {provide: HostWindowService, useValue: window}, - {provide: AuthService, useValue: {setRedirectUrl: () => { /*empty*/ }}} + { provide: HostWindowService, useValue: window }, + { + provide: AuthService, useValue: { + setRedirectUrl: () => { /*empty*/ + } + } + } ], schemas: [ CUSTOM_ELEMENTS_SCHEMA @@ -234,6 +267,9 @@ describe('AuthNavMenuComponent', () => { })); + beforeEach(() => { + init(); + }); describe('when user is not authenticated', () => { beforeEach(inject([Store], (store: Store) => { @@ -260,6 +296,11 @@ describe('AuthNavMenuComponent', () => { deNavMenuItem = deNavMenu.query(By.css(navMenuItemSelector)); })); + afterEach(() => { + fixture.destroy(); + component = null; + }); + it('should render login link', () => { const loginDropdownMenu = deNavMenuItem.query(By.css('a[id=loginLink]')); expect(loginDropdownMenu.nativeElement).toBeDefined(); @@ -291,6 +332,11 @@ describe('AuthNavMenuComponent', () => { deNavMenuItem = deNavMenu.query(By.css(navMenuItemSelector)); })); + afterEach(() => { + fixture.destroy(); + component = null; + }); + it('should render logout link', inject([Store], (store: Store) => { const logoutDropdownMenu = deNavMenuItem.query(By.css('a[id=logoutLink]')); expect(logoutDropdownMenu.nativeElement).toBeDefined(); diff --git a/src/app/shared/auth-nav-menu/auth-nav-menu.component.ts b/src/app/shared/auth-nav-menu/auth-nav-menu.component.ts index 5fb6aaaabf..4361163538 100644 --- a/src/app/shared/auth-nav-menu/auth-nav-menu.component.ts +++ b/src/app/shared/auth-nav-menu/auth-nav-menu.component.ts @@ -60,15 +60,17 @@ export class AuthNavMenuComponent implements OnInit { this.user = this.store.pipe(select(getAuthenticatedUser)); - this.showAuth = this.store.select(routerStateSelector) - .filter((router: RouterReducerState) => isNotUndefined(router) && isNotUndefined(router.state)) - .map((router: RouterReducerState) => { + this.showAuth = this.store.pipe( + select(routerStateSelector), + filter((router: RouterReducerState) => isNotUndefined(router) && isNotUndefined(router.state)), + map((router: RouterReducerState) => { const url = router.state.url; const show = !router.state.url.startsWith(LOGIN_ROUTE) && !router.state.url.startsWith(LOGOUT_ROUTE); if (show) { this.authService.setRedirectUrl(url); } return show; - }); + }) + ); } } diff --git a/src/app/shared/browse-by/browse-by.component.spec.ts b/src/app/shared/browse-by/browse-by.component.spec.ts index 883d61a221..2417dde7ca 100644 --- a/src/app/shared/browse-by/browse-by.component.spec.ts +++ b/src/app/shared/browse-by/browse-by.component.spec.ts @@ -3,7 +3,7 @@ import { async, ComponentFixture, TestBed } from '@angular/core/testing'; import { TranslateModule } from '@ngx-translate/core'; import { By } from '@angular/platform-browser'; import { NO_ERRORS_SCHEMA } from '@angular/core'; -import { Observable } from 'rxjs/Observable'; +import { of as observableOf } from 'rxjs'; import { SharedModule } from '../shared.module'; describe('BrowseByComponent', () => { @@ -30,7 +30,7 @@ describe('BrowseByComponent', () => { }); it('should display results when objects is not empty', () => { - (comp as any).objects = Observable.of({ + (comp as any).objects = observableOf({ payload: { page: { length: 1 diff --git a/src/app/shared/form/builder/ds-dynamic-form-ui/ds-dynamic-form-control.component.html b/src/app/shared/form/builder/ds-dynamic-form-ui/ds-dynamic-form-control.component.html index d838a90f20..750ef721c2 100644 --- a/src/app/shared/form/builder/ds-dynamic-form-ui/ds-dynamic-form-control.component.html +++ b/src/app/shared/form/builder/ds-dynamic-form-ui/ds-dynamic-form-control.component.html @@ -1,8 +1,8 @@ -
- diff --git a/src/app/shared/form/builder/ds-dynamic-form-ui/ds-dynamic-form-control.component.spec.ts b/src/app/shared/form/builder/ds-dynamic-form-ui/ds-dynamic-form-control.component.spec.ts index ab98476cc3..ca12a7a4b4 100644 --- a/src/app/shared/form/builder/ds-dynamic-form-ui/ds-dynamic-form-control.component.spec.ts +++ b/src/app/shared/form/builder/ds-dynamic-form-ui/ds-dynamic-form-control.component.spec.ts @@ -172,7 +172,6 @@ describe('DsDynamicFormControlComponent test suite', () => { }); fixture.detectChanges(); - console.log(fixture.componentInstance.componentViewContainerRef); testElement = debugElement.query(By.css(`input[id='${testModel.id}']`)); })); diff --git a/src/app/shared/form/builder/ds-dynamic-form-ui/models/date-picker/date-picker.component.ts b/src/app/shared/form/builder/ds-dynamic-form-ui/models/date-picker/date-picker.component.ts index 6cac65ff65..2e22f314ed 100644 --- a/src/app/shared/form/builder/ds-dynamic-form-ui/models/date-picker/date-picker.component.ts +++ b/src/app/shared/form/builder/ds-dynamic-form-ui/models/date-picker/date-picker.component.ts @@ -20,7 +20,6 @@ export class DsDatePickerComponent extends DynamicFormControlComponent implement @Input() bindId = true; @Input() group: FormGroup; @Input() model: DynamicDsDatePickerModel; - // @Input() showErrorMessages = false; // @Input() // minDate; // @Input() diff --git a/src/app/shared/form/builder/ds-dynamic-form-ui/models/ds-dynamic-row-array-model.ts b/src/app/shared/form/builder/ds-dynamic-form-ui/models/ds-dynamic-row-array-model.ts index b38ea142f0..b91af8f0c9 100644 --- a/src/app/shared/form/builder/ds-dynamic-form-ui/models/ds-dynamic-row-array-model.ts +++ b/src/app/shared/form/builder/ds-dynamic-form-ui/models/ds-dynamic-row-array-model.ts @@ -6,16 +6,16 @@ import { import { DYNAMIC_FORM_CONTROL_TYPE_TAG } from './tag/dynamic-tag.model'; export interface DynamicRowArrayModelConfig extends DynamicFormArrayModelConfig { - notRepeteable: boolean; + notRepeatable: boolean; } export class DynamicRowArrayModel extends DynamicFormArrayModel { - @serializable() notRepeteable = false; + @serializable() notRepeatable = false; isRowArray = true; constructor(config: DynamicRowArrayModelConfig, layout?: DynamicFormControlLayout) { super(config, layout); - this.notRepeteable = config.notRepeteable; + this.notRepeatable = config.notRepeatable; } } diff --git a/src/app/shared/form/builder/ds-dynamic-form-ui/models/dynamic-group/dynamic-group.component.spec.ts b/src/app/shared/form/builder/ds-dynamic-form-ui/models/dynamic-group/dynamic-group.component.spec.ts index a3205e69c6..42d8f4b6de 100644 --- a/src/app/shared/form/builder/ds-dynamic-form-ui/models/dynamic-group/dynamic-group.component.spec.ts +++ b/src/app/shared/form/builder/ds-dynamic-form-ui/models/dynamic-group/dynamic-group.component.spec.ts @@ -4,7 +4,6 @@ import { async, ComponentFixture, inject, TestBed, } from '@angular/core/testing import { FormControl, FormGroup, FormsModule, ReactiveFormsModule } from '@angular/forms'; import { TranslateModule } from '@ngx-translate/core'; -import { of as observableOf } from 'rxjs'; import { NgbModule } from '@ng-bootstrap/ng-bootstrap'; import { DsDynamicGroupComponent } from './dynamic-group.components'; @@ -23,63 +22,69 @@ import { Chips } from '../../../../../chips/models/chips.model'; import { FormFieldMetadataValueObject } from '../../../models/form-field-metadata-value.model'; import { DsDynamicInputModel } from '../ds-dynamic-input.model'; import { createTestComponent } from '../../../../../testing/utils'; -import { getMockFormBuilderService } from '../../../../../mocks/mock-form-builder-service'; -import { getMockFormService } from '../../../../../mocks/mock-form-service'; -import { MockComponent } from 'ng-mocks'; import { DynamicFormLayoutService, DynamicFormValidationService } from '@ng-dynamic-forms/core'; +import { MockStore } from '../../../../../testing/mock-store'; +import { Store } from '@ngrx/store'; +import { AppState } from '../../../../../../app.reducer'; -export const FORM_GROUP_TEST_MODEL_CONFIG = { - disabled: false, - errorMessages: {required: 'You must specify at least one author.'}, - formConfiguration: [{ - fields: [{ - hints: 'Enter the name of the author.', - input: {type: 'onebox'}, - label: 'Author', - languageCodes: [], - mandatory: 'true', - mandatoryMessage: 'Required field!', - repeatable: false, - selectableMetadata: [{ - authority: 'RPAuthority', - closed: false, - metadata: 'dc.contributor.author' - }], - } as FormFieldModel] - } as FormRowModel, { - fields: [{ - hints: 'Enter the affiliation of the author.', - input: {type: 'onebox'}, - label: 'Affiliation', - languageCodes: [], - mandatory: 'false', - repeatable: false, - selectableMetadata: [{ - authority: 'OUAuthority', - closed: false, - metadata: 'local.contributor.affiliation' - }] - } as FormFieldModel] - } as FormRowModel], - id: 'dc_contributor_author', - label: 'Authors', - mandatoryField: 'dc.contributor.author', - name: 'dc.contributor.author', - placeholder: 'Authors', - readOnly: false, - relationFields: ['local.contributor.affiliation'], - required: true, - scopeUUID: '43fe1f8c-09a6-4fcf-9c78-5d4fed8f2c8f', - submissionScope: undefined, - validators: {required: null} -} as DynamicGroupModelConfig; +export let FORM_GROUP_TEST_MODEL_CONFIG; -export const FORM_GROUP_TEST_GROUP = new FormGroup({ - dc_contributor_author: new FormControl(), -}); +export let FORM_GROUP_TEST_GROUP; -describe('DsDynamicGroupComponent test suite', () => { - const config = { +let config; + +function init() { + FORM_GROUP_TEST_MODEL_CONFIG = { + disabled: false, + errorMessages: { required: 'You must specify at least one author.' }, + formConfiguration: [{ + fields: [{ + hints: 'Enter the name of the author.', + input: { type: 'onebox' }, + label: 'Author', + languageCodes: [], + mandatory: 'true', + mandatoryMessage: 'Required field!', + repeatable: false, + selectableMetadata: [{ + authority: 'RPAuthority', + closed: false, + metadata: 'dc.contributor.author' + }], + } as FormFieldModel] + } as FormRowModel, { + fields: [{ + hints: 'Enter the affiliation of the author.', + input: { type: 'onebox' }, + label: 'Affiliation', + languageCodes: [], + mandatory: 'false', + repeatable: false, + selectableMetadata: [{ + authority: 'OUAuthority', + closed: false, + metadata: 'local.contributor.affiliation' + }] + } as FormFieldModel] + } as FormRowModel], + id: 'dc_contributor_author', + label: 'Authors', + mandatoryField: 'dc.contributor.author', + name: 'dc.contributor.author', + placeholder: 'Authors', + readOnly: false, + relationFields: ['local.contributor.affiliation'], + required: true, + scopeUUID: '43fe1f8c-09a6-4fcf-9c78-5d4fed8f2c8f', + submissionScope: undefined, + validators: { required: null } + } as DynamicGroupModelConfig; + + FORM_GROUP_TEST_GROUP = new FormGroup({ + dc_contributor_author: new FormControl(), + }); + + config = { form: { validatorMap: { required: 'required', @@ -87,11 +92,15 @@ describe('DsDynamicGroupComponent test suite', () => { } } } as any; + +} + +describe('DsDynamicGroupComponent test suite', () => { let testComp: TestComponent; let groupComp: DsDynamicGroupComponent; let testFixture: ComponentFixture; let groupFixture: ComponentFixture; - // let modelValue: any; + let modelValue: any; let html; let control1: FormControl; let model1: DsDynamicInputModel; @@ -100,7 +109,9 @@ describe('DsDynamicGroupComponent test suite', () => { // async beforeEach beforeEach(async(() => { - + init(); + const store = new MockStore(Object.create(null)); + /* TODO make sure these files use mocks instead of real services/components https://github.com/DSpace/dspace-angular/issues/281 */ TestBed.configureTestingModule({ imports: [ BrowserAnimationsModule, @@ -110,18 +121,20 @@ describe('DsDynamicGroupComponent test suite', () => { TranslateModule.forRoot() ], declarations: [ - MockComponent(FormComponent), + FormComponent, DsDynamicGroupComponent, TestComponent, ], // declare the test component providers: [ ChangeDetectorRef, DsDynamicGroupComponent, - {provide: FormBuilderService, useValue: getMockFormBuilderService()}, - {provide: FormService, useValue: getMockFormService()}, - {provide: GLOBAL_CONFIG, useValue: config}, - {provide: DynamicFormLayoutService, useValue: {}}, - {provide: DynamicFormValidationService, useValue: {}} + DynamicFormValidationService, + DynamicFormLayoutService, + FormBuilderService, + FormComponent, + FormService, + { provide: GLOBAL_CONFIG, useValue: config }, + {provide: Store, useValue: store}, ], schemas: [CUSTOM_ELEMENTS_SCHEMA] }); @@ -143,6 +156,11 @@ describe('DsDynamicGroupComponent test suite', () => { testComp = testFixture.componentInstance; }); + afterEach(() => { + testFixture.destroy(); + testComp = null; + }); + it('should create DsDynamicGroupComponent', inject([DsDynamicGroupComponent], (app: DsDynamicGroupComponent) => { expect(app).toBeDefined(); @@ -158,7 +176,6 @@ describe('DsDynamicGroupComponent test suite', () => { groupComp.group = FORM_GROUP_TEST_GROUP; groupComp.model = new DynamicGroupModel(FORM_GROUP_TEST_MODEL_CONFIG); groupFixture.detectChanges(); - control1 = service.getFormControlById('dc_contributor_author', (groupComp as any).formRef.formGroup, groupComp.formModel) as FormControl; model1 = service.findById('dc_contributor_author', groupComp.formModel) as DsDynamicInputModel; control2 = service.getFormControlById('local_contributor_affiliation', (groupComp as any).formRef.formGroup, groupComp.formModel) as FormControl; @@ -172,123 +189,132 @@ describe('DsDynamicGroupComponent test suite', () => { groupComp = null; }); - // it('should init component properly', inject([FormBuilderService], (service: FormBuilderService) => { - // const formConfig = {rows: groupComp.model.formConfiguration} as SubmissionFormsModel; - // const formModel = service.modelFromConfiguration(formConfig, groupComp.model.scopeUUID, {}, groupComp.model.submissionScope, groupComp.model.readOnly); - // const chips = new Chips([], 'value', 'dc.contributor.author'); - // - // expect(groupComp.formCollapsed).toEqual(observableOf(false)); - // expect(groupComp.formModel.length).toEqual(formModel.length); - // expect(groupComp.chips.getChipsItems()).toEqual(chips.getChipsItems()); - // })); - // - // it('should save a new chips item', () => { - // control1.setValue('test author'); - // (model1 as any).value = new FormFieldMetadataValueObject('test author'); - // control2.setValue('test affiliation'); - // (model2 as any).value = new FormFieldMetadataValueObject('test affiliation'); - // modelValue = [{ - // 'dc.contributor.author': new FormFieldMetadataValueObject('test author'), - // 'local.contributor.affiliation': new FormFieldMetadataValueObject('test affiliation') - // }]; - // groupFixture.detectChanges(); - // - // const buttons = groupFixture.debugElement.nativeElement.querySelectorAll('button'); - // const btnEl = buttons[0]; - // btnEl.click(); - // - // expect(groupComp.chips.getChipsItems()).toEqual(modelValue); - // expect(groupComp.formCollapsed).toEqual(observableOf(true)); - // }); - // - // it('should clear form inputs', () => { - // control1.setValue('test author'); - // (model1 as any).value = new FormFieldMetadataValueObject('test author'); - // control2.setValue('test affiliation'); - // (model2 as any).value = new FormFieldMetadataValueObject('test affiliation'); - // - // groupFixture.detectChanges(); - // - // const buttons = groupFixture.debugElement.nativeElement.querySelectorAll('button'); - // const btnEl = buttons[2]; - // btnEl.click(); - // - // expect(control1.value).toBeNull(); - // expect(control2.value).toBeNull(); - // expect(groupComp.formCollapsed).toEqual(observableOf(false)); - // }); - // }); - // - // describe('when init model value is not empty', () => { - // beforeEach(() => { - // - // groupFixture = TestBed.createComponent(DsDynamicGroupComponent); - // groupComp = groupFixture.componentInstance; // FormComponent test instance - // groupComp.formId = 'testForm'; - // groupComp.group = FORM_GROUP_TEST_GROUP; - // groupComp.model = new DynamicGroupModel(FORM_GROUP_TEST_MODEL_CONFIG); - // modelValue = [{ - // 'dc.contributor.author': new FormFieldMetadataValueObject('test author'), - // 'local.contributor.affiliation': new FormFieldMetadataValueObject('test affiliation') - // }]; - // groupComp.model.value = modelValue; - // groupComp.showErrorMessages = false; - // groupFixture.detectChanges(); - // - // }); - // - // afterEach(() => { - // groupFixture.destroy(); - // groupComp = null; - // }); - // - // it('should init component properly', inject([FormBuilderService], (service: FormBuilderService) => { - // const formConfig = {rows: groupComp.model.formConfiguration} as SubmissionFormsModel; - // const formModel = service.modelFromConfiguration(formConfig, groupComp.model.scopeUUID, {}, groupComp.model.submissionScope, groupComp.model.readOnly); - // const chips = new Chips(modelValue, 'value', 'dc.contributor.author'); - // - // expect(groupComp.formCollapsed).toEqual(observableOf(true)); - // expect(groupComp.formModel.length).toEqual(formModel.length); - // expect(groupComp.chips.getChipsItems()).toEqual(chips.getChipsItems()); - // })); - // - // it('should modify existing chips item', inject([FormBuilderService], (service: FormBuilderService) => { - // groupComp.onChipSelected(0); - // groupFixture.detectChanges(); - // - // control1 = service.getFormControlById('dc_contributor_author', (groupComp as any).formRef.formGroup, groupComp.formModel) as FormControl; - // model1 = service.findById('dc_contributor_author', groupComp.formModel) as DsDynamicInputModel; - // - // control1.setValue('test author modify'); - // (model1 as any).value = new FormFieldMetadataValueObject('test author modify'); - // - // modelValue = [{ - // 'dc.contributor.author': new FormFieldMetadataValueObject('test author modify'), - // 'local.contributor.affiliation': new FormFieldMetadataValueObject('test affiliation') - // }]; - // groupFixture.detectChanges(); - // - // const buttons = groupFixture.debugElement.nativeElement.querySelectorAll('button'); - // const btnEl = buttons[0]; - // btnEl.click(); - // - // groupFixture.detectChanges(); - // - // expect(groupComp.chips.getChipsItems()).toEqual(modelValue); - // expect(groupComp.formCollapsed).toEqual(observableOf(true)); - // })); - // - // it('should delete existing chips item', () => { - // groupComp.onChipSelected(0); - // groupFixture.detectChanges(); - // - // const buttons = groupFixture.debugElement.nativeElement.querySelectorAll('button'); - // const btnEl = buttons[1]; - // btnEl.click(); - // - // expect(groupComp.chips.getChipsItems()).toEqual([]); - // expect(groupComp.formCollapsed).toEqual(observableOf(false)); - // }); + it('should init component properly', inject([FormBuilderService], (service: FormBuilderService) => { + const formConfig = { rows: groupComp.model.formConfiguration } as SubmissionFormsModel; + const formModel = service.modelFromConfiguration(formConfig, groupComp.model.scopeUUID, {}, groupComp.model.submissionScope, groupComp.model.readOnly); + const chips = new Chips([], 'value', 'dc.contributor.author'); + groupComp.formCollapsed.subscribe((value) => { + expect(value).toEqual(false); + }); + expect(groupComp.formModel.length).toEqual(formModel.length); + expect(groupComp.chips.getChipsItems()).toEqual(chips.getChipsItems()); + })); + + it('should save a new chips item', () => { + control1.setValue('test author'); + (model1 as any).value = new FormFieldMetadataValueObject('test author'); + control2.setValue('test affiliation'); + (model2 as any).value = new FormFieldMetadataValueObject('test affiliation'); + modelValue = [{ + 'dc.contributor.author': new FormFieldMetadataValueObject('test author'), + 'local.contributor.affiliation': new FormFieldMetadataValueObject('test affiliation') + }]; + groupFixture.detectChanges(); + + const buttons = groupFixture.debugElement.nativeElement.querySelectorAll('button'); + const btnEl = buttons[0]; + btnEl.click(); + + expect(groupComp.chips.getChipsItems()).toEqual(modelValue); + groupComp.formCollapsed.subscribe((value) => { + expect(value).toEqual(true); + }) + }); + + it('should clear form inputs', () => { + control1.setValue('test author'); + (model1 as any).value = new FormFieldMetadataValueObject('test author'); + control2.setValue('test affiliation'); + (model2 as any).value = new FormFieldMetadataValueObject('test affiliation'); + + groupFixture.detectChanges(); + + const buttons = groupFixture.debugElement.nativeElement.querySelectorAll('button'); + const btnEl = buttons[2]; + btnEl.click(); + + expect(control1.value).toBeNull(); + expect(control2.value).toBeNull(); + groupComp.formCollapsed.subscribe((value) => { + expect(value).toEqual(false); + }); + }); + }); + + describe('when init model value is not empty', () => { + beforeEach(() => { + + groupFixture = TestBed.createComponent(DsDynamicGroupComponent); + groupComp = groupFixture.componentInstance; // FormComponent test instance + groupComp.formId = 'testForm'; + groupComp.group = FORM_GROUP_TEST_GROUP; + groupComp.model = new DynamicGroupModel(FORM_GROUP_TEST_MODEL_CONFIG); + modelValue = [{ + 'dc.contributor.author': new FormFieldMetadataValueObject('test author'), + 'local.contributor.affiliation': new FormFieldMetadataValueObject('test affiliation') + }]; + groupComp.model.value = modelValue; + groupFixture.detectChanges(); + + }); + + afterEach(() => { + groupFixture.destroy(); + groupComp = null; + }); + + it('should init component properly', inject([FormBuilderService], (service: FormBuilderService) => { + const formConfig = { rows: groupComp.model.formConfiguration } as SubmissionFormsModel; + const formModel = service.modelFromConfiguration(formConfig, groupComp.model.scopeUUID, {}, groupComp.model.submissionScope, groupComp.model.readOnly); + const chips = new Chips(modelValue, 'value', 'dc.contributor.author'); + groupComp.formCollapsed.subscribe((value) => { + expect(value).toEqual(true); + }) + expect(groupComp.formModel.length).toEqual(formModel.length); + expect(groupComp.chips.getChipsItems()).toEqual(chips.getChipsItems()); + })); + + it('should modify existing chips item', inject([FormBuilderService], (service: FormBuilderService) => { + groupComp.onChipSelected(0); + groupFixture.detectChanges(); + + control1 = service.getFormControlById('dc_contributor_author', (groupComp as any).formRef.formGroup, groupComp.formModel) as FormControl; + model1 = service.findById('dc_contributor_author', groupComp.formModel) as DsDynamicInputModel; + + control1.setValue('test author modify'); + (model1 as any).value = new FormFieldMetadataValueObject('test author modify'); + + modelValue = [{ + 'dc.contributor.author': new FormFieldMetadataValueObject('test author modify'), + 'local.contributor.affiliation': new FormFieldMetadataValueObject('test affiliation') + }]; + groupFixture.detectChanges(); + + const buttons = groupFixture.debugElement.nativeElement.querySelectorAll('button'); + const btnEl = buttons[0]; + btnEl.click(); + + groupFixture.detectChanges(); + + expect(groupComp.chips.getChipsItems()).toEqual(modelValue); + groupComp.formCollapsed.subscribe((value) => { + expect(value).toEqual(true); + }) + })); + + it('should delete existing chips item', () => { + groupComp.onChipSelected(0); + groupFixture.detectChanges(); + + const buttons = groupFixture.debugElement.nativeElement.querySelectorAll('button'); + const btnEl = buttons[1]; + btnEl.click(); + + expect(groupComp.chips.getChipsItems()).toEqual([]); + groupComp.formCollapsed.subscribe((value) => { + expect(value).toEqual(false); + }) + }); }); }); diff --git a/src/app/shared/form/builder/ds-dynamic-form-ui/models/dynamic-group/dynamic-group.components.ts b/src/app/shared/form/builder/ds-dynamic-form-ui/models/dynamic-group/dynamic-group.components.ts index fa3350e43c..40e337588a 100644 --- a/src/app/shared/form/builder/ds-dynamic-form-ui/models/dynamic-group/dynamic-group.components.ts +++ b/src/app/shared/form/builder/ds-dynamic-form-ui/models/dynamic-group/dynamic-group.components.ts @@ -45,7 +45,6 @@ export class DsDynamicGroupComponent extends DynamicFormControlComponent impleme @Input() formId: string; @Input() group: FormGroup; @Input() model: DynamicGroupModel; - // @Input() showErrorMessages = false; @Output() blur: EventEmitter = new EventEmitter(); @Output() change: EventEmitter = new EventEmitter(); diff --git a/src/app/shared/form/builder/ds-dynamic-form-ui/models/list/dynamic-list.component.ts b/src/app/shared/form/builder/ds-dynamic-form-ui/models/list/dynamic-list.component.ts index f5285ffa87..dc808f4759 100644 --- a/src/app/shared/form/builder/ds-dynamic-form-ui/models/list/dynamic-list.component.ts +++ b/src/app/shared/form/builder/ds-dynamic-form-ui/models/list/dynamic-list.component.ts @@ -33,7 +33,6 @@ export class DsDynamicListComponent extends DynamicFormControlComponent implemen @Input() bindId = true; @Input() group: FormGroup; @Input() model: DynamicListCheckboxGroupModel | DynamicListRadioGroupModel; - // @Input() showErrorMessages = false; @Output() blur: EventEmitter = new EventEmitter(); @Output() change: EventEmitter = new EventEmitter(); diff --git a/src/app/shared/form/builder/ds-dynamic-form-ui/models/lookup/dynamic-lookup.component.spec.ts b/src/app/shared/form/builder/ds-dynamic-form-ui/models/lookup/dynamic-lookup.component.spec.ts index a1ab4dfacd..62e9191893 100644 --- a/src/app/shared/form/builder/ds-dynamic-form-ui/models/lookup/dynamic-lookup.component.spec.ts +++ b/src/app/shared/form/builder/ds-dynamic-form-ui/models/lookup/dynamic-lookup.component.spec.ts @@ -18,16 +18,13 @@ import { DsDynamicLookupComponent } from './dynamic-lookup.component'; import { DynamicLookupModel } from './dynamic-lookup.model'; import { InfiniteScrollModule } from 'ngx-infinite-scroll'; import { TranslateModule } from '@ngx-translate/core'; -import { FormBuilderService } from '../../../form-builder.service'; -import { FormService } from '../../../../form.service'; -import { FormComponent } from '../../../../form.component'; import { FormFieldMetadataValueObject } from '../../../models/form-field-metadata-value.model'; import { By } from '@angular/platform-browser'; import { AuthorityValueModel } from '../../../../../../core/integration/models/authority-value.model'; -import { DynamicLookupNameModel } from './dynamic-lookup-name.model'; import { createTestComponent } from '../../../../../testing/utils'; +import { DynamicLookupNameModel } from './dynamic-lookup-name.model'; -export const LOOKUP_TEST_MODEL_CONFIG = { +let LOOKUP_TEST_MODEL_CONFIG = { authorityOptions: { closed: false, metadata: 'lookup', @@ -35,7 +32,7 @@ export const LOOKUP_TEST_MODEL_CONFIG = { scope: 'c1c16450-d56f-41bc-bb81-27f1d1eb5c23' } as AuthorityOptions, disabled: false, - errorMessages: {required: 'Required field.'}, + errorMessages: { required: 'Required field.' }, id: 'lookup', label: 'Author', maxOptions: 10, @@ -45,11 +42,11 @@ export const LOOKUP_TEST_MODEL_CONFIG = { required: true, repeatable: true, separator: ',', - validators: {required: null}, + validators: { required: null }, value: undefined }; -export const LOOKUP_NAME_TEST_MODEL_CONFIG = { +let LOOKUP_NAME_TEST_MODEL_CONFIG = { authorityOptions: { closed: false, metadata: 'lookup-name', @@ -57,7 +54,7 @@ export const LOOKUP_NAME_TEST_MODEL_CONFIG = { scope: 'c1c16450-d56f-41bc-bb81-27f1d1eb5c23' } as AuthorityOptions, disabled: false, - errorMessages: {required: 'Required field.'}, + errorMessages: { required: 'Required field.' }, id: 'lookupName', label: 'Author', maxOptions: 10, @@ -67,16 +64,67 @@ export const LOOKUP_NAME_TEST_MODEL_CONFIG = { required: true, repeatable: true, separator: ',', - validators: {required: null}, + validators: { required: null }, value: undefined }; -export const LOOKUP_TEST_GROUP = new FormGroup({ +let LOOKUP_TEST_GROUP = new FormGroup({ lookup: new FormControl(), lookupName: new FormControl() }); describe('Dynamic Lookup component', () => { + function init() { + LOOKUP_TEST_MODEL_CONFIG = { + authorityOptions: { + closed: false, + metadata: 'lookup', + name: 'RPAuthority', + scope: 'c1c16450-d56f-41bc-bb81-27f1d1eb5c23' + } as AuthorityOptions, + disabled: false, + errorMessages: { required: 'Required field.' }, + id: 'lookup', + label: 'Author', + maxOptions: 10, + name: 'lookup', + placeholder: 'Author', + readOnly: false, + required: true, + repeatable: true, + separator: ',', + validators: { required: null }, + value: undefined + }; + + LOOKUP_NAME_TEST_MODEL_CONFIG = { + authorityOptions: { + closed: false, + metadata: 'lookup-name', + name: 'RPAuthority', + scope: 'c1c16450-d56f-41bc-bb81-27f1d1eb5c23' + } as AuthorityOptions, + disabled: false, + errorMessages: { required: 'Required field.' }, + id: 'lookupName', + label: 'Author', + maxOptions: 10, + name: 'lookupName', + placeholder: 'Author', + readOnly: false, + required: true, + repeatable: true, + separator: ',', + validators: { required: null }, + value: undefined + }; + + LOOKUP_TEST_GROUP = new FormGroup({ + lookup: new FormControl(), + lookupName: new FormControl() + }); + + } let testComp: TestComponent; let lookupComp: DsDynamicLookupComponent; @@ -84,11 +132,11 @@ describe('Dynamic Lookup component', () => { let lookupFixture: ComponentFixture; let html; - const authorityServiceStub = new AuthorityServiceStub(); - + let authorityServiceStub; // async beforeEach beforeEach(async(() => { - + const authorityService = new AuthorityServiceStub(); + authorityServiceStub = authorityService; TestBed.configureTestingModule({ imports: [ DynamicFormsCoreModule, @@ -106,16 +154,19 @@ describe('Dynamic Lookup component', () => { providers: [ ChangeDetectorRef, DsDynamicLookupComponent, - {provide: AuthorityService, useValue: authorityServiceStub}, - {provide: DynamicFormLayoutService, useValue: {}}, - {provide: DynamicFormValidationService, useValue: {}} + { provide: AuthorityService, useValue: authorityService }, + { provide: DynamicFormLayoutService, useValue: {} }, + { provide: DynamicFormValidationService, useValue: {} } ], schemas: [CUSTOM_ELEMENTS_SCHEMA] }); - })); - describe('', () => { + beforeEach(() => { + init(); + }); + + describe('DynamicLookUpComponent', () => { // synchronous beforeEach beforeEach(() => { html = ` @@ -130,200 +181,236 @@ describe('Dynamic Lookup component', () => { testFixture = createTestComponent(html, TestComponent) as ComponentFixture; testComp = testFixture.componentInstance; }); - + afterEach(() => { + testFixture.destroy(); + testComp = null; + }); it('should create DsDynamicLookupComponent', inject([DsDynamicLookupComponent], (app: DsDynamicLookupComponent) => { expect(app).toBeDefined(); })); - }); - describe('when model is DynamicLookupModel', () => { + describe('when model is DynamicLookupModel', () => { - describe('', () => { - beforeEach(() => { + describe('', () => { + beforeEach(() => { + + lookupFixture = TestBed.createComponent(DsDynamicLookupComponent); + lookupComp = lookupFixture.componentInstance; // FormComponent test instance + lookupComp.group = LOOKUP_TEST_GROUP; + lookupComp.model = new DynamicLookupModel(LOOKUP_TEST_MODEL_CONFIG); + lookupFixture.detectChanges(); + }); + afterEach(() => { + lookupFixture.destroy(); + lookupComp = null; + }); + it('should render only an input element', () => { + const de = lookupFixture.debugElement.queryAll(By.css('input.form-control')); + expect(de.length).toBe(1); + }); - lookupFixture = TestBed.createComponent(DsDynamicLookupComponent); - lookupComp = lookupFixture.componentInstance; // FormComponent test instance - lookupComp.group = LOOKUP_TEST_GROUP; - lookupComp.model = new DynamicLookupModel(LOOKUP_TEST_MODEL_CONFIG); - lookupFixture.detectChanges(); }); - it('should render only an input element', () => { - const de = lookupFixture.debugElement.queryAll(By.css('input.form-control')); - expect(de.length).toBe(1); + describe('and init model value is empty', () => { + beforeEach(() => { + lookupFixture = TestBed.createComponent(DsDynamicLookupComponent); + lookupComp = lookupFixture.componentInstance; // FormComponent test instance + lookupComp.group = LOOKUP_TEST_GROUP; + lookupComp.model = new DynamicLookupModel(LOOKUP_TEST_MODEL_CONFIG); + lookupFixture.detectChanges(); + }); + + afterEach(() => { + lookupFixture.destroy(); + lookupComp = null; + }); + + it('should init component properly', () => { + expect(lookupComp.firstInputValue).toBe(''); + }); + + it('should return search results', fakeAsync(() => { + const de = lookupFixture.debugElement.queryAll(By.css('button')); + const btnEl = de[0].nativeElement; + const results$ = authorityServiceStub.getEntriesByName({} as any); + + lookupComp.firstInputValue = 'test'; + lookupFixture.detectChanges(); + + btnEl.click(); + tick(); + lookupFixture.detectChanges(); + results$.subscribe((results) => { + expect(lookupComp.optionsList).toEqual(results.payload); + }); + + })); + + it('should select a results entry properly', fakeAsync(() => { + let de = lookupFixture.debugElement.queryAll(By.css('button')); + const btnEl = de[0].nativeElement; + const selectedValue = Object.assign(new AuthorityValueModel(), { + id: 1, + display: 'one', + value: 1 + }); + spyOn(lookupComp.change, 'emit'); + lookupComp.firstInputValue = 'test'; + lookupFixture.detectChanges(); + btnEl.click(); + tick(); + lookupFixture.detectChanges(); + de = lookupFixture.debugElement.queryAll(By.css('button.dropdown-item')); + const entryEl = de[0].nativeElement; + entryEl.click(); + lookupFixture.detectChanges(); + expect(lookupComp.firstInputValue).toEqual('one'); + expect(lookupComp.model.value).toEqual(selectedValue); + expect(lookupComp.change.emit).toHaveBeenCalled(); + })); + + it('should set model.value on input type when AuthorityOptions.closed is false', fakeAsync(() => { + lookupComp.firstInputValue = 'test'; + lookupFixture.detectChanges(); + + lookupComp.onInput(new Event('input')); + expect(lookupComp.model.value).toEqual(new FormFieldMetadataValueObject('test')) + + })); + + it('should not set model.value on input type when AuthorityOptions.closed is true', () => { + lookupComp.model.authorityOptions.closed = true; + lookupComp.firstInputValue = 'test'; + lookupFixture.detectChanges(); + + lookupComp.onInput(new Event('input')); + expect(lookupComp.model.value).not.toBeDefined(); + + }); }); - }); + describe('and init model value is not empty', () => { + beforeEach(() => { - describe('and init model value is empty', () => { - beforeEach(() => { - - lookupFixture = TestBed.createComponent(DsDynamicLookupComponent); - lookupComp = lookupFixture.componentInstance; // FormComponent test instance - lookupComp.group = LOOKUP_TEST_GROUP; - lookupComp.model = new DynamicLookupModel(LOOKUP_TEST_MODEL_CONFIG); - lookupFixture.detectChanges(); - }); - - it('should init component properly', () => { - expect(lookupComp.firstInputValue).toBe(''); - }); - - it('should return search results', fakeAsync(() => { - const de = lookupFixture.debugElement.queryAll(By.css('button')); - const btnEl = de[0].nativeElement; - const results$ = authorityServiceStub.getEntriesByName({} as any); - - lookupComp.firstInputValue = 'test'; - lookupFixture.detectChanges(); - - btnEl.click(); - tick(); - lookupFixture.detectChanges(); - results$.subscribe((results) => { - expect(lookupComp.optionsList).toEqual(results.payload); - }) - - })); - - it('should select a results entry properly', fakeAsync(() => { - let de = lookupFixture.debugElement.queryAll(By.css('button')); - const btnEl = de[0].nativeElement; - const selectedValue = Object.assign(new AuthorityValueModel(), {id: 1, display: 'one', value: 1}); - spyOn(lookupComp.change, 'emit'); - console.log("debugger"); - lookupComp.firstInputValue = 'test'; - lookupFixture.detectChanges(); - btnEl.click(); - tick(); - lookupFixture.detectChanges(); - de = lookupFixture.debugElement.queryAll(By.css('button.dropdown-item')); - const entryEl = de[0].nativeElement; - entryEl.click(); - - expect(lookupComp.firstInputValue).toEqual('one'); - expect(lookupComp.model.value).toEqual(selectedValue); - expect(lookupComp.change.emit).toHaveBeenCalled(); - })); - - it('should set model.value on input type when AuthorityOptions.closed is false', fakeAsync(() => { - lookupComp.firstInputValue = 'test'; - lookupFixture.detectChanges(); - - lookupComp.onInput(new Event('input')); - expect(lookupComp.model.value).toEqual(new FormFieldMetadataValueObject('test')) - - })); - - it('should not set model.value on input type when AuthorityOptions.closed is true', () => { - lookupComp.model.authorityOptions.closed = true; - lookupComp.firstInputValue = 'test'; - lookupFixture.detectChanges(); - - lookupComp.onInput(new Event('input')); - expect(lookupComp.model.value).not.toBeDefined(); + lookupFixture = TestBed.createComponent(DsDynamicLookupComponent); + lookupComp = lookupFixture.componentInstance; // FormComponent test instance + lookupComp.group = LOOKUP_TEST_GROUP; + lookupComp.model = new DynamicLookupModel(LOOKUP_TEST_MODEL_CONFIG); + lookupComp.model.value = new FormFieldMetadataValueObject('test', null, 'test001'); + lookupFixture.detectChanges(); + // spyOn(store, 'dispatch'); + }); + afterEach(() => { + lookupFixture.destroy(); + lookupComp = null; + }); + it('should init component properly', () => { + expect(lookupComp.firstInputValue).toBe('test'); + }); }); }); - describe('and init model value is not empty', () => { - beforeEach(() => { + describe('when model is DynamicLookupNameModel', () => { - lookupFixture = TestBed.createComponent(DsDynamicLookupComponent); - lookupComp = lookupFixture.componentInstance; // FormComponent test instance - lookupComp.group = LOOKUP_TEST_GROUP; - lookupComp.model = new DynamicLookupModel(LOOKUP_TEST_MODEL_CONFIG); - lookupComp.model.value = new FormFieldMetadataValueObject('test', null, 'test001'); - lookupFixture.detectChanges(); + describe('', () => { + beforeEach(() => { + + lookupFixture = TestBed.createComponent(DsDynamicLookupComponent); + lookupComp = lookupFixture.componentInstance; // FormComponent test instance + lookupComp.group = LOOKUP_TEST_GROUP; + lookupComp.model = new DynamicLookupNameModel(LOOKUP_NAME_TEST_MODEL_CONFIG); + lookupFixture.detectChanges(); + + // spyOn(store, 'dispatch'); + }); + afterEach(() => { + lookupFixture.destroy(); + lookupComp = null; + }); + it('should render two input element', () => { + const de = lookupFixture.debugElement.queryAll(By.css('input.form-control')); + expect(de.length).toBe(2); + }); - // spyOn(store, 'dispatch'); }); - it('should init component properly', () => { - expect(lookupComp.firstInputValue).toBe('test') + describe('and init model value is empty', () => { + + beforeEach(() => { + + lookupFixture = TestBed.createComponent(DsDynamicLookupComponent); + lookupComp = lookupFixture.componentInstance; // FormComponent test instance + lookupComp.group = LOOKUP_TEST_GROUP; + lookupComp.model = new DynamicLookupNameModel(LOOKUP_NAME_TEST_MODEL_CONFIG); + lookupFixture.detectChanges(); + }); + + afterEach(() => { + lookupFixture.destroy(); + lookupComp = null; + }); + + it('should select a results entry properly', fakeAsync(() => { + const payload = [ + Object.assign(new AuthorityValueModel(), { + id: 1, + display: 'Name, Lastname', + value: 1 + }), + Object.assign(new AuthorityValueModel(), { + id: 2, + display: 'NameTwo, LastnameTwo', + value: 2 + }), + ]; + let de = lookupFixture.debugElement.queryAll(By.css('button')); + const btnEl = de[0].nativeElement; + const selectedValue = Object.assign(new AuthorityValueModel(), { + id: 1, + display: 'Name, Lastname', + value: 1 + }); + spyOn(lookupComp.change, 'emit'); + authorityServiceStub.setNewPayload(payload); + lookupComp.firstInputValue = 'test'; + lookupFixture.detectChanges(); + btnEl.click(); + tick(); + lookupFixture.detectChanges(); + de = lookupFixture.debugElement.queryAll(By.css('button.dropdown-item')); + const entryEl = de[0].nativeElement; + entryEl.click(); + + expect(lookupComp.firstInputValue).toEqual('Name'); + expect(lookupComp.secondInputValue).toEqual('Lastname'); + expect(lookupComp.model.value).toEqual(selectedValue); + expect(lookupComp.change.emit).toHaveBeenCalled(); + })); + }); + + describe('and init model value is not empty', () => { + beforeEach(() => { + + lookupFixture = TestBed.createComponent(DsDynamicLookupComponent); + lookupComp = lookupFixture.componentInstance; // FormComponent test instance + lookupComp.group = LOOKUP_TEST_GROUP; + lookupComp.model = new DynamicLookupNameModel(LOOKUP_NAME_TEST_MODEL_CONFIG); + lookupComp.model.value = new FormFieldMetadataValueObject('Name, Lastname', null, 'test001'); + lookupFixture.detectChanges(); + + }); + afterEach(() => { + lookupFixture.destroy(); + lookupComp = null; + }); + it('should init component properly', () => { + expect(lookupComp.firstInputValue).toBe('Name'); + expect(lookupComp.secondInputValue).toBe('Lastname'); + }); }); }); }); - - describe('when model is DynamicLookupNameModel', () => { - - describe('', () => { - beforeEach(() => { - - lookupFixture = TestBed.createComponent(DsDynamicLookupComponent); - lookupComp = lookupFixture.componentInstance; // FormComponent test instance - lookupComp.group = LOOKUP_TEST_GROUP; - lookupComp.model = new DynamicLookupNameModel(LOOKUP_NAME_TEST_MODEL_CONFIG); - lookupFixture.detectChanges(); - - // spyOn(store, 'dispatch'); - }); - - it('should render two input element', () => { - const de = lookupFixture.debugElement.queryAll(By.css('input.form-control')); - expect(de.length).toBe(2); - }); - - }); - - describe('and init model value is empty', () => { - - beforeEach(() => { - - lookupFixture = TestBed.createComponent(DsDynamicLookupComponent); - lookupComp = lookupFixture.componentInstance; // FormComponent test instance - lookupComp.group = LOOKUP_TEST_GROUP; - lookupComp.model = new DynamicLookupNameModel(LOOKUP_NAME_TEST_MODEL_CONFIG); - lookupFixture.detectChanges(); - }); - - it('should select a results entry properly', fakeAsync(() => { - const payload = [ - Object.assign(new AuthorityValueModel(), {id: 1, display: 'Name, Lastname', value: 1}), - Object.assign(new AuthorityValueModel(), {id: 2, display: 'NameTwo, LastnameTwo', value: 2}), - ]; - let de = lookupFixture.debugElement.queryAll(By.css('button')); - const btnEl = de[0].nativeElement; - const selectedValue = Object.assign(new AuthorityValueModel(), {id: 1, display: 'Name, Lastname', value: 1}); - - spyOn(lookupComp.change, 'emit'); - authorityServiceStub.setNewPayload(payload); - lookupComp.firstInputValue = 'test'; - lookupFixture.detectChanges(); - btnEl.click(); - tick(); - lookupFixture.detectChanges(); - de = lookupFixture.debugElement.queryAll(By.css('button.dropdown-item')); - const entryEl = de[0].nativeElement; - entryEl.click(); - - expect(lookupComp.firstInputValue).toEqual('Name'); - expect(lookupComp.secondInputValue).toEqual('Lastname'); - expect(lookupComp.model.value).toEqual(selectedValue); - expect(lookupComp.change.emit).toHaveBeenCalled(); - })); - - }); - - describe('and init model value is not empty', () => { - beforeEach(() => { - - lookupFixture = TestBed.createComponent(DsDynamicLookupComponent); - lookupComp = lookupFixture.componentInstance; // FormComponent test instance - lookupComp.group = LOOKUP_TEST_GROUP; - lookupComp.model = new DynamicLookupNameModel(LOOKUP_NAME_TEST_MODEL_CONFIG); - lookupComp.model.value = new FormFieldMetadataValueObject('Name, Lastname', null, 'test001'); - lookupFixture.detectChanges(); - - }); - - it('should init component properly', () => { - expect(lookupComp.firstInputValue).toBe('Name'); - expect(lookupComp.secondInputValue).toBe('Lastname'); - }); - }); - - }); }); // declare a test component @@ -338,7 +425,4 @@ class TestComponent { inputLookupModelConfig = LOOKUP_TEST_MODEL_CONFIG; model = new DynamicLookupModel(this.inputLookupModelConfig); - - showErrorMessages = false; - } diff --git a/src/app/shared/form/builder/ds-dynamic-form-ui/models/lookup/dynamic-lookup.component.ts b/src/app/shared/form/builder/ds-dynamic-form-ui/models/lookup/dynamic-lookup.component.ts index abe14dfb49..2a2ee64e9e 100644 --- a/src/app/shared/form/builder/ds-dynamic-form-ui/models/lookup/dynamic-lookup.component.ts +++ b/src/app/shared/form/builder/ds-dynamic-form-ui/models/lookup/dynamic-lookup.component.ts @@ -28,7 +28,6 @@ export class DsDynamicLookupComponent extends DynamicFormControlComponent implem @Input() bindId = true; @Input() group: FormGroup; @Input() model: DynamicLookupModel | DynamicLookupNameModel; - // @Input() showErrorMessages = false; @Output() blur: EventEmitter = new EventEmitter(); @Output() change: EventEmitter = new EventEmitter(); diff --git a/src/app/shared/form/builder/ds-dynamic-form-ui/models/scrollable-dropdown/dynamic-scrollable-dropdown.component.ts b/src/app/shared/form/builder/ds-dynamic-form-ui/models/scrollable-dropdown/dynamic-scrollable-dropdown.component.ts index 4b259b6cce..02468f9fbf 100644 --- a/src/app/shared/form/builder/ds-dynamic-form-ui/models/scrollable-dropdown/dynamic-scrollable-dropdown.component.ts +++ b/src/app/shared/form/builder/ds-dynamic-form-ui/models/scrollable-dropdown/dynamic-scrollable-dropdown.component.ts @@ -26,7 +26,6 @@ export class DsDynamicScrollableDropdownComponent extends DynamicFormControlComp @Input() bindId = true; @Input() group: FormGroup; @Input() model: DynamicScrollableDropdownModel; - // @Input() showErrorMessages = false; @Output() blur: EventEmitter = new EventEmitter(); @Output() change: EventEmitter = new EventEmitter(); diff --git a/src/app/shared/form/builder/ds-dynamic-form-ui/models/tag/dynamic-tag.component.spec.ts b/src/app/shared/form/builder/ds-dynamic-form-ui/models/tag/dynamic-tag.component.spec.ts index 656d43bb68..9eaa23c004 100644 --- a/src/app/shared/form/builder/ds-dynamic-form-ui/models/tag/dynamic-tag.component.spec.ts +++ b/src/app/shared/form/builder/ds-dynamic-form-ui/models/tag/dynamic-tag.component.spec.ts @@ -37,27 +37,32 @@ function createKeyUpEvent(key: number) { return event; } -export const TAG_TEST_GROUP = new FormGroup({ - tag: new FormControl(), -}); +let TAG_TEST_GROUP; +let TAG_TEST_MODEL_CONFIG; -export const TAG_TEST_MODEL_CONFIG = { - authorityOptions: { - closed: false, - metadata: 'tag', - name: 'common_iso_languages', - scope: 'c1c16450-d56f-41bc-bb81-27f1d1eb5c23' - } as AuthorityOptions, - disabled: false, - id: 'tag', - label: 'Keywords', - minChars: 3, - name: 'tag', - placeholder: 'Keywords', - readOnly: false, - required: false, - repeatable: false -}; +function init() { + TAG_TEST_GROUP = new FormGroup({ + tag: new FormControl(), + }); + + TAG_TEST_MODEL_CONFIG = { + authorityOptions: { + closed: false, + metadata: 'tag', + name: 'common_iso_languages', + scope: 'c1c16450-d56f-41bc-bb81-27f1d1eb5c23' + } as AuthorityOptions, + disabled: false, + id: 'tag', + label: 'Keywords', + minChars: 3, + name: 'tag', + placeholder: 'Keywords', + readOnly: false, + required: false, + repeatable: false + }; +} describe('DsDynamicTagComponent test suite', () => { @@ -72,7 +77,7 @@ describe('DsDynamicTagComponent test suite', () => { // async beforeEach beforeEach(async(() => { const authorityServiceStub = new AuthorityServiceStub(); - + init(); TestBed.configureTestingModule({ imports: [ DynamicFormsCoreModule, @@ -88,10 +93,10 @@ describe('DsDynamicTagComponent test suite', () => { providers: [ ChangeDetectorRef, DsDynamicTagComponent, - {provide: AuthorityService, useValue: authorityServiceStub}, - {provide: GLOBAL_CONFIG, useValue: {} as GlobalConfig}, - {provide: DynamicFormLayoutService, useValue: {}}, - {provide: DynamicFormValidationService, useValue: {}} + { provide: AuthorityService, useValue: authorityServiceStub }, + { provide: GLOBAL_CONFIG, useValue: {} as GlobalConfig }, + { provide: DynamicFormLayoutService, useValue: {} }, + { provide: DynamicFormValidationService, useValue: {} } ], schemas: [CUSTOM_ELEMENTS_SCHEMA] }); @@ -112,7 +117,9 @@ describe('DsDynamicTagComponent test suite', () => { testFixture = createTestComponent(html, TestComponent) as ComponentFixture; testComp = testFixture.componentInstance; }); - + afterEach(() => { + testFixture.destroy(); + }); it('should create DsDynamicTagComponent', inject([DsDynamicTagComponent], (app: DsDynamicTagComponent) => { expect(app).toBeDefined(); @@ -138,6 +145,7 @@ describe('DsDynamicTagComponent test suite', () => { it('should init component properly', () => { chips = new Chips([], 'display'); expect(tagComp.chips.getChipsItems()).toEqual(chips.getChipsItems()); + expect(tagComp.searchOptions).toBeDefined(); }); @@ -151,10 +159,14 @@ describe('DsDynamicTagComponent test suite', () => { it('should select a results entry properly', fakeAsync(() => { modelValue = [ - Object.assign(new AuthorityValueModel(), {id: 1, display: 'Name, Lastname', value: 1}) + Object.assign(new AuthorityValueModel(), { id: 1, display: 'Name, Lastname', value: 1 }) ]; const event: NgbTypeaheadSelectItemEvent = { - item: Object.assign(new AuthorityValueModel(), {id: 1, display: 'Name, Lastname', value: 1}), + item: Object.assign(new AuthorityValueModel(), { + id: 1, + display: 'Name, Lastname', + value: 1 + }), preventDefault: () => { return; } diff --git a/src/app/shared/form/builder/ds-dynamic-form-ui/models/tag/dynamic-tag.component.ts b/src/app/shared/form/builder/ds-dynamic-form-ui/models/tag/dynamic-tag.component.ts index ce8d85b5e4..b8ef84d48d 100644 --- a/src/app/shared/form/builder/ds-dynamic-form-ui/models/tag/dynamic-tag.component.ts +++ b/src/app/shared/form/builder/ds-dynamic-form-ui/models/tag/dynamic-tag.component.ts @@ -1,4 +1,3 @@ - import {of as observableOf, Observable } from 'rxjs'; import {catchError, debounceTime, distinctUntilChanged, tap, switchMap, map, merge} from 'rxjs/operators'; @@ -29,7 +28,6 @@ export class DsDynamicTagComponent extends DynamicFormControlComponent implement @Input() bindId = true; @Input() group: FormGroup; @Input() model: DynamicTagModel; - // @Input() showErrorMessages = false; @Output() blur: EventEmitter = new EventEmitter(); @Output() change: EventEmitter = new EventEmitter(); @@ -80,12 +78,13 @@ export class DsDynamicTagComponent extends DynamicFormControlComponent implement private cdr: ChangeDetectorRef, protected layoutService: DynamicFormLayoutService, protected validationService: DynamicFormValidationService - ) { + ) { super(layoutService, validationService); } ngOnInit() { this.hasAuthority = this.model.authorityOptions && hasValue(this.model.authorityOptions.name); + if (this.hasAuthority) { this.searchOptions = new IntegrationSearchOptions( this.model.authorityOptions.scope, diff --git a/src/app/shared/form/builder/ds-dynamic-form-ui/models/typeahead/dynamic-typeahead.component.spec.ts b/src/app/shared/form/builder/ds-dynamic-form-ui/models/typeahead/dynamic-typeahead.component.spec.ts index eb50ae732f..c950f8f4ef 100644 --- a/src/app/shared/form/builder/ds-dynamic-form-ui/models/typeahead/dynamic-typeahead.component.spec.ts +++ b/src/app/shared/form/builder/ds-dynamic-form-ui/models/typeahead/dynamic-typeahead.component.spec.ts @@ -22,29 +22,34 @@ import { DynamicTypeaheadModel } from './dynamic-typeahead.model'; import { FormFieldMetadataValueObject } from '../../../models/form-field-metadata-value.model'; import { createTestComponent } from '../../../../../testing/utils'; -export const TYPEAHEAD_TEST_GROUP = new FormGroup({ - typeahead: new FormControl(), -}); +export let TYPEAHEAD_TEST_GROUP; -export const TYPEAHEAD_TEST_MODEL_CONFIG = { - authorityOptions: { - closed: false, - metadata: 'typeahead', - name: 'EVENTAuthority', - scope: 'c1c16450-d56f-41bc-bb81-27f1d1eb5c23' - } as AuthorityOptions, - disabled: false, - id: 'typeahead', - label: 'Conference', - minChars: 3, - name: 'typeahead', - placeholder: 'Conference', - readOnly: false, - required: false, - repeatable: false, - value: undefined -}; +export let TYPEAHEAD_TEST_MODEL_CONFIG; +function init() { + TYPEAHEAD_TEST_GROUP = new FormGroup({ + typeahead: new FormControl(), + }); + + TYPEAHEAD_TEST_MODEL_CONFIG = { + authorityOptions: { + closed: false, + metadata: 'typeahead', + name: 'EVENTAuthority', + scope: 'c1c16450-d56f-41bc-bb81-27f1d1eb5c23' + } as AuthorityOptions, + disabled: false, + id: 'typeahead', + label: 'Conference', + minChars: 3, + name: 'typeahead', + placeholder: 'Conference', + readOnly: false, + required: false, + repeatable: false, + value: undefined + }; +} describe('DsDynamicTypeaheadComponent test suite', () => { let testComp: TestComponent; @@ -56,7 +61,7 @@ describe('DsDynamicTypeaheadComponent test suite', () => { // async beforeEach beforeEach(async(() => { const authorityServiceStub = new AuthorityServiceStub(); - + init() TestBed.configureTestingModule({ imports: [ DynamicFormsCoreModule, @@ -72,9 +77,9 @@ describe('DsDynamicTypeaheadComponent test suite', () => { providers: [ ChangeDetectorRef, DsDynamicTypeaheadComponent, - {provide: AuthorityService, useValue: authorityServiceStub}, - {provide: DynamicFormLayoutService, useValue: {}}, - {provide: DynamicFormValidationService, useValue: {}} + { provide: AuthorityService, useValue: authorityServiceStub }, + { provide: DynamicFormLayoutService, useValue: {} }, + { provide: DynamicFormValidationService, useValue: {} } ], schemas: [CUSTOM_ELEMENTS_SCHEMA] }); @@ -96,6 +101,9 @@ describe('DsDynamicTypeaheadComponent test suite', () => { testComp = testFixture.componentInstance; }); + afterEach(() => { + testFixture.destroy(); + }); it('should create DsDynamicTypeaheadComponent', inject([DsDynamicTypeaheadComponent], (app: DsDynamicTypeaheadComponent) => { expect(app).toBeDefined(); @@ -221,6 +229,4 @@ class TestComponent { model = new DynamicTypeaheadModel(TYPEAHEAD_TEST_MODEL_CONFIG); - showErrorMessages = false; - } diff --git a/src/app/shared/form/builder/ds-dynamic-form-ui/models/typeahead/dynamic-typeahead.component.ts b/src/app/shared/form/builder/ds-dynamic-form-ui/models/typeahead/dynamic-typeahead.component.ts index 482820931f..58f8030bcc 100644 --- a/src/app/shared/form/builder/ds-dynamic-form-ui/models/typeahead/dynamic-typeahead.component.ts +++ b/src/app/shared/form/builder/ds-dynamic-form-ui/models/typeahead/dynamic-typeahead.component.ts @@ -26,7 +26,6 @@ export class DsDynamicTypeaheadComponent extends DynamicFormControlComponent imp @Input() bindId = true; @Input() group: FormGroup; @Input() model: DynamicTypeaheadModel; - @Input() showErrorMessages = false; @Output() blur: EventEmitter = new EventEmitter(); @Output() change: EventEmitter = new EventEmitter(); diff --git a/src/app/shared/form/builder/form-builder.service.spec.ts b/src/app/shared/form/builder/form-builder.service.spec.ts index 4e9f720e4e..5266afabfd 100644 --- a/src/app/shared/form/builder/form-builder.service.spec.ts +++ b/src/app/shared/form/builder/form-builder.service.spec.ts @@ -254,7 +254,7 @@ describe('FormBuilderService test suite', () => { { id: 'testFormRowArray', initialCount: 5, - notRepeteable: false, + notRepeatable: false, groupFactory: () => { return [ new DynamicInputModel({id: 'testFormRowArrayGroupInput'}) diff --git a/src/app/shared/form/builder/parsers/field-parser.ts b/src/app/shared/form/builder/parsers/field-parser.ts index f37b3868f3..3286b3fdbb 100644 --- a/src/app/shared/form/builder/parsers/field-parser.ts +++ b/src/app/shared/form/builder/parsers/field-parser.ts @@ -35,7 +35,7 @@ export abstract class FieldParser { id: uniqueId() + '_array', label: this.configData.label, initialCount: this.getInitArrayIndex(), - notRepeteable: !this.configData.repeatable, + notRepeatable: !this.configData.repeatable, groupFactory: () => { let model; if ((arrayCounter === 0)) { diff --git a/src/app/shared/form/form.component.html b/src/app/shared/form/form.component.html index 1b5f2ef72f..958c9a6c73 100644 --- a/src/app/shared/form/form.component.html +++ b/src/app/shared/form/form.component.html @@ -14,7 +14,7 @@ -
-
-
-
- - diff --git a/src/app/+collection-page/collection-page.component.ts b/src/app/+collection-page/collection-page.component.ts index 95aa8ddc4a..047613d6d1 100644 --- a/src/app/+collection-page/collection-page.component.ts +++ b/src/app/+collection-page/collection-page.component.ts @@ -39,8 +39,6 @@ export class CollectionPageComponent implements OnInit, OnDestroy { sortConfig: SortOptions; private subs: Subscription[] = []; private collectionId: string; - href: string; - newname: string; constructor( private collectionDataService: CollectionDataService, @@ -77,12 +75,8 @@ export class CollectionPageComponent implements OnInit, OnDestroy { pagination: pagination, sort: this.sortConfig }); - }) - ); - this.collectionRD$.pipe(first()).subscribe((crd) => { - this.href = crd.payload.self; - this.newname = crd.payload.name; - }); + })); + } updatePage(searchOptions) { @@ -115,9 +109,4 @@ export class CollectionPageComponent implements OnInit, OnDestroy { } }) } - - patchIt(): void { - console.log('patching it!', this.href, this.newname); - this.collectionDataService.patch(this.href, [{ op: 'replace', path: '/name', value: this.newname }]); - } } From 5b71788a20993670ccd12a3d14296714aaffa660 Mon Sep 17 00:00:00 2001 From: lotte Date: Fri, 12 Oct 2018 14:24:41 +0200 Subject: [PATCH 44/48] improved test compiling time --- package.json | 3 +- src/app/core/registry/registry.service.ts | 3 - .../ds-dynamic-form-control.component.ts | 16 +++-- .../ds-dynamic-form.component.ts | 2 +- src/app/shared/form/form.component.ts | 2 +- .../notification.component.spec.ts | 7 +- .../notification/notification.component.ts | 5 +- .../notifications/notifications.service.ts | 9 ++- webpack/webpack.test.js | 18 +++-- yarn.lock | 70 +++++++++++++------ 10 files changed, 83 insertions(+), 52 deletions(-) diff --git a/package.json b/package.json index f4ab6e2ff4..0c2c0a776c 100644 --- a/package.json +++ b/package.json @@ -97,6 +97,7 @@ "express": "4.16.2", "express-session": "1.15.6", "font-awesome": "4.7.0", + "fork-ts-checker-webpack-plugin": "^0.4.10", "http-server": "0.11.1", "https": "1.0.0", "js-cookie": "2.2.0", @@ -119,6 +120,7 @@ "rxjs": "6.2.2", "sortablejs": "1.7.0", "text-mask-core": "5.0.1", + "ts-loader": "^5.2.1", "ts-md5": "^1.2.4", "uuid": "^3.2.1", "webfontloader": "1.6.28", @@ -152,7 +154,6 @@ "ajv-keywords": "^3.1.0", "angular2-template-loader": "0.6.2", "autoprefixer": "^9.1.3", - "awesome-typescript-loader": "5.2.0", "caniuse-lite": "^1.0.30000697", "codelyzer": "^4.4.4", "compression-webpack-plugin": "^1.1.6", diff --git a/src/app/core/registry/registry.service.ts b/src/app/core/registry/registry.service.ts index 8bd2818b78..7e7c18f69e 100644 --- a/src/app/core/registry/registry.service.ts +++ b/src/app/core/registry/registry.service.ts @@ -17,14 +17,11 @@ import { ResponseCacheService } from '../cache/response-cache.service'; import { RegistryMetadataschemasResponse } from './registry-metadataschemas-response.model'; import { ResponseCacheEntry } from '../cache/response-cache.reducer'; import { - MetadataschemaSuccessResponse, RegistryBitstreamformatsSuccessResponse, RegistryMetadatafieldsSuccessResponse, RegistryMetadataschemasSuccessResponse } from '../cache/response-cache.models'; import { HALEndpointService } from '../shared/hal-endpoint.service'; -import { MetadataschemaParsingService } from '../data/metadataschema-parsing.service'; -import { Res } from 'awesome-typescript-loader/dist/checker/protocol'; import { RegistryMetadatafieldsResponseParsingService } from '../data/registry-metadatafields-response-parsing.service'; import { RegistryMetadatafieldsResponse } from './registry-metadatafields-response.model'; import { isNotEmpty } from '../../shared/empty.util'; diff --git a/src/app/shared/form/builder/ds-dynamic-form-ui/ds-dynamic-form-control.component.ts b/src/app/shared/form/builder/ds-dynamic-form-ui/ds-dynamic-form-control.component.ts index a5d6b923df..3544bce280 100644 --- a/src/app/shared/form/builder/ds-dynamic-form-ui/ds-dynamic-form-control.component.ts +++ b/src/app/shared/form/builder/ds-dynamic-form-ui/ds-dynamic-form-control.component.ts @@ -1,12 +1,16 @@ import { - Component, ComponentFactoryResolver, + Component, + ComponentFactoryResolver, ContentChildren, EventEmitter, Input, OnChanges, Output, QueryList, - SimpleChanges, Type, ViewChild, ViewContainerRef + SimpleChanges, + Type, + ViewChild, + ViewContainerRef } from '@angular/core'; import { FormGroup } from '@angular/forms'; import { @@ -20,11 +24,11 @@ import { DYNAMIC_FORM_CONTROL_TYPE_SELECT, DYNAMIC_FORM_CONTROL_TYPE_TEXTAREA, DYNAMIC_FORM_CONTROL_TYPE_TIMEPICKER, - DynamicDatePickerModel, DynamicFormControl, DynamicFormControlComponent, + DynamicDatePickerModel, + DynamicFormControl, DynamicFormControlContainerComponent, DynamicFormControlEvent, - DynamicFormControlModel, - DynamicFormLayout, + DynamicFormControlModel, DynamicFormLayout, DynamicFormLayoutService, DynamicFormValidationService, DynamicTemplateDirective, @@ -77,7 +81,7 @@ export class DsDynamicFormControlComponent extends DynamicFormControlContainerCo @Input() context: any | null = null; @Input() group: FormGroup; @Input() hasErrorMessaging = false; - @Input() layout: DynamicFormLayout; + @Input() layout = null as DynamicFormLayout; @Input() model: any; /* tslint:disable:no-output-rename */ diff --git a/src/app/shared/form/builder/ds-dynamic-form-ui/ds-dynamic-form.component.ts b/src/app/shared/form/builder/ds-dynamic-form-ui/ds-dynamic-form.component.ts index c0c207eaff..c1b4ca71c8 100644 --- a/src/app/shared/form/builder/ds-dynamic-form-ui/ds-dynamic-form.component.ts +++ b/src/app/shared/form/builder/ds-dynamic-form-ui/ds-dynamic-form.component.ts @@ -29,7 +29,7 @@ export class DsDynamicFormComponent extends DynamicFormComponent { @Input() formId: string; @Input() formGroup: FormGroup; @Input() formModel: DynamicFormControlModel[]; - @Input() formLayout: DynamicFormLayout = null; + @Input() formLayout = null as DynamicFormLayout; /* tslint:disable:no-output-rename */ @Output('dfBlur') blur: EventEmitter = new EventEmitter(); diff --git a/src/app/shared/form/form.component.ts b/src/app/shared/form/form.component.ts index 97cb76565f..2d74ddf8d4 100644 --- a/src/app/shared/form/form.component.ts +++ b/src/app/shared/form/form.component.ts @@ -59,7 +59,7 @@ export class FormComponent implements OnDestroy, OnInit { @Input() formModel: DynamicFormControlModel[]; @Input() parentFormModel: DynamicFormGroupModel | DynamicFormGroupModel[]; @Input() formGroup: FormGroup; - @Input() formLayout: DynamicFormLayout = null; + @Input() formLayout = null as DynamicFormLayout; /* tslint:disable:no-output-rename */ @Output('dfBlur') blur: EventEmitter = new EventEmitter(); diff --git a/src/app/shared/notifications/notification/notification.component.spec.ts b/src/app/shared/notifications/notification/notification.component.spec.ts index e2a80f9f70..d460a4a67f 100644 --- a/src/app/shared/notifications/notification/notification.component.spec.ts +++ b/src/app/shared/notifications/notification/notification.component.spec.ts @@ -1,4 +1,4 @@ -import { async, ComponentFixture, inject, TestBed } from '@angular/core/testing'; +import { async, ComponentFixture, TestBed } from '@angular/core/testing'; import { BrowserModule, By } from '@angular/platform-browser'; import { ChangeDetectorRef, DebugElement } from '@angular/core'; @@ -9,11 +9,6 @@ import { notificationsReducer } from '../notifications.reducers'; import { Store, StoreModule } from '@ngrx/store'; import { NotificationOptions } from '../models/notification-options.model'; import { BrowserAnimationsModule } from '@angular/platform-browser/animations'; -import { Router } from '@angular/router'; -import { NotificationsServiceStub } from '../../testing/notifications-service-stub'; -import { AppState } from '../../../app.reducer'; -import { Observable } from 'rxjs'; -import { SearchPageComponent } from '../../../+search-page/search-page.component'; import { INotificationBoardOptions } from '../../../../config/notifications-config.interfaces'; import { GlobalConfig } from '../../../../config/global-config.interface'; import { Notification } from '../models/notification.model'; diff --git a/src/app/shared/notifications/notification/notification.component.ts b/src/app/shared/notifications/notification/notification.component.ts index f3fbe83fde..81842c62f7 100644 --- a/src/app/shared/notifications/notification/notification.component.ts +++ b/src/app/shared/notifications/notification/notification.component.ts @@ -1,4 +1,3 @@ - import {of as observableOf, Observable } from 'rxjs'; import { ChangeDetectionStrategy, @@ -14,7 +13,6 @@ import { import { trigger } from '@angular/animations'; import { DomSanitizer } from '@angular/platform-browser'; import { NotificationsService } from '../notifications.service'; -import { INotification } from '../models/notification.model'; import { scaleEnter, scaleInState, scaleLeave, scaleOutState } from '../../animations/scale'; import { rotateEnter, rotateInState, rotateLeave, rotateOutState } from '../../animations/rotate'; import { fromBottomEnter, fromBottomInState, fromBottomLeave, fromBottomOutState } from '../../animations/fromBottom'; @@ -24,6 +22,7 @@ import { fromTopEnter, fromTopInState, fromTopLeave, fromTopOutState } from '../ import { fadeInEnter, fadeInState, fadeOutLeave, fadeOutState } from '../../animations/fade'; import { NotificationAnimationsStatus } from '../models/notification-animations-type'; import { isNotEmpty } from '../../empty.util'; +import { INotification } from '../models/notification.model'; @Component({ selector: 'ds-notification', @@ -46,7 +45,7 @@ import { isNotEmpty } from '../../empty.util'; export class NotificationComponent implements OnInit, OnDestroy { - @Input() public notification: INotification; + @Input() public notification = null as INotification; // Progress bar variables public title: Observable; diff --git a/src/app/shared/notifications/notifications.service.ts b/src/app/shared/notifications/notifications.service.ts index d6bb210652..55df6a4f7f 100644 --- a/src/app/shared/notifications/notifications.service.ts +++ b/src/app/shared/notifications/notifications.service.ts @@ -1,12 +1,15 @@ - -import {of as observableOf, Observable } from 'rxjs'; +import { of as observableOf, Observable } from 'rxjs'; import { Inject, Injectable } from '@angular/core'; import { INotification, Notification } from './models/notification.model'; import { NotificationType } from './models/notification-type'; import { NotificationOptions } from './models/notification-options.model'; import { uniqueId } from 'lodash'; import { Store } from '@ngrx/store'; -import { NewNotificationAction, RemoveAllNotificationsAction, RemoveNotificationAction } from './notifications.actions'; +import { + NewNotificationAction, + RemoveAllNotificationsAction, + RemoveNotificationAction +} from './notifications.actions'; import { GLOBAL_CONFIG, GlobalConfig } from '../../../config'; @Injectable() diff --git a/webpack/webpack.test.js b/webpack/webpack.test.js index 3c3c46b84c..b0305728d3 100644 --- a/webpack/webpack.test.js +++ b/webpack/webpack.test.js @@ -5,11 +5,14 @@ const { /** * Webpack Plugins */ + + + const ContextReplacementPlugin = require('webpack/lib/ContextReplacementPlugin'); const DefinePlugin = require('webpack/lib/DefinePlugin'); const LoaderOptionsPlugin = require('webpack/lib/LoaderOptionsPlugin'); const ProvidePlugin = require('webpack/lib/ProvidePlugin'); - +const ForkTsCheckerWebpackPlugin = require('fork-ts-checker-webpack-plugin'); /** * Webpack Constants */ @@ -81,14 +84,15 @@ module.exports = function (options) { /** * Typescript loader support for .ts and Angular 2 async routes via .async.ts * - * See: https://github.com/s-panferov/awesome-typescript-loader + * See: https://github.com/TypeStrong/ts-loader */ { - test: /\.ts$/, - loaders: [{ - loader: 'awesome-typescript-loader', + test: /\.tsx?$/, + loaders: [{ + loader: 'ts-loader', options: { - configFileName: './src/tsconfig.test.json' + configFile: root('src/tsconfig.test.json'), + transpileOnly: true } }, 'angular2-template-loader' @@ -249,7 +253,7 @@ module.exports = function (options) { } }), - + new ForkTsCheckerWebpackPlugin() ], /** diff --git a/yarn.lock b/yarn.lock index e509a2878f..da7122c474 100644 --- a/yarn.lock +++ b/yarn.lock @@ -946,19 +946,6 @@ autoprefixer@^9.1.3: postcss "^7.0.2" postcss-value-parser "^3.2.3" -awesome-typescript-loader@5.2.0: - version "5.2.0" - resolved "https://registry.yarnpkg.com/awesome-typescript-loader/-/awesome-typescript-loader-5.2.0.tgz#d7bccf4823c45096ec24da4c12a1507d276ba15a" - dependencies: - chalk "^2.4.1" - enhanced-resolve "^4.0.0" - loader-utils "^1.1.0" - lodash "^4.17.5" - micromatch "^3.1.9" - mkdirp "^0.5.1" - source-map-support "^0.5.3" - webpack-log "^1.2.0" - aws-sign2@~0.7.0: version "0.7.0" resolved "https://registry.yarnpkg.com/aws-sign2/-/aws-sign2-0.7.0.tgz#b46e890934a9591f2d2f6f86d7e6a9f1b3fe76a8" @@ -1569,7 +1556,7 @@ chokidar@^1.4.2: optionalDependencies: fsevents "^1.0.0" -chokidar@^2.0.0, chokidar@^2.0.2, chokidar@^2.0.3: +chokidar@^2.0.0, chokidar@^2.0.2, chokidar@^2.0.3, chokidar@^2.0.4: version "2.0.4" resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-2.0.4.tgz#356ff4e2b0e8e43e322d18a372460bbcf3accd26" dependencies: @@ -1965,11 +1952,7 @@ copy-webpack-plugin@^4.4.1: p-limit "^1.0.0" serialize-javascript "^1.4.0" -core-js@^2.2.0, core-js@^2.4.0: - version "2.5.7" - resolved "https://registry.yarnpkg.com/core-js/-/core-js-2.5.7.tgz#f972608ff0cead68b841a16a932d0b183791814e" - -core-js@^2.5.7: +core-js@^2.2.0, core-js@^2.4.0, core-js@^2.5.7: version "2.5.7" resolved "https://registry.yarnpkg.com/core-js/-/core-js-2.5.7.tgz#f972608ff0cead68b841a16a932d0b183791814e" @@ -3185,6 +3168,21 @@ forever-agent@~0.6.1: version "0.6.1" resolved "https://registry.yarnpkg.com/forever-agent/-/forever-agent-0.6.1.tgz#fbc71f0c41adeb37f96c577ad1ed42d8fdacca91" +fork-ts-checker-webpack-plugin@^0.4.10: + version "0.4.10" + resolved "https://registry.yarnpkg.com/fork-ts-checker-webpack-plugin/-/fork-ts-checker-webpack-plugin-0.4.10.tgz#e96f87ea599af4501c1a69f44ecfb3163bbf30b9" + dependencies: + babel-code-frame "^6.22.0" + chalk "^2.4.1" + chokidar "^2.0.4" + lodash.endswith "^4.2.1" + lodash.isfunction "^3.0.8" + lodash.isstring "^4.0.1" + lodash.startswith "^4.2.1" + minimatch "^3.0.4" + resolve "^1.5.0" + tapable "^1.0.0" + form-data@~2.3.1, form-data@~2.3.2: version "2.3.2" resolved "https://registry.yarnpkg.com/form-data/-/form-data-2.3.2.tgz#4970498be604c20c005d4f5c23aecd21d6b49099" @@ -4837,6 +4835,10 @@ lodash.defaults@^4.0.0: version "4.2.0" resolved "https://registry.yarnpkg.com/lodash.defaults/-/lodash.defaults-4.2.0.tgz#d09178716ffea4dde9e5fb7b37f6f0802274580c" +lodash.endswith@^4.2.1: + version "4.2.1" + resolved "https://registry.yarnpkg.com/lodash.endswith/-/lodash.endswith-4.2.1.tgz#fed59ac1738ed3e236edd7064ec456448b37bc09" + lodash.escape@^3.0.0: version "3.2.0" resolved "https://registry.yarnpkg.com/lodash.escape/-/lodash.escape-3.2.0.tgz#995ee0dc18c1b48cc92effae71a10aab5b487698" @@ -4851,6 +4853,14 @@ lodash.isarray@^3.0.0: version "3.0.4" resolved "https://registry.yarnpkg.com/lodash.isarray/-/lodash.isarray-3.0.4.tgz#79e4eb88c36a8122af86f844aa9bcd851b5fbb55" +lodash.isfunction@^3.0.8: + version "3.0.9" + resolved "https://registry.yarnpkg.com/lodash.isfunction/-/lodash.isfunction-3.0.9.tgz#06de25df4db327ac931981d1bdb067e5af68d051" + +lodash.isstring@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/lodash.isstring/-/lodash.isstring-4.0.1.tgz#d527dfb5456eca7cc9bb95d5daeaf88ba54a5451" + lodash.keys@^3.0.0: version "3.1.2" resolved "https://registry.yarnpkg.com/lodash.keys/-/lodash.keys-3.1.2.tgz#4dbc0472b156be50a0b286855d1bd0b0c656098a" @@ -4871,6 +4881,10 @@ lodash.restparam@^3.0.0: version "3.6.1" resolved "https://registry.yarnpkg.com/lodash.restparam/-/lodash.restparam-3.6.1.tgz#936a4e309ef330a7645ed4145986c85ae5b20805" +lodash.startswith@^4.2.1: + version "4.2.1" + resolved "https://registry.yarnpkg.com/lodash.startswith/-/lodash.startswith-4.2.1.tgz#c598c4adce188a27e53145731cdc6c0e7177600c" + lodash.tail@^4.1.1: version "4.1.1" resolved "https://registry.yarnpkg.com/lodash.tail/-/lodash.tail-4.1.1.tgz#d2333a36d9e7717c8ad2f7cacafec7c32b444664" @@ -7367,6 +7381,10 @@ semver-intersect@^1.1.2: version "5.5.1" resolved "https://registry.yarnpkg.com/semver/-/semver-5.5.1.tgz#7dfdd8814bdb7cabc7be0fb1d734cfb66c940477" +semver@^5.0.1: + version "5.6.0" + resolved "https://registry.yarnpkg.com/semver/-/semver-5.6.0.tgz#7e74256fbaa49c75aa7c7a205cc22799cac80004" + semver@~5.3.0: version "5.3.0" resolved "https://registry.yarnpkg.com/semver/-/semver-5.3.0.tgz#9b2ce5d3de02d17c6012ad326aa6b4d0cf54f94f" @@ -7657,7 +7675,7 @@ source-map-resolve@^0.5.0, source-map-resolve@^0.5.1: source-map-url "^0.4.0" urix "^0.1.0" -source-map-support@^0.5.0, source-map-support@^0.5.3, source-map-support@~0.5.6: +source-map-support@^0.5.0, source-map-support@~0.5.6: version "0.5.9" resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.9.tgz#41bc953b2534267ea2d605bccfa7bfa3111ced5f" dependencies: @@ -8171,6 +8189,16 @@ ts-helpers@1.1.2: version "1.1.2" resolved "https://registry.yarnpkg.com/ts-helpers/-/ts-helpers-1.1.2.tgz#fc69be9f1f3baed01fb1a0ef8d4cfe748814d835" +ts-loader@^5.2.1: + version "5.2.1" + resolved "https://registry.yarnpkg.com/ts-loader/-/ts-loader-5.2.1.tgz#e6815c631dcafc24319ce8be6f8af94908749cf3" + dependencies: + chalk "^2.3.0" + enhanced-resolve "^4.0.0" + loader-utils "^1.0.2" + micromatch "^3.1.4" + semver "^5.0.1" + ts-md5@^1.2.4: version "1.2.4" resolved "https://registry.yarnpkg.com/ts-md5/-/ts-md5-1.2.4.tgz#7030d7ba9134449deedf6f609d4b4509b94a5712" @@ -8749,7 +8777,7 @@ webpack-dev-server@^3.1.5: webpack-log "^2.0.0" yargs "12.0.1" -webpack-log@^1.0.1, webpack-log@^1.2.0: +webpack-log@^1.0.1: version "1.2.0" resolved "https://registry.yarnpkg.com/webpack-log/-/webpack-log-1.2.0.tgz#a4b34cda6b22b518dbb0ab32e567962d5c72a43d" dependencies: From 2330e96158dffe4dec6eafcb7703efc4ba3e4868 Mon Sep 17 00:00:00 2001 From: lotte Date: Wed, 17 Oct 2018 13:18:01 +0200 Subject: [PATCH 45/48] intermediate commit --- .../top-level-community-list.component.ts | 1 + .../search-service/search.service.spec.ts | 18 +-- .../search-service/search.service.ts | 54 ++++---- src/app/core/auth/auth-request.service.ts | 15 +-- .../auth-response-parsing.service.spec.ts | 2 +- .../auth/auth-response-parsing.service.ts | 2 +- src/app/core/browse/browse.service.spec.ts | 21 +-- src/app/core/browse/browse.service.ts | 35 ++--- .../builders/remote-data-build.service.ts | 62 ++++----- src/app/core/cache/response-cache.actions.ts | 72 ---------- .../core/cache/response-cache.effects.spec.ts | 38 ------ src/app/core/cache/response-cache.effects.ts | 27 ---- .../core/cache/response-cache.reducer.spec.ts | 124 ------------------ src/app/core/cache/response-cache.reducer.ts | 111 ---------------- .../core/cache/response-cache.service.spec.ts | 100 -------------- src/app/core/cache/response-cache.service.ts | 100 -------------- ...nse-cache.models.ts => response.models.ts} | 2 +- src/app/core/config/config.service.spec.ts | 12 -- src/app/core/config/config.service.ts | 14 +- .../submission-definitions-config.service.ts | 2 - .../config/submission-forms-config.service.ts | 2 - .../submission-sections-config.service.ts | 2 - src/app/core/core.effects.ts | 2 - src/app/core/core.module.ts | 2 - src/app/core/core.reducers.ts | 3 - ...e-entries-response-parsing.service.spec.ts | 2 +- ...browse-entries-response-parsing.service.ts | 2 +- ...wse-items-response-parsing-service.spec.ts | 2 +- .../browse-items-response-parsing-service.ts | 2 +- .../browse-response-parsing.service.spec.ts | 2 +- .../data/browse-response-parsing.service.ts | 2 +- src/app/core/data/collection-data.service.ts | 3 - src/app/core/data/comcol-data.service.spec.ts | 15 --- src/app/core/data/comcol-data.service.ts | 23 ++-- src/app/core/data/community-data.service.ts | 11 +- .../config-response-parsing.service.spec.ts | 2 +- .../data/config-response-parsing.service.ts | 2 +- src/app/core/data/data.service.spec.ts | 6 +- src/app/core/data/data.service.ts | 19 ++- .../data/debug-response-parsing.service.ts | 2 +- .../core/data/dso-response-parsing.service.ts | 8 +- .../core/data/dspace-object-data.service.ts | 8 +- .../endpoint-map-response-parsing.service.ts | 2 +- .../facet-config-response-parsing.service.ts | 2 +- ...acet-value-map-response-parsing.service.ts | 2 +- .../facet-value-response-parsing.service.ts | 2 +- src/app/core/data/item-data.service.spec.ts | 3 - src/app/core/data/item-data.service.ts | 6 +- .../data/metadataschema-parsing.service.ts | 2 +- src/app/core/data/parsing.service.ts | 2 +- ...tstreamformats-response-parsing.service.ts | 2 +- ...metadatafields-response-parsing.service.ts | 2 +- ...etadataschemas-response-parsing.service.ts | 2 +- src/app/core/data/request.actions.ts | 38 +++++- src/app/core/data/request.effects.ts | 43 ++++-- src/app/core/data/request.models.ts | 13 +- src/app/core/data/request.reducer.ts | 30 ++++- src/app/core/data/request.service.spec.ts | 5 - src/app/core/data/request.service.ts | 87 ++++++++---- .../data/search-response-parsing.service.ts | 2 +- src/app/core/integration/authority.service.ts | 2 - ...tegration-response-parsing.service.spec.ts | 2 +- .../integration-response-parsing.service.ts | 2 +- .../integration/integration.service.spec.ts | 15 +-- .../core/integration/integration.service.ts | 13 +- .../core/metadata/metadata.service.spec.ts | 8 +- .../core/registry/registry.service.spec.ts | 6 +- src/app/core/registry/registry.service.ts | 66 ++++------ .../core/shared/hal-endpoint.service.spec.ts | 18 --- src/app/core/shared/hal-endpoint.service.ts | 44 +++++-- src/app/core/shared/operators.spec.ts | 50 +------ src/app/core/shared/operators.ts | 29 ++-- .../mocks/mock-remote-data-build.service.ts | 3 +- .../mocks/mock-response-cache.service.ts | 16 --- src/server.ts | 1 + 75 files changed, 387 insertions(+), 1067 deletions(-) delete mode 100644 src/app/core/cache/response-cache.actions.ts delete mode 100644 src/app/core/cache/response-cache.effects.spec.ts delete mode 100644 src/app/core/cache/response-cache.effects.ts delete mode 100644 src/app/core/cache/response-cache.reducer.spec.ts delete mode 100644 src/app/core/cache/response-cache.reducer.ts delete mode 100644 src/app/core/cache/response-cache.service.spec.ts delete mode 100644 src/app/core/cache/response-cache.service.ts rename src/app/core/cache/{response-cache.models.ts => response.models.ts} (99%) diff --git a/src/app/+home-page/top-level-community-list/top-level-community-list.component.ts b/src/app/+home-page/top-level-community-list/top-level-community-list.component.ts index 8e8c83ce5b..3fdb7e48a2 100644 --- a/src/app/+home-page/top-level-community-list/top-level-community-list.component.ts +++ b/src/app/+home-page/top-level-community-list/top-level-community-list.component.ts @@ -17,6 +17,7 @@ import { PaginationComponentOptions } from '../../shared/pagination/pagination-c changeDetection: ChangeDetectionStrategy.OnPush, animations: [fadeInOut] }) + export class TopLevelCommunityListComponent { communitiesRDObs: Observable>>; config: PaginationComponentOptions; diff --git a/src/app/+search-page/search-service/search.service.spec.ts b/src/app/+search-page/search-service/search.service.spec.ts index 6bfc9200ec..028a3fa446 100644 --- a/src/app/+search-page/search-service/search.service.spec.ts +++ b/src/app/+search-page/search-service/search.service.spec.ts @@ -8,21 +8,18 @@ import { SearchService } from './search.service'; import { RemoteDataBuildService } from '../../core/cache/builders/remote-data-build.service'; import { ActivatedRoute, Router, UrlTree } from '@angular/router'; import { RequestService } from '../../core/data/request.service'; -import { ResponseCacheService } from '../../core/cache/response-cache.service'; import { ActivatedRouteStub } from '../../shared/testing/active-router-stub'; import { RouterStub } from '../../shared/testing/router-stub'; import { HALEndpointService } from '../../core/shared/hal-endpoint.service'; import { Observable, combineLatest as observableCombineLatest } from 'rxjs'; import { PaginatedSearchOptions } from '../paginated-search-options.model'; import { RemoteData } from '../../core/data/remote-data'; -import { ResponseCacheEntry } from '../../core/cache/response-cache.reducer'; import { RequestEntry } from '../../core/data/request.reducer'; import { getMockRequestService } from '../../shared/mocks/mock-request.service'; -import { getMockResponseCacheService } from '../../shared/mocks/mock-response-cache.service'; import { FacetConfigSuccessResponse, SearchSuccessResponse -} from '../../core/cache/response-cache.models'; +} from '../../core/cache/response.models'; import { SearchQueryResponse } from './search-query-response.model'; import { SearchFilterConfig } from './search-filter-config.model'; import { CommunityDataService } from '../../core/data/community-data.service'; @@ -54,7 +51,6 @@ describe('SearchService', () => { providers: [ { provide: Router, useValue: router }, { provide: ActivatedRoute, useValue: route }, - { provide: ResponseCacheService, useValue: getMockResponseCacheService() }, { provide: RequestService, useValue: getMockRequestService() }, { provide: RemoteDataBuildService, useValue: {} }, { provide: HALEndpointService, useValue: {} }, @@ -86,9 +82,8 @@ describe('SearchService', () => { }; const remoteDataBuildService = { - toRemoteDataObservable: (requestEntryObs: Observable, responseCacheObs: Observable, payloadObs: Observable) => { - return observableCombineLatest(requestEntryObs, - responseCacheObs, payloadObs).pipe( + toRemoteDataObservable: (requestEntryObs: Observable, payloadObs: Observable) => { + return observableCombineLatest(requestEntryObs, payloadObs).pipe( map(([req, res, pay]) => { return { req, res, pay }; }) @@ -113,7 +108,6 @@ describe('SearchService', () => { providers: [ { provide: Router, useValue: router }, { provide: ActivatedRoute, useValue: route }, - { provide: ResponseCacheService, useValue: getMockResponseCacheService() }, { provide: RequestService, useValue: getMockRequestService() }, { provide: RemoteDataBuildService, useValue: remoteDataBuildService }, { provide: HALEndpointService, useValue: halService }, @@ -162,10 +156,8 @@ describe('SearchService', () => { const searchOptions = new PaginatedSearchOptions({}); const queryResponse = Object.assign(new SearchQueryResponse(), { objects: [] }); const response = new SearchSuccessResponse(queryResponse, '200'); - const responseEntry = Object.assign(new ResponseCacheEntry(), { response: response }); beforeEach(() => { spyOn((searchService as any).halService, 'getEndpoint').and.returnValue(observableOf(endPoint)); - (searchService as any).responseCache.get.and.returnValue(observableOf(responseEntry)); /* tslint:disable:no-empty */ searchService.search(searchOptions).subscribe((t) => { }); // subscribe to make sure all methods are called @@ -192,10 +184,8 @@ describe('SearchService', () => { const endPoint = 'http://endpoint.com/test/config'; const filterConfig = [new SearchFilterConfig()]; const response = new FacetConfigSuccessResponse(filterConfig, '200'); - const responseEntry = Object.assign(new ResponseCacheEntry(), { response: response }); beforeEach(() => { spyOn((searchService as any).halService, 'getEndpoint').and.returnValue(observableOf(endPoint)); - (searchService as any).responseCache.get.and.returnValue(observableOf(responseEntry)); /* tslint:disable:no-empty */ searchService.getConfig(null).subscribe((t) => { }); // subscribe to make sure all methods are called @@ -224,10 +214,8 @@ describe('SearchService', () => { const requestUrl = endPoint + '?scope=' + scope; const filterConfig = [new SearchFilterConfig()]; const response = new FacetConfigSuccessResponse(filterConfig, '200'); - const responseEntry = Object.assign(new ResponseCacheEntry(), { response: response }); beforeEach(() => { spyOn((searchService as any).halService, 'getEndpoint').and.returnValue(observableOf(endPoint)); - (searchService as any).responseCache.get.and.returnValue(observableOf(responseEntry)); /* tslint:disable:no-empty */ searchService.getConfig(scope).subscribe((t) => { }); // subscribe to make sure all methods are called diff --git a/src/app/+search-page/search-service/search.service.ts b/src/app/+search-page/search-service/search.service.ts index 1503440eb0..c628fd350e 100644 --- a/src/app/+search-page/search-service/search.service.ts +++ b/src/app/+search-page/search-service/search.service.ts @@ -1,4 +1,4 @@ -import { of as observableOf, combineLatest as observableCombineLatest, Observable } from 'rxjs'; +import { combineLatest as observableCombineLatest, Observable, of as observableOf } from 'rxjs'; import { Injectable, OnDestroy } from '@angular/core'; import { ActivatedRoute, @@ -7,15 +7,13 @@ import { Router, UrlSegmentGroup } from '@angular/router'; -import { flatMap, map, switchMap } from 'rxjs/operators'; +import { filter, flatMap, map, switchMap } from 'rxjs/operators'; import { RemoteDataBuildService } from '../../core/cache/builders/remote-data-build.service'; import { FacetConfigSuccessResponse, FacetValueSuccessResponse, SearchSuccessResponse -} from '../../core/cache/response-cache.models'; -import { ResponseCacheEntry } from '../../core/cache/response-cache.reducer'; -import { ResponseCacheService } from '../../core/cache/response-cache.service'; +} from '../../core/cache/response.models'; import { PaginatedList } from '../../core/data/paginated-list'; import { ResponseParsingService } from '../../core/data/parsing.service'; import { RemoteData } from '../../core/data/remote-data'; @@ -24,7 +22,11 @@ import { RequestService } from '../../core/data/request.service'; 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, getSucceededRemoteData } from '../../core/shared/operators'; +import { + configureRequest, + getResponseFromEntry, + getSucceededRemoteData +} from '../../core/shared/operators'; import { URLCombiner } from '../../core/url-combiner/url-combiner'; import { hasValue, isEmpty, isNotEmpty } from '../../shared/empty.util'; import { NormalizedSearchResult } from '../normalized-search-result.model'; @@ -45,6 +47,7 @@ import { CommunityDataService } from '../../core/data/community-data.service'; import { ViewMode } from '../../core/shared/view-mode.model'; import { ResourceType } from '../../core/shared/resource-type'; import { DSpaceObjectDataService } from '../../core/data/dspace-object-data.service'; +import { RequestEntry } from '../../core/data/request.reducer'; /** * Service that performs all general actions that have to do with the search page @@ -68,7 +71,6 @@ export class SearchService implements OnDestroy { constructor(private router: Router, private route: ActivatedRoute, - protected responseCache: ResponseCacheService, protected requestService: RequestService, private rdb: RemoteDataBuildService, private halService: HALEndpointService, @@ -101,13 +103,9 @@ export class SearchService implements OnDestroy { flatMap((request: RestRequest) => this.requestService.getByHref(request.href)) ); - const responseCacheObs = requestObs.pipe( - flatMap((request: RestRequest) => this.responseCache.get(request.href)) - ); - // get search results from response cache - const sqrObs: Observable = responseCacheObs.pipe( - map((entry: ResponseCacheEntry) => entry.response), + const sqrObs: Observable = requestEntryObs.pipe( + getResponseFromEntry(), map((response: SearchSuccessResponse) => response.results) ); @@ -139,8 +137,8 @@ export class SearchService implements OnDestroy { }) ); - const pageInfoObs: Observable = responseCacheObs.pipe( - map((entry: ResponseCacheEntry) => entry.response), + const pageInfoObs: Observable = requestEntryObs.pipe( + getResponseFromEntry(), map((response: FacetValueSuccessResponse) => response.pageInfo) ); @@ -150,7 +148,7 @@ export class SearchService implements OnDestroy { }) ); - return this.rdb.toRemoteDataObservable(requestEntryObs, responseCacheObs, payloadObs); + return this.rdb.toRemoteDataObservable(requestEntryObs, payloadObs); } /** @@ -185,18 +183,14 @@ export class SearchService implements OnDestroy { flatMap((request: RestRequest) => this.requestService.getByHref(request.href)) ); - const responseCacheObs = requestObs.pipe( - flatMap((request: RestRequest) => this.responseCache.get(request.href)) - ); - // get search results from response cache - const facetConfigObs: Observable = responseCacheObs.pipe( - map((entry: ResponseCacheEntry) => entry.response), + const facetConfigObs: Observable = requestEntryObs.pipe( + getResponseFromEntry(), map((response: FacetConfigSuccessResponse) => response.results.map((result: any) => Object.assign(new SearchFilterConfig(), result))) ); - return this.rdb.toRemoteDataObservable(requestEntryObs, responseCacheObs, facetConfigObs); + return this.rdb.toRemoteDataObservable(requestEntryObs, facetConfigObs); } /** @@ -232,18 +226,14 @@ export class SearchService implements OnDestroy { flatMap((request: RestRequest) => this.requestService.getByHref(request.href)) ); - const responseCacheObs = requestObs.pipe( - flatMap((request: RestRequest) => this.responseCache.get(request.href)) - ); - // get search results from response cache - const facetValueObs: Observable = responseCacheObs.pipe( - map((entry: ResponseCacheEntry) => entry.response), + const facetValueObs: Observable = requestEntryObs.pipe( + getResponseFromEntry(), map((response: FacetValueSuccessResponse) => response.results) ); - const pageInfoObs: Observable = responseCacheObs.pipe( - map((entry: ResponseCacheEntry) => entry.response), + const pageInfoObs: Observable = requestEntryObs.pipe( + getResponseFromEntry(), map((response: FacetValueSuccessResponse) => response.pageInfo) ); @@ -253,7 +243,7 @@ export class SearchService implements OnDestroy { }) ); - return this.rdb.toRemoteDataObservable(requestEntryObs, responseCacheObs, payloadObs); + return this.rdb.toRemoteDataObservable(requestEntryObs, payloadObs); } /** diff --git a/src/app/core/auth/auth-request.service.ts b/src/app/core/auth/auth-request.service.ts index 7cb5fae7e4..0752149eae 100644 --- a/src/app/core/auth/auth-request.service.ts +++ b/src/app/core/auth/auth-request.service.ts @@ -2,15 +2,15 @@ import { Observable, of as observableOf, throwError as observableThrowError } fr import { distinctUntilChanged, filter, map, mergeMap, tap } from 'rxjs/operators'; import { Inject, Injectable } from '@angular/core'; import { HALEndpointService } from '../shared/hal-endpoint.service'; -import { ResponseCacheService } from '../cache/response-cache.service'; import { RequestService } from '../data/request.service'; import { GLOBAL_CONFIG } from '../../../config'; import { GlobalConfig } from '../../../config/global-config.interface'; import { isNotEmpty } from '../../shared/empty.util'; import { AuthGetRequest, AuthPostRequest, PostRequest, RestRequest } from '../data/request.models'; -import { ResponseCacheEntry } from '../cache/response-cache.reducer'; -import { AuthStatusResponse, ErrorResponse } from '../cache/response-cache.models'; +import { AuthStatusResponse, ErrorResponse } from '../cache/response.models'; import { HttpOptions } from '../dspace-rest-v2/dspace-rest-v2.service'; +import { RequestEntry } from '../data/request.reducer'; +import { getResponseFromEntry } from '../shared/operators'; @Injectable() export class AuthRequestService { @@ -19,18 +19,17 @@ export class AuthRequestService { constructor(@Inject(GLOBAL_CONFIG) protected EnvConfig: GlobalConfig, protected halService: HALEndpointService, - protected responseCache: ResponseCacheService, protected requestService: RequestService) { } protected fetchRequest(request: RestRequest): Observable { - return this.responseCache.get(request.href).pipe( - map((entry: ResponseCacheEntry) => entry.response), + return this.requestService.getByHref(request.href).pipe( + getResponseFromEntry(), // TODO to review when https://github.com/DSpace/dspace-angular/issues/217 will be fixed - tap(() => this.responseCache.remove(request.href)), + // tap(() => this.responseCache.remove(request.href)), mergeMap((response) => { if (response.isSuccessful && isNotEmpty(response)) { - return observableOf((response as AuthStatusResponse).response); + return observableOf((response as AuthStatusResponse).response); } else if (!response.isSuccessful) { return observableThrowError(new Error((response as ErrorResponse).errorMessage)); } diff --git a/src/app/core/auth/auth-response-parsing.service.spec.ts b/src/app/core/auth/auth-response-parsing.service.spec.ts index 138d0f1be3..e23e3ac56b 100644 --- a/src/app/core/auth/auth-response-parsing.service.spec.ts +++ b/src/app/core/auth/auth-response-parsing.service.spec.ts @@ -1,4 +1,4 @@ -import { AuthStatusResponse } from '../cache/response-cache.models'; +import { AuthStatusResponse } from '../cache/response.models'; import { ObjectCacheService } from '../cache/object-cache.service'; import { GlobalConfig } from '../../../config/global-config.interface'; diff --git a/src/app/core/auth/auth-response-parsing.service.ts b/src/app/core/auth/auth-response-parsing.service.ts index 8efa36f9e2..65d093de61 100644 --- a/src/app/core/auth/auth-response-parsing.service.ts +++ b/src/app/core/auth/auth-response-parsing.service.ts @@ -2,7 +2,7 @@ import { Inject, Injectable } from '@angular/core'; import { AuthObjectFactory } from './auth-object-factory'; import { BaseResponseParsingService } from '../data/base-response-parsing.service'; -import { AuthStatusResponse, RestResponse } from '../cache/response-cache.models'; +import { AuthStatusResponse, RestResponse } from '../cache/response.models'; import { DSpaceRESTV2Response } from '../dspace-rest-v2/dspace-rest-v2-response.model'; import { GLOBAL_CONFIG } from '../../../config'; import { GlobalConfig } from '../../../config/global-config.interface'; diff --git a/src/app/core/browse/browse.service.spec.ts b/src/app/core/browse/browse.service.spec.ts index d43a26ed4b..4465eae1ee 100644 --- a/src/app/core/browse/browse.service.spec.ts +++ b/src/app/core/browse/browse.service.spec.ts @@ -2,10 +2,8 @@ import { cold, getTestScheduler, hot } from 'jasmine-marbles'; import { TestScheduler } from 'rxjs/testing'; import { getMockRemoteDataBuildService } from '../../shared/mocks/mock-remote-data-build.service'; import { getMockRequestService } from '../../shared/mocks/mock-request.service'; -import { getMockResponseCacheService } from '../../shared/mocks/mock-response-cache.service'; import { HALEndpointServiceStub } from '../../shared/testing/hal-endpoint-service-stub'; import { RemoteDataBuildService } from '../cache/builders/remote-data-build.service'; -import { ResponseCacheService } from '../cache/response-cache.service'; import { BrowseEndpointRequest, BrowseEntriesRequest, BrowseItemsRequest } from '../data/request.models'; import { RequestService } from '../data/request.service'; import { BrowseDefinition } from '../shared/browse-definition.model'; @@ -14,7 +12,6 @@ import { BrowseService } from './browse.service'; describe('BrowseService', () => { let scheduler: TestScheduler; let service: BrowseService; - let responseCache: ResponseCacheService; let requestService: RequestService; let rdbService: RemoteDataBuildService; @@ -79,22 +76,10 @@ describe('BrowseService', () => { }) ]; - function initMockResponseCacheService(isSuccessful: boolean) { - const rcs = getMockResponseCacheService(); - (rcs.get as any).and.returnValue(cold('b-', { - b: { - response: { - isSuccessful, - payload: browseDefinitions, - } - } - })); - return rcs; - } + function initTestService() { return new BrowseService( - responseCache, requestService, halService, rdbService @@ -108,7 +93,6 @@ describe('BrowseService', () => { describe('getBrowseDefinitions', () => { beforeEach(() => { - responseCache = initMockResponseCacheService(true); requestService = getMockRequestService(); rdbService = getMockRemoteDataBuildService(); service = initTestService(); @@ -147,7 +131,6 @@ describe('BrowseService', () => { const mockAuthorName = 'Donald Smith'; beforeEach(() => { - responseCache = initMockResponseCacheService(true); requestService = getMockRequestService(); rdbService = getMockRemoteDataBuildService(); service = initTestService(); @@ -221,7 +204,6 @@ describe('BrowseService', () => { describe('if getBrowseDefinitions fires', () => { beforeEach(() => { - responseCache = initMockResponseCacheService(true); requestService = getMockRequestService(); rdbService = getMockRemoteDataBuildService(); service = initTestService(); @@ -277,7 +259,6 @@ describe('BrowseService', () => { describe('if getBrowseDefinitions doesn\'t fire', () => { it('should return undefined', () => { - responseCache = initMockResponseCacheService(true); requestService = getMockRequestService(); rdbService = getMockRemoteDataBuildService(); service = initTestService(); diff --git a/src/app/core/browse/browse.service.ts b/src/app/core/browse/browse.service.ts index ddce277e7e..c1c893ec27 100644 --- a/src/app/core/browse/browse.service.ts +++ b/src/app/core/browse/browse.service.ts @@ -1,8 +1,8 @@ import { Injectable } from '@angular/core'; import { Observable } from 'rxjs'; -import { distinctUntilChanged, map, startWith } from 'rxjs/operators'; +import { distinctUntilChanged, filter, map, startWith, tap } from 'rxjs/operators'; import { - ensureArrayHasValue, + ensureArrayHasValue, hasValue, hasValueOperator, isEmpty, isNotEmpty, @@ -11,16 +11,13 @@ import { import { PaginationComponentOptions } from '../../shared/pagination/pagination-component-options.model'; import { RemoteDataBuildService } from '../cache/builders/remote-data-build.service'; import { SortOptions } from '../cache/models/sort-options.model'; -import { GenericSuccessResponse } from '../cache/response-cache.models'; -import { ResponseCacheEntry } from '../cache/response-cache.reducer'; -import { ResponseCacheService } from '../cache/response-cache.service'; +import { GenericSuccessResponse } from '../cache/response.models'; import { PaginatedList } from '../data/paginated-list'; import { RemoteData } from '../data/remote-data'; import { BrowseEndpointRequest, BrowseEntriesRequest, BrowseItemsRequest, - GetRequest, RestRequest } from '../data/request.models'; import { RequestService } from '../data/request.service'; @@ -29,14 +26,15 @@ import { BrowseEntry } from '../shared/browse-entry.model'; import { HALEndpointService } from '../shared/hal-endpoint.service'; import { configureRequest, - filterSuccessfulResponses, getBrowseDefinitionLinks, + filterSuccessfulResponses, + getBrowseDefinitionLinks, getRemoteDataPayload, - getRequestFromSelflink, - getResponseFromSelflink + getRequestFromSelflink } from '../shared/operators'; import { URLCombiner } from '../url-combiner/url-combiner'; import { Item } from '../shared/item.model'; import { DSpaceObject } from '../shared/dspace-object.model'; +import { RequestEntry } from '../data/request.reducer'; @Injectable() export class BrowseService { @@ -56,7 +54,6 @@ export class BrowseService { } constructor( - protected responseCache: ResponseCacheService, protected requestService: RequestService, protected halService: HALEndpointService, private rdb: RemoteDataBuildService, @@ -73,10 +70,8 @@ export class BrowseService { const href$ = request$.pipe(map((request: RestRequest) => request.href)); const requestEntry$ = href$.pipe(getRequestFromSelflink(this.requestService)); - const responseCache$ = href$.pipe(getResponseFromSelflink(this.responseCache)); - const payload$ = responseCache$.pipe( + const payload$ = requestEntry$.pipe( filterSuccessfulResponses(), - map((entry: ResponseCacheEntry) => entry.response), map((response: GenericSuccessResponse) => response.payload), ensureArrayHasValue(), map((definitions: BrowseDefinition[]) => definitions @@ -84,7 +79,7 @@ export class BrowseService { distinctUntilChanged() ); - return this.rdb.toRemoteDataObservable(requestEntry$, responseCache$, payload$); + return this.rdb.toRemoteDataObservable(requestEntry$, payload$); } getBrowseEntriesFor(definitionID: string, options: { @@ -118,11 +113,9 @@ export class BrowseService { const href$ = request$.pipe(map((request: RestRequest) => request.href)); const requestEntry$ = href$.pipe(getRequestFromSelflink(this.requestService)); - const responseCache$ = href$.pipe(getResponseFromSelflink(this.responseCache)); - const payload$ = responseCache$.pipe( + const payload$ = requestEntry$.pipe( filterSuccessfulResponses(), - map((entry: ResponseCacheEntry) => entry.response), map((response: GenericSuccessResponse) => new PaginatedList(response.pageInfo, response.payload)), map((list: PaginatedList) => Object.assign(list, { page: list.page ? list.page.map((entry: BrowseEntry) => Object.assign(new BrowseEntry(), entry)) : list.page @@ -130,7 +123,7 @@ export class BrowseService { distinctUntilChanged() ); - return this.rdb.toRemoteDataObservable(requestEntry$, responseCache$, payload$); + return this.rdb.toRemoteDataObservable(requestEntry$, payload$); } /** @@ -175,11 +168,9 @@ export class BrowseService { const href$ = request$.pipe(map((request: RestRequest) => request.href)); const requestEntry$ = href$.pipe(getRequestFromSelflink(this.requestService)); - const responseCache$ = href$.pipe(getResponseFromSelflink(this.responseCache)); - const payload$ = responseCache$.pipe( + const payload$ = requestEntry$.pipe( filterSuccessfulResponses(), - map((entry: ResponseCacheEntry) => entry.response), map((response: GenericSuccessResponse) => new PaginatedList(response.pageInfo, response.payload)), map((list: PaginatedList) => Object.assign(list, { page: list.page ? list.page.map((item: DSpaceObject) => Object.assign(new Item(), item)) : list.page @@ -187,7 +178,7 @@ export class BrowseService { distinctUntilChanged() ); - return this.rdb.toRemoteDataObservable(requestEntry$, responseCache$, payload$); + return this.rdb.toRemoteDataObservable(requestEntry$, payload$); } getBrowseURLFor(metadatumKey: string, linkPath: string): Observable { 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 fe7f56220f..27b5ddf50d 100644 --- a/src/app/core/cache/builders/remote-data-build.service.ts +++ b/src/app/core/cache/builders/remote-data-build.service.ts @@ -1,11 +1,11 @@ import { combineLatest as observableCombineLatest, - of as observableOf, Observable, + of as observableOf, race as observableRace } from 'rxjs'; import { Injectable } from '@angular/core'; -import { distinctUntilChanged, flatMap, map, startWith } from 'rxjs/operators'; +import { distinctUntilChanged, flatMap, map, startWith, switchMap, tap } from 'rxjs/operators'; import { hasValue, hasValueOperator, isEmpty, isNotEmpty } from '../../../shared/empty.util'; import { PaginatedList } from '../../data/paginated-list'; import { RemoteData } from '../../data/remote-data'; @@ -16,22 +16,18 @@ import { RequestService } from '../../data/request.service'; import { NormalizedObject } from '../models/normalized-object.model'; import { ObjectCacheService } from '../object-cache.service'; -import { DSOSuccessResponse, ErrorResponse } from '../response-cache.models'; -import { ResponseCacheEntry } from '../response-cache.reducer'; -import { ResponseCacheService } from '../response-cache.service'; +import { DSOSuccessResponse, ErrorResponse } from '../response.models'; import { getMapsTo, getRelationMetadata, getRelationships } from './build-decorators'; import { PageInfo } from '../../shared/page-info.model'; import { + filterSuccessfulResponses, getRequestFromSelflink, - getResourceLinksFromResponse, - getResponseFromSelflink, - filterSuccessfulResponses + getResourceLinksFromResponse } from '../../shared/operators'; @Injectable() export class RemoteDataBuildService { constructor(protected objectCache: ObjectCacheService, - protected responseCache: ResponseCacheService, protected requestService: RequestService) { } @@ -39,19 +35,16 @@ export class RemoteDataBuildService { if (typeof href$ === 'string') { href$ = observableOf(href$); } - const requestHref$ = href$.pipe(flatMap((href: string) => - this.objectCache.getRequestHrefBySelfLink(href))); + const requestHref$ = href$.pipe( + switchMap((href: string) => + this.objectCache.getRequestHrefBySelfLink(href)), + ); const requestEntry$ = observableRace( href$.pipe(getRequestFromSelflink(this.requestService)), requestHref$.pipe(getRequestFromSelflink(this.requestService)) ); - const responseCache$ = observableRace( - href$.pipe(getResponseFromSelflink(this.responseCache)), - requestHref$.pipe(getResponseFromSelflink(this.responseCache)) - ); - // always use self link if that is cached, only if it isn't, get it via the response. const payload$ = observableCombineLatest( @@ -59,7 +52,7 @@ export class RemoteDataBuildService { flatMap((href: string) => this.objectCache.getBySelfLink(href)), startWith(undefined) ), - responseCache$.pipe( + requestEntry$.pipe( getResourceLinksFromResponse(), flatMap((resourceSelfLinks: string[]) => { if (isNotEmpty(resourceSelfLinks)) { @@ -86,21 +79,21 @@ export class RemoteDataBuildService { startWith(undefined), distinctUntilChanged() ); - return this.toRemoteDataObservable(requestEntry$, responseCache$, payload$); + return this.toRemoteDataObservable(requestEntry$, payload$); } - toRemoteDataObservable(requestEntry$: Observable, responseCache$: Observable, payload$: Observable) { - return observableCombineLatest(requestEntry$, responseCache$.pipe(startWith(undefined)), payload$).pipe( - map(([reqEntry, resEntry, payload]) => { + toRemoteDataObservable(requestEntry$: Observable, payload$: Observable) { + return observableCombineLatest(requestEntry$, requestEntry$.pipe(startWith(undefined)), payload$).pipe( + map(([reqEntry, payload]) => { const requestPending = hasValue(reqEntry.requestPending) ? reqEntry.requestPending : true; const responsePending = hasValue(reqEntry.responsePending) ? reqEntry.responsePending : false; let isSuccessful: boolean; let error: RemoteDataError; - if (hasValue(resEntry) && hasValue(resEntry.response)) { - isSuccessful = resEntry.response.isSuccessful; - const errorMessage = isSuccessful === false ? (resEntry.response as ErrorResponse).errorMessage : undefined; + if (hasValue(reqEntry) && hasValue(reqEntry.response)) { + isSuccessful = reqEntry.response.isSuccessful; + const errorMessage = isSuccessful === false ? (reqEntry.response as ErrorResponse).errorMessage : undefined; if (hasValue(errorMessage)) { - error = new RemoteDataError(resEntry.response.statusCode, errorMessage); + error = new RemoteDataError(reqEntry.response.statusCode, errorMessage); } } return new RemoteData( @@ -120,9 +113,7 @@ export class RemoteDataBuildService { } const requestEntry$ = href$.pipe(getRequestFromSelflink(this.requestService)); - const responseCache$ = href$.pipe(getResponseFromSelflink(this.responseCache)); - - const tDomainList$ = responseCache$.pipe( + const tDomainList$ = requestEntry$.pipe( getResourceLinksFromResponse(), flatMap((resourceUUIDs: string[]) => { return this.objectCache.getList(resourceUUIDs).pipe( @@ -135,12 +126,12 @@ export class RemoteDataBuildService { startWith([]), distinctUntilChanged() ); - - const pageInfo$ = responseCache$.pipe( + // tDomainList$.subscribe((t) => {console.log('domainlist', t)}); + const pageInfo$ = requestEntry$.pipe( filterSuccessfulResponses(), - map((entry: ResponseCacheEntry) => { - if (hasValue((entry.response as DSOSuccessResponse).pageInfo)) { - const resPageInfo = (entry.response as DSOSuccessResponse).pageInfo; + map((response: DSOSuccessResponse) => { + if (hasValue((response as DSOSuccessResponse).pageInfo)) { + const resPageInfo = (response as DSOSuccessResponse).pageInfo; if (isNotEmpty(resPageInfo) && resPageInfo.currentPage >= 0) { return Object.assign({}, resPageInfo, { currentPage: resPageInfo.currentPage + 1 }); } else { @@ -156,7 +147,7 @@ export class RemoteDataBuildService { }) ); - return this.toRemoteDataObservable(requestEntry$, responseCache$, payload$); + return this.toRemoteDataObservable(requestEntry$, payload$); } build(normalized: TNormalized): TDomain { @@ -204,8 +195,9 @@ export class RemoteDataBuildService { } } }); - const domainModel = getMapsTo(normalized.constructor); + // console.log('domain model', normalized); + return Object.assign(new domainModel(), normalized, links); } diff --git a/src/app/core/cache/response-cache.actions.ts b/src/app/core/cache/response-cache.actions.ts deleted file mode 100644 index 0389067690..0000000000 --- a/src/app/core/cache/response-cache.actions.ts +++ /dev/null @@ -1,72 +0,0 @@ -import { Action } from '@ngrx/store'; - -import { type } from '../../shared/ngrx/type'; -import { RestResponse } from './response-cache.models'; - -/** - * The list of ResponseCacheAction type definitions - */ -export const ResponseCacheActionTypes = { - ADD: type('dspace/core/cache/response/ADD'), - REMOVE: type('dspace/core/cache/response/REMOVE'), - RESET_TIMESTAMPS: type('dspace/core/cache/response/RESET_TIMESTAMPS') -}; - -/* tslint:disable:max-classes-per-file */ -export class ResponseCacheAddAction implements Action { - type = ResponseCacheActionTypes.ADD; - payload: { - key: string, - response: RestResponse - timeAdded: number; - msToLive: number; - }; - - constructor(key: string, response: RestResponse, timeAdded: number, msToLive: number) { - this.payload = { key, response, timeAdded, msToLive }; - } -} - -/** - * An ngrx action to remove a request from the cache - */ -export class ResponseCacheRemoveAction implements Action { - type = ResponseCacheActionTypes.REMOVE; - payload: string; - - /** - * Create a new ResponseCacheRemoveAction - * @param key - * The key of the request to remove - */ - constructor(key: string) { - this.payload = key; - } -} - -/** - * An ngrx action to reset the timeAdded property of all cached objects - */ -export class ResetResponseCacheTimestampsAction implements Action { - type = ResponseCacheActionTypes.RESET_TIMESTAMPS; - payload: number; - - /** - * Create a new ResetObjectCacheTimestampsAction - * - * @param newTimestamp - * the new timeAdded all objects should get - */ - constructor(newTimestamp: number) { - this.payload = newTimestamp; - } -} -/* tslint:enable:max-classes-per-file */ - -/** - * A type to encompass all ResponseCacheActions - */ -export type ResponseCacheAction - = ResponseCacheAddAction - | ResponseCacheRemoveAction - | ResetResponseCacheTimestampsAction; diff --git a/src/app/core/cache/response-cache.effects.spec.ts b/src/app/core/cache/response-cache.effects.spec.ts deleted file mode 100644 index 950049bfca..0000000000 --- a/src/app/core/cache/response-cache.effects.spec.ts +++ /dev/null @@ -1,38 +0,0 @@ -import { TestBed } from '@angular/core/testing'; -import { Observable } from 'rxjs'; -import { provideMockActions } from '@ngrx/effects/testing'; -import { cold, hot } from 'jasmine-marbles'; -import { StoreActionTypes } from '../../store.actions'; -import { ResponseCacheEffects } from './response-cache.effects'; -import { ResetResponseCacheTimestampsAction } from './response-cache.actions'; - -describe('ResponseCacheEffects', () => { - let cacheEffects: ResponseCacheEffects; - let actions: Observable; - const timestamp = 10000; - beforeEach(() => { - TestBed.configureTestingModule({ - providers: [ - ResponseCacheEffects, - provideMockActions(() => actions), - // other providers - ], - }); - - cacheEffects = TestBed.get(ResponseCacheEffects); - }); - - describe('fixTimestampsOnRehydrate$', () => { - - it('should return a RESET_TIMESTAMPS action in response to a REHYDRATE action', () => { - spyOn(Date.prototype, 'getTime').and.callFake(() => { - return timestamp; - }); - actions = hot('--a-', { a: { type: StoreActionTypes.REHYDRATE, payload: {} } }); - - const expected = cold('--b-', { b: new ResetResponseCacheTimestampsAction(new Date().getTime()) }); - - expect(cacheEffects.fixTimestampsOnRehydrate).toBeObservable(expected); - }); - }); -}); diff --git a/src/app/core/cache/response-cache.effects.ts b/src/app/core/cache/response-cache.effects.ts deleted file mode 100644 index 5a1e53e20c..0000000000 --- a/src/app/core/cache/response-cache.effects.ts +++ /dev/null @@ -1,27 +0,0 @@ -import { map } from 'rxjs/operators'; -import { Injectable } from '@angular/core'; -import { Actions, Effect, ofType } from '@ngrx/effects'; - -import { ResetResponseCacheTimestampsAction } from './response-cache.actions'; -import { StoreActionTypes } from '../../store.actions'; - -@Injectable() -export class ResponseCacheEffects { - - /** - * When the store is rehydrated in the browser, set all cache - * timestamps to 'now', because the time zone of the server can - * differ from the client. - * - * This assumes that the server cached everything a negligible - * time ago, and will likely need to be revisited later - */ - @Effect() fixTimestampsOnRehydrate = this.actions$ - .pipe(ofType(StoreActionTypes.REHYDRATE), - map(() => new ResetResponseCacheTimestampsAction(new Date().getTime())) - ); - - constructor(private actions$: Actions,) { - } - -} diff --git a/src/app/core/cache/response-cache.reducer.spec.ts b/src/app/core/cache/response-cache.reducer.spec.ts deleted file mode 100644 index 9037b20030..0000000000 --- a/src/app/core/cache/response-cache.reducer.spec.ts +++ /dev/null @@ -1,124 +0,0 @@ -import * as deepFreeze from 'deep-freeze'; - -import { responseCacheReducer, ResponseCacheState } from './response-cache.reducer'; - -import { - ResponseCacheRemoveAction, - ResetResponseCacheTimestampsAction, ResponseCacheAddAction -} from './response-cache.actions'; -import { RestResponse } from './response-cache.models'; - -class NullAction extends ResponseCacheRemoveAction { - type = null; - payload = null; - - constructor() { - super(null); - } -} - -describe('responseCacheReducer', () => { - const keys = ['125c17f89046283c5f0640722aac9feb', 'a06c3006a41caec5d635af099b0c780c']; - const msToLive = 900000; - const uuids = [ - '9e32a2e2-6b91-4236-a361-995ccdc14c60', - '598ce822-c357-46f3-ab70-63724d02d6ad', - 'be8325f7-243b-49f4-8a4b-df2b793ff3b5' - ]; - const testState: ResponseCacheState = { - [keys[0]]: { - key: keys[0], - response: new RestResponse(true, '200'), - timeAdded: new Date().getTime(), - msToLive: msToLive - }, - [keys[1]]: { - key: keys[1], - response: new RestResponse(true, '200'), - timeAdded: new Date().getTime(), - msToLive: msToLive - } - }; - deepFreeze(testState); - const errorState: {} = { - [keys[0]]: { - errorMessage: 'error', - resourceUUIDs: uuids - } - }; - deepFreeze(errorState); - - it('should return the current state when no valid actions have been made', () => { - const action = new NullAction(); - const newState = responseCacheReducer(testState, action); - - expect(newState).toEqual(testState); - }); - - it('should start with an empty cache', () => { - const action = new NullAction(); - const initialState = responseCacheReducer(undefined, action); - - expect(initialState).toEqual(Object.create(null)); - }); - - describe('ADD', () => { - const addTimeAdded = new Date().getTime(); - const addMsToLive = 5; - const addResponse = new RestResponse(true, '200'); - const action = new ResponseCacheAddAction(keys[0], addResponse, addTimeAdded, addMsToLive); - - it('should perform the action without affecting the previous state', () => { - // testState has already been frozen above - responseCacheReducer(testState, action); - }); - - it('should add the response to the cached request', () => { - const newState = responseCacheReducer(testState, action); - expect(newState[keys[0]].timeAdded).toBe(addTimeAdded); - expect(newState[keys[0]].msToLive).toBe(addMsToLive); - expect(newState[keys[0]].response).toBe(addResponse); - }); - }); - - describe('REMOVE', () => { - it('should perform the action without affecting the previous state', () => { - const action = new ResponseCacheRemoveAction(keys[0]); - // testState has already been frozen above - responseCacheReducer(testState, action); - }); - - it('should remove the specified request from the cache', () => { - const action = new ResponseCacheRemoveAction(keys[0]); - const newState = responseCacheReducer(testState, action); - expect(testState[keys[0]]).not.toBeUndefined(); - expect(newState[keys[0]]).toBeUndefined(); - }); - - it('shouldn\'t do anything when the specified key isn\'t cached', () => { - const wrongKey = 'this isn\'t cached'; - const action = new ResponseCacheRemoveAction(wrongKey); - const newState = responseCacheReducer(testState, action); - expect(testState[wrongKey]).toBeUndefined(); - expect(newState).toEqual(testState); - }); - }); - - describe('RESET_TIMESTAMPS', () => { - const newTimeStamp = new Date().getTime(); - const action = new ResetResponseCacheTimestampsAction(newTimeStamp); - - it('should perform the action without affecting the previous state', () => { - // testState has already been frozen above - responseCacheReducer(testState, action); - }); - - it('should set the timestamp of all requests in the cache', () => { - const newState = responseCacheReducer(testState, action); - Object.keys(newState).forEach((key) => { - expect(newState[key].timeAdded).toEqual(newTimeStamp); - }); - }); - - }); -}); diff --git a/src/app/core/cache/response-cache.reducer.ts b/src/app/core/cache/response-cache.reducer.ts deleted file mode 100644 index 73c680c1f5..0000000000 --- a/src/app/core/cache/response-cache.reducer.ts +++ /dev/null @@ -1,111 +0,0 @@ -import { - ResponseCacheAction, ResponseCacheActionTypes, - ResponseCacheRemoveAction, ResetResponseCacheTimestampsAction, - ResponseCacheAddAction -} from './response-cache.actions'; -import { CacheEntry } from './cache-entry'; -import { hasValue } from '../../shared/empty.util'; -import { RestResponse } from './response-cache.models'; - -/** - * An entry in the ResponseCache - */ -export class ResponseCacheEntry implements CacheEntry { - key: string; - response: RestResponse; - timeAdded: number; - msToLive: number; -} - -/** - * The ResponseCache State - */ -export interface ResponseCacheState { - [key: string]: ResponseCacheEntry -} - -// Object.create(null) ensures the object has no default js properties (e.g. `__proto__`) -const initialState = Object.create(null); - -/** - * The ResponseCache Reducer - * - * @param state - * the current state - * @param action - * the action to perform on the state - * @return ResponseCacheState - * the new state - */ -export function responseCacheReducer(state = initialState, action: ResponseCacheAction): ResponseCacheState { - switch (action.type) { - - case ResponseCacheActionTypes.ADD: { - return addToCache(state, action as ResponseCacheAddAction); - } - - case ResponseCacheActionTypes.REMOVE: { - return removeFromCache(state, action as ResponseCacheRemoveAction); - } - - case ResponseCacheActionTypes.RESET_TIMESTAMPS: { - return resetResponseCacheTimestamps(state, action as ResetResponseCacheTimestampsAction) - } - - default: { - return state; - } - } -} - -function addToCache(state: ResponseCacheState, action: ResponseCacheAddAction): ResponseCacheState { - return Object.assign({}, state, { - [action.payload.key]: { - key: action.payload.key, - response: action.payload.response, - timeAdded: action.payload.timeAdded, - msToLive: action.payload.msToLive - } - }); -} - -/** - * Remove a request from the cache - * - * @param state - * the current state - * @param action - * an ResponseCacheRemoveAction - * @return ResponseCacheState - * the new state, with the request removed if it existed. - */ -function removeFromCache(state: ResponseCacheState, action: ResponseCacheRemoveAction): ResponseCacheState { - if (hasValue(state[action.payload])) { - const newCache = Object.assign({}, state); - delete newCache[action.payload]; - - return newCache; - } else { - return state; - } -} - -/** - * Set the timeAdded timestamp of every cached request to the specified value - * - * @param state - * the current state - * @param action - * a ResetResponseCacheTimestampsAction - * @return ResponseCacheState - * the new state, with all timeAdded timestamps set to the specified value - */ -function resetResponseCacheTimestamps(state: ResponseCacheState, action: ResetResponseCacheTimestampsAction): ResponseCacheState { - const newState = Object.create(null); - Object.keys(state).forEach((key) => { - newState[key] = Object.assign({}, state[key], { - timeAdded: action.payload - }); - }); - return newState; -} diff --git a/src/app/core/cache/response-cache.service.spec.ts b/src/app/core/cache/response-cache.service.spec.ts deleted file mode 100644 index 4fcd926343..0000000000 --- a/src/app/core/cache/response-cache.service.spec.ts +++ /dev/null @@ -1,100 +0,0 @@ -import { Store } from '@ngrx/store'; - -import { ResponseCacheService } from './response-cache.service'; -import { of as observableOf } from 'rxjs'; -import { CoreState } from '../core.reducers'; -import { RestResponse } from './response-cache.models'; -import { ResponseCacheEntry } from './response-cache.reducer'; -import { first } from 'rxjs/operators'; -import * as ngrx from '@ngrx/store' -import { cold } from 'jasmine-marbles'; - -describe('ResponseCacheService', () => { - let service: ResponseCacheService; - let store: Store; - - const keys = ['125c17f89046283c5f0640722aac9feb', 'a06c3006a41caec5d635af099b0c780c']; - const timestamp = new Date().getTime(); - const validCacheEntry = (key) => { - return { - key: key, - response: new RestResponse(true, '200'), - timeAdded: timestamp, - msToLive: 24 * 60 * 60 * 1000 // a day - } - }; - const invalidCacheEntry = (key) => { - return { - key: key, - response: new RestResponse(true, '200'), - timeAdded: 0, - msToLive: 0 - } - }; - - beforeEach(() => { - store = new Store(undefined, undefined, undefined); - spyOn(store, 'dispatch'); - service = new ResponseCacheService(store); - spyOn(Date.prototype, 'getTime').and.callFake(() => { - return timestamp; - }); - }); - - describe('get', () => { - it('should return an observable of the cached request with the specified key', () => { - spyOnProperty(ngrx, 'select').and.callFake(() => { - return () => { - return () => observableOf(validCacheEntry(keys[1])); - }; - }); - let testObj: ResponseCacheEntry; - service.get(keys[1]).pipe(first()).subscribe((entry) => { - testObj = entry; - }); - expect(testObj.key).toEqual(keys[1]); - }); - - it('should not return a cached request that has exceeded its time to live', () => { - spyOnProperty(ngrx, 'select').and.callFake(() => { - return () => { - return () => observableOf(invalidCacheEntry(keys[1])); - }; - }); - - let getObsHasFired = false; - const subscription = service.get(keys[1]).subscribe((entry) => getObsHasFired = true); - expect(getObsHasFired).toBe(false); - subscription.unsubscribe(); - }); - }); - - describe('has', () => { - it('should return true if the request with the supplied key is cached and still valid', () => { - spyOnProperty(ngrx, 'select').and.callFake(() => { - return () => { - return () => observableOf(validCacheEntry(keys[1])); - }; - }); - expect(service.has(keys[1])).toBe(true); - }); - - it('should return false if the request with the supplied key isn\'t cached', () => { - spyOnProperty(ngrx, 'select').and.callFake(() => { - return () => { - return () => observableOf(undefined); - }; - }); - expect(service.has(keys[1])).toBe(false); - }); - - it('should return false if the request with the supplied key is cached but has exceeded its time to live', () => { - spyOnProperty(ngrx, 'select').and.callFake(() => { - return () => { - return () => observableOf(invalidCacheEntry(keys[1])); - }; - }); - expect(service.has(keys[1])).toBe(false); - }); - }); -}); diff --git a/src/app/core/cache/response-cache.service.ts b/src/app/core/cache/response-cache.service.ts deleted file mode 100644 index 973d3620ff..0000000000 --- a/src/app/core/cache/response-cache.service.ts +++ /dev/null @@ -1,100 +0,0 @@ -import { filter, take, distinctUntilChanged, first } from 'rxjs/operators'; -import { Injectable } from '@angular/core'; -import { MemoizedSelector, select, Store } from '@ngrx/store'; - -import { Observable } from 'rxjs'; - -import { ResponseCacheEntry } from './response-cache.reducer'; -import { hasNoValue } from '../../shared/empty.util'; -import { ResponseCacheRemoveAction, ResponseCacheAddAction } from './response-cache.actions'; -import { RestResponse } from './response-cache.models'; -import { coreSelector, CoreState } from '../core.reducers'; -import { pathSelector } from '../shared/selectors'; - -function entryFromKeySelector(key: string): MemoizedSelector { - return pathSelector(coreSelector, 'cache/response', key); -} - -/** - * A service to interact with the response cache - */ -@Injectable() -export class ResponseCacheService { - constructor( - private store: Store - ) { - } - - add(key: string, response: RestResponse, msToLive: number): Observable { - if (!this.has(key)) { - this.store.dispatch(new ResponseCacheAddAction(key, response, new Date().getTime(), msToLive)); - } - return this.get(key); - } - - /** - * Get an observable of the response with the specified key - * - * @param key - * the key of the response to get - * @return Observable - * an observable of the ResponseCacheEntry with the specified key - */ - get(key: string): Observable { - return this.store.pipe( - select(entryFromKeySelector(key)), - filter((entry: ResponseCacheEntry) => this.isValid(entry)), - distinctUntilChanged() - ) - } - - /** - * Check whether the response with the specified key is cached - * - * @param key - * the key of the response to check - * @return boolean - * true if the response with the specified key is cached, - * false otherwise - */ - has(key: string): boolean { - let result: boolean; - - this.store.pipe(select(entryFromKeySelector(key)), - first() - ).subscribe((entry: ResponseCacheEntry) => { - result = this.isValid(entry); - }); - - return result; - } - - remove(key: string): void { - if (this.has(key)) { - this.store.dispatch(new ResponseCacheRemoveAction(key)); - } - } - - /** - * Check whether a ResponseCacheEntry should still be cached - * - * @param entry - * the entry to check - * @return boolean - * false if the entry is null, undefined, or its time to - * live has been exceeded, true otherwise - */ - private isValid(entry: ResponseCacheEntry): boolean { - if (hasNoValue(entry)) { - return false; - } else { - const timeOutdated = entry.timeAdded + entry.msToLive; - const isOutDated = new Date().getTime() > timeOutdated; - if (isOutDated) { - this.store.dispatch(new ResponseCacheRemoveAction(entry.key)); - } - return !isOutDated; - } - } - -} diff --git a/src/app/core/cache/response-cache.models.ts b/src/app/core/cache/response.models.ts similarity index 99% rename from src/app/core/cache/response-cache.models.ts rename to src/app/core/cache/response.models.ts index 9566dcdc3c..fcec635655 100644 --- a/src/app/core/cache/response-cache.models.ts +++ b/src/app/core/cache/response.models.ts @@ -13,7 +13,7 @@ import { AuthStatus } from '../auth/models/auth-status.model'; /* tslint:disable:max-classes-per-file */ export class RestResponse { - public toCache = true; + public timeAdded: number; constructor( public isSuccessful: boolean, diff --git a/src/app/core/config/config.service.spec.ts b/src/app/core/config/config.service.spec.ts index 46c8fd1859..8e9f7db27a 100644 --- a/src/app/core/config/config.service.spec.ts +++ b/src/app/core/config/config.service.spec.ts @@ -1,7 +1,6 @@ import { cold, getTestScheduler, hot } from 'jasmine-marbles'; import { TestScheduler } from 'rxjs/testing'; import { getMockRequestService } from '../../shared/mocks/mock-request.service'; -import { ResponseCacheService } from '../cache/response-cache.service'; import { ConfigService } from './config.service'; import { RequestService } from '../data/request.service'; import { ConfigRequest, FindAllOptions } from '../data/request.models'; @@ -16,7 +15,6 @@ class TestService extends ConfigService { protected browseEndpoint = BROWSE; constructor( - protected responseCache: ResponseCacheService, protected requestService: RequestService, protected halService: HALEndpointService) { super(); @@ -26,7 +24,6 @@ class TestService extends ConfigService { describe('ConfigService', () => { let scheduler: TestScheduler; let service: TestService; - let responseCache: ResponseCacheService; let requestService: RequestService; let halService: any; @@ -39,17 +36,9 @@ describe('ConfigService', () => { const scopedEndpoint = `${serviceEndpoint}/${scopeName}`; const searchEndpoint = `${serviceEndpoint}/${BROWSE}?uuid=${scopeID}`; - function initMockResponseCacheService(isSuccessful: boolean): ResponseCacheService { - return jasmine.createSpyObj('responseCache', { - get: cold('c-', { - c: { response: { isSuccessful } } - }) - }); - } function initTestService(): TestService { return new TestService( - responseCache, requestService, halService ); @@ -57,7 +46,6 @@ describe('ConfigService', () => { beforeEach(() => { scheduler = getTestScheduler(); - responseCache = initMockResponseCacheService(true); requestService = getMockRequestService(); halService = new HALEndpointServiceStub(configEndpoint); service = initTestService(); diff --git a/src/app/core/config/config.service.ts b/src/app/core/config/config.service.ts index 872bc57c2b..c6c2e2e7d2 100644 --- a/src/app/core/config/config.service.ts +++ b/src/app/core/config/config.service.ts @@ -1,24 +1,25 @@ -import { Observable, of as observableOf, throwError as observableThrowError, merge as observableMerge } from 'rxjs'; +import { merge as observableMerge, Observable, throwError as observableThrowError } from 'rxjs'; import { distinctUntilChanged, filter, map, mergeMap, tap } from 'rxjs/operators'; import { RequestService } from '../data/request.service'; -import { ResponseCacheService } from '../cache/response-cache.service'; -import { ConfigSuccessResponse } from '../cache/response-cache.models'; +import { ConfigSuccessResponse } from '../cache/response.models'; import { ConfigRequest, FindAllOptions, RestRequest } from '../data/request.models'; -import { ResponseCacheEntry } from '../cache/response-cache.reducer'; import { hasValue, isNotEmpty } from '../../shared/empty.util'; import { HALEndpointService } from '../shared/hal-endpoint.service'; import { ConfigData } from './config-data'; +import { RequestEntry } from '../data/request.reducer'; +import { getResponseFromEntry } from '../shared/operators'; export abstract class ConfigService { protected request: ConfigRequest; - protected abstract responseCache: ResponseCacheService; protected abstract requestService: RequestService; protected abstract linkPath: string; protected abstract browseEndpoint: string; protected abstract halService: HALEndpointService; protected getConfig(request: RestRequest): Observable { - const responses = this.responseCache.get(request.href).pipe(map((entry: ResponseCacheEntry) => entry.response)); + const responses = this.requestService.getByHref(request.href).pipe( + getResponseFromEntry() + ); const errorResponses = responses.pipe( filter((response) => !response.isSuccessful), mergeMap(() => observableThrowError(new Error(`Couldn't retrieve the config`))) @@ -94,7 +95,6 @@ export abstract class ConfigService { } public getConfigBySearch(options: FindAllOptions = {}): Observable { - console.log(this.halService.getEndpoint(this.linkPath)); return this.halService.getEndpoint(this.linkPath).pipe( map((endpoint: string) => this.getConfigSearchHref(endpoint, options)), filter((href: string) => isNotEmpty(href)), diff --git a/src/app/core/config/submission-definitions-config.service.ts b/src/app/core/config/submission-definitions-config.service.ts index 6cbe0c55b5..b7b0873c21 100644 --- a/src/app/core/config/submission-definitions-config.service.ts +++ b/src/app/core/config/submission-definitions-config.service.ts @@ -1,7 +1,6 @@ import { Injectable } from '@angular/core'; import { ConfigService } from './config.service'; -import { ResponseCacheService } from '../cache/response-cache.service'; import { RequestService } from '../data/request.service'; import { HALEndpointService } from '../shared/hal-endpoint.service'; @@ -11,7 +10,6 @@ export class SubmissionDefinitionsConfigService extends ConfigService { protected browseEndpoint = 'search/findByCollection'; constructor( - protected responseCache: ResponseCacheService, protected requestService: RequestService, protected halService: HALEndpointService) { super(); diff --git a/src/app/core/config/submission-forms-config.service.ts b/src/app/core/config/submission-forms-config.service.ts index 27eac78218..b688859ec9 100644 --- a/src/app/core/config/submission-forms-config.service.ts +++ b/src/app/core/config/submission-forms-config.service.ts @@ -1,7 +1,6 @@ import { Injectable } from '@angular/core'; import { ConfigService } from './config.service'; -import { ResponseCacheService } from '../cache/response-cache.service'; import { RequestService } from '../data/request.service'; import { HALEndpointService } from '../shared/hal-endpoint.service'; @@ -11,7 +10,6 @@ export class SubmissionFormsConfigService extends ConfigService { protected browseEndpoint = ''; constructor( - protected responseCache: ResponseCacheService, protected requestService: RequestService, protected halService: HALEndpointService) { super(); diff --git a/src/app/core/config/submission-sections-config.service.ts b/src/app/core/config/submission-sections-config.service.ts index 6d4d2ca825..c8bbc0dd97 100644 --- a/src/app/core/config/submission-sections-config.service.ts +++ b/src/app/core/config/submission-sections-config.service.ts @@ -1,7 +1,6 @@ import { Injectable } from '@angular/core'; import { ConfigService } from './config.service'; -import { ResponseCacheService } from '../cache/response-cache.service'; import { RequestService } from '../data/request.service'; import { HALEndpointService } from '../shared/hal-endpoint.service'; @@ -11,7 +10,6 @@ export class SubmissionSectionsConfigService extends ConfigService { protected browseEndpoint = ''; constructor( - protected responseCache: ResponseCacheService, protected requestService: RequestService, protected halService: HALEndpointService) { super(); diff --git a/src/app/core/core.effects.ts b/src/app/core/core.effects.ts index 881f01aed0..c9a352c545 100644 --- a/src/app/core/core.effects.ts +++ b/src/app/core/core.effects.ts @@ -1,13 +1,11 @@ import { ObjectCacheEffects } from './cache/object-cache.effects'; -import { ResponseCacheEffects } from './cache/response-cache.effects'; import { UUIDIndexEffects } from './index/index.effects'; import { RequestEffects } from './data/request.effects'; import { AuthEffects } from './auth/auth.effects'; import { ServerSyncBufferEffects } from './cache/server-sync-buffer.effects'; export const coreEffects = [ - ResponseCacheEffects, RequestEffects, ObjectCacheEffects, UUIDIndexEffects, diff --git a/src/app/core/core.module.ts b/src/app/core/core.module.ts index 73e97c7933..dcbdbd0049 100644 --- a/src/app/core/core.module.ts +++ b/src/app/core/core.module.ts @@ -32,7 +32,6 @@ import { ObjectCacheService } from './cache/object-cache.service'; import { PaginationComponentOptions } from '../shared/pagination/pagination-component-options.model'; import { RemoteDataBuildService } from './cache/builders/remote-data-build.service'; import { RequestService } from './data/request.service'; -import { ResponseCacheService } from './cache/response-cache.service'; import { EndpointMapResponseParsingService } from './data/endpoint-map-response-parsing.service'; import { ServerResponseService } from '../shared/services/server-response.service'; import { NativeWindowFactory, NativeWindowService } from '../shared/services/window.service'; @@ -102,7 +101,6 @@ const PROVIDERS = [ RegistryService, RemoteDataBuildService, RequestService, - ResponseCacheService, EndpointMapResponseParsingService, FacetValueResponseParsingService, FacetValueMapResponseParsingService, diff --git a/src/app/core/core.reducers.ts b/src/app/core/core.reducers.ts index 6905eb1300..1843e10671 100644 --- a/src/app/core/core.reducers.ts +++ b/src/app/core/core.reducers.ts @@ -1,6 +1,5 @@ import { ActionReducerMap, createFeatureSelector } from '@ngrx/store'; -import { responseCacheReducer, ResponseCacheState } from './cache/response-cache.reducer'; import { objectCacheReducer, ObjectCacheState } from './cache/object-cache.reducer'; import { indexReducer, IndexState } from './index/index.reducer'; import { requestReducer, RequestState } from './data/request.reducer'; @@ -9,7 +8,6 @@ import { serverSyncBufferReducer, ServerSyncBufferState } from './cache/server-s export interface CoreState { 'cache/object': ObjectCacheState, - 'cache/response': ResponseCacheState, 'cache/syncbuffer': ServerSyncBufferState, 'data/request': RequestState, 'index': IndexState, @@ -18,7 +16,6 @@ export interface CoreState { export const coreReducers: ActionReducerMap = { 'cache/object': objectCacheReducer, - 'cache/response': responseCacheReducer, 'cache/syncbuffer': serverSyncBufferReducer, 'data/request': requestReducer, 'index': indexReducer, diff --git a/src/app/core/data/browse-entries-response-parsing.service.spec.ts b/src/app/core/data/browse-entries-response-parsing.service.spec.ts index dd04e4f2f5..a61da7aa95 100644 --- a/src/app/core/data/browse-entries-response-parsing.service.spec.ts +++ b/src/app/core/data/browse-entries-response-parsing.service.spec.ts @@ -1,5 +1,5 @@ import { getMockObjectCacheService } from '../../shared/mocks/mock-object-cache.service'; -import { ErrorResponse, GenericSuccessResponse } from '../cache/response-cache.models'; +import { ErrorResponse, GenericSuccessResponse } from '../cache/response.models'; import { DSpaceRESTV2Response } from '../dspace-rest-v2/dspace-rest-v2-response.model'; import { BrowseEntriesResponseParsingService } from './browse-entries-response-parsing.service'; import { BrowseEntriesRequest } from './request.models'; diff --git a/src/app/core/data/browse-entries-response-parsing.service.ts b/src/app/core/data/browse-entries-response-parsing.service.ts index 171def60df..39600b637d 100644 --- a/src/app/core/data/browse-entries-response-parsing.service.ts +++ b/src/app/core/data/browse-entries-response-parsing.service.ts @@ -7,7 +7,7 @@ import { ErrorResponse, GenericSuccessResponse, RestResponse -} from '../cache/response-cache.models'; +} from '../cache/response.models'; import { DSpaceRESTV2Response } from '../dspace-rest-v2/dspace-rest-v2-response.model'; import { DSpaceRESTv2Serializer } from '../dspace-rest-v2/dspace-rest-v2.serializer'; import { BrowseEntry } from '../shared/browse-entry.model'; diff --git a/src/app/core/data/browse-items-response-parsing-service.spec.ts b/src/app/core/data/browse-items-response-parsing-service.spec.ts index 6a141c01c4..99ea474dc6 100644 --- a/src/app/core/data/browse-items-response-parsing-service.spec.ts +++ b/src/app/core/data/browse-items-response-parsing-service.spec.ts @@ -1,5 +1,5 @@ import { getMockObjectCacheService } from '../../shared/mocks/mock-object-cache.service'; -import { ErrorResponse, GenericSuccessResponse } from '../cache/response-cache.models'; +import { ErrorResponse, GenericSuccessResponse } from '../cache/response.models'; import { DSpaceRESTV2Response } from '../dspace-rest-v2/dspace-rest-v2-response.model'; import { BrowseEntriesResponseParsingService } from './browse-entries-response-parsing.service'; import { BrowseEntriesRequest, BrowseItemsRequest } from './request.models'; diff --git a/src/app/core/data/browse-items-response-parsing-service.ts b/src/app/core/data/browse-items-response-parsing-service.ts index e513ad0898..218c25bac6 100644 --- a/src/app/core/data/browse-items-response-parsing-service.ts +++ b/src/app/core/data/browse-items-response-parsing-service.ts @@ -7,7 +7,7 @@ import { ErrorResponse, GenericSuccessResponse, RestResponse -} from '../cache/response-cache.models'; +} from '../cache/response.models'; import { DSpaceRESTV2Response } from '../dspace-rest-v2/dspace-rest-v2-response.model'; import { DSpaceRESTv2Serializer } from '../dspace-rest-v2/dspace-rest-v2.serializer'; import { BaseResponseParsingService } from './base-response-parsing.service'; diff --git a/src/app/core/data/browse-response-parsing.service.spec.ts b/src/app/core/data/browse-response-parsing.service.spec.ts index 2b1703e38f..bedf5f03a7 100644 --- a/src/app/core/data/browse-response-parsing.service.spec.ts +++ b/src/app/core/data/browse-response-parsing.service.spec.ts @@ -1,6 +1,6 @@ import { BrowseResponseParsingService } from './browse-response-parsing.service'; import { BrowseEndpointRequest } from './request.models'; -import { GenericSuccessResponse, ErrorResponse } from '../cache/response-cache.models'; +import { GenericSuccessResponse, ErrorResponse } from '../cache/response.models'; import { BrowseDefinition } from '../shared/browse-definition.model'; import { DSpaceRESTV2Response } from '../dspace-rest-v2/dspace-rest-v2-response.model'; diff --git a/src/app/core/data/browse-response-parsing.service.ts b/src/app/core/data/browse-response-parsing.service.ts index 8feb1bc82b..523fffd565 100644 --- a/src/app/core/data/browse-response-parsing.service.ts +++ b/src/app/core/data/browse-response-parsing.service.ts @@ -2,7 +2,7 @@ import { Injectable } from '@angular/core'; import { ResponseParsingService } from './parsing.service'; import { RestRequest } from './request.models'; import { DSpaceRESTV2Response } from '../dspace-rest-v2/dspace-rest-v2-response.model'; -import { GenericSuccessResponse, ErrorResponse, RestResponse } from '../cache/response-cache.models'; +import { GenericSuccessResponse, ErrorResponse, RestResponse } from '../cache/response.models'; import { isNotEmpty } from '../../shared/empty.util'; import { DSpaceRESTv2Serializer } from '../dspace-rest-v2/dspace-rest-v2.serializer'; import { BrowseDefinition } from '../shared/browse-definition.model'; diff --git a/src/app/core/data/collection-data.service.ts b/src/app/core/data/collection-data.service.ts index 2642c4b5e6..74c73e37f3 100644 --- a/src/app/core/data/collection-data.service.ts +++ b/src/app/core/data/collection-data.service.ts @@ -1,10 +1,8 @@ import { Inject, Injectable } from '@angular/core'; import { Store } from '@ngrx/store'; -import { GLOBAL_CONFIG, GlobalConfig } from '../../../config'; import { RemoteDataBuildService } from '../cache/builders/remote-data-build.service'; import { NormalizedCollection } from '../cache/models/normalized-collection.model'; import { ObjectCacheService } from '../cache/object-cache.service'; -import { ResponseCacheService } from '../cache/response-cache.service'; import { CoreState } from '../core.reducers'; import { Collection } from '../shared/collection.model'; import { ComColDataService } from './comcol-data.service'; @@ -17,7 +15,6 @@ export class CollectionDataService extends ComColDataService, diff --git a/src/app/core/data/comcol-data.service.spec.ts b/src/app/core/data/comcol-data.service.spec.ts index bc9dc9114a..2125aff797 100644 --- a/src/app/core/data/comcol-data.service.spec.ts +++ b/src/app/core/data/comcol-data.service.spec.ts @@ -5,7 +5,6 @@ import { GlobalConfig } from '../../../config'; import { getMockRequestService } from '../../shared/mocks/mock-request.service'; import { RemoteDataBuildService } from '../cache/builders/remote-data-build.service'; import { ObjectCacheService } from '../cache/object-cache.service'; -import { ResponseCacheService } from '../cache/response-cache.service'; import { CoreState } from '../core.reducers'; import { ComColDataService } from './comcol-data.service'; import { CommunityDataService } from './community-data.service'; @@ -23,7 +22,6 @@ class NormalizedTestObject extends NormalizedObject { class TestService extends ComColDataService { constructor( - protected responseCache: ResponseCacheService, protected requestService: RequestService, protected rdbService: RemoteDataBuildService, protected store: Store, @@ -41,7 +39,6 @@ class TestService extends ComColDataService { describe('ComColDataService', () => { let scheduler: TestScheduler; let service: TestService; - let responseCache: ResponseCacheService; let requestService: RequestService; let cds: CommunityDataService; let objectCache: ObjectCacheService; @@ -68,14 +65,6 @@ describe('ComColDataService', () => { }); } - function initMockResponseCacheService(isSuccessful: boolean): ResponseCacheService { - return jasmine.createSpyObj('responseCache', { - get: cold('c-', { - c: { response: { isSuccessful } } - }) - }); - } - function initMockObjectCacheService(): ObjectCacheService { return jasmine.createSpyObj('objectCache', { getByUUID: cold('d-', { @@ -90,7 +79,6 @@ describe('ComColDataService', () => { function initTestService(): TestService { return new TestService( - responseCache, requestService, rdbService, store, @@ -111,7 +99,6 @@ describe('ComColDataService', () => { cds = initMockCommunityDataService(); requestService = getMockRequestService(); objectCache = initMockObjectCacheService(); - responseCache = initMockResponseCacheService(true); service = initTestService(); const expected = new FindByIDRequest(requestService.generateRequestId(), communityEndpoint, scopeID); @@ -127,7 +114,6 @@ describe('ComColDataService', () => { cds = initMockCommunityDataService(); requestService = getMockRequestService(); objectCache = initMockObjectCacheService(); - responseCache = initMockResponseCacheService(true); service = initTestService(); }); @@ -150,7 +136,6 @@ describe('ComColDataService', () => { cds = initMockCommunityDataService(); requestService = getMockRequestService(); objectCache = initMockObjectCacheService(); - responseCache = initMockResponseCacheService(false); service = initTestService(); }); diff --git a/src/app/core/data/comcol-data.service.ts b/src/app/core/data/comcol-data.service.ts index c589c5bdc8..95a0015125 100644 --- a/src/app/core/data/comcol-data.service.ts +++ b/src/app/core/data/comcol-data.service.ts @@ -1,15 +1,16 @@ -import { distinctUntilChanged, filter, map, mergeMap, take, tap } from 'rxjs/operators'; +import { distinctUntilChanged, filter, map, mergeMap, share, take, tap } from 'rxjs/operators'; import { merge as observableMerge, Observable, throwError as observableThrowError } from 'rxjs'; -import { isEmpty, isNotEmpty } from '../../shared/empty.util'; +import { hasValue, isEmpty, isNotEmpty } from '../../shared/empty.util'; import { NormalizedCommunity } from '../cache/models/normalized-community.model'; import { ObjectCacheService } from '../cache/object-cache.service'; -import { ResponseCacheEntry } from '../cache/response-cache.reducer'; import { CommunityDataService } from './community-data.service'; import { DataService } from './data.service'; import { FindAllOptions, FindByIDRequest } from './request.models'; import { NormalizedObject } from '../cache/models/normalized-object.model'; import { HALEndpointService } from '../shared/hal-endpoint.service'; +import { RequestEntry } from './request.reducer'; +import { getResponseFromEntry } from '../shared/operators'; export abstract class ComColDataService extends DataService { protected abstract cds: CommunityDataService; @@ -26,9 +27,9 @@ export abstract class ComColDataService } * an Observable containing the scoped URL */ - public getBrowseEndpoint(options: FindAllOptions = {}): Observable { + public getBrowseEndpoint(options: FindAllOptions = {}, linkPath: string = this.linkPath): Observable { if (isEmpty(options.scopeID)) { - return this.halService.getEndpoint(this.linkPath); + return this.halService.getEndpoint(linkPath); } else { const scopeCommunityHrefObs = this.cds.getEndpoint().pipe( mergeMap((endpoint: string) => this.cds.getFindByIDHref(endpoint, options.scopeID)), @@ -37,7 +38,7 @@ export abstract class ComColDataService { const request = new FindByIDRequest(this.requestService.generateRequestId(), href, options.scopeID); this.requestService.configure(request); - }),); + })); // return scopeCommunityHrefObs.pipe( // mergeMap((href: string) => this.responseCache.get(href)), @@ -46,7 +47,7 @@ export abstract class ComColDataService = this.objectCache.getByUUID(scopeID); // return community$.pipe( - // map((community) => community._links[this.linkPath]), + // map((community) => community._links[linkPath]), // filter((href) => isNotEmpty(href)), // distinctUntilChanged() // ); @@ -57,8 +58,8 @@ export abstract class ComColDataService this.responseCache.get(href)), - map((entry: ResponseCacheEntry) => entry.response)); + mergeMap((href: string) => this.requestService.getByHref(href)), + getResponseFromEntry()); const errorResponses = responses.pipe( filter((response) => !response.isSuccessful), mergeMap(() => observableThrowError(new Error(`The Community with scope ${options.scopeID} couldn't be retrieved`))) @@ -66,11 +67,11 @@ export abstract class ComColDataService response.isSuccessful), mergeMap(() => this.objectCache.getByUUID(options.scopeID)), - map((nc: NormalizedCommunity) => nc._links[this.linkPath]), + map((nc: NormalizedCommunity) => nc._links[linkPath]), filter((href) => isNotEmpty(href)) ); - return observableMerge(errorResponses, successResponses).pipe(distinctUntilChanged()); + return observableMerge(errorResponses, successResponses).pipe(distinctUntilChanged(), share()); } } } diff --git a/src/app/core/data/community-data.service.ts b/src/app/core/data/community-data.service.ts index df0e739490..a037936202 100644 --- a/src/app/core/data/community-data.service.ts +++ b/src/app/core/data/community-data.service.ts @@ -1,12 +1,10 @@ - -import {mergeMap, filter, take} from 'rxjs/operators'; +import { filter, mergeMap, take } from 'rxjs/operators'; import { Injectable } from '@angular/core'; import { Store } from '@ngrx/store'; import { RemoteDataBuildService } from '../cache/builders/remote-data-build.service'; import { NormalizedCommunity } from '../cache/models/normalized-community.model'; import { ObjectCacheService } from '../cache/object-cache.service'; -import { ResponseCacheService } from '../cache/response-cache.service'; import { CoreState } from '../core.reducers'; import { Community } from '../shared/community.model'; import { ComColDataService } from './comcol-data.service'; @@ -25,7 +23,6 @@ export class CommunityDataService extends ComColDataService, @@ -40,12 +37,10 @@ export class CommunityDataService extends ComColDataService>> { - const hrefObs = this.halService.getEndpoint(this.topLinkPath).pipe(filter((href: string) => isNotEmpty(href)), - mergeMap((endpoint: string) => this.getFindAllHref(options)),); - + const hrefObs = this.getFindAllHref(options, this.topLinkPath); hrefObs.pipe( filter((href: string) => hasValue(href)), - take(1),) + take(1)) .subscribe((href: string) => { const request = new FindAllRequest(this.requestService.generateRequestId(), href, options); this.requestService.configure(request); diff --git a/src/app/core/data/config-response-parsing.service.spec.ts b/src/app/core/data/config-response-parsing.service.spec.ts index 654ee53651..a33c5cf5b5 100644 --- a/src/app/core/data/config-response-parsing.service.spec.ts +++ b/src/app/core/data/config-response-parsing.service.spec.ts @@ -1,4 +1,4 @@ -import { ConfigSuccessResponse, ErrorResponse } from '../cache/response-cache.models'; +import { ConfigSuccessResponse, ErrorResponse } from '../cache/response.models'; import { ConfigResponseParsingService } from './config-response-parsing.service'; import { ObjectCacheService } from '../cache/object-cache.service'; import { GlobalConfig } from '../../../config/global-config.interface'; diff --git a/src/app/core/data/config-response-parsing.service.ts b/src/app/core/data/config-response-parsing.service.ts index 2b1b923625..ddf884e02b 100644 --- a/src/app/core/data/config-response-parsing.service.ts +++ b/src/app/core/data/config-response-parsing.service.ts @@ -3,7 +3,7 @@ import { Inject, Injectable } from '@angular/core'; import { ResponseParsingService } from './parsing.service'; import { RestRequest } from './request.models'; import { DSpaceRESTV2Response } from '../dspace-rest-v2/dspace-rest-v2-response.model'; -import { ConfigSuccessResponse, ErrorResponse, RestResponse } from '../cache/response-cache.models'; +import { ConfigSuccessResponse, ErrorResponse, RestResponse } from '../cache/response.models'; import { isNotEmpty } from '../../shared/empty.util'; import { ConfigObjectFactory } from '../shared/config/config-object-factory'; diff --git a/src/app/core/data/data.service.spec.ts b/src/app/core/data/data.service.spec.ts index e60725c4c2..7da709abd5 100644 --- a/src/app/core/data/data.service.spec.ts +++ b/src/app/core/data/data.service.spec.ts @@ -1,6 +1,5 @@ import { DataService } from './data.service'; import { NormalizedObject } from '../cache/models/normalized-object.model'; -import { ResponseCacheService } from '../cache/response-cache.service'; import { RequestService } from './request.service'; import { RemoteDataBuildService } from '../cache/builders/remote-data-build.service'; import { CoreState } from '../core.reducers'; @@ -22,7 +21,6 @@ class NormalizedTestObject extends NormalizedObject { class TestService extends DataService { constructor( - protected responseCache: ResponseCacheService, protected requestService: RequestService, protected rdbService: RemoteDataBuildService, protected store: Store, @@ -33,7 +31,7 @@ class TestService extends DataService { super(); } - public getBrowseEndpoint(options: FindAllOptions): Observable { + public getBrowseEndpoint(options: FindAllOptions = {}, linkPath: string = this.linkPath): Observable { return observableOf(endpoint); } } @@ -41,7 +39,6 @@ class TestService extends DataService { describe('DataService', () => { let service: TestService; let options: FindAllOptions; - const responseCache = {} as ResponseCacheService; const requestService = {} as RequestService; const halService = {} as HALEndpointService; const rdbService = {} as RemoteDataBuildService; @@ -57,7 +54,6 @@ describe('DataService', () => { function initTestService(): TestService { return new TestService( - responseCache, requestService, rdbService, store, diff --git a/src/app/core/data/data.service.ts b/src/app/core/data/data.service.ts index d23d7e8064..4a993e4ac6 100644 --- a/src/app/core/data/data.service.ts +++ b/src/app/core/data/data.service.ts @@ -1,9 +1,8 @@ -import { distinctUntilChanged, filter, first, map, take } from 'rxjs/operators'; +import { delay, distinctUntilChanged, filter, first, map, take, tap } from 'rxjs/operators'; import { Observable } from 'rxjs'; import { Store } from '@ngrx/store'; import { hasValue, isNotEmpty } from '../../shared/empty.util'; import { RemoteDataBuildService } from '../cache/builders/remote-data-build.service'; -import { ResponseCacheService } from '../cache/response-cache.service'; import { CoreState } from '../core.reducers'; import { HALEndpointService } from '../shared/hal-endpoint.service'; import { URLCombiner } from '../url-combiner/url-combiner'; @@ -15,9 +14,9 @@ import { NormalizedObject } from '../cache/models/normalized-object.model'; import { compare, Operation } from 'fast-json-patch'; import { ObjectCacheService } from '../cache/object-cache.service'; import { DSpaceObject } from '../shared/dspace-object.model'; +import { of } from 'rxjs/internal/observable/of'; export abstract class DataService { - protected abstract responseCache: ResponseCacheService; protected abstract requestService: RequestService; protected abstract rdbService: RemoteDataBuildService; protected abstract store: Store; @@ -25,34 +24,31 @@ export abstract class DataService protected abstract halService: HALEndpointService; protected abstract objectCache: ObjectCacheService; - public abstract getBrowseEndpoint(options: FindAllOptions): Observable + public abstract getBrowseEndpoint(options: FindAllOptions, linkPath?: string): Observable - protected getFindAllHref(options: FindAllOptions = {}): Observable { + protected getFindAllHref(options: FindAllOptions = {}, linkPath?: string): Observable { let result: Observable; const args = []; - result = this.getBrowseEndpoint(options).pipe(distinctUntilChanged()); - + result = this.getBrowseEndpoint(options, linkPath); if (hasValue(options.currentPage) && typeof options.currentPage === 'number') { /* TODO: this is a temporary fix for the pagination start index (0 or 1) discrepancy between the rest and the frontend respectively */ args.push(`page=${options.currentPage - 1}`); } - if (hasValue(options.elementsPerPage)) { args.push(`size=${options.elementsPerPage}`); } - if (hasValue(options.sort)) { args.push(`sort=${options.sort.field},${options.sort.direction}`); } - if (hasValue(options.startsWith)) { args.push(`startsWith=${options.startsWith}`); } - if (isNotEmpty(args)) { return result.pipe(map((href: string) => new URLCombiner(href, `?${args.join('&')}`).toString())); } else { + result.subscribe((t) => console.log(t)); + return result; } } @@ -115,6 +111,7 @@ export abstract class DataService this.objectCache.addPatch(object.self, operations); } } + // TODO implement, after the structure of the REST server's POST response is finalized // create(dso: DSpaceObject): Observable> { // const postHrefObs = this.getEndpoint(); diff --git a/src/app/core/data/debug-response-parsing.service.ts b/src/app/core/data/debug-response-parsing.service.ts index d530948559..174abec897 100644 --- a/src/app/core/data/debug-response-parsing.service.ts +++ b/src/app/core/data/debug-response-parsing.service.ts @@ -1,5 +1,5 @@ import { Injectable } from '@angular/core'; -import { RestResponse } from '../cache/response-cache.models'; +import { RestResponse } from '../cache/response.models'; import { DSpaceRESTV2Response } from '../dspace-rest-v2/dspace-rest-v2-response.model'; import { ResponseParsingService } from './parsing.service'; import { RestRequest } from './request.models'; diff --git a/src/app/core/data/dso-response-parsing.service.ts b/src/app/core/data/dso-response-parsing.service.ts index aff450781f..568114be1a 100644 --- a/src/app/core/data/dso-response-parsing.service.ts +++ b/src/app/core/data/dso-response-parsing.service.ts @@ -7,7 +7,7 @@ import { NormalizedObject } from '../cache/models/normalized-object.model'; import { ResourceType } from '../shared/resource-type'; import { NormalizedObjectFactory } from '../cache/models/normalized-object-factory'; import { DSpaceRESTV2Response } from '../dspace-rest-v2/dspace-rest-v2-response.model'; -import { RestResponse, DSOSuccessResponse } from '../cache/response-cache.models'; +import { RestResponse, DSOSuccessResponse } from '../cache/response.models'; import { RestRequest } from './request.models'; import { ResponseParsingService } from './parsing.service'; @@ -23,12 +23,14 @@ export class DSOResponseParsingService extends BaseResponseParsingService implem constructor( @Inject(GLOBAL_CONFIG) protected EnvConfig: GlobalConfig, protected objectCache: ObjectCacheService, - ) { super(); + ) { + super(); } parse(request: RestRequest, data: DSpaceRESTV2Response): RestResponse { - const processRequestDTO = this.process(data.payload, request.href); + const processRequestDTO = this.process(data.payload, request.href); let objectList = processRequestDTO; + if (hasNoValue(processRequestDTO)) { return new DSOSuccessResponse([], data.statusCode, undefined) } diff --git a/src/app/core/data/dspace-object-data.service.ts b/src/app/core/data/dspace-object-data.service.ts index 03c602d2aa..324692c676 100644 --- a/src/app/core/data/dspace-object-data.service.ts +++ b/src/app/core/data/dspace-object-data.service.ts @@ -3,7 +3,6 @@ import { Store } from '@ngrx/store'; import { Observable } from 'rxjs'; import { RemoteDataBuildService } from '../cache/builders/remote-data-build.service'; import { NormalizedDSpaceObject } from '../cache/models/normalized-dspace-object.model'; -import { ResponseCacheService } from '../cache/response-cache.service'; import { CoreState } from '../core.reducers'; import { DSpaceObject } from '../shared/dspace-object.model'; import { HALEndpointService } from '../shared/hal-endpoint.service'; @@ -18,7 +17,6 @@ class DataServiceImpl extends DataService protected linkPath = 'dso'; constructor( - protected responseCache: ResponseCacheService, protected requestService: RequestService, protected rdbService: RemoteDataBuildService, protected store: Store, @@ -27,8 +25,8 @@ class DataServiceImpl extends DataService super(); } - getBrowseEndpoint(options: FindAllOptions): Observable { - return this.halService.getEndpoint(this.linkPath); + getBrowseEndpoint(options: FindAllOptions = {}, linkPath: string = this.linkPath): Observable { + return this.halService.getEndpoint(linkPath); } getFindByIDHref(endpoint, resourceID): string { @@ -46,7 +44,7 @@ export class DSpaceObjectDataService { protected rdbService: RemoteDataBuildService, protected halService: HALEndpointService, protected objectCache: ObjectCacheService) { - this.dataService = new DataServiceImpl(null, requestService, rdbService, null, halService, objectCache); + this.dataService = new DataServiceImpl(requestService, rdbService, null, halService, objectCache); } findById(uuid: string): Observable> { diff --git a/src/app/core/data/endpoint-map-response-parsing.service.ts b/src/app/core/data/endpoint-map-response-parsing.service.ts index b850e13932..a145477953 100644 --- a/src/app/core/data/endpoint-map-response-parsing.service.ts +++ b/src/app/core/data/endpoint-map-response-parsing.service.ts @@ -1,7 +1,7 @@ import { Inject, Injectable } from '@angular/core'; import { GLOBAL_CONFIG } from '../../../config'; import { GlobalConfig } from '../../../config/global-config.interface'; -import { ErrorResponse, RestResponse, EndpointMapSuccessResponse } from '../cache/response-cache.models'; +import { ErrorResponse, RestResponse, EndpointMapSuccessResponse } from '../cache/response.models'; import { DSpaceRESTV2Response } from '../dspace-rest-v2/dspace-rest-v2-response.model'; import { ResponseParsingService } from './parsing.service'; import { RestRequest } from './request.models'; diff --git a/src/app/core/data/facet-config-response-parsing.service.ts b/src/app/core/data/facet-config-response-parsing.service.ts index b0d89fb03e..02b12dfa10 100644 --- a/src/app/core/data/facet-config-response-parsing.service.ts +++ b/src/app/core/data/facet-config-response-parsing.service.ts @@ -2,7 +2,7 @@ import { Inject, Injectable } from '@angular/core'; import { FacetConfigSuccessResponse, RestResponse -} from '../cache/response-cache.models'; +} from '../cache/response.models'; import { ResponseParsingService } from './parsing.service'; import { RestRequest } from './request.models'; import { DSpaceRESTV2Response } from '../dspace-rest-v2/dspace-rest-v2-response.model'; diff --git a/src/app/core/data/facet-value-map-response-parsing.service.ts b/src/app/core/data/facet-value-map-response-parsing.service.ts index 8588e4aa0b..0fc5917847 100644 --- a/src/app/core/data/facet-value-map-response-parsing.service.ts +++ b/src/app/core/data/facet-value-map-response-parsing.service.ts @@ -4,7 +4,7 @@ import { FacetValueMapSuccessResponse, FacetValueSuccessResponse, RestResponse -} from '../cache/response-cache.models'; +} from '../cache/response.models'; import { ResponseParsingService } from './parsing.service'; import { RestRequest } from './request.models'; import { DSpaceRESTV2Response } from '../dspace-rest-v2/dspace-rest-v2-response.model'; diff --git a/src/app/core/data/facet-value-response-parsing.service.ts b/src/app/core/data/facet-value-response-parsing.service.ts index bc3f4e5368..585172c22e 100644 --- a/src/app/core/data/facet-value-response-parsing.service.ts +++ b/src/app/core/data/facet-value-response-parsing.service.ts @@ -4,7 +4,7 @@ import { FacetValueMapSuccessResponse, FacetValueSuccessResponse, RestResponse -} from '../cache/response-cache.models'; +} from '../cache/response.models'; import { ResponseParsingService } from './parsing.service'; import { RestRequest } from './request.models'; import { DSpaceRESTV2Response } from '../dspace-rest-v2/dspace-rest-v2-response.model'; diff --git a/src/app/core/data/item-data.service.spec.ts b/src/app/core/data/item-data.service.spec.ts index 050c888de2..bb67fc8412 100644 --- a/src/app/core/data/item-data.service.spec.ts +++ b/src/app/core/data/item-data.service.spec.ts @@ -3,7 +3,6 @@ import { cold, getTestScheduler } from 'jasmine-marbles'; import { TestScheduler } from 'rxjs/testing'; import { BrowseService } from '../browse/browse.service'; import { RemoteDataBuildService } from '../cache/builders/remote-data-build.service'; -import { ResponseCacheService } from '../cache/response-cache.service'; import { CoreState } from '../core.reducers'; import { ItemDataService } from './item-data.service'; import { RequestService } from './request.service'; @@ -16,7 +15,6 @@ describe('ItemDataService', () => { let service: ItemDataService; let bs: BrowseService; const requestService = {} as RequestService; - const responseCache = {} as ResponseCacheService; const rdbService = {} as RemoteDataBuildService; const objectCache = {} as ObjectCacheService; const store = {} as Store; @@ -48,7 +46,6 @@ describe('ItemDataService', () => { function initTestService() { return new ItemDataService( - responseCache, requestService, rdbService, store, diff --git a/src/app/core/data/item-data.service.ts b/src/app/core/data/item-data.service.ts index 22ca23a4e2..9c2c87119f 100644 --- a/src/app/core/data/item-data.service.ts +++ b/src/app/core/data/item-data.service.ts @@ -7,7 +7,6 @@ import { isNotEmpty } from '../../shared/empty.util'; import { BrowseService } from '../browse/browse.service'; import { RemoteDataBuildService } from '../cache/builders/remote-data-build.service'; import { NormalizedItem } from '../cache/models/normalized-item.model'; -import { ResponseCacheService } from '../cache/response-cache.service'; import { CoreState } from '../core.reducers'; import { Item } from '../shared/item.model'; import { URLCombiner } from '../url-combiner/url-combiner'; @@ -23,7 +22,6 @@ export class ItemDataService extends DataService { protected linkPath = 'items'; constructor( - protected responseCache: ResponseCacheService, protected requestService: RequestService, protected rdbService: RemoteDataBuildService, protected store: Store, @@ -39,12 +37,12 @@ export class ItemDataService extends DataService { * @param {FindAllOptions} options * @returns {Observable} */ - public getBrowseEndpoint(options: FindAllOptions = {}): Observable { + public getBrowseEndpoint(options: FindAllOptions = {}, linkPath: string = this.linkPath): Observable { let field = 'dc.date.issued'; if (options.sort && options.sort.field) { field = options.sort.field; } - return this.bs.getBrowseURLFor(field, this.linkPath).pipe( + return this.bs.getBrowseURLFor(field, linkPath).pipe( filter((href: string) => isNotEmpty(href)), map((href: string) => new URLCombiner(href, `?scope=${options.scopeID}`).toString()), distinctUntilChanged(),); diff --git a/src/app/core/data/metadataschema-parsing.service.ts b/src/app/core/data/metadataschema-parsing.service.ts index cdd87c19d4..78a5257456 100644 --- a/src/app/core/data/metadataschema-parsing.service.ts +++ b/src/app/core/data/metadataschema-parsing.service.ts @@ -4,7 +4,7 @@ import { DSpaceRESTV2Response } from '../dspace-rest-v2/dspace-rest-v2-response. import { RestRequest } from './request.models'; import { ResponseParsingService } from './parsing.service'; import { Injectable } from '@angular/core'; -import { MetadataschemaSuccessResponse, RestResponse } from '../cache/response-cache.models'; +import { MetadataschemaSuccessResponse, RestResponse } from '../cache/response.models'; @Injectable() export class MetadataschemaParsingService implements ResponseParsingService { diff --git a/src/app/core/data/parsing.service.ts b/src/app/core/data/parsing.service.ts index a137b99079..ea8d1ea810 100644 --- a/src/app/core/data/parsing.service.ts +++ b/src/app/core/data/parsing.service.ts @@ -1,6 +1,6 @@ import { DSpaceRESTV2Response } from '../dspace-rest-v2/dspace-rest-v2-response.model'; import { RestRequest } from './request.models'; -import { RestResponse } from '../cache/response-cache.models'; +import { RestResponse } from '../cache/response.models'; export interface ResponseParsingService { parse(request: RestRequest, data: DSpaceRESTV2Response): RestResponse; diff --git a/src/app/core/data/registry-bitstreamformats-response-parsing.service.ts b/src/app/core/data/registry-bitstreamformats-response-parsing.service.ts index d981a12719..2ee3bbf75e 100644 --- a/src/app/core/data/registry-bitstreamformats-response-parsing.service.ts +++ b/src/app/core/data/registry-bitstreamformats-response-parsing.service.ts @@ -1,4 +1,4 @@ -import { RegistryBitstreamformatsSuccessResponse, RestResponse } from '../cache/response-cache.models'; +import { RegistryBitstreamformatsSuccessResponse, RestResponse } from '../cache/response.models'; import { RegistryBitstreamformatsResponse } from '../registry/registry-bitstreamformats-response.model'; import { DSpaceRESTv2Serializer } from '../dspace-rest-v2/dspace-rest-v2.serializer'; import { DSpaceRESTV2Response } from '../dspace-rest-v2/dspace-rest-v2-response.model'; diff --git a/src/app/core/data/registry-metadatafields-response-parsing.service.ts b/src/app/core/data/registry-metadatafields-response-parsing.service.ts index 1fe8b1e15f..0b0982d048 100644 --- a/src/app/core/data/registry-metadatafields-response-parsing.service.ts +++ b/src/app/core/data/registry-metadatafields-response-parsing.service.ts @@ -1,7 +1,7 @@ import { RegistryMetadatafieldsSuccessResponse, RestResponse -} from '../cache/response-cache.models'; +} from '../cache/response.models'; import { DSpaceRESTV2Response } from '../dspace-rest-v2/dspace-rest-v2-response.model'; import { RestRequest } from './request.models'; import { ResponseParsingService } from './parsing.service'; diff --git a/src/app/core/data/registry-metadataschemas-response-parsing.service.ts b/src/app/core/data/registry-metadataschemas-response-parsing.service.ts index 2bb1302450..a70c985b15 100644 --- a/src/app/core/data/registry-metadataschemas-response-parsing.service.ts +++ b/src/app/core/data/registry-metadataschemas-response-parsing.service.ts @@ -1,4 +1,4 @@ -import { RegistryMetadataschemasSuccessResponse, RestResponse } from '../cache/response-cache.models'; +import { RegistryMetadataschemasSuccessResponse, RestResponse } from '../cache/response.models'; import { DSpaceRESTV2Response } from '../dspace-rest-v2/dspace-rest-v2-response.model'; import { RestRequest } from './request.models'; import { ResponseParsingService } from './parsing.service'; diff --git a/src/app/core/data/request.actions.ts b/src/app/core/data/request.actions.ts index 436c365caa..28149c2ead 100644 --- a/src/app/core/data/request.actions.ts +++ b/src/app/core/data/request.actions.ts @@ -1,6 +1,7 @@ import { Action } from '@ngrx/store'; import { type } from '../../shared/ngrx/type'; import { RestRequest } from './request.models'; +import { RestResponse } from '../cache/response.models'; /** * The list of RequestAction type definitions @@ -8,7 +9,8 @@ import { RestRequest } from './request.models'; export const RequestActionTypes = { CONFIGURE: type('dspace/core/data/request/CONFIGURE'), EXECUTE: type('dspace/core/data/request/EXECUTE'), - COMPLETE: type('dspace/core/data/request/COMPLETE') + COMPLETE: type('dspace/core/data/request/COMPLETE'), + RESET_TIMESTAMPS: type('dspace/core/data/request/RESET_TIMESTAMPS') }; /* tslint:disable:max-classes-per-file */ @@ -43,7 +45,10 @@ export class RequestExecuteAction implements Action { */ export class RequestCompleteAction implements Action { type = RequestActionTypes.COMPLETE; - payload: string; + payload: { + uuid: string, + response: RestResponse + }; /** * Create a new RequestCompleteAction @@ -51,10 +56,32 @@ export class RequestCompleteAction implements Action { * @param uuid * the request's uuid */ - constructor(uuid: string) { - this.payload = uuid; + constructor(uuid: string, response: RestResponse) { + this.payload = { + uuid, + response + }; } } + +/** + * An ngrx action to reset the timeAdded property of all responses in the cached objects + */ +export class ResetResponseTimestampsAction implements Action { + type = RequestActionTypes.RESET_TIMESTAMPS; + payload: number; + + /** + * Create a new ResetResponseTimestampsAction + * + * @param newTimestamp + * the new timeAdded all objects should get + */ + constructor(newTimestamp: number) { + this.payload = newTimestamp; + } +} + /* tslint:enable:max-classes-per-file */ /** @@ -63,4 +90,5 @@ export class RequestCompleteAction implements Action { export type RequestAction = RequestConfigureAction | RequestExecuteAction - | RequestCompleteAction; + | RequestCompleteAction + | ResetResponseTimestampsAction; diff --git a/src/app/core/data/request.effects.ts b/src/app/core/data/request.effects.ts index 6d42f792d1..bda91283bf 100644 --- a/src/app/core/data/request.effects.ts +++ b/src/app/core/data/request.effects.ts @@ -1,30 +1,33 @@ - -import {of as observableOf, Observable } from 'rxjs'; +import { Observable, of as observableOf } from 'rxjs'; import { Inject, Injectable, Injector } from '@angular/core'; -import { Request } from '@angular/http'; -import { RequestArgs } from '@angular/http/src/interfaces'; import { Actions, Effect, ofType } from '@ngrx/effects'; import { GLOBAL_CONFIG, GlobalConfig } from '../../../config'; import { isNotEmpty } from '../../shared/empty.util'; -import { ErrorResponse, RestResponse } from '../cache/response-cache.models'; -import { ResponseCacheService } from '../cache/response-cache.service'; import { DSpaceRESTV2Response } from '../dspace-rest-v2/dspace-rest-v2-response.model'; import { DSpaceRESTv2Service } from '../dspace-rest-v2/dspace-rest-v2.service'; -import { RequestActionTypes, RequestCompleteAction, RequestExecuteAction } from './request.actions'; +import { + RequestActionTypes, + RequestCompleteAction, + RequestExecuteAction, + ResetResponseTimestampsAction +} from './request.actions'; import { RequestError, RestRequest } from './request.models'; import { RequestEntry } from './request.reducer'; import { RequestService } from './request.service'; import { DSpaceRESTv2Serializer } from '../dspace-rest-v2/dspace-rest-v2.serializer'; import { NormalizedObjectFactory } from '../cache/models/normalized-object-factory'; import { catchError, flatMap, map, take, tap } from 'rxjs/operators'; +import { ErrorResponse, RestResponse } from '../cache/response.models'; +import { StoreActionTypes } from '../../store.actions'; -export const addToResponseCacheAndCompleteAction = (request: RestRequest, responseCache: ResponseCacheService, envConfig: GlobalConfig) => - (source: Observable): Observable => +export const addToResponseCacheAndCompleteAction = (request: RestRequest, envConfig: GlobalConfig) => + (source: Observable): Observable => source.pipe( - tap((response: RestResponse) => responseCache.add(request.href, response, request.responseMsToLive ? request.responseMsToLive : envConfig.cache.msToLive.default)), - map((response: RestResponse) => new RequestCompleteAction(request.uuid)) + map((response: RestResponse) => { + return new RequestCompleteAction(request.uuid, response) + }) ); @Injectable() @@ -46,20 +49,32 @@ export class RequestEffects { } return this.restApi.request(request.method, request.href, body, request.options).pipe( map((data: DSpaceRESTV2Response) => this.injector.get(request.getResponseParser()).parse(request, data)), - addToResponseCacheAndCompleteAction(request, this.responseCache, this.EnvConfig), + addToResponseCacheAndCompleteAction(request, this.EnvConfig), catchError((error: RequestError) => observableOf(new ErrorResponse(error)).pipe( - addToResponseCacheAndCompleteAction(request, this.responseCache, this.EnvConfig) + addToResponseCacheAndCompleteAction(request, this.EnvConfig) )) ); }) ); + /** + * When the store is rehydrated in the browser, set all cache + * timestamps to 'now', because the time zone of the server can + * differ from the client. + * + * This assumes that the server cached everything a negligible + * time ago, and will likely need to be revisited later + */ + @Effect() fixTimestampsOnRehydrate = this.actions$ + .pipe(ofType(StoreActionTypes.REHYDRATE), + map(() => new ResetResponseTimestampsAction(new Date().getTime())) + ); + constructor( @Inject(GLOBAL_CONFIG) private EnvConfig: GlobalConfig, private actions$: Actions, private restApi: DSpaceRESTv2Service, private injector: Injector, - private responseCache: ResponseCacheService, protected requestService: RequestService ) { } diff --git a/src/app/core/data/request.models.ts b/src/app/core/data/request.models.ts index cd6ac1dbe2..a96d9716b2 100644 --- a/src/app/core/data/request.models.ts +++ b/src/app/core/data/request.models.ts @@ -14,32 +14,36 @@ import { BrowseItemsResponseParsingService } from './browse-items-response-parsi /* tslint:disable:max-classes-per-file */ - export abstract class RestRequest { + public responseMsToLive = 0; constructor( public uuid: string, public href: string, public method: RestRequestMethod = RestRequestMethod.GET, public body?: any, public options?: HttpOptions, - public responseMsToLive?: number ) { } getResponseParser(): GenericConstructor { return DSOResponseParsingService; } + + get toCache(): boolean { + return this.responseMsToLive > 0; + } } export class GetRequest extends RestRequest { + public responseMsToLive = 60 * 15 * 1000; + constructor( public uuid: string, public href: string, public body?: any, public options?: HttpOptions, - public responseMsToLive?: number ) { - super(uuid, href, RestRequestMethod.GET, body, options, responseMsToLive) + super(uuid, href, RestRequestMethod.GET, body, options) } } @@ -212,6 +216,7 @@ export class IntegrationRequest extends GetRequest { return IntegrationResponseParsingService; } } + export class RequestError extends Error { statusText: string; } diff --git a/src/app/core/data/request.reducer.ts b/src/app/core/data/request.reducer.ts index 3ac35d2741..b0875f37b3 100644 --- a/src/app/core/data/request.reducer.ts +++ b/src/app/core/data/request.reducer.ts @@ -1,14 +1,16 @@ import { RequestActionTypes, RequestAction, RequestConfigureAction, - RequestExecuteAction, RequestCompleteAction + RequestExecuteAction, RequestCompleteAction, ResetResponseTimestampsAction } from './request.actions'; import { RestRequest } from './request.models'; +import { RestResponse } from '../cache/response.models'; export class RequestEntry { request: RestRequest; requestPending: boolean; responsePending: boolean; completed: boolean; + response: RestResponse } export interface RequestState { @@ -32,6 +34,9 @@ export function requestReducer(state = initialState, action: RequestAction): Req case RequestActionTypes.COMPLETE: { return completeRequest(state, action as RequestCompleteAction); } + case RequestActionTypes.RESET_TIMESTAMPS: { + return resetResponseTimestamps(state, action as ResetResponseTimestampsAction); + } default: { return state; @@ -45,7 +50,7 @@ function configureRequest(state: RequestState, action: RequestConfigureAction): request: action.payload, requestPending: true, responsePending: false, - completed: false + completed: false, } }); } @@ -70,10 +75,25 @@ function executeRequest(state: RequestState, action: RequestExecuteAction): Requ * the new state, with the response added to the request */ function completeRequest(state: RequestState, action: RequestCompleteAction): RequestState { - return Object.assign({}, state, { - [action.payload]: Object.assign({}, state[action.payload], { + const time = new Date().getTime(); + + const ob = Object.assign({}, state, { + [action.payload.uuid]: Object.assign({}, state[action.payload.uuid], { responsePending: false, - completed: true + completed: true, + response: Object.assign({}, action.payload.response, { timeAdded: time }) }) }); + console.log(ob); + return ob; +} + +function resetResponseTimestamps(state: RequestState, action: ResetResponseTimestampsAction) { + const newState = Object.create(null); + Object.keys(state).forEach((key) => { + newState[key] = Object.assign({}, state[key], + { response: Object.assign({}, state[key].response, { timeAdded: action.payload }) } + ); + }); + return newState; } diff --git a/src/app/core/data/request.service.spec.ts b/src/app/core/data/request.service.spec.ts index 39f29a9beb..5953d43c9f 100644 --- a/src/app/core/data/request.service.spec.ts +++ b/src/app/core/data/request.service.spec.ts @@ -1,10 +1,8 @@ import { cold, getTestScheduler, hot } from 'jasmine-marbles'; import { of as observableOf } from 'rxjs'; import { getMockObjectCacheService } from '../../shared/mocks/mock-object-cache.service'; -import { getMockResponseCacheService } from '../../shared/mocks/mock-response-cache.service'; import { defaultUUID, getMockUUIDService } from '../../shared/mocks/mock-uuid.service'; import { ObjectCacheService } from '../cache/object-cache.service'; -import { ResponseCacheService } from '../cache/response-cache.service'; import { CoreState } from '../core.reducers'; import { UUIDService } from '../shared/uuid.service'; import { RequestConfigureAction, RequestExecuteAction } from './request.actions'; @@ -29,7 +27,6 @@ describe('RequestService', () => { let service: RequestService; let serviceAsAny: any; let objectCache: ObjectCacheService; - let responseCache: ResponseCacheService; let uuidService: UUIDService; let store: Store; @@ -49,7 +46,6 @@ describe('RequestService', () => { objectCache = getMockObjectCacheService(); (objectCache.hasBySelfLink as any).and.returnValue(false); - responseCache = getMockResponseCacheService(); (responseCache.has as any).and.returnValue(false); (responseCache.get as any).and.returnValue(observableOf(undefined)); @@ -65,7 +61,6 @@ describe('RequestService', () => { service = new RequestService( objectCache, - responseCache, uuidService, store ); diff --git a/src/app/core/data/request.service.ts b/src/app/core/data/request.service.ts index 71d0189816..cc8c9816f8 100644 --- a/src/app/core/data/request.service.ts +++ b/src/app/core/data/request.service.ts @@ -1,14 +1,23 @@ -import { Observable, merge as observableMerge } from 'rxjs'; -import { filter, first, map, mergeMap, partition, take } from 'rxjs/operators'; +import { merge as observableMerge, Observable, of as observableOf } from 'rxjs'; +import { + filter, + find, + first, + map, + mergeMap, + reduce, + startWith, + switchMap, + take, + tap +} from 'rxjs/operators'; import { Injectable } from '@angular/core'; import { MemoizedSelector, select, Store } from '@ngrx/store'; -import { hasValue } from '../../shared/empty.util'; +import { hasNoValue, hasValue } from '../../shared/empty.util'; import { CacheableObject } from '../cache/object-cache.reducer'; import { ObjectCacheService } from '../cache/object-cache.service'; -import { DSOSuccessResponse, RestResponse } from '../cache/response-cache.models'; -import { ResponseCacheEntry } from '../cache/response-cache.reducer'; -import { ResponseCacheService } from '../cache/response-cache.service'; +import { DSOSuccessResponse, RestResponse } from '../cache/response.models'; import { coreSelector, CoreState } from '../core.reducers'; import { IndexName } from '../index/index.reducer'; import { pathSelector } from '../shared/selectors'; @@ -19,13 +28,13 @@ import { 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'; @Injectable() export class RequestService { private requestsOnTheirWayToTheStore: string[] = []; constructor(private objectCache: ObjectCacheService, - private responseCache: ResponseCacheService, private uuidService: UUIDService, private store: Store) { } @@ -83,23 +92,27 @@ export class RequestService { private isCachedOrPending(request: GetRequest) { let isCached = this.objectCache.hasBySelfLink(request.href); - if (!isCached && this.responseCache.has(request.href)) { - const responses = this.responseCache.get(request.href).pipe( - take(1), - map((entry: ResponseCacheEntry) => entry.response) - ); + const responses: Observable = this.isReusable(request.uuid).pipe( + filter((reusable: boolean) => !isCached && reusable), + switchMap(() => { + return this.getByHref(request.href).pipe( + getResponseFromEntry(), + take(1) + ); + } + )); - 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)); + 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); - observableMerge(errorResponses, otherSuccessResponses, dsoSuccessResponses).subscribe((c) => isCached = c); - } const isPending = this.isPending(request); return isCached || isPending; } @@ -129,4 +142,34 @@ export class RequestService { commit(method?: RestRequestMethod) { this.store.dispatch(new CommitSSBAction(method)) } + + /** + * Check whether a ResponseCacheEntry should still be cached + * + * @param entry + * the entry to check + * @return boolean + * false if the entry is null, undefined, or its time to + * live has been exceeded, true otherwise + */ + private isReusable(uuid: string): Observable { + if (hasNoValue(uuid)) { + return observableOf(false); + } 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 observableOf(false); + } + } } diff --git a/src/app/core/data/search-response-parsing.service.ts b/src/app/core/data/search-response-parsing.service.ts index 4039b8f761..7ee2b60f89 100644 --- a/src/app/core/data/search-response-parsing.service.ts +++ b/src/app/core/data/search-response-parsing.service.ts @@ -1,5 +1,5 @@ import { Injectable } from '@angular/core'; -import { RestResponse, SearchSuccessResponse } from '../cache/response-cache.models'; +import { RestResponse, SearchSuccessResponse } from '../cache/response.models'; import { DSOResponseParsingService } from './dso-response-parsing.service'; import { ResponseParsingService } from './parsing.service'; import { RestRequest } from './request.models'; diff --git a/src/app/core/integration/authority.service.ts b/src/app/core/integration/authority.service.ts index cb2595adc4..a5fa3a8d09 100644 --- a/src/app/core/integration/authority.service.ts +++ b/src/app/core/integration/authority.service.ts @@ -1,6 +1,5 @@ import { Injectable } from '@angular/core'; -import { ResponseCacheService } from '../cache/response-cache.service'; import { RequestService } from '../data/request.service'; import { IntegrationService } from './integration.service'; import { HALEndpointService } from '../shared/hal-endpoint.service'; @@ -11,7 +10,6 @@ export class AuthorityService extends IntegrationService { protected browseEndpoint = 'entries'; constructor( - protected responseCache: ResponseCacheService, protected requestService: RequestService, protected halService: HALEndpointService) { super(); diff --git a/src/app/core/integration/integration-response-parsing.service.spec.ts b/src/app/core/integration/integration-response-parsing.service.spec.ts index 9c3e5b0344..38741da4e2 100644 --- a/src/app/core/integration/integration-response-parsing.service.spec.ts +++ b/src/app/core/integration/integration-response-parsing.service.spec.ts @@ -1,4 +1,4 @@ -import { ErrorResponse, IntegrationSuccessResponse } from '../cache/response-cache.models'; +import { ErrorResponse, IntegrationSuccessResponse } from '../cache/response.models'; import { ObjectCacheService } from '../cache/object-cache.service'; import { GlobalConfig } from '../../../config/global-config.interface'; diff --git a/src/app/core/integration/integration-response-parsing.service.ts b/src/app/core/integration/integration-response-parsing.service.ts index 06c6b9620d..6eff7ab792 100644 --- a/src/app/core/integration/integration-response-parsing.service.ts +++ b/src/app/core/integration/integration-response-parsing.service.ts @@ -6,7 +6,7 @@ import { ErrorResponse, IntegrationSuccessResponse, RestResponse -} from '../cache/response-cache.models'; +} from '../cache/response.models'; import { isNotEmpty } from '../../shared/empty.util'; import { IntegrationObjectFactory } from './integration-object-factory'; diff --git a/src/app/core/integration/integration.service.spec.ts b/src/app/core/integration/integration.service.spec.ts index f7e3769620..158f4b0680 100644 --- a/src/app/core/integration/integration.service.spec.ts +++ b/src/app/core/integration/integration.service.spec.ts @@ -1,7 +1,6 @@ import { cold, getTestScheduler } from 'jasmine-marbles'; import { TestScheduler } from 'rxjs/testing'; import { getMockRequestService } from '../../shared/mocks/mock-request.service'; -import { ResponseCacheService } from '../cache/response-cache.service'; import { RequestService } from '../data/request.service'; import { IntegrationRequest } from '../data/request.models'; @@ -18,7 +17,6 @@ class TestService extends IntegrationService { protected browseEndpoint = BROWSE; constructor( - protected responseCache: ResponseCacheService, protected requestService: RequestService, protected halService: HALEndpointService) { super(); @@ -28,7 +26,6 @@ class TestService extends IntegrationService { describe('IntegrationService', () => { let scheduler: TestScheduler; let service: TestService; - let responseCache: ResponseCacheService; let requestService: RequestService; let halService: any; let findOptions: IntegrationSearchOptions; @@ -43,24 +40,14 @@ describe('IntegrationService', () => { findOptions = new IntegrationSearchOptions(uuid, name, metadata); - function initMockResponseCacheService(isSuccessful: boolean): ResponseCacheService { - return jasmine.createSpyObj('responseCache', { - get: cold('c-', { - c: {response: {isSuccessful}} - }) - }); - } - - function initTestService(): TestService { + function initTestService(): TestService { return new TestService( - responseCache, requestService, halService ); } beforeEach(() => { - responseCache = initMockResponseCacheService(true); requestService = getMockRequestService(); scheduler = getTestScheduler(); halService = new HALEndpointServiceStub(integrationEndpoint); diff --git a/src/app/core/integration/integration.service.ts b/src/app/core/integration/integration.service.ts index 3c71ca5f3b..2ace710dc7 100644 --- a/src/app/core/integration/integration.service.ts +++ b/src/app/core/integration/integration.service.ts @@ -1,27 +1,26 @@ import { Observable, of as observableOf, throwError as observableThrowError } from 'rxjs'; import { distinctUntilChanged, filter, map, mergeMap, tap } from 'rxjs/operators'; import { RequestService } from '../data/request.service'; -import { ResponseCacheService } from '../cache/response-cache.service'; -import { IntegrationSuccessResponse } from '../cache/response-cache.models'; +import { IntegrationSuccessResponse } from '../cache/response.models'; import { GetRequest, IntegrationRequest } from '../data/request.models'; -import { ResponseCacheEntry } from '../cache/response-cache.reducer'; import { hasValue, isNotEmpty } from '../../shared/empty.util'; import { HALEndpointService } from '../shared/hal-endpoint.service'; import { IntegrationData } from './integration-data'; import { IntegrationSearchOptions } from './models/integration-options.model'; +import { RequestEntry } from '../data/request.reducer'; +import { getResponseFromEntry } from '../shared/operators'; export abstract class IntegrationService { protected request: IntegrationRequest; - protected abstract responseCache: ResponseCacheService; protected abstract requestService: RequestService; protected abstract linkPath: string; protected abstract browseEndpoint: string; protected abstract halService: HALEndpointService; protected getData(request: GetRequest): Observable { - return this.responseCache.get(request.href).pipe( - map((entry: ResponseCacheEntry) => entry.response), - mergeMap((response) => { + return this.requestService.getByHref(request.href).pipe( + getResponseFromEntry(), + mergeMap((response) => { if (response.isSuccessful && isNotEmpty(response)) { const dataResponse = response as IntegrationSuccessResponse; return observableOf(new IntegrationData(dataResponse.pageInfo, dataResponse.dataDefinition)); diff --git a/src/app/core/metadata/metadata.service.spec.ts b/src/app/core/metadata/metadata.service.spec.ts index 50ce4711ff..f8d6435a03 100644 --- a/src/app/core/metadata/metadata.service.spec.ts +++ b/src/app/core/metadata/metadata.service.spec.ts @@ -23,7 +23,6 @@ import { ItemDataService } from '../data/item-data.service'; import { ObjectCacheService } from '../cache/object-cache.service'; import { RemoteDataBuildService } from '../cache/builders/remote-data-build.service'; import { RequestService } from '../data/request.service'; -import { ResponseCacheService } from '../cache/response-cache.service'; import { RemoteData } from '../../core/data/remote-data'; import { Item } from '../../core/shared/item.model'; @@ -62,7 +61,6 @@ describe('MetadataService', () => { let store: Store; let objectCacheService: ObjectCacheService; - let responseCacheService: ResponseCacheService; let requestService: RequestService; let uuidService: UUIDService; let remoteDataBuildService: RemoteDataBuildService; @@ -82,10 +80,9 @@ describe('MetadataService', () => { spyOn(store, 'dispatch'); objectCacheService = new ObjectCacheService(store); - responseCacheService = new ResponseCacheService(store); uuidService = new UUIDService(); - requestService = new RequestService(objectCacheService, responseCacheService, uuidService, store); - remoteDataBuildService = new RemoteDataBuildService(objectCacheService, responseCacheService, requestService); + requestService = new RequestService(objectCacheService, uuidService, store); + remoteDataBuildService = new RemoteDataBuildService(objectCacheService, requestService); TestBed.configureTestingModule({ imports: [ @@ -108,7 +105,6 @@ describe('MetadataService', () => { ], providers: [ { provide: ObjectCacheService, useValue: objectCacheService }, - { provide: ResponseCacheService, useValue: responseCacheService }, { provide: RequestService, useValue: requestService }, { provide: RemoteDataBuildService, useValue: remoteDataBuildService }, { provide: GLOBAL_CONFIG, useValue: ENV_CONFIG }, diff --git a/src/app/core/registry/registry.service.spec.ts b/src/app/core/registry/registry.service.spec.ts index d0ed1e5cb8..adb2ed8b05 100644 --- a/src/app/core/registry/registry.service.spec.ts +++ b/src/app/core/registry/registry.service.spec.ts @@ -1,24 +1,21 @@ import { TestBed } from '@angular/core/testing'; import { RegistryService } from './registry.service'; import { CommonModule } from '@angular/common'; -import { ResponseCacheService } from '../cache/response-cache.service'; import { RequestService } from '../data/request.service'; import { RemoteDataBuildService } from '../cache/builders/remote-data-build.service'; import { HALEndpointService } from '../shared/hal-endpoint.service'; import { PaginationComponentOptions } from '../../shared/pagination/pagination-component-options.model'; import { Observable, of as observableOf, combineLatest as observableCombineLatest } from 'rxjs'; -import { ResponseCacheEntry } from '../cache/response-cache.reducer'; import { RequestEntry } from '../data/request.reducer'; import { RemoteData } from '../data/remote-data'; import { PageInfo } from '../shared/page-info.model'; import { getMockRequestService } from '../../shared/mocks/mock-request.service'; -import { getMockResponseCacheService } from '../../shared/mocks/mock-response-cache.service'; import { RegistryBitstreamformatsSuccessResponse, RegistryMetadatafieldsSuccessResponse, RegistryMetadataschemasSuccessResponse -} from '../cache/response-cache.models'; +} from '../cache/response.models'; import { Component } from '@angular/core'; import { RegistryMetadataschemasResponse } from './registry-metadataschemas-response.model'; import { RegistryMetadatafieldsResponse } from './registry-metadatafields-response.model'; @@ -146,7 +143,6 @@ describe('RegistryService', () => { DummyComponent ], providers: [ - { provide: ResponseCacheService, useValue: getMockResponseCacheService() }, { provide: RequestService, useValue: getMockRequestService() }, { provide: RemoteDataBuildService, useValue: rdbStub }, { provide: HALEndpointService, useValue: halServiceStub }, diff --git a/src/app/core/registry/registry.service.ts b/src/app/core/registry/registry.service.ts index 7e7c18f69e..ef92d42ce9 100644 --- a/src/app/core/registry/registry.service.ts +++ b/src/app/core/registry/registry.service.ts @@ -6,29 +6,29 @@ import { PageInfo } from '../shared/page-info.model'; import { MetadataSchema } from '../metadata/metadataschema.model'; import { MetadataField } from '../metadata/metadatafield.model'; import { BitstreamFormat } from './mock-bitstream-format.model'; -import { flatMap, map, tap } from 'rxjs/operators'; +import { filter, flatMap, map, tap } from 'rxjs/operators'; import { GetRequest, RestRequest } from '../data/request.models'; import { GenericConstructor } from '../shared/generic-constructor'; import { ResponseParsingService } from '../data/parsing.service'; import { RegistryMetadataschemasResponseParsingService } from '../data/registry-metadataschemas-response-parsing.service'; import { RemoteDataBuildService } from '../cache/builders/remote-data-build.service'; import { RequestService } from '../data/request.service'; -import { ResponseCacheService } from '../cache/response-cache.service'; import { RegistryMetadataschemasResponse } from './registry-metadataschemas-response.model'; -import { ResponseCacheEntry } from '../cache/response-cache.reducer'; import { RegistryBitstreamformatsSuccessResponse, RegistryMetadatafieldsSuccessResponse, RegistryMetadataschemasSuccessResponse -} from '../cache/response-cache.models'; +} from '../cache/response.models'; import { HALEndpointService } from '../shared/hal-endpoint.service'; import { RegistryMetadatafieldsResponseParsingService } from '../data/registry-metadatafields-response-parsing.service'; import { RegistryMetadatafieldsResponse } from './registry-metadatafields-response.model'; -import { isNotEmpty } from '../../shared/empty.util'; +import { hasValue, isNotEmpty } from '../../shared/empty.util'; import { URLCombiner } from '../url-combiner/url-combiner'; import { PaginationComponentOptions } from '../../shared/pagination/pagination-component-options.model'; import { RegistryBitstreamformatsResponseParsingService } from '../data/registry-bitstreamformats-response-parsing.service'; import { RegistryBitstreamformatsResponse } from './registry-bitstreamformats-response.model'; +import { RequestEntry } from '../data/request.reducer'; +import { getResponseFromEntry } from '../shared/operators'; @Injectable() export class RegistryService { @@ -37,8 +37,7 @@ export class RegistryService { private metadataFieldsPath = 'metadatafields'; private bitstreamFormatsPath = 'bitstreamformats'; - constructor(protected responseCache: ResponseCacheService, - protected requestService: RequestService, + constructor(protected requestService: RequestService, private rdb: RemoteDataBuildService, private halService: HALEndpointService) { @@ -51,12 +50,8 @@ export class RegistryService { flatMap((request: RestRequest) => this.requestService.getByHref(request.href)) ); - const responseCacheObs = requestObs.pipe( - flatMap((request: RestRequest) => this.responseCache.get(request.href)) - ); - - const rmrObs: Observable = responseCacheObs.pipe( - map((entry: ResponseCacheEntry) => entry.response), + const rmrObs: Observable = requestEntryObs.pipe( + getResponseFromEntry(), map((response: RegistryMetadataschemasSuccessResponse) => response.metadataschemasResponse) ); @@ -64,8 +59,8 @@ export class RegistryService { map((rmr: RegistryMetadataschemasResponse) => rmr.metadataschemas) ); - const pageInfoObs: Observable = responseCacheObs.pipe( - map((entry: ResponseCacheEntry) => entry.response), + const pageInfoObs: Observable = requestEntryObs.pipe( + getResponseFromEntry(), map((response: RegistryMetadataschemasSuccessResponse) => response.pageInfo) ); @@ -75,7 +70,7 @@ export class RegistryService { }) ); - return this.rdb.toRemoteDataObservable(requestEntryObs, responseCacheObs, payloadObs); + return this.rdb.toRemoteDataObservable(requestEntryObs, payloadObs); } public getMetadataSchemaByName(schemaName: string): Observable> { @@ -90,12 +85,8 @@ export class RegistryService { flatMap((request: RestRequest) => this.requestService.getByHref(request.href)) ); - const responseCacheObs = requestObs.pipe( - flatMap((request: RestRequest) => this.responseCache.get(request.href)) - ); - - const rmrObs: Observable = responseCacheObs.pipe( - map((entry: ResponseCacheEntry) => entry.response), + const rmrObs: Observable = requestEntryObs.pipe( + getResponseFromEntry(), map((response: RegistryMetadataschemasSuccessResponse) => response.metadataschemasResponse) ); @@ -104,7 +95,7 @@ export class RegistryService { map((metadataSchemas: MetadataSchema[]) => metadataSchemas.filter((value) => value.prefix === schemaName)[0]) ); - return this.rdb.toRemoteDataObservable(requestEntryObs, responseCacheObs, metadataschemaObs); + return this.rdb.toRemoteDataObservable(requestEntryObs, metadataschemaObs); } public getMetadataFieldsBySchema(schema: MetadataSchema, pagination: PaginationComponentOptions): Observable>> { @@ -114,12 +105,8 @@ export class RegistryService { flatMap((request: RestRequest) => this.requestService.getByHref(request.href)) ); - const responseCacheObs = requestObs.pipe( - flatMap((request: RestRequest) => this.responseCache.get(request.href)) - ); - - const rmrObs: Observable = responseCacheObs.pipe( - map((entry: ResponseCacheEntry) => entry.response), + const rmrObs: Observable = requestEntryObs.pipe( + getResponseFromEntry(), map((response: RegistryMetadatafieldsSuccessResponse) => response.metadatafieldsResponse) ); @@ -128,8 +115,9 @@ export class RegistryService { map((metadataFields: MetadataField[]) => metadataFields.filter((field) => field.schema.id === schema.id)) ); - const pageInfoObs: Observable = responseCacheObs.pipe( - map((entry: ResponseCacheEntry) => entry.response), + const pageInfoObs: Observable = requestEntryObs.pipe( + getResponseFromEntry(), + map((response: RegistryMetadatafieldsSuccessResponse) => response.pageInfo) ); @@ -139,7 +127,7 @@ export class RegistryService { }) ); - return this.rdb.toRemoteDataObservable(requestEntryObs, responseCacheObs, payloadObs); + return this.rdb.toRemoteDataObservable(requestEntryObs, payloadObs); } public getBitstreamFormats(pagination: PaginationComponentOptions): Observable>> { @@ -149,12 +137,8 @@ export class RegistryService { flatMap((request: RestRequest) => this.requestService.getByHref(request.href)) ); - const responseCacheObs = requestObs.pipe( - flatMap((request: RestRequest) => this.responseCache.get(request.href)) - ); - - const rbrObs: Observable = responseCacheObs.pipe( - map((entry: ResponseCacheEntry) => entry.response), + const rbrObs: Observable = requestEntryObs.pipe( + getResponseFromEntry(), map((response: RegistryBitstreamformatsSuccessResponse) => response.bitstreamformatsResponse) ); @@ -162,8 +146,8 @@ export class RegistryService { map((rbr: RegistryBitstreamformatsResponse) => rbr.bitstreamformats) ); - const pageInfoObs: Observable = responseCacheObs.pipe( - map((entry: ResponseCacheEntry) => entry.response), + const pageInfoObs: Observable = requestEntryObs.pipe( + getResponseFromEntry(), map((response: RegistryBitstreamformatsSuccessResponse) => response.pageInfo) ); @@ -173,7 +157,7 @@ export class RegistryService { }) ); - return this.rdb.toRemoteDataObservable(requestEntryObs, responseCacheObs, payloadObs); + return this.rdb.toRemoteDataObservable(requestEntryObs, payloadObs); } private getMetadataSchemasRequestObs(pagination: PaginationComponentOptions): Observable { diff --git a/src/app/core/shared/hal-endpoint.service.spec.ts b/src/app/core/shared/hal-endpoint.service.spec.ts index 0c2afe938b..d36da207ca 100644 --- a/src/app/core/shared/hal-endpoint.service.spec.ts +++ b/src/app/core/shared/hal-endpoint.service.spec.ts @@ -1,14 +1,12 @@ import { cold, hot } from 'jasmine-marbles'; import { GlobalConfig } from '../../../config/global-config.interface'; import { getMockRequestService } from '../../shared/mocks/mock-request.service'; -import { ResponseCacheService } from '../cache/response-cache.service'; import { RequestService } from '../data/request.service'; import { HALEndpointService } from './hal-endpoint.service'; import { EndpointMapRequest } from '../data/request.models'; describe('HALEndpointService', () => { let service: HALEndpointService; - let responseCache: ResponseCacheService; let requestService: RequestService; let envConfig: GlobalConfig; @@ -19,14 +17,6 @@ describe('HALEndpointService', () => { describe('getRootEndpointMap', () => { beforeEach(() => { - responseCache = jasmine.createSpyObj('responseCache', { - get: hot('a-', { - a: { - response: { endpointMap: endpointMap } - } - }) - }); - requestService = getMockRequestService(); envConfig = { @@ -34,7 +24,6 @@ describe('HALEndpointService', () => { } as any; service = new HALEndpointService( - responseCache, requestService, envConfig ); @@ -60,12 +49,6 @@ describe('HALEndpointService', () => { envConfig = { rest: { baseUrl: 'https://rest.api/' } } as any; - - service = new HALEndpointService( - responseCache, - requestService, - envConfig - ); }); it('should return the endpoint URL for the service\'s linkPath', () => { @@ -89,7 +72,6 @@ describe('HALEndpointService', () => { describe('isEnabledOnRestApi', () => { beforeEach(() => { service = new HALEndpointService( - responseCache, requestService, envConfig ); diff --git a/src/app/core/shared/hal-endpoint.service.ts b/src/app/core/shared/hal-endpoint.service.ts index d72b9e9a9f..8ef65c4dd1 100644 --- a/src/app/core/shared/hal-endpoint.service.ts +++ b/src/app/core/shared/hal-endpoint.service.ts @@ -1,21 +1,27 @@ -import {of as observableOf, Observable } from 'rxjs'; -import {filter, distinctUntilChanged, map, flatMap, startWith, tap } from 'rxjs/operators'; +import { Observable, of as observableOf } from 'rxjs'; +import { + distinctUntilChanged, + filter, + flatMap, + map, + startWith, + switchMap, + tap +} from 'rxjs/operators'; import { RequestService } from '../data/request.service'; -import { ResponseCacheService } from '../cache/response-cache.service'; import { GlobalConfig } from '../../../config/global-config.interface'; -import { EndpointMap, EndpointMapSuccessResponse } from '../cache/response-cache.models'; import { EndpointMapRequest } from '../data/request.models'; -import { ResponseCacheEntry } from '../cache/response-cache.reducer'; -import { hasNoValue, hasValue, isEmpty, isNotEmpty } from '../../shared/empty.util'; +import { hasValue, isEmpty, isNotEmpty, isNotUndefined } from '../../shared/empty.util'; import { RESTURLCombiner } from '../url-combiner/rest-url-combiner'; import { Inject, Injectable } from '@angular/core'; import { GLOBAL_CONFIG } from '../../../config'; +import { EndpointMap, EndpointMapSuccessResponse } from '../cache/response.models'; +import { getResponseFromEntry } from './operators'; @Injectable() export class HALEndpointService { - constructor(private responseCache: ResponseCacheService, - private requestService: RequestService, + constructor(private requestService: RequestService, @Inject(GLOBAL_CONFIG) private EnvConfig: GlobalConfig) { } @@ -29,12 +35,22 @@ export class HALEndpointService { private getEndpointMapAt(href): Observable { const request = new EndpointMapRequest(this.requestService.generateRequestId(), href); - this.requestService.configure(request); - return this.responseCache.get(request.href).pipe( - map((entry: ResponseCacheEntry) => entry.response), - filter((response: EndpointMapSuccessResponse) => isNotEmpty(response)), + + this.requestService.getByUUID(request.uuid).pipe( + getResponseFromEntry(), map((response: EndpointMapSuccessResponse) => response.endpointMap), - distinctUntilChanged(),); + distinctUntilChanged()).subscribe((t) => console.log('uuid', t)); + this.requestService.getByHref(request.href).pipe( + getResponseFromEntry(), + map((response: EndpointMapSuccessResponse) => response.endpointMap), + distinctUntilChanged()).subscribe((t) => console.log('href', t)); + + this.requestService.configure(request); + return this.requestService.getByHref(request.href).pipe( /*<-- changing this to UUID breaks it */ + getResponseFromEntry(), + map((response: EndpointMapSuccessResponse) => response.endpointMap), + distinctUntilChanged()); + } public getEndpoint(linkPath: string): Observable { @@ -48,7 +64,7 @@ export class HALEndpointService { let currentPath; const pipeArguments = path .map((subPath: string, index: number) => [ - flatMap((href: string) => this.getEndpointMapAt(href)), + switchMap((href: string) => this.getEndpointMapAt(href)), map((endpointMap: EndpointMap) => { if (hasValue(endpointMap) && hasValue(endpointMap[subPath])) { currentPath = endpointMap[subPath]; diff --git a/src/app/core/shared/operators.spec.ts b/src/app/core/shared/operators.spec.ts index 16bf633705..0684308fe9 100644 --- a/src/app/core/shared/operators.spec.ts +++ b/src/app/core/shared/operators.spec.ts @@ -1,17 +1,15 @@ import { cold, getTestScheduler, hot } from 'jasmine-marbles'; import { TestScheduler } from 'rxjs/testing'; import { getMockRequestService } from '../../shared/mocks/mock-request.service'; -import { getMockResponseCacheService } from '../../shared/mocks/mock-response-cache.service'; -import { ResponseCacheEntry } from '../cache/response-cache.reducer'; -import { ResponseCacheService } from '../cache/response-cache.service'; -import { GetRequest, RestRequest } from '../data/request.models'; +import { GetRequest } from '../data/request.models'; import { RequestEntry } from '../data/request.reducer'; import { RequestService } from '../data/request.service'; import { configureRequest, - filterSuccessfulResponses, getRemoteDataPayload, - getRequestFromSelflink, getResourceLinksFromResponse, - getResponseFromSelflink + filterSuccessfulResponses, + getRemoteDataPayload, + getRequestFromSelflink, + getResourceLinksFromResponse, } from './operators'; describe('Core Module - RxJS Operators', () => { @@ -64,44 +62,6 @@ describe('Core Module - RxJS Operators', () => { }); }); - describe('getResponseFromSelflink', () => { - let responseCacheService: ResponseCacheService; - - beforeEach(() => { - scheduler = getTestScheduler(); - }); - - it('should return the ResponseCacheEntry corresponding to the self link in the source', () => { - responseCacheService = getMockResponseCacheService(); - - const source = hot('a', { a: testSelfLink }); - const result = source.pipe(getResponseFromSelflink(responseCacheService)); - const expected = cold('a', { a: new ResponseCacheEntry()}); - - expect(result).toBeObservable(expected) - }); - - it('should use the responseCacheService to fetch the response by the request\'s link', () => { - responseCacheService = getMockResponseCacheService(); - - const source = hot('a', { a: testSelfLink }); - scheduler.schedule(() => source.pipe(getResponseFromSelflink(responseCacheService)).subscribe()); - scheduler.flush(); - - expect(responseCacheService.get).toHaveBeenCalledWith(testSelfLink) - }); - - it('shouldn\'t return anything if there is no response matching the request\'s link', () => { - responseCacheService = getMockResponseCacheService(undefined, cold('a', { a: undefined })); - - const source = hot('a', { a: testSelfLink }); - const result = source.pipe(getResponseFromSelflink(responseCacheService)); - const expected = cold('-'); - - expect(result).toBeObservable(expected) - }); - }); - describe('filterSuccessfulResponses', () => { it('should only return responses for which isSuccessful === true', () => { const source = hot('abcde', testRCEs); diff --git a/src/app/core/shared/operators.ts b/src/app/core/shared/operators.ts index 476119399b..e9ab8794ff 100644 --- a/src/app/core/shared/operators.ts +++ b/src/app/core/shared/operators.ts @@ -1,9 +1,7 @@ import { Observable } from 'rxjs'; import { filter, first, flatMap, map, tap } from 'rxjs/operators'; -import { hasValueOperator, isNotEmpty } from '../../shared/empty.util'; -import { DSOSuccessResponse } from '../cache/response-cache.models'; -import { ResponseCacheEntry } from '../cache/response-cache.reducer'; -import { ResponseCacheService } from '../cache/response-cache.service'; +import { hasValue, hasValueOperator, isNotEmpty } from '../../shared/empty.util'; +import { DSOSuccessResponse, RestResponse } from '../cache/response.models'; import { RemoteData } from '../data/remote-data'; import { RestRequest } from '../data/request.models'; import { RequestEntry } from '../data/request.reducer'; @@ -24,22 +22,25 @@ export const getRequestFromSelflink = (requestService: RequestService) => hasValueOperator() ); -export const getResponseFromSelflink = (responseCache: ResponseCacheService) => - (source: Observable): Observable => +export const filterSuccessfulResponses = () => + (source: Observable): Observable => source.pipe( - flatMap((href: string) => responseCache.get(href)), - hasValueOperator() + getResponseFromEntry(), + filter((response: RestResponse) => response.isSuccessful === true), ); -export const filterSuccessfulResponses = () => - (source: Observable): Observable => - source.pipe(filter((entry: ResponseCacheEntry) => entry.response.isSuccessful === true)); +export const getResponseFromEntry = () => + (source: Observable): Observable => + source.pipe( + filter((entry: RequestEntry) => hasValue(entry) && hasValue(entry.response)), + map((entry: RequestEntry) => entry.response) + ); export const getResourceLinksFromResponse = () => - (source: Observable): Observable => + (source: Observable): Observable => source.pipe( filterSuccessfulResponses(), - map((entry: ResponseCacheEntry) => (entry.response as DSOSuccessResponse).resourceSelfLinks), + map((response: DSOSuccessResponse) => response.resourceSelfLinks), ); export const configureRequest = (requestService: RequestService) => @@ -60,7 +61,7 @@ export const toDSpaceObjectListRD = () => map((rd: RemoteData>>) => { const dsoPage: T[] = rd.payload.page.map((searchResult: SearchResult) => searchResult.dspaceObject); const payload = Object.assign(rd.payload, { page: dsoPage }) as PaginatedList; - return Object.assign(rd, {payload: payload}); + return Object.assign(rd, { payload: payload }); }) ); diff --git a/src/app/shared/mocks/mock-remote-data-build.service.ts b/src/app/shared/mocks/mock-remote-data-build.service.ts index ea263239ea..675e539d90 100644 --- a/src/app/shared/mocks/mock-remote-data-build.service.ts +++ b/src/app/shared/mocks/mock-remote-data-build.service.ts @@ -1,14 +1,13 @@ import {of as observableOf, Observable } from 'rxjs'; import { map, take } from 'rxjs/operators'; import { RemoteDataBuildService } from '../../core/cache/builders/remote-data-build.service'; -import { ResponseCacheEntry } from '../../core/cache/response-cache.reducer'; import { RemoteData } from '../../core/data/remote-data'; import { RequestEntry } from '../../core/data/request.reducer'; import { hasValue } from '../empty.util'; export function getMockRemoteDataBuildService(toRemoteDataObservable$?: Observable>): RemoteDataBuildService { return { - toRemoteDataObservable: (requestEntry$: Observable, responseCache$: Observable, payload$: Observable) => { + toRemoteDataObservable: (requestEntry$: Observable, payload$: Observable) => { if (hasValue(toRemoteDataObservable$)) { return toRemoteDataObservable$; diff --git a/src/app/shared/mocks/mock-response-cache.service.ts b/src/app/shared/mocks/mock-response-cache.service.ts index a5a999873d..e69de29bb2 100644 --- a/src/app/shared/mocks/mock-response-cache.service.ts +++ b/src/app/shared/mocks/mock-response-cache.service.ts @@ -1,16 +0,0 @@ -import {of as observableOf, Observable } from 'rxjs'; -import { ResponseCacheEntry } from '../../core/cache/response-cache.reducer'; -import { ResponseCacheService } from '../../core/cache/response-cache.service'; - -export function getMockResponseCacheService( - add$: Observable = observableOf(new ResponseCacheEntry()), - get$: Observable = observableOf(new ResponseCacheEntry()), - has: boolean = false -): ResponseCacheService { - return jasmine.createSpyObj('ResponseCacheService', { - add: add$, - get: get$, - has, - }); - -} diff --git a/src/server.ts b/src/server.ts index 0e68e4f139..13d0b2fd89 100644 --- a/src/server.ts +++ b/src/server.ts @@ -53,6 +53,7 @@ export function startServer(bootstrap: Type<{}> | NgModuleFactory<{}>) { function ngApp(req, res) { function onHandleError(parentZoneDelegate, currentZone, targetZone, error) { + console.error('Error:', error); console.warn('Error in SSR, serving for direct CSR'); res.sendFile('index.csr.html', { root: './src' }); } From ec5f977dd2de4139a0916c62ab1b4d290e0db379 Mon Sep 17 00:00:00 2001 From: lotte Date: Thu, 18 Oct 2018 15:59:41 +0200 Subject: [PATCH 46/48] finished up response cache refactoring --- .../collection-page.component.ts | 4 +- .../search-service/search.service.spec.ts | 13 +--- .../search-service/search.service.ts | 16 ++--- .../auth-response-parsing.service.spec.ts | 3 +- src/app/core/browse/browse.service.spec.ts | 16 +++-- src/app/core/browse/browse.service.ts | 5 +- .../builders/remote-data-build.service.ts | 23 +++---- src/app/core/data/comcol-data.service.spec.ts | 18 +++-- src/app/core/data/request.reducer.spec.ts | 38 +++++++++-- src/app/core/data/request.reducer.ts | 8 +-- src/app/core/data/request.service.spec.ts | 20 +++--- src/app/core/data/request.service.ts | 5 +- .../core/registry/registry.service.spec.ts | 38 ++++------- .../core/shared/hal-endpoint.service.spec.ts | 41 +++++++----- src/app/core/shared/hal-endpoint.service.ts | 65 +++++++++---------- src/app/core/shared/operators.spec.ts | 10 ++- src/app/core/shared/operators.ts | 1 + 17 files changed, 174 insertions(+), 150 deletions(-) diff --git a/src/app/+collection-page/collection-page.component.ts b/src/app/+collection-page/collection-page.component.ts index 047613d6d1..b76c0a7520 100644 --- a/src/app/+collection-page/collection-page.component.ts +++ b/src/app/+collection-page/collection-page.component.ts @@ -1,6 +1,6 @@ import { ChangeDetectionStrategy, Component, OnDestroy, OnInit } from '@angular/core'; import { ActivatedRoute } from '@angular/router'; -import { Observable, Subscription } from 'rxjs'; +import { Observable, Subscription } from 'rxjs'; import { SortDirection, SortOptions } from '../core/cache/models/sort-options.model'; import { CollectionDataService } from '../core/data/collection-data.service'; import { PaginatedList } from '../core/data/paginated-list'; @@ -15,7 +15,7 @@ import { Item } from '../core/shared/item.model'; import { fadeIn, fadeInOut } from '../shared/animations/fade'; import { hasValue, isNotEmpty } from '../shared/empty.util'; import { PaginationComponentOptions } from '../shared/pagination/pagination-component-options.model'; -import { filter, first, flatMap, map } from 'rxjs/operators'; +import { filter, flatMap, map, tap } from 'rxjs/operators'; import { SearchService } from '../+search-page/search-service/search.service'; import { PaginatedSearchOptions } from '../+search-page/paginated-search-options.model'; import { toDSpaceObjectListRD } from '../core/shared/operators'; diff --git a/src/app/+search-page/search-service/search.service.spec.ts b/src/app/+search-page/search-service/search.service.spec.ts index 028a3fa446..4af0ffcb2e 100644 --- a/src/app/+search-page/search-service/search.service.spec.ts +++ b/src/app/+search-page/search-service/search.service.spec.ts @@ -84,8 +84,8 @@ describe('SearchService', () => { const remoteDataBuildService = { toRemoteDataObservable: (requestEntryObs: Observable, payloadObs: Observable) => { return observableCombineLatest(requestEntryObs, payloadObs).pipe( - map(([req, res, pay]) => { - return { req, res, pay }; + map(([req, pay]) => { + return { req, pay }; }) ); }, @@ -175,9 +175,6 @@ describe('SearchService', () => { it('should call getByHref on the request service with the correct request url', () => { expect((searchService as any).requestService.getByHref).toHaveBeenCalledWith(endPoint); }); - it('should call get on the request service with the correct request url', () => { - expect((searchService as any).responseCache.get).toHaveBeenCalledWith(endPoint); - }); }); describe('when getConfig is called without a scope', () => { @@ -203,9 +200,6 @@ describe('SearchService', () => { it('should call getByHref on the request service with the correct request url', () => { expect((searchService as any).requestService.getByHref).toHaveBeenCalledWith(endPoint); }); - it('should call get on the request service with the correct request url', () => { - expect((searchService as any).responseCache.get).toHaveBeenCalledWith(endPoint); - }); }); describe('when getConfig is called with a scope', () => { @@ -233,9 +227,6 @@ describe('SearchService', () => { it('should call getByHref on the request service with the correct request url', () => { expect((searchService as any).requestService.getByHref).toHaveBeenCalledWith(requestUrl); }); - it('should call get on the request service with the correct request url', () => { - expect((searchService as any).responseCache.get).toHaveBeenCalledWith(requestUrl); - }); }); }); }); diff --git a/src/app/+search-page/search-service/search.service.ts b/src/app/+search-page/search-service/search.service.ts index c628fd350e..275b0b3340 100644 --- a/src/app/+search-page/search-service/search.service.ts +++ b/src/app/+search-page/search-service/search.service.ts @@ -7,7 +7,7 @@ import { Router, UrlSegmentGroup } from '@angular/router'; -import { filter, flatMap, map, switchMap } from 'rxjs/operators'; +import { map, switchMap, tap } from 'rxjs/operators'; import { RemoteDataBuildService } from '../../core/cache/builders/remote-data-build.service'; import { FacetConfigSuccessResponse, @@ -47,7 +47,6 @@ import { CommunityDataService } from '../../core/data/community-data.service'; import { ViewMode } from '../../core/shared/view-mode.model'; import { ResourceType } from '../../core/shared/resource-type'; import { DSpaceObjectDataService } from '../../core/data/dspace-object-data.service'; -import { RequestEntry } from '../../core/data/request.reducer'; /** * Service that performs all general actions that have to do with the search page @@ -100,7 +99,7 @@ export class SearchService implements OnDestroy { configureRequest(this.requestService) ); const requestEntryObs = requestObs.pipe( - flatMap((request: RestRequest) => this.requestService.getByHref(request.href)) + switchMap((request: RestRequest) => this.requestService.getByHref(request.href)) ); // get search results from response cache @@ -113,10 +112,11 @@ export class SearchService implements OnDestroy { // Turn list of observable remote data DSO's into observable remote data object with list of DSO const dsoObs: Observable> = sqrObs.pipe( map((sqr: SearchQueryResponse) => { - return sqr.objects.map((nsr: NormalizedSearchResult) => - this.rdb.buildSingle(nsr.dspaceObject)); + return sqr.objects.map((nsr: NormalizedSearchResult) => { + return this.rdb.buildSingle(nsr.dspaceObject); + }) }), - flatMap((input: Array>>) => this.rdb.aggregate(input)) + switchMap((input: Array>>) => this.rdb.aggregate(input)), ); // Create search results again with the correct dso objects linked to each result @@ -180,7 +180,7 @@ export class SearchService implements OnDestroy { ); const requestEntryObs = requestObs.pipe( - flatMap((request: RestRequest) => this.requestService.getByHref(request.href)) + switchMap((request: RestRequest) => this.requestService.getByHref(request.href)) ); // get search results from response cache @@ -223,7 +223,7 @@ export class SearchService implements OnDestroy { ); const requestEntryObs = requestObs.pipe( - flatMap((request: RestRequest) => this.requestService.getByHref(request.href)) + switchMap((request: RestRequest) => this.requestService.getByHref(request.href)) ); // get search results from response cache diff --git a/src/app/core/auth/auth-response-parsing.service.spec.ts b/src/app/core/auth/auth-response-parsing.service.spec.ts index e23e3ac56b..a4131db489 100644 --- a/src/app/core/auth/auth-response-parsing.service.spec.ts +++ b/src/app/core/auth/auth-response-parsing.service.spec.ts @@ -1,7 +1,6 @@ import { AuthStatusResponse } from '../cache/response.models'; import { ObjectCacheService } from '../cache/object-cache.service'; -import { GlobalConfig } from '../../../config/global-config.interface'; import { AuthStatus } from './models/auth-status.model'; import { AuthResponseParsingService } from './auth-response-parsing.service'; import { AuthGetRequest, AuthPostRequest } from '../data/request.models'; @@ -11,7 +10,7 @@ import { ObjectCacheState } from '../cache/object-cache.reducer'; describe('AuthResponseParsingService', () => { let service: AuthResponseParsingService; - const EnvConfig = { cache: { msToLive: 1000 } } as GlobalConfig; + const EnvConfig = { cache: { msToLive: 1000 } } as any; const store = new MockStore({}); const objectCacheService = new ObjectCacheService(store as any); diff --git a/src/app/core/browse/browse.service.spec.ts b/src/app/core/browse/browse.service.spec.ts index 4465eae1ee..da75e1a877 100644 --- a/src/app/core/browse/browse.service.spec.ts +++ b/src/app/core/browse/browse.service.spec.ts @@ -8,6 +8,8 @@ import { BrowseEndpointRequest, BrowseEntriesRequest, BrowseItemsRequest } from import { RequestService } from '../data/request.service'; import { BrowseDefinition } from '../shared/browse-definition.model'; import { BrowseService } from './browse.service'; +import { RequestEntry } from '../data/request.reducer'; +import { of as observableOf } from 'rxjs'; describe('BrowseService', () => { let scheduler: TestScheduler; @@ -76,7 +78,11 @@ describe('BrowseService', () => { }) ]; - + const getRequestEntry$ = (successful: boolean) => { + return observableOf({ + response: { isSuccessful: successful, payload: browseDefinitions } as any + } as RequestEntry) + }; function initTestService() { return new BrowseService( @@ -93,7 +99,7 @@ describe('BrowseService', () => { describe('getBrowseDefinitions', () => { beforeEach(() => { - requestService = getMockRequestService(); + requestService = getMockRequestService(getRequestEntry$(true)); rdbService = getMockRemoteDataBuildService(); service = initTestService(); spyOn(halService, 'getEndpoint').and @@ -131,7 +137,7 @@ describe('BrowseService', () => { const mockAuthorName = 'Donald Smith'; beforeEach(() => { - requestService = getMockRequestService(); + requestService = getMockRequestService(getRequestEntry$(true)); rdbService = getMockRemoteDataBuildService(); service = initTestService(); spyOn(service, 'getBrowseDefinitions').and @@ -204,7 +210,7 @@ describe('BrowseService', () => { describe('if getBrowseDefinitions fires', () => { beforeEach(() => { - requestService = getMockRequestService(); + requestService = getMockRequestService(getRequestEntry$(true)); rdbService = getMockRemoteDataBuildService(); service = initTestService(); spyOn(service, 'getBrowseDefinitions').and @@ -259,7 +265,7 @@ describe('BrowseService', () => { describe('if getBrowseDefinitions doesn\'t fire', () => { it('should return undefined', () => { - requestService = getMockRequestService(); + requestService = getMockRequestService(getRequestEntry$(true)); rdbService = getMockRemoteDataBuildService(); service = initTestService(); spyOn(service, 'getBrowseDefinitions').and diff --git a/src/app/core/browse/browse.service.ts b/src/app/core/browse/browse.service.ts index c1c893ec27..ca56c0d267 100644 --- a/src/app/core/browse/browse.service.ts +++ b/src/app/core/browse/browse.service.ts @@ -1,8 +1,8 @@ import { Injectable } from '@angular/core'; import { Observable } from 'rxjs'; -import { distinctUntilChanged, filter, map, startWith, tap } from 'rxjs/operators'; +import { distinctUntilChanged, map, startWith } from 'rxjs/operators'; import { - ensureArrayHasValue, hasValue, + ensureArrayHasValue, hasValueOperator, isEmpty, isNotEmpty, @@ -34,7 +34,6 @@ import { import { URLCombiner } from '../url-combiner/url-combiner'; import { Item } from '../shared/item.model'; import { DSpaceObject } from '../shared/dspace-object.model'; -import { RequestEntry } from '../data/request.reducer'; @Injectable() export class BrowseService { 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 27b5ddf50d..ad5707bbf6 100644 --- a/src/app/core/cache/builders/remote-data-build.service.ts +++ b/src/app/core/cache/builders/remote-data-build.service.ts @@ -5,7 +5,7 @@ import { race as observableRace } from 'rxjs'; import { Injectable } from '@angular/core'; -import { distinctUntilChanged, flatMap, map, startWith, switchMap, tap } from 'rxjs/operators'; +import { distinctUntilChanged, first, flatMap, map, startWith, switchMap } from 'rxjs/operators'; import { hasValue, hasValueOperator, isEmpty, isNotEmpty } from '../../../shared/empty.util'; import { PaginatedList } from '../../data/paginated-list'; import { RemoteData } from '../../data/remote-data'; @@ -32,6 +32,8 @@ export class RemoteDataBuildService { } buildSingle(href$: string | Observable): Observable> { + console.log('call buildSingle', href$); + if (typeof href$ === 'string') { href$ = observableOf(href$); } @@ -42,19 +44,18 @@ export class RemoteDataBuildService { const requestEntry$ = observableRace( href$.pipe(getRequestFromSelflink(this.requestService)), - requestHref$.pipe(getRequestFromSelflink(this.requestService)) - ); + requestHref$.pipe(getRequestFromSelflink(this.requestService)), + ).pipe(first()); // always use self link if that is cached, only if it isn't, get it via the response. const payload$ = observableCombineLatest( href$.pipe( - flatMap((href: string) => this.objectCache.getBySelfLink(href)), - startWith(undefined) - ), + switchMap((href: string) => this.objectCache.getBySelfLink(href)), + startWith(undefined)), requestEntry$.pipe( getResourceLinksFromResponse(), - flatMap((resourceSelfLinks: string[]) => { + switchMap((resourceSelfLinks: string[]) => { if (isNotEmpty(resourceSelfLinks)) { return this.objectCache.getBySelfLink(resourceSelfLinks[0]); } else { @@ -83,7 +84,7 @@ export class RemoteDataBuildService { } toRemoteDataObservable(requestEntry$: Observable, payload$: Observable) { - return observableCombineLatest(requestEntry$, requestEntry$.pipe(startWith(undefined)), payload$).pipe( + return observableCombineLatest(requestEntry$, payload$).pipe( map(([reqEntry, payload]) => { const requestPending = hasValue(reqEntry.requestPending) ? reqEntry.requestPending : true; const responsePending = hasValue(reqEntry.responsePending) ? reqEntry.responsePending : false; @@ -124,9 +125,8 @@ export class RemoteDataBuildService { })); }), startWith([]), - distinctUntilChanged() + distinctUntilChanged(), ); - // tDomainList$.subscribe((t) => {console.log('domainlist', t)}); const pageInfo$ = requestEntry$.pipe( filterSuccessfulResponses(), map((response: DSOSuccessResponse) => { @@ -152,7 +152,6 @@ export class RemoteDataBuildService { build(normalized: TNormalized): TDomain { const links: any = {}; - const relationships = getRelationships(normalized.constructor) || []; relationships.forEach((relationship: string) => { @@ -196,8 +195,6 @@ export class RemoteDataBuildService { } }); const domainModel = getMapsTo(normalized.constructor); - // console.log('domain model', normalized); - return Object.assign(new domainModel(), normalized, links); } diff --git a/src/app/core/data/comcol-data.service.spec.ts b/src/app/core/data/comcol-data.service.spec.ts index 2125aff797..867d559c70 100644 --- a/src/app/core/data/comcol-data.service.spec.ts +++ b/src/app/core/data/comcol-data.service.spec.ts @@ -12,6 +12,8 @@ import { FindAllOptions, FindByIDRequest } from './request.models'; import { RequestService } from './request.service'; import { NormalizedObject } from '../cache/models/normalized-object.model'; import { HALEndpointService } from '../shared/hal-endpoint.service'; +import { RequestEntry } from './request.reducer'; +import { of as observableOf } from 'rxjs'; const LINK_NAME = 'test'; @@ -34,6 +36,7 @@ class TestService extends ComColDataService { super(); } } + /* tslint:enable:max-classes-per-file */ describe('ComColDataService', () => { @@ -52,6 +55,11 @@ describe('ComColDataService', () => { const options = Object.assign(new FindAllOptions(), { scopeID: scopeID }); + const getRequestEntry$ = (successful: boolean) => { + return observableOf({ + response: { isSuccessful: successful } as any + } as RequestEntry) + }; const communitiesEndpoint = 'https://rest.api/core/communities'; const communityEndpoint = `${communitiesEndpoint}/${scopeID}`; @@ -97,7 +105,7 @@ describe('ComColDataService', () => { it('should configure a new FindByIDRequest for the scope Community', () => { cds = initMockCommunityDataService(); - requestService = getMockRequestService(); + requestService = getMockRequestService(getRequestEntry$(true)); objectCache = initMockObjectCacheService(); service = initTestService(); @@ -112,7 +120,7 @@ describe('ComColDataService', () => { describe('if the scope Community can be found', () => { beforeEach(() => { cds = initMockCommunityDataService(); - requestService = getMockRequestService(); + requestService = getMockRequestService(getRequestEntry$(true)); objectCache = initMockObjectCacheService(); service = initTestService(); }); @@ -125,16 +133,16 @@ describe('ComColDataService', () => { it('should return the endpoint to fetch resources within the given scope', () => { const result = service.getBrowseEndpoint(options); - const expected = cold('--e-', { e: scopedEndpoint }); + const expected = '--e-'; - expect(result).toBeObservable(expected); + scheduler.expectObservable(result).toBe(expected, { e: scopedEndpoint }); }); }); describe('if the scope Community can\'t be found', () => { beforeEach(() => { cds = initMockCommunityDataService(); - requestService = getMockRequestService(); + requestService = getMockRequestService(getRequestEntry$(false)); objectCache = initMockObjectCacheService(); service = initTestService(); }); diff --git a/src/app/core/data/request.reducer.spec.ts b/src/app/core/data/request.reducer.spec.ts index bd8fad5de7..57fbb01ce1 100644 --- a/src/app/core/data/request.reducer.spec.ts +++ b/src/app/core/data/request.reducer.spec.ts @@ -2,16 +2,20 @@ import * as deepFreeze from 'deep-freeze'; import { requestReducer, RequestState } from './request.reducer'; import { - RequestCompleteAction, RequestConfigureAction, RequestExecuteAction + RequestCompleteAction, + RequestConfigureAction, + RequestExecuteAction, ResetResponseTimestampsAction } from './request.actions'; -import { GetRequest, RestRequest } from './request.models'; +import { GetRequest } from './request.models'; +import { RestResponse } from '../cache/response.models'; +const response = new RestResponse(true, 'OK'); class NullAction extends RequestCompleteAction { type = null; payload = null; constructor() { - super(null); + super(null, null); } } @@ -25,7 +29,8 @@ describe('requestReducer', () => { request: new GetRequest(id1, link1), requestPending: false, responsePending: false, - completed: false + completed: false, + response: undefined } }; deepFreeze(testState); @@ -56,6 +61,7 @@ describe('requestReducer', () => { expect(newState[id2].requestPending).toEqual(true); expect(newState[id2].responsePending).toEqual(false); expect(newState[id2].completed).toEqual(false); + expect(newState[id2].response).toEqual(undefined); }); it('should set \'requestPending\' to false, \'responsePending\' to true and leave \'completed\' untouched for the given RestRequest in the state, in response to an EXECUTE action', () => { @@ -69,11 +75,13 @@ describe('requestReducer', () => { expect(newState[id1].requestPending).toEqual(false); expect(newState[id1].responsePending).toEqual(true); expect(newState[id1].completed).toEqual(state[id1].completed); + expect(newState[id1].response).toEqual(undefined) }); + it('should leave \'requestPending\' untouched, set \'responsePending\' to false and \'completed\' to true for the given RestRequest in the state, in response to a COMPLETE action', () => { const state = testState; - const action = new RequestCompleteAction(id1); + const action = new RequestCompleteAction(id1, response); const newState = requestReducer(state, action); expect(newState[id1].request.uuid).toEqual(id1); @@ -81,5 +89,25 @@ describe('requestReducer', () => { expect(newState[id1].requestPending).toEqual(state[id1].requestPending); expect(newState[id1].responsePending).toEqual(false); expect(newState[id1].completed).toEqual(true); + expect(newState[id1].response.isSuccessful).toEqual(response.isSuccessful) + expect(newState[id1].response.statusCode).toEqual(response.statusCode) + expect(newState[id1].response.timeAdded).toBeTruthy() + }); + + it('should leave \'requestPending\' untouched, should leave \'responsePending\' untouched and leave \'completed\' untouched, but update the response\'s timeAdded for the given RestRequest in the state, in response to a COMPLETE action', () => { + const update = Object.assign({}, testState[id1], {response}); + const state = Object.assign({}, testState, {[id1]: update}); + const timeStamp = 1000; + const action = new ResetResponseTimestampsAction(timeStamp); + const newState = requestReducer(state, action); + + expect(newState[id1].request.uuid).toEqual(state[id1].request.uuid); + expect(newState[id1].request.href).toEqual(state[id1].request.href); + expect(newState[id1].requestPending).toEqual(state[id1].requestPending); + expect(newState[id1].responsePending).toEqual(state[id1].responsePending); + expect(newState[id1].completed).toEqual(state[id1].completed); + expect(newState[id1].response.isSuccessful).toEqual(response.isSuccessful); + expect(newState[id1].response.statusCode).toEqual(response.statusCode); + expect(newState[id1].response.timeAdded).toBe(timeStamp); }); }); diff --git a/src/app/core/data/request.reducer.ts b/src/app/core/data/request.reducer.ts index b0875f37b3..a680de2d6b 100644 --- a/src/app/core/data/request.reducer.ts +++ b/src/app/core/data/request.reducer.ts @@ -56,12 +56,13 @@ function configureRequest(state: RequestState, action: RequestConfigureAction): } function executeRequest(state: RequestState, action: RequestExecuteAction): RequestState { - return Object.assign({}, state, { + const obs = Object.assign({}, state, { [action.payload]: Object.assign({}, state[action.payload], { requestPending: false, responsePending: true }) }); + return obs; } /** @@ -76,16 +77,13 @@ function executeRequest(state: RequestState, action: RequestExecuteAction): Requ */ function completeRequest(state: RequestState, action: RequestCompleteAction): RequestState { const time = new Date().getTime(); - - const ob = Object.assign({}, state, { + return Object.assign({}, state, { [action.payload.uuid]: Object.assign({}, state[action.payload.uuid], { responsePending: false, completed: true, response: Object.assign({}, action.payload.response, { timeAdded: time }) }) }); - console.log(ob); - return ob; } function resetResponseTimestamps(state: RequestState, action: ResetResponseTimestampsAction) { diff --git a/src/app/core/data/request.service.spec.ts b/src/app/core/data/request.service.spec.ts index 5953d43c9f..5232d7efab 100644 --- a/src/app/core/data/request.service.spec.ts +++ b/src/app/core/data/request.service.spec.ts @@ -46,13 +46,10 @@ describe('RequestService', () => { objectCache = getMockObjectCacheService(); (objectCache.hasBySelfLink as any).and.returnValue(false); - (responseCache.has as any).and.returnValue(false); - (responseCache.get as any).and.returnValue(observableOf(undefined)); - uuidService = getMockUUIDService(); store = new Store(new BehaviorSubject({}), new ActionsSubject(), null); - selectSpy = spyOnProperty(ngrx, 'select') + selectSpy = spyOnProperty(ngrx, 'select'); selectSpy.and.callFake(() => { return () => { return () => cold('a', { a: undefined }); @@ -322,7 +319,7 @@ describe('RequestService', () => { describe('when the request is cached', () => { describe('in the ObjectCache', () => { beforeEach(() => { - (objectCache.hasBySelfLink as any).and.returnValues(true); + (objectCache.hasBySelfLink as any).and.returnValue(true); }); it('should return true', () => { @@ -334,12 +331,13 @@ describe('RequestService', () => { }); describe('in the responseCache', () => { beforeEach(() => { - (responseCache.has as any).and.returnValues(true); + spyOn(serviceAsAny, 'isReusable').and.returnValue(observableOf(true)); + spyOn(serviceAsAny, 'getByHref').and.returnValue(observableOf(undefined)); }); describe('and it\'s a DSOSuccessResponse', () => { beforeEach(() => { - (responseCache.get as any).and.returnValues(observableOf({ + (serviceAsAny.getByHref as any).and.returnValue(observableOf({ response: { isSuccessful: true, resourceSelfLinks: [ @@ -361,6 +359,7 @@ describe('RequestService', () => { }); 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; @@ -368,11 +367,12 @@ describe('RequestService', () => { expect(result).toEqual(expected); }); }); + describe('and it isn\'t a DSOSuccessResponse', () => { beforeEach(() => { - (objectCache.hasBySelfLink as any).and.returnValues(false); - (responseCache.has as any).and.returnValues(true); - (responseCache.get as any).and.returnValues(observableOf({ + (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 } diff --git a/src/app/core/data/request.service.ts b/src/app/core/data/request.service.ts index cc8c9816f8..564b19de75 100644 --- a/src/app/core/data/request.service.ts +++ b/src/app/core/data/request.service.ts @@ -1,5 +1,6 @@ import { merge as observableMerge, Observable, of as observableOf } from 'rxjs'; import { + distinctUntilChanged, filter, find, first, @@ -109,10 +110,10 @@ export class RequestService { 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; } @@ -144,7 +145,7 @@ export class RequestService { } /** - * Check whether a ResponseCacheEntry should still be cached + * Check whether a Response should still be cached * * @param entry * the entry to check diff --git a/src/app/core/registry/registry.service.spec.ts b/src/app/core/registry/registry.service.spec.ts index adb2ed8b05..c87597cffc 100644 --- a/src/app/core/registry/registry.service.spec.ts +++ b/src/app/core/registry/registry.service.spec.ts @@ -124,10 +124,10 @@ describe('RegistryService', () => { }; const rdbStub = { - toRemoteDataObservable: (requestEntryObs: Observable, responseCacheObs: Observable, payloadObs: Observable) => { + toRemoteDataObservable: (requestEntryObs: Observable, payloadObs: Observable) => { return observableCombineLatest(requestEntryObs, - responseCacheObs, payloadObs).pipe(map(([req, res, pay]) => { - return { req, res, pay }; + payloadObs).pipe(map(([req, pay]) => { + return { req, pay }; }) ); }, @@ -160,10 +160,10 @@ describe('RegistryService', () => { page: pageInfo }); const response = new RegistryMetadataschemasSuccessResponse(queryResponse, '200', pageInfo); - const responseEntry = Object.assign(new ResponseCacheEntry(), { response: response }); + const responseEntry = Object.assign(new RequestEntry(), { response: response }); beforeEach(() => { - (registryService as any).responseCache.get.and.returnValue(observableOf(responseEntry)); + (registryService as any).requestService.getByHref.and.returnValue(observableOf(responseEntry)); /* tslint:disable:no-empty */ registryService.getMetadataSchemas(pagination).subscribe((value) => { }); @@ -181,10 +181,6 @@ describe('RegistryService', () => { it('should call getByHref on the request service with the correct request url', () => { expect((registryService as any).requestService.getByHref).toHaveBeenCalledWith(endpointWithParams); }); - - it('should call get on the request service with the correct request url', () => { - expect((registryService as any).responseCache.get).toHaveBeenCalledWith(endpointWithParams); - }); }); describe('when requesting metadataschema by name', () => { @@ -193,10 +189,10 @@ describe('RegistryService', () => { page: pageInfo }); const response = new RegistryMetadataschemasSuccessResponse(queryResponse, '200', pageInfo); - const responseEntry = Object.assign(new ResponseCacheEntry(), { response: response }); + const responseEntry = Object.assign(new RequestEntry(), { response: response }); beforeEach(() => { - (registryService as any).responseCache.get.and.returnValue(observableOf(responseEntry)); + (registryService as any).requestService.getByHref.and.returnValue(observableOf(responseEntry)); /* tslint:disable:no-empty */ registryService.getMetadataSchemaByName(mockSchemasList[0].prefix).subscribe((value) => { }); @@ -214,10 +210,6 @@ describe('RegistryService', () => { it('should call getByHref on the request service with the correct request url', () => { expect((registryService as any).requestService.getByHref.calls.argsFor(0)[0]).toContain(endpoint); }); - - it('should call get on the request service with the correct request url', () => { - expect((registryService as any).responseCache.get.calls.argsFor(0)[0]).toContain(endpoint); - }); }); describe('when requesting metadatafields', () => { @@ -226,10 +218,10 @@ describe('RegistryService', () => { page: pageInfo }); const response = new RegistryMetadatafieldsSuccessResponse(queryResponse, '200', pageInfo); - const responseEntry = Object.assign(new ResponseCacheEntry(), { response: response }); + const responseEntry = Object.assign(new RequestEntry(), { response: response }); beforeEach(() => { - (registryService as any).responseCache.get.and.returnValue(observableOf(responseEntry)); + (registryService as any).requestService.getByHref.and.returnValue(observableOf(responseEntry)); /* tslint:disable:no-empty */ registryService.getMetadataFieldsBySchema(mockSchemasList[0], pagination).subscribe((value) => { }); @@ -247,10 +239,6 @@ describe('RegistryService', () => { it('should call getByHref on the request service with the correct request url', () => { expect((registryService as any).requestService.getByHref).toHaveBeenCalledWith(endpointWithParams); }); - - it('should call get on the request service with the correct request url', () => { - expect((registryService as any).responseCache.get).toHaveBeenCalledWith(endpointWithParams); - }); }); describe('when requesting bitstreamformats', () => { @@ -259,10 +247,10 @@ describe('RegistryService', () => { page: pageInfo }); const response = new RegistryBitstreamformatsSuccessResponse(queryResponse, '200', pageInfo); - const responseEntry = Object.assign(new ResponseCacheEntry(), { response: response }); + const responseEntry = Object.assign(new RequestEntry(), { response: response }); beforeEach(() => { - (registryService as any).responseCache.get.and.returnValue(observableOf(responseEntry)); + (registryService as any).requestService.getByHref.and.returnValue(observableOf(responseEntry)); /* tslint:disable:no-empty */ registryService.getBitstreamFormats(pagination).subscribe((value) => { }); @@ -280,9 +268,5 @@ describe('RegistryService', () => { it('should call getByHref on the request service with the correct request url', () => { expect((registryService as any).requestService.getByHref).toHaveBeenCalledWith(endpointWithParams); }); - - it('should call get on the request service with the correct request url', () => { - expect((registryService as any).responseCache.get).toHaveBeenCalledWith(endpointWithParams); - }); }); }); diff --git a/src/app/core/shared/hal-endpoint.service.spec.ts b/src/app/core/shared/hal-endpoint.service.spec.ts index d36da207ca..b65b3f905b 100644 --- a/src/app/core/shared/hal-endpoint.service.spec.ts +++ b/src/app/core/shared/hal-endpoint.service.spec.ts @@ -1,33 +1,44 @@ -import { cold, hot } from 'jasmine-marbles'; +import { cold, getTestScheduler, hot } from 'jasmine-marbles'; import { GlobalConfig } from '../../../config/global-config.interface'; import { getMockRequestService } from '../../shared/mocks/mock-request.service'; import { RequestService } from '../data/request.service'; import { HALEndpointService } from './hal-endpoint.service'; import { EndpointMapRequest } from '../data/request.models'; +import { RequestEntry } from '../data/request.reducer'; +import { of as observableOf } from 'rxjs'; describe('HALEndpointService', () => { let service: HALEndpointService; let requestService: RequestService; let envConfig: GlobalConfig; + let requestEntry; const endpointMap = { test: 'https://rest.api/test', }; const linkPath = 'test'; + beforeEach(() => { + requestEntry = { + request: { responseMsToLive: 1000 } as any, + requestPending: false, + responsePending: false, + completed: true, + response: { endpointMap: endpointMap } as any + } as RequestEntry; + requestService = getMockRequestService(observableOf(requestEntry)); + + envConfig = { + rest: { baseUrl: 'https://rest.api/' } + } as any; + + service = new HALEndpointService( + requestService, + envConfig + ); + }); + describe('getRootEndpointMap', () => { - beforeEach(() => { - requestService = getMockRequestService(); - - envConfig = { - rest: { baseUrl: 'https://rest.api/' } - } as any; - - service = new HALEndpointService( - requestService, - envConfig - ); - }); it('should configure a new EndpointMapRequest', () => { (service as any).getRootEndpointMap(); @@ -37,8 +48,8 @@ describe('HALEndpointService', () => { it('should return an Observable of the endpoint map', () => { const result = (service as any).getRootEndpointMap(); - const expected = cold('b-', { b: endpointMap }); - expect(result).toBeObservable(expected); + const expected = '(b|)'; + getTestScheduler().expectObservable(result).toBe(expected, { b: endpointMap }); }); }); diff --git a/src/app/core/shared/hal-endpoint.service.ts b/src/app/core/shared/hal-endpoint.service.ts index 8ef65c4dd1..3a5da84e13 100644 --- a/src/app/core/shared/hal-endpoint.service.ts +++ b/src/app/core/shared/hal-endpoint.service.ts @@ -1,9 +1,8 @@ -import { Observable, of as observableOf } from 'rxjs'; +import { Observable, of as observableOf, combineLatest as observableCombineLatest } from 'rxjs'; import { distinctUntilChanged, - filter, - flatMap, map, + mergeMap, startWith, switchMap, tap @@ -11,12 +10,13 @@ import { import { RequestService } from '../data/request.service'; import { GlobalConfig } from '../../../config/global-config.interface'; import { EndpointMapRequest } from '../data/request.models'; -import { hasValue, isEmpty, isNotEmpty, isNotUndefined } from '../../shared/empty.util'; +import { hasValue, isEmpty, isNotEmpty } from '../../shared/empty.util'; import { RESTURLCombiner } from '../url-combiner/rest-url-combiner'; import { Inject, Injectable } from '@angular/core'; import { GLOBAL_CONFIG } from '../../../config'; import { EndpointMap, EndpointMapSuccessResponse } from '../cache/response.models'; import { getResponseFromEntry } from './operators'; +import { URLCombiner } from '../url-combiner/url-combiner'; @Injectable() export class HALEndpointService { @@ -36,48 +36,41 @@ export class HALEndpointService { private getEndpointMapAt(href): Observable { const request = new EndpointMapRequest(this.requestService.generateRequestId(), href); - this.requestService.getByUUID(request.uuid).pipe( - getResponseFromEntry(), - map((response: EndpointMapSuccessResponse) => response.endpointMap), - distinctUntilChanged()).subscribe((t) => console.log('uuid', t)); - this.requestService.getByHref(request.href).pipe( - getResponseFromEntry(), - map((response: EndpointMapSuccessResponse) => response.endpointMap), - distinctUntilChanged()).subscribe((t) => console.log('href', t)); - this.requestService.configure(request); - return this.requestService.getByHref(request.href).pipe( /*<-- changing this to UUID breaks it */ + return this.requestService.getByHref(request.href).pipe( getResponseFromEntry(), map((response: EndpointMapSuccessResponse) => response.endpointMap), distinctUntilChanged()); - } public getEndpoint(linkPath: string): Observable { - return this.getEndpointAt(...linkPath.split('/')); + return this.getEndpointAt(this.getRootHref(), ...linkPath.split('/')); } - private getEndpointAt(...path: string[]): Observable { - if (isEmpty(path)) { - path = ['/']; + private getEndpointAt(href: string, ...halNames: string[]): Observable { + if (isEmpty(halNames)) { + throw new Error('cant\'t fetch the URL without the HAL link names') + } + + const nextHref$ = this.getEndpointMapAt(href).pipe( + map((endpointMap: EndpointMap): string => { + /*TODO remove if/else block once the rest response contains _links for facets*/ + const nextName = halNames[0]; + if (hasValue(endpointMap) && hasValue(endpointMap[nextName])) { + return endpointMap[nextName]; + } else { + return new URLCombiner(href, nextName).toString(); + } + }) + ) as Observable; + + if (halNames.length === 1) { + return nextHref$; + } else { + return nextHref$.pipe( + switchMap((nextHref) => this.getEndpointAt(nextHref, ...halNames.slice(1))) + ); } - let currentPath; - const pipeArguments = path - .map((subPath: string, index: number) => [ - switchMap((href: string) => this.getEndpointMapAt(href)), - map((endpointMap: EndpointMap) => { - if (hasValue(endpointMap) && hasValue(endpointMap[subPath])) { - currentPath = endpointMap[subPath]; - return endpointMap[subPath]; - } else { - /*TODO remove if/else block once the rest response contains _links for facets*/ - currentPath += '/' + subPath; - return currentPath; - } - }), - ]) - .reduce((combined, thisElement) => [...combined, ...thisElement], []); - return observableOf(this.getRootHref()).pipe(...pipeArguments, distinctUntilChanged()); } public isEnabledOnRestApi(linkPath: string): Observable { diff --git a/src/app/core/shared/operators.spec.ts b/src/app/core/shared/operators.spec.ts index 0684308fe9..5f29de9e93 100644 --- a/src/app/core/shared/operators.spec.ts +++ b/src/app/core/shared/operators.spec.ts @@ -25,6 +25,14 @@ describe('Core Module - RxJS Operators', () => { e: { response: { isSuccessful: 1, resourceSelfLinks: [] } } }; + const testResponses = { + a: testRCEs.a.response, + b: testRCEs.b.response, + c: testRCEs.c.response, + d: testRCEs.d.response, + e: testRCEs.e.response + }; + beforeEach(() => { scheduler = getTestScheduler(); }); @@ -66,7 +74,7 @@ describe('Core Module - RxJS Operators', () => { it('should only return responses for which isSuccessful === true', () => { const source = hot('abcde', testRCEs); const result = source.pipe(filterSuccessfulResponses()); - const expected = cold('a--d-', testRCEs); + const expected = cold('a--d-', testResponses); expect(result).toBeObservable(expected) }); diff --git a/src/app/core/shared/operators.ts b/src/app/core/shared/operators.ts index e9ab8794ff..a6335ebb5d 100644 --- a/src/app/core/shared/operators.ts +++ b/src/app/core/shared/operators.ts @@ -58,6 +58,7 @@ export const getSucceededRemoteData = () => export const toDSpaceObjectListRD = () => (source: Observable>>>): Observable>> => source.pipe( + filter((rd: RemoteData>>) => rd.hasSucceeded), map((rd: RemoteData>>) => { const dsoPage: T[] = rd.payload.page.map((searchResult: SearchResult) => searchResult.dspaceObject); const payload = Object.assign(rd.payload, { page: dsoPage }) as PaginatedList; From 5c12e2d995711bdea06e75ae1a7800383e233766 Mon Sep 17 00:00:00 2001 From: lotte Date: Fri, 19 Oct 2018 16:07:07 +0200 Subject: [PATCH 47/48] added indexing for different UUIDs --- src/app/core/auth/auth-request.service.ts | 3 + src/app/core/auth/auth.service.ts | 1 + .../builders/remote-data-build.service.ts | 16 +++-- src/app/core/data/comcol-data.service.ts | 14 +++- src/app/core/data/data.service.ts | 2 - src/app/core/data/request.effects.ts | 6 +- src/app/core/data/request.reducer.ts | 8 +++ src/app/core/data/request.service.spec.ts | 8 +-- src/app/core/data/request.service.ts | 64 +++++++++++++------ src/app/core/index/index.reducer.spec.ts | 4 ++ src/app/core/index/index.reducer.ts | 14 ++-- src/app/core/shared/hal-endpoint.service.ts | 4 +- 12 files changed, 101 insertions(+), 43 deletions(-) diff --git a/src/app/core/auth/auth-request.service.ts b/src/app/core/auth/auth-request.service.ts index 0752149eae..284f588040 100644 --- a/src/app/core/auth/auth-request.service.ts +++ b/src/app/core/auth/auth-request.service.ts @@ -24,9 +24,12 @@ export class AuthRequestService { protected fetchRequest(request: RestRequest): Observable { return this.requestService.getByHref(request.href).pipe( + tap((t) => console.log(t)), + getResponseFromEntry(), // TODO to review when https://github.com/DSpace/dspace-angular/issues/217 will be fixed // tap(() => this.responseCache.remove(request.href)), + tap((t) => console.log(t)), mergeMap((response) => { if (response.isSuccessful && isNotEmpty(response)) { return observableOf((response as AuthStatusResponse).response); diff --git a/src/app/core/auth/auth.service.ts b/src/app/core/auth/auth.service.ts index 229c44bcfa..4c520e8f30 100644 --- a/src/app/core/auth/auth.service.ts +++ b/src/app/core/auth/auth.service.ts @@ -116,6 +116,7 @@ export class AuthService { options.headers = headers; return this.authRequestService.postToEndpoint('login', body, options).pipe( map((status: AuthStatus) => { + console.log('yey response'); if (status.authenticated) { return status; } else { 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 ad5707bbf6..3877c19ff9 100644 --- a/src/app/core/cache/builders/remote-data-build.service.ts +++ b/src/app/core/cache/builders/remote-data-build.service.ts @@ -5,7 +5,15 @@ import { race as observableRace } from 'rxjs'; import { Injectable } from '@angular/core'; -import { distinctUntilChanged, first, flatMap, map, startWith, switchMap } from 'rxjs/operators'; +import { + distinctUntilChanged, + first, + flatMap, + map, + startWith, + switchMap, + takeUntil, tap +} from 'rxjs/operators'; import { hasValue, hasValueOperator, isEmpty, isNotEmpty } from '../../../shared/empty.util'; import { PaginatedList } from '../../data/paginated-list'; import { RemoteData } from '../../data/remote-data'; @@ -32,8 +40,6 @@ export class RemoteDataBuildService { } buildSingle(href$: string | Observable): Observable> { - console.log('call buildSingle', href$); - if (typeof href$ === 'string') { href$ = observableOf(href$); } @@ -45,7 +51,9 @@ export class RemoteDataBuildService { const requestEntry$ = observableRace( href$.pipe(getRequestFromSelflink(this.requestService)), requestHref$.pipe(getRequestFromSelflink(this.requestService)), - ).pipe(first()); + ).pipe( + first() + ); // always use self link if that is cached, only if it isn't, get it via the response. const payload$ = diff --git a/src/app/core/data/comcol-data.service.ts b/src/app/core/data/comcol-data.service.ts index 95a0015125..63c11dd8cb 100644 --- a/src/app/core/data/comcol-data.service.ts +++ b/src/app/core/data/comcol-data.service.ts @@ -1,4 +1,13 @@ -import { distinctUntilChanged, filter, map, mergeMap, share, take, tap } from 'rxjs/operators'; +import { + distinctUntilChanged, + filter, + first, + map, + mergeMap, + share, + take, + tap +} from 'rxjs/operators'; import { merge as observableMerge, Observable, throwError as observableThrowError } from 'rxjs'; import { hasValue, isEmpty, isNotEmpty } from '../../shared/empty.util'; import { NormalizedCommunity } from '../cache/models/normalized-community.model'; @@ -59,7 +68,8 @@ export abstract class ComColDataService this.requestService.getByHref(href)), - getResponseFromEntry()); + getResponseFromEntry() + ); const errorResponses = responses.pipe( filter((response) => !response.isSuccessful), mergeMap(() => observableThrowError(new Error(`The Community with scope ${options.scopeID} couldn't be retrieved`))) diff --git a/src/app/core/data/data.service.ts b/src/app/core/data/data.service.ts index 4a993e4ac6..6a7916854b 100644 --- a/src/app/core/data/data.service.ts +++ b/src/app/core/data/data.service.ts @@ -47,8 +47,6 @@ export abstract class DataService if (isNotEmpty(args)) { return result.pipe(map((href: string) => new URLCombiner(href, `?${args.join('&')}`).toString())); } else { - result.subscribe((t) => console.log(t)); - return result; } } diff --git a/src/app/core/data/request.effects.ts b/src/app/core/data/request.effects.ts index bda91283bf..537a0b69b6 100644 --- a/src/app/core/data/request.effects.ts +++ b/src/app/core/data/request.effects.ts @@ -3,7 +3,7 @@ import { Inject, Injectable, Injector } from '@angular/core'; import { Actions, Effect, ofType } from '@ngrx/effects'; import { GLOBAL_CONFIG, GlobalConfig } from '../../../config'; -import { isNotEmpty } from '../../shared/empty.util'; +import { hasValue, isNotEmpty } from '../../shared/empty.util'; import { DSpaceRESTV2Response } from '../dspace-rest-v2/dspace-rest-v2-response.model'; import { DSpaceRESTv2Service } from '../dspace-rest-v2/dspace-rest-v2.service'; @@ -18,7 +18,7 @@ import { RequestEntry } from './request.reducer'; import { RequestService } from './request.service'; import { DSpaceRESTv2Serializer } from '../dspace-rest-v2/dspace-rest-v2.serializer'; import { NormalizedObjectFactory } from '../cache/models/normalized-object-factory'; -import { catchError, flatMap, map, take, tap } from 'rxjs/operators'; +import { catchError, filter, flatMap, map, take, tap } from 'rxjs/operators'; import { ErrorResponse, RestResponse } from '../cache/response.models'; import { StoreActionTypes } from '../../store.actions'; @@ -40,7 +40,9 @@ export class RequestEffects { take(1) ); }), + filter((entry: RequestEntry) => hasValue(entry)), map((entry: RequestEntry) => entry.request), + tap((entry: RequestEntry) => console.log(entry)), flatMap((request: RestRequest) => { let body; if (isNotEmpty(request.body)) { diff --git a/src/app/core/data/request.reducer.ts b/src/app/core/data/request.reducer.ts index a680de2d6b..e6a9097dce 100644 --- a/src/app/core/data/request.reducer.ts +++ b/src/app/core/data/request.reducer.ts @@ -53,6 +53,14 @@ function configureRequest(state: RequestState, action: RequestConfigureAction): completed: false, } }); + console.log(Object.assign({}, state, { + [action.payload.uuid]: { + request: action.payload, + requestPending: true, + responsePending: false, + completed: false, + } + });); } function executeRequest(state: RequestState, action: RequestExecuteAction): RequestState { diff --git a/src/app/core/data/request.service.spec.ts b/src/app/core/data/request.service.spec.ts index 5232d7efab..debddb748c 100644 --- a/src/app/core/data/request.service.spec.ts +++ b/src/app/core/data/request.service.spec.ts @@ -170,11 +170,11 @@ describe('RequestService', () => { it('should return an Observable of undefined', () => { const result = service.getByUUID(testUUID); - const expected = cold('b', { - b: undefined - }); + // const expected = cold('b', { + // b: undefined + // }); - expect(result).toBeObservable(expected); + scheduler.expectObservable(result).toBe('b', {b: undefined}); }); }); diff --git a/src/app/core/data/request.service.ts b/src/app/core/data/request.service.ts index 564b19de75..4b7a7c9b49 100644 --- a/src/app/core/data/request.service.ts +++ b/src/app/core/data/request.service.ts @@ -12,10 +12,11 @@ import { take, tap } from 'rxjs/operators'; +import { race as observableRace } from 'rxjs'; import { Injectable } from '@angular/core'; import { MemoizedSelector, select, Store } from '@ngrx/store'; -import { hasNoValue, hasValue } from '../../shared/empty.util'; +import { hasNoValue, hasValue, isNotUndefined } 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'; @@ -30,6 +31,7 @@ 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 } from '../index/index.actions'; @Injectable() export class RequestService { @@ -48,6 +50,10 @@ export class RequestService { return pathSelector(coreSelector, 'index', IndexName.REQUEST, href); } + private originalUUIDFromUUIDSelector(uuid: string): MemoizedSelector { + return pathSelector(coreSelector, 'index', IndexName.UUID_MAPPING, uuid); + } + generateRequestId(): string { return `client/${this.uuidService.generate()}`; } @@ -70,7 +76,15 @@ export class RequestService { } getByUUID(uuid: string): Observable { - return this.store.pipe(select(this.entryFromUUIDSelector(uuid))); + return observableRace( + this.store.pipe(select(this.entryFromUUIDSelector(uuid))), + this.store.pipe( + select(this.originalUUIDFromUUIDSelector(uuid)), + switchMap((originalUUID) => { + return this.store.pipe(select(this.entryFromUUIDSelector(originalUUID))) + }, + )) + ); } getByHref(href: string): Observable { @@ -88,32 +102,42 @@ export class RequestService { if (isGetRequest && !forceBypassCache) { this.trackRequestsOnTheirWayToTheStore(request); } + } else { + this.getByHref(request.href).pipe( + filter((entry) => hasValue(entry)), + take(1) + ).subscribe((entry) => { + return this.store.dispatch(new AddToIndexAction(IndexName.UUID_MAPPING, request.uuid, entry.request.uuid)) + } + ) } } private isCachedOrPending(request: GetRequest) { let isCached = this.objectCache.hasBySelfLink(request.href); - const responses: Observable = this.isReusable(request.uuid).pipe( - filter((reusable: boolean) => !isCached && reusable), - switchMap(() => { - return this.getByHref(request.href).pipe( - getResponseFromEntry(), - take(1) - ); - } - )); + if (isCached) { + const responses: Observable = this.isReusable(request.uuid).pipe( + filter((reusable: boolean) => reusable), + switchMap(() => { + return this.getByHref(request.href).pipe( + getResponseFromEntry(), + take(1) + ); + } + )); - 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 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)); + const otherSuccessResponses = responses.pipe(filter((response) => response.isSuccessful && !hasValue((response as DSOSuccessResponse).resourceSelfLinks)), map(() => true)); - observableMerge(errorResponses, otherSuccessResponses, dsoSuccessResponses).subscribe((c) => isCached = c); + observableMerge(errorResponses, otherSuccessResponses, dsoSuccessResponses).subscribe((c) => isCached = c); + } const isPending = this.isPending(request); return isCached || isPending; } diff --git a/src/app/core/index/index.reducer.spec.ts b/src/app/core/index/index.reducer.spec.ts index a1cf92aeb3..ffc2c9fadc 100644 --- a/src/app/core/index/index.reducer.spec.ts +++ b/src/app/core/index/index.reducer.spec.ts @@ -20,6 +20,10 @@ describe('requestReducer', () => { const testState: IndexState = { [IndexName.OBJECT]: { [key1]: val1 + },[IndexName.REQUEST]: { + [key1]: val1 + },[IndexName.UUID_MAPPING]: { + [key1]: val1 } }; deepFreeze(testState); diff --git a/src/app/core/index/index.reducer.ts b/src/app/core/index/index.reducer.ts index 869dee9e51..c179182509 100644 --- a/src/app/core/index/index.reducer.ts +++ b/src/app/core/index/index.reducer.ts @@ -7,13 +7,12 @@ import { export enum IndexName { OBJECT = 'object/uuid-to-self-link', - REQUEST = 'get-request/href-to-uuid' + REQUEST = 'get-request/href-to-uuid', + UUID_MAPPING = 'get-request/configured-to-cache-uuid' } -export interface IndexState { - // TODO this should be `[name in IndexName]: {` but that's currently broken, - // see https://github.com/Microsoft/TypeScript/issues/13042 - [name: string]: { +export type IndexState = { + [name in IndexName]: { [key: string]: string } } @@ -43,9 +42,10 @@ function addToIndex(state: IndexState, action: AddToIndexAction): IndexState { const newSubState = Object.assign({}, subState, { [action.payload.key]: action.payload.value }); - return Object.assign({}, state, { + const obs = Object.assign({}, state, { [action.payload.name]: newSubState - }) + }); + return obs; } function removeFromIndexByValue(state: IndexState, action: RemoveFromIndexByValueAction): IndexState { diff --git a/src/app/core/shared/hal-endpoint.service.ts b/src/app/core/shared/hal-endpoint.service.ts index 3a5da84e13..a0bf7aabd5 100644 --- a/src/app/core/shared/hal-endpoint.service.ts +++ b/src/app/core/shared/hal-endpoint.service.ts @@ -1,6 +1,6 @@ import { Observable, of as observableOf, combineLatest as observableCombineLatest } from 'rxjs'; import { - distinctUntilChanged, + distinctUntilChanged, first, map, mergeMap, startWith, @@ -40,7 +40,7 @@ export class HALEndpointService { return this.requestService.getByHref(request.href).pipe( getResponseFromEntry(), map((response: EndpointMapSuccessResponse) => response.endpointMap), - distinctUntilChanged()); + ); } public getEndpoint(linkPath: string): Observable { From 6de7104b7c0b9b625414ce32a31109dc2dbeb5c3 Mon Sep 17 00:00:00 2001 From: lotte Date: Fri, 19 Oct 2018 16:18:44 +0200 Subject: [PATCH 48/48] finished update --- src/app/core/auth/auth-request.service.ts | 5 +---- src/app/core/data/request.reducer.ts | 8 -------- 2 files changed, 1 insertion(+), 12 deletions(-) diff --git a/src/app/core/auth/auth-request.service.ts b/src/app/core/auth/auth-request.service.ts index 284f588040..f957d807c1 100644 --- a/src/app/core/auth/auth-request.service.ts +++ b/src/app/core/auth/auth-request.service.ts @@ -23,13 +23,10 @@ export class AuthRequestService { } protected fetchRequest(request: RestRequest): Observable { - return this.requestService.getByHref(request.href).pipe( - tap((t) => console.log(t)), - + return this.requestService.getByUUID(request.uuid).pipe( getResponseFromEntry(), // TODO to review when https://github.com/DSpace/dspace-angular/issues/217 will be fixed // tap(() => this.responseCache.remove(request.href)), - tap((t) => console.log(t)), mergeMap((response) => { if (response.isSuccessful && isNotEmpty(response)) { return observableOf((response as AuthStatusResponse).response); diff --git a/src/app/core/data/request.reducer.ts b/src/app/core/data/request.reducer.ts index e6a9097dce..a680de2d6b 100644 --- a/src/app/core/data/request.reducer.ts +++ b/src/app/core/data/request.reducer.ts @@ -53,14 +53,6 @@ function configureRequest(state: RequestState, action: RequestConfigureAction): completed: false, } }); - console.log(Object.assign({}, state, { - [action.payload.uuid]: { - request: action.payload, - requestPending: true, - responsePending: false, - completed: false, - } - });); } function executeRequest(state: RequestState, action: RequestExecuteAction): RequestState {