diff --git a/package.json b/package.json index cc687ea269..7755f3d3d0 100644 --- a/package.json +++ b/package.json @@ -221,7 +221,7 @@ "typedoc": "^0.9.0", "typescript": "^2.9.1", "webpack": "^4.17.1", - "webpack-bundle-analyzer": "^2.13.1", + "webpack-bundle-analyzer": "^3.3.2", "webpack-dev-middleware": "3.2.0", "webpack-dev-server": "^3.1.5", "webpack-merge": "4.1.4", diff --git a/resources/i18n/en.json b/resources/i18n/en.json index e9eef8b9b8..a066ffe9d0 100644 --- a/resources/i18n/en.json +++ b/resources/i18n/en.json @@ -597,6 +597,18 @@ "objectpeople": { "placeholder": "People", "head": "People" + }, + "jobTitle": { + "placeholder": "Job Title", + "head": "Job Title" + }, + "knowsLanguage": { + "placeholder": "Known language", + "head": "Known language" + }, + "birthDate": { + "placeholder": "Birth Date", + "head": "Birth Date" } } } diff --git a/src/app/+search-page/filtered-search-page.component.spec.ts b/src/app/+search-page/filtered-search-page.component.spec.ts index 5c49767ed2..59ab9d7b0d 100644 --- a/src/app/+search-page/filtered-search-page.component.spec.ts +++ b/src/app/+search-page/filtered-search-page.component.spec.ts @@ -18,20 +18,4 @@ describe('FilteredSearchPageComponent', () => { searchConfigService = (comp as any).searchConfigService; fixture.detectChanges(); }); - - describe('when fixedFilterQuery is defined', () => { - const fixedFilterQuery = 'fixedFilterQuery'; - - beforeEach(() => { - spyOn(searchConfigService, 'updateFixedFilter').and.callThrough(); - comp.fixedFilterQuery = fixedFilterQuery; - comp.ngOnInit(); - fixture.detectChanges(); - }); - - it('should update the paginated search options', () => { - expect(searchConfigService.updateFixedFilter).toHaveBeenCalledWith(fixedFilterQuery); - }); - }); - }); diff --git a/src/app/+search-page/filtered-search-page.component.ts b/src/app/+search-page/filtered-search-page.component.ts index d577c2c44c..66c619b823 100644 --- a/src/app/+search-page/filtered-search-page.component.ts +++ b/src/app/+search-page/filtered-search-page.component.ts @@ -2,20 +2,22 @@ import { HostWindowService } from '../shared/host-window.service'; import { SearchService } from './search-service/search.service'; import { SearchSidebarService } from './search-sidebar/search-sidebar.service'; import { SearchPageComponent } from './search-page.component'; -import { ChangeDetectionStrategy, Component, Inject, Input } from '@angular/core'; +import { ChangeDetectionStrategy, Component, Inject, Input, OnInit } from '@angular/core'; import { pushInOut } from '../shared/animations/push'; import { RouteService } from '../shared/services/route.service'; import { SearchConfigurationService } from './search-service/search-configuration.service'; import { Observable } from 'rxjs'; import { PaginatedSearchOptions } from './paginated-search-options.model'; import { SEARCH_CONFIG_SERVICE } from '../+my-dspace-page/my-dspace-page.component'; +import { map } from 'rxjs/operators'; /** * This component renders a simple item page. * The route parameter 'id' is used to request the item it represents. * All fields of the item that should be displayed, are defined in its template. */ -@Component({selector: 'ds-filtered-search-page', +@Component({ + selector: 'ds-filtered-search-page', styleUrls: ['./search-page.component.scss'], templateUrl: './search-page.component.html', changeDetection: ChangeDetectionStrategy.OnPush, @@ -28,8 +30,7 @@ import { SEARCH_CONFIG_SERVICE } from '../+my-dspace-page/my-dspace-page.compone ] }) -export class FilteredSearchPageComponent extends SearchPageComponent { - +export class FilteredSearchPageComponent extends SearchPageComponent implements OnInit { /** * The actual query for the fixed filter. * If empty, the query will be determined by the route parameter called 'filter' @@ -44,6 +45,17 @@ export class FilteredSearchPageComponent extends SearchPageComponent { super(service, sidebarService, windowService, searchConfigService, routeService); } + /** + * Listening to changes in the paginated search options + * If something changes, update the search results + * + * Listen to changes in the scope + * If something changes, update the list of scopes for the dropdown + */ + ngOnInit(): void { + super.ngOnInit(); + } + /** * Get the current paginated search options after updating the fixed filter using the fixedFilterQuery input * This is to make sure the fixed filter is included in the paginated search options, as it is not part of any @@ -51,8 +63,11 @@ export class FilteredSearchPageComponent extends SearchPageComponent { * @returns {Observable} */ protected getSearchOptions(): Observable { - this.searchConfigService.updateFixedFilter(this.fixedFilterQuery); - return this.searchConfigService.paginatedSearchOptions; + return this.searchConfigService.paginatedSearchOptions.pipe( + map((options: PaginatedSearchOptions) => { + const filter = this.fixedFilterQuery || options.fixedFilter; + return Object.assign(options, { fixedFilter: filter }); + }) + ); } - } diff --git a/src/app/+search-page/search-filters/search-filter/search-facet-filter/search-facet-filter.component.ts b/src/app/+search-page/search-filters/search-filter/search-facet-filter/search-facet-filter.component.ts index 772240eb0b..ee980a0599 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,12 +1,12 @@ import { - combineLatest as observableCombineLatest, - of as observableOf, BehaviorSubject, + combineLatest as observableCombineLatest, Observable, + of as observableOf, Subject, Subscription } from 'rxjs'; -import { switchMap, distinctUntilChanged, map, take, flatMap, tap } from 'rxjs/operators'; +import { distinctUntilChanged, map, switchMap, take, tap } 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'; @@ -137,7 +137,7 @@ export class SearchFacetFilterComponent implements OnInit, OnDestroy { this.selectedValues$ = this.filterService.getSelectedValuesForFilter(this.filterConfig).pipe( map((selectedValues) => { return selectedValues.map((value: string) => { - const fValue = [].concat(...rd.payload.map((page) => page.page)).find((facetValue: FacetValue) => facetValue.value === value); + const fValue = [].concat(...rd.payload.map((page) => page.page)).find((facetValue: FacetValue) => this.getFacetValue(facetValue) === value); if (hasValue(fValue)) { return fValue; } diff --git a/src/app/+search-page/search-filters/search-filter/search-fixed-filter.service.spec.ts b/src/app/+search-page/search-filters/search-filter/search-fixed-filter.service.spec.ts index 3207345564..3f6c2ef133 100644 --- a/src/app/+search-page/search-filters/search-filter/search-fixed-filter.service.spec.ts +++ b/src/app/+search-page/search-filters/search-filter/search-fixed-filter.service.spec.ts @@ -17,7 +17,7 @@ describe('SearchFixedFilterService', () => { configure: () => {}, /* tslint:enable:no-empty */ generateRequestId: () => 'fake-id', - getByUUID: () => observableOf(Object.assign(new RequestEntry(), { + getByHref: () => observableOf(Object.assign(new RequestEntry(), { response: new FilteredDiscoveryQueryResponse(filterQuery, 200, 'OK') })) }) as RequestService; @@ -56,5 +56,4 @@ describe('SearchFixedFilterService', () => { expect(query).toContain(itemUUID); }); }); - }); diff --git a/src/app/+search-page/search-filters/search-filter/search-fixed-filter.service.ts b/src/app/+search-page/search-filters/search-filter/search-fixed-filter.service.ts index 7d59e5a446..0f17b508c9 100644 --- a/src/app/+search-page/search-filters/search-filter/search-fixed-filter.service.ts +++ b/src/app/+search-page/search-filters/search-filter/search-fixed-filter.service.ts @@ -1,6 +1,6 @@ import { Injectable } from '@angular/core'; -import { flatMap, map } from 'rxjs/operators'; -import { Observable , of as observableOf } from 'rxjs'; +import { flatMap, map, switchMap, tap } from 'rxjs/operators'; +import { Observable, of as observableOf } from 'rxjs'; import { HALEndpointService } from '../../../core/shared/hal-endpoint.service'; import { GetRequest, RestRequest } from '../../../core/data/request.models'; import { RequestService } from '../../../core/data/request.service'; @@ -33,7 +33,7 @@ export class SearchFixedFilterService { getQueryByFilterName(filterName: string): Observable { if (hasValue(filterName)) { const requestUuid = this.requestService.generateRequestId(); - this.halService.getEndpoint(this.queryByFilterPath).pipe( + const requestObs = this.halService.getEndpoint(this.queryByFilterPath).pipe( map((url: string) => { url += ('/' + filterName); const request = new GetRequest(requestUuid, url); @@ -44,10 +44,12 @@ export class SearchFixedFilterService { }); }), configureRequest(this.requestService) - ).subscribe(); + ); - // get search results from response cache - const filterQuery: Observable = this.requestService.getByUUID(requestUuid).pipe( + const requestEntryObs = requestObs.pipe( + switchMap((request: RestRequest) => this.requestService.getByHref(request.href)), + ); + const filterQuery = requestEntryObs.pipe( getResponseFromEntry(), map((response: FilteredDiscoveryQueryResponse) => response.filterQuery @@ -75,5 +77,4 @@ export class SearchFixedFilterService { getFilterByRelation(relationType: string, itemUUID: string): string { return `f.${relationType}=${itemUUID}`; } - } diff --git a/src/app/+search-page/search-page.component.html b/src/app/+search-page/search-page.component.html index c11e863429..b4d8c70f11 100644 --- a/src/app/+search-page/search-page.component.html +++ b/src/app/+search-page/search-page.component.html @@ -2,7 +2,7 @@
+ [resultCount]="(resultsRD$ | async)?.payload?.totalElements" [inPlaceSearch]="inPlaceSearch">
this.service.search(options).pipe(getSucceededRemoteData()))) + switchMap((options) => this.service.search(options).pipe(getSucceededRemoteData(), startWith(observableOf(undefined))))) .subscribe((results) => { this.resultsRD$.next(results); }); diff --git a/src/app/+search-page/search-results/search-results.component.html b/src/app/+search-page/search-results/search-results.component.html index d7ecb0357e..824d531155 100644 --- a/src/app/+search-page/search-results/search-results.component.html +++ b/src/app/+search-page/search-results/search-results.component.html @@ -6,7 +6,7 @@ [objects]="searchResults" [hideGear]="true">
- +
{{ 'search.results.no-results' | translate }} diff --git a/src/app/+search-page/search-results/search-results.component.ts b/src/app/+search-page/search-results/search-results.component.ts index c2c86e8a9f..ea6b407ee7 100644 --- a/src/app/+search-page/search-results/search-results.component.ts +++ b/src/app/+search-page/search-results/search-results.component.ts @@ -6,7 +6,7 @@ import { SetViewMode } from '../../shared/view-mode'; import { SearchOptions } from '../search-options.model'; import { SearchResult } from '../search-result.model'; import { PaginatedList } from '../../core/data/paginated-list'; -import { isNotEmpty } from '../../shared/empty.util'; +import { hasNoValue, isNotEmpty } from '../../shared/empty.util'; import { SortOptions } from '../../core/cache/models/sort-options.model'; @Component({ @@ -22,6 +22,8 @@ import { SortOptions } from '../../core/cache/models/sort-options.model'; * Component that represents all results from a search */ export class SearchResultsComponent { + hasNoValue = hasNoValue; + /** * The actual search result objects */ 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 79932805c1..fb95ab8d04 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 @@ -171,20 +171,4 @@ describe('SearchConfigurationService', () => { expect((service as any).routeService.getRouteParameterValue).toHaveBeenCalledWith('filter'); }); }); - - describe('when updateFixedFilter is called', () => { - const filter = 'filter'; - - beforeEach(() => { - service.updateFixedFilter(filter); - }); - - it('should update the paginated search options with the correct fixed filter', () => { - expect(service.paginatedSearchOptions.getValue().fixedFilter).toEqual(filter); - }); - - it('should update the search options with the correct fixed filter', () => { - expect(service.searchOptions.getValue().fixedFilter).toEqual(filter); - }); - }); }); 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 39acd19ccd..14fcdd8d60 100644 --- a/src/app/+search-page/search-service/search-configuration.service.ts +++ b/src/app/+search-page/search-service/search-configuration.service.ts @@ -9,7 +9,7 @@ import { of as observableOf, Subscription } from 'rxjs'; -import { filter, flatMap, map } from 'rxjs/operators'; +import { filter, flatMap, map, switchMap, tap } 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'; @@ -44,7 +44,7 @@ export class SearchConfigurationService implements OnDestroy { /** * Default configuration parameter setting */ - protected defaultConfiguration = 'default'; + protected defaultConfiguration; /** * Default scope setting @@ -99,10 +99,8 @@ export class SearchConfigurationService implements OnDestroy { const defs = defRD.payload; this.paginatedSearchOptions = new BehaviorSubject(defs); this.searchOptions = new BehaviorSubject(defs); - this.subs.push(this.subscribeToSearchOptions(defs)); this.subs.push(this.subscribeToPaginatedSearchOptions(defs)); - } ) } @@ -206,7 +204,7 @@ export class SearchConfigurationService implements OnDestroy { */ getCurrentFixedFilter(): Observable { return this.routeService.getRouteParameterValue('filter').pipe( - flatMap((f) => this.fixedFilterService.getQueryByFilterName(f)) + switchMap((f) => this.fixedFilterService.getQueryByFilterName(f)) ); } @@ -357,21 +355,7 @@ export class SearchConfigurationService implements OnDestroy { isNotEmptyOperator(), map((fixedFilter) => { return { fixedFilter } - }) + }), ); } - - /** - * Update the fixed filter in paginated and non-paginated search options with a given value - * @param {string} fixedFilter - */ - public updateFixedFilter(fixedFilter: string) { - const currentPaginatedValue: PaginatedSearchOptions = this.paginatedSearchOptions.getValue(); - const updatedPaginatedValue: PaginatedSearchOptions = Object.assign(currentPaginatedValue, { fixedFilter: fixedFilter }); - this.paginatedSearchOptions.next(updatedPaginatedValue); - - const currentValue: SearchOptions = this.searchOptions.getValue(); - const updatedValue: SearchOptions = Object.assign(currentValue, { fixedFilter: fixedFilter }); - this.searchOptions.next(updatedValue); - } } diff --git a/src/app/+search-page/search-service/search.service.ts b/src/app/+search-page/search-service/search.service.ts index 598657a1b2..52be0417a8 100644 --- a/src/app/+search-page/search-service/search.service.ts +++ b/src/app/+search-page/search-service/search.service.ts @@ -354,7 +354,10 @@ export class SearchService implements OnDestroy { * @returns {string} The base path to the search page */ getSearchLink(): string { - return '/search'; + const urlTree = this.router.parseUrl(this.router.url); + const g: UrlSegmentGroup = urlTree.root.children[PRIMARY_OUTLET]; + const searchLink: any = '/' + g.toString(); + return (searchLink !== '/search' && searchLink !== '/mydspace') ? '/search' : searchLink; } /** diff --git a/src/app/+search-page/search-settings/search-settings.component.html b/src/app/+search-page/search-settings/search-settings.component.html index d693196dae..7bdbaa73a8 100644 --- a/src/app/+search-page/search-settings/search-settings.component.html +++ b/src/app/+search-page/search-settings/search-settings.component.html @@ -1,3 +1,4 @@ +

{{ 'search.sidebar.settings.title' | translate}}

diff --git a/src/app/+search-page/search-sidebar/search-sidebar.component.html b/src/app/+search-page/search-sidebar/search-sidebar.component.html index 50877052ec..7a5857fcff 100644 --- a/src/app/+search-page/search-sidebar/search-sidebar.component.html +++ b/src/app/+search-page/search-sidebar/search-sidebar.component.html @@ -10,7 +10,7 @@
diff --git a/src/app/+search-page/search-switch-configuration/search-switch-configuration.component.spec.ts b/src/app/+search-page/search-switch-configuration/search-switch-configuration.component.spec.ts index b3efc240e1..602dee33e6 100644 --- a/src/app/+search-page/search-switch-configuration/search-switch-configuration.component.spec.ts +++ b/src/app/+search-page/search-switch-configuration/search-switch-configuration.component.spec.ts @@ -94,7 +94,7 @@ describe('SearchSwitchConfigurationComponent', () => { }); it('should navigate to the route when selecting an option', () => { - (comp as any).searchService.getSearchLink.and.returnValue(MYDSPACE_ROUTE); + spyOn((comp as any), 'getSearchLinkParts').and.returnValue([MYDSPACE_ROUTE]); comp.selectedOption = MyDSpaceConfigurationValueType.Workflow; const navigationExtras: NavigationExtras = { queryParams: {configuration: MyDSpaceConfigurationValueType.Workflow}, diff --git a/src/app/+search-page/search-switch-configuration/search-switch-configuration.component.ts b/src/app/+search-page/search-switch-configuration/search-switch-configuration.component.ts index c34fe20303..1ce1bf84ec 100644 --- a/src/app/+search-page/search-switch-configuration/search-switch-configuration.component.ts +++ b/src/app/+search-page/search-switch-configuration/search-switch-configuration.component.ts @@ -20,6 +20,10 @@ import { SearchService } from '../search-service/search.service'; */ export class SearchSwitchConfigurationComponent implements OnDestroy, OnInit { + /** + * True when the search component should show results on the current page + */ + @Input() inPlaceSearch; /** * The list of available configuration options */ @@ -56,7 +60,7 @@ export class SearchSwitchConfigurationComponent implements OnDestroy, OnInit { queryParams: {configuration: this.selectedOption}, }; - this.router.navigate([this.searchService.getSearchLink()], navigationExtras); + this.router.navigate(this.getSearchLinkParts(), navigationExtras); } /** @@ -77,4 +81,24 @@ export class SearchSwitchConfigurationComponent implements OnDestroy, OnInit { this.sub.unsubscribe(); } } + + /** + * @returns {string} The base path to the search page, or the current page when inPlaceSearch is true + */ + public getSearchLink(): string { + if (this.inPlaceSearch) { + return './'; + } + return this.searchService.getSearchLink(); + } + + /** + * @returns {string[]} The base path to the search page, or the current page when inPlaceSearch is true, split in separate pieces + */ + public getSearchLinkParts(): string[] { + if (this.searchService) { + return []; + } + return this.getSearchLink().split('/'); + } } diff --git a/src/app/app.component.ts b/src/app/app.component.ts index da01b1297a..37cc791558 100644 --- a/src/app/app.component.ts +++ b/src/app/app.component.ts @@ -57,7 +57,6 @@ export class AppComponent implements OnInit, AfterViewInit { private angulartics2GoogleAnalytics: Angulartics2GoogleAnalytics, private authService: AuthService, private router: Router, - private routeService: RouteService, private cssService: CSSVariableService, private menuService: MenuService, private windowService: HostWindowService @@ -77,13 +76,10 @@ export class AppComponent implements OnInit, AfterViewInit { metadata.listenForRouteChange(); - routeService.saveRouting(); - if (config.debug) { console.info(config); } this.storeCSSVariables(); - } ngOnInit() { diff --git a/src/app/core/core.effects.ts b/src/app/core/core.effects.ts index bb25c49a7a..9ade23e6c5 100644 --- a/src/app/core/core.effects.ts +++ b/src/app/core/core.effects.ts @@ -6,6 +6,7 @@ import { AuthEffects } from './auth/auth.effects'; import { JsonPatchOperationsEffects } from './json-patch/json-patch-operations.effects'; import { ServerSyncBufferEffects } from './cache/server-sync-buffer.effects'; import { ObjectUpdatesEffects } from './data/object-updates/object-updates.effects'; +import { RouteEffects } from '../shared/services/route.effects'; export const coreEffects = [ RequestEffects, @@ -14,5 +15,6 @@ export const coreEffects = [ AuthEffects, JsonPatchOperationsEffects, ServerSyncBufferEffects, - ObjectUpdatesEffects + ObjectUpdatesEffects, + RouteEffects ]; diff --git a/src/app/core/core.reducers.ts b/src/app/core/core.reducers.ts index c93b4bf44b..7aecb91a7a 100644 --- a/src/app/core/core.reducers.ts +++ b/src/app/core/core.reducers.ts @@ -13,6 +13,7 @@ import { objectUpdatesReducer, ObjectUpdatesState } from './data/object-updates/object-updates.reducer'; +import { routeReducer, RouteState } from '../shared/services/route.reducer'; export interface CoreState { 'cache/object': ObjectCacheState, @@ -21,7 +22,8 @@ export interface CoreState { 'data/request': RequestState, 'index': MetaIndexState, 'auth': AuthState, - 'json/patch': JsonPatchOperationsState + 'json/patch': JsonPatchOperationsState, + 'route': RouteState } export const coreReducers: ActionReducerMap = { @@ -31,5 +33,6 @@ export const coreReducers: ActionReducerMap = { 'data/request': requestReducer, 'index': indexReducer, 'auth': authReducer, - 'json/patch': jsonPatchOperationsReducer + 'json/patch': jsonPatchOperationsReducer, + 'route': routeReducer }; diff --git a/src/app/core/index/index.actions.ts b/src/app/core/index/index.actions.ts index 98d07d59d5..42804dbe26 100644 --- a/src/app/core/index/index.actions.ts +++ b/src/app/core/index/index.actions.ts @@ -14,7 +14,7 @@ export const IndexActionTypes = { /* tslint:disable:max-classes-per-file */ /** - * An ngrx action to add an value to the index + * An ngrx action to add a value to the index */ export class AddToIndexAction implements Action { type = IndexActionTypes.ADD; @@ -40,7 +40,7 @@ export class AddToIndexAction implements Action { } /** - * An ngrx action to remove an value from the index + * An ngrx action to remove a value from the index */ export class RemoveFromIndexByValueAction implements Action { type = IndexActionTypes.REMOVE_BY_VALUE; 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 ef4660fdd9..a370d3a632 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 @@ -75,7 +75,6 @@ describe('ItemSearchResultListElementComponent', () => { it('should show the relationship type badge', () => { const badge = fixture.debugElement.query(By.css('span.badge')); - console.log(itemSearchResultListElementComponent.dso); expect(badge.nativeElement.textContent).toContain(type.toLowerCase()); }); }); diff --git a/src/app/shared/services/route.actions.ts b/src/app/shared/services/route.actions.ts new file mode 100644 index 0000000000..968319d260 --- /dev/null +++ b/src/app/shared/services/route.actions.ts @@ -0,0 +1,116 @@ +import { Action } from '@ngrx/store'; +import { type } from '../../shared/ngrx/type'; +import { Params } from '@angular/router'; + +/** + * The list of HrefIndexAction type definitions + */ +export const RouteActionTypes = { + SET_QUERY_PARAMETERS: type('dspace/core/route/SET_QUERY_PARAMETERS'), + SET_PARAMETERS: type('dspace/core/route/SET_PARAMETERS'), + ADD_QUERY_PARAMETER: type('dspace/core/route/ADD_QUERY_PARAMETER'), + ADD_PARAMETER: type('dspace/core/route/ADD_PARAMETER'), + RESET: type('dspace/core/route/RESET'), +}; + +/* tslint:disable:max-classes-per-file */ +/** + * An ngrx action to set the query parameters + */ +export class SetQueryParametersAction implements Action { + type = RouteActionTypes.SET_QUERY_PARAMETERS; + payload: Params; + + /** + * Create a new SetQueryParametersAction + * + * @param parameters + * the query parameters + */ + constructor(parameters: Params) { + this.payload = parameters; + } +} + +/** + * An ngrx action to set the parameters + */ +export class SetParametersAction implements Action { + type = RouteActionTypes.SET_PARAMETERS; + payload: Params; + + /** + * Create a new SetParametersAction + * + * @param parameters + * the parameters + */ + constructor(parameters: Params) { + this.payload = parameters; + } +} + +/** + * An ngrx action to add a query parameter + */ +export class AddQueryParameterAction implements Action { + type = RouteActionTypes.ADD_QUERY_PARAMETER; + payload: { + key: string; + value: string; + }; + + /** + * Create a new AddQueryParameterAction + * + * @param key + * the key to add + * @param value + * the value of this key + */ + constructor(key: string, value: string) { + this.payload = { key, value }; + } +} + +/** + * An ngrx action to add a parameter + */ +export class AddParameterAction implements Action { + type = RouteActionTypes.ADD_PARAMETER; + payload: { + key: string; + value: string; + }; + + /** + * Create a new AddParameterAction + * + * @param key + * the key to add + * @param value + * the value of this key + */ + constructor(key: string, value: string) { + this.payload = { key, value }; + } +} + +/** + * An ngrx action to reset the route state + */ +export class ResetRouteStateAction implements Action { + type = RouteActionTypes.RESET; +} + +/* tslint:enable:max-classes-per-file */ + +/** + * A type to encompass all RouteActions + */ +export type RouteActions = + SetQueryParametersAction + | SetParametersAction + | AddQueryParameterAction + | AddParameterAction + | ResetRouteStateAction; diff --git a/src/app/shared/services/route.effects.ts b/src/app/shared/services/route.effects.ts new file mode 100644 index 0000000000..687f8f9921 --- /dev/null +++ b/src/app/shared/services/route.effects.ts @@ -0,0 +1,23 @@ +import { map } from 'rxjs/operators'; +import { Injectable } from '@angular/core'; +import { Actions, Effect, ofType } from '@ngrx/effects' +import * as fromRouter from '@ngrx/router-store'; +import { ResetRouteStateAction } from './route.actions'; + +@Injectable() +export class RouteEffects { + /** + * Effect that resets the route state on reroute + * @type {Observable} + */ + @Effect() routeChange$ = this.actions$ + .pipe( + ofType(fromRouter.ROUTER_NAVIGATION), + map(() => new ResetRouteStateAction()) + ); + + constructor(private actions$: Actions) { + + } + +} diff --git a/src/app/shared/services/route.reducer.ts b/src/app/shared/services/route.reducer.ts new file mode 100644 index 0000000000..b078521c11 --- /dev/null +++ b/src/app/shared/services/route.reducer.ts @@ -0,0 +1,74 @@ +import { Params } from '@angular/router'; +import { + AddParameterAction, + AddQueryParameterAction, + RouteActions, + RouteActionTypes, SetParametersAction, SetQueryParametersAction +} from './route.actions'; + +/** + * Interface to represent the parameter state of a current route in the store + */ +export interface RouteState { + queryParams: Params; + params: Params; +} + +/** + * The initial route state + */ +const initialState: RouteState = { + queryParams: {}, + params: {} +}; + +/** + * Reducer function to save the current route parameters and query parameters in the store + * @param state The current or initial state + * @param action The action to perform on the state + */ +export function routeReducer(state = initialState, action: RouteActions): RouteState { + switch (action.type) { + case RouteActionTypes.RESET: { + return initialState + } + case RouteActionTypes.SET_PARAMETERS: { + return setParameters(state, action as SetParametersAction, 'params'); + } + case RouteActionTypes.SET_QUERY_PARAMETERS: { + return setParameters(state, action as SetQueryParametersAction, 'queryParams'); + } + case RouteActionTypes.ADD_PARAMETER: { + return addParameter(state, action as AddParameterAction, 'params'); + } + case RouteActionTypes.ADD_QUERY_PARAMETER: { + return addParameter(state, action as AddQueryParameterAction, 'queryParams'); + } + default: { + return state; + } + } +} + +/** + * Add a route or query parameter in the store + * @param state The current state + * @param action The add action to perform on the current state + * @param paramType The type of parameter to add: route or query parameter + */ +function addParameter(state: RouteState, action: AddParameterAction | AddQueryParameterAction, paramType: string): RouteState { + const subState = state[paramType]; + const existingValues = subState[action.payload.key] || []; + const newValues = [...existingValues, action.payload.value]; + const newSubstate = Object.assign(subState, { [action.payload.key]: newValues }); + return Object.assign({}, state, { [paramType]: newSubstate }); +} +/** + * Set a route or query parameter in the store + * @param state The current state + * @param action The set action to perform on the current state + * @param paramType The type of parameter to set: route or query parameter + */ +function setParameters(state: RouteState, action: SetParametersAction | SetQueryParametersAction, paramType: string): RouteState { + return Object.assign({}, state, { [paramType]: action.payload }); +} diff --git a/src/app/shared/services/route.service.spec.ts b/src/app/shared/services/route.service.spec.ts index c9b3710ee6..c6003521a7 100644 --- a/src/app/shared/services/route.service.spec.ts +++ b/src/app/shared/services/route.service.spec.ts @@ -42,6 +42,7 @@ describe('RouteService', () => { provide: ActivatedRoute, useValue: { queryParams: observableOf(paramObject), + params: 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 a94b7e56da..dc626484c1 100644 --- a/src/app/shared/services/route.service.ts +++ b/src/app/shared/services/route.service.ts @@ -1,4 +1,4 @@ -import { distinctUntilChanged, filter, map, mergeMap } from 'rxjs/operators'; +import { distinctUntilChanged, filter, map, tap } from 'rxjs/operators'; import { Injectable } from '@angular/core'; import { ActivatedRoute, @@ -8,24 +8,67 @@ import { RouterStateSnapshot, } from '@angular/router'; -import { Observable } from 'rxjs'; -import { select, Store } from '@ngrx/store'; +import { combineLatest, Observable } from 'rxjs'; +import { createSelector, MemoizedSelector, select, Store } from '@ngrx/store'; import { isEqual } from 'lodash'; -import { AppState } from '../../app.reducer'; import { AddUrlToHistoryAction } from '../history/history.actions'; import { historySelector } from '../history/selectors'; +import { SetParametersAction, SetQueryParametersAction } from './route.actions'; +import { CoreState } from '../../core/core.reducers'; +import { hasValue } from '../empty.util'; +import { coreSelector } from '../../core/core.selectors'; + +/** + * Selector to select all route parameters from the store + */ +export const routeParametersSelector = createSelector( + coreSelector, + (state: CoreState) => state.route.params +); + +/** + * Selector to select all query parameters from the store + */ +export const queryParametersSelector = createSelector( + coreSelector, + (state: CoreState) => state.route.queryParams +); + +/** + * Selector to select a specific route parameter from the store + * @param key The key of the parameter + */ +export const routeParameterSelector = (key: string) => parameterSelector(key, routeParametersSelector); + +/** + * Selector to select a specific query parameter from the store + * @param key The key of the parameter + */ +export const queryParameterSelector = (key: string) => parameterSelector(key, queryParametersSelector); + +/** + * Function to select a specific parameter from the store + * @param key The key to look for + * @param paramsSelector The selector that selects the parameters to search in + */ +export function parameterSelector(key: string, paramsSelector: (state: CoreState) => Params): MemoizedSelector { + return createSelector(paramsSelector, (state: Params) => { + if (hasValue(state)) { + return state[key]; + } else { + return undefined; + } + }); +} /** * Service to keep track of the current query parameters */ @Injectable() export class RouteService { - params: Observable; - - constructor(private route: ActivatedRoute, private router: Router, private store: Store) { - this.subscribeToRouterParams(); - + constructor(private route: ActivatedRoute, private router: Router, private store: Store) { + this.saveRouting(); } /** @@ -74,11 +117,11 @@ export class RouteService { } getRouteParameterValue(paramName: string): Observable { - return this.params.pipe(map((params) => params[paramName]),distinctUntilChanged(),); + return this.store.pipe(select(routeParameterSelector(paramName))); } getRouteDataValue(datafield: string): Observable { - return this.route.data.pipe(map((data) => data[datafield]),distinctUntilChanged(),); + return this.route.data.pipe(map((data) => data[datafield]), distinctUntilChanged(),); } /** @@ -114,23 +157,21 @@ export class RouteService { } public saveRouting(): void { - this.router.events - .pipe(filter((event) => event instanceof NavigationEnd)) - .subscribe(({ urlAfterRedirects }: NavigationEnd) => { - this.store.dispatch(new AddUrlToHistoryAction(urlAfterRedirects)) + combineLatest(this.router.events, this.getRouteParams(), this.route.queryParams) + .pipe(filter(([event, params, queryParams]) => event instanceof NavigationEnd)) + .subscribe(([event, params, queryParams]: [NavigationEnd, Params, Params]) => { + this.store.dispatch(new SetParametersAction(params)); + this.store.dispatch(new SetQueryParametersAction(queryParams)); + this.store.dispatch(new AddUrlToHistoryAction(event.urlAfterRedirects)); }); } - subscribeToRouterParams() { - this.params = this.router.events.pipe( - mergeMap((event) => { - let active = this.route; - while (active.firstChild) { - active = active.firstChild; - } - return active.params; - }) - ); + private getRouteParams(): Observable { + let active = this.route; + while (active.firstChild) { + active = active.firstChild; + } + return active.params; } public getHistory(): Observable { diff --git a/src/app/submission/form/collection/submission-form-collection.component.html b/src/app/submission/form/collection/submission-form-collection.component.html index 6547a3cc3c..37ada35155 100644 --- a/src/app/submission/form/collection/submission-form-collection.component.html +++ b/src/app/submission/form/collection/submission-form-collection.component.html @@ -38,7 +38,7 @@ title="{{ listItem.collection.name }}" (click)="onSelect(listItem)">
    -
  • +
  • {{ item.name}}
  • {{ listItem.collection.name}}
  • diff --git a/src/app/submission/form/collection/submission-form-collection.component.ts b/src/app/submission/form/collection/submission-form-collection.component.ts index 2fe424bd3f..b576834091 100644 --- a/src/app/submission/form/collection/submission-form-collection.component.ts +++ b/src/app/submission/form/collection/submission-form-collection.component.ts @@ -237,7 +237,7 @@ export class SubmissionFormCollectionComponent implements OnChanges, OnInit { if (isEmpty(searchTerm)) { return listCollection; } else { - return listCollection.filter((v) => v.collection.name.toLowerCase().indexOf(searchTerm.toLowerCase()) > -1).slice(0, 5) + return listCollection.filter((v) => v.collection.name.toLowerCase().indexOf(searchTerm.toLowerCase()) > -1).slice(0, 5); } })); } diff --git a/yarn.lock b/yarn.lock index 50cf67c8d8..9a4f96e805 100644 --- a/yarn.lock +++ b/yarn.lock @@ -655,6 +655,14 @@ accepts@~1.3.4, accepts@~1.3.5: mime-types "~2.1.18" negotiator "0.6.1" +accepts@~1.3.7: + version "1.3.7" + resolved "https://registry.yarnpkg.com/accepts/-/accepts-1.3.7.tgz#531bc726517a3b2b41f850021c6cc15eaab507cd" + integrity sha512-Il80Qs2WjYlJIBNzNkK6KYqlVMTbZLXgHx2oT0pU/fjRHyEp+PEfEPY0R3WCwAGVOtauxh1hOxNgIf5bv7dQpA== + dependencies: + mime-types "~2.1.24" + negotiator "0.6.2" + 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" @@ -662,11 +670,21 @@ acorn-dynamic-import@^3.0.0: dependencies: acorn "^5.0.0" -acorn@^5.0.0, acorn@^5.3.0, acorn@^5.5.0, acorn@^5.6.2: +acorn-walk@^6.1.1: + version "6.1.1" + resolved "https://registry.yarnpkg.com/acorn-walk/-/acorn-walk-6.1.1.tgz#d363b66f5fac5f018ff9c3a1e7b6f8e310cc3913" + integrity sha512-OtUw6JUTgxA2QoqqmrmQ7F2NYqiBPi/L2jqHyFtllhOUvXYQXf0Z1CYUinIfyT4bTCGmrA7gX9FvHA81uzCoVw== + +acorn@^5.0.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" integrity sha512-cJrKCNcr2kv8dlDnbw+JPUGjHZzo4myaxOLmpOX8a+rgX94YeTcTMv/LFJUSByRpc+i4GgVnnhLxvMu/2Y+rqw== +acorn@^6.0.7: + version "6.1.1" + resolved "https://registry.yarnpkg.com/acorn/-/acorn-6.1.1.tgz#7d25ae05bb8ad1f9b699108e1094ecd7884adc1f" + integrity sha512-jPTiwtOxaHNaAPg/dmrJ/beuzLRnXtB0kQPQ8JpotKJgTB6rX6c8mlf315941pyjBSaPg8NHXS9fhP4u17DpGA== + 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" @@ -1319,13 +1337,14 @@ better-assert@~1.0.0: dependencies: callsite "1.0.0" -bfj-node4@^5.2.0: - version "5.3.1" - resolved "https://registry.yarnpkg.com/bfj-node4/-/bfj-node4-5.3.1.tgz#e23d8b27057f1d0214fc561142ad9db998f26830" - integrity sha512-SOmOsowQWfXc7ybFARsK3C4MCOWzERaOMV/Fl3Tgjs+5dJWyzo3oa127jL44eMbQiAN17J7SvAs2TRxEScTUmg== +bfj@^6.1.1: + version "6.1.1" + resolved "https://registry.yarnpkg.com/bfj/-/bfj-6.1.1.tgz#05a3b7784fbd72cfa3c22e56002ef99336516c48" + integrity sha512-+GUNvzHR4nRyGybQc2WpNJL4MJazMuvf92ueIyA0bIkPRwhhQu3IfZQ2PSoVPpCBJfmoSdOxu5rnotfFLlvYRQ== dependencies: bluebird "^3.5.1" check-types "^7.3.0" + hoopy "^0.1.2" tryer "^1.0.0" big.js@^3.1.3: @@ -1391,6 +1410,22 @@ body-parser@1.18.2: raw-body "2.3.2" type-is "~1.6.15" +body-parser@1.19.0: + version "1.19.0" + resolved "https://registry.yarnpkg.com/body-parser/-/body-parser-1.19.0.tgz#96b2709e57c9c4e09a6fd66a8fd979844f69f08a" + integrity sha512-dhEPs72UPbDnAQJ9ZKMNTP6ptJaionhP5cBb541nXPlW60Jepo9RV/a4fX4XWW9CuFNK22krhrj1+rgzifNCsw== + dependencies: + bytes "3.1.0" + content-type "~1.0.4" + debug "2.6.9" + depd "~1.1.2" + http-errors "1.7.2" + iconv-lite "0.4.24" + on-finished "~2.3.0" + qs "6.7.0" + raw-body "2.4.0" + type-is "~1.6.17" + body-parser@^1.16.1: version "1.18.3" resolved "https://registry.yarnpkg.com/body-parser/-/body-parser-1.18.3.tgz#5b292198ffdd553b3a0f20ded0592b956955c8b4" @@ -1678,6 +1713,11 @@ bytes@3.0.0: resolved "https://registry.yarnpkg.com/bytes/-/bytes-3.0.0.tgz#d32815404d689699f85a4ea4fa8755dd13a96048" integrity sha1-0ygVQE1olpn4Wk6k+odV3ROpYEg= +bytes@3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/bytes/-/bytes-3.1.0.tgz#f6cf7933a360e0588fa9fde85651cdc7f805d1f6" + integrity sha512-zauLjrfCG+xvoyaqLoV8bLVXXNGC4JqlxFCutSDWA6fJrTo2ZuvLYTqZ7aHBLZSMOopbzwv8f+wZcVzfVTI2Dg== + cacache@^10.0.1, cacache@^10.0.4: version "10.0.4" resolved "https://registry.yarnpkg.com/cacache/-/cacache-10.0.4.tgz#6452367999eff9d4188aefd9a14e9d7c6a263460" @@ -1843,16 +1883,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.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" - integrity sha512-ObN6h1v2fTJSmUXoS3nMQ92LbDK9be4TV+6G+omQlGJFdcUX5heKi1LZ1YnRMIgwTLEj3E24bT6tYni50rlCfQ== - dependencies: - ansi-styles "^3.2.1" - escape-string-regexp "^1.0.5" - supports-color "^5.3.0" - -chalk@^2.4.2: +chalk@^2.0.0, chalk@^2.0.1, chalk@^2.1.0, chalk@^2.3.0, chalk@^2.4.1, chalk@^2.4.2: version "2.4.2" resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424" integrity sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ== @@ -2166,11 +2197,16 @@ combined-stream@1.0.6, combined-stream@~1.0.5, combined-stream@~1.0.6: dependencies: delayed-stream "~1.0.0" -commander@2.17.x, commander@^2.12.1, commander@^2.13.0, commander@~2.17.1: +commander@2.17.x, commander@~2.17.1: version "2.17.1" resolved "https://registry.yarnpkg.com/commander/-/commander-2.17.1.tgz#bd77ab7de6de94205ceacc72f1716d29f20a77bf" integrity sha512-wPMUt6FnH2yzG95SA6mzjQOEKUU3aLaDEmzs1ti+1E9h+CsrZghRlqEM/EJ4KscsQVG8uNN4uVreUeT8+drlgg== +commander@^2.12.1, commander@^2.18.0: + version "2.20.0" + resolved "https://registry.yarnpkg.com/commander/-/commander-2.20.0.tgz#d58bb2b5c1ee8f87b0d340027e9e94e222c5a422" + integrity sha512-7j2y+40w61zy6YC2iRNpUe/NwhNyoXrYpHMrSunaMG64nRnaf96zO/KMQR4OyN/UnE5KLyEBnKHd4aG3rskjpQ== + commander@~2.13.0: version "2.13.0" resolved "https://registry.yarnpkg.com/commander/-/commander-2.13.0.tgz#6964bca67685df7c1f1430c584f07d7597885b9c" @@ -2314,6 +2350,13 @@ content-disposition@0.5.2: resolved "https://registry.yarnpkg.com/content-disposition/-/content-disposition-0.5.2.tgz#0cf68bb9ddf5f2be7961c3a85178cb85dba78cb4" integrity sha1-DPaLud318r55YcOoUXjLhdunjLQ= +content-disposition@0.5.3: + version "0.5.3" + resolved "https://registry.yarnpkg.com/content-disposition/-/content-disposition-0.5.3.tgz#e130caf7e7279087c5616c2007d0485698984fbd" + integrity sha512-ExO0774ikEObIAEV9kDo50o+79VCUdEB6n6lzKgGwupcVeRlhrj3qGAfwq8G6uBJjkqLrhT0qEYFcWng8z1z0g== + dependencies: + safe-buffer "5.1.2" + content-type@~1.0.4: version "1.0.4" resolved "https://registry.yarnpkg.com/content-type/-/content-type-1.0.4.tgz#e138cc75e040c727b1966fe5e5f8c9aee256fe3b" @@ -2347,6 +2390,11 @@ cookie@0.3.1: resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.3.1.tgz#e7e0a1f9ef43b4c8ba925c5c5a96e806d16873bb" integrity sha1-5+Ch+e9DtMi6klxcWpboBtFoc7s= +cookie@0.4.0: + version "0.4.0" + resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.4.0.tgz#beb437e7022b3b6d49019d088665303ebe9c14ba" + integrity sha512-+Hp8fLp57wnUSt0tY0tHEXh4voZRDnoIrZPqlo3DPiI4y9lwg/jqx+1Om94/W6ZaPDOUbnjOt/99w66zk+l1Xg== + copy-concurrently@^1.0.0: version "1.0.5" resolved "https://registry.yarnpkg.com/copy-concurrently/-/copy-concurrently-1.0.5.tgz#92297398cae34937fcafd6ec8139c18051f0b5e0" @@ -3164,7 +3212,7 @@ ee-first@1.1.1: resolved "https://registry.yarnpkg.com/ee-first/-/ee-first-1.1.1.tgz#590c61156b0ae2f4f0255732a158b266bc56b21d" integrity sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0= -ejs@^2.5.7: +ejs@^2.6.1: version "2.6.1" resolved "https://registry.yarnpkg.com/ejs/-/ejs-2.6.1.tgz#498ec0d495655abc6f23cd61868d926464071aa0" integrity sha512-0xy4A/twfrRCnkhfk8ErDi5DqdAsAqeGxht4xkCUrsvhhbQNs7E+4jV0CN7+NKIY0aHE72+XvqtBIXzD31ZbXQ== @@ -3624,39 +3672,39 @@ 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" - integrity sha1-avilAjUNsyRuzEvs9rWjTSL37VM= +express@^4.16.2, express@^4.16.3: + version "4.17.1" + resolved "https://registry.yarnpkg.com/express/-/express-4.17.1.tgz#4491fc38605cf51f8629d39c2b5d026f98a4c134" + integrity sha512-mHJ9O79RqluphRrcw2X/GTh3k9tVv8YcoyY4Kkh4WDMUYKRZUq0h1o0w2rrrxBqM7VoeUVqgb27xlEMXTnYt4g== dependencies: - accepts "~1.3.5" + accepts "~1.3.7" array-flatten "1.1.1" - body-parser "1.18.2" - content-disposition "0.5.2" + body-parser "1.19.0" + content-disposition "0.5.3" content-type "~1.0.4" - cookie "0.3.1" + cookie "0.4.0" 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" + finalhandler "~1.1.2" fresh "0.5.2" merge-descriptors "1.0.1" methods "~1.1.2" on-finished "~2.3.0" - parseurl "~1.3.2" + parseurl "~1.3.3" 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" + proxy-addr "~2.0.5" + qs "6.7.0" + range-parser "~1.2.1" + safe-buffer "5.1.2" + send "0.17.1" + serve-static "1.14.1" + setprototypeof "1.1.1" + statuses "~1.5.0" + type-is "~1.6.18" utils-merge "1.0.1" vary "~1.1.2" @@ -3837,7 +3885,7 @@ filename-regex@^2.0.0: resolved "https://registry.yarnpkg.com/filename-regex/-/filename-regex-2.0.1.tgz#c1c4b9bee3e09725ddb106b75c1e301fe2f18b26" integrity sha1-wcS5vuPglyXdsQa3XB4wH+LxiyY= -filesize@^3.5.11: +filesize@^3.6.1: version "3.6.1" resolved "https://registry.yarnpkg.com/filesize/-/filesize-3.6.1.tgz#090bb3ee01b6f801a8a8be99d31710b3422bb317" integrity sha512-7KjR1vv6qnicaPMi1iiTcI85CyYwRO/PSFCu6SvqL8jN2Wjt/NIYQTFtFs7fSDCYOstUkEWIQGFUg5YZQfjlcg== @@ -3876,17 +3924,17 @@ 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" - integrity sha512-Y1GUDo39ez4aHAw7MysnUD5JzYX+WaIj8I57kO3aEPT1fFRL4sr7mjei97FgnwhAyyzRYmQZaTHb2+9uZ1dPtg== +finalhandler@~1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/finalhandler/-/finalhandler-1.1.2.tgz#b7e7d000ffd11938d0fdb053506f6ebabe9f587d" + integrity sha512-aAWcW57uxVNrQZqFXjITpW3sIUQmHGG3qSb9mUah9MgMC4NeWhNOlNjXEYq3HjRAvL6arUviZGGJsBg6z0zsWA== 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" + parseurl "~1.3.3" + statuses "~1.5.0" unpipe "~1.0.0" find-cache-dir@^1.0.0: @@ -4367,13 +4415,13 @@ gulplog@^1.0.0: dependencies: glogg "^1.0.0" -gzip-size@^4.1.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/gzip-size/-/gzip-size-4.1.0.tgz#8ae096257eabe7d69c45be2b67c448124ffb517c" - integrity sha1-iuCWJX6r59acRb4rZ8RIEk/7UXw= +gzip-size@^5.0.0: + version "5.1.1" + resolved "https://registry.yarnpkg.com/gzip-size/-/gzip-size-5.1.1.tgz#cb9bee692f87c0612b232840a873904e4c135274" + integrity sha512-FNHi6mmoHvs1mxZAds4PpdCS6QG8B4C1krxJsMutgxl5t3+GlRTzzI3NEkifXx2pVsOvJdOGSmIgDhQ55FwdPA== dependencies: duplexer "^0.1.1" - pify "^3.0.0" + pify "^4.0.1" handle-thing@^1.2.5: version "1.2.5" @@ -4566,6 +4614,11 @@ homedir-polyfill@^1.0.1: dependencies: parse-passwd "^1.0.0" +hoopy@^0.1.2: + version "0.1.4" + resolved "https://registry.yarnpkg.com/hoopy/-/hoopy-0.1.4.tgz#609207d661100033a9a9402ad3dea677381c1b1d" + integrity sha512-HRcs+2mr52W0K+x8RzcLzuPPmVIKMSv97RGHy0Ea9y/mpcaK+xTrjICA04KAHi4GRzxliNqNJEFYWHghy3rSfQ== + 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" @@ -4662,6 +4715,17 @@ http-errors@1.6.3, http-errors@~1.6.2, http-errors@~1.6.3: setprototypeof "1.1.0" statuses ">= 1.4.0 < 2" +http-errors@1.7.2, http-errors@~1.7.2: + version "1.7.2" + resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-1.7.2.tgz#4f5029cf13239f31036e5b2e55292bcfbcc85c8f" + integrity sha512-uUQBt3H/cSIVfch6i1EuPNy/YsRSOUBXTVfZ+yR7Zjez3qjBz6i9+i4zjNaoqcoFVI4lQJ5plg63TvGfRSDCRg== + dependencies: + depd "~1.1.2" + inherits "2.0.3" + setprototypeof "1.1.1" + statuses ">= 1.5.0 < 2" + toidentifier "1.0.0" + 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" @@ -4739,7 +4803,7 @@ iconv-lite@0.4.23: dependencies: safer-buffer ">= 2.1.2 < 3" -iconv-lite@^0.4.17, iconv-lite@^0.4.24, iconv-lite@^0.4.4, iconv-lite@~0.4.13: +iconv-lite@0.4.24, 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" integrity sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA== @@ -4961,6 +5025,11 @@ ipaddr.js@1.8.0: resolved "https://registry.yarnpkg.com/ipaddr.js/-/ipaddr.js-1.8.0.tgz#eaa33d6ddd7ace8f7f6fe0c9ca0440e706738b1e" integrity sha1-6qM9bd16zo9/b+DJygRA5wZzix4= +ipaddr.js@1.9.0: + version "1.9.0" + resolved "https://registry.yarnpkg.com/ipaddr.js/-/ipaddr.js-1.9.0.tgz#37df74e430a0e47550fe54a2defe30d8acd95f65" + integrity sha512-M4Sjn6N/+O6/IXSJseKqHoFc+5FdGJ22sXqnjTpdZweHK64MzEPAyQZyEU3R/KRv2GLoa7nNtg/C2Ev6m7z+eA== + ipaddr.js@^1.5.2: version "1.8.1" resolved "https://registry.yarnpkg.com/ipaddr.js/-/ipaddr.js-1.8.1.tgz#fa4b79fa47fd3def5e3b159825161c0a519c9427" @@ -6402,6 +6471,11 @@ miller-rabin@^4.0.0: bn.js "^4.0.0" brorand "^1.0.1" +mime-db@1.40.0: + version "1.40.0" + resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.40.0.tgz#a65057e998db090f732a68f6c276d387d4126c32" + integrity sha512-jYdeOMPy9vnxEqFRRo6ZvTZ8d9oPb+k18PKoYNYUe2stVEBPPwsln/qWzdbmaIvnhZ9v2P+CuecK+fpUfsV2mA== + "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" @@ -6414,12 +6488,19 @@ mime-types@^2.1.12, mime-types@~2.1.17, mime-types@~2.1.18, mime-types@~2.1.19: dependencies: mime-db "~1.36.0" +mime-types@~2.1.24: + version "2.1.24" + resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.24.tgz#b6f8d0b3e951efb77dedeca194cff6d16f676f81" + integrity sha512-WaFHS3MCl5fapm3oLxU4eYDw77IQM2ACcxQ9RIxfaC3ooc6PFuBMGZZsYpvoXS5D5QTWPieo1jjLdAm3TBP3cQ== + dependencies: + mime-db "1.40.0" + mime@1.4.1: version "1.4.1" resolved "https://registry.yarnpkg.com/mime/-/mime-1.4.1.tgz#121f9ebc49e3766f311a76e1fa1c8003c4b03aa6" integrity sha512-KI1+qOZu5DcW6wayYHSzR/tXKCDC5Om4s1z2QJjDULzLcmf3DvzS7oluY4HCTrc+9FiKmWUgeNLg7W3uIQvxtQ== -mime@^1.6.0: +mime@1.6.0, mime@^1.6.0: version "1.6.0" resolved "https://registry.yarnpkg.com/mime/-/mime-1.6.0.tgz#32cd9e5c64553bd58d19a568af452acff04981b1" integrity sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg== @@ -6558,6 +6639,11 @@ ms@2.0.0: resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8" integrity sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g= +ms@2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.1.tgz#30a5864eb3ebb0a66f2ebe6d727af06a09d86e0a" + integrity sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg== + multicast-dns-service-types@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/multicast-dns-service-types/-/multicast-dns-service-types-1.1.0.tgz#899f11d9686e5e05cb91b35d5f0e63b773cfc901" @@ -6619,6 +6705,11 @@ negotiator@0.6.1: resolved "https://registry.yarnpkg.com/negotiator/-/negotiator-0.6.1.tgz#2b327184e8992101177b28563fb5e7102acd0ca9" integrity sha1-KzJxhOiZIQEXeyhWP7XnECrNDKk= +negotiator@0.6.2: + version "0.6.2" + resolved "https://registry.yarnpkg.com/negotiator/-/negotiator-0.6.2.tgz#feacf7ccf525a77ae9634436a64883ffeca346fb" + integrity sha512-hZXc7K2e+PgeI1eDBe/10Ard4ekbfrrqG8Ep+8Jmf4JID2bNg7NvCPOZN+kfF574pFQI7mum2AUqDidoKqcTOw== + neo-async@^2.5.0: version "2.5.2" resolved "https://registry.yarnpkg.com/neo-async/-/neo-async-2.5.2.tgz#489105ce7bc54e709d736b195f82135048c50fcc" @@ -7117,7 +7208,7 @@ opencollective@^1.0.3: node-fetch "1.6.3" opn "4.0.2" -opener@^1.4.3: +opener@^1.5.1: version "1.5.1" resolved "https://registry.yarnpkg.com/opener/-/opener-1.5.1.tgz#6d2f0e77f1a0af0032aca716c2c1fbb8e7e8abed" integrity sha512-goYSy5c2UXE4Ra1xixabeVh1guIX/ZV/YokJksb6q2lubWu6UbvPQ20p542/sFIll1nl8JnCyK9oBaOcCWXwvA== @@ -7355,6 +7446,11 @@ parseurl@~1.3.2: resolved "https://registry.yarnpkg.com/parseurl/-/parseurl-1.3.2.tgz#fc289d4ed8993119460c156253262cdc8de65bf3" integrity sha1-/CidTtiZMRlGDBViUyYs3I3mW/M= +parseurl@~1.3.3: + version "1.3.3" + resolved "https://registry.yarnpkg.com/parseurl/-/parseurl-1.3.3.tgz#9da19e7bee8d12dff0513ed5b76957793bc2e8d4" + integrity sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ== + pascalcase@^0.1.1: version "0.1.1" resolved "https://registry.yarnpkg.com/pascalcase/-/pascalcase-0.1.1.tgz#b363e55e8006ca6fe21784d2db22bd15d7917f14" @@ -7486,6 +7582,11 @@ pify@^3.0.0: resolved "https://registry.yarnpkg.com/pify/-/pify-3.0.0.tgz#e5a4acd2c101fdf3d9a4d07f0dbc4db49dd28176" integrity sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY= +pify@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/pify/-/pify-4.0.1.tgz#4b2cd25c50d598735c50292224fd8c6df41e3231" + integrity sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g== + pinkie-promise@^2.0.0: version "2.0.1" resolved "https://registry.yarnpkg.com/pinkie-promise/-/pinkie-promise-2.0.1.tgz#2135d6dfa7a358c069ac9b178776288228450ffa" @@ -8347,7 +8448,7 @@ protractor@^5.3.0: webdriver-js-extender "2.0.0" webdriver-manager "^12.0.6" -proxy-addr@~2.0.2, proxy-addr@~2.0.3: +proxy-addr@~2.0.2: version "2.0.4" resolved "https://registry.yarnpkg.com/proxy-addr/-/proxy-addr-2.0.4.tgz#ecfc733bf22ff8c6f407fa275327b9ab67e48b93" integrity sha512-5erio2h9jp5CHGwcybmxmVqHmnCBZeewlfJ0pex+UW7Qny7OOZXTtH56TGNyBizkgiOwhJtMKrVzDTeKcySZwA== @@ -8355,6 +8456,14 @@ proxy-addr@~2.0.2, proxy-addr@~2.0.3: forwarded "~0.1.2" ipaddr.js "1.8.0" +proxy-addr@~2.0.5: + version "2.0.5" + resolved "https://registry.yarnpkg.com/proxy-addr/-/proxy-addr-2.0.5.tgz#34cbd64a2d81f4b1fd21e76f9f06c8a45299ee34" + integrity sha512-t/7RxHXPH6cJtP0pRG6smSr9QJidhB+3kXu0KgXnbGYMgzEnUxRQ4/LDdfOwZEMyIh3/xHb8PX3t+lfL9z+YVQ== + dependencies: + forwarded "~0.1.2" + ipaddr.js "1.9.0" + prr@~1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/prr/-/prr-1.0.1.tgz#d3fc114ba06995a45ec6893f484ceb1d78f5f476" @@ -8452,6 +8561,11 @@ qs@6.5.2, qs@~6.5.1, qs@~6.5.2: resolved "https://registry.yarnpkg.com/qs/-/qs-6.5.2.tgz#cb3ae806e8740444584ef154ce8ee98d403f3e36" integrity sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA== +qs@6.7.0: + version "6.7.0" + resolved "https://registry.yarnpkg.com/qs/-/qs-6.7.0.tgz#41dc1a015e3d581f1621776be31afb2876a9b1bc" + integrity sha512-VCdBRNFTX1fyE7Nb6FYoURo/SPe62QCaAyzJvUjwRaIsc+NePBEniHlvxFmmX56+HZphIGtV0XeCirBtpDrTyQ== + qs@~2.3.3: version "2.3.3" resolved "https://registry.yarnpkg.com/qs/-/qs-2.3.3.tgz#e9e85adbe75da0bbe4c8e0476a086290f863b404" @@ -8506,6 +8620,11 @@ range-parser@^1.0.3, range-parser@^1.2.0, range-parser@~1.2.0: resolved "https://registry.yarnpkg.com/range-parser/-/range-parser-1.2.0.tgz#f49be6b487894ddc40dcc94a322f611092e00d5e" integrity sha1-9JvmtIeJTdxA3MlKMi9hEJLgDV4= +range-parser@~1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/range-parser/-/range-parser-1.2.1.tgz#3cf37023d199e1c24d1a55b84800c2f3e6468031" + integrity sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg== + raw-body@2.3.2: version "2.3.2" resolved "https://registry.yarnpkg.com/raw-body/-/raw-body-2.3.2.tgz#bcd60c77d3eb93cde0050295c3f379389bc88f89" @@ -8526,6 +8645,16 @@ raw-body@2.3.3: iconv-lite "0.4.23" unpipe "1.0.0" +raw-body@2.4.0: + version "2.4.0" + resolved "https://registry.yarnpkg.com/raw-body/-/raw-body-2.4.0.tgz#a1ce6fb9c9bc356ca52e89256ab59059e13d0332" + integrity sha512-4Oz8DUIwdvoa5qMJelxipzi/iJIi40O5cGV1wNYp5hvZP8ZN0T+jiNkL0QepXs+EsQ9XJ8ipEDoiH70ySUJP3Q== + dependencies: + bytes "3.1.0" + http-errors "1.7.2" + iconv-lite "0.4.24" + 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" @@ -9284,10 +9413,10 @@ 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" - integrity sha512-E64YFPUssFHEFBvpbbjr44NCLtI1AohxQ8ZSiJjQLskAdKuriYEP6VyGEsRDH8ScozGpkaX1BGvhanqCwkcEZw== +send@0.17.1: + version "0.17.1" + resolved "https://registry.yarnpkg.com/send/-/send-0.17.1.tgz#c1d8b059f7900f7466dd4938bdc44e11ddb376c8" + integrity sha512-BsVKsiGcQMFwT8UxypobUKyv7irCNRHk1T0G680vk88yf6LBByGcZJOTJCrTP2xVN6yI+XjPJcNuE3V4fT9sAg== dependencies: debug "2.6.9" depd "~1.1.2" @@ -9296,12 +9425,12 @@ send@0.16.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" + http-errors "~1.7.2" + mime "1.6.0" + ms "2.1.1" on-finished "~2.3.0" - range-parser "~1.2.0" - statuses "~1.4.0" + range-parser "~1.2.1" + statuses "~1.5.0" serialize-javascript@^1.4.0: version "1.5.0" @@ -9331,15 +9460,15 @@ 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" - integrity sha512-p/tdJrO4U387R9oMjb1oj7qSMaMfmOyd4j9hOFoxZe2baQszgHcSWjuya/CiT5kgZZKRudHNOA0pYXOl8rQ5nw== +serve-static@1.14.1: + version "1.14.1" + resolved "https://registry.yarnpkg.com/serve-static/-/serve-static-1.14.1.tgz#666e636dc4f010f7ef29970a88a674320898b2f9" + integrity sha512-JMrvUwE54emCYWlTI+hGrGv5I8dEwmco/00EvkzIIsR7MqrHonbD9pO2MOfFnpFntl7ecpZs+3mW+XbQZu9QCg== dependencies: encodeurl "~1.0.2" escape-html "~1.0.3" - parseurl "~1.3.2" - send "0.16.2" + parseurl "~1.3.3" + send "0.17.1" set-blocking@^2.0.0, set-blocking@~2.0.0: version "2.0.0" @@ -9386,6 +9515,11 @@ setprototypeof@1.1.0: resolved "https://registry.yarnpkg.com/setprototypeof/-/setprototypeof-1.1.0.tgz#d0bd85536887b6fe7c0d818cb962d9d91c54e656" integrity sha512-BvE/TwpZX4FXExxOxZyRGQQv651MSwmWKZGqvmPcRIjDqWub67kTKuIMx43cZZrS/cBBzwBcNDWoFxt2XEFIpQ== +setprototypeof@1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/setprototypeof/-/setprototypeof-1.1.1.tgz#7e95acb24aa92f5885e0abef5ba131330d4ae683" + integrity sha512-JvdAWfbXeIGaZ9cILp38HntZSFSo3mWg6xGcJJsd+d4aRMOqauag1C63dJfDw7OaMYwEbHMOxEZ1lqVRYP2OAw== + 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" @@ -9783,7 +9917,7 @@ static-extend@^0.1.1: define-property "^0.2.5" object-copy "^0.1.0" -"statuses@>= 1.3.1 < 2", "statuses@>= 1.4.0 < 2": +"statuses@>= 1.3.1 < 2", "statuses@>= 1.4.0 < 2", "statuses@>= 1.5.0 < 2", statuses@~1.5.0: version "1.5.0" resolved "https://registry.yarnpkg.com/statuses/-/statuses-1.5.0.tgz#161c7dac177659fd9811f43771fa99381478628c" integrity sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow= @@ -9793,11 +9927,6 @@ statuses@~1.3.1: resolved "https://registry.yarnpkg.com/statuses/-/statuses-1.3.1.tgz#faf51b9eb74aaef3b3acf4ad5f61abf24cb7b93e" integrity sha1-+vUbnrdKrvOzrPStX2Gr8ky3uT4= -statuses@~1.4.0: - version "1.4.0" - resolved "https://registry.yarnpkg.com/statuses/-/statuses-1.4.0.tgz#bb73d446da2796106efcc1b601a253d6c46bd087" - integrity sha512-zhSCtt8v2NDrRlPQpCNtw/heZLtfUDqxBM1udqikb/Hbk52LK4nQSwr10u77iopCW5LsyHpuXS0GnEc48mLeew== - stdout-stream@^1.4.0: version "1.4.1" resolved "https://registry.yarnpkg.com/stdout-stream/-/stdout-stream-1.4.1.tgz#5ac174cdd5cd726104aa0c0b2bd83815d8d535de" @@ -10200,6 +10329,11 @@ to-string-loader@1.1.5: dependencies: loader-utils "^0.2.16" +toidentifier@1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/toidentifier/-/toidentifier-1.0.0.tgz#7e1be3470f1e77948bc43d94a3c8f4d7752ba553" + integrity sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw== + touch@^3.1.0: version "3.1.0" resolved "https://registry.yarnpkg.com/touch/-/touch-3.1.0.tgz#fe365f5f75ec9ed4e56825e0bb76d24ab74af83b" @@ -10369,6 +10503,14 @@ type-is@~1.6.15, type-is@~1.6.16: media-typer "0.3.0" mime-types "~2.1.18" +type-is@~1.6.17, type-is@~1.6.18: + version "1.6.18" + resolved "https://registry.yarnpkg.com/type-is/-/type-is-1.6.18.tgz#4e552cd05df09467dcbc4ef739de89f2cf37c131" + integrity sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g== + dependencies: + media-typer "0.3.0" + mime-types "~2.1.24" + typedarray@^0.0.6: version "0.0.6" resolved "https://registry.yarnpkg.com/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777" @@ -10844,23 +10986,24 @@ webfontloader@1.6.28: resolved "https://registry.yarnpkg.com/webfontloader/-/webfontloader-1.6.28.tgz#db786129253cb6e8eae54c2fb05f870af6675bae" integrity sha1-23hhKSU8tujq5UwvsF+HCvZnW64= -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" - integrity sha512-rwxyfecTAxoarCC9VlHlIpfQCmmJ/qWD5bpbjkof+7HrNhTNZIwZITxN6CdlYL2axGmwNUQ+tFgcSOiNXMf/sQ== +webpack-bundle-analyzer@^3.3.2: + version "3.3.2" + resolved "https://registry.yarnpkg.com/webpack-bundle-analyzer/-/webpack-bundle-analyzer-3.3.2.tgz#3da733a900f515914e729fcebcd4c40dde71fc6f" + integrity sha512-7qvJLPKB4rRWZGjVp5U1KEjwutbDHSKboAl0IfafnrdXMrgC0tOtZbQD6Rw0u4cmpgRN4O02Fc0t8eAT+FgGzA== dependencies: - acorn "^5.3.0" - bfj-node4 "^5.2.0" - chalk "^2.3.0" - commander "^2.13.0" - ejs "^2.5.7" - express "^4.16.2" - filesize "^3.5.11" - gzip-size "^4.1.0" - lodash "^4.17.4" + acorn "^6.0.7" + acorn-walk "^6.1.1" + bfj "^6.1.1" + chalk "^2.4.1" + commander "^2.18.0" + ejs "^2.6.1" + express "^4.16.3" + filesize "^3.6.1" + gzip-size "^5.0.0" + lodash "^4.17.10" mkdirp "^0.5.1" - opener "^1.4.3" - ws "^4.0.0" + opener "^1.5.1" + ws "^6.0.0" webpack-cli@^3.1.0: version "3.1.0" @@ -11101,13 +11244,12 @@ write-file-atomic@^2.0.0: imurmurhash "^0.1.4" signal-exit "^3.0.2" -ws@^4.0.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/ws/-/ws-4.1.0.tgz#a979b5d7d4da68bf54efe0408967c324869a7289" - integrity sha512-ZGh/8kF9rrRNffkLFV4AzhvooEclrOH0xaugmqGsIfFgOE/pIz4fMc4Ef+5HSQqTEug2S9JZIWDR47duDSLfaA== +ws@^6.0.0: + version "6.2.1" + resolved "https://registry.yarnpkg.com/ws/-/ws-6.2.1.tgz#442fdf0a47ed64f59b6a5d8ff130f4748ed524fb" + integrity sha512-GIyAXC2cB7LjvpgMt9EKS2ldqr0MTrORaleiOno6TweZ6r3TKtoFQWay/2PceJ3RuBasOHzXNn5Lrw1X0bEjqA== dependencies: async-limiter "~1.0.0" - safe-buffer "~5.1.0" ws@~3.3.1: version "3.3.3"