metadata service

This commit is contained in:
William Welling
2017-10-12 19:08:03 -05:00
parent c9338e2626
commit f4c0df176e
25 changed files with 1018 additions and 170 deletions

View File

@@ -12,15 +12,14 @@
},
"scripts": {
"global": "npm install -g @angular/cli marked node-gyp nodemon node-nightly npm-check-updates npm-run-all rimraf typescript ts-node typedoc webpack webpack-bundle-analyzer pm2 rollup",
"clean:coverage": "yarn run rimraf coverage",
"clean:dist": "yarn run rimraf dist",
"clean:doc": "yarn run rimraf doc",
"clean:log": "yarn run rimraf *.log*",
"clean:json": "yarn run rimraf *.records.json",
"clean:node": "yarn run rimraf node_modules",
"clean:coverage": "rimraf coverage",
"clean:dist": "rimraf dist",
"clean:doc": "rimraf doc",
"clean:log": "rimraf *.log*",
"clean:json": "rimraf *.records.json",
"clean:node": "rimraf node_modules",
"clean:prod": "yarn run clean:coverage && yarn run clean:doc && yarn run clean:dist && yarn run clean:log && yarn run clean:json",
"clean": "yarn run clean:prod && yarn run clean:node",
"rimraf": "rimraf",
"prebuild": "yarn run clean:dist",
"prebuild:aot": "yarn run prebuild",
"prebuild:prod": "yarn run prebuild",
@@ -69,15 +68,15 @@
"coverage": "http-server -c-1 -o -p 9875 ./coverage"
},
"dependencies": {
"@angular/animations": "4.4.4",
"@angular/common": "4.4.4",
"@angular/core": "4.4.4",
"@angular/forms": "4.4.4",
"@angular/http": "4.4.4",
"@angular/platform-browser": "4.4.4",
"@angular/platform-browser-dynamic": "4.4.4",
"@angular/platform-server": "4.4.4",
"@angular/router": "4.4.4",
"@angular/animations": "4.4.5",
"@angular/common": "4.4.5",
"@angular/core": "4.4.5",
"@angular/forms": "4.4.5",
"@angular/http": "4.4.5",
"@angular/platform-browser": "4.4.5",
"@angular/platform-browser-dynamic": "4.4.5",
"@angular/platform-server": "4.4.5",
"@angular/router": "4.4.5",
"@angularclass/bootloader": "1.0.1",
"@angularclass/idle-preload": "1.0.4",
"@ng-bootstrap/ng-bootstrap": "1.0.0-beta.5",
@@ -89,11 +88,11 @@
"@ngx-translate/http-loader": "2.0.0",
"body-parser": "1.18.2",
"bootstrap": "v4.0.0-beta",
"cerialize": "0.1.16",
"cerialize": "0.1.18",
"compression": "1.7.1",
"cookie-parser": "1.4.3",
"core-js": "2.5.1",
"express": "4.16.1",
"express": "4.16.2",
"express-session": "1.15.6",
"font-awesome": "4.7.0",
"http-server": "0.10.0",
@@ -103,7 +102,7 @@
"methods": "1.1.2",
"morgan": "1.9.0",
"ngx-pagination": "3.0.1",
"pem": "1.12.2",
"pem": "1.12.3",
"reflect-metadata": "0.1.10",
"rxjs": "5.4.3",
"ts-md5": "1.2.2",
@@ -111,10 +110,10 @@
"zone.js": "0.8.18"
},
"devDependencies": {
"@angular/compiler": "4.4.4",
"@angular/compiler-cli": "4.4.4",
"@angular/compiler": "4.4.5",
"@angular/compiler-cli": "4.4.5",
"@ngrx/store-devtools": "4.0.0",
"@ngtools/webpack": "1.7.2",
"@ngtools/webpack": "1.7.4",
"@types/cookie-parser": "1.4.1",
"@types/deep-freeze": "0.1.1",
"@types/express": "4.0.37",
@@ -168,13 +167,13 @@
"postcss-apply": "0.8.0",
"postcss-cli": "4.1.1",
"postcss-cssnext": "3.0.2",
"postcss-loader": "2.0.6",
"postcss-loader": "2.0.7",
"postcss-responsive-type": "1.0.0",
"postcss-smart-import": "0.7.5",
"protractor": "5.1.2",
"protractor-istanbul-plugin": "2.0.0",
"raw-loader": "0.5.1",
"resolve-url-loader": "2.1.0",
"resolve-url-loader": "2.1.1",
"rimraf": "2.6.2",
"rollup": "0.50.0",
"rollup-plugin-commonjs": "8.2.1",
@@ -191,7 +190,7 @@
"tslint": "5.7.0",
"typedoc": "0.9.0",
"typescript": "2.5.3",
"webpack": "3.6.0",
"webpack": "3.7.1",
"webpack-bundle-analyzer": "2.9.0",
"webpack-dev-middleware": "1.12.0",
"webpack-dev-server": "2.9.1",

View File

@@ -2,12 +2,15 @@ import { NgModule } from '@angular/core';
import { RouterModule } from '@angular/router';
import { CollectionPageComponent } from './collection-page.component';
import { NormalizedCollection } from '../core/cache/models/normalized-collection.model';
@NgModule({
imports: [
RouterModule.forChild([
{ path: ':id', component: CollectionPageComponent, pathMatch: 'full' }
{ path: ':id', component: CollectionPageComponent, pathMatch: 'full', data: { type: NormalizedCollection } }
])
]
})
export class CollectionPageRoutingModule { }
export class CollectionPageRoutingModule {
}

View File

@@ -2,12 +2,15 @@ import { NgModule } from '@angular/core';
import { RouterModule } from '@angular/router';
import { CommunityPageComponent } from './community-page.component';
import { NormalizedCommunity } from '../core/cache/models/normalized-community.model';
@NgModule({
imports: [
RouterModule.forChild([
{ path: ':id', component: CommunityPageComponent, pathMatch: 'full' }
{ path: ':id', component: CommunityPageComponent, pathMatch: 'full', data: { type: NormalizedCommunity } }
])
]
})
export class CommunityPageRoutingModule { }
export class CommunityPageRoutingModule {
}

View File

@@ -3,12 +3,13 @@ import { RouterModule } from '@angular/router';
import { ItemPageComponent } from './simple/item-page.component';
import { FullItemPageComponent } from './full/full-item-page.component';
import { NormalizedItem } from '../core/cache/models/normalized-item.model';
@NgModule({
imports: [
RouterModule.forChild([
{ path: ':id', component: ItemPageComponent, pathMatch: 'full' },
{ path: ':id/full', component: FullItemPageComponent }
{ path: ':id', component: ItemPageComponent, pathMatch: 'full', data: { type: NormalizedItem } },
{ path: ':id/full', component: FullItemPageComponent, data: { type: NormalizedItem } }
])
]
})

View File

@@ -104,7 +104,7 @@ describe('SearchPageComponent', () => {
(comp as any).updateSearchResults({});
expect(comp.results as any).toBe(mockResults);
});
});
});
});

View File

@@ -1,4 +1,3 @@
// ... test imports
import {
async,
ComponentFixture,
@@ -23,14 +22,18 @@ import { AppComponent } from './app.component';
import { HostWindowState } from './shared/host-window.reducer';
import { HostWindowResizeAction } from './shared/host-window.actions';
import { MockTranslateLoader } from './shared/testing/mock-translate-loader';
import { BrowserTransferStateModule } from '../modules/transfer-state/browser-transfer-state.module';
import { BrowserTransferStoreModule } from '../modules/transfer-store/browser-transfer-store.module';
import { MetadataService } from './core/metadata/metadata.service';
import { GLOBAL_CONFIG, ENV_CONFIG } from '../config';
import { NativeWindowRef, NativeWindowService } from './shared/window.service';
import { MockTranslateLoader } from './shared/mocks/mock-translate-loader';
import { MockMetadataService } from './shared/mocks/mock-metadata-service';
let comp: AppComponent;
let fixture: ComponentFixture<AppComponent>;
let de: DebugElement;
@@ -57,6 +60,7 @@ describe('App component', () => {
providers: [
{ provide: GLOBAL_CONFIG, useValue: ENV_CONFIG },
{ provide: NativeWindowService, useValue: new NativeWindowRef() },
{ provide: MetadataService, useValue: new MockMetadataService() },
AppComponent
],
schemas: [CUSTOM_ELEMENTS_SCHEMA]

View File

@@ -12,12 +12,10 @@ import { TranslateService } from '@ngx-translate/core';
import { Store } from '@ngrx/store';
import { TransferState } from '../modules/transfer-state/transfer-state';
import { HostWindowState } from './shared/host-window.reducer';
import { HostWindowResizeAction } from './shared/host-window.actions';
import { NativeWindowRef, NativeWindowService } from './shared/window.service';
import { MetadataService } from './core/metadata/metadata.service';
import { GLOBAL_CONFIG, GlobalConfig } from '../config';
@@ -35,13 +33,16 @@ export class AppComponent implements OnInit {
@Inject(NativeWindowService) private _window: NativeWindowRef,
private translate: TranslateService,
private cache: TransferState,
private store: Store<HostWindowState>
private store: Store<HostWindowState>,
private metadata: MetadataService
) {
// this language will be used as a fallback when a translation isn't found in the current language
translate.setDefaultLang('en');
// the lang to use, if the lang isn't available, it will use the current loader to get them
translate.use('en');
metadata.listenForRouteChange();
if (config.debug) {
console.info(config);
}

View File

@@ -1,29 +1,35 @@
import { NgModule, Optional, SkipSelf, ModuleWithProviders } from '@angular/core';
import {
NgModule,
Optional,
SkipSelf,
ModuleWithProviders
} from '@angular/core';
import { CommonModule } from '@angular/common';
import { isNotEmpty } from '../shared/empty.util';
import { DSpaceRESTv2Service } from './dspace-rest-v2/dspace-rest-v2.service';
import { ObjectCacheService } from './cache/object-cache.service';
import { ResponseCacheService } from './cache/response-cache.service';
import { CollectionDataService } from './data/collection-data.service';
import { ItemDataService } from './data/item-data.service';
import { RequestService } from './data/request.service';
import { RemoteDataBuildService } from './cache/builders/remote-data-build.service';
import { CommunityDataService } from './data/community-data.service';
import { PaginationComponentOptions } from '../shared/pagination/pagination-component-options.model';
import { coreEffects } from './core.effects';
import { EffectsModule } from '@ngrx/effects';
import { StoreModule } from '@ngrx/store';
import { EffectsModule } from '@ngrx/effects';
import { coreEffects } from './core.effects';
import { coreReducers } from './core.reducers';
import { DSOResponseParsingService } from './data/dso-response-parsing.service';
import { RootResponseParsingService } from './data/root-response-parsing.service';
import { isNotEmpty } from '../shared/empty.util';
import { ApiService } from '../shared/api.service';
import { CollectionDataService } from './data/collection-data.service';
import { CommunityDataService } from './data/community-data.service';
import { DSOResponseParsingService } from './data/dso-response-parsing.service';
import { DSpaceRESTv2Service } from './dspace-rest-v2/dspace-rest-v2.service';
import { HostWindowService } from '../shared/host-window.service';
import { NativeWindowFactory, NativeWindowService } from '../shared/window.service';
import { ItemDataService } from './data/item-data.service';
import { MetadataService } from './metadata/metadata.service';
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 { RootResponseParsingService } from './data/root-response-parsing.service';
import { ServerResponseService } from '../shared/server-response.service';
import { NativeWindowFactory, NativeWindowService } from '../shared/window.service';
const IMPORTS = [
CommonModule,
@@ -47,6 +53,7 @@ const PROVIDERS = [
DSpaceRESTv2Service,
HostWindowService,
ItemDataService,
MetadataService,
ObjectCacheService,
PaginationComponentOptions,
RemoteDataBuildService,

View File

@@ -3,7 +3,10 @@ import { CacheableObject } from '../cache/object-cache.reducer';
import { hasValue, isNotEmpty } from '../../shared/empty.util';
import { RemoteData } from './remote-data';
import {
FindAllOptions, FindAllRequest, FindByIDRequest, RestRequest,
FindAllOptions,
FindAllRequest,
FindByIDRequest,
RestRequest,
RootEndpointRequest
} from './request.models';
import { Store } from '@ngrx/store';
@@ -51,7 +54,7 @@ export abstract class DataService<TNormalized extends CacheableObject, TDomain>
}
public isEnabledOnRestApi(): Observable<boolean> {
return this.getEndpointMap()
return this.getEndpointMap()
.map((map: EndpointMap) => isNotEmpty(map[this.linkName]))
.startWith(undefined)
.distinctUntilChanged();

View File

@@ -0,0 +1,114 @@
import { ComponentFixture, TestBed, async, fakeAsync, inject, tick } from '@angular/core/testing';
import { RouterTestingModule } from '@angular/router/testing';
import { Location, CommonModule } from '@angular/common';
import { Component, CUSTOM_ELEMENTS_SCHEMA } from '@angular/core';
import { By, Meta } from '@angular/platform-browser';
import { Router } from '@angular/router';
import { Store, StoreModule } from '@ngrx/store';
import { Observable } from 'rxjs/Observable';
import { MetadataService } from './metadata.service';
import { CoreState } from '../core.reducers';
import { GlobalConfig } from '../../../config/global-config.interface';
import { ENV_CONFIG, GLOBAL_CONFIG } from '../../../config';
import { ObjectCacheService } from '../cache/object-cache.service';
import { RequestService } from '../data/request.service';
import { ResponseCacheService } from '../cache/response-cache.service';
import { RemoteDataBuildService } from '../cache/builders/remote-data-build.service';
import { NormalizedItem } from '../cache/models/normalized-item.model';
import { MockRouter } from '../../shared/mocks/mock-router';
import { MockNormalizedItem } from '../../shared/mocks/mock-normalized-item';
import { MockItem } from '../../shared/mocks/mock-item';
/* tslint:disable:max-classes-per-file */
@Component({
template: `<router-outlet></router-outlet>`
})
class TestComponent {
constructor(private metadata: MetadataService) {
metadata.listenForRouteChange();
}
}
@Component({ template: '' }) class DummyItemComponent { }
/* tslint:enable:max-classes-per-file */
describe('MetadataService', () => {
let metadataService: MetadataService;
let meta: Meta;
let store: Store<CoreState>;
let objectCacheService: ObjectCacheService;
let responseCacheService: ResponseCacheService;
let requestService: RequestService;
let remoteDataBuildService: RemoteDataBuildService;
let location: Location;
let router: Router;
let fixture: ComponentFixture<TestComponent>;
beforeEach(() => {
store = new Store<CoreState>(undefined, undefined, undefined);
spyOn(store, 'dispatch');
objectCacheService = new ObjectCacheService(store);
responseCacheService = new ResponseCacheService(store);
requestService = new RequestService(objectCacheService, responseCacheService, store);
remoteDataBuildService = new RemoteDataBuildService(objectCacheService, responseCacheService, requestService);
TestBed.configureTestingModule({
imports: [
CommonModule,
StoreModule.forRoot({}),
RouterTestingModule.withRoutes([
{ path: 'items/:id', component: DummyItemComponent, pathMatch: 'full', data: { type: NormalizedItem } }
])
],
declarations: [
TestComponent,
DummyItemComponent
],
providers: [
{ provide: ObjectCacheService, useValue: objectCacheService },
{ provide: ResponseCacheService, useValue: responseCacheService },
{ provide: RequestService, useValue: requestService },
{ provide: RemoteDataBuildService, useValue: remoteDataBuildService },
{ provide: GLOBAL_CONFIG, useValue: ENV_CONFIG },
Meta,
MetadataService
],
schemas: [CUSTOM_ELEMENTS_SCHEMA]
});
meta = TestBed.get(Meta);
metadataService = TestBed.get(MetadataService);
router = TestBed.get(Router);
location = TestBed.get(Location);
fixture = TestBed.createComponent(TestComponent);
fixture.detectChanges();
});
beforeEach(() => {
spyOn(objectCacheService, 'getByUUID').and.returnValue(Observable.create((observer) => {
observer.next(MockNormalizedItem);
}));
spyOn(remoteDataBuildService, 'build').and.returnValue(MockItem);
});
it('upon navigation should call meta tag setters', () => {
router.navigate(['/items/0ec7ff22-f211-40ab-a69e-c819b0b1f357']);
});
});

View File

@@ -0,0 +1,354 @@
import 'rxjs/add/operator/first'
import 'rxjs/add/operator/take'
import { Inject, Injectable } from '@angular/core';
import {
ActivatedRoute,
Event,
NavigationEnd,
Params,
Router
} from '@angular/router';
import { Meta, MetaDefinition } from '@angular/platform-browser';
import { BehaviorSubject } from 'rxjs/BehaviorSubject';
import { Observable } from 'rxjs/Observable';
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 { ObjectCacheService } from '../cache/object-cache.service';
import { RemoteDataBuildService } from '../cache/builders/remote-data-build.service';
import { GLOBAL_CONFIG, GlobalConfig } from '../../../config';
@Injectable()
export class MetadataService {
private initialized: boolean;
private tagStore: Map<string, MetaDefinition[]>;
private currentObject: BehaviorSubject<DSpaceObject>;
constructor(
private router: Router,
private objectCacheService: ObjectCacheService,
private remoteDataBuildService: RemoteDataBuildService,
private meta: Meta,
@Inject(GLOBAL_CONFIG) private envConfig: GlobalConfig
) {
this.meta.addTags([
{ property: 'og:title', content: 'DSpace Angular Universal' }
]);
this.initialized = false;
this.tagStore = new Map<string, MetaDefinition[]>();
}
public listenForRouteChange(): void {
const subscription = this.router.events
.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) => {
if (routeInfo.params.value.id && routeInfo.data.value.type) {
this.objectCacheService.getByUUID(routeInfo.params.value.id, routeInfo.data.value.type)
.first().subscribe((normalizedObject: CacheableObject) => {
const dspaceObject = this.remoteDataBuildService.build(normalizedObject) as DSpaceObject;
if (!this.initialized) {
this.initialize(dspaceObject);
}
this.currentObject.next(dspaceObject);
});
} else {
this.clearMetaTags();
}
});
}
private initialize(dspaceObject: DSpaceObject): void {
this.currentObject = new BehaviorSubject<DSpaceObject>(dspaceObject);
const subscription = this.currentObject.asObservable().distinctUntilKeyChanged('uuid').subscribe(() => {
this.setMetaTags();
});
this.initialized = true;
}
private getCurrentRoute(route: ActivatedRoute): ActivatedRoute {
while (route.firstChild) {
route = route.firstChild;
}
return route;
}
private setMetaTags(): void {
this.clearMetaTags();
this.setCitationTitleTag();
this.setCitationAuthorTags();
this.setCitationDateTag();
this.setCitationISSNTag();
this.setCitationISBNTag();
this.setCitationLanguageTag();
this.setCitationKeywordsTag();
this.setCitationAbstractUrlTag();
this.setCitationPdfUrlTag();
if (this.isDissertation()) {
this.setCitationDissertationNameTag();
this.setCitationDissertationInstitutionTag();
}
if (this.isTechReport()) {
this.setCitationTechReportInstitutionTag();
}
// this.setCitationJournalTitleTag();
// this.setCitationVolumeTag();
// this.setCitationIssueTag();
// this.setCitationFirstPageTag();
// this.setCitationLastPageTag();
// this.setCitationDOITag();
// this.setCitationPMIDTag();
// this.setCitationFullTextTag();
// this.setCitationConferenceTag();
// this.setCitationPatentCountryTag();
// this.setCitationPatentNumberTag();
}
/**
* Add <meta name="citation_title" ... > to the <head>
*/
private setCitationTitleTag(): void {
const value = this.getMetaTagValue('dc.title');
this.addMetaTag('citation_title', value);
}
/**
* Add <meta name="citation_author" ... > to the <head>
*/
private setCitationAuthorTags(): void {
const values: string[] = this.getMetaTagValues(['dc.author', 'dc.contributor.author', 'dc.creator']);
this.addMetaTags('citation_author', values);
}
/**
* Add <meta name="citation_date" ... > to the <head>
*/
private setCitationDateTag(): void {
const value = this.getFirstMetaTagValue(['dc.date.copyright', 'dc.date.issued', 'dc.date.available', 'dc.date.accessioned']);
this.addMetaTag('citation_date', value);
}
/**
* Add <meta name="citation_issn" ... > to the <head>
*/
private setCitationISSNTag(): void {
const value = this.getMetaTagValue('dc.identifier.issn');
this.addMetaTag('citation_issn', value);
}
/**
* Add <meta name="citation_isbn" ... > to the <head>
*/
private setCitationISBNTag(): void {
const value = this.getMetaTagValue('dc.identifier.isbn');
this.addMetaTag('citation_isbn', value);
}
/**
* Add <meta name="citation_language" ... > to the <head>
*/
private setCitationLanguageTag(): void {
const value = this.getMetaTagValue('dc.language.iso');
this.addMetaTag('citation_language', value);
}
/**
* Add <meta name="citation_dissertation_name" ... > to the <head>
*/
private setCitationDissertationNameTag(): void {
const value = this.getMetaTagValue('dc.title');
this.addMetaTag('citation_dissertation_name', value);
}
/**
* Add <meta name="citation_dissertation_institution" ... > to the <head>
*/
private setCitationDissertationInstitutionTag(): void {
const value = this.getMetaTagValue('dc.publisher');
this.addMetaTag('citation_dissertation_institution', value);
}
/**
* Add <meta name="citation_technical_report_institution" ... > to the <head>
*/
private setCitationTechReportInstitutionTag(): void {
const value = this.getMetaTagValue('dc.publisher');
this.addMetaTag('citation_technical_report_institution', value);
}
/**
* Add <meta name="citation_keywords" ... > to the <head>
*/
private setCitationKeywordsTag(): void {
const value = this.getMetaTagValuesAndCombine('dc.subject');
this.addMetaTag('citation_keywords', value);
}
/**
* Add <meta name="citation_abstract_html_url" ... > to the <head>
*/
private setCitationAbstractUrlTag(): void {
if (this.currentObject.value instanceof Item) {
const value = [this.envConfig.ui.baseUrl, this.router.url].join('');
this.addMetaTag('citation_abstract_html_url', value);
}
}
/**
* Add <meta name="citation_pdf_url" ... > to the <head>
*/
private setCitationPdfUrlTag(): void {
if (this.currentObject.value instanceof Item) {
const item = this.currentObject.value as Item;
// NOTE: Observable resolves many times with same data
// taking only two, fist one is empty array
const subscription = item.getFiles().take(2).subscribe((bitstreams: Bitstream[]) => {
for (const bitstream of bitstreams) {
if (bitstream.mimetype === 'application/pdf') {
this.addMetaTag('citation_abstract_html_url', bitstream.content);
break;
}
}
});
}
}
/**
* Returns true if this._item is a dissertation
*
* @returns {boolean}
* true if this._item has a dc.type equal to 'Thesis'
*/
private isDissertation(): boolean {
let isDissertation = false;
for (const metadatum of this.currentObject.value.metadata) {
if (metadatum.key === 'dc.type') {
isDissertation = metadatum.value === 'Thesis';
break;
}
}
return isDissertation;
}
/**
* Returns true if this._item is a technical report
*
* @returns {boolean}
* true if this._item has a dc.type equal to 'Technical Report'
*/
private isTechReport(): boolean {
let isTechReport = false;
for (const metadatum of this.currentObject.value.metadata) {
if (metadatum.key === 'dc.type') {
isTechReport = metadatum.value === 'Technical Report';
break;
}
}
return isTechReport;
}
private getMetaTagValue(key: string): string {
let value: string;
for (const metadatum of this.currentObject.value.metadata) {
if (metadatum.key === key) {
value = metadatum.value;
}
}
return value;
}
private getFirstMetaTagValue(keys: string[]): string {
let value: string;
for (const metadatum of this.currentObject.value.metadata) {
for (const key of keys) {
if (key === metadatum.key) {
value = metadatum.value;
break;
}
}
if (value !== undefined) {
break;
}
}
return value;
}
private getMetaTagValuesAndCombine(key: string): string {
return this.getMetaTagValues([key]).join('; ');
}
private getMetaTagValues(keys: string[]): string[] {
const values: string[] = [];
for (const metadatum of this.currentObject.value.metadata) {
for (const key of keys) {
if (key === metadatum.key) {
values.push(metadatum.value);
}
}
}
return values;
}
private addMetaTag(property: string, content: string): void {
if (content) {
const tag = { property, content } as MetaDefinition;
this.meta.addTag(tag);
this.storeTag(property, tag);
}
}
private addMetaTags(property: string, content: string[]): void {
for (const value of content) {
this.addMetaTag(property, value);
}
}
private storeTag(key: string, tag: MetaDefinition): void {
const tags: MetaDefinition[] = this.getTags(key);
tags.push(tag);
this.setTags(key, tags);
}
private getTags(key: string): MetaDefinition[] {
let tags: MetaDefinition[] = this.tagStore.get(key);
if (tags === undefined) {
tags = [];
}
return tags;
}
private setTags(key: string, tags: MetaDefinition[]): void {
this.tagStore.set(key, tags);
}
private clearMetaTags() {
this.tagStore.forEach((tags: MetaDefinition[], property: string) => {
this.meta.removeTag("property='" + property + "'");
});
this.tagStore.clear();
}
}

View File

@@ -21,7 +21,7 @@ import { Store, StoreModule } from '@ngrx/store';
// Load the implementations that should be tested
import { FooterComponent } from './footer.component';
import { MockTranslateLoader } from '../shared/testing/mock-translate-loader';
import { MockTranslateLoader } from '../shared/mocks/mock-translate-loader';
let comp: FooterComponent;
let fixture: ComponentFixture<FooterComponent>;

View File

@@ -4,7 +4,7 @@ import { DebugElement } from '@angular/core';
import { TranslateModule, TranslateLoader, TranslateService } from '@ngx-translate/core';
import { MockTranslateLoader } from '../testing/mock-translate-loader';
import { MockTranslateLoader } from '../mocks/mock-translate-loader';
import { ErrorComponent } from './error.component';
@@ -25,8 +25,8 @@ describe('ErrorComponent (inline template)', () => {
}
}),
],
declarations: [ ErrorComponent ], // declare the test component
providers: [ TranslateService ]
declarations: [ErrorComponent], // declare the test component
providers: [TranslateService]
}).compileComponents(); // compile template and css
}));

View File

@@ -4,7 +4,7 @@ import { DebugElement } from '@angular/core';
import { TranslateModule, TranslateLoader, TranslateService } from '@ngx-translate/core';
import { MockTranslateLoader } from '../testing/mock-translate-loader';
import { MockTranslateLoader } from '../mocks/mock-translate-loader';
import { LoadingComponent } from './loading.component';
@@ -25,8 +25,8 @@ describe('LoadingComponent (inline template)', () => {
}
}),
],
declarations: [ LoadingComponent ], // declare the test component
providers: [ TranslateService ]
declarations: [LoadingComponent], // declare the test component
providers: [TranslateService]
}).compileComponents(); // compile template and css
}));

View File

@@ -0,0 +1,6 @@
import { Action } from '@ngrx/store';
export class MockAction implements Action {
type = null;
payload: {};
}

View File

@@ -0,0 +1,34 @@
import { Params } from '@angular/router';
import { BehaviorSubject } from 'rxjs/BehaviorSubject';
export class MockActivatedRoute {
private _testParams?: any;
// ActivatedRoute.params is Observable
private subject?: BehaviorSubject<any> = new BehaviorSubject(this.testParams);
params = this.subject.asObservable();
queryParams = this.subject.asObservable();
constructor(params?: Params) {
if (params) {
this.testParams = params;
} else {
this.testParams = {};
}
}
// Test parameters
get testParams() { return this._testParams; }
set testParams(params: {}) {
this._testParams = params;
this.subject.next(params);
}
// ActivatedRoute.snapshot.params
get snapshot() {
return { params: this.testParams };
}
}

View File

@@ -0,0 +1,19 @@
import { Observable } from 'rxjs/Observable';
// declare a stub service
export class MockHostWindowService {
private width: number;
constructor(width) {
this.setWidth(width);
}
setWidth(width) {
this.width = width;
}
isXs(): Observable<boolean> {
return Observable.of(this.width < 576);
}
}

View File

@@ -0,0 +1,164 @@
import { Observable } from 'rxjs/Observable';
import { Item } from '../../core/shared/item.model';
export const MockItem: Item = Object.assign(new Item(), {
handle: '10673/6',
lastModified: '2017-04-24T19:44:08.178+0000',
isArchived: true,
isDiscoverable: true,
isWithdrawn: false,
bitstreams: {
self: {
_isScalar: true,
value: '1507836003548',
scheduler: null
},
requestPending: Observable.create((observer) => {
observer.next(false);
}),
responsePending: Observable.create((observer) => {
observer.next(false);
}),
isSuccessFul: Observable.create((observer) => {
observer.next(true);
}),
errorMessage: Observable.create((observer) => {
observer.next('');
}),
statusCode: Observable.create((observer) => {
observer.next(202);
}),
pageInfo: Observable.create((observer) => {
observer.next({});
}),
payload: Observable.create((observer) => {
observer.next([]);
})
},
self: 'https://dspace7.4science.it/dspace-spring-rest/api/core/items/0ec7ff22-f211-40ab-a69e-c819b0b1f357',
id: '0ec7ff22-f211-40ab-a69e-c819b0b1f357',
uuid: '0ec7ff22-f211-40ab-a69e-c819b0b1f357',
type: 'item',
name: 'Test PowerPoint Document',
metadata: [
{
key: 'dc.creator',
language: 'en_US',
value: 'Doe, Jane'
},
{
key: 'dc.date.accessioned',
language: null,
value: '1650-06-26T19:58:25Z'
},
{
key: 'dc.date.available',
language: null,
value: '1650-06-26T19:58:25Z'
},
{
key: 'dc.date.issued',
language: null,
value: '1650-06-26'
},
{
key: 'dc.identifier.issn',
language: 'en_US',
value: '123456789'
},
{
key: 'dc.identifier.uri',
language: null,
value: 'http://dspace7.4science.it/xmlui/handle/10673/6'
},
{
key: 'dc.description.abstract',
language: 'en_US',
value: 'This is really just a sample abstract. If it was a real abstract it would contain useful information about this test document. Sorry though, nothing useful in this paragraph. You probably shouldn\'t have even bothered to read it!'
},
{
key: 'dc.description.provenance',
language: 'en',
value: 'Made available in DSpace on 2012-06-26T19:58:25Z (GMT). No. of bitstreams: 2\r\ntest_ppt.ppt: 12707328 bytes, checksum: a353fc7d29b3c558c986f7463a41efd3 (MD5)\r\ntest_ppt.pptx: 12468572 bytes, checksum: 599305edb4ebee329667f2c35b14d1d6 (MD5)'
},
{
key: 'dc.description.provenance',
language: 'en',
value: 'Restored into DSpace on 2013-06-13T09:17:34Z (GMT).'
},
{
key: 'dc.description.provenance',
language: 'en',
value: 'Restored into DSpace on 2013-06-13T11:04:16Z (GMT).'
},
{
key: 'dc.description.provenance',
language: 'en',
value: 'Restored into DSpace on 2017-04-24T19:44:08Z (GMT).'
},
{
key: 'dc.language',
language: 'en_US',
value: 'en'
},
{
key: 'dc.rights',
language: 'en_US',
value: '© Jane Doe'
},
{
key: 'dc.subject',
language: 'en_US',
value: 'keyword1'
},
{
key: 'dc.subject',
language: 'en_US',
value: 'keyword2'
},
{
key: 'dc.subject',
language: 'en_US',
value: 'keyword3'
},
{
key: 'dc.title',
language: 'en_US',
value: 'Test PowerPoint Document'
},
{
key: 'dc.type',
language: 'en_US',
value: 'text'
}
],
owningCollection: {
self: {
_isScalar: true,
value: 'https://dspace7.4science.it/dspace-spring-rest/api/core/collections/1c11f3f1-ba1f-4f36-908a-3f1ea9a557eb',
scheduler: null
},
requestPending: Observable.create((observer) => {
observer.next(false);
}),
responsePending: Observable.create((observer) => {
observer.next(false);
}),
isSuccessFul: Observable.create((observer) => {
observer.next(true);
}),
errorMessage: Observable.create((observer) => {
observer.next('');
}),
statusCode: Observable.create((observer) => {
observer.next(202);
}),
pageInfo: Observable.create((observer) => {
observer.next({});
}),
payload: Observable.create((observer) => {
observer.next([]);
})
}
})

View File

@@ -0,0 +1,9 @@
export class MockMetadataService {
// tslint:disable-next-line:no-empty
public listenForRouteChange(): void {
}
}

View File

@@ -0,0 +1,114 @@
import { NormalizedItem } from '../../core/cache/models/normalized-item.model';
export const MockNormalizedItem: NormalizedItem = Object.assign(new NormalizedItem(), {
handle: '10673/6',
lastModified: new Date('2017-04-24T19:44:08.178+0000'),
isArchived: true,
isDiscoverable: true,
isWithdrawn: false,
bitstreams: [
'https://dspace7.4science.it/dspace-spring-rest/api/core/bitstreams/a7cd7d97-4e40-41db-80a8-fac908b63bb8',
'https://dspace7.4science.it/dspace-spring-rest/api/core/bitstreams/9ff3df0d-1709-472f-8c00-d3e8db2153c8',
'https://dspace7.4science.it/dspace-spring-rest/api/core/bitstreams/d660a4b8-e7cc-45cd-b026-35f98c5bd3ba'
],
self: 'https://dspace7.4science.it/dspace-spring-rest/api/core/items/0ec7ff22-f211-40ab-a69e-c819b0b1f357',
id: '0ec7ff22-f211-40ab-a69e-c819b0b1f357',
uuid: '0ec7ff22-f211-40ab-a69e-c819b0b1f357',
type: 'item',
name: 'Test PowerPoint Document',
metadata: [
{
key: 'dc.creator',
language: 'en_US',
value: 'Doe, Jane L'
},
{
key: 'dc.date.accessioned',
language: null,
value: '1650-06-26T19:58:25Z'
},
{
key: 'dc.date.available',
language: null,
value: '1650-06-26T19:58:25Z'
},
{
key: 'dc.date.issued',
language: null,
value: '1650-06-26'
},
{
key: 'dc.identifier.issn',
language: 'en_US',
value: '123456789'
},
{
key: 'dc.identifier.uri',
language: null,
value: 'http://dspace7.4science.it/xmlui/handle/10673/6'
},
{
key: 'dc.description.abstract',
language: 'en_US',
value: 'This is really just a sample abstract. If it was a real abstract it would contain useful information about this test document. Sorry though, nothing useful in this paragraph. You probably shouldn\'t have even bothered to read it!'
},
{
key: 'dc.description.provenance',
language: 'en',
value: 'Made available in DSpace on 2012-06-26T19:58:25Z (GMT). No. of bitstreams: 2\r\ntest_ppt.ppt: 12707328 bytes, checksum: a353fc7d29b3c558c986f7463a41efd3 (MD5)\r\ntest_ppt.pptx: 12468572 bytes, checksum: 599305edb4ebee329667f2c35b14d1d6 (MD5)'
},
{
key: 'dc.description.provenance',
language: 'en',
value: 'Restored into DSpace on 2013-06-13T09:17:34Z (GMT).'
},
{
key: 'dc.description.provenance',
language: 'en',
value: 'Restored into DSpace on 2013-06-13T11:04:16Z (GMT).'
},
{
key: 'dc.description.provenance',
language: 'en',
value: 'Restored into DSpace on 2017-04-24T19:44:08Z (GMT).'
},
{
key: 'dc.language',
language: 'en_US',
value: 'en'
},
{
key: 'dc.rights',
language: 'en_US',
value: '© Jane Doe'
},
{
key: 'dc.subject',
language: 'en_US',
value: 'keyword1'
},
{
key: 'dc.subject',
language: 'en_US',
value: 'keyword2'
},
{
key: 'dc.subject',
language: 'en_US',
value: 'keyword3'
},
{
key: 'dc.title',
language: 'en_US',
value: 'Test PowerPoint Document'
},
{
key: 'dc.type',
language: 'en_US',
value: 'text'
}
],
owningCollection: [
'https://dspace7.4science.it/dspace-spring-rest/api/core/collections/1c11f3f1-ba1f-4f36-908a-3f1ea9a557eb'
]
})

View File

@@ -0,0 +1,4 @@
export class MockRouter {
// noinspection TypeScriptUnresolvedFunction
navigate = jasmine.createSpy('navigate');
}

View File

@@ -0,0 +1,23 @@
import { Action } from '@ngrx/store';
import { Observable } from 'rxjs/Observable';
import { BehaviorSubject } from 'rxjs/BehaviorSubject';
export class MockStore<T> extends BehaviorSubject<T> {
constructor(private _initialState: T) {
super(_initialState);
}
dispatch = (action: Action): void => {
console.info();
}
select = <R>(pathOrMapFn: any): Observable<T> => {
return Observable.of(this.getValue());
}
nextState(_newState: T) {
this.next(_newState);
}
}

View File

@@ -0,0 +1,8 @@
import { TranslateLoader } from '@ngx-translate/core';
import { Observable } from 'rxjs/Observable';
export class MockTranslateLoader implements TranslateLoader {
getTranslation(lang: string): Observable<any> {
return Observable.of({});
}
}

View File

@@ -34,10 +34,10 @@ import Spy = jasmine.Spy;
import { PaginationComponent } from './pagination.component';
import { PaginationComponentOptions } from './pagination-component-options.model';
import { MockTranslateLoader } from '../testing/mock-translate-loader';
import { HostWindowServiceStub } from '../testing/host-window-service-stub';
import { ActivatedRouteStub } from '../testing/active-router-stub';
import { RouterStub } from '../testing/router-stub';
import { MockTranslateLoader } from '../mocks/mock-translate-loader';
import { MockHostWindowService } from '../mocks/mock-host-window-service';
import { MockActivatedRoute } from '../mocks/mock-active-router';
import { MockRouter } from '../mocks/mock-router';
import { HostWindowService } from '../host-window.service';
import { EnumKeysPipe } from '../utils/enum-keys-pipe';
@@ -45,7 +45,7 @@ import { SortOptions } from '../../core/cache/models/sort-options.model';
import { GLOBAL_CONFIG, ENV_CONFIG } from '../../../config';
function createTestComponent<T>(html: string, type: { new (...args: any[]): T }): ComponentFixture<T> {
function createTestComponent<T>(html: string, type: { new(...args: any[]): T }): ComponentFixture<T> {
TestBed.overrideComponent(type, {
set: { template: html }
});
@@ -123,19 +123,19 @@ describe('Pagination component', () => {
let testFixture: ComponentFixture<TestComponent>;
let de: DebugElement;
let html;
let hostWindowServiceStub: HostWindowServiceStub;
let hostWindowServiceStub: MockHostWindowService;
let activatedRouteStub: ActivatedRouteStub;
let routerStub: RouterStub;
let activatedRouteStub: MockActivatedRoute;
let routerStub: MockRouter;
// Define initial state and test state
const _initialState = { width: 1600, height: 770 };
// async beforeEach
beforeEach(async(() => {
activatedRouteStub = new ActivatedRouteStub();
routerStub = new RouterStub();
hostWindowServiceStub = new HostWindowServiceStub(_initialState.width);
activatedRouteStub = new MockActivatedRoute();
routerStub = new MockRouter();
hostWindowServiceStub = new MockHostWindowService(_initialState.width);
TestBed.configureTestingModule({
imports: [

166
yarn.lock
View File

@@ -2,79 +2,79 @@
# yarn lockfile v1
"@angular/animations@4.4.4":
version "4.4.4"
resolved "https://registry.yarnpkg.com/@angular/animations/-/animations-4.4.4.tgz#a2f9353604347abe15df98292058842f52f08bc2"
"@angular/animations@4.4.5":
version "4.4.5"
resolved "https://registry.yarnpkg.com/@angular/animations/-/animations-4.4.5.tgz#5a5a551d757e5a5560098f6f8535c102d93954d7"
dependencies:
tslib "^1.7.1"
"@angular/common@4.4.4":
version "4.4.4"
resolved "https://registry.yarnpkg.com/@angular/common/-/common-4.4.4.tgz#ae0a818aaa0c6a3f0901e7b80bd94e1c22eb9365"
"@angular/common@4.4.5":
version "4.4.5"
resolved "https://registry.yarnpkg.com/@angular/common/-/common-4.4.5.tgz#bd5179dc922adbf4c3ea6dfb19e73cb849ffdc37"
dependencies:
tslib "^1.7.1"
"@angular/compiler-cli@4.4.4":
version "4.4.4"
resolved "https://registry.yarnpkg.com/@angular/compiler-cli/-/compiler-cli-4.4.4.tgz#063080a497d9175396825050222c717da184f6cf"
"@angular/compiler-cli@4.4.5":
version "4.4.5"
resolved "https://registry.yarnpkg.com/@angular/compiler-cli/-/compiler-cli-4.4.5.tgz#61fa0336acd1a208c5f1c5c6d4df679e99953248"
dependencies:
"@angular/tsc-wrapped" "4.4.4"
"@angular/tsc-wrapped" "4.4.5"
minimist "^1.2.0"
reflect-metadata "^0.1.2"
"@angular/compiler@4.4.4":
version "4.4.4"
resolved "https://registry.yarnpkg.com/@angular/compiler/-/compiler-4.4.4.tgz#326eb0029d9a3541aaca124def9adc51c36f2b41"
"@angular/compiler@4.4.5":
version "4.4.5"
resolved "https://registry.yarnpkg.com/@angular/compiler/-/compiler-4.4.5.tgz#8721a5910f2bb52f09e2d404cad264f35ede5902"
dependencies:
tslib "^1.7.1"
"@angular/core@4.4.4":
version "4.4.4"
resolved "https://registry.yarnpkg.com/@angular/core/-/core-4.4.4.tgz#bd37ecf54158f97489996c9386bd222f80a32f5c"
"@angular/core@4.4.5":
version "4.4.5"
resolved "https://registry.yarnpkg.com/@angular/core/-/core-4.4.5.tgz#54acbcbda11719f883c786a906974abeb132f1a0"
dependencies:
tslib "^1.7.1"
"@angular/forms@4.4.4":
version "4.4.4"
resolved "https://registry.yarnpkg.com/@angular/forms/-/forms-4.4.4.tgz#4db3790509b6b10f1db8a7c1b7f52187cf64cfd4"
"@angular/forms@4.4.5":
version "4.4.5"
resolved "https://registry.yarnpkg.com/@angular/forms/-/forms-4.4.5.tgz#e9552086232aab2ce1d08ef198b62204ea13c43b"
dependencies:
tslib "^1.7.1"
"@angular/http@4.4.4":
version "4.4.4"
resolved "https://registry.yarnpkg.com/@angular/http/-/http-4.4.4.tgz#667faf616bb624168eafae6ee92e5eba23a9d1f2"
"@angular/http@4.4.5":
version "4.4.5"
resolved "https://registry.yarnpkg.com/@angular/http/-/http-4.4.5.tgz#2c735ed842401fc2356419268e288dcf2396e84f"
dependencies:
tslib "^1.7.1"
"@angular/platform-browser-dynamic@4.4.4":
version "4.4.4"
resolved "https://registry.yarnpkg.com/@angular/platform-browser-dynamic/-/platform-browser-dynamic-4.4.4.tgz#c3c9eb854a528556a07054127932e527fa932e14"
"@angular/platform-browser-dynamic@4.4.5":
version "4.4.5"
resolved "https://registry.yarnpkg.com/@angular/platform-browser-dynamic/-/platform-browser-dynamic-4.4.5.tgz#774dbdc1d90f775dbf1e319f6ed42b260623b61f"
dependencies:
tslib "^1.7.1"
"@angular/platform-browser@4.4.4":
version "4.4.4"
resolved "https://registry.yarnpkg.com/@angular/platform-browser/-/platform-browser-4.4.4.tgz#a3898e2e7ba9d84ffa0d47144c6971179c75aee6"
"@angular/platform-browser@4.4.5":
version "4.4.5"
resolved "https://registry.yarnpkg.com/@angular/platform-browser/-/platform-browser-4.4.5.tgz#74eb91c0b758126f26d53ee56c7cf4668bd9cac5"
dependencies:
tslib "^1.7.1"
"@angular/platform-server@4.4.4":
version "4.4.4"
resolved "https://registry.yarnpkg.com/@angular/platform-server/-/platform-server-4.4.4.tgz#73ee41fa1cec8628fcc03174727b27cb0031b22a"
"@angular/platform-server@4.4.5":
version "4.4.5"
resolved "https://registry.yarnpkg.com/@angular/platform-server/-/platform-server-4.4.5.tgz#76f23b2c384ed7395dc1793cf85978883ba2cb50"
dependencies:
parse5 "^3.0.1"
tslib "^1.7.1"
xhr2 "^0.1.4"
"@angular/router@4.4.4":
version "4.4.4"
resolved "https://registry.yarnpkg.com/@angular/router/-/router-4.4.4.tgz#7be391096e843cb3e04f9f05d1d65a88df9bc7cf"
"@angular/router@4.4.5":
version "4.4.5"
resolved "https://registry.yarnpkg.com/@angular/router/-/router-4.4.5.tgz#f73130cf487d9a32cc1988afda59665f44a28a89"
dependencies:
tslib "^1.7.1"
"@angular/tsc-wrapped@4.4.4":
version "4.4.4"
resolved "https://registry.yarnpkg.com/@angular/tsc-wrapped/-/tsc-wrapped-4.4.4.tgz#9841821e55616b826ca160250fe85e15fc74ffc3"
"@angular/tsc-wrapped@4.4.5":
version "4.4.5"
resolved "https://registry.yarnpkg.com/@angular/tsc-wrapped/-/tsc-wrapped-4.4.5.tgz#30a0cbb43a663aa75dca984894be4813778ddc9c"
dependencies:
tsickle "^0.21.0"
@@ -106,9 +106,9 @@
version "4.0.3"
resolved "https://registry.yarnpkg.com/@ngrx/store/-/store-4.0.3.tgz#36abacdfa19bfb8506e40de80bae06050a1e15e9"
"@ngtools/webpack@1.7.2":
version "1.7.2"
resolved "https://registry.yarnpkg.com/@ngtools/webpack/-/webpack-1.7.2.tgz#3fc4de01786dcc2f50d8cbaaa117311e56799977"
"@ngtools/webpack@1.7.4":
version "1.7.4"
resolved "https://registry.yarnpkg.com/@ngtools/webpack/-/webpack-1.7.4.tgz#5015c47ebd339045dd89a1bef0497f4524d2c8ed"
dependencies:
enhanced-resolve "^3.1.0"
loader-utils "^1.0.2"
@@ -192,7 +192,11 @@
version "2.0.29"
resolved "https://registry.yarnpkg.com/@types/minimatch/-/minimatch-2.0.29.tgz#5002e14f75e2d71e564281df0431c8c1b4a2a36a"
"@types/node@*", "@types/node@8.0.26":
"@types/node@*":
version "8.0.34"
resolved "https://registry.yarnpkg.com/@types/node/-/node-8.0.34.tgz#55f801fa2ddb2a40dd6dfc15ecfe1dde9c129fe9"
"@types/node@8.0.26":
version "8.0.26"
resolved "https://registry.yarnpkg.com/@types/node/-/node-8.0.26.tgz#4d58be925306fd22b1141085535a0268b8beb189"
@@ -568,7 +572,7 @@ atob@~1.1.0:
version "1.1.3"
resolved "https://registry.yarnpkg.com/atob/-/atob-1.1.3.tgz#95f13629b12c3a51a5d215abdce2aa9f32f80773"
autoprefixer@7.1.5:
autoprefixer@7.1.5, autoprefixer@^7.1.1:
version "7.1.5"
resolved "https://registry.yarnpkg.com/autoprefixer/-/autoprefixer-7.1.5.tgz#d65d14b83c7cd1dd7bc801daa00557addf5a06b2"
dependencies:
@@ -590,17 +594,6 @@ autoprefixer@^6.3.1:
postcss "^5.2.16"
postcss-value-parser "^3.2.3"
autoprefixer@^7.1.1:
version "7.1.4"
resolved "https://registry.yarnpkg.com/autoprefixer/-/autoprefixer-7.1.4.tgz#960847dbaa4016bc8e8e52ec891cbf8f1257a748"
dependencies:
browserslist "^2.4.0"
caniuse-lite "^1.0.30000726"
normalize-range "^0.1.2"
num2fraction "^1.2.2"
postcss "^6.0.11"
postcss-value-parser "^3.2.3"
awesome-typescript-loader@3.2.3:
version "3.2.3"
resolved "https://registry.yarnpkg.com/awesome-typescript-loader/-/awesome-typescript-loader-3.2.3.tgz#aa2119b7c808a031e2b28945b031450a8975367f"
@@ -793,11 +786,7 @@ blocking-proxy@0.0.5:
dependencies:
minimist "^1.2.0"
bluebird@^3.3.0, bluebird@^3.4.7:
version "3.5.0"
resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-3.5.0.tgz#791420d7f551eea2897453a8a77653f96606d67c"
bluebird@^3.5.1:
bluebird@^3.3.0, bluebird@^3.4.7, bluebird@^3.5.1:
version "3.5.1"
resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-3.5.1.tgz#d9551f9de98f1fcda1e683d17ee91a0602ee2eb9"
@@ -975,14 +964,7 @@ 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.4.0:
version "2.4.0"
resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-2.4.0.tgz#693ee93d01e66468a6348da5498e011f578f87f8"
dependencies:
caniuse-lite "^1.0.30000718"
electron-to-chromium "^1.3.18"
browserslist@^2.5.0:
browserslist@^2.0.0, browserslist@^2.5.0:
version "2.5.1"
resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-2.5.1.tgz#68e4bc536bbcc6086d62843a2ffccea8396821c6"
dependencies:
@@ -1099,11 +1081,7 @@ caniuse-lite@1.0.30000697:
version "1.0.30000697"
resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30000697.tgz#125fb00604b63fbb188db96a667ce2922dcd6cdd"
caniuse-lite@^1.0.0, caniuse-lite@^1.0.30000718, caniuse-lite@^1.0.30000726:
version "1.0.30000740"
resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30000740.tgz#f2c4c04d6564eb812e61006841700ad557f6f973"
caniuse-lite@^1.0.30000744:
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"
@@ -1126,11 +1104,11 @@ center-align@^0.1.1:
align-text "^0.1.3"
lazy-cache "^1.0.3"
cerialize@0.1.16:
version "0.1.16"
resolved "https://registry.yarnpkg.com/cerialize/-/cerialize-0.1.16.tgz#88678bffbd7817a90aa5b58a8c66d6bdca3035be"
cerialize@0.1.18:
version "0.1.18"
resolved "https://registry.yarnpkg.com/cerialize/-/cerialize-0.1.18.tgz#d0f4f1b61cec7e4ed16a3eda0cac2bc99787414d"
dependencies:
typescript "^2.1.6"
typescript "^2.5.0"
chalk@^1.0.0, chalk@^1.1.1, chalk@^1.1.3:
version "1.1.3"
@@ -2042,7 +2020,7 @@ ejs@^2.5.6:
version "2.5.7"
resolved "https://registry.yarnpkg.com/ejs/-/ejs-2.5.7.tgz#cc872c168880ae3c7189762fd5ffc00896c9518a"
electron-to-chromium@^1.2.7, electron-to-chromium@^1.3.18, electron-to-chromium@^1.3.24:
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"
@@ -2414,9 +2392,9 @@ express-session@1.15.6:
uid-safe "~2.1.5"
utils-merge "1.0.1"
express@4.16.1, express@^4.13.3, express@^4.15.2:
version "4.16.1"
resolved "https://registry.yarnpkg.com/express/-/express-4.16.1.tgz#6b33b560183c9b253b7b62144df33a4654ac9ed0"
express@4.16.2, express@^4.13.3, express@^4.15.2:
version "4.16.2"
resolved "https://registry.yarnpkg.com/express/-/express-4.16.2.tgz#e35c6dfe2d64b7dca0a5cd4f21781be3299e076c"
dependencies:
accepts "~1.3.4"
array-flatten "1.1.1"
@@ -5129,9 +5107,9 @@ pbkdf2@^3.0.3:
safe-buffer "^5.0.1"
sha.js "^2.4.8"
pem@1.12.2:
version "1.12.2"
resolved "https://registry.yarnpkg.com/pem/-/pem-1.12.2.tgz#d2f1744c9ff8144f795f96d0c54a4b2be6f43b0c"
pem@1.12.3:
version "1.12.3"
resolved "https://registry.yarnpkg.com/pem/-/pem-1.12.3.tgz#b1fb5c8b79da8d18146c27fee79b0d4ddf9905b3"
dependencies:
md5 "^2.2.1"
os-tmpdir "^1.0.1"
@@ -5484,12 +5462,12 @@ postcss-load-plugins@^2.3.0:
cosmiconfig "^2.1.1"
object-assign "^4.1.0"
postcss-loader@2.0.6:
version "2.0.6"
resolved "https://registry.yarnpkg.com/postcss-loader/-/postcss-loader-2.0.6.tgz#8c7e0055a3df1889abc6bad52dd45b2f41bbc6fc"
postcss-loader@2.0.7:
version "2.0.7"
resolved "https://registry.yarnpkg.com/postcss-loader/-/postcss-loader-2.0.7.tgz#4d2da1489cee0a14f72c0d9440c9ee7eded34345"
dependencies:
loader-utils "^1.1.0"
postcss "^6.0.2"
postcss "^6.0.0"
postcss-load-config "^1.2.0"
schema-utils "^0.3.0"
@@ -5755,7 +5733,7 @@ postcss-zindex@^2.0.1:
postcss "^5.0.4"
uniqs "^2.0.0"
postcss@6.0.13, postcss@^6.0.0, postcss@^6.0.1, postcss@^6.0.11, postcss@^6.0.13, postcss@^6.0.2, postcss@^6.0.3, postcss@^6.0.5, postcss@^6.0.6, postcss@^6.0.8:
postcss@6.0.13, 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:
@@ -6320,9 +6298,9 @@ requires-port@1.0.x, requires-port@1.x.x:
version "1.0.0"
resolved "https://registry.yarnpkg.com/requires-port/-/requires-port-1.0.0.tgz#925d2601d39ac485e091cf0da5c6e694dc3dcaff"
resolve-url-loader@2.1.0:
version "2.1.0"
resolved "https://registry.yarnpkg.com/resolve-url-loader/-/resolve-url-loader-2.1.0.tgz#27c95cc16a4353923fdbdc2dbaf5eef22232c477"
resolve-url-loader@2.1.1:
version "2.1.1"
resolved "https://registry.yarnpkg.com/resolve-url-loader/-/resolve-url-loader-2.1.1.tgz#5354e87381aae348371e555172c50816708e6c1c"
dependencies:
adjust-sourcemap-loader "^1.1.0"
camelcase "^4.0.0"
@@ -7419,7 +7397,7 @@ typescript@2.4.1:
version "2.4.1"
resolved "https://registry.yarnpkg.com/typescript/-/typescript-2.4.1.tgz#c3ccb16ddaa0b2314de031e7e6fee89e5ba346bc"
typescript@2.5.3, typescript@^2.1.6:
typescript@2.5.3, typescript@^2.5.0:
version "2.5.3"
resolved "https://registry.yarnpkg.com/typescript/-/typescript-2.5.3.tgz#df3dcdc38f3beb800d4bc322646b04a3f6ca7f0d"
@@ -7827,9 +7805,9 @@ webpack-sources@^1.0.1:
source-list-map "^2.0.0"
source-map "~0.5.3"
webpack@3.6.0:
version "3.6.0"
resolved "https://registry.yarnpkg.com/webpack/-/webpack-3.6.0.tgz#a89a929fbee205d35a4fa2cc487be9cbec8898bc"
webpack@3.7.1:
version "3.7.1"
resolved "https://registry.yarnpkg.com/webpack/-/webpack-3.7.1.tgz#6046b5c415ff7df7a0dc54c5b6b86098e8b952da"
dependencies:
acorn "^5.0.0"
acorn-dynamic-import "^2.0.0"