From 8d8dcea518f9ff6f280a714ff9c1e8c2b7312f94 Mon Sep 17 00:00:00 2001 From: Sebastian Date: Sat, 1 Jun 2019 23:11:43 +0200 Subject: [PATCH 01/47] Ng8 --- src/Squidex/app/app.routes.ts | 18 +- .../pages/graphql/graphql-page.component.scss | 2 +- .../pages/graphql/graphql-page.component.ts | 2 +- .../apps/pages/apps-page.component.scss | 2 +- .../apps/pages/news-dialog.component.scss | 2 +- .../pages/onboarding-dialog.component.scss | 2 +- .../assets/pages/assets-page.component.scss | 2 +- .../content-history-page.component.scss | 2 +- .../pages/content/content-page.component.ts | 2 +- .../contents/contents-page.component.scss | 6 +- .../pages/contents/contents-page.component.ts | 2 +- .../content/shared/array-item.component.scss | 2 +- .../shared/contents-selector.component.scss | 12 +- .../pages/dashboard-page.component.scss | 4 +- .../pages/rules/rule-element.component.scss | 8 +- .../pages/schema/field-wizard.component.scss | 6 +- .../pages/schema/field-wizard.component.ts | 2 +- .../pages/schemas/schema-form.component.scss | 10 +- .../settings/pages/roles/role.component.ts | 2 +- .../angular/forms/autocomplete.component.ts | 4 +- .../angular/forms/code-editor.component.scss | 2 +- .../angular/forms/code-editor.component.ts | 2 +- .../angular/forms/color-picker.component.scss | 2 +- .../forms/date-time-editor.component.ts | 2 +- .../angular/forms/iframe-editor.component.ts | 2 +- .../angular/forms/json-editor.component.scss | 2 +- .../angular/forms/json-editor.component.ts | 2 +- .../angular/forms/tag-editor.component.ts | 4 +- .../angular/modals/modal-dialog.component.ts | 4 +- .../angular/modals/root-view.component.ts | 2 +- .../app/framework/angular/panel.component.ts | 2 +- .../shared/components/asset.component.scss | 5 +- .../components/assets-selector.component.scss | 2 +- .../geolocation-editor.component.ts | 4 +- .../components/history-list.component.scss | 2 +- .../components/markdown-editor.component.ts | 6 +- .../components/rich-editor.component.ts | 2 +- .../internal/internal-area.component.scss | 2 +- src/Squidex/app/shims.ts | 105 +- src/Squidex/app/theme/_bootstrap.scss | 2 +- src/Squidex/package-lock.json | 2657 ++++++----------- src/Squidex/package.json | 52 +- src/Squidex/tsconfig.json | 1 + 43 files changed, 1123 insertions(+), 1835 deletions(-) diff --git a/src/Squidex/app/app.routes.ts b/src/Squidex/app/app.routes.ts index d7598968f..8331b68a4 100644 --- a/src/Squidex/app/app.routes.ts +++ b/src/Squidex/app/app.routes.ts @@ -38,12 +38,12 @@ export const routes: Routes = [ children: [ { path: '', - loadChildren: './features/apps/module#SqxFeatureAppsModule', + loadChildren: () => import('./features/apps/module').then(m => m.SqxFeatureAppsModule), canActivate: [UnsetAppGuard] }, { path: 'administration', - loadChildren: './features/administration/module#SqxFeatureAdministrationModule', + loadChildren: () => import('./features/administration/module').then(m => m.SqxFeatureAdministrationModule), canActivate: [UnsetAppGuard] }, { @@ -53,31 +53,31 @@ export const routes: Routes = [ children: [ { path: '', - loadChildren: './features/dashboard/module#SqxFeatureDashboardModule' + loadChildren: () => import('./features/dashboard/module').then(m => m.SqxFeatureDashboardModule) }, { path: 'content', - loadChildren: './features/content/module#SqxFeatureContentModule' + loadChildren: () => import('./features/content/module').then(m => m.SqxFeatureContentModule) }, { path: 'schemas', - loadChildren: './features/schemas/module#SqxFeatureSchemasModule' + loadChildren: () => import('./features/schemas/module').then(m => m.SqxFeatureSchemasModule) }, { path: 'assets', - loadChildren: './features/assets/module#SqxFeatureAssetsModule' + loadChildren: () => import('./features/assets/module').then(m => m.SqxFeatureAssetsModule) }, { path: 'rules', - loadChildren: './features/rules/module#SqxFeatureRulesModule' + loadChildren: () => import('./features/rules/module').then(m => m.SqxFeatureRulesModule) }, { path: 'settings', - loadChildren: './features/settings/module#SqxFeatureSettingsModule' + loadChildren: () => import('./features/settings/module').then(m => m.SqxFeatureSettingsModule) }, { path: 'api', - loadChildren: './features/api/module#SqxFeatureApiModule' + loadChildren: () => import('./features/api/module').then(m => m.SqxFeatureApiModule) } ] } diff --git a/src/Squidex/app/features/api/pages/graphql/graphql-page.component.scss b/src/Squidex/app/features/api/pages/graphql/graphql-page.component.scss index 6d3c84b1c..e47eee080 100644 --- a/src/Squidex/app/features/api/pages/graphql/graphql-page.component.scss +++ b/src/Squidex/app/features/api/pages/graphql/graphql-page.component.scss @@ -1,7 +1,7 @@ @import '_vars'; @import '_mixins'; -:host /deep/ { +::ng-deep { @import '~graphiql/graphiql'; .graphiql-container { diff --git a/src/Squidex/app/features/api/pages/graphql/graphql-page.component.ts b/src/Squidex/app/features/api/pages/graphql/graphql-page.component.ts index 3ae06545c..3d32114d0 100644 --- a/src/Squidex/app/features/api/pages/graphql/graphql-page.component.ts +++ b/src/Squidex/app/features/api/pages/graphql/graphql-page.component.ts @@ -22,7 +22,7 @@ import { AppsState, GraphQlService } from '@app/shared'; templateUrl: './graphql-page.component.html' }) export class GraphQLPageComponent implements AfterViewInit { - @ViewChild('graphiQLContainer') + @ViewChild('graphiQLContainer', { static: false }) public graphiQLContainer: ElementRef; constructor( diff --git a/src/Squidex/app/features/apps/pages/apps-page.component.scss b/src/Squidex/app/features/apps/pages/apps-page.component.scss index e428d32c9..af1a2f69f 100644 --- a/src/Squidex/app/features/apps/pages/apps-page.component.scss +++ b/src/Squidex/app/features/apps/pages/apps-page.component.scss @@ -66,7 +66,7 @@ } &:hover { - @include box-shadow(0, 3px, 16px, .2px); + @include box-shadow(0, 3px, 16px, .2); } &:focus { diff --git a/src/Squidex/app/features/apps/pages/news-dialog.component.scss b/src/Squidex/app/features/apps/pages/news-dialog.component.scss index 787e1d95a..927e34891 100644 --- a/src/Squidex/app/features/apps/pages/news-dialog.component.scss +++ b/src/Squidex/app/features/apps/pages/news-dialog.component.scss @@ -1,7 +1,7 @@ @import '_vars'; @import '_mixins'; -:host /deep/ { +::ng-deep { img { @include box-shadow(0, 4px, 20px, .2); width: 80%; diff --git a/src/Squidex/app/features/apps/pages/onboarding-dialog.component.scss b/src/Squidex/app/features/apps/pages/onboarding-dialog.component.scss index a2dadddb3..01f6bf120 100644 --- a/src/Squidex/app/features/apps/pages/onboarding-dialog.component.scss +++ b/src/Squidex/app/features/apps/pages/onboarding-dialog.component.scss @@ -19,7 +19,7 @@ p { max-width: 489px; } -:host /deep/ .modal { +::ng-deep .modal { &-content, &-dialog { min-height: $size-height; diff --git a/src/Squidex/app/features/assets/pages/assets-page.component.scss b/src/Squidex/app/features/assets/pages/assets-page.component.scss index 6bc6bf7dc..1c98c09d3 100644 --- a/src/Squidex/app/features/assets/pages/assets-page.component.scss +++ b/src/Squidex/app/features/assets/pages/assets-page.component.scss @@ -6,7 +6,7 @@ padding: 1rem; } -:host /deep/ { +::ng-deep { .search { .form-control { @include border-radius-right; diff --git a/src/Squidex/app/features/content/pages/content/content-history-page.component.scss b/src/Squidex/app/features/content/pages/content/content-history-page.component.scss index cf0dec62a..d7f4584de 100644 --- a/src/Squidex/app/features/content/pages/content/content-history-page.component.scss +++ b/src/Squidex/app/features/content/pages/content/content-history-page.component.scss @@ -1,7 +1,7 @@ @import '_vars'; @import '_mixins'; -:host /deep/ { +::ng-deep { .user-ref { color: $color-title; } diff --git a/src/Squidex/app/features/content/pages/content/content-page.component.ts b/src/Squidex/app/features/content/pages/content/content-page.component.ts index 228595a75..5704468b4 100644 --- a/src/Squidex/app/features/content/pages/content/content-page.component.ts +++ b/src/Squidex/app/features/content/pages/content/content-page.component.ts @@ -59,7 +59,7 @@ export class ContentPageComponent extends ResourceOwner implements CanComponentD public language: AppLanguageDto; public languages: ImmutableArray; - @ViewChild('dueTimeSelector') + @ViewChild('dueTimeSelector', { static: false }) public dueTimeSelector: DueTimeSelectorComponent; constructor(apiUrl: ApiUrlConfig, authService: AuthService, diff --git a/src/Squidex/app/features/content/pages/contents/contents-page.component.scss b/src/Squidex/app/features/content/pages/contents/contents-page.component.scss index e9f528877..46a30425b 100644 --- a/src/Squidex/app/features/content/pages/contents/contents-page.component.scss +++ b/src/Squidex/app/features/content/pages/contents/contents-page.component.scss @@ -1,8 +1,10 @@ @import '_vars'; @import '_mixins'; -:host /deep/ .search-form { - display: block; +::ng-deep { + .search-form { + display: block; + } } .content { diff --git a/src/Squidex/app/features/content/pages/contents/contents-page.component.ts b/src/Squidex/app/features/content/pages/contents/contents-page.component.ts index 4531e3df8..73acdf1da 100644 --- a/src/Squidex/app/features/content/pages/contents/contents-page.component.ts +++ b/src/Squidex/app/features/content/pages/contents/contents-page.component.ts @@ -56,7 +56,7 @@ export class ContentsPageComponent extends ResourceOwner implements OnInit { public isAllSelected = false; - @ViewChild('dueTimeSelector') + @ViewChild('dueTimeSelector', { static: false }) public dueTimeSelector: DueTimeSelectorComponent; constructor( diff --git a/src/Squidex/app/features/content/shared/array-item.component.scss b/src/Squidex/app/features/content/shared/array-item.component.scss index 7b54dfb82..976c37102 100644 --- a/src/Squidex/app/features/content/shared/array-item.component.scss +++ b/src/Squidex/app/features/content/shared/array-item.component.scss @@ -1,7 +1,7 @@ @import '_vars'; @import '_mixins'; -:host /deep/ { +::ng-deep { .ui-separator { border-color: $color-border !important; font-size: 1.2rem; diff --git a/src/Squidex/app/features/content/shared/contents-selector.component.scss b/src/Squidex/app/features/content/shared/contents-selector.component.scss index c9609948f..6daf3f73c 100644 --- a/src/Squidex/app/features/content/shared/contents-selector.component.scss +++ b/src/Squidex/app/features/content/shared/contents-selector.component.scss @@ -1,10 +1,12 @@ @import '_vars'; @import '_mixins'; -:host /deep/ .modal-body { - background: $color-background; -} +::ng-deep { + .modal-body { + background: $color-background; + } -:host /deep/ .modal-tabs { - background: $color-dark-foreground; + .modal-tabs { + background: $color-dark-foreground; + } } \ No newline at end of file diff --git a/src/Squidex/app/features/dashboard/pages/dashboard-page.component.scss b/src/Squidex/app/features/dashboard/pages/dashboard-page.component.scss index 936b11b25..c8ff0d705 100644 --- a/src/Squidex/app/features/dashboard/pages/dashboard-page.component.scss +++ b/src/Squidex/app/features/dashboard/pages/dashboard-page.component.scss @@ -19,7 +19,7 @@ } } -:host /deep/ canvas { +::ng-deep canvas { height: 12rem !important; margin-top: -1rem; margin-bottom: 0; @@ -72,7 +72,7 @@ } &:hover { - @include box-shadow(0, 3px, 16px, .2px); + @include box-shadow(0, 3px, 16px, .2); } &:focus { diff --git a/src/Squidex/app/features/rules/pages/rules/rule-element.component.scss b/src/Squidex/app/features/rules/pages/rules/rule-element.component.scss index aab579f44..7c0f4f750 100644 --- a/src/Squidex/app/features/rules/pages/rules/rule-element.component.scss +++ b/src/Squidex/app/features/rules/pages/rules/rule-element.component.scss @@ -82,7 +82,9 @@ display: inline-block; } -/deep/ svg { - fill: $color-dark-foreground; - display: block; +::ng-deep { + svg { + fill: $color-dark-foreground; + display: block; + } } \ No newline at end of file diff --git a/src/Squidex/app/features/schemas/pages/schema/field-wizard.component.scss b/src/Squidex/app/features/schemas/pages/schema/field-wizard.component.scss index c828581c5..5a7bb98a7 100644 --- a/src/Squidex/app/features/schemas/pages/schema/field-wizard.component.scss +++ b/src/Squidex/app/features/schemas/pages/schema/field-wizard.component.scss @@ -3,8 +3,10 @@ $icon-size: 4.5rem; -:host /deep/ .table-items-row-details-tab { - padding: 1.5rem 1.75rem; +::ng-deep { + .table-items-row-details-tab { + padding: 1.5rem 1.75rem; + } } .form-group { diff --git a/src/Squidex/app/features/schemas/pages/schema/field-wizard.component.ts b/src/Squidex/app/features/schemas/pages/schema/field-wizard.component.ts index 100635708..0ce144904 100644 --- a/src/Squidex/app/features/schemas/pages/schema/field-wizard.component.ts +++ b/src/Squidex/app/features/schemas/pages/schema/field-wizard.component.ts @@ -29,7 +29,7 @@ const DEFAULT_FIELD = { name: '', partitioning: 'invariant', properties: createP templateUrl: './field-wizard.component.html' }) export class FieldWizardComponent implements OnInit { - @ViewChild('nameInput') + @ViewChild('nameInput', { static: false }) public nameInput: ElementRef; @Input() diff --git a/src/Squidex/app/features/schemas/pages/schemas/schema-form.component.scss b/src/Squidex/app/features/schemas/pages/schemas/schema-form.component.scss index 99b0c95da..5642dbe21 100644 --- a/src/Squidex/app/features/schemas/pages/schemas/schema-form.component.scss +++ b/src/Squidex/app/features/schemas/pages/schemas/schema-form.component.scss @@ -8,10 +8,12 @@ $icon-size: 4.5rem; margin-left: -.5rem; } -:host /deep/ .editor { - height: 15rem !important; - margin-bottom: .5rem; - margin-top: 0; +::ng-deep { + .editor { + height: 15rem !important; + margin-bottom: .5rem; + margin-top: 0; + } } .name-group { diff --git a/src/Squidex/app/features/settings/pages/roles/role.component.ts b/src/Squidex/app/features/settings/pages/roles/role.component.ts index 385fe6cf2..f72576839 100644 --- a/src/Squidex/app/features/settings/pages/roles/role.component.ts +++ b/src/Squidex/app/features/settings/pages/roles/role.component.ts @@ -40,7 +40,7 @@ export class RoleComponent implements OnChanges { @Input() public allPermissions: AutocompleteSource; - @ViewChild('addInput') + @ViewChild('addInput', { static: false }) public addPermissionInput: AutocompleteComponent; public isEditing = false; diff --git a/src/Squidex/app/framework/angular/forms/autocomplete.component.ts b/src/Squidex/app/framework/angular/forms/autocomplete.component.ts index 24115d8fa..5f90c45ef 100644 --- a/src/Squidex/app/framework/angular/forms/autocomplete.component.ts +++ b/src/Squidex/app/framework/angular/forms/autocomplete.component.ts @@ -52,10 +52,10 @@ export class AutocompleteComponent extends StatefulControlComponent; - @ViewChild('input') + @ViewChild('input', { static: false }) public inputControl: ElementRef; public queryInput = new FormControl(); diff --git a/src/Squidex/app/framework/angular/forms/code-editor.component.scss b/src/Squidex/app/framework/angular/forms/code-editor.component.scss index cb89af65e..0fb96d3fb 100644 --- a/src/Squidex/app/framework/angular/forms/code-editor.component.scss +++ b/src/Squidex/app/framework/angular/forms/code-editor.component.scss @@ -3,7 +3,7 @@ // sass-lint:disable class-name-format -:host /deep/ { +::ng-deep { .ace_editor { background: $color-dark-foreground; border: 1px solid $color-input; diff --git a/src/Squidex/app/framework/angular/forms/code-editor.component.ts b/src/Squidex/app/framework/angular/forms/code-editor.component.ts index 3bf6f7a04..caa716184 100644 --- a/src/Squidex/app/framework/angular/forms/code-editor.component.ts +++ b/src/Squidex/app/framework/angular/forms/code-editor.component.ts @@ -35,7 +35,7 @@ export class CodeEditorComponent extends ExternalControlComponent implem private value: string; private isDisabled = false; - @ViewChild('editor') + @ViewChild('editor', { static: false }) public editor: ElementRef; @Input() diff --git a/src/Squidex/app/framework/angular/forms/color-picker.component.scss b/src/Squidex/app/framework/angular/forms/color-picker.component.scss index 85b930ea9..8b35bf458 100644 --- a/src/Squidex/app/framework/angular/forms/color-picker.component.scss +++ b/src/Squidex/app/framework/angular/forms/color-picker.component.scss @@ -1,7 +1,7 @@ @import '_mixins'; @import '_vars'; -:host /deep/ { +::ng-deep { .color-picker { & { border-color: $color-border; diff --git a/src/Squidex/app/framework/angular/forms/date-time-editor.component.ts b/src/Squidex/app/framework/angular/forms/date-time-editor.component.ts index 8cffe33e9..9c0f06a54 100644 --- a/src/Squidex/app/framework/angular/forms/date-time-editor.component.ts +++ b/src/Squidex/app/framework/angular/forms/date-time-editor.component.ts @@ -41,7 +41,7 @@ export class DateTimeEditorComponent extends StatefulControlComponent<{}, string @Input() public hideClear: boolean; - @ViewChild('dateInput') + @ViewChild('dateInput', { static: false }) public dateInput: ElementRef; public timeControl = new FormControl(); diff --git a/src/Squidex/app/framework/angular/forms/iframe-editor.component.ts b/src/Squidex/app/framework/angular/forms/iframe-editor.component.ts index 5eb1115cc..f4badb851 100644 --- a/src/Squidex/app/framework/angular/forms/iframe-editor.component.ts +++ b/src/Squidex/app/framework/angular/forms/iframe-editor.component.ts @@ -26,7 +26,7 @@ export class IFrameEditorComponent extends ExternalControlComponent impleme private isDisabled = false; private isInitialized = false; - @ViewChild('iframe') + @ViewChild('iframe', { static: false }) public iframe: ElementRef; @Input() diff --git a/src/Squidex/app/framework/angular/forms/json-editor.component.scss b/src/Squidex/app/framework/angular/forms/json-editor.component.scss index cb89af65e..0fb96d3fb 100644 --- a/src/Squidex/app/framework/angular/forms/json-editor.component.scss +++ b/src/Squidex/app/framework/angular/forms/json-editor.component.scss @@ -3,7 +3,7 @@ // sass-lint:disable class-name-format -:host /deep/ { +::ng-deep { .ace_editor { background: $color-dark-foreground; border: 1px solid $color-input; diff --git a/src/Squidex/app/framework/angular/forms/json-editor.component.ts b/src/Squidex/app/framework/angular/forms/json-editor.component.ts index e2baa6854..0adf10a0a 100644 --- a/src/Squidex/app/framework/angular/forms/json-editor.component.ts +++ b/src/Squidex/app/framework/angular/forms/json-editor.component.ts @@ -32,7 +32,7 @@ export class JsonEditorComponent extends ExternalControlComponent implem private valueString: string; private isDisabled = false; - @ViewChild('editor') + @ViewChild('editor', { static: false }) public editor: ElementRef; constructor(changeDetector: ChangeDetectorRef, diff --git a/src/Squidex/app/framework/angular/forms/tag-editor.component.ts b/src/Squidex/app/framework/angular/forms/tag-editor.component.ts index df703254b..3649ab638 100644 --- a/src/Squidex/app/framework/angular/forms/tag-editor.component.ts +++ b/src/Squidex/app/framework/angular/forms/tag-editor.component.ts @@ -93,10 +93,10 @@ interface State { changeDetection: ChangeDetectionStrategy.OnPush }) export class TagEditorComponent extends StatefulControlComponent implements AfterViewInit, OnInit { - @ViewChild('form') + @ViewChild('form', { static: false }) public formElement: ElementRef; - @ViewChild('input') + @ViewChild('input', { static: false }) public inputElement: ElementRef; @Input() diff --git a/src/Squidex/app/framework/angular/modals/modal-dialog.component.ts b/src/Squidex/app/framework/angular/modals/modal-dialog.component.ts index d549ae62c..5bc25ec37 100644 --- a/src/Squidex/app/framework/angular/modals/modal-dialog.component.ts +++ b/src/Squidex/app/framework/angular/modals/modal-dialog.component.ts @@ -51,10 +51,10 @@ export class ModalDialogComponent extends StatefulComponent implements Af @Output() public close = new EventEmitter(); - @ViewChild('tabsElement') + @ViewChild('tabsElement', { static: false }) public tabsElement: ElementRef; - @ViewChild('footerElement') + @ViewChild('footerElement', { static: false }) public footerElement: ElementRef; constructor(changeDetector: ChangeDetectorRef) { diff --git a/src/Squidex/app/framework/angular/modals/root-view.component.ts b/src/Squidex/app/framework/angular/modals/root-view.component.ts index 2f3ec887c..5a53a9d79 100644 --- a/src/Squidex/app/framework/angular/modals/root-view.component.ts +++ b/src/Squidex/app/framework/angular/modals/root-view.component.ts @@ -14,6 +14,6 @@ import { ChangeDetectionStrategy, Component, ViewChild, ViewContainerRef } from changeDetection: ChangeDetectionStrategy.OnPush }) export class RootViewComponent { - @ViewChild('element', { read: ViewContainerRef }) + @ViewChild('element', { read: ViewContainerRef, static: false }) public viewContainer: ViewContainerRef; } \ No newline at end of file diff --git a/src/Squidex/app/framework/angular/panel.component.ts b/src/Squidex/app/framework/angular/panel.component.ts index 54bb5023d..46f5cd838 100644 --- a/src/Squidex/app/framework/angular/panel.component.ts +++ b/src/Squidex/app/framework/angular/panel.component.ts @@ -64,7 +64,7 @@ export class PanelComponent implements AfterViewInit, OnDestroy, OnInit { @Input() public sidebarClass = ''; - @ViewChild('panel') + @ViewChild('panel', { static: false }) public panel: ElementRef; constructor( diff --git a/src/Squidex/app/shared/components/asset.component.scss b/src/Squidex/app/shared/components/asset.component.scss index 58ab1e5d0..d155b89e4 100644 --- a/src/Squidex/app/shared/components/asset.component.scss +++ b/src/Squidex/app/shared/components/asset.component.scss @@ -44,7 +44,7 @@ $list-height: 2.375rem; padding: 0; } -:host /deep/ { +::ng-deep { .form-control { &.disabled, &:disabled { @@ -107,7 +107,8 @@ $list-height: 2.375rem; background: $color-dark-black; } - &-name, &-info { + &-name, + &-info { @include truncate; } diff --git a/src/Squidex/app/shared/components/assets-selector.component.scss b/src/Squidex/app/shared/components/assets-selector.component.scss index 4a020bd99..0438b80c5 100644 --- a/src/Squidex/app/shared/components/assets-selector.component.scss +++ b/src/Squidex/app/shared/components/assets-selector.component.scss @@ -1,7 +1,7 @@ @import '_vars'; @import '_mixins'; -:host /deep/ { +::ng-deep { .search { .form-control { @include border-radius-right; diff --git a/src/Squidex/app/shared/components/geolocation-editor.component.ts b/src/Squidex/app/shared/components/geolocation-editor.component.ts index 00de85805..6de6e97bf 100644 --- a/src/Squidex/app/shared/components/geolocation-editor.component.ts +++ b/src/Squidex/app/shared/components/geolocation-editor.component.ts @@ -64,10 +64,10 @@ export class GeolocationEditorComponent extends StatefulControlComponent; - @ViewChild('searchBox') + @ViewChild('searchBox', { static: false }) public searchBoxInput: ElementRef; constructor(changeDetector: ChangeDetectorRef, diff --git a/src/Squidex/app/shared/components/history-list.component.scss b/src/Squidex/app/shared/components/history-list.component.scss index 5c1e18804..5226994c0 100644 --- a/src/Squidex/app/shared/components/history-list.component.scss +++ b/src/Squidex/app/shared/components/history-list.component.scss @@ -1,7 +1,7 @@ @import '_vars'; @import '_mixins'; -:host /deep/ { +::ng-deep { .user-ref { color: $color-title; } diff --git a/src/Squidex/app/shared/components/markdown-editor.component.ts b/src/Squidex/app/shared/components/markdown-editor.component.ts index 237f33a6c..24a155f37 100644 --- a/src/Squidex/app/shared/components/markdown-editor.component.ts +++ b/src/Squidex/app/shared/components/markdown-editor.component.ts @@ -40,13 +40,13 @@ export class MarkdownEditorComponent extends StatefulControlComponent i private value: string; private isDisabled = false; - @ViewChild('editor') + @ViewChild('editor', { static: false }) public editor: ElementRef; @Output() diff --git a/src/Squidex/app/shell/pages/internal/internal-area.component.scss b/src/Squidex/app/shell/pages/internal/internal-area.component.scss index f2d93d283..d31100410 100644 --- a/src/Squidex/app/shell/pages/internal/internal-area.component.scss +++ b/src/Squidex/app/shell/pages/internal/internal-area.component.scss @@ -2,7 +2,7 @@ @import '_mixins'; .navbar { - @include box-shadow(0, 3px, 5px, .13px); + @include box-shadow(0, 3px, 5px, .13); display: block; } diff --git a/src/Squidex/app/shims.ts b/src/Squidex/app/shims.ts index 779923fd5..4c18a84a4 100644 --- a/src/Squidex/app/shims.ts +++ b/src/Squidex/app/shims.ts @@ -5,20 +5,93 @@ * Copyright (c) Squidex UG (haftungsbeschränkt). All rights reserved. */ -import 'core-js/es6/array'; -import 'core-js/es6/date'; -import 'core-js/es6/function'; -import 'core-js/es6/map'; -import 'core-js/es6/math'; -import 'core-js/es6/number'; -import 'core-js/es6/object'; -import 'core-js/es6/parse-float'; -import 'core-js/es6/parse-int'; -import 'core-js/es6/reflect'; -import 'core-js/es6/regexp'; -import 'core-js/es6/set'; -import 'core-js/es6/string'; -import 'core-js/es6/symbol'; - -import 'core-js/es7/reflect'; +// ES2015 symbol capabilities +import 'core-js/modules/es.symbol'; + +// ES2015 function capabilities +import 'core-js/modules/es.function.bind'; +import 'core-js/modules/es.function.has-instance'; +import 'core-js/modules/es.function.name'; + +// ES2015 object capabilities +import 'core-js/modules/es.object.assign'; +import 'core-js/modules/es.object.create'; +import 'core-js/modules/es.object.define-properties'; +import 'core-js/modules/es.object.define-property'; +import 'core-js/modules/es.object.freeze'; +import 'core-js/modules/es.object.get-own-property-descriptor'; +import 'core-js/modules/es.object.get-own-property-names'; +import 'core-js/modules/es.object.get-prototype-of'; +import 'core-js/modules/es.object.is'; +import 'core-js/modules/es.object.is-extensible'; +import 'core-js/modules/es.object.is-frozen'; +import 'core-js/modules/es.object.is-sealed'; +import 'core-js/modules/es.object.keys'; +import 'core-js/modules/es.object.prevent-extensions'; +import 'core-js/modules/es.object.seal'; +import 'core-js/modules/es.object.set-prototype-of'; +import 'core-js/modules/es.object.to-string'; + +// ES2015 array capabilities +import 'core-js/modules/es.array.copy-within'; +import 'core-js/modules/es.array.every'; +import 'core-js/modules/es.array.fill'; +import 'core-js/modules/es.array.filter'; +import 'core-js/modules/es.array.find'; +import 'core-js/modules/es.array.find-index'; +import 'core-js/modules/es.array.for-each'; +import 'core-js/modules/es.array.from'; +import 'core-js/modules/es.array.index-of'; +import 'core-js/modules/es.array.is-array'; +import 'core-js/modules/es.array.iterator'; +import 'core-js/modules/es.array.join'; +import 'core-js/modules/es.array.last-index-of'; +import 'core-js/modules/es.array.map'; +import 'core-js/modules/es.array.of'; +import 'core-js/modules/es.array.reduce'; +import 'core-js/modules/es.array.reduce-right'; +import 'core-js/modules/es.array.slice'; +import 'core-js/modules/es.array.some'; +import 'core-js/modules/es.array.sort'; + +// ES2015 string capabilities +import 'core-js/modules/es.string.anchor'; +import 'core-js/modules/es.string.big'; +import 'core-js/modules/es.string.blink'; +import 'core-js/modules/es.string.bold'; +import 'core-js/modules/es.string.code-point-at'; +import 'core-js/modules/es.string.ends-with'; +import 'core-js/modules/es.string.fixed'; +import 'core-js/modules/es.string.fontcolor'; +import 'core-js/modules/es.string.fontsize'; +import 'core-js/modules/es.string.from-code-point'; +import 'core-js/modules/es.string.includes'; +import 'core-js/modules/es.string.italics'; +import 'core-js/modules/es.string.iterator'; +import 'core-js/modules/es.string.link'; +import 'core-js/modules/es.string.raw'; +import 'core-js/modules/es.string.repeat'; +import 'core-js/modules/es.string.small'; +import 'core-js/modules/es.string.starts-with'; +import 'core-js/modules/es.string.strike'; +import 'core-js/modules/es.string.sub'; +import 'core-js/modules/es.string.sup'; +import 'core-js/modules/es.string.trim'; + +import 'core-js/modules/es.parse-float'; +import 'core-js/modules/es.parse-int'; + +import 'core-js/es/date'; +import 'core-js/es/math'; +import 'core-js/es/number'; +import 'core-js/es/regexp'; + +import 'core-js/modules/es.map'; +import 'core-js/modules/es.promise'; +import 'core-js/modules/es.set'; +import 'core-js/modules/es.weak-map'; +import 'core-js/modules/web.dom-collections.iterator'; + +import 'core-js/proposals/reflect-metadata'; + import 'zone.js/dist/zone'; \ No newline at end of file diff --git a/src/Squidex/app/theme/_bootstrap.scss b/src/Squidex/app/theme/_bootstrap.scss index a59dffcc0..20f9b0077 100644 --- a/src/Squidex/app/theme/_bootstrap.scss +++ b/src/Squidex/app/theme/_bootstrap.scss @@ -162,7 +162,7 @@ a { .dropdown-menu { // White dropdown menu without border and shadow. & { - @include box-shadow(0, 3px, 16px, .2px); + @include box-shadow(0, 3px, 16px, .2); border: 0; background: $panel-light-background; } diff --git a/src/Squidex/package-lock.json b/src/Squidex/package-lock.json index 3051cf82b..183d8b57a 100644 --- a/src/Squidex/package-lock.json +++ b/src/Squidex/package-lock.json @@ -5,22 +5,22 @@ "requires": true, "dependencies": { "@angular-devkit/core": { - "version": "7.3.8", - "resolved": "https://registry.npmjs.org/@angular-devkit/core/-/core-7.3.8.tgz", - "integrity": "sha512-3X9uzaZXFpm5o2TSzhD6wEOtVU32CgeytKjD1Scxj+uMMVo48SWLlKiFh312T+smI9ko7tOT8VqxglwYkWosgg==", + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/@angular-devkit/core/-/core-8.0.1.tgz", + "integrity": "sha512-GQtspR2umZeuTUDTLy2dpUstvQfK7oAwE0o+rWSa8mx0DyhYssrfBbvfE4GzUzKp6OSz1sbZAatSO+iimZjbQw==", "dev": true, "requires": { - "ajv": "6.9.1", - "chokidar": "2.0.4", + "ajv": "6.10.0", "fast-json-stable-stringify": "2.0.0", - "rxjs": "6.3.3", + "magic-string": "0.25.2", + "rxjs": "6.4.0", "source-map": "0.7.3" }, "dependencies": { "ajv": { - "version": "6.9.1", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.9.1.tgz", - "integrity": "sha512-XDN92U311aINL77ieWHmqCcNlwjoP5cHXDxIxbf2MaPYuCXOHS7gHH8jktxeK5omgd52XbSTX6a4Piwd1pQmzA==", + "version": "6.10.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.10.0.tgz", + "integrity": "sha512-nffhOpkymDECQyR0mnsUtoCE8RlX38G0rYP+wgLWFyZuUyuuojSSvi/+euOiQBIn63whYwYVIIH1TvE3tu4OEg==", "dev": true, "requires": { "fast-deep-equal": "^2.0.1", @@ -29,6 +29,88 @@ "uri-js": "^4.2.2" } }, + "fast-deep-equal": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-2.0.1.tgz", + "integrity": "sha1-ewUhjd+WZ79/Nwv3/bLLFf3Qqkk=", + "dev": true + }, + "json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true + }, + "rxjs": { + "version": "6.4.0", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.4.0.tgz", + "integrity": "sha512-Z9Yfa11F6B9Sg/BK9MnqnQ+aQYicPLtilXBp2yUtDt2JRCE0h26d33EnfO3ZxoNxG0T92OUucP3Ct7cpfkdFfw==", + "dev": true, + "requires": { + "tslib": "^1.9.0" + } + }, + "source-map": { + "version": "0.7.3", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.3.tgz", + "integrity": "sha512-CkCj6giN3S+n9qrYiBTX5gystlENnRW5jZeNLHpe6aue+SrHcG5VYwujhW9s4dY31mEGsxBDrHR6oI69fTXsaQ==", + "dev": true + }, + "uri-js": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.2.2.tgz", + "integrity": "sha512-KY9Frmirql91X2Qgjry0Wd4Y+YTdrdZheS8TFwvkbLWf/G5KNJDCh6pKL5OZctEW4+0Baa5idK2ZQuELRwPznQ==", + "dev": true, + "requires": { + "punycode": "^2.1.0" + } + } + } + }, + "@angular/animations": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/@angular/animations/-/animations-8.0.0.tgz", + "integrity": "sha512-hggSRi83rmocLwzrKZtmFcqPdivKSJqp2yiYaiNmJ2yQWJ1JW/Lurypv9H347RWxmwCCwC2kV8embTGbOXIFDQ==", + "requires": { + "tslib": "^1.9.0" + } + }, + "@angular/common": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/@angular/common/-/common-8.0.0.tgz", + "integrity": "sha512-iOAJZ0+1zTRHnHE/5G30+4Q66W1pfZkSkxZIXvgijZ+wtuNloYdWNy/IdZ/m7ayBI7A6FsYEhyMUoWz2HVEJNw==", + "requires": { + "tslib": "^1.9.0" + } + }, + "@angular/compiler": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/@angular/compiler/-/compiler-8.0.0.tgz", + "integrity": "sha512-4rKsVFMNykF83tPL1VE1+j9kZ3cWHUsLOAB/VqmF64EcR/GsbjKog2v23rSso5kqUtPiVq/FWGYllW6qMdxtJA==", + "dev": true, + "requires": { + "tslib": "^1.9.0" + } + }, + "@angular/compiler-cli": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/@angular/compiler-cli/-/compiler-cli-8.0.0.tgz", + "integrity": "sha512-Z0U0Ih8A7V3J1gq7AXnXbrGAD2ERmz7JbREJJRHDWiUNxIqGQiV3Odo1V8FL5n/cKvLwSYM2Ubvk10gb0+3njA==", + "dev": true, + "requires": { + "canonical-path": "1.0.0", + "chokidar": "^2.1.1", + "convert-source-map": "^1.5.1", + "dependency-graph": "^0.7.2", + "magic-string": "^0.25.0", + "minimist": "^1.2.0", + "reflect-metadata": "^0.1.2", + "shelljs": "^0.8.1", + "source-map": "^0.6.1", + "tslib": "^1.9.0", + "yargs": "13.1.0" + }, + "dependencies": { "anymatch": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-2.0.0.tgz", @@ -37,6 +119,17 @@ "requires": { "micromatch": "^3.1.4", "normalize-path": "^2.1.1" + }, + "dependencies": { + "normalize-path": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz", + "integrity": "sha1-GrKLVW4Zg2Oowab35vogE3/mrtk=", + "dev": true, + "requires": { + "remove-trailing-separator": "^1.0.1" + } + } } }, "arr-diff": { @@ -81,24 +174,23 @@ } }, "chokidar": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-2.0.4.tgz", - "integrity": "sha512-z9n7yt9rOvIJrMhvDtDictKrkFHeihkNl6uWMmZlmL6tJtX9Cs+87oK+teBx+JIgzvbX3yZHT3eF8vpbDxHJXQ==", + "version": "2.1.6", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-2.1.6.tgz", + "integrity": "sha512-V2jUo67OKkc6ySiRpJrjlpJKl9kDuG+Xb8VgsGzb+aEouhgS1D0weyPU4lEzdAcsCAvrih2J2BqyXqHWvVLw5g==", "dev": true, "requires": { "anymatch": "^2.0.0", - "async-each": "^1.0.0", - "braces": "^2.3.0", - "fsevents": "^1.2.2", + "async-each": "^1.0.1", + "braces": "^2.3.2", + "fsevents": "^1.2.7", "glob-parent": "^3.1.0", - "inherits": "^2.0.1", + "inherits": "^2.0.3", "is-binary-path": "^1.0.0", "is-glob": "^4.0.0", - "lodash.debounce": "^4.0.8", - "normalize-path": "^2.1.1", + "normalize-path": "^3.0.0", "path-is-absolute": "^1.0.0", - "readdirp": "^2.0.0", - "upath": "^1.0.5" + "readdirp": "^2.2.1", + "upath": "^1.1.1" } }, "expand-brackets": { @@ -229,12 +321,6 @@ } } }, - "fast-deep-equal": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-2.0.1.tgz", - "integrity": "sha1-ewUhjd+WZ79/Nwv3/bLLFf3Qqkk=", - "dev": true - }, "fill-range": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", @@ -258,486 +344,59 @@ } } }, - "glob-parent": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-3.1.0.tgz", - "integrity": "sha1-nmr2KZ2NO9K9QEMIMr0RPfkGxa4=", + "fsevents": { + "version": "1.2.9", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.2.9.tgz", + "integrity": "sha512-oeyj2H3EjjonWcFjD5NvZNE9Rqe4UW+nQBU2HNeKw0koVLEFIhtyETyAakeAM3de7Z/SW5kcA+fZUait9EApnw==", "dev": true, + "optional": true, "requires": { - "is-glob": "^3.1.0", - "path-dirname": "^1.0.0" + "nan": "^2.12.1", + "node-pre-gyp": "^0.12.0" }, "dependencies": { - "is-glob": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz", - "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=", + "abbrev": { + "version": "1.1.1", + "bundled": true, + "dev": true, + "optional": true + }, + "ansi-regex": { + "version": "2.1.1", + "bundled": true, + "dev": true, + "optional": true + }, + "aproba": { + "version": "1.2.0", + "bundled": true, + "dev": true, + "optional": true + }, + "are-we-there-yet": { + "version": "1.1.5", + "bundled": true, "dev": true, + "optional": true, "requires": { - "is-extglob": "^2.1.0" + "delegates": "^1.0.0", + "readable-stream": "^2.0.6" } - } - } - }, - "is-accessor-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", - "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", - "dev": true, - "requires": { - "kind-of": "^6.0.0" - } - }, - "is-data-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", - "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", - "dev": true, - "requires": { - "kind-of": "^6.0.0" - } - }, - "is-descriptor": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", - "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", - "dev": true, - "requires": { - "is-accessor-descriptor": "^1.0.0", - "is-data-descriptor": "^1.0.0", - "kind-of": "^6.0.2" - } - }, - "is-extglob": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", - "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=", - "dev": true - }, - "is-glob": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.1.tgz", - "integrity": "sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg==", - "dev": true, - "requires": { - "is-extglob": "^2.1.1" - } - }, - "is-number": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", - "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", - "dev": true, - "requires": { - "kind-of": "^3.0.2" - }, - "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + }, + "balanced-match": { + "version": "1.0.0", + "bundled": true, + "dev": true, + "optional": true + }, + "brace-expansion": { + "version": "1.1.11", + "bundled": true, "dev": true, + "optional": true, "requires": { - "is-buffer": "^1.1.5" - } - } - } - }, - "isobject": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", - "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", - "dev": true - }, - "json-schema-traverse": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", - "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", - "dev": true - }, - "kind-of": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", - "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==", - "dev": true - }, - "micromatch": { - "version": "3.1.10", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", - "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", - "dev": true, - "requires": { - "arr-diff": "^4.0.0", - "array-unique": "^0.3.2", - "braces": "^2.3.1", - "define-property": "^2.0.2", - "extend-shallow": "^3.0.2", - "extglob": "^2.0.4", - "fragment-cache": "^0.2.1", - "kind-of": "^6.0.2", - "nanomatch": "^1.2.9", - "object.pick": "^1.3.0", - "regex-not": "^1.0.0", - "snapdragon": "^0.8.1", - "to-regex": "^3.0.2" - } - }, - "rxjs": { - "version": "6.3.3", - "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.3.3.tgz", - "integrity": "sha512-JTWmoY9tWCs7zvIk/CvRjhjGaOd+OVBM987mxFo+OW66cGpdKjZcpmc74ES1sB//7Kl/PAe8+wEakuhG4pcgOw==", - "dev": true, - "requires": { - "tslib": "^1.9.0" - } - }, - "source-map": { - "version": "0.7.3", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.3.tgz", - "integrity": "sha512-CkCj6giN3S+n9qrYiBTX5gystlENnRW5jZeNLHpe6aue+SrHcG5VYwujhW9s4dY31mEGsxBDrHR6oI69fTXsaQ==", - "dev": true - }, - "uri-js": { - "version": "4.2.2", - "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.2.2.tgz", - "integrity": "sha512-KY9Frmirql91X2Qgjry0Wd4Y+YTdrdZheS8TFwvkbLWf/G5KNJDCh6pKL5OZctEW4+0Baa5idK2ZQuELRwPznQ==", - "dev": true, - "requires": { - "punycode": "^2.1.0" - } - } - } - }, - "@angular/animations": { - "version": "7.2.14", - "resolved": "https://registry.npmjs.org/@angular/animations/-/animations-7.2.14.tgz", - "integrity": "sha512-K+wdq7TslmvDhrbwy65x7owE8wezI0fDdO+8SO9RU4m/w6R6vo4QS3uSdc5I2pxwm4QSXSc5eKhoWJkq0muTbQ==", - "requires": { - "tslib": "^1.9.0" - } - }, - "@angular/common": { - "version": "7.2.14", - "resolved": "https://registry.npmjs.org/@angular/common/-/common-7.2.14.tgz", - "integrity": "sha512-c2QBhVpbQhg1FDhOQkyVdFvU11mfvYHW5ZaXzxdCpq2rZXCureYiCSnlv++EsIAKqi22+2a6GACHF9Gh8kBmSg==", - "requires": { - "tslib": "^1.9.0" - } - }, - "@angular/compiler": { - "version": "7.2.14", - "resolved": "https://registry.npmjs.org/@angular/compiler/-/compiler-7.2.14.tgz", - "integrity": "sha512-Idhs+5HIzx+1+hrXIDaRpSqobMB7UvSvPlvCvtb3EDYjmltTNG68TtwMzGM8W2jdayliYuFOjFrnw1wCTkK3Ag==", - "dev": true, - "requires": { - "tslib": "^1.9.0" - } - }, - "@angular/compiler-cli": { - "version": "7.2.14", - "resolved": "https://registry.npmjs.org/@angular/compiler-cli/-/compiler-cli-7.2.14.tgz", - "integrity": "sha512-w5qn1nIPjiCP3WdbqicofpKpiRlh6NMYjWhe6mJysSBnVd34aSuGisYW/gVPQrmD46E1gmfpWTnWPeABVnjj6w==", - "dev": true, - "requires": { - "canonical-path": "1.0.0", - "chokidar": "^2.1.1", - "convert-source-map": "^1.5.1", - "dependency-graph": "^0.7.2", - "magic-string": "^0.25.0", - "minimist": "^1.2.0", - "reflect-metadata": "^0.1.2", - "shelljs": "^0.8.1", - "source-map": "^0.6.1", - "tslib": "^1.9.0", - "yargs": "9.0.1" - }, - "dependencies": { - "anymatch": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-2.0.0.tgz", - "integrity": "sha512-5teOsQWABXHHBFP9y3skS5P3d/WfWXpv3FUpy+LorMrNYaT9pI4oLMQX7jzQ2KklNpGpWHzdCXTDT2Y3XGlZBw==", - "dev": true, - "requires": { - "micromatch": "^3.1.4", - "normalize-path": "^2.1.1" - }, - "dependencies": { - "normalize-path": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz", - "integrity": "sha1-GrKLVW4Zg2Oowab35vogE3/mrtk=", - "dev": true, - "requires": { - "remove-trailing-separator": "^1.0.1" - } - } - } - }, - "arr-diff": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz", - "integrity": "sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA=", - "dev": true - }, - "array-unique": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz", - "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=", - "dev": true - }, - "braces": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", - "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", - "dev": true, - "requires": { - "arr-flatten": "^1.1.0", - "array-unique": "^0.3.2", - "extend-shallow": "^2.0.1", - "fill-range": "^4.0.0", - "isobject": "^3.0.1", - "repeat-element": "^1.1.2", - "snapdragon": "^0.8.1", - "snapdragon-node": "^2.0.1", - "split-string": "^3.0.2", - "to-regex": "^3.0.1" - }, - "dependencies": { - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "requires": { - "is-extendable": "^0.1.0" - } - } - } - }, - "chokidar": { - "version": "2.1.5", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-2.1.5.tgz", - "integrity": "sha512-i0TprVWp+Kj4WRPtInjexJ8Q+BqTE909VpH8xVhXrJkoc5QC8VO9TryGOqTr+2hljzc1sC62t22h5tZePodM/A==", - "dev": true, - "requires": { - "anymatch": "^2.0.0", - "async-each": "^1.0.1", - "braces": "^2.3.2", - "fsevents": "^1.2.7", - "glob-parent": "^3.1.0", - "inherits": "^2.0.3", - "is-binary-path": "^1.0.0", - "is-glob": "^4.0.0", - "normalize-path": "^3.0.0", - "path-is-absolute": "^1.0.0", - "readdirp": "^2.2.1", - "upath": "^1.1.1" - } - }, - "expand-brackets": { - "version": "2.1.4", - "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz", - "integrity": "sha1-t3c14xXOMPa27/D4OwQVGiJEliI=", - "dev": true, - "requires": { - "debug": "^2.3.3", - "define-property": "^0.2.5", - "extend-shallow": "^2.0.1", - "posix-character-classes": "^0.1.0", - "regex-not": "^1.0.0", - "snapdragon": "^0.8.1", - "to-regex": "^3.0.1" - }, - "dependencies": { - "define-property": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", - "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", - "dev": true, - "requires": { - "is-descriptor": "^0.1.0" - } - }, - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "requires": { - "is-extendable": "^0.1.0" - } - }, - "is-accessor-descriptor": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", - "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", - "dev": true, - "requires": { - "kind-of": "^3.0.2" - }, - "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "requires": { - "is-buffer": "^1.1.5" - } - } - } - }, - "is-data-descriptor": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", - "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", - "dev": true, - "requires": { - "kind-of": "^3.0.2" - }, - "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "requires": { - "is-buffer": "^1.1.5" - } - } - } - }, - "is-descriptor": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", - "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", - "dev": true, - "requires": { - "is-accessor-descriptor": "^0.1.6", - "is-data-descriptor": "^0.1.4", - "kind-of": "^5.0.0" - } - }, - "kind-of": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", - "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", - "dev": true - } - } - }, - "extglob": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/extglob/-/extglob-2.0.4.tgz", - "integrity": "sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw==", - "dev": true, - "requires": { - "array-unique": "^0.3.2", - "define-property": "^1.0.0", - "expand-brackets": "^2.1.4", - "extend-shallow": "^2.0.1", - "fragment-cache": "^0.2.1", - "regex-not": "^1.0.0", - "snapdragon": "^0.8.1", - "to-regex": "^3.0.1" - }, - "dependencies": { - "define-property": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", - "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", - "dev": true, - "requires": { - "is-descriptor": "^1.0.0" - } - }, - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "requires": { - "is-extendable": "^0.1.0" - } - } - } - }, - "fill-range": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", - "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=", - "dev": true, - "requires": { - "extend-shallow": "^2.0.1", - "is-number": "^3.0.0", - "repeat-string": "^1.6.1", - "to-regex-range": "^2.1.0" - }, - "dependencies": { - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "requires": { - "is-extendable": "^0.1.0" - } - } - } - }, - "fsevents": { - "version": "1.2.8", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.2.8.tgz", - "integrity": "sha512-tPvHgPGB7m40CZ68xqFGkKuzN+RnpGmSV+hgeKxhRpbxdqKXUFJGC3yonBOLzQBcJyGpdZFDfCsdOC2KFsXzeA==", - "dev": true, - "optional": true, - "requires": { - "nan": "^2.12.1", - "node-pre-gyp": "^0.12.0" - }, - "dependencies": { - "abbrev": { - "version": "1.1.1", - "bundled": true, - "dev": true, - "optional": true - }, - "ansi-regex": { - "version": "2.1.1", - "bundled": true, - "dev": true, - "optional": true - }, - "aproba": { - "version": "1.2.0", - "bundled": true, - "dev": true, - "optional": true - }, - "are-we-there-yet": { - "version": "1.1.5", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "delegates": "^1.0.0", - "readable-stream": "^2.0.6" - } - }, - "balanced-match": { - "version": "1.0.0", - "bundled": true, - "dev": true, - "optional": true - }, - "brace-expansion": { - "version": "1.1.11", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" } }, "chownr": { @@ -1352,9 +1011,9 @@ } }, "nan": { - "version": "2.13.2", - "resolved": "https://registry.npmjs.org/nan/-/nan-2.13.2.tgz", - "integrity": "sha512-TghvYc72wlMGMVMluVo9WRJc0mB8KxxF/gZ4YYFy7V2ZQX9l7rgbPg7vjS9mt6U5HXODVFVI2bOduCzwOMv/lw==", + "version": "2.14.0", + "resolved": "https://registry.npmjs.org/nan/-/nan-2.14.0.tgz", + "integrity": "sha512-INOFj37C7k3AfaNTtX8RhsTw7qRy7eLET14cROi9+5HAVbbHuIWUHEauBv5qT4Av2tWasiTY1Jw6puUNqRJXQg==", "dev": true, "optional": true }, @@ -1378,59 +1037,59 @@ } }, "@angular/core": { - "version": "7.2.14", - "resolved": "https://registry.npmjs.org/@angular/core/-/core-7.2.14.tgz", - "integrity": "sha512-XeZZJCyBKSKo0E/7Ef0SfJejmn+E7uBXa5cR1QapafS0Hnrq/hZu/NI039IDU/51NoycMDH2vTV19SmKu9Mkow==", + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/@angular/core/-/core-8.0.0.tgz", + "integrity": "sha512-mrkP1PTzqCmZGLYll+TDyawLXHzi+FcRPqSuRxCmDMthUUE93SLXT2yISDkx9aMPtFKgFr6KfrIkKuCz16BP/g==", "requires": { "tslib": "^1.9.0" } }, "@angular/forms": { - "version": "7.2.14", - "resolved": "https://registry.npmjs.org/@angular/forms/-/forms-7.2.14.tgz", - "integrity": "sha512-jL5YbTk7VZmz4l0++iFVUNa1vGM+nnALjHKi1Ub8VWioRDRboYUsHyxzlgWW9gZRbHpnLEXFiUz1td+v7TouJw==", + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/@angular/forms/-/forms-8.0.0.tgz", + "integrity": "sha512-T6XdG3mALWzvnrN3fA1hAmfwvraiF1SPMWNXgPk2riuMf8CFdoro+tQZ4eo1islHrTTw5QzmqN8JJALfhAG6bg==", "requires": { "tslib": "^1.9.0" } }, "@angular/http": { - "version": "7.2.14", - "resolved": "https://registry.npmjs.org/@angular/http/-/http-7.2.14.tgz", - "integrity": "sha512-rSdH2JojApDU83qVm7RabIlNo3Ni3yr2gwsmQWs4XZ7SC8jLNnDkzdUbQ6T0vfuVX3v/FtAuMJl0yaVcG3EUJg==", + "version": "7.2.15", + "resolved": "https://registry.npmjs.org/@angular/http/-/http-7.2.15.tgz", + "integrity": "sha512-TR7PEdmLWNIre3Zn8lvyb4lSrvPUJhKLystLnp4hBMcWsJqq5iK8S3bnlR4viZ9HMlf7bW7+Hm4SI6aB3tdUtw==", "requires": { "tslib": "^1.9.0" } }, "@angular/platform-browser": { - "version": "7.2.14", - "resolved": "https://registry.npmjs.org/@angular/platform-browser/-/platform-browser-7.2.14.tgz", - "integrity": "sha512-yAq2+3W4J4B48HEmZYQucdEb9AHwRnv72q9CC/SxU7g59vaLhl1nv7cAWGJ4XFaJTbB7aB4Y4rLffuR+Gxkn7A==", + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/@angular/platform-browser/-/platform-browser-8.0.0.tgz", + "integrity": "sha512-fTD+pTMbq+On9Uv3VXiei2lfuX7GX31dngm/Y4yWTFeW6eXy0+7kkfflzpLOb0hykCZvcXzarqCuEBBYNLrrOg==", "requires": { "tslib": "^1.9.0" } }, "@angular/platform-browser-dynamic": { - "version": "7.2.14", - "resolved": "https://registry.npmjs.org/@angular/platform-browser-dynamic/-/platform-browser-dynamic-7.2.14.tgz", - "integrity": "sha512-lmTCBiDRbOPtniIqBjm1n5jl1TdyQM0qWQdBcoCsKpMNS/6/RacRcQsJZApAMdWm6gIVuLgmRQzaCLkSoekfYA==", + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/@angular/platform-browser-dynamic/-/platform-browser-dynamic-8.0.0.tgz", + "integrity": "sha512-dx7W7JoSFbsveexjZ/BPlsXbMDLWVLmRCo7IqLvibMrTbdpaaOCNJIXJk1X+f7JJrQ7SwlZaVkoLCMoDWw6fmA==", "requires": { "tslib": "^1.9.0" } }, "@angular/platform-server": { - "version": "7.2.14", - "resolved": "https://registry.npmjs.org/@angular/platform-server/-/platform-server-7.2.14.tgz", - "integrity": "sha512-ijFqRrxpbPQiAlbRtw0uKX8Qf+wWZhY5vNwV8wfP5oVziJdO7Vdtcmmw2NQxHAIHUrK7FQ5yklUxfglKa2G7SQ==", + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/@angular/platform-server/-/platform-server-8.0.0.tgz", + "integrity": "sha512-pA6m1okOfyy2qH5A6jUxrhx6z7eAG+ne7IM+j/6JUBDjp4KO9BC84aa/xfpZq5dsskl8E8II9c4hUKocMyeRjA==", "requires": { - "domino": "^2.1.0", + "domino": "^2.1.2", "tslib": "^1.9.0", "xhr2": "^0.1.4" } }, "@angular/router": { - "version": "7.2.14", - "resolved": "https://registry.npmjs.org/@angular/router/-/router-7.2.14.tgz", - "integrity": "sha512-uqg0SKy79voEOIOvzVbCzFDD9XOAfZWkYt01ca2qLFXMx+6jWeVQIDuXc8Dmz5udIXNK5Ae//9R+nt5UZUZrSA==", + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/@angular/router/-/router-8.0.0.tgz", + "integrity": "sha512-DGUTb8qpndE5m716xh00GxuC8o7qamlqbUruGB+SQD6ynU7s5yLGxtKffxqb1BT63+YewpsVxc2Koruvb1qjDw==", "requires": { "tslib": "^1.9.0" } @@ -1606,22 +1265,22 @@ } }, "@ngtools/webpack": { - "version": "7.3.8", - "resolved": "https://registry.npmjs.org/@ngtools/webpack/-/webpack-7.3.8.tgz", - "integrity": "sha512-gfjSKz+F/2T4tZHpnQ1XqelKP/CIfI87XdoHsOI53ceTUrAkVKsOb3ULmEfkcdsdQZ/HhmCiLivcutHcW8xkhQ==", + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/@ngtools/webpack/-/webpack-8.0.1.tgz", + "integrity": "sha512-ly+KyzD5S8dVbwDv4pWt8+NNevPskmdXYJVxa068nE1dQV+CCK4mi6aR0GqrRR9zPvhgRoQKK8tMbN6WDCJS7g==", "dev": true, "requires": { - "@angular-devkit/core": "7.3.8", + "@angular-devkit/core": "8.0.1", "enhanced-resolve": "4.1.0", - "rxjs": "6.3.3", + "rxjs": "6.4.0", "tree-kill": "1.2.1", "webpack-sources": "1.3.0" }, "dependencies": { "rxjs": { - "version": "6.3.3", - "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.3.3.tgz", - "integrity": "sha512-JTWmoY9tWCs7zvIk/CvRjhjGaOd+OVBM987mxFo+OW66cGpdKjZcpmc74ES1sB//7Kl/PAe8+wEakuhG4pcgOw==", + "version": "6.4.0", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.4.0.tgz", + "integrity": "sha512-Z9Yfa11F6B9Sg/BK9MnqnQ+aQYicPLtilXBp2yUtDt2JRCE0h26d33EnfO3ZxoNxG0T92OUucP3Ct7cpfkdFfw==", "dev": true, "requires": { "tslib": "^1.9.0" @@ -1645,10 +1304,27 @@ "integrity": "sha512-qjkHL3wF0JMHMqgm/kmL8Pf8rIiqvueEiZ0g6NVTcBX1WN46GWDr+V5z+gsHUeL0n8TfAmXnYmF7ajsxmBp4PQ==", "dev": true }, + "@types/events": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@types/events/-/events-3.0.0.tgz", + "integrity": "sha512-EaObqwIvayI5a8dCzhFrjKzVwKLxjoG9T6Ppd5CEo07LRKfQ8Yokw54r5+Wq7FaBQ+yXRvQAYPrHwya1/UFt9g==", + "dev": true + }, + "@types/glob": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/@types/glob/-/glob-7.1.1.tgz", + "integrity": "sha512-1Bh06cbWJUHMC97acuD6UMG29nMt0Aqz1vF3guLfG+kHHJhy3AyohZFFxYk2f7Q1SQIrNwvncxAE0N/9s70F2w==", + "dev": true, + "requires": { + "@types/events": "*", + "@types/minimatch": "*", + "@types/node": "*" + } + }, "@types/jasmine": { - "version": "3.3.12", - "resolved": "https://registry.npmjs.org/@types/jasmine/-/jasmine-3.3.12.tgz", - "integrity": "sha512-lXvr2xFQEVQLkIhuGaR3GC1L9lMU1IxeWnAF/wNY5ZWpC4p9dgxkKkzMp7pntpAdv9pZSnYqgsBkCg32MXSZMg==", + "version": "3.3.13", + "resolved": "https://registry.npmjs.org/@types/jasmine/-/jasmine-3.3.13.tgz", + "integrity": "sha512-iczmLoIiVymaD1TIr2UctxjFkNEslVE/QtNAUmpDsD71cZfZBAsPCUv1Y+8AwsfA8bLx2ccr7d95T9w/UAirlQ==", "dev": true }, "@types/json5": { @@ -1663,6 +1339,12 @@ "integrity": "sha512-6kBKf64aVfx93UJrcyEZ+OBM5nGv4RLsI6sR1Ar34bpgvGVRoyTgpxn4ZmtxOM5aDTAaaznYuYUH8bUX3Nk3YA==", "dev": true }, + "@types/minimatch": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@types/minimatch/-/minimatch-3.0.3.tgz", + "integrity": "sha512-tHq6qdbT9U1IRSGf14CL0pUlULksvY9OZ+5eEgl1N7t+OA3tGvNpxJCzuKQlsNgCVwbAs670L1vcVQi8j9HjnA==", + "dev": true + }, "@types/mousetrap": { "version": "1.6.0", "resolved": "https://registry.npmjs.org/@types/mousetrap/-/mousetrap-1.6.0.tgz", @@ -1670,9 +1352,9 @@ "dev": true }, "@types/node": { - "version": "12.0.0", - "resolved": "https://registry.npmjs.org/@types/node/-/node-12.0.0.tgz", - "integrity": "sha512-Jrb/x3HT4PTJp6a4avhmJCDEVrPdqLfl3e8GGMbpkGGdwAV5UGlIs4vVEfsHHfylZVOKZWpOqmqFH8CbfOZ6kg==", + "version": "12.0.4", + "resolved": "https://registry.npmjs.org/@types/node/-/node-12.0.4.tgz", + "integrity": "sha512-j8YL2C0fXq7IONwl/Ud5Kt0PeXw22zGERt+HSSnwbKOJVsAGkEz3sFCYwaF9IOuoG1HOtE0vKCj6sXF7Q0+Vaw==", "dev": true }, "@types/prop-types": { @@ -1688,9 +1370,9 @@ "dev": true }, "@types/react": { - "version": "16.8.16", - "resolved": "https://registry.npmjs.org/@types/react/-/react-16.8.16.tgz", - "integrity": "sha512-A0+6kS6zwPtvubOLiCJmZ8li5bm3wKIkoKV0h3RdMDOnCj9cYkUnj3bWbE03/lcICdQmwBmUfoFiHeNhbFiyHQ==", + "version": "16.8.19", + "resolved": "https://registry.npmjs.org/@types/react/-/react-16.8.19.tgz", + "integrity": "sha512-QzEzjrd1zFzY9cDlbIiFvdr+YUmefuuRYrPxmkwG0UQv5XF35gFIi7a95m1bNVcFU0VimxSZ5QVGSiBmlggQXQ==", "dev": true, "requires": { "@types/prop-types": "*", @@ -2235,11 +1917,12 @@ } }, "assert": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/assert/-/assert-1.4.1.tgz", - "integrity": "sha1-mZEtWRg2tab1s0XA8H7vwI/GXZE=", + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/assert/-/assert-1.5.0.tgz", + "integrity": "sha512-EDsgawzwoun2CZkCgtxJbv392v4nbk9XDD06zI+kQYoBM/3RBWLlEyJARDOmhAAosBjWACEkKL6S+lIZtcAubA==", "dev": true, "requires": { + "object-assign": "^4.1.1", "util": "0.10.3" }, "dependencies": { @@ -3298,9 +2981,9 @@ }, "dependencies": { "glob": { - "version": "7.1.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.3.tgz", - "integrity": "sha512-vcfuiIxogLV4DlGBHIUOwI0IbrJ8HWPc4MU7HzviGeNho/UJDfi6B5p3sHeWIQ0KGIU0Jpxi5ZHxemQfLkkAwQ==", + "version": "7.1.4", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.4.tgz", + "integrity": "sha512-hkLPepehmnKk41pUGm3sYxoFs/umurYfYJCerbXEyFIWcAzvpipAgVkBqqT9RBKMGjnq6kMuyYwha6csxbiM1A==", "dev": true, "requires": { "fs.realpath": "^1.0.0", @@ -3414,9 +3097,9 @@ } }, "camelcase": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-4.1.0.tgz", - "integrity": "sha1-1UVjW+HjPFQmScaRc+Xeas+uNN0=", + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", + "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", "dev": true }, "camelcase-keys": { @@ -3528,9 +3211,9 @@ "dev": true }, "chrome-trace-event": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/chrome-trace-event/-/chrome-trace-event-1.0.0.tgz", - "integrity": "sha512-xDbVgyfDTT2piup/h8dK/y4QZfJRSa73bw1WZ8b4XM1o7fsFubUVGYcE+1ANtOzJJELGpYoG2961z0Z6OAld9A==", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/chrome-trace-event/-/chrome-trace-event-1.0.2.tgz", + "integrity": "sha512-9e/zx1jw7B4CO+c/RXoCsfg/x1AfUBioy4owYH0bJprEYAx5hRFLRhWBqHAG57D0ZM4H7vxbP7bPe0VwhQRYDQ==", "dev": true, "requires": { "tslib": "^1.9.0" @@ -3931,10 +3614,13 @@ "dev": true }, "content-disposition": { - "version": "0.5.2", - "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.2.tgz", - "integrity": "sha1-DPaLud318r55YcOoUXjLhdunjLQ=", - "dev": true + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.3.tgz", + "integrity": "sha512-ExO0774ikEObIAEV9kDo50o+79VCUdEB6n6lzKgGwupcVeRlhrj3qGAfwq8G6uBJjkqLrhT0qEYFcWng8z1z0g==", + "dev": true, + "requires": { + "safe-buffer": "5.1.2" + } }, "content-type": { "version": "1.0.4", @@ -3984,9 +3670,9 @@ "dev": true }, "core-js": { - "version": "2.6.3", - "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.6.3.tgz", - "integrity": "sha512-l00tmFFZOBHtYhN4Cz7k32VM7vTn3rE2ANjQDxdEN6zmXZ/xq1jQuutnmHvMG1ZJ7xd72+TA5YpUK8wz3rWsfQ==" + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.1.3.tgz", + "integrity": "sha512-PWZ+ZfuaKf178BIAg+CRsljwjIMRV8MY00CbZczkR6Zk5LfkSkjGoaab3+bqRQWVITNZxQB7TFYz+CFcyuamvA==" }, "core-util-is": { "version": "1.0.2", @@ -4084,12 +3770,14 @@ } }, "cross-spawn": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-5.1.0.tgz", - "integrity": "sha1-6L0O/uWPz/b4+UUQoKVUu/ojVEk=", + "version": "6.0.5", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz", + "integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==", "dev": true, "requires": { - "lru-cache": "^4.0.1", + "nice-try": "^1.0.4", + "path-key": "^2.0.1", + "semver": "^5.5.0", "shebang-command": "^1.2.0", "which": "^1.2.9" } @@ -4461,9 +4149,9 @@ } }, "csstype": { - "version": "2.6.4", - "resolved": "https://registry.npmjs.org/csstype/-/csstype-2.6.4.tgz", - "integrity": "sha512-lAJUJP3M6HxFXbqtGRc0iZrdyeN+WzOWeY0q/VnFzI+kqVrYIzC7bWlKqCW7oCIdzoPkvfp82EVvrTlQ8zsWQg==", + "version": "2.6.5", + "resolved": "https://registry.npmjs.org/csstype/-/csstype-2.6.5.tgz", + "integrity": "sha512-JsTaiksRsel5n7XwqPAfB0l3TFKdpjW/kgAELf9vrb5adGA7UCPLajKK5s3nFrcFm3Rkyp/Qkgl73ENc1UY3cA==", "dev": true }, "currently-unhandled": { @@ -4570,45 +4258,6 @@ "requires": { "execa": "^1.0.0", "ip-regex": "^2.1.0" - }, - "dependencies": { - "cross-spawn": { - "version": "6.0.5", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz", - "integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==", - "dev": true, - "requires": { - "nice-try": "^1.0.4", - "path-key": "^2.0.1", - "semver": "^5.5.0", - "shebang-command": "^1.2.0", - "which": "^1.2.9" - } - }, - "execa": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/execa/-/execa-1.0.0.tgz", - "integrity": "sha512-adbxcyWV46qiHyvSp50TKt05tB4tK3HcmF7/nxfAdhnox83seTDbwnaqKO4sXRy7roHAIFqJP/Rw/AuEbX61LA==", - "dev": true, - "requires": { - "cross-spawn": "^6.0.0", - "get-stream": "^4.0.0", - "is-stream": "^1.1.0", - "npm-run-path": "^2.0.0", - "p-finally": "^1.0.0", - "signal-exit": "^3.0.0", - "strip-eof": "^1.0.0" - } - }, - "get-stream": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-4.1.0.tgz", - "integrity": "sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w==", - "dev": true, - "requires": { - "pump": "^3.0.0" - } - } } }, "default-require-extensions": { @@ -4683,11 +4332,12 @@ } }, "del": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/del/-/del-4.1.0.tgz", - "integrity": "sha512-C4kvKNlYrwXhKxz97BuohF8YoGgQ23Xm9lvoHmgT7JaPGprSEjk3+XFled74Yt/x0ZABUHg2D67covzAPUKx5Q==", + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/del/-/del-4.1.1.tgz", + "integrity": "sha512-QwGuEUouP2kVwQenAsOof5Fv8K9t3D8Ca8NxcXKrIpEHjTXK5J2nXLdP+ALI1cgv8wj7KuwBhTwBkOZSJKM5XQ==", "dev": true, "requires": { + "@types/glob": "^7.1.1", "globby": "^6.1.0", "is-path-cwd": "^2.0.0", "is-path-in-cwd": "^2.0.0", @@ -4970,6 +4620,12 @@ "minimalistic-crypto-utils": "^1.0.0" } }, + "emoji-regex": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz", + "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==", + "dev": true + }, "emojis-list": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/emojis-list/-/emojis-list-2.1.0.tgz", @@ -5396,13 +5052,13 @@ } }, "execa": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/execa/-/execa-0.7.0.tgz", - "integrity": "sha1-lEvs00zEHuMqY6n68nrVpl/Fl3c=", + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/execa/-/execa-1.0.0.tgz", + "integrity": "sha512-adbxcyWV46qiHyvSp50TKt05tB4tK3HcmF7/nxfAdhnox83seTDbwnaqKO4sXRy7roHAIFqJP/Rw/AuEbX61LA==", "dev": true, "requires": { - "cross-spawn": "^5.0.1", - "get-stream": "^3.0.0", + "cross-spawn": "^6.0.0", + "get-stream": "^4.0.0", "is-stream": "^1.1.0", "npm-run-path": "^2.0.0", "p-finally": "^1.0.0", @@ -5444,137 +5100,90 @@ } }, "express": { - "version": "4.16.4", - "resolved": "https://registry.npmjs.org/express/-/express-4.16.4.tgz", - "integrity": "sha512-j12Uuyb4FMrd/qQAm6uCHAkPtO8FDTRJZBDd5D2KOL2eLaz1yUNdUB/NOIyq0iU4q4cFarsUCrnFDPBcnksuOg==", + "version": "4.17.1", + "resolved": "https://registry.npmjs.org/express/-/express-4.17.1.tgz", + "integrity": "sha512-mHJ9O79RqluphRrcw2X/GTh3k9tVv8YcoyY4Kkh4WDMUYKRZUq0h1o0w2rrrxBqM7VoeUVqgb27xlEMXTnYt4g==", "dev": true, "requires": { - "accepts": "~1.3.5", + "accepts": "~1.3.7", "array-flatten": "1.1.1", - "body-parser": "1.18.3", - "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.4", - "qs": "6.5.2", - "range-parser": "~1.2.0", + "proxy-addr": "~2.0.5", + "qs": "6.7.0", + "range-parser": "~1.2.1", "safe-buffer": "5.1.2", - "send": "0.16.2", - "serve-static": "1.13.2", - "setprototypeof": "1.1.0", - "statuses": "~1.4.0", - "type-is": "~1.6.16", + "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" }, "dependencies": { + "accepts": { + "version": "1.3.7", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.7.tgz", + "integrity": "sha512-Il80Qs2WjYlJIBNzNkK6KYqlVMTbZLXgHx2oT0pU/fjRHyEp+PEfEPY0R3WCwAGVOtauxh1hOxNgIf5bv7dQpA==", + "dev": true, + "requires": { + "mime-types": "~2.1.24", + "negotiator": "0.6.2" + } + }, "array-flatten": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", "integrity": "sha1-ml9pkFGx5wczKPKgCJaLZOopVdI=", "dev": true }, - "body-parser": { - "version": "1.18.3", - "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.18.3.tgz", - "integrity": "sha1-WykhmP/dVTs6DyDe0FkrlWlVyLQ=", - "dev": true, - "requires": { - "bytes": "3.0.0", - "content-type": "~1.0.4", - "debug": "2.6.9", - "depd": "~1.1.2", - "http-errors": "~1.6.3", - "iconv-lite": "0.4.23", - "on-finished": "~2.3.0", - "qs": "6.5.2", - "raw-body": "2.3.3", - "type-is": "~1.6.16" - } - }, - "bytes": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.0.0.tgz", - "integrity": "sha1-0ygVQE1olpn4Wk6k+odV3ROpYEg=", + "cookie": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.0.tgz", + "integrity": "sha512-+Hp8fLp57wnUSt0tY0tHEXh4voZRDnoIrZPqlo3DPiI4y9lwg/jqx+1Om94/W6ZaPDOUbnjOt/99w66zk+l1Xg==", "dev": true }, "finalhandler": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.1.tgz", - "integrity": "sha512-Y1GUDo39ez4aHAw7MysnUD5JzYX+WaIj8I57kO3aEPT1fFRL4sr7mjei97FgnwhAyyzRYmQZaTHb2+9uZ1dPtg==", + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.2.tgz", + "integrity": "sha512-aAWcW57uxVNrQZqFXjITpW3sIUQmHGG3qSb9mUah9MgMC4NeWhNOlNjXEYq3HjRAvL6arUviZGGJsBg6z0zsWA==", "dev": true, "requires": { "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" } }, - "http-errors": { - "version": "1.6.3", - "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.6.3.tgz", - "integrity": "sha1-i1VoC7S+KDoLW/TqLjhYC+HZMg0=", - "dev": true, - "requires": { - "depd": "~1.1.2", - "inherits": "2.0.3", - "setprototypeof": "1.1.0", - "statuses": ">= 1.4.0 < 2" - } - }, - "iconv-lite": { - "version": "0.4.23", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.23.tgz", - "integrity": "sha512-neyTUVFtahjf0mB3dZT77u+8O0QB89jFdnBkd5P1JgYPbPaia3gXXOVL2fq8VyU2gMMD7SaN7QukTB/pmXYvDA==", - "dev": true, - "requires": { - "safer-buffer": ">= 2.1.2 < 3" - } - }, - "qs": { - "version": "6.5.2", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.2.tgz", - "integrity": "sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA==", - "dev": true - }, - "raw-body": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.3.3.tgz", - "integrity": "sha512-9esiElv1BrZoI3rCDuOuKCBRbuApGGaDPQfjSflGxdy4oyzqghxu6klEkkVIvBje+FF0BX9coEv8KqW6X/7njw==", - "dev": true, - "requires": { - "bytes": "3.0.0", - "http-errors": "1.6.3", - "iconv-lite": "0.4.23", - "unpipe": "1.0.0" - } - }, - "setprototypeof": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.0.tgz", - "integrity": "sha512-BvE/TwpZX4FXExxOxZyRGQQv651MSwmWKZGqvmPcRIjDqWub67kTKuIMx43cZZrS/cBBzwBcNDWoFxt2XEFIpQ==", + "negotiator": { + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.2.tgz", + "integrity": "sha512-hZXc7K2e+PgeI1eDBe/10Ard4ekbfrrqG8Ep+8Jmf4JID2bNg7NvCPOZN+kfF574pFQI7mum2AUqDidoKqcTOw==", "dev": true }, - "statuses": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.4.0.tgz", - "integrity": "sha512-zhSCtt8v2NDrRlPQpCNtw/heZLtfUDqxBM1udqikb/Hbk52LK4nQSwr10u77iopCW5LsyHpuXS0GnEc48mLeew==", + "range-parser": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", + "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", "dev": true } } @@ -5760,12 +5369,12 @@ "dev": true }, "find-up": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz", - "integrity": "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", + "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", "dev": true, "requires": { - "locate-path": "^2.0.0" + "locate-path": "^3.0.0" } }, "findup-sync": { @@ -6870,10 +6479,13 @@ "dev": true }, "get-stream": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-3.0.0.tgz", - "integrity": "sha1-jpQ9E1jcN1VQVOy+LtsFqhdO3hQ=", - "dev": true + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-4.1.0.tgz", + "integrity": "sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w==", + "dev": true, + "requires": { + "pump": "^3.0.0" + } }, "get-value": { "version": "2.0.6", @@ -7020,9 +6632,9 @@ } }, "graphql": { - "version": "14.2.1", - "resolved": "https://registry.npmjs.org/graphql/-/graphql-14.2.1.tgz", - "integrity": "sha512-2PL1UbvKeSjy/lUeJqHk+eR9CvuErXoCNwJI4jm3oNFEeY+9ELqHNKO1ZuSxAkasPkpWbmT/iMRMFxd3cEL3tQ==", + "version": "14.3.1", + "resolved": "https://registry.npmjs.org/graphql/-/graphql-14.3.1.tgz", + "integrity": "sha512-FZm7kAa3FqKdXy8YSSpAoTtyDFMIYSpCDOr+3EqlI1bxmtHu+Vv/I2vrSeT1sBOEnEniX3uo4wFhFdS/8XN6gA==", "requires": { "iterall": "^1.2.2" } @@ -8726,9 +8338,9 @@ "dev": true }, "json3": { - "version": "3.3.2", - "resolved": "https://registry.npmjs.org/json3/-/json3-3.3.2.tgz", - "integrity": "sha1-PAQ0dD35Pi9cQq7nsZvLSDV19OE=", + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/json3/-/json3-3.3.3.tgz", + "integrity": "sha512-c7/8mbUsKigAbLkD5B010BK4D9LZm7A1pNItkEwiUZRpIN66exu/e7YQWysGun+TRKaJp8MhemM+VkfWv42aCA==", "dev": true }, "json5": { @@ -9924,18 +9536,6 @@ "uc.micro": "^1.0.1" } }, - "load-json-file": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-2.0.0.tgz", - "integrity": "sha1-eUfkIUmvgNaWy/eXvKq8/h/inKg=", - "dev": true, - "requires": { - "graceful-fs": "^4.1.2", - "parse-json": "^2.2.0", - "pify": "^2.0.0", - "strip-bom": "^3.0.0" - } - }, "loader-runner": { "version": "2.4.0", "resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-2.4.0.tgz", @@ -9954,12 +9554,12 @@ } }, "locate-path": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz", - "integrity": "sha1-K1aLJl7slExtnA3pw9u7ygNUzY4=", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", + "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", "dev": true, "requires": { - "p-locate": "^2.0.0", + "p-locate": "^3.0.0", "path-exists": "^3.0.0" } }, @@ -9974,12 +9574,6 @@ "integrity": "sha1-+CbJtOKoUR2E46yinbBeGk87cqk=", "dev": true }, - "lodash.debounce": { - "version": "4.0.8", - "resolved": "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz", - "integrity": "sha1-gteb/zCmfEAF/9XiUVMArZyk168=", - "dev": true - }, "lodash.kebabcase": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/lodash.kebabcase/-/lodash.kebabcase-4.1.1.tgz", @@ -10044,9 +9638,9 @@ } }, "loglevel": { - "version": "1.6.1", - "resolved": "https://registry.npmjs.org/loglevel/-/loglevel-1.6.1.tgz", - "integrity": "sha1-4PyVEztu8nbNyIh82vJKpvFW+Po=", + "version": "1.6.2", + "resolved": "https://registry.npmjs.org/loglevel/-/loglevel-1.6.2.tgz", + "integrity": "sha512-Jt2MHrCNdtIe1W6co3tF5KXGRkzF+TYffiQstfXa04mrss9IKXzAAXYWak8LbZseAQY03sH2GzMCMU0ZOUc9bg==", "dev": true }, "loglevelnext": { @@ -10214,12 +9808,14 @@ "dev": true }, "mem": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/mem/-/mem-1.1.0.tgz", - "integrity": "sha1-Xt1StIXKHZAP5kiVUFOZoN+kX3Y=", + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/mem/-/mem-4.3.0.tgz", + "integrity": "sha512-qX2bG48pTqYRVmDB37rn/6PT7LcR8T7oAX3bf99u1Tt1nzxYfxkgqDwUwolPlXweM0XzBOBFzSx4kfp7KP1s/w==", "dev": true, "requires": { - "mimic-fn": "^1.0.0" + "map-age-cleaner": "^0.1.1", + "mimic-fn": "^2.0.0", + "p-is-promise": "^2.0.0" } }, "memory-fs": { @@ -10396,32 +9992,33 @@ } }, "mimic-fn": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-1.2.0.tgz", - "integrity": "sha512-jf84uxzwiuiIVKiOLpfYk7N46TSy8ubTonmneY9vrpHNAnp0QBt2BxWV9dO3/j+BoVAb+a5G6YDPW3M5HOdMWQ==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", + "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", "dev": true }, "mini-css-extract-plugin": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/mini-css-extract-plugin/-/mini-css-extract-plugin-0.6.0.tgz", - "integrity": "sha512-79q5P7YGI6rdnVyIAV4NXpBQJFWdkzJxCim3Kog4078fM0piAaFlwocqbejdWtLW1cEzCexPrh6EdyFsPgVdAw==", + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/mini-css-extract-plugin/-/mini-css-extract-plugin-0.7.0.tgz", + "integrity": "sha512-RQIw6+7utTYn8DBGsf/LpRgZCJMpZt+kuawJ/fju0KiOL6nAaTBNmCJwS7HtwSCXfS47gCkmtBFS7HdsquhdxQ==", "dev": true, "requires": { "loader-utils": "^1.1.0", - "normalize-url": "^2.0.1", + "normalize-url": "1.9.1", "schema-utils": "^1.0.0", "webpack-sources": "^1.1.0" }, "dependencies": { "normalize-url": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-2.0.1.tgz", - "integrity": "sha512-D6MUW4K/VzoJ4rJ01JFKxDrtY1v9wrgzCX5f2qj/lzH1m/lW6MhUZFKerVsnyjOhOsYzI9Kqqak+10l4LvLpMw==", + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-1.9.1.tgz", + "integrity": "sha1-LMDWazHqIwNkWENuNiDYWVTGbDw=", "dev": true, "requires": { - "prepend-http": "^2.0.0", - "query-string": "^5.0.1", - "sort-keys": "^2.0.0" + "object-assign": "^4.0.1", + "prepend-http": "^1.0.0", + "query-string": "^4.1.0", + "sort-keys": "^1.0.0" } } } @@ -11171,14 +10768,31 @@ "dev": true }, "os-locale": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-2.1.0.tgz", - "integrity": "sha512-3sslG3zJbEYcaC4YVAvDorjGxc7tv6KVATnLPZONiljsUncvihe9BQoVCEs0RZ1kmf4Hk9OBqlZfJZWI4GanKA==", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-3.1.0.tgz", + "integrity": "sha512-Z8l3R4wYWM40/52Z+S265okfFj8Kt2cC2MKY+xNi3kFs+XGI7WXu/I309QQQYbRW4ijiZ+yxs9pqEhJh0DqW3Q==", "dev": true, "requires": { - "execa": "^0.7.0", - "lcid": "^1.0.0", - "mem": "^1.1.0" + "execa": "^1.0.0", + "lcid": "^2.0.0", + "mem": "^4.0.0" + }, + "dependencies": { + "invert-kv": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/invert-kv/-/invert-kv-2.0.0.tgz", + "integrity": "sha512-wPVv/y/QQ/Uiirj/vh3oP+1Ww+AWehmi1g5fFWGPF6IpCBCDVrhgHRMvrLfdYcwDh3QJbGXDW4JAuzxElLSqKA==", + "dev": true + }, + "lcid": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/lcid/-/lcid-2.0.0.tgz", + "integrity": "sha512-avPEb8P8EGnwXKClwsNUgryVjllcRqtMYa49NTsbQagYuT1DcXnl1915oxWjoyGrXR6zH/Y0Zc96xWsPcoDKeA==", + "dev": true, + "requires": { + "invert-kv": "^2.0.0" + } + } } }, "os-tmpdir": { @@ -11216,21 +10830,21 @@ "dev": true }, "p-limit": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.3.0.tgz", - "integrity": "sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q==", + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.2.0.tgz", + "integrity": "sha512-pZbTJpoUsCzV48Mc9Nh51VbwO0X9cuPFE8gYwx9BTCt9SF8/b7Zljd2fVgOxhIF/HDTKgpVzs+GPhyKfjLLFRQ==", "dev": true, "requires": { - "p-try": "^1.0.0" + "p-try": "^2.0.0" } }, "p-locate": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-2.0.0.tgz", - "integrity": "sha1-IKAQOyIqcMj9OcwuWAaA893l7EM=", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", + "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", "dev": true, "requires": { - "p-limit": "^1.1.0" + "p-limit": "^2.0.0" } }, "p-map": { @@ -11240,9 +10854,9 @@ "dev": true }, "p-try": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/p-try/-/p-try-1.0.0.tgz", - "integrity": "sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M=", + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", + "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", "dev": true }, "pako": { @@ -11390,15 +11004,6 @@ "integrity": "sha1-32BBeABfUi8V60SQ5yR6G/qmf4w=", "dev": true }, - "path-type": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/path-type/-/path-type-2.0.0.tgz", - "integrity": "sha1-8BLMuEFbcJb8LaoQVMPXI4lZTHM=", - "dev": true, - "requires": { - "pify": "^2.0.0" - } - }, "pbkdf2": { "version": "3.0.17", "resolved": "https://registry.npmjs.org/pbkdf2/-/pbkdf2-3.0.17.tgz", @@ -11418,6 +11023,12 @@ "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=", "dev": true }, + "picomatch": { + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.0.7.tgz", + "integrity": "sha512-oLHIdio3tZ0qH76NybpeneBhYVj0QFTfXEFTc/B3zKQspYfYYkWYgFsmzo+4kvId/bQRcNkVeguI3y+CD22BtA==", + "dev": true + }, "pify": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", @@ -11445,57 +11056,12 @@ } }, "pkg-dir": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-3.0.0.tgz", - "integrity": "sha512-/E57AYkoeQ25qkxMj5PBOVgF8Kiu/h7cYS30Z5+R7WaiCCBfLq58ZI/dSeaEKb9WVJV5n/03QwrN3IeWIFllvw==", - "dev": true, - "requires": { - "find-up": "^3.0.0" - }, - "dependencies": { - "find-up": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", - "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", - "dev": true, - "requires": { - "locate-path": "^3.0.0" - } - }, - "locate-path": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", - "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", - "dev": true, - "requires": { - "p-locate": "^3.0.0", - "path-exists": "^3.0.0" - } - }, - "p-limit": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.2.0.tgz", - "integrity": "sha512-pZbTJpoUsCzV48Mc9Nh51VbwO0X9cuPFE8gYwx9BTCt9SF8/b7Zljd2fVgOxhIF/HDTKgpVzs+GPhyKfjLLFRQ==", - "dev": true, - "requires": { - "p-try": "^2.0.0" - } - }, - "p-locate": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", - "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", - "dev": true, - "requires": { - "p-limit": "^2.0.0" - } - }, - "p-try": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", - "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", - "dev": true - } + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-3.0.0.tgz", + "integrity": "sha512-/E57AYkoeQ25qkxMj5PBOVgF8Kiu/h7cYS30Z5+R7WaiCCBfLq58ZI/dSeaEKb9WVJV5n/03QwrN3IeWIFllvw==", + "dev": true, + "requires": { + "find-up": "^3.0.0" } }, "pluralize": { @@ -12619,9 +12185,9 @@ "dev": true }, "prepend-http": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/prepend-http/-/prepend-http-2.0.0.tgz", - "integrity": "sha1-6SQ0v6XqjBn0HN/UAddBo8gZ2Jc=", + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/prepend-http/-/prepend-http-1.0.4.tgz", + "integrity": "sha1-1PRWKwzjaW5BrFLQ4ALlemNdxtw=", "dev": true }, "preserve": { @@ -12788,12 +12354,11 @@ "dev": true }, "query-string": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/query-string/-/query-string-5.1.1.tgz", - "integrity": "sha512-gjWOsm2SoGlgLEdAGt7a6slVOk9mGiXmPFMqrEhLQ68rhQuBnpfs3+EmlvqKyxnCo9/PPlF+9MtY02S1aFg+Jw==", + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/query-string/-/query-string-4.3.4.tgz", + "integrity": "sha1-u7aTucqRXCMlFbIosaArYJBD2+s=", "dev": true, "requires": { - "decode-uri-component": "^0.2.0", "object-assign": "^4.1.0", "strict-uri-encode": "^1.0.0" } @@ -12915,27 +12480,6 @@ "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.8.6.tgz", "integrity": "sha512-aUk3bHfZ2bRSVFFbbeVS4i+lNPZr3/WM5jT2J5omUVV1zzcs1nAaf3l51ctA5FFvCRbhrH0bdAsRRQddFJZPtA==" }, - "read-pkg": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-2.0.0.tgz", - "integrity": "sha1-jvHAYjxqbbDcZxPEv6xGMysjaPg=", - "dev": true, - "requires": { - "load-json-file": "^2.0.0", - "normalize-package-data": "^2.3.2", - "path-type": "^2.0.0" - } - }, - "read-pkg-up": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-2.0.0.tgz", - "integrity": "sha1-a3KoBImE4MQeeVEP1en6mbO1Sb4=", - "dev": true, - "requires": { - "find-up": "^2.0.0", - "read-pkg": "^2.0.0" - } - }, "readable-stream": { "version": "2.3.6", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", @@ -13341,9 +12885,9 @@ "dev": true }, "rxjs": { - "version": "6.5.1", - "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.5.1.tgz", - "integrity": "sha512-y0j31WJc83wPu31vS1VlAFW5JGrnGC+j+TtGAa1fRQphy48+fDYiDmX8tjGloToEsMkxnouOg/1IzXGKkJnZMg==", + "version": "6.5.2", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.5.2.tgz", + "integrity": "sha512-HUb7j3kvb7p7eCUHE3FqjoDsC1xfZQ4AHFWfTKSpZ+sAhhz5X1WX0ZuUqWbzB2QhSLp3DoLUG+hMdEDKqWo2Zg==", "requires": { "tslib": "^1.9.0" } @@ -13675,9 +13219,9 @@ } }, "send": { - "version": "0.16.2", - "resolved": "https://registry.npmjs.org/send/-/send-0.16.2.tgz", - "integrity": "sha512-E64YFPUssFHEFBvpbbjr44NCLtI1AohxQ8ZSiJjQLskAdKuriYEP6VyGEsRDH8ScozGpkaX1BGvhanqCwkcEZw==", + "version": "0.17.1", + "resolved": "https://registry.npmjs.org/send/-/send-0.17.1.tgz", + "integrity": "sha512-BsVKsiGcQMFwT8UxypobUKyv7irCNRHk1T0G680vk88yf6LBByGcZJOTJCrTP2xVN6yI+XjPJcNuE3V4fT9sAg==", "dev": true, "requires": { "debug": "2.6.9", @@ -13687,42 +13231,30 @@ "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" }, "dependencies": { - "http-errors": { - "version": "1.6.3", - "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.6.3.tgz", - "integrity": "sha1-i1VoC7S+KDoLW/TqLjhYC+HZMg0=", - "dev": true, - "requires": { - "depd": "~1.1.2", - "inherits": "2.0.3", - "setprototypeof": "1.1.0", - "statuses": ">= 1.4.0 < 2" - } - }, "mime": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/mime/-/mime-1.4.1.tgz", - "integrity": "sha512-KI1+qOZu5DcW6wayYHSzR/tXKCDC5Om4s1z2QJjDULzLcmf3DvzS7oluY4HCTrc+9FiKmWUgeNLg7W3uIQvxtQ==", + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", + "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", "dev": true }, - "setprototypeof": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.0.tgz", - "integrity": "sha512-BvE/TwpZX4FXExxOxZyRGQQv651MSwmWKZGqvmPcRIjDqWub67kTKuIMx43cZZrS/cBBzwBcNDWoFxt2XEFIpQ==", + "ms": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", + "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==", "dev": true }, - "statuses": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.4.0.tgz", - "integrity": "sha512-zhSCtt8v2NDrRlPQpCNtw/heZLtfUDqxBM1udqikb/Hbk52LK4nQSwr10u77iopCW5LsyHpuXS0GnEc48mLeew==", + "range-parser": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", + "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", "dev": true } } @@ -13769,15 +13301,15 @@ } }, "serve-static": { - "version": "1.13.2", - "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.13.2.tgz", - "integrity": "sha512-p/tdJrO4U387R9oMjb1oj7qSMaMfmOyd4j9hOFoxZe2baQszgHcSWjuya/CiT5kgZZKRudHNOA0pYXOl8rQ5nw==", + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.14.1.tgz", + "integrity": "sha512-JMrvUwE54emCYWlTI+hGrGv5I8dEwmco/00EvkzIIsR7MqrHonbD9pO2MOfFnpFntl7ecpZs+3mW+XbQZu9QCg==", "dev": true, "requires": { "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": { @@ -14196,9 +13728,9 @@ } }, "sort-keys": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/sort-keys/-/sort-keys-2.0.0.tgz", - "integrity": "sha1-ZYU1WEhh7JfXMNbPQYIuH1ZoQSg=", + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/sort-keys/-/sort-keys-1.1.2.tgz", + "integrity": "sha1-RBttTTRnmPG05J6JIK37oOVD+a0=", "dev": true, "requires": { "is-plain-obj": "^1.0.0" @@ -14348,9 +13880,9 @@ "dev": true }, "readable-stream": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.3.0.tgz", - "integrity": "sha512-EsI+s3k3XsW+fU8fQACLN59ky34AZ14LoeVZpYwmZvldCFo0r0gnelwF2TcMjLor/BTL5aDJVBMkss0dthToPw==", + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.4.0.tgz", + "integrity": "sha512-jItXPLmrSR8jmTRmRWJXCnGJsfy85mB3Wd/uINMXA65yrnFo0cPClFIUWzo2najVNSl+mx7/4W8ttlLWJe99pQ==", "dev": true, "requires": { "inherits": "^2.0.3", @@ -14788,525 +14320,330 @@ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", "dev": true - } - } - }, - "tapable": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/tapable/-/tapable-1.0.0.tgz", - "integrity": "sha512-dQRhbNQkRnaqauC7WqSJ21EEksgT0fYZX2lqXzGkpo8JNig9zGZTYoMGvyI2nWmXlE2VSVXVDu7wLVGu/mQEsg==", - "dev": true - }, - "tar": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/tar/-/tar-2.2.1.tgz", - "integrity": "sha1-jk0qJWwOIYXGsYrWlK7JaLg8sdE=", - "dev": true, - "requires": { - "block-stream": "*", - "fstream": "^1.0.2", - "inherits": "2" - } - }, - "terser": { - "version": "3.17.0", - "resolved": "https://registry.npmjs.org/terser/-/terser-3.17.0.tgz", - "integrity": "sha512-/FQzzPJmCpjAH9Xvk2paiWrFq+5M6aVOf+2KRbwhByISDX/EujxsK+BAvrhb6H+2rtrLCHK9N01wO014vrIwVQ==", - "dev": true, - "requires": { - "commander": "^2.19.0", - "source-map": "~0.6.1", - "source-map-support": "~0.5.10" - }, - "dependencies": { - "commander": { - "version": "2.20.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.0.tgz", - "integrity": "sha512-7j2y+40w61zy6YC2iRNpUe/NwhNyoXrYpHMrSunaMG64nRnaf96zO/KMQR4OyN/UnE5KLyEBnKHd4aG3rskjpQ==", - "dev": true - }, - "source-map-support": { - "version": "0.5.12", - "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.12.tgz", - "integrity": "sha512-4h2Pbvyy15EE02G+JOZpUCmqWJuqrs+sEkzewTm++BPi7Hvn/HwcqLAcNxYAyI0x13CpPPn+kMjl+hplXMHITQ==", - "dev": true, - "requires": { - "buffer-from": "^1.0.0", - "source-map": "^0.6.0" - } - } - } - }, - "terser-webpack-plugin": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-1.2.3.tgz", - "integrity": "sha512-GOK7q85oAb/5kE12fMuLdn2btOS9OBZn4VsecpHDywoUC/jLhSAKOiYo0ezx7ss2EXPMzyEWFoE0s1WLE+4+oA==", - "dev": true, - "requires": { - "cacache": "^11.0.2", - "find-cache-dir": "^2.0.0", - "schema-utils": "^1.0.0", - "serialize-javascript": "^1.4.0", - "source-map": "^0.6.1", - "terser": "^3.16.1", - "webpack-sources": "^1.1.0", - "worker-farm": "^1.5.2" - } - }, - "text-table": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", - "integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=", - "dev": true - }, - "through": { - "version": "2.3.8", - "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", - "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=", - "dev": true - }, - "through2": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz", - "integrity": "sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==", - "dev": true, - "requires": { - "readable-stream": "~2.3.6", - "xtend": "~4.0.1" - } - }, - "thunky": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/thunky/-/thunky-1.0.3.tgz", - "integrity": "sha512-YwT8pjmNcAXBZqrubu22P4FYsh2D4dxRmnWBOL8Jk8bUcRUtc5326kx32tuTmFDAZtLOGEVNl8POAR8j896Iow==", - "dev": true - }, - "timers-browserify": { - "version": "2.0.10", - "resolved": "https://registry.npmjs.org/timers-browserify/-/timers-browserify-2.0.10.tgz", - "integrity": "sha512-YvC1SV1XdOUaL6gx5CoGroT3Gu49pK9+TZ38ErPldOWW4j49GI1HKs9DV+KGq/w6y+LZ72W1c8cKz2vzY+qpzg==", - "dev": true, - "requires": { - "setimmediate": "^1.0.4" - } - }, - "timsort": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/timsort/-/timsort-0.3.0.tgz", - "integrity": "sha1-QFQRqOfmM5/mTbmiNN4R3DHgK9Q=", - "dev": true - }, - "tmp": { - "version": "0.0.33", - "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz", - "integrity": "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==", - "dev": true, - "requires": { - "os-tmpdir": "~1.0.2" - } - }, - "to-array": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/to-array/-/to-array-0.1.4.tgz", - "integrity": "sha1-F+bBH3PdTz10zaek/zI46a2b+JA=", - "dev": true - }, - "to-arraybuffer": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/to-arraybuffer/-/to-arraybuffer-1.0.1.tgz", - "integrity": "sha1-fSKbH8xjfkZsoIEYCDanqr/4P0M=", - "dev": true - }, - "to-fast-properties": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-1.0.3.tgz", - "integrity": "sha1-uDVx+k2MJbguIxsG46MFXeTKGkc=", - "dev": true - }, - "to-object-path": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/to-object-path/-/to-object-path-0.3.0.tgz", - "integrity": "sha1-KXWIt7Dn4KwI4E5nL4XB9JmeF68=", - "dev": true, - "requires": { - "kind-of": "^3.0.2" - } - }, - "to-regex": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/to-regex/-/to-regex-3.0.2.tgz", - "integrity": "sha512-FWtleNAtZ/Ki2qtqej2CXTOayOH9bHDQF+Q48VpWyDXjbYxA4Yz8iDB31zXOBUlOHHKidDbqGVrTUvQMPmBGBw==", - "dev": true, - "requires": { - "define-property": "^2.0.2", - "extend-shallow": "^3.0.2", - "regex-not": "^1.0.2", - "safe-regex": "^1.1.0" - } - }, - "to-regex-range": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-2.1.1.tgz", - "integrity": "sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg=", - "dev": true, - "requires": { - "is-number": "^3.0.0", - "repeat-string": "^1.6.1" - }, - "dependencies": { - "is-number": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", - "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", - "dev": true, - "requires": { - "kind-of": "^3.0.2" - } - } - } - }, - "toidentifier": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.0.tgz", - "integrity": "sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw==", - "dev": true - }, - "toposort": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/toposort/-/toposort-1.0.7.tgz", - "integrity": "sha1-LmhELZ9k7HILjMieZEOsbKqVACk=", - "dev": true - }, - "tough-cookie": { - "version": "2.4.3", - "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.4.3.tgz", - "integrity": "sha512-Q5srk/4vDM54WJsJio3XNn6K2sCG+CQ8G5Wz6bZhRZoAe/+TxjWB/GlFAnYEbkYVlON9FMk/fE3h2RLpPXo4lQ==", - "dev": true, - "requires": { - "psl": "^1.1.24", - "punycode": "^1.4.1" - }, - "dependencies": { - "punycode": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", - "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=", - "dev": true - } - } - }, - "tree-kill": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/tree-kill/-/tree-kill-1.2.1.tgz", - "integrity": "sha512-4hjqbObwlh2dLyW4tcz0Ymw0ggoaVDMveUB9w8kFSQScdRLo0gxO9J7WFcUBo+W3C1TLdFIEwNOWebgZZ0RH9Q==", - "dev": true - }, - "trim-newlines": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/trim-newlines/-/trim-newlines-1.0.0.tgz", - "integrity": "sha1-WIeWa7WCpFA6QetST301ARgVphM=", - "dev": true - }, - "trim-right": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/trim-right/-/trim-right-1.0.1.tgz", - "integrity": "sha1-yy4SAwZ+DI3h9hQJS5/kVwTqYAM=", + } + } + }, + "tapable": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/tapable/-/tapable-1.0.0.tgz", + "integrity": "sha512-dQRhbNQkRnaqauC7WqSJ21EEksgT0fYZX2lqXzGkpo8JNig9zGZTYoMGvyI2nWmXlE2VSVXVDu7wLVGu/mQEsg==", "dev": true }, - "true-case-path": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/true-case-path/-/true-case-path-1.0.3.tgz", - "integrity": "sha512-m6s2OdQe5wgpFMC+pAJ+q9djG82O2jcHPOI6RNg1yy9rCYR+WD6Nbpl32fDpfC56nirdRy+opFa/Vk7HYhqaew==", + "tar": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/tar/-/tar-2.2.1.tgz", + "integrity": "sha1-jk0qJWwOIYXGsYrWlK7JaLg8sdE=", "dev": true, "requires": { - "glob": "^7.1.2" + "block-stream": "*", + "fstream": "^1.0.2", + "inherits": "2" } }, - "ts-loader": { - "version": "5.4.5", - "resolved": "https://registry.npmjs.org/ts-loader/-/ts-loader-5.4.5.tgz", - "integrity": "sha512-XYsjfnRQCBum9AMRZpk2rTYSVpdZBpZK+kDh0TeT3kxmQNBDVIeUjdPjY5RZry4eIAb8XHc4gYSUiUWPYvzSRw==", + "terser": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/terser/-/terser-4.0.0.tgz", + "integrity": "sha512-dOapGTU0hETFl1tCo4t56FN+2jffoKyER9qBGoUFyZ6y7WLoKT0bF+lAYi6B6YsILcGF3q1C2FBh8QcKSCgkgA==", "dev": true, "requires": { - "chalk": "^2.3.0", - "enhanced-resolve": "^4.0.0", - "loader-utils": "^1.0.2", - "micromatch": "^3.1.4", - "semver": "^5.0.1" + "commander": "^2.19.0", + "source-map": "~0.6.1", + "source-map-support": "~0.5.10" }, "dependencies": { - "arr-diff": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz", - "integrity": "sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA=", + "commander": { + "version": "2.20.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.0.tgz", + "integrity": "sha512-7j2y+40w61zy6YC2iRNpUe/NwhNyoXrYpHMrSunaMG64nRnaf96zO/KMQR4OyN/UnE5KLyEBnKHd4aG3rskjpQ==", "dev": true - }, - "array-unique": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz", - "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=", + } + } + }, + "terser-webpack-plugin": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-1.3.0.tgz", + "integrity": "sha512-W2YWmxPjjkUcOWa4pBEv4OP4er1aeQJlSo2UhtCFQCuRXEHjOFscO8VyWHj9JLlA0RzQb8Y2/Ta78XZvT54uGg==", + "dev": true, + "requires": { + "cacache": "^11.3.2", + "find-cache-dir": "^2.0.0", + "is-wsl": "^1.1.0", + "loader-utils": "^1.2.3", + "schema-utils": "^1.0.0", + "serialize-javascript": "^1.7.0", + "source-map": "^0.6.1", + "terser": "^4.0.0", + "webpack-sources": "^1.3.0", + "worker-farm": "^1.7.0" + }, + "dependencies": { + "big.js": { + "version": "5.2.2", + "resolved": "https://registry.npmjs.org/big.js/-/big.js-5.2.2.tgz", + "integrity": "sha512-vyL2OymJxmarO8gxMr0mhChsO9QGwhynfuu4+MHTAW6czfq9humCB7rKpUjDd9YUiDPU4mzpyupFSvOClAwbmQ==", "dev": true }, - "braces": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", - "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", - "dev": true, - "requires": { - "arr-flatten": "^1.1.0", - "array-unique": "^0.3.2", - "extend-shallow": "^2.0.1", - "fill-range": "^4.0.0", - "isobject": "^3.0.1", - "repeat-element": "^1.1.2", - "snapdragon": "^0.8.1", - "snapdragon-node": "^2.0.1", - "split-string": "^3.0.2", - "to-regex": "^3.0.1" - }, - "dependencies": { - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "requires": { - "is-extendable": "^0.1.0" - } - } - } - }, - "expand-brackets": { - "version": "2.1.4", - "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz", - "integrity": "sha1-t3c14xXOMPa27/D4OwQVGiJEliI=", + "json5": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.1.tgz", + "integrity": "sha512-aKS4WQjPenRxiQsC93MNfjx+nbF4PAdYzmd/1JIj8HYzqfbu86beTuNgXDzPknWk0n0uARlyewZo4s++ES36Ow==", "dev": true, "requires": { - "debug": "^2.3.3", - "define-property": "^0.2.5", - "extend-shallow": "^2.0.1", - "posix-character-classes": "^0.1.0", - "regex-not": "^1.0.0", - "snapdragon": "^0.8.1", - "to-regex": "^3.0.1" - }, - "dependencies": { - "define-property": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", - "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", - "dev": true, - "requires": { - "is-descriptor": "^0.1.0" - } - }, - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "requires": { - "is-extendable": "^0.1.0" - } - }, - "is-accessor-descriptor": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", - "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", - "dev": true, - "requires": { - "kind-of": "^3.0.2" - }, - "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "requires": { - "is-buffer": "^1.1.5" - } - } - } - }, - "is-data-descriptor": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", - "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", - "dev": true, - "requires": { - "kind-of": "^3.0.2" - }, - "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "requires": { - "is-buffer": "^1.1.5" - } - } - } - }, - "is-descriptor": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", - "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", - "dev": true, - "requires": { - "is-accessor-descriptor": "^0.1.6", - "is-data-descriptor": "^0.1.4", - "kind-of": "^5.0.0" - } - }, - "kind-of": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", - "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", - "dev": true - } + "minimist": "^1.2.0" } }, - "extglob": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/extglob/-/extglob-2.0.4.tgz", - "integrity": "sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw==", + "loader-utils": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-1.2.3.tgz", + "integrity": "sha512-fkpz8ejdnEMG3s37wGL07iSBDg99O9D5yflE9RGNH3hRdx9SOwYfnGYdZOUIZitN8E+E2vkq3MUMYMvPYl5ZZA==", "dev": true, "requires": { - "array-unique": "^0.3.2", - "define-property": "^1.0.0", - "expand-brackets": "^2.1.4", - "extend-shallow": "^2.0.1", - "fragment-cache": "^0.2.1", - "regex-not": "^1.0.0", - "snapdragon": "^0.8.1", - "to-regex": "^3.0.1" - }, - "dependencies": { - "define-property": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", - "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", - "dev": true, - "requires": { - "is-descriptor": "^1.0.0" - } - }, - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "requires": { - "is-extendable": "^0.1.0" - } - } + "big.js": "^5.2.2", + "emojis-list": "^2.0.0", + "json5": "^1.0.1" } }, - "fill-range": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", - "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=", + "webpack-sources": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-1.3.0.tgz", + "integrity": "sha512-OiVgSrbGu7NEnEvQJJgdSFPl2qWKkWq5lHMhgiToIiN9w34EBnjYzSYs+VbL5KoYiLNtFFa7BZIKxRED3I32pA==", "dev": true, "requires": { - "extend-shallow": "^2.0.1", - "is-number": "^3.0.0", - "repeat-string": "^1.6.1", - "to-regex-range": "^2.1.0" - }, - "dependencies": { - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "requires": { - "is-extendable": "^0.1.0" - } - } + "source-list-map": "^2.0.0", + "source-map": "~0.6.1" } - }, - "is-accessor-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", - "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + } + } + }, + "text-table": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", + "integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=", + "dev": true + }, + "through": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", + "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=", + "dev": true + }, + "through2": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz", + "integrity": "sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==", + "dev": true, + "requires": { + "readable-stream": "~2.3.6", + "xtend": "~4.0.1" + } + }, + "thunky": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/thunky/-/thunky-1.0.3.tgz", + "integrity": "sha512-YwT8pjmNcAXBZqrubu22P4FYsh2D4dxRmnWBOL8Jk8bUcRUtc5326kx32tuTmFDAZtLOGEVNl8POAR8j896Iow==", + "dev": true + }, + "timers-browserify": { + "version": "2.0.10", + "resolved": "https://registry.npmjs.org/timers-browserify/-/timers-browserify-2.0.10.tgz", + "integrity": "sha512-YvC1SV1XdOUaL6gx5CoGroT3Gu49pK9+TZ38ErPldOWW4j49GI1HKs9DV+KGq/w6y+LZ72W1c8cKz2vzY+qpzg==", + "dev": true, + "requires": { + "setimmediate": "^1.0.4" + } + }, + "timsort": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/timsort/-/timsort-0.3.0.tgz", + "integrity": "sha1-QFQRqOfmM5/mTbmiNN4R3DHgK9Q=", + "dev": true + }, + "tmp": { + "version": "0.0.33", + "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz", + "integrity": "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==", + "dev": true, + "requires": { + "os-tmpdir": "~1.0.2" + } + }, + "to-array": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/to-array/-/to-array-0.1.4.tgz", + "integrity": "sha1-F+bBH3PdTz10zaek/zI46a2b+JA=", + "dev": true + }, + "to-arraybuffer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/to-arraybuffer/-/to-arraybuffer-1.0.1.tgz", + "integrity": "sha1-fSKbH8xjfkZsoIEYCDanqr/4P0M=", + "dev": true + }, + "to-fast-properties": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-1.0.3.tgz", + "integrity": "sha1-uDVx+k2MJbguIxsG46MFXeTKGkc=", + "dev": true + }, + "to-object-path": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/to-object-path/-/to-object-path-0.3.0.tgz", + "integrity": "sha1-KXWIt7Dn4KwI4E5nL4XB9JmeF68=", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + } + }, + "to-regex": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/to-regex/-/to-regex-3.0.2.tgz", + "integrity": "sha512-FWtleNAtZ/Ki2qtqej2CXTOayOH9bHDQF+Q48VpWyDXjbYxA4Yz8iDB31zXOBUlOHHKidDbqGVrTUvQMPmBGBw==", + "dev": true, + "requires": { + "define-property": "^2.0.2", + "extend-shallow": "^3.0.2", + "regex-not": "^1.0.2", + "safe-regex": "^1.1.0" + } + }, + "to-regex-range": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-2.1.1.tgz", + "integrity": "sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg=", + "dev": true, + "requires": { + "is-number": "^3.0.0", + "repeat-string": "^1.6.1" + }, + "dependencies": { + "is-number": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", + "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", "dev": true, "requires": { - "kind-of": "^6.0.0" + "kind-of": "^3.0.2" } - }, - "is-data-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", - "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + } + } + }, + "toidentifier": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.0.tgz", + "integrity": "sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw==", + "dev": true + }, + "toposort": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/toposort/-/toposort-1.0.7.tgz", + "integrity": "sha1-LmhELZ9k7HILjMieZEOsbKqVACk=", + "dev": true + }, + "tough-cookie": { + "version": "2.4.3", + "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.4.3.tgz", + "integrity": "sha512-Q5srk/4vDM54WJsJio3XNn6K2sCG+CQ8G5Wz6bZhRZoAe/+TxjWB/GlFAnYEbkYVlON9FMk/fE3h2RLpPXo4lQ==", + "dev": true, + "requires": { + "psl": "^1.1.24", + "punycode": "^1.4.1" + }, + "dependencies": { + "punycode": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", + "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=", + "dev": true + } + } + }, + "tree-kill": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/tree-kill/-/tree-kill-1.2.1.tgz", + "integrity": "sha512-4hjqbObwlh2dLyW4tcz0Ymw0ggoaVDMveUB9w8kFSQScdRLo0gxO9J7WFcUBo+W3C1TLdFIEwNOWebgZZ0RH9Q==", + "dev": true + }, + "trim-newlines": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/trim-newlines/-/trim-newlines-1.0.0.tgz", + "integrity": "sha1-WIeWa7WCpFA6QetST301ARgVphM=", + "dev": true + }, + "trim-right": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/trim-right/-/trim-right-1.0.1.tgz", + "integrity": "sha1-yy4SAwZ+DI3h9hQJS5/kVwTqYAM=", + "dev": true + }, + "true-case-path": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/true-case-path/-/true-case-path-1.0.3.tgz", + "integrity": "sha512-m6s2OdQe5wgpFMC+pAJ+q9djG82O2jcHPOI6RNg1yy9rCYR+WD6Nbpl32fDpfC56nirdRy+opFa/Vk7HYhqaew==", + "dev": true, + "requires": { + "glob": "^7.1.2" + } + }, + "ts-loader": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/ts-loader/-/ts-loader-6.0.2.tgz", + "integrity": "sha512-kkF3sGf3oBUehlvXI9fkbItbFTnNgGkYAz91vtWnsKAU4m+LAmQjuby7uTZNo3As+/zHLuyB052SkQDY6vLXtg==", + "dev": true, + "requires": { + "chalk": "^2.3.0", + "enhanced-resolve": "^4.0.0", + "loader-utils": "^1.0.2", + "micromatch": "^4.0.0", + "semver": "^6.0.0" + }, + "dependencies": { + "braces": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", + "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", "dev": true, "requires": { - "kind-of": "^6.0.0" + "fill-range": "^7.0.1" } }, - "is-descriptor": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", - "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "fill-range": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", + "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", "dev": true, "requires": { - "is-accessor-descriptor": "^1.0.0", - "is-data-descriptor": "^1.0.0", - "kind-of": "^6.0.2" + "to-regex-range": "^5.0.1" } }, "is-number": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", - "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "dev": true + }, + "micromatch": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.2.tgz", + "integrity": "sha512-y7FpHSbMUMoyPbYUSzO6PaZ6FyRnQOpHuKwbo1G+Knck95XVU4QAiKdGEnj5wwoS7PlOgthX/09u5iFJ+aYf5Q==", "dev": true, "requires": { - "kind-of": "^3.0.2" - }, - "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "requires": { - "is-buffer": "^1.1.5" - } - } + "braces": "^3.0.1", + "picomatch": "^2.0.5" } }, - "isobject": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", - "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", - "dev": true - }, - "kind-of": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", - "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==", + "semver": { + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.1.1.tgz", + "integrity": "sha512-rWYq2e5iYW+fFe/oPPtYJxYgjBm8sC4rmoGdUOgBB7VnwKt6HrL793l2voH1UlsyYZpJ4g0wfjnTEO1s1NP2eQ==", "dev": true }, - "micromatch": { - "version": "3.1.10", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", - "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", + "to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", "dev": true, "requires": { - "arr-diff": "^4.0.0", - "array-unique": "^0.3.2", - "braces": "^2.3.1", - "define-property": "^2.0.2", - "extend-shallow": "^3.0.2", - "extglob": "^2.0.4", - "fragment-cache": "^0.2.1", - "kind-of": "^6.0.2", - "nanomatch": "^1.2.9", - "object.pick": "^1.3.0", - "regex-not": "^1.0.0", - "snapdragon": "^0.8.1", - "to-regex": "^3.0.2" + "is-number": "^7.0.0" } } } @@ -15358,9 +14695,9 @@ "integrity": "sha512-4krF8scpejhaOgqzBEcGM7yDIEfi0/8+8zDRZhNZZ2kjmHJ4hv3zCbQWxoJGz1iw5U0Jl0nma13xzHXcncMavQ==" }, "tslint": { - "version": "5.16.0", - "resolved": "https://registry.npmjs.org/tslint/-/tslint-5.16.0.tgz", - "integrity": "sha512-UxG2yNxJ5pgGwmMzPMYh/CCnCnh0HfPgtlVRDs1ykZklufFBL1ZoTlWFRz2NQjcoEiDoRp+JyT0lhBbbH/obyA==", + "version": "5.17.0", + "resolved": "https://registry.npmjs.org/tslint/-/tslint-5.17.0.tgz", + "integrity": "sha512-pflx87WfVoYepTet3xLfDOLDm9Jqi61UXIKePOuca0qoAZyrGWonDG9VTbji58Fy+8gciUn8Bt7y69+KEVjc/w==", "dev": true, "requires": { "@babel/code-frame": "^7.0.0", @@ -15369,7 +14706,7 @@ "commander": "^2.12.1", "diff": "^3.2.0", "glob": "^7.1.1", - "js-yaml": "^3.13.0", + "js-yaml": "^3.13.1", "minimatch": "^3.0.4", "mkdirp": "^0.5.1", "resolve": "^1.3.2", @@ -15474,9 +14811,9 @@ } }, "typescript": { - "version": "3.2.4", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-3.2.4.tgz", - "integrity": "sha512-0RNDbSdEokBeEAkgNbxJ+BLwSManFy9TeXz8uW+48j/xhEXv1ePME60olyzw2XzUqUBNAYFeJadIqAgNqIACwg==", + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-3.4.3.tgz", + "integrity": "sha512-FFgHdPt4T/duxx6Ndf7hwgMZZjZpB+U0nMNGVCYPq0rEzWKjEDobm4J6yb3CS7naZ0yURFqdw9Gwc7UOh/P9oQ==", "dev": true }, "uc.micro": { @@ -15495,19 +14832,48 @@ } }, "uglifyjs-webpack-plugin": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/uglifyjs-webpack-plugin/-/uglifyjs-webpack-plugin-2.1.2.tgz", - "integrity": "sha512-G1fJx2uOAAfvdZ77SVCzmFo6mv8uKaHoZBL9Qq/ciC8r6p0ANOL1uY85fIUiyWXKw5RzAaJYZfNSL58Or2hQ0A==", + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/uglifyjs-webpack-plugin/-/uglifyjs-webpack-plugin-2.1.3.tgz", + "integrity": "sha512-/lRkCaFbI6pT3CxsQHDhBcqB6tocOnqba0vJqJ2DzSWFLRgOIiip8q0nVFydyXk+n8UtF7ZuS6hvWopcYH5FuA==", "dev": true, "requires": { - "cacache": "^11.2.0", - "find-cache-dir": "^2.0.0", + "cacache": "^11.3.2", + "find-cache-dir": "^2.1.0", + "is-wsl": "^1.1.0", "schema-utils": "^1.0.0", - "serialize-javascript": "^1.4.0", + "serialize-javascript": "^1.7.0", "source-map": "^0.6.1", - "uglify-js": "^3.0.0", - "webpack-sources": "^1.1.0", - "worker-farm": "^1.5.2" + "uglify-js": "^3.5.12", + "webpack-sources": "^1.3.0", + "worker-farm": "^1.7.0" + }, + "dependencies": { + "commander": { + "version": "2.20.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.0.tgz", + "integrity": "sha512-7j2y+40w61zy6YC2iRNpUe/NwhNyoXrYpHMrSunaMG64nRnaf96zO/KMQR4OyN/UnE5KLyEBnKHd4aG3rskjpQ==", + "dev": true + }, + "uglify-js": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.6.0.tgz", + "integrity": "sha512-W+jrUHJr3DXKhrsS7NUVxn3zqMOFn0hL/Ei6v0anCIMoKC93TjcflTagwIHLW7SfMFfiQuktQyFVCFHGUE0+yg==", + "dev": true, + "requires": { + "commander": "~2.20.0", + "source-map": "~0.6.1" + } + }, + "webpack-sources": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-1.3.0.tgz", + "integrity": "sha512-OiVgSrbGu7NEnEvQJJgdSFPl2qWKkWq5lHMhgiToIiN9w34EBnjYzSYs+VbL5KoYiLNtFFa7BZIKxRED3I32pA==", + "dev": true, + "requires": { + "source-list-map": "^2.0.0", + "source-map": "~0.6.1" + } + } } }, "ultron": { @@ -15781,9 +15147,9 @@ "dev": true }, "v8-compile-cache": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.0.2.tgz", - "integrity": "sha512-1wFuMUIM16MDJRCrpbpuEPTUGmM5QMUg0cr3KFwra2XgOgFcPGDQHDh3CszSCD2Zewc/dh/pamNEW8CbfDebUw==", + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.0.3.tgz", + "integrity": "sha512-CNmdbwQMBjwr9Gsmohvm0pbL954tJrNzf6gWL3K+QMQf00PF7ERGrEiLgjuU3mKreLC2MeGhUsNV9ybTbLgd3w==", "dev": true }, "validate-npm-package-license": { @@ -15908,9 +15274,9 @@ } }, "chokidar": { - "version": "2.1.5", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-2.1.5.tgz", - "integrity": "sha512-i0TprVWp+Kj4WRPtInjexJ8Q+BqTE909VpH8xVhXrJkoc5QC8VO9TryGOqTr+2hljzc1sC62t22h5tZePodM/A==", + "version": "2.1.6", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-2.1.6.tgz", + "integrity": "sha512-V2jUo67OKkc6ySiRpJrjlpJKl9kDuG+Xb8VgsGzb+aEouhgS1D0weyPU4lEzdAcsCAvrih2J2BqyXqHWvVLw5g==", "dev": true, "requires": { "anymatch": "^2.0.0", @@ -16079,9 +15445,9 @@ } }, "fsevents": { - "version": "1.2.8", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.2.8.tgz", - "integrity": "sha512-tPvHgPGB7m40CZ68xqFGkKuzN+RnpGmSV+hgeKxhRpbxdqKXUFJGC3yonBOLzQBcJyGpdZFDfCsdOC2KFsXzeA==", + "version": "1.2.9", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.2.9.tgz", + "integrity": "sha512-oeyj2H3EjjonWcFjD5NvZNE9Rqe4UW+nQBU2HNeKw0koVLEFIhtyETyAakeAM3de7Z/SW5kcA+fZUait9EApnw==", "dev": true, "optional": true, "requires": { @@ -16745,9 +16111,9 @@ } }, "nan": { - "version": "2.13.2", - "resolved": "https://registry.npmjs.org/nan/-/nan-2.13.2.tgz", - "integrity": "sha512-TghvYc72wlMGMVMluVo9WRJc0mB8KxxF/gZ4YYFy7V2ZQX9l7rgbPg7vjS9mt6U5HXODVFVI2bOduCzwOMv/lw==", + "version": "2.14.0", + "resolved": "https://registry.npmjs.org/nan/-/nan-2.14.0.tgz", + "integrity": "sha512-INOFj37C7k3AfaNTtX8RhsTw7qRy7eLET14cROi9+5HAVbbHuIWUHEauBv5qT4Av2tWasiTY1Jw6puUNqRJXQg==", "dev": true, "optional": true }, @@ -16780,9 +16146,9 @@ } }, "webpack": { - "version": "4.30.0", - "resolved": "https://registry.npmjs.org/webpack/-/webpack-4.30.0.tgz", - "integrity": "sha512-4hgvO2YbAFUhyTdlR4FNyt2+YaYBYHavyzjCMbZzgglo02rlKi/pcsEzwCuCpsn1ryzIl1cq/u8ArIKu8JBYMg==", + "version": "4.32.2", + "resolved": "https://registry.npmjs.org/webpack/-/webpack-4.32.2.tgz", + "integrity": "sha512-F+H2Aa1TprTQrpodRAWUMJn7A8MgDx82yQiNvYMaj3d1nv3HetKU0oqEulL9huj8enirKi8KvEXQ3QtuHF89Zg==", "dev": true, "requires": { "@webassemblyjs/ast": "1.8.5", @@ -17110,9 +16476,9 @@ } }, "webpack-cli": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/webpack-cli/-/webpack-cli-3.3.1.tgz", - "integrity": "sha512-c2inFU7SM0IttEgF7fK6AaUsbBnORRzminvbyRKS+NlbQHVZdCtzKBlavRL5359bFsywXGRAItA5di/IruC8mg==", + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/webpack-cli/-/webpack-cli-3.3.2.tgz", + "integrity": "sha512-FLkobnaJJ+03j5eplxlI0TUxhGCOdfewspIGuvDVtpOlrAuKMFC57K42Ukxqs1tn8947/PM6tP95gQc0DCzRYA==", "dev": true, "requires": { "chalk": "^2.4.1", @@ -17134,12 +16500,6 @@ "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", "dev": true }, - "camelcase": { - "version": "5.3.1", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", - "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", - "dev": true - }, "cliui": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/cliui/-/cliui-4.1.0.tgz", @@ -17151,129 +16511,6 @@ "wrap-ansi": "^2.0.0" } }, - "cross-spawn": { - "version": "6.0.5", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz", - "integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==", - "dev": true, - "requires": { - "nice-try": "^1.0.4", - "path-key": "^2.0.1", - "semver": "^5.5.0", - "shebang-command": "^1.2.0", - "which": "^1.2.9" - } - }, - "execa": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/execa/-/execa-1.0.0.tgz", - "integrity": "sha512-adbxcyWV46qiHyvSp50TKt05tB4tK3HcmF7/nxfAdhnox83seTDbwnaqKO4sXRy7roHAIFqJP/Rw/AuEbX61LA==", - "dev": true, - "requires": { - "cross-spawn": "^6.0.0", - "get-stream": "^4.0.0", - "is-stream": "^1.1.0", - "npm-run-path": "^2.0.0", - "p-finally": "^1.0.0", - "signal-exit": "^3.0.0", - "strip-eof": "^1.0.0" - } - }, - "find-up": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", - "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", - "dev": true, - "requires": { - "locate-path": "^3.0.0" - } - }, - "get-stream": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-4.1.0.tgz", - "integrity": "sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w==", - "dev": true, - "requires": { - "pump": "^3.0.0" - } - }, - "invert-kv": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/invert-kv/-/invert-kv-2.0.0.tgz", - "integrity": "sha512-wPVv/y/QQ/Uiirj/vh3oP+1Ww+AWehmi1g5fFWGPF6IpCBCDVrhgHRMvrLfdYcwDh3QJbGXDW4JAuzxElLSqKA==", - "dev": true - }, - "lcid": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/lcid/-/lcid-2.0.0.tgz", - "integrity": "sha512-avPEb8P8EGnwXKClwsNUgryVjllcRqtMYa49NTsbQagYuT1DcXnl1915oxWjoyGrXR6zH/Y0Zc96xWsPcoDKeA==", - "dev": true, - "requires": { - "invert-kv": "^2.0.0" - } - }, - "locate-path": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", - "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", - "dev": true, - "requires": { - "p-locate": "^3.0.0", - "path-exists": "^3.0.0" - } - }, - "mem": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/mem/-/mem-4.3.0.tgz", - "integrity": "sha512-qX2bG48pTqYRVmDB37rn/6PT7LcR8T7oAX3bf99u1Tt1nzxYfxkgqDwUwolPlXweM0XzBOBFzSx4kfp7KP1s/w==", - "dev": true, - "requires": { - "map-age-cleaner": "^0.1.1", - "mimic-fn": "^2.0.0", - "p-is-promise": "^2.0.0" - } - }, - "mimic-fn": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", - "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", - "dev": true - }, - "os-locale": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-3.1.0.tgz", - "integrity": "sha512-Z8l3R4wYWM40/52Z+S265okfFj8Kt2cC2MKY+xNi3kFs+XGI7WXu/I309QQQYbRW4ijiZ+yxs9pqEhJh0DqW3Q==", - "dev": true, - "requires": { - "execa": "^1.0.0", - "lcid": "^2.0.0", - "mem": "^4.0.0" - } - }, - "p-limit": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.2.0.tgz", - "integrity": "sha512-pZbTJpoUsCzV48Mc9Nh51VbwO0X9cuPFE8gYwx9BTCt9SF8/b7Zljd2fVgOxhIF/HDTKgpVzs+GPhyKfjLLFRQ==", - "dev": true, - "requires": { - "p-try": "^2.0.0" - } - }, - "p-locate": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", - "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", - "dev": true, - "requires": { - "p-limit": "^2.0.0" - } - }, - "p-try": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", - "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", - "dev": true - }, "strip-ansi": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", @@ -17340,31 +16577,31 @@ } }, "webpack-dev-server": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/webpack-dev-server/-/webpack-dev-server-3.3.1.tgz", - "integrity": "sha512-jY09LikOyGZrxVTXK0mgIq9y2IhCoJ05848dKZqX1gAGLU1YDqgpOT71+W53JH/wI4v6ky4hm+KvSyW14JEs5A==", + "version": "3.5.1", + "resolved": "https://registry.npmjs.org/webpack-dev-server/-/webpack-dev-server-3.5.1.tgz", + "integrity": "sha512-0IdMGddJcnK9zesZOeHWl4uAOVfypn7DSrdNWtclROkVBXy/TcBN+6eEG1wNfLT9dXVfaRZZsLTJt0mJtgTQgw==", "dev": true, "requires": { "ansi-html": "0.0.7", "bonjour": "^3.5.0", - "chokidar": "^2.1.5", + "chokidar": "^2.1.6", "compression": "^1.7.4", "connect-history-api-fallback": "^1.6.0", "debug": "^4.1.1", - "del": "^4.1.0", - "express": "^4.16.4", + "del": "^4.1.1", + "express": "^4.17.1", "html-entities": "^1.2.1", "http-proxy-middleware": "^0.19.1", "import-local": "^2.0.0", - "internal-ip": "^4.2.0", + "internal-ip": "^4.3.0", "ip": "^1.1.5", "killable": "^1.0.1", - "loglevel": "^1.6.1", + "loglevel": "^1.6.2", "opn": "^5.5.0", "portfinder": "^1.0.20", "schema-utils": "^1.0.0", "selfsigned": "^1.10.4", - "semver": "^6.0.0", + "semver": "^6.1.1", "serve-index": "^1.9.1", "sockjs": "0.3.19", "sockjs-client": "1.3.0", @@ -17372,7 +16609,7 @@ "strip-ansi": "^3.0.1", "supports-color": "^6.1.0", "url": "^0.11.0", - "webpack-dev-middleware": "^3.6.2", + "webpack-dev-middleware": "^3.7.0", "webpack-log": "^2.0.0", "yargs": "12.0.5" }, @@ -17445,16 +16682,10 @@ } } }, - "camelcase": { - "version": "5.3.1", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", - "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", - "dev": true - }, "chokidar": { - "version": "2.1.5", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-2.1.5.tgz", - "integrity": "sha512-i0TprVWp+Kj4WRPtInjexJ8Q+BqTE909VpH8xVhXrJkoc5QC8VO9TryGOqTr+2hljzc1sC62t22h5tZePodM/A==", + "version": "2.1.6", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-2.1.6.tgz", + "integrity": "sha512-V2jUo67OKkc6ySiRpJrjlpJKl9kDuG+Xb8VgsGzb+aEouhgS1D0weyPU4lEzdAcsCAvrih2J2BqyXqHWvVLw5g==", "dev": true, "requires": { "anymatch": "^2.0.0", @@ -17493,27 +16724,6 @@ } } }, - "cross-spawn": { - "version": "6.0.5", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz", - "integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==", - "dev": true, - "requires": { - "nice-try": "^1.0.4", - "path-key": "^2.0.1", - "semver": "^5.5.0", - "shebang-command": "^1.2.0", - "which": "^1.2.9" - }, - "dependencies": { - "semver": { - "version": "5.7.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.0.tgz", - "integrity": "sha512-Ya52jSX2u7QKghxeoFGpLwCtGlt7j0oY9DYb5apt9nPlJ42ID+ulTXESnt/qAQcoSERyZ5sl3LDIOw0nAn/5DA==", - "dev": true - } - } - }, "debug": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", @@ -17531,21 +16741,6 @@ } } }, - "execa": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/execa/-/execa-1.0.0.tgz", - "integrity": "sha512-adbxcyWV46qiHyvSp50TKt05tB4tK3HcmF7/nxfAdhnox83seTDbwnaqKO4sXRy7roHAIFqJP/Rw/AuEbX61LA==", - "dev": true, - "requires": { - "cross-spawn": "^6.0.0", - "get-stream": "^4.0.0", - "is-stream": "^1.1.0", - "npm-run-path": "^2.0.0", - "p-finally": "^1.0.0", - "signal-exit": "^3.0.0", - "strip-eof": "^1.0.0" - } - }, "expand-brackets": { "version": "2.1.4", "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz", @@ -17706,19 +16901,10 @@ } } }, - "find-up": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", - "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", - "dev": true, - "requires": { - "locate-path": "^3.0.0" - } - }, "fsevents": { - "version": "1.2.8", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.2.8.tgz", - "integrity": "sha512-tPvHgPGB7m40CZ68xqFGkKuzN+RnpGmSV+hgeKxhRpbxdqKXUFJGC3yonBOLzQBcJyGpdZFDfCsdOC2KFsXzeA==", + "version": "1.2.9", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.2.9.tgz", + "integrity": "sha512-oeyj2H3EjjonWcFjD5NvZNE9Rqe4UW+nQBU2HNeKw0koVLEFIhtyETyAakeAM3de7Z/SW5kcA+fZUait9EApnw==", "dev": true, "optional": true, "requires": { @@ -18263,15 +17449,6 @@ } } }, - "get-stream": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-4.1.0.tgz", - "integrity": "sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w==", - "dev": true, - "requires": { - "pump": "^3.0.0" - } - }, "glob-parent": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-3.1.0.tgz", @@ -18293,12 +17470,6 @@ } } }, - "invert-kv": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/invert-kv/-/invert-kv-2.0.0.tgz", - "integrity": "sha512-wPVv/y/QQ/Uiirj/vh3oP+1Ww+AWehmi1g5fFWGPF6IpCBCDVrhgHRMvrLfdYcwDh3QJbGXDW4JAuzxElLSqKA==", - "dev": true - }, "is-accessor-descriptor": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", @@ -18375,36 +17546,6 @@ "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==", "dev": true }, - "lcid": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/lcid/-/lcid-2.0.0.tgz", - "integrity": "sha512-avPEb8P8EGnwXKClwsNUgryVjllcRqtMYa49NTsbQagYuT1DcXnl1915oxWjoyGrXR6zH/Y0Zc96xWsPcoDKeA==", - "dev": true, - "requires": { - "invert-kv": "^2.0.0" - } - }, - "locate-path": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", - "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", - "dev": true, - "requires": { - "p-locate": "^3.0.0", - "path-exists": "^3.0.0" - } - }, - "mem": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/mem/-/mem-4.3.0.tgz", - "integrity": "sha512-qX2bG48pTqYRVmDB37rn/6PT7LcR8T7oAX3bf99u1Tt1nzxYfxkgqDwUwolPlXweM0XzBOBFzSx4kfp7KP1s/w==", - "dev": true, - "requires": { - "map-age-cleaner": "^0.1.1", - "mimic-fn": "^2.0.0", - "p-is-promise": "^2.0.0" - } - }, "micromatch": { "version": "3.1.10", "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", @@ -18426,16 +17567,16 @@ "to-regex": "^3.0.2" } }, - "mimic-fn": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", - "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", + "mime": { + "version": "2.4.3", + "resolved": "https://registry.npmjs.org/mime/-/mime-2.4.3.tgz", + "integrity": "sha512-QgrPRJfE+riq5TPZMcHZOtm8c6K/yYrMbKIoRfapfiGLxS8OTeIfRhUGW5LU7MlRa52KOAGCfUNruqLrIBvWZw==", "dev": true }, "nan": { - "version": "2.13.2", - "resolved": "https://registry.npmjs.org/nan/-/nan-2.13.2.tgz", - "integrity": "sha512-TghvYc72wlMGMVMluVo9WRJc0mB8KxxF/gZ4YYFy7V2ZQX9l7rgbPg7vjS9mt6U5HXODVFVI2bOduCzwOMv/lw==", + "version": "2.14.0", + "resolved": "https://registry.npmjs.org/nan/-/nan-2.14.0.tgz", + "integrity": "sha512-INOFj37C7k3AfaNTtX8RhsTw7qRy7eLET14cROi9+5HAVbbHuIWUHEauBv5qT4Av2tWasiTY1Jw6puUNqRJXQg==", "dev": true, "optional": true }, @@ -18445,39 +17586,10 @@ "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", "dev": true }, - "os-locale": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-3.1.0.tgz", - "integrity": "sha512-Z8l3R4wYWM40/52Z+S265okfFj8Kt2cC2MKY+xNi3kFs+XGI7WXu/I309QQQYbRW4ijiZ+yxs9pqEhJh0DqW3Q==", - "dev": true, - "requires": { - "execa": "^1.0.0", - "lcid": "^2.0.0", - "mem": "^4.0.0" - } - }, - "p-limit": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.2.0.tgz", - "integrity": "sha512-pZbTJpoUsCzV48Mc9Nh51VbwO0X9cuPFE8gYwx9BTCt9SF8/b7Zljd2fVgOxhIF/HDTKgpVzs+GPhyKfjLLFRQ==", - "dev": true, - "requires": { - "p-try": "^2.0.0" - } - }, - "p-locate": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", - "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", - "dev": true, - "requires": { - "p-limit": "^2.0.0" - } - }, - "p-try": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", - "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", + "range-parser": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", + "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", "dev": true }, "readdirp": { @@ -18492,9 +17604,9 @@ } }, "semver": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.0.0.tgz", - "integrity": "sha512-0UewU+9rFapKFnlbirLi3byoOuhrSsli/z/ihNnvM24vgF+8sNBiI1LZPBSH9wJKUwaUbw+s3hToDLCXkrghrQ==", + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.1.1.tgz", + "integrity": "sha512-rWYq2e5iYW+fFe/oPPtYJxYgjBm8sC4rmoGdUOgBB7VnwKt6HrL793l2voH1UlsyYZpJ4g0wfjnTEO1s1NP2eQ==", "dev": true }, "supports-color": { @@ -18507,14 +17619,14 @@ } }, "webpack-dev-middleware": { - "version": "3.6.2", - "resolved": "https://registry.npmjs.org/webpack-dev-middleware/-/webpack-dev-middleware-3.6.2.tgz", - "integrity": "sha512-A47I5SX60IkHrMmZUlB0ZKSWi29TZTcPz7cha1Z75yYOsgWh/1AcPmQEbC8ZIbU3A1ytSv1PMU0PyPz2Lmz2jg==", + "version": "3.7.0", + "resolved": "https://registry.npmjs.org/webpack-dev-middleware/-/webpack-dev-middleware-3.7.0.tgz", + "integrity": "sha512-qvDesR1QZRIAZHOE3iQ4CXLZZSQ1lAUsSpnQmlB1PBfoN/xdRjmge3Dok0W4IdaVLJOGJy3sGI4sZHwjRU0PCA==", "dev": true, "requires": { "memory-fs": "^0.4.1", - "mime": "^2.3.1", - "range-parser": "^1.0.3", + "mime": "^2.4.2", + "range-parser": "^1.2.1", "webpack-log": "^2.0.0" } }, @@ -18643,9 +17755,9 @@ "dev": true }, "worker-farm": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/worker-farm/-/worker-farm-1.6.0.tgz", - "integrity": "sha512-6w+3tHbM87WnSWnENBUvA2pxJPLhQUg5LKwUQHq3r+XPhIM+Gh2R5ycbwPCyuGbNg+lPgdcnQUhuC02kJCvffQ==", + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/worker-farm/-/worker-farm-1.7.0.tgz", + "integrity": "sha512-rvw3QTZc8lAxyVrqcSGVm5yP/IJ2UcB3U0graE3LCFoZ0Yn2x4EoVSqJKdB/T5M+FLcRPjz4TDacRf3OCfNUzw==", "dev": true, "requires": { "errno": "~0.1.7" @@ -18736,33 +17848,124 @@ "dev": true }, "yargs": { - "version": "9.0.1", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-9.0.1.tgz", - "integrity": "sha1-UqzCP+7Kw0BCB47njAwAf1CF20w=", + "version": "13.1.0", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-13.1.0.tgz", + "integrity": "sha512-1UhJbXfzHiPqkfXNHYhiz79qM/kZqjTE8yGlEjZa85Q+3+OwcV6NRkV7XOV1W2Eom2bzILeUn55pQYffjVOLAg==", "dev": true, "requires": { - "camelcase": "^4.1.0", - "cliui": "^3.2.0", - "decamelize": "^1.1.1", - "get-caller-file": "^1.0.1", - "os-locale": "^2.0.0", - "read-pkg-up": "^2.0.0", + "cliui": "^4.0.0", + "find-up": "^3.0.0", + "get-caller-file": "^2.0.1", + "os-locale": "^3.1.0", "require-directory": "^2.1.1", - "require-main-filename": "^1.0.1", + "require-main-filename": "^2.0.0", "set-blocking": "^2.0.0", - "string-width": "^2.0.0", + "string-width": "^3.0.0", "which-module": "^2.0.0", - "y18n": "^3.2.1", - "yargs-parser": "^7.0.0" + "y18n": "^4.0.0", + "yargs-parser": "^13.0.0" + }, + "dependencies": { + "ansi-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", + "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", + "dev": true + }, + "cliui": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-4.1.0.tgz", + "integrity": "sha512-4FG+RSG9DL7uEwRUZXZn3SS34DiDPfzP0VOiEwtUWlE+AR2EIg+hSyvrIgUUfhdgR/UkAeW2QHgeP+hWrXs7jQ==", + "dev": true, + "requires": { + "string-width": "^2.1.1", + "strip-ansi": "^4.0.0", + "wrap-ansi": "^2.0.0" + }, + "dependencies": { + "string-width": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", + "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", + "dev": true, + "requires": { + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^4.0.0" + } + } + } + }, + "get-caller-file": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", + "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", + "dev": true + }, + "is-fullwidth-code-point": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", + "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", + "dev": true + }, + "require-main-filename": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz", + "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==", + "dev": true + }, + "string-width": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", + "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", + "dev": true, + "requires": { + "emoji-regex": "^7.0.1", + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^5.1.0" + }, + "dependencies": { + "ansi-regex": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", + "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", + "dev": true + }, + "strip-ansi": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", + "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", + "dev": true, + "requires": { + "ansi-regex": "^4.1.0" + } + } + } + }, + "strip-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", + "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", + "dev": true, + "requires": { + "ansi-regex": "^3.0.0" + } + }, + "y18n": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.0.tgz", + "integrity": "sha512-r9S/ZyXu/Xu9q1tYlpsLIsa3EeLXXk0VwlxqTcFRfg9EhMW+17kbt9G0NrgCmhGb5vT2hyhJZLfDGx+7+5Uj/w==", + "dev": true + } } }, "yargs-parser": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-7.0.0.tgz", - "integrity": "sha1-jQrELxbqVd69MyyvTEA4s+P139k=", + "version": "13.1.0", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-13.1.0.tgz", + "integrity": "sha512-Yq+32PrijHRri0vVKQEm+ys8mbqWjLiwQkMFNXEENutzLPP0bE4Lcd4iA3OQY5HF+GD3xXxf0MEHb8E4/SA3AA==", "dev": true, "requires": { - "camelcase": "^4.1.0" + "camelcase": "^5.0.0", + "decamelize": "^1.2.0" } }, "yeast": { diff --git a/src/Squidex/package.json b/src/Squidex/package.json index 72f1ab671..cf9b1f8af 100644 --- a/src/Squidex/package.json +++ b/src/Squidex/package.json @@ -15,21 +15,21 @@ "build:clean": "rimraf wwwroot/build" }, "dependencies": { - "@angular/animations": "7.2.14", - "@angular/common": "7.2.14", - "@angular/core": "7.2.14", - "@angular/forms": "7.2.14", - "@angular/http": "7.2.14", - "@angular/platform-browser-dynamic": "7.2.14", - "@angular/platform-browser": "7.2.14", - "@angular/platform-server": "7.2.14", - "@angular/router": "7.2.14", + "@angular/animations": "8.0.0", + "@angular/common": "8.0.0", + "@angular/core": "8.0.0", + "@angular/forms": "8.0.0", + "@angular/http": "7.2.15", + "@angular/platform-browser-dynamic": "8.0.0", + "@angular/platform-browser": "8.0.0", + "@angular/platform-server": "8.0.0", + "@angular/router": "8.0.0", "angular2-chartjs": "0.5.1", "babel-polyfill": "6.26.0", "bootstrap": "4.3.1", - "core-js": "2.6.3", + "core-js": "3.1.3", "graphiql": "0.13.0", - "graphql": "14.2.1", + "graphql": "14.3.1", "marked": "0.6.2", "moment": "2.24.0", "mousetrap": "1.6.3", @@ -40,23 +40,23 @@ "progressbar.js": "1.0.1", "react-dom": "16.8.6", "react": "16.8.6", - "rxjs": "6.5.1", + "rxjs": "6.5.2", "slugify": "1.3.4", "sortablejs": "1.9.0", "tslib": "1.9.3", "zone.js": "0.9.1" }, "devDependencies": { - "@angular/compiler-cli": "7.2.14", - "@angular/compiler": "7.2.14", - "@ngtools/webpack": "7.3.8", + "@angular/compiler-cli": "8.0.0", + "@angular/compiler": "8.0.0", + "@ngtools/webpack": "8.0.1", "@types/core-js": "2.5.0", - "@types/jasmine": "3.3.12", + "@types/jasmine": "3.3.13", "@types/marked": "0.6.5", "@types/mousetrap": "1.6", - "@types/node": "12.0.0", + "@types/node": "12.0.4", "@types/react-dom": "16.8.4", - "@types/react": "16.8.16", + "@types/react": "16.8.19", "@types/sortablejs": "1.7.2", "angular-router-loader": "0.8.5", "angular2-template-loader": "0.6.2", @@ -82,7 +82,7 @@ "karma-sourcemap-loader": "0.3.7", "karma-webpack": "3.0.5", "karma": "4.1.0", - "mini-css-extract-plugin": "0.6.0", + "mini-css-extract-plugin": "0.7.0", "node-sass": "4.12.0", "optimize-css-assets-webpack-plugin": "5.0.1", "raw-loader": "1.0.0", @@ -91,17 +91,17 @@ "sass-lint": "1.13.1", "sass-loader": "7.1.0", "style-loader": "0.23.1", - "ts-loader": "5.4.5", + "ts-loader": "6.0.2", "tsconfig-paths-webpack-plugin": "3.2.0", "tslint-webpack-plugin": "2.0.4", - "tslint": "5.16.0", + "tslint": "5.17.0", "typemoq": "2.1.0", - "typescript": "3.2.4", - "uglifyjs-webpack-plugin": "2.1.2", + "typescript": "3.4.3", + "uglifyjs-webpack-plugin": "2.1.3", "underscore": "1.9.1", - "webpack-cli": "3.3.1", - "webpack-dev-server": "3.3.1", + "webpack-cli": "3.3.2", + "webpack-dev-server": "3.5.1", "webpack-merge": "4.2.1", - "webpack": "4.30.0" + "webpack": "4.32.2" } } diff --git a/src/Squidex/tsconfig.json b/src/Squidex/tsconfig.json index 9bb19bd05..38f1bc4dd 100644 --- a/src/Squidex/tsconfig.json +++ b/src/Squidex/tsconfig.json @@ -3,6 +3,7 @@ "baseUrl": ".", "emitDecoratorMetadata": true, "experimentalDecorators": true, + "incremental": true, "importHelpers": true, "lib": ["es6", "esnext", "dom"], "moduleResolution": "node", From 35d9640b856b5ce1bc2bb27d71d155659aed4b70 Mon Sep 17 00:00:00 2001 From: Sebastian Date: Sun, 2 Jun 2019 11:11:44 +0200 Subject: [PATCH 02/47] Simplified build --- src/Squidex/.vscode/settings.json | 36 -- src/Squidex/app-config/helpers.js | 25 - src/Squidex/app-config/karma-test-shim.js | 3 +- src/Squidex/app-config/karma.conf.js | 6 +- src/Squidex/app-config/karma.coverage.conf.js | 6 +- src/Squidex/app-config/webpack.config.js | 446 +++++++++++++----- src/Squidex/app-config/webpack.run.base.js | 35 -- src/Squidex/app-config/webpack.run.dev.js | 68 --- src/Squidex/app-config/webpack.run.prod.js | 137 ------ .../app-config/webpack.test.coverage.js | 37 -- src/Squidex/app-config/webpack.test.js | 16 - .../app/shared/state/assets.state.spec.ts | 31 +- src/Squidex/app/shims.ts | 2 - src/Squidex/package-lock.json | 78 +-- src/Squidex/package.json | 13 +- 15 files changed, 377 insertions(+), 562 deletions(-) delete mode 100644 src/Squidex/.vscode/settings.json delete mode 100644 src/Squidex/app-config/helpers.js delete mode 100644 src/Squidex/app-config/webpack.run.base.js delete mode 100644 src/Squidex/app-config/webpack.run.dev.js delete mode 100644 src/Squidex/app-config/webpack.run.prod.js delete mode 100644 src/Squidex/app-config/webpack.test.coverage.js delete mode 100644 src/Squidex/app-config/webpack.test.js diff --git a/src/Squidex/.vscode/settings.json b/src/Squidex/.vscode/settings.json deleted file mode 100644 index 26a63fc30..000000000 --- a/src/Squidex/.vscode/settings.json +++ /dev/null @@ -1,36 +0,0 @@ -{ - // When opening a file, `editor.tabSize` and `editor.insertSpaces` will be detected based on the file contents. - "editor.detectIndentation": false, - - // Typescript version from local package to be consistent - "typescript.tsdk": "node_modules/typescript/lib", - - // Configure glob patterns for excluding files and folders. - "files.exclude": { - "**/node_modules": true, - "**/Assets": true, - "**/artifacts": true, - "**/build": true, - "**/logs": true, - "**/out": true, - "**/obj": true, - "**/bin": true, - "**/*.lock.json": true, - "**/*.bat": true, - "**/*.sln": true, - "**/*.sln.DotSettings": true, - "**/*.user": true, - "**/*.xproj": true, - "**/*.gitattributes": true, - "appsetttings.Development.json": true, - "appsetttings.Production.json": true, - ".awcache": true, - ".vs:": true, - ".vscode:": true - }, - - "coverage-gutters.coverageFileNames": [ - "_test-output/coverage/lcov.info" - ], - "coverage-gutters.showLineCoverage": true -} \ No newline at end of file diff --git a/src/Squidex/app-config/helpers.js b/src/Squidex/app-config/helpers.js deleted file mode 100644 index acae3e4bb..000000000 --- a/src/Squidex/app-config/helpers.js +++ /dev/null @@ -1,25 +0,0 @@ -var path = require('path'); - -var appRoot = path.resolve(__dirname, '..'); - -exports.root = function () { - var newArgs = Array.prototype.slice.call(arguments, 0); - - return path.join.apply(path, [appRoot].concat(newArgs)); -}; - -exports.removeLoaders = function (config, extensions) { - var rules = config.module.rules; - - for (var i = 0; i < rules.length; i += 1) { - var rule = rules[i]; - - for (var j = 0; j < extensions.length; j += 1) { - if (rule.test.source.indexOf(extensions[j]) >= 0) { - rules.splice(i, 1); - i--; - break; - } - } - } -} \ No newline at end of file diff --git a/src/Squidex/app-config/karma-test-shim.js b/src/Squidex/app-config/karma-test-shim.js index 41a41e554..773d09e87 100644 --- a/src/Squidex/app-config/karma-test-shim.js +++ b/src/Squidex/app-config/karma-test-shim.js @@ -1,7 +1,6 @@ Error.stackTraceLimit = Infinity; -require('core-js/es6'); -require('core-js/es7/reflect'); +require('core-js/proposals/reflect-metadata'); require('zone.js/dist/zone'); require('zone.js/dist/long-stack-trace-zone'); diff --git a/src/Squidex/app-config/karma.conf.js b/src/Squidex/app-config/karma.conf.js index 8b64456f4..f4776e18a 100644 --- a/src/Squidex/app-config/karma.conf.js +++ b/src/Squidex/app-config/karma.conf.js @@ -1,4 +1,4 @@ -var webpackConfig = require('./webpack.test'); +const webpackConfig = require('./webpack.config'); module.exports = function (config) { var _config = { @@ -10,7 +10,7 @@ module.exports = function (config) { frameworks: ['jasmine'], /** - * Load additional test shim to setup angular2 for testing. + * Load additional test shim to setup angular for testing. */ files: [ { pattern: './app-config/karma-test-shim.js', watched: false } @@ -23,7 +23,7 @@ module.exports = function (config) { /** * Load the files with webpack and use test configuration for it. */ - webpack: webpackConfig, + webpack: webpackConfig({ target: 'tests', jit: true }), webpackMiddleware: { stats: 'errors-only' diff --git a/src/Squidex/app-config/karma.coverage.conf.js b/src/Squidex/app-config/karma.coverage.conf.js index 441b998b9..8a9b849bf 100644 --- a/src/Squidex/app-config/karma.coverage.conf.js +++ b/src/Squidex/app-config/karma.coverage.conf.js @@ -1,4 +1,4 @@ -var webpackConfig = require('./webpack.test.coverage'); +const webpackConfig = require('./webpack.config'); module.exports = function (config) { var _config = { @@ -10,7 +10,7 @@ module.exports = function (config) { frameworks: ['jasmine'], /** - * Load additional test shim to setup angular2 for testing. + * Load additional test shim to setup angular for testing. */ files: [ { pattern: './app-config/karma-test-shim.js', watched: false } @@ -23,7 +23,7 @@ module.exports = function (config) { /** * Load the files with webpack and use test configuration for it. */ - webpack: webpackConfig, + webpack: webpackConfig({ target: 'tests', coverage: true, jit: true }), webpackMiddleware: { stats: 'errors-only' diff --git a/src/Squidex/app-config/webpack.config.js b/src/Squidex/app-config/webpack.config.js index 5ff10d725..edaeaa5a8 100644 --- a/src/Squidex/app-config/webpack.config.js +++ b/src/Squidex/app-config/webpack.config.js @@ -1,6 +1,13 @@ const webpack = require('webpack'), - path = require('path'), - helpers = require('./helpers'); + path = require('path'); + +const appRoot = path.resolve(__dirname, '..'); + +function root() { + var newArgs = Array.prototype.slice.call(arguments, 0); + + return path.join.apply(path, [appRoot].concat(newArgs)); +}; const plugins = { // https://github.com/webpack-contrib/mini-css-extract-plugin @@ -8,147 +15,356 @@ const plugins = { // https://github.com/dividab/tsconfig-paths-webpack-plugin TsconfigPathsPlugin: require('tsconfig-paths-webpack-plugin'), // https://github.com/aackerman/circular-dependency-plugin - CircularDependencyPlugin: require('circular-dependency-plugin') + CircularDependencyPlugin: require('circular-dependency-plugin'), + // https://github.com/jantimon/html-webpack-plugin + HtmlWebpackPlugin: require('html-webpack-plugin'), + // https://github.com/mishoo/UglifyJS2/tree/harmony + UglifyJsPlugin: require('uglifyjs-webpack-plugin'), + // https://www.npmjs.com/package/@ngtools/webpack + NgToolsWebpack: require('@ngtools/webpack'), + // https://github.com/NMFR/optimize-css-assets-webpack-plugin + OptimizeCSSAssetsPlugin: require("optimize-css-assets-webpack-plugin"), + // https://github.com/jrparish/tslint-webpack-plugin + TsLintPlugin: require('tslint-webpack-plugin') }; -const isDevServer = path.basename(require.main.filename) === 'webpack-dev-server.js'; +module.exports = function(env) { + const isDevServer = path.basename(require.main.filename) === 'webpack-dev-server.js'; + const isProduction = env && env.production; + const isTesting = env && env.target === 'tests'; + const isCoverage = env && env.coverage; + const isJit = env && env.jit; + + const config = { + mode: isProduction ? 'production' : 'development', -module.exports = { - /** - * Options affecting the resolving of modules. - * - * See: https://webpack.js.org/configuration/resolve/ - */ - resolve: { /** - * An array of extensions that should be used to resolve modules. + * Source map for Karma from the help of karma-sourcemap-loader & karma-webpack. * - * See: https://webpack.js.org/configuration/resolve/#resolve-extensions + * See: https://webpack.js.org/configuration/devtool/ */ - extensions: ['.js', '.mjs', '.ts', '.css', '.scss'], - modules: [ - helpers.root('app'), - helpers.root('app', 'theme'), - helpers.root('node_modules') - ], + devtool: isProduction ? undefined : (isTesting ? 'inline-source-map' : 'source-map'), + + /** + * Options affecting the resolving of modules. + * + * See: https://webpack.js.org/configuration/resolve/ + */ + resolve: { + /** + * An array of extensions that should be used to resolve modules. + * + * See: https://webpack.js.org/configuration/resolve/#resolve-extensions + */ + extensions: ['.js', '.mjs', '.ts', '.css', '.scss'], + modules: [ + root('app'), + root('app', 'theme'), + root('node_modules') + ], + + plugins: [ + new plugins.TsconfigPathsPlugin() + ] + }, + + /** + * Options affecting the normal modules. + * + * See: https://webpack.js.org/configuration/module/ + */ + module: { + /** + * An array of Rules which are matched to requests when modules are created. + * + * See: https://webpack.js.org/configuration/module/#module-rules + */ + rules: [{ + test: /\.mjs$/, + type: "javascript/auto", + include: [/node_modules/] + }, { + test: /[\/\\]@angular[\/\\]core[\/\\].+\.js$/, + parser: { system: true }, + include: [/node_modules/] + }, { + test: /\.js\.flow$/, + use: [{ + loader: 'ignore-loader' + }], + include: [/node_modules/] + }, { + test: /\.html$/, + use: [{ + loader: 'raw-loader' + }] + }, { + test: /\.(woff|woff2|ttf|eot)(\?.*$|$)/, + use: [{ + loader: 'file-loader?name=[name].[hash].[ext]', + options: { + outputPath: 'assets', + /* + * Use custom public path as ./ is not supported by fonts. + */ + publicPath: isDevServer ? undefined : 'assets' + } + }] + }, { + test: /\.(png|jpe?g|gif|svg|ico)(\?.*$|$)/, + use: [{ + loader: 'file-loader?name=[name].[hash].[ext]', + options: { + outputPath: 'assets' + } + }] + }, { + test: /\.css$/, + use: [ + plugins.MiniCssExtractPlugin.loader, + { + loader: 'css-loader' + }] + }, { + test: /\.scss$/, + use: [{ + loader: 'raw-loader' + }, { + loader: 'sass-loader', options: { includePaths: [root('app', 'theme')] } + }], + exclude: root('app', 'theme') + }] + }, plugins: [ - new plugins.TsconfigPathsPlugin() - ] - }, - - /** - * Options affecting the normal modules. - * - * See: https://webpack.js.org/configuration/module/ - */ - module: { + new webpack.ContextReplacementPlugin(/\@angular(\\|\/)core(\\|\/)fesm5/, root('./app'), {}), + new webpack.ContextReplacementPlugin(/moment[\/\\]locale$/, /en/), + + /** + * Puts each bundle into a file and appends the hash of the file to the path. + * + * See: https://github.com/webpack-contrib/mini-css-extract-plugin + */ + new plugins.MiniCssExtractPlugin('[name].css'), + + new webpack.LoaderOptionsPlugin({ + options: { + htmlLoader: { + /** + * Define the root for images, so that we can use absolute urls. + * + * See: https://github.com/webpack/html-loader#Advanced_Options + */ + root: root('app', 'images') + }, + context: '/' + } + }), + + /** + * Detect circular dependencies in app. + * + * See: https://github.com/aackerman/circular-dependency-plugin + */ + new plugins.CircularDependencyPlugin({ + exclude: /([\\\/]node_modules[\\\/])|(ngfactory\.js$)/, + // Add errors to webpack instead of warnings + failOnError: true + }), + ], + + devServer: { + headers: { + 'Access-Control-Allow-Origin': '*' + }, + historyApiFallback: true + } + }; + + if (!isTesting) { /** - * An array of Rules which are matched to requests when modules are created. + * The entry point for the bundle. Our Angular app. * - * See: https://webpack.js.org/configuration/module/#module-rules + * See: https://webpack.js.org/configuration/entry-context/ */ - rules: [{ - test: /\.mjs$/, - type: "javascript/auto", - include: [/node_modules/] - }, { - test: /[\/\\]@angular[\/\\]core[\/\\].+\.js$/, - parser: { system: true }, - include: [/node_modules/] - }, { + config.entry = { + 'shims': './app/shims.ts', + 'app': './app/app.ts' + }; + + if (isProduction) { + config.output = { + /** + * The output directory as absolute path (required). + * + * See: https://webpack.js.org/configuration/output/#output-path + */ + path: root('wwwroot/build/'), + + publicPath: './build/', + + /** + * Specifies the name of each output file on disk. + * + * See: https://webpack.js.org/configuration/output/#output-filename + */ + filename: '[name].js', + + /** + * The filename of non-entry chunks as relative path inside the output.path directory. + * + * See: https://webpack.js.org/configuration/output/#output-chunkfilename + */ + chunkFilename: '[id].[hash].chunk.js' + }; + } else { + config.output = { + filename: '[name].js', + + /** + * Set the public path, because we are running the website from another port (5000). + */ + publicPath: 'http://localhost:3000/' + }; + } + + config.plugins.push( + new plugins.HtmlWebpackPlugin({ + hash: true, + chunks: ['shims', 'app'], + chunksSortMode: 'manual', + template: 'wwwroot/index.html' + }) + ); + + config.plugins.push( + new plugins.HtmlWebpackPlugin({ + template: 'wwwroot/_theme.html', hash: true, chunksSortMode: 'none', filename: 'theme.html' + }) + ); + + config.plugins.push( + new plugins.TsLintPlugin({ + files: ['./app/**/*.ts'], + /** + * Path to a configuration file. + */ + config: root('tslint.json'), + /** + * Wait for linting and fail the build when linting error occur. + */ + waitForLinting: isProduction + }) + ); + } + + if (isProduction) { + config.optimization = { + minimizer: [ + new plugins.UglifyJsPlugin({ + uglifyOptions: { + compress: false, + ecma: 6, + mangle: true, + output: { + comments: false + } + }, + extractComments: true + }), + + new plugins.OptimizeCSSAssetsPlugin({}) + ] + }; + + config.performance = { + hints: false + }; + } + + if (!isCoverage) { + config.module.rules.push({ test: /\.ts$/, use: [{ loader: 'awesome-typescript-loader' - }, { - loader: 'angular-router-loader' - }, { - loader: 'angular2-template-loader' }], exclude: [/node_modules/] - }, { + }) + } else { + config.module.rules.push({ test: /\.ts$/, use: [{ - loader: 'awesome-typescript-loader' + loader: 'ts-loader' }], - include: [/node_modules/] - }, { - test: /\.js\.flow$/, + include: [/\.(e2e|spec)\.ts$/], + }); + + // Use instrument loader for all normal builds. + config.module.rules.push({ + test: /\.ts$/, use: [{ - loader: 'ignore-loader' + loader: 'istanbul-instrumenter-loader' + }, { + loader: 'ts-loader' }], - include: [/node_modules/] - }, { - test: /\.html$/, - use: [{ - loader: 'raw-loader' - }] - }, { - test: /\.(woff|woff2|ttf|eot)(\?.*$|$)/, - use: [{ - loader: 'file-loader?name=[name].[hash].[ext]', - options: { - outputPath: 'assets', - /* - * Use custom public path as ./ is not supported by fonts. - */ - publicPath: isDevServer ? undefined : 'assets' - } - }] - }, { - test: /\.(png|jpe?g|gif|svg|ico)(\?.*$|$)/, - use: [{ - loader: 'file-loader?name=[name].[hash].[ext]', - options: { - outputPath: 'assets' - } - }] - }, { - test: /\.css$/, + exclude: [/\.(e2e|spec)\.ts$/] + }); + } + + if (isProduction) { + config.module.rules.push({ + test: /\.scss$/, + /* + * Extract the content from a bundle to a file. + * + * See: https://github.com/webpack-contrib/extract-text-webpack-plugin + */ use: [ plugins.MiniCssExtractPlugin.loader, { loader: 'css-loader' - }] - }, { + }, { + loader: 'sass-loader' + }], + /* + * Do not include component styles. + */ + include: root('app', 'theme'), + }); + } else { + config.module.rules.push({ test: /\.scss$/, use: [{ - loader: 'raw-loader' + loader: 'style-loader' }, { - loader: 'sass-loader', options: { includePaths: [helpers.root('app', 'theme')] } + loader: 'css-loader' + }, { + loader: 'sass-loader?sourceMap' }], - exclude: helpers.root('app', 'theme') - }] - }, + /* + * Do not include component styles. + */ + include: root('app', 'theme') + }); + } - plugins: [ - /** - * Puts each bundle into a file and appends the hash of the file to the path. - * - * See: https://github.com/webpack-contrib/mini-css-extract-plugin - */ - new plugins.MiniCssExtractPlugin('[name].css'), - - new webpack.LoaderOptionsPlugin({ - options: { - htmlLoader: { - /** - * Define the root for images, so that we can use absolute urls. - * - * See: https://github.com/webpack/html-loader#Advanced_Options - */ - root: helpers.root('app', 'images') - }, - context: '/' - } - }), - - new plugins.CircularDependencyPlugin({ - exclude: /([\\\/]node_modules[\\\/])|(ngfactory\.js$)/, - // Add errors to webpack instead of warnings - failOnError: true - }), - - new webpack.ContextReplacementPlugin(/moment[\/\\]locale$/, /en/) - ] + if (!isJit) { + config.module.rules.push({ + test: /(?:\.ngfactory\.js|\.ngstyle\.js|\.ts)$/, + use: [{ + loader: '@ngtools/webpack' + }] + }); + + config.plugins.push( + new plugins.NgToolsWebpack.AngularCompilerPlugin({ + entryModule: 'app/app.module#AppModule', + sourceMap: !isProduction, + skipSourceGeneration: false, + tsConfigPath: './tsconfig.json' + }) + ); + } + + return config; }; \ No newline at end of file diff --git a/src/Squidex/app-config/webpack.run.base.js b/src/Squidex/app-config/webpack.run.base.js deleted file mode 100644 index 06012fa60..000000000 --- a/src/Squidex/app-config/webpack.run.base.js +++ /dev/null @@ -1,35 +0,0 @@ -const webpack = require('webpack'), - webpackMerge = require('webpack-merge'), - path = require('path'), - helpers = require('./helpers'), - commonConfig = require('./webpack.config.js'); - -const plugins = { - // https://github.com/jantimon/html-webpack-plugin - HtmlWebpackPlugin: require('html-webpack-plugin') -}; - -module.exports = webpackMerge(commonConfig, { - /** - * The entry point for the bundle. Our Angular app. - * - * See: https://webpack.js.org/configuration/entry-context/ - */ - entry: { - 'shims': './app/shims.ts', - 'app': './app/app.ts' - }, - - plugins: [ - new plugins.HtmlWebpackPlugin({ - hash: true, - chunks: ['shims', 'app'], - chunksSortMode: 'manual', - template: 'wwwroot/index.html' - }), - - new plugins.HtmlWebpackPlugin({ - template: 'wwwroot/_theme.html', hash: true, chunksSortMode: 'none', filename: 'theme.html' - }) - ] -}); \ No newline at end of file diff --git a/src/Squidex/app-config/webpack.run.dev.js b/src/Squidex/app-config/webpack.run.dev.js deleted file mode 100644 index 5a34d49d9..000000000 --- a/src/Squidex/app-config/webpack.run.dev.js +++ /dev/null @@ -1,68 +0,0 @@ -const webpack = require('webpack'), - webpackMerge = require('webpack-merge'), - path = require('path'), - helpers = require('./helpers'), - runConfig = require('./webpack.run.base.js'); - -const plugins = { - // https://github.com/jrparish/tslint-webpack-plugin - TsLintPlugin: require('tslint-webpack-plugin') -}; - -module.exports = webpackMerge(runConfig, { - mode: 'development', - - devtool: 'source-map', - - output: { - filename: '[name].js', - - /** - * Set the public path, because we are running the website from another port (5000). - */ - publicPath: 'http://localhost:3000/' - }, - - /* - * Options affecting the normal modules. - * - * See: https://webpack.js.org/configuration/module/ - */ - module: { - /** - * An array of Rules which are matched to requests when modules are created. - * - * See: https://webpack.js.org/configuration/module/#module-rules - */ - rules: [{ - test: /\.scss$/, - use: [{ - loader: 'style-loader' - }, { - loader: 'css-loader' - }, { - loader: 'sass-loader?sourceMap', options: { includePaths: [helpers.root('app', 'theme')] } - }], - include: helpers.root('app', 'theme') - }] - }, - - plugins: [ - new webpack.ContextReplacementPlugin(/\@angular(\\|\/)core(\\|\/)fesm5/, helpers.root('./src'), {}), - - new plugins.TsLintPlugin({ - files: ['./app/**/*.ts'], - /** - * Path to a configuration file. - */ - config: helpers.root('tslint.json') - }) - ], - - devServer: { - headers: { - 'Access-Control-Allow-Origin': '*' - }, - historyApiFallback: true - } -}); \ No newline at end of file diff --git a/src/Squidex/app-config/webpack.run.prod.js b/src/Squidex/app-config/webpack.run.prod.js deleted file mode 100644 index 07fbca634..000000000 --- a/src/Squidex/app-config/webpack.run.prod.js +++ /dev/null @@ -1,137 +0,0 @@ -const webpack = require('webpack'), - webpackMerge = require('webpack-merge'), - path = require('path'), - helpers = require('./helpers'), - runConfig = require('./webpack.run.base.js'); - -const plugins = { - // https://github.com/mishoo/UglifyJS2/tree/harmony - UglifyJsPlugin: require('uglifyjs-webpack-plugin'), - // https://www.npmjs.com/package/@ngtools/webpack - NgToolsWebpack: require('@ngtools/webpack'), - // https://github.com/webpack-contrib/mini-css-extract-plugin - MiniCssExtractPlugin: require('mini-css-extract-plugin'), - // https://github.com/NMFR/optimize-css-assets-webpack-plugin - OptimizeCSSAssetsPlugin: require("optimize-css-assets-webpack-plugin"), - // https://github.com/jrparish/tslint-webpack-plugin - TsLintPlugin: require('tslint-webpack-plugin') -}; - -helpers.removeLoaders(runConfig, ['scss', 'ts']); - -module.exports = webpackMerge(runConfig, { - mode: 'production', - - output: { - /** - * The output directory as absolute path (required). - * - * See: https://webpack.js.org/configuration/output/#output-path - */ - path: helpers.root('wwwroot/build/'), - - publicPath: './build/', - - /** - * Specifies the name of each output file on disk. - * - * See: https://webpack.js.org/configuration/output/#output-filename - */ - filename: '[name].js', - - /** - * The filename of non-entry chunks as relative path inside the output.path directory. - * - * See: https://webpack.js.org/configuration/output/#output-chunkfilename - */ - chunkFilename: '[id].[hash].chunk.js' - }, - - /* - * Options affecting the normal modules. - * - * See: https://webpack.js.org/configuration/module/ - */ - module: { - /** - * An array of Rules which are matched to requests when modules are created. - * - * See: https://webpack.js.org/configuration/module/#module-rules - */ - rules: [{ - test: /\.scss$/, - /* - * Extract the content from a bundle to a file. - * - * See: https://github.com/webpack-contrib/extract-text-webpack-plugin - */ - use: [ - plugins.MiniCssExtractPlugin.loader, - { - loader: 'css-loader' - }, { - loader: 'sass-loader' - }], - /* - * Do not include component styles. - */ - include: helpers.root('app', 'theme'), - }, { - test: /\.scss$/, - use: [{ - loader: 'raw-loader' - }, { - loader: 'sass-loader', options: { includePaths: [helpers.root('app', 'theme')] } - }], - exclude: helpers.root('app', 'theme'), - }, { - test: /(?:\.ngfactory\.js|\.ngstyle\.js|\.ts)$/, - use: [{ - loader: '@ngtools/webpack' - }] - }] - }, - - plugins: [ - new plugins.NgToolsWebpack.AngularCompilerPlugin({ - entryModule: 'app/app.module#AppModule', - sourceMap: false, - skipSourceGeneration: false, - tsConfigPath: './tsconfig.json' - }), - - new plugins.TsLintPlugin({ - files: ['./app/**/*.ts'], - /** - * Path to a configuration file. - */ - config: helpers.root('tslint.json'), - /** - * Wait for linting and fail the build when linting error occur. - */ - waitForLinting: true - }) - ], - - optimization: { - minimizer: [ - new plugins.UglifyJsPlugin({ - uglifyOptions: { - compress: false, - ecma: 6, - mangle: true, - output: { - comments: false - } - }, - extractComments: true - }), - - new plugins.OptimizeCSSAssetsPlugin({}) - ] - }, - - performance: { - hints: false - } -}); \ No newline at end of file diff --git a/src/Squidex/app-config/webpack.test.coverage.js b/src/Squidex/app-config/webpack.test.coverage.js deleted file mode 100644 index 1989b80d4..000000000 --- a/src/Squidex/app-config/webpack.test.coverage.js +++ /dev/null @@ -1,37 +0,0 @@ -const webpack = require('webpack'), - webpackMerge = require('webpack-merge'), - path = require('path'), - helpers = require('./helpers'), - testConfig = require('./webpack.test.js'); - -helpers.removeLoaders(testConfig, ['ts']); - -module.exports = webpackMerge(testConfig, { - module: { - /** - * An array of Rules which are matched to requests when modules are created. - * - * See: https://webpack.js.org/configuration/module/#module-rules - */ - rules: [{ - test: /\.ts$/, - use: [{ - loader: 'ts-loader' - }], - include: [/\.(e2e|spec)\.ts$/], - - }, { - test: /\.ts$/, - use: [{ - loader: 'istanbul-instrumenter-loader' - }, { - loader: 'ts-loader' - }, { - loader: 'angular-router-loader' - }, { - loader: 'angular2-template-loader' - }], - exclude: [/\.(e2e|spec)\.ts$/] - }] - } -}); \ No newline at end of file diff --git a/src/Squidex/app-config/webpack.test.js b/src/Squidex/app-config/webpack.test.js deleted file mode 100644 index eacdb4361..000000000 --- a/src/Squidex/app-config/webpack.test.js +++ /dev/null @@ -1,16 +0,0 @@ -const webpack = require('webpack'), - webpackMerge = require('webpack-merge'), - path = require('path'), - helpers = require('./helpers'), - commonConfig = require('./webpack.config.js'); - -module.exports = webpackMerge(commonConfig, { - mode: 'development', - - /** - * Source map for Karma from the help of karma-sourcemap-loader & karma-webpack. - * - * See: https://webpack.js.org/configuration/devtool/ - */ - devtool: 'inline-source-map' -}); \ No newline at end of file diff --git a/src/Squidex/app/shared/state/assets.state.spec.ts b/src/Squidex/app/shared/state/assets.state.spec.ts index 17f604219..cf9e52d59 100644 --- a/src/Squidex/app/shared/state/assets.state.spec.ts +++ b/src/Squidex/app/shared/state/assets.state.spec.ts @@ -54,13 +54,15 @@ describe('AssetsState', () => { }); describe('Loading', () => { + beforeEach(() => { + assetsService.setup(x => x.getTags(app)) + .returns(() => of({ tag1: 1, shared: 2, tag2: 1 })).verifiable(Times.atLeastOnce()); + }); + it('should load assets', () => { assetsService.setup(x => x.getAssets(app, 30, 0, undefined, [])) .returns(() => of(new AssetsDto(200, oldAssets))).verifiable(); - assetsService.setup(x => x.getTags(app)) - .returns(() => of({ tag1: 1, shared: 2, tag2: 1 })).verifiable(); - assetsState.load().subscribe(); expect(assetsState.snapshot.assets.values).toEqual(oldAssets); @@ -72,10 +74,7 @@ describe('AssetsState', () => { it('should show notification on load when reload is true', () => { assetsService.setup(x => x.getAssets(app, 30, 0, undefined, [])) - .returns(() => of(new AssetsDto(200, oldAssets))); - - assetsService.setup(x => x.getTags(app)) - .returns(() => of({ tag1: 1, shared: 2, tag2: 1 })).verifiable(); + .returns(() => of(new AssetsDto(200, oldAssets))).verifiable(); assetsState.load(true).subscribe(); @@ -86,7 +85,7 @@ describe('AssetsState', () => { it('should load with tags when tag toggled', () => { assetsService.setup(x => x.getAssets(app, 30, 0, undefined, ['tag1'])) - .returns(() => of(new AssetsDto(0, []))); + .returns(() => of(new AssetsDto(0, []))).verifiable(); assetsState.toggleTag('tag1').subscribe(); @@ -95,10 +94,10 @@ describe('AssetsState', () => { it('should load without tags when tag toggled', () => { assetsService.setup(x => x.getAssets(app, 30, 0, undefined, ['tag1'])) - .returns(() => of(new AssetsDto(0, []))); + .returns(() => of(new AssetsDto(0, []))).verifiable(); assetsService.setup(x => x.getAssets(app, 30, 0, undefined, [])) - .returns(() => of(new AssetsDto(0, []))); + .returns(() => of(new AssetsDto(0, []))).verifiable(); assetsState.toggleTag('tag1').subscribe(); assetsState.toggleTag('tag1').subscribe(); @@ -108,7 +107,7 @@ describe('AssetsState', () => { it('should load with tags when tags selected', () => { assetsService.setup(x => x.getAssets(app, 30, 0, undefined, ['tag1', 'tag2'])) - .returns(() => of(new AssetsDto(0, []))); + .returns(() => of(new AssetsDto(0, []))).verifiable(); assetsState.selectTags(['tag1', 'tag2']).subscribe(); @@ -117,7 +116,7 @@ describe('AssetsState', () => { it('should load without tags when tags reset', () => { assetsService.setup(x => x.getAssets(app, 30, 0, undefined, [])) - .returns(() => of(new AssetsDto(0, []))); + .returns(() => of(new AssetsDto(0, []))).verifiable(); assetsState.resetTags().subscribe(); @@ -125,9 +124,13 @@ describe('AssetsState', () => { }); it('should load next page and prev page when paging', () => { + assetsService.setup(x => x.getAssets(app, 30, 0, undefined, [])) + .returns(() => of(new AssetsDto(200, []))).verifiable(Times.exactly(2)); + assetsService.setup(x => x.getAssets(app, 30, 30, undefined, [])) - .returns(() => of(new AssetsDto(200, []))); + .returns(() => of(new AssetsDto(200, []))).verifiable(); + assetsState.load().subscribe(); assetsState.goNext().subscribe(); assetsState.goPrev().subscribe(); @@ -136,7 +139,7 @@ describe('AssetsState', () => { it('should load with query when searching', () => { assetsService.setup(x => x.getAssets(app, 30, 0, 'my-query', [])) - .returns(() => of(new AssetsDto(0, []))); + .returns(() => of(new AssetsDto(0, []))).verifiable(); assetsState.search('my-query').subscribe(); diff --git a/src/Squidex/app/shims.ts b/src/Squidex/app/shims.ts index 4c18a84a4..f2b179e2a 100644 --- a/src/Squidex/app/shims.ts +++ b/src/Squidex/app/shims.ts @@ -92,6 +92,4 @@ import 'core-js/modules/es.set'; import 'core-js/modules/es.weak-map'; import 'core-js/modules/web.dom-collections.iterator'; -import 'core-js/proposals/reflect-metadata'; - import 'zone.js/dist/zone'; \ No newline at end of file diff --git a/src/Squidex/package-lock.json b/src/Squidex/package-lock.json index 183d8b57a..721adebda 100644 --- a/src/Squidex/package-lock.json +++ b/src/Squidex/package-lock.json @@ -1669,15 +1669,6 @@ "integrity": "sha1-SlKCrBZHKek2Gbz9OtFR+BfOkfU=", "dev": true }, - "angular-router-loader": { - "version": "0.8.5", - "resolved": "https://registry.npmjs.org/angular-router-loader/-/angular-router-loader-0.8.5.tgz", - "integrity": "sha512-8wggCTKGgzB1o8co3Wvj+p9pKN7T7q3C477lEz3NLjvPVzUti8rv9i45Di+4aO/k+HvzGh3s8QdNlXU2Bl4avQ==", - "dev": true, - "requires": { - "loader-utils": "^1.0.2" - } - }, "angular2-chartjs": { "version": "0.5.1", "resolved": "https://registry.npmjs.org/angular2-chartjs/-/angular2-chartjs-0.5.1.tgz", @@ -1686,29 +1677,6 @@ "chart.js": "^2.3.0" } }, - "angular2-template-loader": { - "version": "0.6.2", - "resolved": "https://registry.npmjs.org/angular2-template-loader/-/angular2-template-loader-0.6.2.tgz", - "integrity": "sha1-wNROkP/w+sleiyPwQ6zaf9HFHXw=", - "dev": true, - "requires": { - "loader-utils": "^0.2.15" - }, - "dependencies": { - "loader-utils": { - "version": "0.2.17", - "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-0.2.17.tgz", - "integrity": "sha1-+G5jdNQyBabmxg6RlvF8Apm/s0g=", - "dev": true, - "requires": { - "big.js": "^3.1.3", - "emojis-list": "^2.0.0", - "json5": "^0.5.0", - "object-assign": "^4.0.1" - } - } - } - }, "ansi-colors": { "version": "3.2.4", "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-3.2.4.tgz", @@ -2879,14 +2847,13 @@ } }, "browserslist": { - "version": "4.3.5", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.3.5.tgz", - "integrity": "sha512-z9ZhGc3d9e/sJ9dIx5NFXkKoaiQTnrvrMsN3R1fGb1tkWWNSz12UewJn9TNxGo1l7J23h0MRaPmk7jfeTZYs1w==", - "dev": true, + "version": "4.6.1", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.6.1.tgz", + "integrity": "sha512-1MC18ooMPRG2UuVFJTHFIAkk6mpByJfxCrnUyvSlu/hyQSFHMrlhM02SzNuCV+quTP4CKmqtOMAIjrifrpBJXQ==", "requires": { - "caniuse-lite": "^1.0.30000912", - "electron-to-chromium": "^1.3.86", - "node-releases": "^1.0.5" + "caniuse-lite": "^1.0.30000971", + "electron-to-chromium": "^1.3.137", + "node-releases": "^1.1.21" } }, "buffer": { @@ -3133,10 +3100,9 @@ } }, "caniuse-lite": { - "version": "1.0.30000918", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30000918.tgz", - "integrity": "sha512-CAZ9QXGViBvhHnmIHhsTPSWFBujDaelKnUj7wwImbyQRxmXynYqKGi3UaZTSz9MoVh+1EVxOS/DFIkrJYgR3aw==", - "dev": true + "version": "1.0.30000971", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30000971.tgz", + "integrity": "sha512-TQFYFhRS0O5rdsmSbF1Wn+16latXYsQJat66f7S7lizXW1PVpWJeZw9wqqVLIjuxDRz7s7xRUj13QCfd8hKn6g==" }, "canonical-path": { "version": "1.0.0", @@ -4600,10 +4566,9 @@ "dev": true }, "electron-to-chromium": { - "version": "1.3.90", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.90.tgz", - "integrity": "sha512-IjJZKRhFbWSOX1w0sdIXgp4CMRguu6UYcTckyFF/Gjtemsu/25eZ+RXwFlV+UWcIueHyQA1UnRJxocTpH5NdGA==", - "dev": true + "version": "1.3.142", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.142.tgz", + "integrity": "sha512-GLOB/wAA2g9l5Hwg1XrPqd6br2WNOPIY8xl/q+g5zZdv3b5fB69oFOooxKxc0DfDfDS1RqaF6hKjwt6v4fuFUw==" }, "elliptic": { "version": "6.4.1", @@ -10352,10 +10317,9 @@ } }, "node-releases": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-1.1.1.tgz", - "integrity": "sha512-2UXrBr6gvaebo5TNF84C66qyJJ6r0kxBObgZIDX3D3/mt1ADKiHux3NJPWisq0wxvJJdkjECH+9IIKYViKj71Q==", - "dev": true, + "version": "1.1.22", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-1.1.22.tgz", + "integrity": "sha512-O6XpteBuntW1j86mw6LlovBIwTe+sO2+7vi9avQffNeIW4upgnaCVm6xrBWH+KATz7mNNRNNeEpuWB7dT6Cr3w==", "requires": { "semver": "^5.3.0" } @@ -13206,8 +13170,7 @@ "semver": { "version": "5.5.0", "resolved": "https://registry.npmjs.org/semver/-/semver-5.5.0.tgz", - "integrity": "sha512-4SJ3dm0WAwWy/NVeioZh5AntkdJoWKxHxcmyP622fOkgHa4z3R0TdBJICINyaSDE6uNwVc8gZr+ZinwZAH4xIA==", - "dev": true + "integrity": "sha512-4SJ3dm0WAwWy/NVeioZh5AntkdJoWKxHxcmyP622fOkgHa4z3R0TdBJICINyaSDE6uNwVc8gZr+ZinwZAH4xIA==" }, "semver-dsl": { "version": "1.0.1", @@ -17684,15 +17647,6 @@ "uuid": "^3.1.0" } }, - "webpack-merge": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/webpack-merge/-/webpack-merge-4.2.1.tgz", - "integrity": "sha512-4p8WQyS98bUJcCvFMbdGZyZmsKuWjWVnVHnAS3FFg0HDaRVrPbkivx2RYCre8UiemD67RsiFFLfn4JhLAin8Vw==", - "dev": true, - "requires": { - "lodash": "^4.17.5" - } - }, "webpack-sources": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-1.2.0.tgz", diff --git a/src/Squidex/package.json b/src/Squidex/package.json index cf9b1f8af..7453f5829 100644 --- a/src/Squidex/package.json +++ b/src/Squidex/package.json @@ -6,12 +6,12 @@ "repository": "https://github.com/SebastianStehle/Squidex", "scripts": { "copy": "cpx node_modules/oidc-client/dist/oidc-client.min.js wwwroot/scripts/", - "start": "npm run copy && webpack-dev-server --config app-config/webpack.run.dev.js --inline --port 3000 --hot", + "start": "npm run copy && webpack-dev-server --config app-config/webpack.config.js --inline --port 3000 --hot", "test": "karma start", "test:coverage": "karma start karma.coverage.conf.js", "test:clean": "rimraf _test-output", "tslint": "tslint -c tslint.json -p tsconfig.json app/**/*.ts", - "build": "npm run copy && webpack --config app-config/webpack.run.prod.js", + "build": "npm run copy && webpack --config app-config/webpack.config.js --env.production", "build:clean": "rimraf wwwroot/build" }, "dependencies": { @@ -20,13 +20,15 @@ "@angular/core": "8.0.0", "@angular/forms": "8.0.0", "@angular/http": "7.2.15", - "@angular/platform-browser-dynamic": "8.0.0", "@angular/platform-browser": "8.0.0", + "@angular/platform-browser-dynamic": "8.0.0", "@angular/platform-server": "8.0.0", "@angular/router": "8.0.0", "angular2-chartjs": "0.5.1", "babel-polyfill": "6.26.0", "bootstrap": "4.3.1", + "browserslist": "^4.6.1", + "caniuse-lite": "^1.0.30000971", "core-js": "3.1.3", "graphiql": "0.13.0", "graphql": "14.3.1", @@ -38,8 +40,8 @@ "oidc-client": "1.7.1", "pikaday": "1.8.0", "progressbar.js": "1.0.1", - "react-dom": "16.8.6", "react": "16.8.6", + "react-dom": "16.8.6", "rxjs": "6.5.2", "slugify": "1.3.4", "sortablejs": "1.9.0", @@ -58,8 +60,6 @@ "@types/react-dom": "16.8.4", "@types/react": "16.8.19", "@types/sortablejs": "1.7.2", - "angular-router-loader": "0.8.5", - "angular2-template-loader": "0.6.2", "awesome-typescript-loader": "5.2.1", "babel-core": "6.26.3", "circular-dependency-plugin": "5.0.2", @@ -101,7 +101,6 @@ "underscore": "1.9.1", "webpack-cli": "3.3.2", "webpack-dev-server": "3.5.1", - "webpack-merge": "4.2.1", "webpack": "4.32.2" } } From 97f74b01b99ec7fa68b8ccb12aec77c6f3edc3ac Mon Sep 17 00:00:00 2001 From: Sebastian Stehle Date: Tue, 18 Jun 2019 15:19:35 +0200 Subject: [PATCH 03/47] Added missing method to workflow. --- src/Squidex.Domain.Apps.Entities/Contents/IContentWorkflow.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/Squidex.Domain.Apps.Entities/Contents/IContentWorkflow.cs b/src/Squidex.Domain.Apps.Entities/Contents/IContentWorkflow.cs index 06738ec71..e2b21d0af 100644 --- a/src/Squidex.Domain.Apps.Entities/Contents/IContentWorkflow.cs +++ b/src/Squidex.Domain.Apps.Entities/Contents/IContentWorkflow.cs @@ -17,6 +17,8 @@ namespace Squidex.Domain.Apps.Entities.Contents Task IsValidNextStatus(IContentEntity content, Status2 next); + Task CanUpdateAsync(IContentEntity content); + Task GetNextsAsync(IContentEntity content); Task GetAllAsync(ISchemaEntity schema); From 5002b7041e3cdfc5ecba8329d56680df1e92c2bd Mon Sep 17 00:00:00 2001 From: Sebastian Stehle Date: Tue, 18 Jun 2019 15:53:53 +0200 Subject: [PATCH 04/47] Use content workflow interface in controller. --- .../Contents/ContentQueryService.cs | 13 +++---- .../Contents/IContentQueryService.cs | 5 +-- .../Contents/ContentsController.cs | 31 +++++++++------- .../Areas/Api/Controllers/Contents/Helper.cs | 7 ++++ .../Controllers/Contents/Models/ContentDto.cs | 26 ++++++++++---- .../Contents/Models/ContentsDto.cs | 36 ++++++++++++++----- .../Contents/ContentQueryServiceTests.cs | 8 ++--- 7 files changed, 84 insertions(+), 42 deletions(-) diff --git a/src/Squidex.Domain.Apps.Entities/Contents/ContentQueryService.cs b/src/Squidex.Domain.Apps.Entities/Contents/ContentQueryService.cs index 5d93788fe..b67536690 100644 --- a/src/Squidex.Domain.Apps.Entities/Contents/ContentQueryService.cs +++ b/src/Squidex.Domain.Apps.Entities/Contents/ContentQueryService.cs @@ -73,16 +73,11 @@ namespace Squidex.Domain.Apps.Entities.Contents this.scriptEngine = scriptEngine; } - public Task ThrowIfSchemaNotExistsAsync(QueryContext context, string schemaIdOrName) - { - return GetSchemaAsync(context, schemaIdOrName); - } - public async Task FindContentAsync(QueryContext context, string schemaIdOrName, Guid id, long version = -1) { Guard.NotNull(context, nameof(context)); - var schema = await GetSchemaAsync(context, schemaIdOrName); + var schema = await GetSchemaOrThrowAsync(context, schemaIdOrName); CheckPermission(context.User, schema); @@ -110,7 +105,7 @@ namespace Squidex.Domain.Apps.Entities.Contents { Guard.NotNull(context, nameof(context)); - var schema = await GetSchemaAsync(context, schemaIdOrName); + var schema = await GetSchemaOrThrowAsync(context, schemaIdOrName); CheckPermission(context.User, schema); @@ -136,7 +131,7 @@ namespace Squidex.Domain.Apps.Entities.Contents } } - public async Task> QueryAsync(QueryContext context, IReadOnlyList ids) + public async Task> QueryAsync(QueryContext context, IReadOnlyList ids) { Guard.NotNull(context, nameof(context)); @@ -295,7 +290,7 @@ namespace Squidex.Domain.Apps.Entities.Contents } } - public async Task GetSchemaAsync(QueryContext context, string schemaIdOrName) + public async Task GetSchemaOrThrowAsync(QueryContext context, string schemaIdOrName) { ISchemaEntity schema = null; diff --git a/src/Squidex.Domain.Apps.Entities/Contents/IContentQueryService.cs b/src/Squidex.Domain.Apps.Entities/Contents/IContentQueryService.cs index 75d89c115..769422de1 100644 --- a/src/Squidex.Domain.Apps.Entities/Contents/IContentQueryService.cs +++ b/src/Squidex.Domain.Apps.Entities/Contents/IContentQueryService.cs @@ -8,6 +8,7 @@ using System; using System.Collections.Generic; using System.Threading.Tasks; +using Squidex.Domain.Apps.Entities.Schemas; using Squidex.Infrastructure; namespace Squidex.Domain.Apps.Entities.Contents @@ -16,12 +17,12 @@ namespace Squidex.Domain.Apps.Entities.Contents { int DefaultPageSizeGraphQl { get; } - Task> QueryAsync(QueryContext context, IReadOnlyList ids); + Task> QueryAsync(QueryContext context, IReadOnlyList ids); Task> QueryAsync(QueryContext context, string schemaIdOrName, Q query); Task FindContentAsync(QueryContext context, string schemaIdOrName, Guid id, long version = EtagVersion.Any); - Task ThrowIfSchemaNotExistsAsync(QueryContext context, string schemaIdOrName); + Task GetSchemaOrThrowAsync(QueryContext context, string schemaIdOrName); } } diff --git a/src/Squidex/Areas/Api/Controllers/Contents/ContentsController.cs b/src/Squidex/Areas/Api/Controllers/Contents/ContentsController.cs index 675833005..a8a4d1e87 100644 --- a/src/Squidex/Areas/Api/Controllers/Contents/ContentsController.cs +++ b/src/Squidex/Areas/Api/Controllers/Contents/ContentsController.cs @@ -16,6 +16,7 @@ using Squidex.Domain.Apps.Entities; using Squidex.Domain.Apps.Entities.Contents; using Squidex.Domain.Apps.Entities.Contents.Commands; using Squidex.Domain.Apps.Entities.Contents.GraphQL; +using Squidex.Infrastructure; using Squidex.Infrastructure.Commands; using Squidex.Shared; using Squidex.Web; @@ -26,15 +27,18 @@ namespace Squidex.Areas.Api.Controllers.Contents { private readonly IOptions controllerOptions; private readonly IContentQueryService contentQuery; + private readonly IContentWorkflow contentWorkflow; private readonly IGraphQLService graphQl; public ContentsController(ICommandBus commandBus, IContentQueryService contentQuery, + IContentWorkflow contentWorkflow, IGraphQLService graphQl, IOptions controllerOptions) : base(commandBus) { this.contentQuery = contentQuery; + this.contentWorkflow = contentWorkflow; this.controllerOptions = controllerOptions; this.graphQl = graphQl; @@ -123,8 +127,9 @@ namespace Squidex.Areas.Api.Controllers.Contents { var context = Context(); var contents = await contentQuery.QueryAsync(context, Q.Empty.WithIds(ids).Ids); + var contentsList = ResultList.Create(contents.Count, contents); - var response = ContentsDto.FromContents(contents.Count, contents, context, this, app, null); + var response = await ContentsDto.FromContentsAsync(contentsList, context, this, null, contentWorkflow); if (controllerOptions.Value.EnableSurrogateKeys && response.Items.Length <= controllerOptions.Value.MaxItemsForSurrogateKeys) { @@ -159,7 +164,9 @@ namespace Squidex.Areas.Api.Controllers.Contents var context = Context(); var contents = await contentQuery.QueryAsync(context, name, Q.Empty.WithIds(ids).WithODataQuery(Request.QueryString.ToString())); - var response = ContentsDto.FromContents(contents.Total, contents, context, this, app, name); + var schema = await contentQuery.GetSchemaOrThrowAsync(context, name); + + var response = await ContentsDto.FromContentsAsync(contents, context, this, schema, contentWorkflow); if (ShouldProvideSurrogateKeys(response)) { @@ -194,7 +201,7 @@ namespace Squidex.Areas.Api.Controllers.Contents var context = Context(); var content = await contentQuery.FindContentAsync(context, name, id); - var response = ContentDto.FromContent(content, context, this, app, name); + var response = await ContentDto.FromContentAsync(context, content, contentWorkflow, this); if (controllerOptions.Value.EnableSurrogateKeys) { @@ -230,7 +237,7 @@ namespace Squidex.Areas.Api.Controllers.Contents var context = Context(); var content = await contentQuery.FindContentAsync(context, name, id, version); - var response = ContentDto.FromContent(content, context, this, app, name); + var response = await ContentDto.FromContentAsync(context, content, contentWorkflow, this); if (controllerOptions.Value.EnableSurrogateKeys) { @@ -264,7 +271,7 @@ namespace Squidex.Areas.Api.Controllers.Contents [ApiCosts(1)] public async Task PostContent(string app, string name, [FromBody] NamedContentData request, [FromQuery] bool publish = false) { - await contentQuery.ThrowIfSchemaNotExistsAsync(Context(), name); + await contentQuery.GetSchemaOrThrowAsync(Context(), name); if (publish && !this.HasPermission(Helper.StatusPermission(app, name, Status.Published))) { @@ -301,7 +308,7 @@ namespace Squidex.Areas.Api.Controllers.Contents [ApiCosts(1)] public async Task PutContent(string app, string name, Guid id, [FromBody] NamedContentData request, [FromQuery] bool asDraft = false) { - await contentQuery.ThrowIfSchemaNotExistsAsync(Context(), name); + await contentQuery.GetSchemaOrThrowAsync(Context(), name); var command = new UpdateContent { ContentId = id, Data = request.ToCleaned(), AsDraft = asDraft }; @@ -333,7 +340,7 @@ namespace Squidex.Areas.Api.Controllers.Contents [ApiCosts(1)] public async Task PatchContent(string app, string name, Guid id, [FromBody] NamedContentData request, [FromQuery] bool asDraft = false) { - await contentQuery.ThrowIfSchemaNotExistsAsync(Context(), name); + await contentQuery.GetSchemaOrThrowAsync(Context(), name); var command = new PatchContent { ContentId = id, Data = request.ToCleaned(), AsDraft = asDraft }; @@ -364,9 +371,9 @@ namespace Squidex.Areas.Api.Controllers.Contents [ApiCosts(1)] public async Task PutContentStatus(string app, string name, Guid id, ChangeStatusDto request) { - await contentQuery.ThrowIfSchemaNotExistsAsync(Context(), name); + await contentQuery.GetSchemaOrThrowAsync(Context(), name); - if (!this.HasPermission(Helper.StatusPermission(app, name, Status.Published))) + if (!this.HasPermission(Helper.StatusPermission(app, name, Status2.Published))) { return new ForbidResult(); } @@ -399,7 +406,7 @@ namespace Squidex.Areas.Api.Controllers.Contents [ApiCosts(1)] public async Task DiscardDraft(string app, string name, Guid id) { - await contentQuery.ThrowIfSchemaNotExistsAsync(Context(), name); + await contentQuery.GetSchemaOrThrowAsync(Context(), name); var command = new DiscardChanges { ContentId = id }; @@ -427,7 +434,7 @@ namespace Squidex.Areas.Api.Controllers.Contents [ApiCosts(1)] public async Task DeleteContent(string app, string name, Guid id) { - await contentQuery.ThrowIfSchemaNotExistsAsync(Context(), name); + await contentQuery.GetSchemaOrThrowAsync(Context(), name); var command = new DeleteContent { ContentId = id }; @@ -441,7 +448,7 @@ namespace Squidex.Areas.Api.Controllers.Contents var context = await CommandBus.PublishAsync(command); var result = context.Result(); - var response = ContentDto.FromContent(result, null, this, app, schema); + var response = await ContentDto.FromContentAsync(null, result, contentWorkflow, this); return response; } diff --git a/src/Squidex/Areas/Api/Controllers/Contents/Helper.cs b/src/Squidex/Areas/Api/Controllers/Contents/Helper.cs index e65648c21..be1f7ef46 100644 --- a/src/Squidex/Areas/Api/Controllers/Contents/Helper.cs +++ b/src/Squidex/Areas/Api/Controllers/Contents/Helper.cs @@ -19,5 +19,12 @@ namespace Squidex.Areas.Api.Controllers.Contents return Permissions.ForApp(id, app, schema); } + + public static Permission StatusPermission(string app, string schema, Status2 status) + { + var id = Permissions.AppContentsStatus.Replace("{status}", status.Name); + + return Permissions.ForApp(id, app, schema); + } } } diff --git a/src/Squidex/Areas/Api/Controllers/Contents/Models/ContentDto.cs b/src/Squidex/Areas/Api/Controllers/Contents/Models/ContentDto.cs index 3939cfd67..c699d7017 100644 --- a/src/Squidex/Areas/Api/Controllers/Contents/Models/ContentDto.cs +++ b/src/Squidex/Areas/Api/Controllers/Contents/Models/ContentDto.cs @@ -7,6 +7,7 @@ using System; using System.ComponentModel.DataAnnotations; +using System.Threading.Tasks; using NodaTime; using Squidex.Domain.Apps.Core.Contents; using Squidex.Domain.Apps.Core.ConvertContent; @@ -79,7 +80,11 @@ namespace Squidex.Areas.Api.Controllers.Contents.Models /// public long Version { get; set; } - public static ContentDto FromContent(IContentEntity content, QueryContext context, ApiController controller, string app, string schema) + public static ValueTask FromContentAsync( + QueryContext context, + IContentEntity content, + IContentWorkflow contentWorkflow, + ApiController controller) { var response = SimpleMapper.Map(content, new ContentDto()); @@ -99,10 +104,14 @@ namespace Squidex.Areas.Api.Controllers.Contents.Models response.ScheduleJob = SimpleMapper.Map(content.ScheduleJob, new ScheduleJobDto()); } - return response.CreateLinks(controller, app, schema); + return response.CreateLinksAsync(content, controller, content.AppId.Name, content.SchemaId.Name, contentWorkflow); } - private ContentDto CreateLinks(ApiController controller, string app, string schema) + private async ValueTask CreateLinksAsync(IContentEntity content, + ApiController controller, + string app, + string schema, + IContentWorkflow contentWorkflow) { var values = new { app, name = schema, id = Id }; @@ -122,7 +131,7 @@ namespace Squidex.Areas.Api.Controllers.Contents.Models AddPutLink("draft/discard", controller.Url(x => nameof(x.DiscardDraft), values)); } - if (controller.HasPermission(Helper.StatusPermission(app, schema, Status.Published))) + if (controller.HasPermission(Helper.StatusPermission(app, schema, Status2.Published))) { AddPutLink("draft/publish", controller.Url(x => nameof(x.PutContentStatus), values)); } @@ -130,7 +139,10 @@ namespace Squidex.Areas.Api.Controllers.Contents.Models if (controller.HasPermission(Permissions.AppContentsUpdate, app, schema)) { - AddPutLink("update", controller.Url(x => nameof(x.PutContent), values)); + if (await contentWorkflow.CanUpdateAsync(content)) + { + AddPutLink("update", controller.Url(x => nameof(x.PutContent), values)); + } if (Status == Status.Published) { @@ -145,7 +157,9 @@ namespace Squidex.Areas.Api.Controllers.Contents.Models AddPutLink("delete", controller.Url(x => nameof(x.DeleteContent), values)); } - foreach (var next in StatusFlow.Next(Status)) + var nextStatuses = await contentWorkflow.GetNextsAsync(content); + + foreach (var next in nextStatuses) { if (controller.HasPermission(Helper.StatusPermission(app, schema, next))) { diff --git a/src/Squidex/Areas/Api/Controllers/Contents/Models/ContentsDto.cs b/src/Squidex/Areas/Api/Controllers/Contents/Models/ContentsDto.cs index 9f664880e..928cc12b2 100644 --- a/src/Squidex/Areas/Api/Controllers/Contents/Models/ContentsDto.cs +++ b/src/Squidex/Areas/Api/Controllers/Contents/Models/ContentsDto.cs @@ -5,12 +5,13 @@ // All rights reserved. Licensed under the MIT license. // ========================================================================== -using System.Collections.Generic; using System.ComponentModel.DataAnnotations; using System.Linq; +using System.Threading.Tasks; using Squidex.Domain.Apps.Core.Contents; using Squidex.Domain.Apps.Entities; using Squidex.Domain.Apps.Entities.Contents; +using Squidex.Domain.Apps.Entities.Schemas; using Squidex.Infrastructure; using Squidex.Shared; using Squidex.Web; @@ -34,7 +35,7 @@ namespace Squidex.Areas.Api.Controllers.Contents.Models /// The possible statuses. /// [Required] - public string[] Statuses { get; set; } + public Status2[] Statuses { get; set; } public string ToEtag() { @@ -46,20 +47,37 @@ namespace Squidex.Areas.Api.Controllers.Contents.Models return Items.ToSurrogateKeys(); } - public static ContentsDto FromContents(long total, IEnumerable contents, QueryContext context, + public static async Task FromContentsAsync(IResultList contents, QueryContext context, ApiController controller, - string app, - string schema) + ISchemaEntity schema, + IContentWorkflow contentWorkflow) { var result = new ContentsDto { - Total = total, - Items = contents.Select(x => ContentDto.FromContent(x, context, controller, app, schema)).ToArray(), + Total = contents.Total, + Items = new ContentDto[contents.Count] }; - result.Statuses = new string[] { "Archived", "Draft", "Published" }; + await Task.WhenAll( + result.AssignContentsAsync(contentWorkflow, contents, context, controller), + result.AssignStatusesAsync(contentWorkflow, schema)); - return result.CreateLinks(controller, app, schema); + return result.CreateLinks(controller, schema.AppId.Name, schema.SchemaDef.Name); + } + + private async Task AssignStatusesAsync(IContentWorkflow contentWorkflow, ISchemaEntity schema) + { + var allStatuses = await contentWorkflow.GetAllAsync(schema); + + Statuses = allStatuses.ToArray(); + } + + private async Task AssignContentsAsync(IContentWorkflow contentWorkflow, IResultList contents, QueryContext context, ApiController controller) + { + for (var i = 0; i < Items.Length; i++) + { + Items[i] = await ContentDto.FromContentAsync(context, contents[i], contentWorkflow, controller); + } } private ContentsDto CreateLinks(ApiController controller, string app, string schema) diff --git a/tests/Squidex.Domain.Apps.Entities.Tests/Contents/ContentQueryServiceTests.cs b/tests/Squidex.Domain.Apps.Entities.Tests/Contents/ContentQueryServiceTests.cs index 9ca83efa0..546454b83 100644 --- a/tests/Squidex.Domain.Apps.Entities.Tests/Contents/ContentQueryServiceTests.cs +++ b/tests/Squidex.Domain.Apps.Entities.Tests/Contents/ContentQueryServiceTests.cs @@ -103,7 +103,7 @@ namespace Squidex.Domain.Apps.Entities.Contents { SetupSchemaFound(); - var result = await sut.GetSchemaAsync(context, schemaId.Name); + var result = await sut.GetSchemaOrThrowAsync(context, schemaId.Name); Assert.Equal(schema, result); } @@ -113,7 +113,7 @@ namespace Squidex.Domain.Apps.Entities.Contents { SetupSchemaFound(); - var result = await sut.GetSchemaAsync(context, schemaId.Name); + var result = await sut.GetSchemaOrThrowAsync(context, schemaId.Name); Assert.Equal(schema, result); } @@ -125,7 +125,7 @@ namespace Squidex.Domain.Apps.Entities.Contents var ctx = context; - await Assert.ThrowsAsync(() => sut.GetSchemaAsync(ctx, schemaId.Name)); + await Assert.ThrowsAsync(() => sut.GetSchemaOrThrowAsync(ctx, schemaId.Name)); } [Fact] @@ -135,7 +135,7 @@ namespace Squidex.Domain.Apps.Entities.Contents var ctx = context; - await Assert.ThrowsAsync(() => sut.ThrowIfSchemaNotExistsAsync(ctx, schemaId.Name)); + await Assert.ThrowsAsync(() => sut.GetSchemaOrThrowAsync(ctx, schemaId.Name)); } [Fact] From de881c88a311e5e435598b16e30c8e6811c02b20 Mon Sep 17 00:00:00 2001 From: Sebastian Stehle Date: Tue, 18 Jun 2019 16:14:04 +0200 Subject: [PATCH 05/47] Finalize status. --- .../Contents/Json/StatusConverter.cs | 42 +++++++++++++ .../Contents/Status2.cs | 2 +- .../Config/Domain/SerializationServices.cs | 2 + .../Model/Contents/StatusTests.cs | 60 +++++++++++++++++++ .../TestUtils.cs | 2 + 5 files changed, 107 insertions(+), 1 deletion(-) create mode 100644 src/Squidex.Domain.Apps.Core.Model/Contents/Json/StatusConverter.cs create mode 100644 tests/Squidex.Domain.Apps.Core.Tests/Model/Contents/StatusTests.cs diff --git a/src/Squidex.Domain.Apps.Core.Model/Contents/Json/StatusConverter.cs b/src/Squidex.Domain.Apps.Core.Model/Contents/Json/StatusConverter.cs new file mode 100644 index 000000000..6c4266e08 --- /dev/null +++ b/src/Squidex.Domain.Apps.Core.Model/Contents/Json/StatusConverter.cs @@ -0,0 +1,42 @@ +// ========================================================================== +// Squidex Headless CMS +// ========================================================================== +// Copyright (c) Squidex UG (haftungsbeschränkt) +// All rights reserved. Licensed under the MIT license. +// ========================================================================== + +using Newtonsoft.Json; +using Squidex.Infrastructure.Json.Newtonsoft; +using System; +using System.Collections.Generic; + +namespace Squidex.Domain.Apps.Core.Contents.Json +{ + public sealed class StatusConverter : JsonConverter, ISupportedTypes + { + public IEnumerable SupportedTypes + { + get { yield return typeof(Status2); } + } + + public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) + { + writer.WriteValue(value.ToString()); + } + + public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) + { + if (reader.TokenType != JsonToken.String) + { + throw new JsonException($"Expected String, but got {reader.TokenType}."); + } + + return new Status2(reader.Value.ToString()); + } + + public override bool CanConvert(Type objectType) + { + return objectType == typeof(Status2); + } + } +} diff --git a/src/Squidex.Domain.Apps.Core.Model/Contents/Status2.cs b/src/Squidex.Domain.Apps.Core.Model/Contents/Status2.cs index 3e684bbe7..7ce6e830c 100644 --- a/src/Squidex.Domain.Apps.Core.Model/Contents/Status2.cs +++ b/src/Squidex.Domain.Apps.Core.Model/Contents/Status2.cs @@ -35,7 +35,7 @@ namespace Squidex.Domain.Apps.Core.Contents public override int GetHashCode() { - return base.GetHashCode(); + return Name.GetHashCode(); } public override string ToString() diff --git a/src/Squidex/Config/Domain/SerializationServices.cs b/src/Squidex/Config/Domain/SerializationServices.cs index 0b1f7cfce..44aadc738 100644 --- a/src/Squidex/Config/Domain/SerializationServices.cs +++ b/src/Squidex/Config/Domain/SerializationServices.cs @@ -11,6 +11,7 @@ using Newtonsoft.Json; using Newtonsoft.Json.Converters; using Squidex.Domain.Apps.Core; using Squidex.Domain.Apps.Core.Apps.Json; +using Squidex.Domain.Apps.Core.Contents.Json; using Squidex.Domain.Apps.Core.Rules.Json; using Squidex.Domain.Apps.Core.Schemas; using Squidex.Domain.Apps.Core.Schemas.Json; @@ -44,6 +45,7 @@ namespace Squidex.Config.Domain new RolesConverter(), new RuleConverter(), new SchemaConverter(), + new StatusConverter(), new StringEnumConverter()); settings.NullValueHandling = NullValueHandling.Ignore; diff --git a/tests/Squidex.Domain.Apps.Core.Tests/Model/Contents/StatusTests.cs b/tests/Squidex.Domain.Apps.Core.Tests/Model/Contents/StatusTests.cs new file mode 100644 index 000000000..5abdd5f2d --- /dev/null +++ b/tests/Squidex.Domain.Apps.Core.Tests/Model/Contents/StatusTests.cs @@ -0,0 +1,60 @@ +// ========================================================================== +// Squidex Headless CMS +// ========================================================================== +// Copyright (c) Squidex UG (haftungsbeschraenkt) +// All rights reserved. Licensed under the MIT license. +// ========================================================================== + +using Squidex.Domain.Apps.Core.Contents; +using Xunit; + +namespace Squidex.Domain.Apps.Core.Model.Contents +{ + public class StatusTests + { + [Fact] + public void Should_initialize_status_from_string() + { + var result = new Status2("Draft"); + + Assert.Equal("Draft", result.Name); + Assert.Equal("Draft", result.ToString()); + } + + [Fact] + public void Should_provide_published_status() + { + var result = Status2.Published; + + Assert.Equal("Published", result.Name); + Assert.Equal("Published", result.ToString()); + } + + [Fact] + public void Should_make_correct_equal_comparisons() + { + var status_1_a = new Status2("Draft"); + var status_1_b = new Status2("Draft"); + + var status2_a = new Status2("Published"); + + Assert.Equal(status_1_a, status_1_b); + Assert.Equal(status_1_a.GetHashCode(), status_1_b.GetHashCode()); + Assert.True(status_1_a.Equals((object)status_1_b)); + + Assert.NotEqual(status_1_a, status2_a); + Assert.NotEqual(status_1_a.GetHashCode(), status2_a.GetHashCode()); + Assert.False(status_1_a.Equals((object)status2_a)); + } + + [Fact] + public void Should_serialize_and_deserialize() + { + var status = new Status2("Draft"); + + var serialized = status.SerializeAndDeserialize(); + + Assert.Equal(status, serialized); + } + } +} diff --git a/tests/Squidex.Domain.Apps.Core.Tests/TestUtils.cs b/tests/Squidex.Domain.Apps.Core.Tests/TestUtils.cs index e3e34b385..58692226c 100644 --- a/tests/Squidex.Domain.Apps.Core.Tests/TestUtils.cs +++ b/tests/Squidex.Domain.Apps.Core.Tests/TestUtils.cs @@ -11,6 +11,7 @@ using System.Reflection; using Newtonsoft.Json; using Newtonsoft.Json.Converters; using Squidex.Domain.Apps.Core.Apps.Json; +using Squidex.Domain.Apps.Core.Contents.Json; using Squidex.Domain.Apps.Core.HandleRules; using Squidex.Domain.Apps.Core.Rules.Json; using Squidex.Domain.Apps.Core.Schemas; @@ -56,6 +57,7 @@ namespace Squidex.Domain.Apps.Core new RolesConverter(), new RuleConverter(), new SchemaConverter(), + new StatusConverter(), new StringEnumConverter()), TypeNameHandling = typeNameHandling From 41bdbdcce710538e764e91b6fa38a043c829a579 Mon Sep 17 00:00:00 2001 From: Sebastian Stehle Date: Tue, 18 Jun 2019 18:01:36 +0200 Subject: [PATCH 06/47] Build improvements. --- .testrunsettings | 6 ++++++ Dockerfile | 7 +------ Dockerfile.build | 7 +------ 3 files changed, 8 insertions(+), 12 deletions(-) create mode 100644 .testrunsettings diff --git a/.testrunsettings b/.testrunsettings new file mode 100644 index 000000000..0082141a9 --- /dev/null +++ b/.testrunsettings @@ -0,0 +1,6 @@ + + + + 4 + + \ No newline at end of file diff --git a/Dockerfile b/Dockerfile index 86485f677..7b5213883 100644 --- a/Dockerfile +++ b/Dockerfile @@ -19,12 +19,7 @@ RUN cp -a /tmp/node_modules src/Squidex/ \ && npm run build # Test Backend -RUN dotnet restore \ - && dotnet test --filter Category!=Dependencies tests/Squidex.Infrastructure.Tests/Squidex.Infrastructure.Tests.csproj \ - && dotnet test tests/Squidex.Domain.Apps.Core.Tests/Squidex.Domain.Apps.Core.Tests.csproj \ - && dotnet test tests/Squidex.Domain.Apps.Entities.Tests/Squidex.Domain.Apps.Entities.Tests.csproj \ - && dotnet test tests/Squidex.Domain.Users.Tests/Squidex.Domain.Users.Tests.csproj \ - && dotnet test tests/Squidex.Web.Tests/Squidex.Web.Tests.csproj +RUN dotnet restore && dotnet test -s ../../.testrunsettings --filter Category!=Dependencies # Publish RUN dotnet publish src/Squidex/Squidex.csproj --output /out/alpine --configuration Release -r alpine.3.7-x64 diff --git a/Dockerfile.build b/Dockerfile.build index 30a5d3091..f1468b1e0 100644 --- a/Dockerfile.build +++ b/Dockerfile.build @@ -16,12 +16,7 @@ RUN cp -a /tmp/node_modules src/Squidex/ \ && npm run build # Test Backend -RUN dotnet restore \ - && dotnet test --filter Category!=Dependencies tests/Squidex.Infrastructure.Tests/Squidex.Infrastructure.Tests.csproj \ - && dotnet test tests/Squidex.Domain.Apps.Core.Tests/Squidex.Domain.Apps.Core.Tests.csproj \ - && dotnet test tests/Squidex.Domain.Apps.Entities.Tests/Squidex.Domain.Apps.Entities.Tests.csproj \ - && dotnet test tests/Squidex.Domain.Users.Tests/Squidex.Domain.Users.Tests.csproj \ - && dotnet test tests/Squidex.Web.Tests/Squidex.Web.Tests.csproj +RUN dotnet restore && dotnet test -s ../../.testrunsettings --filter Category!=Dependencies # Publish RUN dotnet publish src/Squidex/Squidex.csproj --output /out/ --configuration Release \ No newline at end of file From 3502e679af697c94393419b38ae155369967d65f Mon Sep 17 00:00:00 2001 From: Sebastian Stehle Date: Tue, 18 Jun 2019 18:14:43 +0200 Subject: [PATCH 07/47] Share nuget folder. --- .drone.yml | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/.drone.yml b/.drone.yml index bc95a8247..04d7f8979 100644 --- a/.drone.yml +++ b/.drone.yml @@ -28,6 +28,8 @@ steps: path: /var/run/docker.sock - name: docker2 path: /var/lib/docker + - name: nuget + path: ~/.nuget/packages environment: DOCKER_USERNAME: from_secret: DOCKER_USERNAME @@ -51,6 +53,8 @@ steps: path: /var/run/docker.sock - name: docker2 path: /var/lib/docker + - name: nuget + path: ~/.nuget/packages environment: DOCKER_USERNAME: from_secret: DOCKER_USERNAME @@ -73,6 +77,8 @@ steps: path: /var/run/docker.sock - name: docker2 path: /var/lib/docker + - name: nuget + path: ~/.nuget/packages when: event: - tag @@ -154,4 +160,7 @@ volumes: path: /var/run/docker.sock - name: docker2 host: - path: /var/lib/docker \ No newline at end of file + path: /var/lib/docker + - name: nuget + host: + path: /var/lib/nuget \ No newline at end of file From 4e588c0d72b7c65b4c3fc3fe6c01ba4959f1c192 Mon Sep 17 00:00:00 2001 From: Sebastian Stehle Date: Tue, 18 Jun 2019 18:17:55 +0200 Subject: [PATCH 08/47] Test --- .testrunsettings | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.testrunsettings b/.testrunsettings index 0082141a9..69a779394 100644 --- a/.testrunsettings +++ b/.testrunsettings @@ -1,6 +1,6 @@ - 4 + 6 \ No newline at end of file From 42ce42502b894e90f0c0714031024a77e13cd24d Mon Sep 17 00:00:00 2001 From: Sebastian Stehle Date: Tue, 18 Jun 2019 18:21:16 +0200 Subject: [PATCH 09/47] Another attempt. --- .drone.yml | 4 ++-- .testrunsettings | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.drone.yml b/.drone.yml index 04d7f8979..b9452ffb5 100644 --- a/.drone.yml +++ b/.drone.yml @@ -29,7 +29,7 @@ steps: - name: docker2 path: /var/lib/docker - name: nuget - path: ~/.nuget/packages + path: /home/.nuget/packages environment: DOCKER_USERNAME: from_secret: DOCKER_USERNAME @@ -54,7 +54,7 @@ steps: - name: docker2 path: /var/lib/docker - name: nuget - path: ~/.nuget/packages + path: /home/.nuget/packages environment: DOCKER_USERNAME: from_secret: DOCKER_USERNAME diff --git a/.testrunsettings b/.testrunsettings index 69a779394..0082141a9 100644 --- a/.testrunsettings +++ b/.testrunsettings @@ -1,6 +1,6 @@ - 6 + 4 \ No newline at end of file From 331e39a1e19a282c8e76b645d0d3256f3488b049 Mon Sep 17 00:00:00 2001 From: Sebastian Stehle Date: Tue, 18 Jun 2019 18:23:28 +0200 Subject: [PATCH 10/47] FF --- .testrunsettings | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.testrunsettings b/.testrunsettings index 0082141a9..69a779394 100644 --- a/.testrunsettings +++ b/.testrunsettings @@ -1,6 +1,6 @@ - 4 + 6 \ No newline at end of file From e71953030a121fe54a5d66d2912f295e5443de58 Mon Sep 17 00:00:00 2001 From: Sebastian Stehle Date: Tue, 18 Jun 2019 18:24:27 +0200 Subject: [PATCH 11/47] Pull Request fix. --- .drone.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.drone.yml b/.drone.yml index b9452ffb5..e0e7ab7f6 100644 --- a/.drone.yml +++ b/.drone.yml @@ -12,6 +12,8 @@ steps: path: /var/run/docker.sock - name: docker2 path: /var/lib/docker + - name: nuget + path: /home/.nuget/packages when: event: - pull_request From 6c791e4e80914d97fba3c0bcf4825516f19be2a5 Mon Sep 17 00:00:00 2001 From: Sebastian Stehle Date: Tue, 18 Jun 2019 18:25:43 +0200 Subject: [PATCH 12/47] T --- .testrunsettings | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.testrunsettings b/.testrunsettings index 69a779394..0082141a9 100644 --- a/.testrunsettings +++ b/.testrunsettings @@ -1,6 +1,6 @@ - 6 + 4 \ No newline at end of file From 311db4942cde17eb4b31057843e77b6435d2f1f4 Mon Sep 17 00:00:00 2001 From: Sebastian Stehle Date: Tue, 18 Jun 2019 18:28:33 +0200 Subject: [PATCH 13/47] Test --- .testrunsettings | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.testrunsettings b/.testrunsettings index 0082141a9..ef537d413 100644 --- a/.testrunsettings +++ b/.testrunsettings @@ -1,6 +1,6 @@ - 4 + 5 \ No newline at end of file From df80cfd57cee3e36385c6e3cd531b2d575557da0 Mon Sep 17 00:00:00 2001 From: Sebastian Stehle Date: Tue, 18 Jun 2019 18:34:41 +0200 Subject: [PATCH 14/47] Nuget cache extraction test #1 --- .drone.yml | 8 ++++---- .testrunsettings | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/.drone.yml b/.drone.yml index e0e7ab7f6..92b954985 100644 --- a/.drone.yml +++ b/.drone.yml @@ -13,7 +13,7 @@ steps: - name: docker2 path: /var/lib/docker - name: nuget - path: /home/.nuget/packages + path: /root/.nuget/packages/ when: event: - pull_request @@ -31,7 +31,7 @@ steps: - name: docker2 path: /var/lib/docker - name: nuget - path: /home/.nuget/packages + path: /root/.nuget/packages/ environment: DOCKER_USERNAME: from_secret: DOCKER_USERNAME @@ -56,7 +56,7 @@ steps: - name: docker2 path: /var/lib/docker - name: nuget - path: /home/.nuget/packages + path: /root/.nuget/packages/ environment: DOCKER_USERNAME: from_secret: DOCKER_USERNAME @@ -80,7 +80,7 @@ steps: - name: docker2 path: /var/lib/docker - name: nuget - path: ~/.nuget/packages + path: /root/.nuget/packages/ when: event: - tag diff --git a/.testrunsettings b/.testrunsettings index ef537d413..0082141a9 100644 --- a/.testrunsettings +++ b/.testrunsettings @@ -1,6 +1,6 @@ - 5 + 4 \ No newline at end of file From b68330af435a0178da4044111b9a46cd9d9aa0c7 Mon Sep 17 00:00:00 2001 From: Sebastian Stehle Date: Tue, 18 Jun 2019 18:51:45 +0200 Subject: [PATCH 15/47] Test --- Dockerfile | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Dockerfile b/Dockerfile index 7b5213883..e6750cb62 100644 --- a/Dockerfile +++ b/Dockerfile @@ -17,6 +17,8 @@ RUN cp -a /tmp/node_modules src/Squidex/ \ && cd src/Squidex \ && npm run test:coverage \ && npm run build + +RUN find / -name "*.nupkg" # Test Backend RUN dotnet restore && dotnet test -s ../../.testrunsettings --filter Category!=Dependencies From 16921870eb236b58b32589ecffcd30d4043ac0b1 Mon Sep 17 00:00:00 2001 From: Sebastian Stehle Date: Tue, 18 Jun 2019 18:58:09 +0200 Subject: [PATCH 16/47] A --- .drone.yml | 8 ++++---- Dockerfile | 6 ++++-- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/.drone.yml b/.drone.yml index 92b954985..26210c516 100644 --- a/.drone.yml +++ b/.drone.yml @@ -13,7 +13,7 @@ steps: - name: docker2 path: /var/lib/docker - name: nuget - path: /root/.nuget/packages/ + path: /root/.nuget/packages when: event: - pull_request @@ -31,7 +31,7 @@ steps: - name: docker2 path: /var/lib/docker - name: nuget - path: /root/.nuget/packages/ + path: /root/.nuget/packages environment: DOCKER_USERNAME: from_secret: DOCKER_USERNAME @@ -56,7 +56,7 @@ steps: - name: docker2 path: /var/lib/docker - name: nuget - path: /root/.nuget/packages/ + path: /root/.nuget/packages environment: DOCKER_USERNAME: from_secret: DOCKER_USERNAME @@ -80,7 +80,7 @@ steps: - name: docker2 path: /var/lib/docker - name: nuget - path: /root/.nuget/packages/ + path: /root/.nuget/packages when: event: - tag diff --git a/Dockerfile b/Dockerfile index e6750cb62..54958061e 100644 --- a/Dockerfile +++ b/Dockerfile @@ -5,6 +5,10 @@ FROM squidex/dotnet:2.2-sdk-chromium-phantomjs-node as builder WORKDIR /src +COPY . . + +RUN dotnet restore + COPY src/Squidex/package*.json /tmp/ # Install Node packages @@ -17,8 +21,6 @@ RUN cp -a /tmp/node_modules src/Squidex/ \ && cd src/Squidex \ && npm run test:coverage \ && npm run build - -RUN find / -name "*.nupkg" # Test Backend RUN dotnet restore && dotnet test -s ../../.testrunsettings --filter Category!=Dependencies From 4dd3a56691ba135130a5ed0e64ae2719bb6f55bb Mon Sep 17 00:00:00 2001 From: Sebastian Stehle Date: Tue, 18 Jun 2019 19:03:08 +0200 Subject: [PATCH 17/47] Reverted --- Dockerfile | 4 ---- 1 file changed, 4 deletions(-) diff --git a/Dockerfile b/Dockerfile index 54958061e..7b5213883 100644 --- a/Dockerfile +++ b/Dockerfile @@ -5,10 +5,6 @@ FROM squidex/dotnet:2.2-sdk-chromium-phantomjs-node as builder WORKDIR /src -COPY . . - -RUN dotnet restore - COPY src/Squidex/package*.json /tmp/ # Install Node packages From d9c05be89f3e56e6f1c39bd6fa5174dda5f18c55 Mon Sep 17 00:00:00 2001 From: Sebastian Stehle Date: Tue, 18 Jun 2019 19:45:33 +0200 Subject: [PATCH 18/47] Reverted docker build volume. --- .drone.yml | 13 +------------ 1 file changed, 1 insertion(+), 12 deletions(-) diff --git a/.drone.yml b/.drone.yml index 26210c516..bc95a8247 100644 --- a/.drone.yml +++ b/.drone.yml @@ -12,8 +12,6 @@ steps: path: /var/run/docker.sock - name: docker2 path: /var/lib/docker - - name: nuget - path: /root/.nuget/packages when: event: - pull_request @@ -30,8 +28,6 @@ steps: path: /var/run/docker.sock - name: docker2 path: /var/lib/docker - - name: nuget - path: /root/.nuget/packages environment: DOCKER_USERNAME: from_secret: DOCKER_USERNAME @@ -55,8 +51,6 @@ steps: path: /var/run/docker.sock - name: docker2 path: /var/lib/docker - - name: nuget - path: /root/.nuget/packages environment: DOCKER_USERNAME: from_secret: DOCKER_USERNAME @@ -79,8 +73,6 @@ steps: path: /var/run/docker.sock - name: docker2 path: /var/lib/docker - - name: nuget - path: /root/.nuget/packages when: event: - tag @@ -162,7 +154,4 @@ volumes: path: /var/run/docker.sock - name: docker2 host: - path: /var/lib/docker - - name: nuget - host: - path: /var/lib/nuget \ No newline at end of file + path: /var/lib/docker \ No newline at end of file From ab1fb499fdedc464a7f86001dde1f052a1645e2c Mon Sep 17 00:00:00 2001 From: Sebastian Date: Tue, 18 Jun 2019 23:00:24 +0200 Subject: [PATCH 19/47] Simple fixes. --- Dockerfile | 12 +++++++++-- Dockerfile.build | 12 +++++++++-- src/Squidex/package-lock.json | 38 +++++++++++++++++++++-------------- src/Squidex/package.json | 16 ++++++++------- 4 files changed, 52 insertions(+), 26 deletions(-) diff --git a/Dockerfile b/Dockerfile index 86485f677..e57b35d67 100644 --- a/Dockerfile +++ b/Dockerfile @@ -5,11 +5,20 @@ FROM squidex/dotnet:2.2-sdk-chromium-phantomjs-node as builder WORKDIR /src +# Copy Node project files. COPY src/Squidex/package*.json /tmp/ # Install Node packages RUN cd /tmp && npm install --loglevel=error +# Copy nuget project files. +COPY /**/**/*.csproj /tmp/ +# Copy nuget.config for package sources. +COPY NuGet.Config /tmp/ + +# Install nuget packages +RUN bash -c 'pushd /tmp; for p in *.csproj; do dotnet restore $p --verbosity quiet; true; done; popd' + COPY . . # Build Frontend @@ -19,8 +28,7 @@ RUN cp -a /tmp/node_modules src/Squidex/ \ && npm run build # Test Backend -RUN dotnet restore \ - && dotnet test --filter Category!=Dependencies tests/Squidex.Infrastructure.Tests/Squidex.Infrastructure.Tests.csproj \ +RUN dotnet test tests/Squidex.Infrastructure.Tests/Squidex.Infrastructure.Tests.csproj --filter Category!=Dependencies \ && dotnet test tests/Squidex.Domain.Apps.Core.Tests/Squidex.Domain.Apps.Core.Tests.csproj \ && dotnet test tests/Squidex.Domain.Apps.Entities.Tests/Squidex.Domain.Apps.Entities.Tests.csproj \ && dotnet test tests/Squidex.Domain.Users.Tests/Squidex.Domain.Users.Tests.csproj \ diff --git a/Dockerfile.build b/Dockerfile.build index 30a5d3091..96debc8cd 100644 --- a/Dockerfile.build +++ b/Dockerfile.build @@ -2,11 +2,20 @@ FROM squidex/dotnet:2.2-sdk-chromium-phantomjs-node as builder WORKDIR /src +# Copy Node project files. COPY src/Squidex/package*.json /tmp/ # Install Node packages RUN cd /tmp && npm install --loglevel=error +# Copy Dotnet project files. +COPY /**/**/*.csproj /tmp/ +# Copy nuget.config for package sources. +COPY NuGet.Config /tmp/ + +# Install Dotnet packages +RUN bash -c 'pushd /tmp; for p in *.csproj; do dotnet restore $p --verbosity quiet; true; done; popd' + COPY . . # Build Frontend @@ -16,8 +25,7 @@ RUN cp -a /tmp/node_modules src/Squidex/ \ && npm run build # Test Backend -RUN dotnet restore \ - && dotnet test --filter Category!=Dependencies tests/Squidex.Infrastructure.Tests/Squidex.Infrastructure.Tests.csproj \ +RUN dotnet test tests/Squidex.Infrastructure.Tests/Squidex.Infrastructure.Tests.csproj --filter Category!=Dependencies \ && dotnet test tests/Squidex.Domain.Apps.Core.Tests/Squidex.Domain.Apps.Core.Tests.csproj \ && dotnet test tests/Squidex.Domain.Apps.Entities.Tests/Squidex.Domain.Apps.Entities.Tests.csproj \ && dotnet test tests/Squidex.Domain.Users.Tests/Squidex.Domain.Users.Tests.csproj \ diff --git a/src/Squidex/package-lock.json b/src/Squidex/package-lock.json index 3051cf82b..b8073c031 100644 --- a/src/Squidex/package-lock.json +++ b/src/Squidex/package-lock.json @@ -3196,14 +3196,22 @@ } }, "browserslist": { - "version": "4.3.5", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.3.5.tgz", - "integrity": "sha512-z9ZhGc3d9e/sJ9dIx5NFXkKoaiQTnrvrMsN3R1fGb1tkWWNSz12UewJn9TNxGo1l7J23h0MRaPmk7jfeTZYs1w==", + "version": "4.6.3", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.6.3.tgz", + "integrity": "sha512-CNBqTCq22RKM8wKJNowcqihHJ4SkI8CGeK7KOR9tPboXUuS5Zk5lQgzzTbs4oxD8x+6HUshZUa2OyNI9lR93bQ==", "dev": true, "requires": { - "caniuse-lite": "^1.0.30000912", - "electron-to-chromium": "^1.3.86", - "node-releases": "^1.0.5" + "caniuse-lite": "^1.0.30000975", + "electron-to-chromium": "^1.3.164", + "node-releases": "^1.1.23" + }, + "dependencies": { + "caniuse-lite": { + "version": "1.0.30000975", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30000975.tgz", + "integrity": "sha512-ZsXA9YWQX6ATu5MNg+Vx/cMQ+hM6vBBSqDeJs8ruk9z0ky4yIHML15MoxcFt088ST2uyjgqyUGRJButkptWf0w==", + "dev": true + } } }, "buffer": { @@ -3450,9 +3458,9 @@ } }, "caniuse-lite": { - "version": "1.0.30000918", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30000918.tgz", - "integrity": "sha512-CAZ9QXGViBvhHnmIHhsTPSWFBujDaelKnUj7wwImbyQRxmXynYqKGi3UaZTSz9MoVh+1EVxOS/DFIkrJYgR3aw==", + "version": "1.0.30000975", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30000975.tgz", + "integrity": "sha512-ZsXA9YWQX6ATu5MNg+Vx/cMQ+hM6vBBSqDeJs8ruk9z0ky4yIHML15MoxcFt088ST2uyjgqyUGRJButkptWf0w==", "dev": true }, "canonical-path": { @@ -4950,9 +4958,9 @@ "dev": true }, "electron-to-chromium": { - "version": "1.3.90", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.90.tgz", - "integrity": "sha512-IjJZKRhFbWSOX1w0sdIXgp4CMRguu6UYcTckyFF/Gjtemsu/25eZ+RXwFlV+UWcIueHyQA1UnRJxocTpH5NdGA==", + "version": "1.3.164", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.164.tgz", + "integrity": "sha512-VLlalqUeduN4+fayVtRZvGP2Hl1WrRxlwzh2XVVMJym3IFrQUS29BFQ1GP/BxOJXJI1OFCrJ5BnFEsAe8NHtOg==", "dev": true }, "elliptic": { @@ -10755,9 +10763,9 @@ } }, "node-releases": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-1.1.1.tgz", - "integrity": "sha512-2UXrBr6gvaebo5TNF84C66qyJJ6r0kxBObgZIDX3D3/mt1ADKiHux3NJPWisq0wxvJJdkjECH+9IIKYViKj71Q==", + "version": "1.1.23", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-1.1.23.tgz", + "integrity": "sha512-uq1iL79YjfYC0WXoHbC/z28q/9pOl8kSHaXdWmAAc8No+bDwqkZbzIJz55g/MUsPgSGm9LZ7QSUbzTcH5tz47w==", "dev": true, "requires": { "semver": "^5.3.0" diff --git a/src/Squidex/package.json b/src/Squidex/package.json index 72f1ab671..09a66cd63 100644 --- a/src/Squidex/package.json +++ b/src/Squidex/package.json @@ -47,21 +47,23 @@ "zone.js": "0.9.1" }, "devDependencies": { - "@angular/compiler-cli": "7.2.14", "@angular/compiler": "7.2.14", + "@angular/compiler-cli": "7.2.14", "@ngtools/webpack": "7.3.8", "@types/core-js": "2.5.0", "@types/jasmine": "3.3.12", "@types/marked": "0.6.5", "@types/mousetrap": "1.6", "@types/node": "12.0.0", - "@types/react-dom": "16.8.4", "@types/react": "16.8.16", + "@types/react-dom": "16.8.4", "@types/sortablejs": "1.7.2", "angular-router-loader": "0.8.5", "angular2-template-loader": "0.6.2", "awesome-typescript-loader": "5.2.1", "babel-core": "6.26.3", + "browserslist": "^4.6.3", + "caniuse-lite": "^1.0.30000975", "circular-dependency-plugin": "5.0.2", "codelyzer": "5.0.1", "cpx": "1.5.0", @@ -72,16 +74,16 @@ "ignore-loader": "0.1.2", "istanbul-instrumenter-loader": "3.0.1", "jasmine-core": "3.4.0", + "karma": "4.1.0", "karma-chrome-launcher": "2.2.0", "karma-cli": "2.0.0", "karma-coverage-istanbul-reporter": "2.0.5", "karma-htmlfile-reporter": "0.3.8", - "karma-jasmine-html-reporter": "1.4.2", "karma-jasmine": "2.0.1", + "karma-jasmine-html-reporter": "1.4.2", "karma-mocha-reporter": "2.2.5", "karma-sourcemap-loader": "0.3.7", "karma-webpack": "3.0.5", - "karma": "4.1.0", "mini-css-extract-plugin": "0.6.0", "node-sass": "4.12.0", "optimize-css-assets-webpack-plugin": "5.0.1", @@ -93,15 +95,15 @@ "style-loader": "0.23.1", "ts-loader": "5.4.5", "tsconfig-paths-webpack-plugin": "3.2.0", - "tslint-webpack-plugin": "2.0.4", "tslint": "5.16.0", + "tslint-webpack-plugin": "2.0.4", "typemoq": "2.1.0", "typescript": "3.2.4", "uglifyjs-webpack-plugin": "2.1.2", "underscore": "1.9.1", + "webpack": "4.30.0", "webpack-cli": "3.3.1", "webpack-dev-server": "3.3.1", - "webpack-merge": "4.2.1", - "webpack": "4.30.0" + "webpack-merge": "4.2.1" } } From 7ff53516728891eea6d5f370405bcac54532b0c0 Mon Sep 17 00:00:00 2001 From: Ben-Fletcher-UK <49555119+Ben-Fletcher-UK@users.noreply.github.com> Date: Wed, 19 Jun 2019 12:48:40 +0100 Subject: [PATCH 20/47] Mapped StatusFlow to new DefaultContentWorkflow (#365) * Mapped StatusFlow to new DefaultContentWorkflow and Added Status2 to IContentEntity * Added DefaultContentWorkflow to DI and added tests. * Addressed feedback from Code Review. * Removed unused reference. --- .../Contents/DefaultContentWorkflow.cs | 75 +++++++++++++ src/Squidex/Config/Domain/EntitiesServices.cs | 3 + .../Squidex.Domain.Apps.Core.Tests.csproj | 1 + .../Contents/DefaultContentWorkflowTests.cs | 101 ++++++++++++++++++ 4 files changed, 180 insertions(+) create mode 100644 src/Squidex.Domain.Apps.Entities/Contents/DefaultContentWorkflow.cs create mode 100644 tests/Squidex.Domain.Apps.Entities.Tests/Contents/DefaultContentWorkflowTests.cs diff --git a/src/Squidex.Domain.Apps.Entities/Contents/DefaultContentWorkflow.cs b/src/Squidex.Domain.Apps.Entities/Contents/DefaultContentWorkflow.cs new file mode 100644 index 000000000..a75dd30a2 --- /dev/null +++ b/src/Squidex.Domain.Apps.Entities/Contents/DefaultContentWorkflow.cs @@ -0,0 +1,75 @@ +// ========================================================================== +// Squidex Headless CMS +// ========================================================================== +// Copyright (c) Squidex UG (haftungsbeschränkt) +// All rights reserved. Licensed under the MIT license. +// ========================================================================== + +using System; +using System.Collections.Generic; +using System.Threading.Tasks; +using Squidex.Domain.Apps.Core.Contents; +using Squidex.Domain.Apps.Entities.Schemas; +using Squidex.Infrastructure.Tasks; + +namespace Squidex.Domain.Apps.Entities.Contents +{ + public sealed class DefaultContentWorkflow : IContentWorkflow + { + private static readonly Status2 Draft = new Status2("Draft"); + private static readonly Status2 Archived = new Status2("Archived"); + private static readonly Status2 Published = new Status2("Published"); + + private static readonly Dictionary Flow = new Dictionary + { + [Draft] = new[] { Published, Archived }, + [Archived] = new[] { Draft }, + [Published] = new[] { Draft, Archived } + }; + + public Task GetInitialStatusAsync(ISchemaEntity schema) + { + return Task.FromResult(Draft); + } + + public Task IsValidNextStatus(IContentEntity content, Status2 next) + { + return TaskHelper.True; + } + + public Task CanUpdateAsync(IContentEntity content) + { + return TaskHelper.True; + } + + public Task GetNextsAsync(IContentEntity content) + { + Status2 statusToCheck; + + switch (content.Status) + { + case Status.Draft: + statusToCheck = Draft; + break; + case Status.Archived: + statusToCheck = Archived; + break; + case Status.Published: + statusToCheck = Published; + break; + default: + { + statusToCheck = Draft; + break; + } + } + + return Task.FromResult(Flow.TryGetValue(statusToCheck, out var result) ? result : Array.Empty()); + } + + public Task GetAllAsync(ISchemaEntity schema) + { + return Task.FromResult(new[] { Draft, Archived, Published } ); + } + } +} diff --git a/src/Squidex/Config/Domain/EntitiesServices.cs b/src/Squidex/Config/Domain/EntitiesServices.cs index 1b378c173..d44e12150 100644 --- a/src/Squidex/Config/Domain/EntitiesServices.cs +++ b/src/Squidex/Config/Domain/EntitiesServices.cs @@ -101,6 +101,9 @@ namespace Squidex.Config.Domain services.AddSingletonAs() .As(); + services.AddSingletonAs() + .AsOptional(); + services.AddSingletonAs() .AsSelf(); diff --git a/tests/Squidex.Domain.Apps.Core.Tests/Squidex.Domain.Apps.Core.Tests.csproj b/tests/Squidex.Domain.Apps.Core.Tests/Squidex.Domain.Apps.Core.Tests.csproj index 7c5aefb48..0b4ac139b 100644 --- a/tests/Squidex.Domain.Apps.Core.Tests/Squidex.Domain.Apps.Core.Tests.csproj +++ b/tests/Squidex.Domain.Apps.Core.Tests/Squidex.Domain.Apps.Core.Tests.csproj @@ -9,6 +9,7 @@ + diff --git a/tests/Squidex.Domain.Apps.Entities.Tests/Contents/DefaultContentWorkflowTests.cs b/tests/Squidex.Domain.Apps.Entities.Tests/Contents/DefaultContentWorkflowTests.cs new file mode 100644 index 000000000..f9f368f6f --- /dev/null +++ b/tests/Squidex.Domain.Apps.Entities.Tests/Contents/DefaultContentWorkflowTests.cs @@ -0,0 +1,101 @@ +// ========================================================================== +// Squidex Headless CMS +// ========================================================================== +// Copyright (c) Squidex UG (haftungsbeschränkt) +// All rights reserved. Licensed under the MIT license. +// ========================================================================== + +using System; +using System.Threading.Tasks; +using FakeItEasy; +using Squidex.Domain.Apps.Core.Contents; +using Xunit; + +namespace Squidex.Domain.Apps.Entities.Contents +{ + public class DefaultContentWorkflowTests + { + private static readonly DefaultContentWorkflow Sut = new DefaultContentWorkflow(); + + [Fact] + public async Task Should_draft_as_initial_status_async_tests() + { + var result = await Sut.GetInitialStatusAsync(null); + + Assert.IsType(result); + Assert.Equal("Draft", result.Name); + } + + [Fact] + public async Task Should_check_is_valid_next_status_tests() + { + var entity = CreateMockContentEntity(Status.Draft); + + var status = new Status2("Draft"); + + var result = await Sut.IsValidNextStatus(entity, status); + + Assert.IsType(result); + Assert.True(result); + } + + [Fact] + public async Task Should_update_async_tests() + { + var entity = CreateMockContentEntity(Status.Draft); + + var result = await Sut.CanUpdateAsync(entity); + + Assert.IsType(result); + Assert.True(result); + } + + [Fact] + public async Task Should_get_nexts_async_tests() + { + var draftContent = CreateMockContentEntity(Status.Draft); + var archivedContent = CreateMockContentEntity(Status.Archived); + var publishedContent = CreateMockContentEntity(Status.Published); + + var draftExpected = new[] { new Status2("Published"), new Status2("Archived") }; + var archivedExpected = new[] { new Status2("Draft") }; + var publishedExpected = new[] { new Status2("Draft"), new Status2("Archived") }; + + var draftResult = await Sut.GetNextsAsync(draftContent); + var archivedResult = await Sut.GetNextsAsync(archivedContent); + var publishedResult = await Sut.GetNextsAsync(publishedContent); + + Assert.IsType(draftResult); + Assert.IsType(archivedResult); + Assert.IsType(publishedResult); + + Assert.Equal(draftExpected, draftResult); + Assert.Equal(archivedExpected, archivedResult); + Assert.Equal(publishedExpected, publishedResult); + } + + [Fact] + public async Task Should_get_all_async_tests() + { + var expected = new[] { new Status2("Draft"), new Status2("Archived"), new Status2("Published") }; + + var result = await Sut.GetAllAsync(null); + + Assert.IsType(result); + Assert.Equal(expected, result); + } + + private IContentEntity CreateMockContentEntity(Status status) + { + var content = A.Fake(); + + A.CallTo(() => content.Id).Returns(default(Guid)); + A.CallTo(() => content.Data).Returns(null); + A.CallTo(() => content.DataDraft).Returns(null); + A.CallTo(() => content.SchemaId).Returns(null); + A.CallTo(() => content.Status).Returns(status); + + return content; + } + } +} From 20787820578d796ce295e4c57a2657b10b126c29 Mon Sep 17 00:00:00 2001 From: Sebastian Stehle Date: Wed, 19 Jun 2019 14:14:33 +0200 Subject: [PATCH 21/47] Formatting. --- .../Contents/DefaultContentWorkflowTests.cs | 75 ++++++++++--------- 1 file changed, 38 insertions(+), 37 deletions(-) diff --git a/tests/Squidex.Domain.Apps.Entities.Tests/Contents/DefaultContentWorkflowTests.cs b/tests/Squidex.Domain.Apps.Entities.Tests/Contents/DefaultContentWorkflowTests.cs index f9f368f6f..25d9d8bb8 100644 --- a/tests/Squidex.Domain.Apps.Entities.Tests/Contents/DefaultContentWorkflowTests.cs +++ b/tests/Squidex.Domain.Apps.Entities.Tests/Contents/DefaultContentWorkflowTests.cs @@ -5,7 +5,6 @@ // All rights reserved. Licensed under the MIT license. // ========================================================================== -using System; using System.Threading.Tasks; using FakeItEasy; using Squidex.Domain.Apps.Core.Contents; @@ -15,73 +14,79 @@ namespace Squidex.Domain.Apps.Entities.Contents { public class DefaultContentWorkflowTests { - private static readonly DefaultContentWorkflow Sut = new DefaultContentWorkflow(); + private readonly DefaultContentWorkflow sut = new DefaultContentWorkflow(); [Fact] - public async Task Should_draft_as_initial_status_async_tests() + public async Task Should_draft_as_initial_status() { - var result = await Sut.GetInitialStatusAsync(null); + var result = await sut.GetInitialStatusAsync(null); - Assert.IsType(result); - Assert.Equal("Draft", result.Name); + Assert.Equal(new Status2("Draft"), result); } [Fact] - public async Task Should_check_is_valid_next_status_tests() + public async Task Should_check_is_valid_next() { var entity = CreateMockContentEntity(Status.Draft); - var status = new Status2("Draft"); + var result = await sut.IsValidNextStatus(entity, new Status2("Draft")); - var result = await Sut.IsValidNextStatus(entity, status); - - Assert.IsType(result); Assert.True(result); } [Fact] - public async Task Should_update_async_tests() + public async Task Should_always_be_able_to_update() { var entity = CreateMockContentEntity(Status.Draft); - var result = await Sut.CanUpdateAsync(entity); + var result = await sut.CanUpdateAsync(entity); - Assert.IsType(result); Assert.True(result); } [Fact] - public async Task Should_get_nexts_async_tests() + public async Task Should_get_next_statuses_for_draft() { - var draftContent = CreateMockContentEntity(Status.Draft); - var archivedContent = CreateMockContentEntity(Status.Archived); - var publishedContent = CreateMockContentEntity(Status.Published); + var content = CreateMockContentEntity(Status.Draft); - var draftExpected = new[] { new Status2("Published"), new Status2("Archived") }; - var archivedExpected = new[] { new Status2("Draft") }; - var publishedExpected = new[] { new Status2("Draft"), new Status2("Archived") }; + var expected = new[] { new Status2("Published"), new Status2("Archived") }; - var draftResult = await Sut.GetNextsAsync(draftContent); - var archivedResult = await Sut.GetNextsAsync(archivedContent); - var publishedResult = await Sut.GetNextsAsync(publishedContent); + var result = await sut.GetNextsAsync(content); - Assert.IsType(draftResult); - Assert.IsType(archivedResult); - Assert.IsType(publishedResult); + Assert.Equal(expected, result); + } - Assert.Equal(draftExpected, draftResult); - Assert.Equal(archivedExpected, archivedResult); - Assert.Equal(publishedExpected, publishedResult); + [Fact] + public async Task Should_get_next_statuses_for_archived() + { + var content = CreateMockContentEntity(Status.Archived); + + var expected = new[] { new Status2("Draft") }; + + var result = await sut.GetNextsAsync(content); + + Assert.Equal(expected, result); + } + + [Fact] + public async Task Should_get_next_statuses_for_published() + { + var content = CreateMockContentEntity(Status.Published); + + var expected = new[] { new Status2("Draft"), new Status2("Archived") }; + + var result = await sut.GetNextsAsync(content); + + Assert.Equal(expected, result); } [Fact] - public async Task Should_get_all_async_tests() + public async Task Should_return_all_statuses() { var expected = new[] { new Status2("Draft"), new Status2("Archived"), new Status2("Published") }; - var result = await Sut.GetAllAsync(null); + var result = await sut.GetAllAsync(null); - Assert.IsType(result); Assert.Equal(expected, result); } @@ -89,10 +94,6 @@ namespace Squidex.Domain.Apps.Entities.Contents { var content = A.Fake(); - A.CallTo(() => content.Id).Returns(default(Guid)); - A.CallTo(() => content.Data).Returns(null); - A.CallTo(() => content.DataDraft).Returns(null); - A.CallTo(() => content.SchemaId).Returns(null); A.CallTo(() => content.Status).Returns(status); return content; From 9fed02581b901b030eee7c94fa77166aa3e70259 Mon Sep 17 00:00:00 2001 From: Sebastian Stehle Date: Wed, 19 Jun 2019 15:55:19 +0200 Subject: [PATCH 22/47] All tests green now. --- .../Contents/Json/StatusConverter.cs | 6 +- .../Contents/Status.cs | 53 +++++++- .../Contents/Status2.cs | 46 ------- .../Contents/StatusChange.cs | 17 --- .../Contents/StatusFlow.cs | 37 ------ .../EnrichedContentEventType.cs | 5 +- .../Contents/MongoContentEntity.cs | 1 - .../Contents/StatusSerializer.cs | 8 +- .../Contents/ContentChangedTriggerHandler.cs | 20 +-- .../Contents/ContentEntity.cs | 21 --- .../Contents/ContentGrain.cs | 59 ++++----- .../Contents/DefaultContentWorkflow.cs | 49 ++----- .../Contents/GraphQL/Types/AllTypes.cs | 4 - .../GraphQL/Types/ContentGraphType.cs | 4 +- .../Contents/Guards/GuardContent.cs | 35 +++-- .../Contents/IContentWorkflow.cs | 8 +- .../Contents/State/ContentState.cs | 5 + .../Contents/ContentCreated.cs | 2 + .../Contents/ContentStatusChanged.cs | 2 - .../Contents/ContentsController.cs | 2 +- .../Areas/Api/Controllers/Contents/Helper.cs | 7 - .../Controllers/Contents/Models/ContentDto.cs | 4 +- .../Contents/Models/ContentsDto.cs | 2 +- .../Model/Contents/StatusFlowTests.cs | 34 ----- .../Model/Contents/StatusTests.cs | 36 +++++- .../ContentChangedTriggerHandlerTests.cs | 6 +- .../Contents/ContentGrainTests.cs | 43 ++++++- .../Contents/ContentQueryServiceTests.cs | 7 +- .../Contents/DefaultContentWorkflowTests.cs | 24 ++-- .../Contents/GraphQL/GraphQLTestBase.cs | 3 +- .../Contents/Guard/GuardContentTests.cs | 120 +++++++++++++----- .../Contents/MongoDb/StatusSerializerTests.cs | 4 +- 32 files changed, 313 insertions(+), 361 deletions(-) delete mode 100644 src/Squidex.Domain.Apps.Core.Model/Contents/Status2.cs delete mode 100644 src/Squidex.Domain.Apps.Core.Model/Contents/StatusChange.cs delete mode 100644 src/Squidex.Domain.Apps.Core.Model/Contents/StatusFlow.cs delete mode 100644 tests/Squidex.Domain.Apps.Core.Tests/Model/Contents/StatusFlowTests.cs diff --git a/src/Squidex.Domain.Apps.Core.Model/Contents/Json/StatusConverter.cs b/src/Squidex.Domain.Apps.Core.Model/Contents/Json/StatusConverter.cs index 6c4266e08..a56722c55 100644 --- a/src/Squidex.Domain.Apps.Core.Model/Contents/Json/StatusConverter.cs +++ b/src/Squidex.Domain.Apps.Core.Model/Contents/Json/StatusConverter.cs @@ -16,7 +16,7 @@ namespace Squidex.Domain.Apps.Core.Contents.Json { public IEnumerable SupportedTypes { - get { yield return typeof(Status2); } + get { yield return typeof(Status); } } public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) @@ -31,12 +31,12 @@ namespace Squidex.Domain.Apps.Core.Contents.Json throw new JsonException($"Expected String, but got {reader.TokenType}."); } - return new Status2(reader.Value.ToString()); + return new Status(reader.Value.ToString()); } public override bool CanConvert(Type objectType) { - return objectType == typeof(Status2); + return objectType == typeof(Status); } } } diff --git a/src/Squidex.Domain.Apps.Core.Model/Contents/Status.cs b/src/Squidex.Domain.Apps.Core.Model/Contents/Status.cs index c20e0c4eb..d4c0374c8 100644 --- a/src/Squidex.Domain.Apps.Core.Model/Contents/Status.cs +++ b/src/Squidex.Domain.Apps.Core.Model/Contents/Status.cs @@ -5,12 +5,57 @@ // All rights reserved. Licensed under the MIT license. // ========================================================================== +using Squidex.Infrastructure; +using System; + namespace Squidex.Domain.Apps.Core.Contents { - public enum Status + public struct Status : IEquatable { - Draft, - Archived, - Published + public static readonly Status Archived = new Status("Archived"); + public static readonly Status Draft = new Status("Draft"); + public static readonly Status Published = new Status("Published"); + + private readonly string name; + + public string Name + { + get { return name ?? "Unknown"; } + } + + public Status(string name) + { + this.name = name; + } + + public override bool Equals(object obj) + { + return obj is Status status && Equals(status); + } + + public bool Equals(Status other) + { + return string.Equals(name, other.name); + } + + public override int GetHashCode() + { + return name?.GetHashCode() ?? 0; + } + + public override string ToString() + { + return name; + } + + public static bool operator ==(Status lhs, Status rhs) + { + return lhs.Equals(rhs); + } + + public static bool operator !=(Status lhs, Status rhs) + { + return !lhs.Equals(rhs); + } } } diff --git a/src/Squidex.Domain.Apps.Core.Model/Contents/Status2.cs b/src/Squidex.Domain.Apps.Core.Model/Contents/Status2.cs deleted file mode 100644 index 7ce6e830c..000000000 --- a/src/Squidex.Domain.Apps.Core.Model/Contents/Status2.cs +++ /dev/null @@ -1,46 +0,0 @@ -// ========================================================================== -// Squidex Headless CMS -// ========================================================================== -// Copyright (c) Squidex UG (haftungsbeschränkt) -// All rights reserved. Licensed under the MIT license. -// ========================================================================== - -using Squidex.Infrastructure; -using System; - -namespace Squidex.Domain.Apps.Core.Contents -{ - public struct Status2 : IEquatable - { - public static readonly Status2 Published = new Status2("Published"); - - public string Name { get; } - - public Status2(string name) - { - Guard.NotNullOrEmpty(name, nameof(name)); - - Name = name; - } - - public override bool Equals(object obj) - { - return obj is Status2 status && Equals(status); - } - - public bool Equals(Status2 other) - { - return Name.Equals(other.Name); - } - - public override int GetHashCode() - { - return Name.GetHashCode(); - } - - public override string ToString() - { - return Name; - } - } -} diff --git a/src/Squidex.Domain.Apps.Core.Model/Contents/StatusChange.cs b/src/Squidex.Domain.Apps.Core.Model/Contents/StatusChange.cs deleted file mode 100644 index 9e3900deb..000000000 --- a/src/Squidex.Domain.Apps.Core.Model/Contents/StatusChange.cs +++ /dev/null @@ -1,17 +0,0 @@ -// ========================================================================== -// Squidex Headless CMS -// ========================================================================== -// Copyright (c) Squidex UG (haftungsbeschraenkt) -// All rights reserved. Licensed under the MIT license. -// ========================================================================== - -namespace Squidex.Domain.Apps.Core.Contents -{ - public enum StatusChange - { - Archived, - Published, - Restored, - Unpublished - } -} diff --git a/src/Squidex.Domain.Apps.Core.Model/Contents/StatusFlow.cs b/src/Squidex.Domain.Apps.Core.Model/Contents/StatusFlow.cs deleted file mode 100644 index 7add93c24..000000000 --- a/src/Squidex.Domain.Apps.Core.Model/Contents/StatusFlow.cs +++ /dev/null @@ -1,37 +0,0 @@ -// ========================================================================== -// Squidex Headless CMS -// ========================================================================== -// Copyright (c) Squidex UG (haftungsbeschränkt) -// All rights reserved. Licensed under the MIT license. -// ========================================================================== - -using System.Collections.Generic; -using System.Linq; - -namespace Squidex.Domain.Apps.Core.Contents -{ - public static class StatusFlow - { - private static readonly Dictionary Flow = new Dictionary - { - [Status.Draft] = new[] { Status.Published, Status.Archived }, - [Status.Archived] = new[] { Status.Draft }, - [Status.Published] = new[] { Status.Draft, Status.Archived } - }; - - public static bool Exists(Status status) - { - return Flow.ContainsKey(status); - } - - public static bool CanChange(Status status, Status toStatus) - { - return Flow.TryGetValue(status, out var state) && state.Contains(toStatus); - } - - public static IEnumerable Next(Status status) - { - return Flow.TryGetValue(status, out var result) ? result : Enumerable.Empty(); - } - } -} diff --git a/src/Squidex.Domain.Apps.Core.Operations/HandleRules/EnrichedEvents/EnrichedContentEventType.cs b/src/Squidex.Domain.Apps.Core.Operations/HandleRules/EnrichedEvents/EnrichedContentEventType.cs index 45148a8e2..7ad49332d 100644 --- a/src/Squidex.Domain.Apps.Core.Operations/HandleRules/EnrichedEvents/EnrichedContentEventType.cs +++ b/src/Squidex.Domain.Apps.Core.Operations/HandleRules/EnrichedEvents/EnrichedContentEventType.cs @@ -9,12 +9,9 @@ namespace Squidex.Domain.Apps.Core.HandleRules.EnrichedEvents { public enum EnrichedContentEventType { - Archived, Created, Deleted, - Published, - Restored, - Unpublished, + StatusChanged, Updated } } diff --git a/src/Squidex.Domain.Apps.Entities.MongoDb/Contents/MongoContentEntity.cs b/src/Squidex.Domain.Apps.Entities.MongoDb/Contents/MongoContentEntity.cs index 9c8f3eba7..fe2e0649c 100644 --- a/src/Squidex.Domain.Apps.Entities.MongoDb/Contents/MongoContentEntity.cs +++ b/src/Squidex.Domain.Apps.Entities.MongoDb/Contents/MongoContentEntity.cs @@ -51,7 +51,6 @@ namespace Squidex.Domain.Apps.Entities.MongoDb.Contents [BsonRequired] [BsonElement("ss")] - [BsonRepresentation(BsonType.String)] public Status Status { get; set; } [BsonIgnoreIfNull] diff --git a/src/Squidex.Domain.Apps.Entities.MongoDb/Contents/StatusSerializer.cs b/src/Squidex.Domain.Apps.Entities.MongoDb/Contents/StatusSerializer.cs index 0b9bf91f0..5d59c836a 100644 --- a/src/Squidex.Domain.Apps.Entities.MongoDb/Contents/StatusSerializer.cs +++ b/src/Squidex.Domain.Apps.Entities.MongoDb/Contents/StatusSerializer.cs @@ -12,7 +12,7 @@ using Squidex.Domain.Apps.Core.Contents; namespace Squidex.Domain.Apps.Entities.MongoDb.Contents { - public sealed class StatusSerializer : SerializerBase + public sealed class StatusSerializer : SerializerBase { private static volatile int isRegistered; @@ -24,14 +24,14 @@ namespace Squidex.Domain.Apps.Entities.MongoDb.Contents } } - public override Status2 Deserialize(BsonDeserializationContext context, BsonDeserializationArgs args) + public override Status Deserialize(BsonDeserializationContext context, BsonDeserializationArgs args) { var value = context.Reader.ReadString(); - return new Status2(value); + return new Status(value); } - public override void Serialize(BsonSerializationContext context, BsonSerializationArgs args, Status2 value) + public override void Serialize(BsonSerializationContext context, BsonSerializationArgs args, Status value) { context.Writer.WriteString(value.Name); } diff --git a/src/Squidex.Domain.Apps.Entities/Contents/ContentChangedTriggerHandler.cs b/src/Squidex.Domain.Apps.Entities/Contents/ContentChangedTriggerHandler.cs index dff657548..0a155f703 100644 --- a/src/Squidex.Domain.Apps.Entities/Contents/ContentChangedTriggerHandler.cs +++ b/src/Squidex.Domain.Apps.Entities/Contents/ContentChangedTriggerHandler.cs @@ -8,7 +8,6 @@ using System; using System.Threading.Tasks; using Orleans; -using Squidex.Domain.Apps.Core.Contents; using Squidex.Domain.Apps.Core.HandleRules; using Squidex.Domain.Apps.Core.HandleRules.EnrichedEvents; using Squidex.Domain.Apps.Core.Rules.Triggers; @@ -60,23 +59,8 @@ namespace Squidex.Domain.Apps.Entities.Contents case ContentUpdated _: result.Type = EnrichedContentEventType.Updated; break; - case ContentStatusChanged contentStatusChanged: - switch (contentStatusChanged.Change) - { - case StatusChange.Published: - result.Type = EnrichedContentEventType.Published; - break; - case StatusChange.Unpublished: - result.Type = EnrichedContentEventType.Unpublished; - break; - case StatusChange.Archived: - result.Type = EnrichedContentEventType.Archived; - break; - case StatusChange.Restored: - result.Type = EnrichedContentEventType.Restored; - break; - } - + case ContentStatusChanged _: + result.Type = EnrichedContentEventType.StatusChanged; break; } diff --git a/src/Squidex.Domain.Apps.Entities/Contents/ContentEntity.cs b/src/Squidex.Domain.Apps.Entities/Contents/ContentEntity.cs index 9c5a5f3f7..8b1b6aac1 100644 --- a/src/Squidex.Domain.Apps.Entities/Contents/ContentEntity.cs +++ b/src/Squidex.Domain.Apps.Entities/Contents/ContentEntity.cs @@ -8,9 +8,7 @@ using System; using NodaTime; using Squidex.Domain.Apps.Core.Contents; -using Squidex.Domain.Apps.Entities.Contents.Commands; using Squidex.Infrastructure; -using Squidex.Infrastructure.Commands; namespace Squidex.Domain.Apps.Entities.Contents { @@ -41,24 +39,5 @@ namespace Squidex.Domain.Apps.Entities.Contents public Status Status { get; set; } public bool IsPending { get; set; } - - public static ContentEntity Create(CreateContent command, EntityCreatedResult result) - { - var now = SystemClock.Instance.GetCurrentInstant(); - - var response = new ContentEntity - { - Id = command.ContentId, - Data = result.IdOrValue, - Version = result.Version, - Created = now, - CreatedBy = command.Actor, - LastModified = now, - LastModifiedBy = command.Actor, - Status = command.Publish ? Status.Published : Status.Draft - }; - - return response; - } } } \ No newline at end of file diff --git a/src/Squidex.Domain.Apps.Entities/Contents/ContentGrain.cs b/src/Squidex.Domain.Apps.Entities/Contents/ContentGrain.cs index baae5d2dd..0f73ab461 100644 --- a/src/Squidex.Domain.Apps.Entities/Contents/ContentGrain.cs +++ b/src/Squidex.Domain.Apps.Entities/Contents/ContentGrain.cs @@ -32,6 +32,7 @@ namespace Squidex.Domain.Apps.Entities.Contents private readonly IAssetRepository assetRepository; private readonly IContentRepository contentRepository; private readonly IScriptEngine scriptEngine; + private readonly IContentWorkflow contentWorkflow; public ContentGrain( IStore store, @@ -39,17 +40,20 @@ namespace Squidex.Domain.Apps.Entities.Contents IAppProvider appProvider, IAssetRepository assetRepository, IScriptEngine scriptEngine, + IContentWorkflow contentWorkflow, IContentRepository contentRepository) : base(store, log) { Guard.NotNull(appProvider, nameof(appProvider)); Guard.NotNull(scriptEngine, nameof(scriptEngine)); Guard.NotNull(assetRepository, nameof(assetRepository)); + Guard.NotNull(contentWorkflow, nameof(contentWorkflow)); Guard.NotNull(contentRepository, nameof(contentRepository)); this.appProvider = appProvider; this.scriptEngine = scriptEngine; this.assetRepository = assetRepository; + this.contentWorkflow = contentWorkflow; this.contentRepository = contentRepository; } @@ -79,25 +83,27 @@ namespace Squidex.Domain.Apps.Entities.Contents await ctx.ExecuteScriptAsync(s => s.Change, "Published", c, c.Data); } - Create(c); + var status = await contentWorkflow.GetInitialStatusAsync(ctx.Schema); + + Create(c, status); return Snapshot; }); case UpdateContent updateContent: - return UpdateReturnAsync(updateContent, c => + return UpdateReturnAsync(updateContent, async c => { - GuardContent.CanUpdate(c); + await GuardContent.CanUpdate(Snapshot, contentWorkflow, c); - return UpdateAsync(c, x => c.Data, false); + return await UpdateAsync(c, x => c.Data, false); }); case PatchContent patchContent: - return UpdateReturnAsync(patchContent, c => + return UpdateReturnAsync(patchContent, async c => { - GuardContent.CanPatch(c); + await GuardContent.CanPatch(Snapshot, contentWorkflow, c); - return UpdateAsync(c, c.Data.MergeInto, true); + return await UpdateAsync(c, c.Data.MergeInto, true); }); case ChangeContentStatus changeContentStatus: @@ -107,7 +113,7 @@ namespace Squidex.Domain.Apps.Entities.Contents { var ctx = await CreateContext(Snapshot.AppId.Id, Snapshot.SchemaId.Id, Snapshot.Id, () => "Failed to change content."); - GuardContent.CanChangeContentStatus(ctx.Schema, Snapshot.IsPending, Snapshot.Status, c); + await GuardContent.CanChangeStatus(ctx.Schema, Snapshot, contentWorkflow, c); if (c.DueTime.HasValue) { @@ -121,28 +127,11 @@ namespace Squidex.Domain.Apps.Entities.Contents } else { - StatusChange reason; - - if (c.Status == Status.Published) - { - reason = StatusChange.Published; - } - else if (c.Status == Status.Archived) - { - reason = StatusChange.Archived; - } - else if (Snapshot.Status == Status.Published) - { - reason = StatusChange.Unpublished; - } - else - { - reason = StatusChange.Restored; - } - - await ctx.ExecuteScriptAsync(s => s.Change, reason, c, Snapshot.Data); - - ChangeStatus(c, reason); + var operation = c.Status == Status.Published ? "Published" : "StatusChanged"; + + await ctx.ExecuteScriptAsync(s => s.Change, operation, c, Snapshot.Data); + + ChangeStatus(c); } } } @@ -227,13 +216,13 @@ namespace Squidex.Domain.Apps.Entities.Contents return Snapshot; } - public void Create(CreateContent command) + public void Create(CreateContent command, Status status) { - RaiseEvent(SimpleMapper.Map(command, new ContentCreated())); + RaiseEvent(SimpleMapper.Map(command, new ContentCreated { Status = status })); if (command.Publish) { - RaiseEvent(SimpleMapper.Map(command, new ContentStatusChanged { Status = Status.Published, Change = StatusChange.Published })); + RaiseEvent(SimpleMapper.Map(command, new ContentStatusChanged { Status = Status.Published })); } } @@ -272,9 +261,9 @@ namespace Squidex.Domain.Apps.Entities.Contents RaiseEvent(SimpleMapper.Map(command, new ContentStatusScheduled { DueTime = command.DueTime.Value })); } - public void ChangeStatus(ChangeContentStatus command, StatusChange reason) + public void ChangeStatus(ChangeContentStatus command) { - RaiseEvent(SimpleMapper.Map(command, new ContentStatusChanged { Change = reason })); + RaiseEvent(SimpleMapper.Map(command, new ContentStatusChanged())); } private void RaiseEvent(SchemaEvent @event) diff --git a/src/Squidex.Domain.Apps.Entities/Contents/DefaultContentWorkflow.cs b/src/Squidex.Domain.Apps.Entities/Contents/DefaultContentWorkflow.cs index a75dd30a2..b1928480a 100644 --- a/src/Squidex.Domain.Apps.Entities/Contents/DefaultContentWorkflow.cs +++ b/src/Squidex.Domain.Apps.Entities/Contents/DefaultContentWorkflow.cs @@ -7,6 +7,7 @@ using System; using System.Collections.Generic; +using System.Linq; using System.Threading.Tasks; using Squidex.Domain.Apps.Core.Contents; using Squidex.Domain.Apps.Entities.Schemas; @@ -16,25 +17,23 @@ namespace Squidex.Domain.Apps.Entities.Contents { public sealed class DefaultContentWorkflow : IContentWorkflow { - private static readonly Status2 Draft = new Status2("Draft"); - private static readonly Status2 Archived = new Status2("Archived"); - private static readonly Status2 Published = new Status2("Published"); + private static readonly Status[] All = { Status.Archived, Status.Draft, Status.Published }; - private static readonly Dictionary Flow = new Dictionary + private static readonly Dictionary Flow = new Dictionary { - [Draft] = new[] { Published, Archived }, - [Archived] = new[] { Draft }, - [Published] = new[] { Draft, Archived } + [Status.Draft] = new[] { Status.Archived, Status.Published }, + [Status.Archived] = new[] { Status.Draft }, + [Status.Published] = new[] { Status.Draft, Status.Archived } }; - public Task GetInitialStatusAsync(ISchemaEntity schema) + public Task GetInitialStatusAsync(ISchemaEntity schema) { - return Task.FromResult(Draft); + return Task.FromResult(Status.Draft); } - public Task IsValidNextStatus(IContentEntity content, Status2 next) + public Task IsValidNextStatus(IContentEntity content, Status next) { - return TaskHelper.True; + return Task.FromResult(Flow.TryGetValue(content.Status, out var state) && state.Contains(next)); } public Task CanUpdateAsync(IContentEntity content) @@ -42,34 +41,14 @@ namespace Squidex.Domain.Apps.Entities.Contents return TaskHelper.True; } - public Task GetNextsAsync(IContentEntity content) + public Task GetNextsAsync(IContentEntity content) { - Status2 statusToCheck; - - switch (content.Status) - { - case Status.Draft: - statusToCheck = Draft; - break; - case Status.Archived: - statusToCheck = Archived; - break; - case Status.Published: - statusToCheck = Published; - break; - default: - { - statusToCheck = Draft; - break; - } - } - - return Task.FromResult(Flow.TryGetValue(statusToCheck, out var result) ? result : Array.Empty()); + return Task.FromResult(Flow.TryGetValue(content.Status, out var result) ? result : Array.Empty()); } - public Task GetAllAsync(ISchemaEntity schema) + public Task GetAllAsync(ISchemaEntity schema) { - return Task.FromResult(new[] { Draft, Archived, Published } ); + return Task.FromResult(All); } } } diff --git a/src/Squidex.Domain.Apps.Entities/Contents/GraphQL/Types/AllTypes.cs b/src/Squidex.Domain.Apps.Entities/Contents/GraphQL/Types/AllTypes.cs index 5e1b6c973..8f3207ebf 100644 --- a/src/Squidex.Domain.Apps.Entities/Contents/GraphQL/Types/AllTypes.cs +++ b/src/Squidex.Domain.Apps.Entities/Contents/GraphQL/Types/AllTypes.cs @@ -28,8 +28,6 @@ namespace Squidex.Domain.Apps.Entities.Contents.GraphQL.Types public static readonly IGraphType Float = new FloatGraphType(); - public static readonly IGraphType Status = new EnumerationGraphType(); - public static readonly IGraphType String = new StringGraphType(); public static readonly IGraphType Boolean = new BooleanGraphType(); @@ -46,8 +44,6 @@ namespace Squidex.Domain.Apps.Entities.Contents.GraphQL.Types public static readonly IGraphType NonNullBoolean = new NonNullGraphType(Boolean); - public static readonly IGraphType NonNullStatusType = new NonNullGraphType(Status); - public static readonly IGraphType NoopDate = new NoopGraphType(Date); public static readonly IGraphType NoopJson = new NoopGraphType(Json); diff --git a/src/Squidex.Domain.Apps.Entities/Contents/GraphQL/Types/ContentGraphType.cs b/src/Squidex.Domain.Apps.Entities/Contents/GraphQL/Types/ContentGraphType.cs index ec8878874..a6d876742 100644 --- a/src/Squidex.Domain.Apps.Entities/Contents/GraphQL/Types/ContentGraphType.cs +++ b/src/Squidex.Domain.Apps.Entities/Contents/GraphQL/Types/ContentGraphType.cs @@ -73,8 +73,8 @@ namespace Squidex.Domain.Apps.Entities.Contents.GraphQL.Types AddField(new FieldType { Name = "status", - ResolvedType = AllTypes.NonNullStatusType, - Resolver = Resolve(x => x.Status), + ResolvedType = AllTypes.NonNullString, + Resolver = Resolve(x => x.Status.Name.ToUpperInvariant()), Description = $"The the status of the {schemaName} content." }); diff --git a/src/Squidex.Domain.Apps.Entities/Contents/Guards/GuardContent.cs b/src/Squidex.Domain.Apps.Entities/Contents/Guards/GuardContent.cs index 379bd601f..35a3acca7 100644 --- a/src/Squidex.Domain.Apps.Entities/Contents/Guards/GuardContent.cs +++ b/src/Squidex.Domain.Apps.Entities/Contents/Guards/GuardContent.cs @@ -5,6 +5,7 @@ // All rights reserved. Licensed under the MIT license. // ========================================================================== +using System.Threading.Tasks; using NodaTime; using Squidex.Domain.Apps.Core.Contents; using Squidex.Domain.Apps.Entities.Contents.Commands; @@ -30,7 +31,7 @@ namespace Squidex.Domain.Apps.Entities.Contents.Guards } } - public static void CanUpdate(UpdateContent command) + public static async Task CanUpdate(IContentEntity content, IContentWorkflow contentWorkflow, UpdateContent command) { Guard.NotNull(command, nameof(command)); @@ -38,9 +39,11 @@ namespace Squidex.Domain.Apps.Entities.Contents.Guards { ValidateData(command, e); }); + + await ValidateCanUpdate(content, contentWorkflow); } - public static void CanPatch(PatchContent command) + public static async Task CanPatch(IContentEntity content, IContentWorkflow contentWorkflow, PatchContent command) { Guard.NotNull(command, nameof(command)); @@ -48,6 +51,8 @@ namespace Squidex.Domain.Apps.Entities.Contents.Guards { ValidateData(command, e); }); + + await ValidateCanUpdate(content, contentWorkflow); } public static void CanDiscardChanges(bool isPending, DiscardChanges command) @@ -60,33 +65,29 @@ namespace Squidex.Domain.Apps.Entities.Contents.Guards } } - public static void CanChangeContentStatus(ISchemaEntity schema, bool isPending, Status status, ChangeContentStatus command) + public static Task CanChangeStatus(ISchemaEntity schema, IContentEntity content, IContentWorkflow contentWorkflow, ChangeContentStatus command) { Guard.NotNull(command, nameof(command)); if (schema.SchemaDef.IsSingleton && command.Status != Status.Published) { - throw new DomainException("Singleton content archived or unpublished."); + throw new DomainException("Singleton content cannot be changed."); } - Validate.It(() => "Cannot change status.", e => + return Validate.It(() => "Cannot change status.", async e => { - if (!StatusFlow.Exists(command.Status)) + if (!await contentWorkflow.IsValidNextStatus(content, command.Status)) { - e(Not.Valid("Status"), nameof(command.Status)); - } - else if (!StatusFlow.CanChange(status, command.Status)) - { - if (status == command.Status && status == Status.Published) + if (content.Status == command.Status && content.Status == Status.Published) { - if (!isPending) + if (!content.IsPending) { e("Content has no changes to publish.", nameof(command.Status)); } } else { - e($"Cannot change status from {status} to {command.Status}.", nameof(command.Status)); + e($"Cannot change status from {content.Status} to {command.Status}.", nameof(command.Status)); } } @@ -114,5 +115,13 @@ namespace Squidex.Domain.Apps.Entities.Contents.Guards e(Not.Defined("Data"), nameof(command.Data)); } } + + private static async Task ValidateCanUpdate(IContentEntity content, IContentWorkflow contentWorkflow) + { + if (!await contentWorkflow.CanUpdateAsync(content)) + { + throw new DomainException($"The workflow does not allow updates at status {content.Status}"); + } + } } } diff --git a/src/Squidex.Domain.Apps.Entities/Contents/IContentWorkflow.cs b/src/Squidex.Domain.Apps.Entities/Contents/IContentWorkflow.cs index e2b21d0af..06de365be 100644 --- a/src/Squidex.Domain.Apps.Entities/Contents/IContentWorkflow.cs +++ b/src/Squidex.Domain.Apps.Entities/Contents/IContentWorkflow.cs @@ -13,14 +13,14 @@ namespace Squidex.Domain.Apps.Entities.Contents { public interface IContentWorkflow { - Task GetInitialStatusAsync(ISchemaEntity schema); + Task GetInitialStatusAsync(ISchemaEntity schema); - Task IsValidNextStatus(IContentEntity content, Status2 next); + Task IsValidNextStatus(IContentEntity content, Status next); Task CanUpdateAsync(IContentEntity content); - Task GetNextsAsync(IContentEntity content); + Task GetNextsAsync(IContentEntity content); - Task GetAllAsync(ISchemaEntity schema); + Task GetAllAsync(ISchemaEntity schema); } } diff --git a/src/Squidex.Domain.Apps.Entities/Contents/State/ContentState.cs b/src/Squidex.Domain.Apps.Entities/Contents/State/ContentState.cs index 1f2169431..0f0234dc9 100644 --- a/src/Squidex.Domain.Apps.Entities/Contents/State/ContentState.cs +++ b/src/Squidex.Domain.Apps.Entities/Contents/State/ContentState.cs @@ -50,6 +50,11 @@ namespace Squidex.Domain.Apps.Entities.Contents.State SimpleMapper.Map(@event, this); UpdateData(null, @event.Data, false); + + if (Status == default) + { + Status = Status.Draft; + } } protected void On(ContentChangesPublished @event) diff --git a/src/Squidex.Domain.Apps.Events/Contents/ContentCreated.cs b/src/Squidex.Domain.Apps.Events/Contents/ContentCreated.cs index ed06a71ec..317b3b176 100644 --- a/src/Squidex.Domain.Apps.Events/Contents/ContentCreated.cs +++ b/src/Squidex.Domain.Apps.Events/Contents/ContentCreated.cs @@ -13,6 +13,8 @@ namespace Squidex.Domain.Apps.Events.Contents [EventType(nameof(ContentCreated))] public sealed class ContentCreated : ContentEvent { + public Status Status { get; set; } + public NamedContentData Data { get; set; } } } diff --git a/src/Squidex.Domain.Apps.Events/Contents/ContentStatusChanged.cs b/src/Squidex.Domain.Apps.Events/Contents/ContentStatusChanged.cs index 81b95e5fb..2c97f5902 100644 --- a/src/Squidex.Domain.Apps.Events/Contents/ContentStatusChanged.cs +++ b/src/Squidex.Domain.Apps.Events/Contents/ContentStatusChanged.cs @@ -13,8 +13,6 @@ namespace Squidex.Domain.Apps.Events.Contents [EventType(nameof(ContentStatusChanged))] public sealed class ContentStatusChanged : ContentEvent { - public StatusChange? Change { get; set; } - public Status Status { get; set; } } } diff --git a/src/Squidex/Areas/Api/Controllers/Contents/ContentsController.cs b/src/Squidex/Areas/Api/Controllers/Contents/ContentsController.cs index a8a4d1e87..833c67dbe 100644 --- a/src/Squidex/Areas/Api/Controllers/Contents/ContentsController.cs +++ b/src/Squidex/Areas/Api/Controllers/Contents/ContentsController.cs @@ -373,7 +373,7 @@ namespace Squidex.Areas.Api.Controllers.Contents { await contentQuery.GetSchemaOrThrowAsync(Context(), name); - if (!this.HasPermission(Helper.StatusPermission(app, name, Status2.Published))) + if (!this.HasPermission(Helper.StatusPermission(app, name, Status.Published))) { return new ForbidResult(); } diff --git a/src/Squidex/Areas/Api/Controllers/Contents/Helper.cs b/src/Squidex/Areas/Api/Controllers/Contents/Helper.cs index be1f7ef46..8644c925a 100644 --- a/src/Squidex/Areas/Api/Controllers/Contents/Helper.cs +++ b/src/Squidex/Areas/Api/Controllers/Contents/Helper.cs @@ -14,13 +14,6 @@ namespace Squidex.Areas.Api.Controllers.Contents public static class Helper { public static Permission StatusPermission(string app, string schema, Status status) - { - var id = Permissions.AppContentsStatus.Replace("{status}", status.ToString()); - - return Permissions.ForApp(id, app, schema); - } - - public static Permission StatusPermission(string app, string schema, Status2 status) { var id = Permissions.AppContentsStatus.Replace("{status}", status.Name); diff --git a/src/Squidex/Areas/Api/Controllers/Contents/Models/ContentDto.cs b/src/Squidex/Areas/Api/Controllers/Contents/Models/ContentDto.cs index c699d7017..c83638142 100644 --- a/src/Squidex/Areas/Api/Controllers/Contents/Models/ContentDto.cs +++ b/src/Squidex/Areas/Api/Controllers/Contents/Models/ContentDto.cs @@ -131,7 +131,7 @@ namespace Squidex.Areas.Api.Controllers.Contents.Models AddPutLink("draft/discard", controller.Url(x => nameof(x.DiscardDraft), values)); } - if (controller.HasPermission(Helper.StatusPermission(app, schema, Status2.Published))) + if (controller.HasPermission(Helper.StatusPermission(app, schema, Status.Published))) { AddPutLink("draft/publish", controller.Url(x => nameof(x.PutContentStatus), values)); } @@ -146,7 +146,7 @@ namespace Squidex.Areas.Api.Controllers.Contents.Models if (Status == Status.Published) { - AddPutLink("draft/propose", controller.Url(x => nameof(x.PutContent), values) + "?asDraft=true"); + AddPutLink("draft/propose", controller.Url((ContentsController x) => nameof(x.PutContent), values) + "?asDraft=true"); } AddPatchLink("patch", controller.Url(x => nameof(x.PatchContent), values)); diff --git a/src/Squidex/Areas/Api/Controllers/Contents/Models/ContentsDto.cs b/src/Squidex/Areas/Api/Controllers/Contents/Models/ContentsDto.cs index 928cc12b2..afcecb7fe 100644 --- a/src/Squidex/Areas/Api/Controllers/Contents/Models/ContentsDto.cs +++ b/src/Squidex/Areas/Api/Controllers/Contents/Models/ContentsDto.cs @@ -35,7 +35,7 @@ namespace Squidex.Areas.Api.Controllers.Contents.Models /// The possible statuses. /// [Required] - public Status2[] Statuses { get; set; } + public Status[] Statuses { get; set; } public string ToEtag() { diff --git a/tests/Squidex.Domain.Apps.Core.Tests/Model/Contents/StatusFlowTests.cs b/tests/Squidex.Domain.Apps.Core.Tests/Model/Contents/StatusFlowTests.cs deleted file mode 100644 index 30126894c..000000000 --- a/tests/Squidex.Domain.Apps.Core.Tests/Model/Contents/StatusFlowTests.cs +++ /dev/null @@ -1,34 +0,0 @@ -// ========================================================================== -// Squidex Headless CMS -// ========================================================================== -// Copyright (c) Squidex UG (haftungsbeschränkt) -// All rights reserved. Licensed under the MIT license. -// ========================================================================== - -using Squidex.Domain.Apps.Core.Contents; -using Xunit; - -namespace Squidex.Domain.Apps.Core.Model.Contents -{ - public class StatusFlowTests - { - [Fact] - public void Should_make_tests() - { - Assert.True(StatusFlow.Exists(Status.Draft)); - Assert.True(StatusFlow.Exists(Status.Archived)); - Assert.True(StatusFlow.Exists(Status.Published)); - - Assert.True(StatusFlow.CanChange(Status.Draft, Status.Archived)); - Assert.True(StatusFlow.CanChange(Status.Draft, Status.Published)); - - Assert.True(StatusFlow.CanChange(Status.Published, Status.Draft)); - Assert.True(StatusFlow.CanChange(Status.Published, Status.Archived)); - - Assert.True(StatusFlow.CanChange(Status.Archived, Status.Draft)); - - Assert.False(StatusFlow.Exists((Status)int.MaxValue)); - Assert.False(StatusFlow.CanChange(Status.Archived, Status.Published)); - } - } -} diff --git a/tests/Squidex.Domain.Apps.Core.Tests/Model/Contents/StatusTests.cs b/tests/Squidex.Domain.Apps.Core.Tests/Model/Contents/StatusTests.cs index 5abdd5f2d..138e399c1 100644 --- a/tests/Squidex.Domain.Apps.Core.Tests/Model/Contents/StatusTests.cs +++ b/tests/Squidex.Domain.Apps.Core.Tests/Model/Contents/StatusTests.cs @@ -15,16 +15,34 @@ namespace Squidex.Domain.Apps.Core.Model.Contents [Fact] public void Should_initialize_status_from_string() { - var result = new Status2("Draft"); + var result = new Status("Custom"); + + Assert.Equal("Custom", result.Name); + Assert.Equal("Custom", result.ToString()); + } + + [Fact] + public void Should_provide_draft_status() + { + var result = Status.Draft; Assert.Equal("Draft", result.Name); Assert.Equal("Draft", result.ToString()); } + [Fact] + public void Should_provide_archived_status() + { + var result = Status.Archived; + + Assert.Equal("Archived", result.Name); + Assert.Equal("Archived", result.ToString()); + } + [Fact] public void Should_provide_published_status() { - var result = Status2.Published; + var result = Status.Published; Assert.Equal("Published", result.Name); Assert.Equal("Published", result.ToString()); @@ -33,10 +51,10 @@ namespace Squidex.Domain.Apps.Core.Model.Contents [Fact] public void Should_make_correct_equal_comparisons() { - var status_1_a = new Status2("Draft"); - var status_1_b = new Status2("Draft"); + var status_1_a = Status.Draft; + var status_1_b = Status.Draft; - var status2_a = new Status2("Published"); + var status2_a = Status.Published; Assert.Equal(status_1_a, status_1_b); Assert.Equal(status_1_a.GetHashCode(), status_1_b.GetHashCode()); @@ -45,12 +63,18 @@ namespace Squidex.Domain.Apps.Core.Model.Contents Assert.NotEqual(status_1_a, status2_a); Assert.NotEqual(status_1_a.GetHashCode(), status2_a.GetHashCode()); Assert.False(status_1_a.Equals((object)status2_a)); + + Assert.True(status_1_a == status_1_b); + Assert.True(status_1_a != status2_a); + + Assert.False(status_1_a != status_1_b); + Assert.False(status_1_a == status2_a); } [Fact] public void Should_serialize_and_deserialize() { - var status = new Status2("Draft"); + var status = Status.Draft; var serialized = status.SerializeAndDeserialize(); diff --git a/tests/Squidex.Domain.Apps.Entities.Tests/Contents/ContentChangedTriggerHandlerTests.cs b/tests/Squidex.Domain.Apps.Entities.Tests/Contents/ContentChangedTriggerHandlerTests.cs index 03b547993..1e49dc457 100644 --- a/tests/Squidex.Domain.Apps.Entities.Tests/Contents/ContentChangedTriggerHandlerTests.cs +++ b/tests/Squidex.Domain.Apps.Entities.Tests/Contents/ContentChangedTriggerHandlerTests.cs @@ -11,7 +11,6 @@ using System.Collections.ObjectModel; using System.Threading.Tasks; using FakeItEasy; using Orleans; -using Squidex.Domain.Apps.Core.Contents; using Squidex.Domain.Apps.Core.HandleRules; using Squidex.Domain.Apps.Core.HandleRules.EnrichedEvents; using Squidex.Domain.Apps.Core.Rules.Triggers; @@ -54,10 +53,7 @@ namespace Squidex.Domain.Apps.Entities.Contents new object[] { new ContentCreated(), EnrichedContentEventType.Created }, new object[] { new ContentUpdated(), EnrichedContentEventType.Updated }, new object[] { new ContentDeleted(), EnrichedContentEventType.Deleted }, - new object[] { new ContentStatusChanged { Change = StatusChange.Archived }, EnrichedContentEventType.Archived }, - new object[] { new ContentStatusChanged { Change = StatusChange.Published }, EnrichedContentEventType.Published }, - new object[] { new ContentStatusChanged { Change = StatusChange.Restored }, EnrichedContentEventType.Restored }, - new object[] { new ContentStatusChanged { Change = StatusChange.Unpublished }, EnrichedContentEventType.Unpublished } + new object[] { new ContentStatusChanged(), EnrichedContentEventType.StatusChanged } }; [Theory] diff --git a/tests/Squidex.Domain.Apps.Entities.Tests/Contents/ContentGrainTests.cs b/tests/Squidex.Domain.Apps.Entities.Tests/Contents/ContentGrainTests.cs index f5a96de1b..8edba81dd 100644 --- a/tests/Squidex.Domain.Apps.Entities.Tests/Contents/ContentGrainTests.cs +++ b/tests/Squidex.Domain.Apps.Entities.Tests/Contents/ContentGrainTests.cs @@ -33,6 +33,8 @@ namespace Squidex.Domain.Apps.Entities.Contents { private readonly ISchemaEntity schema = A.Fake(); private readonly IScriptEngine scriptEngine = A.Fake(); + private readonly IContentRepository contentRepository = A.Dummy(); + private readonly IContentWorkflow contentWorkflow = A.Fake(); private readonly IAppProvider appProvider = A.Fake(); private readonly IAppEntity app = A.Fake(); private readonly LanguagesConfig languagesConfig = LanguagesConfig.Build(Language.DE); @@ -100,9 +102,15 @@ namespace Squidex.Domain.Apps.Entities.Contents A.CallTo(() => scriptEngine.ExecuteAndTransform(A.Ignored, A.Ignored)) .ReturnsLazily(x => x.GetArgument(0).Data); + A.CallTo(() => contentWorkflow.CanUpdateAsync(A.Ignored)) + .Returns(true); + + A.CallTo(() => contentWorkflow.IsValidNextStatus(A.Ignored, A.Ignored)) + .Returns(true); + patched = patch.MergeInto(data); - sut = new ContentGrain(Store, A.Dummy(), appProvider, A.Dummy(), scriptEngine, A.Dummy()); + sut = new ContentGrain(Store, A.Dummy(), appProvider, A.Dummy(), scriptEngine, contentWorkflow, contentRepository); sut.ActivateAsync(Id).Wait(); } @@ -135,6 +143,26 @@ namespace Squidex.Domain.Apps.Entities.Contents .MustNotHaveHappened(); } + [Fact] + public async Task Create_should_create_events_and_update_state_with_custom_initial_status() + { + var command = new CreateContent { Data = data }; + + A.CallTo(() => contentWorkflow.GetInitialStatusAsync(schema)) + .Returns(Status.Archived); + + var result = await sut.ExecuteAsync(CreateContentCommand(command)); + + result.ShouldBeEquivalent(sut.Snapshot); + + Assert.Equal(Status.Archived, sut.Snapshot.Status); + + LastEvents + .ShouldHaveSameEvents( + CreateContentEvent(new ContentCreated { Data = data, Status = Status.Archived }) + ); + } + [Fact] public async Task Create_should_also_publish() { @@ -147,7 +175,7 @@ namespace Squidex.Domain.Apps.Entities.Contents LastEvents .ShouldHaveSameEvents( CreateContentEvent(new ContentCreated { Data = data }), - CreateContentEvent(new ContentStatusChanged { Status = Status.Published, Change = StatusChange.Published }) + CreateContentEvent(new ContentStatusChanged { Status = Status.Published }) ); A.CallTo(() => scriptEngine.ExecuteAndTransform(A.Ignored, "")) @@ -315,7 +343,7 @@ namespace Squidex.Domain.Apps.Entities.Contents LastEvents .ShouldHaveSameEvents( - CreateContentEvent(new ContentStatusChanged { Status = Status.Published, Change = StatusChange.Published }) + CreateContentEvent(new ContentStatusChanged { Status = Status.Published }) ); A.CallTo(() => scriptEngine.Execute(A.Ignored, "")) @@ -337,7 +365,7 @@ namespace Squidex.Domain.Apps.Entities.Contents LastEvents .ShouldHaveSameEvents( - CreateContentEvent(new ContentStatusChanged { Status = Status.Archived, Change = StatusChange.Archived }) + CreateContentEvent(new ContentStatusChanged { Status = Status.Archived }) ); A.CallTo(() => scriptEngine.Execute(A.Ignored, "")) @@ -360,7 +388,7 @@ namespace Squidex.Domain.Apps.Entities.Contents LastEvents .ShouldHaveSameEvents( - CreateContentEvent(new ContentStatusChanged { Status = Status.Draft, Change = StatusChange.Unpublished }) + CreateContentEvent(new ContentStatusChanged { Status = Status.Draft }) ); A.CallTo(() => scriptEngine.Execute(A.Ignored, "")) @@ -383,7 +411,7 @@ namespace Squidex.Domain.Apps.Entities.Contents LastEvents .ShouldHaveSameEvents( - CreateContentEvent(new ContentStatusChanged { Status = Status.Draft, Change = StatusChange.Restored }) + CreateContentEvent(new ContentStatusChanged { Status = Status.Draft }) ); A.CallTo(() => scriptEngine.Execute(A.Ignored, "")) @@ -448,6 +476,9 @@ namespace Squidex.Domain.Apps.Entities.Contents var command = new ChangeContentStatus { Status = Status.Draft, JobId = sut.Snapshot.ScheduleJob.Id }; + A.CallTo(() => contentWorkflow.IsValidNextStatus(sut.Snapshot, command.Status)) + .Returns(false); + var result = await sut.ExecuteAsync(CreateContentCommand(command)); result.ShouldBeEquivalent(sut.Snapshot); diff --git a/tests/Squidex.Domain.Apps.Entities.Tests/Contents/ContentQueryServiceTests.cs b/tests/Squidex.Domain.Apps.Entities.Tests/Contents/ContentQueryServiceTests.cs index 546454b83..e6fb4334b 100644 --- a/tests/Squidex.Domain.Apps.Entities.Tests/Contents/ContentQueryServiceTests.cs +++ b/tests/Squidex.Domain.Apps.Entities.Tests/Contents/ContentQueryServiceTests.cs @@ -520,7 +520,12 @@ namespace Squidex.Domain.Apps.Entities.Contents .Returns((ISchemaEntity)null); } - private IContentEntity CreateContent(Guid id, Status status = Status.Published) + private IContentEntity CreateContent(Guid id) + { + return CreateContent(id, Status.Published); + } + + private IContentEntity CreateContent(Guid id, Status status) { var content = A.Fake(); diff --git a/tests/Squidex.Domain.Apps.Entities.Tests/Contents/DefaultContentWorkflowTests.cs b/tests/Squidex.Domain.Apps.Entities.Tests/Contents/DefaultContentWorkflowTests.cs index 25d9d8bb8..6a1b5f32a 100644 --- a/tests/Squidex.Domain.Apps.Entities.Tests/Contents/DefaultContentWorkflowTests.cs +++ b/tests/Squidex.Domain.Apps.Entities.Tests/Contents/DefaultContentWorkflowTests.cs @@ -21,15 +21,15 @@ namespace Squidex.Domain.Apps.Entities.Contents { var result = await sut.GetInitialStatusAsync(null); - Assert.Equal(new Status2("Draft"), result); + Assert.Equal(Status.Draft, result); } [Fact] public async Task Should_check_is_valid_next() { - var entity = CreateMockContentEntity(Status.Draft); + var entity = CreateContent(Status.Published); - var result = await sut.IsValidNextStatus(entity, new Status2("Draft")); + var result = await sut.IsValidNextStatus(entity, Status.Draft); Assert.True(result); } @@ -37,7 +37,7 @@ namespace Squidex.Domain.Apps.Entities.Contents [Fact] public async Task Should_always_be_able_to_update() { - var entity = CreateMockContentEntity(Status.Draft); + var entity = CreateContent(Status.Published); var result = await sut.CanUpdateAsync(entity); @@ -47,9 +47,9 @@ namespace Squidex.Domain.Apps.Entities.Contents [Fact] public async Task Should_get_next_statuses_for_draft() { - var content = CreateMockContentEntity(Status.Draft); + var content = CreateContent(Status.Draft); - var expected = new[] { new Status2("Published"), new Status2("Archived") }; + var expected = new[] { Status.Archived, Status.Published }; var result = await sut.GetNextsAsync(content); @@ -59,9 +59,9 @@ namespace Squidex.Domain.Apps.Entities.Contents [Fact] public async Task Should_get_next_statuses_for_archived() { - var content = CreateMockContentEntity(Status.Archived); + var content = CreateContent(Status.Archived); - var expected = new[] { new Status2("Draft") }; + var expected = new[] { Status.Draft }; var result = await sut.GetNextsAsync(content); @@ -71,9 +71,9 @@ namespace Squidex.Domain.Apps.Entities.Contents [Fact] public async Task Should_get_next_statuses_for_published() { - var content = CreateMockContentEntity(Status.Published); + var content = CreateContent(Status.Published); - var expected = new[] { new Status2("Draft"), new Status2("Archived") }; + var expected = new[] { Status.Draft, Status.Archived }; var result = await sut.GetNextsAsync(content); @@ -83,14 +83,14 @@ namespace Squidex.Domain.Apps.Entities.Contents [Fact] public async Task Should_return_all_statuses() { - var expected = new[] { new Status2("Draft"), new Status2("Archived"), new Status2("Published") }; + var expected = new[] { Status.Archived, Status.Draft, Status.Published }; var result = await sut.GetAllAsync(null); Assert.Equal(expected, result); } - private IContentEntity CreateMockContentEntity(Status status) + private IContentEntity CreateContent(Status status) { var content = A.Fake(); diff --git a/tests/Squidex.Domain.Apps.Entities.Tests/Contents/GraphQL/GraphQLTestBase.cs b/tests/Squidex.Domain.Apps.Entities.Tests/Contents/GraphQL/GraphQLTestBase.cs index d3f6b5ea1..cfc9e817b 100644 --- a/tests/Squidex.Domain.Apps.Entities.Tests/Contents/GraphQL/GraphQLTestBase.cs +++ b/tests/Squidex.Domain.Apps.Entities.Tests/Contents/GraphQL/GraphQLTestBase.cs @@ -159,7 +159,8 @@ namespace Squidex.Domain.Apps.Entities.Contents.GraphQL LastModified = now, LastModifiedBy = new RefToken(RefTokenType.Subject, "user2"), Data = data, - DataDraft = dataDraft + DataDraft = dataDraft, + Status = Status.Draft }; return content; diff --git a/tests/Squidex.Domain.Apps.Entities.Tests/Contents/Guard/GuardContentTests.cs b/tests/Squidex.Domain.Apps.Entities.Tests/Contents/Guard/GuardContentTests.cs index 5dda8794d..1f1eb91cb 100644 --- a/tests/Squidex.Domain.Apps.Entities.Tests/Contents/Guard/GuardContentTests.cs +++ b/tests/Squidex.Domain.Apps.Entities.Tests/Contents/Guard/GuardContentTests.cs @@ -5,6 +5,7 @@ // All rights reserved. Licensed under the MIT license. // ========================================================================== +using System.Threading.Tasks; using FakeItEasy; using NodaTime; using Squidex.Domain.Apps.Core.Contents; @@ -21,6 +22,7 @@ namespace Squidex.Domain.Apps.Entities.Contents.Guard public class GuardContentTests { private readonly ISchemaEntity schema = A.Fake(); + private readonly IContentWorkflow contentWorkflow = A.Fake(); private readonly Instant dueTimeInPast = SystemClock.Instance.GetCurrentInstant().Minus(Duration.FromHours(1)); [Fact] @@ -65,119 +67,155 @@ namespace Squidex.Domain.Apps.Entities.Contents.Guard } [Fact] - public void CanUpdate_should_throw_exception_if_data_is_null() + public async Task CanUpdate_should_throw_exception_if_data_is_null() { SetupSingleton(false); + SetupCanUpdate(true); + var content = CreateContent(Status.Draft, false); var command = new UpdateContent(); - ValidationAssert.Throws(() => GuardContent.CanUpdate(command), + await ValidationAssert.ThrowsAsync(() => GuardContent.CanUpdate(content, contentWorkflow, command), new ValidationError("Data is required.", "Data")); } [Fact] - public void CanUpdate_should_not_throw_exception_if_data_is_not_null() + public async Task CanUpdate_should_throw_exception_if_workflow_blocks_it() { SetupSingleton(false); + SetupCanUpdate(false); + var content = CreateContent(Status.Draft, false); var command = new UpdateContent { Data = new NamedContentData() }; - GuardContent.CanUpdate(command); + await Assert.ThrowsAsync(() => GuardContent.CanUpdate(content, contentWorkflow, command)); } [Fact] - public void CanPatch_should_throw_exception_if_data_is_null() + public async Task CanUpdate_should_not_throw_exception_if_data_is_not_null() { SetupSingleton(false); + SetupCanUpdate(true); + var content = CreateContent(Status.Draft, false); + var command = new UpdateContent { Data = new NamedContentData() }; + + await GuardContent.CanUpdate(content, contentWorkflow, command); + } + + [Fact] + public async Task CanPatch_should_throw_exception_if_data_is_null() + { + SetupSingleton(false); + SetupCanUpdate(true); + + var content = CreateContent(Status.Draft, false); var command = new PatchContent(); - ValidationAssert.Throws(() => GuardContent.CanPatch(command), + await ValidationAssert.ThrowsAsync(() => GuardContent.CanPatch(content, contentWorkflow, command), new ValidationError("Data is required.", "Data")); } [Fact] - public void CanPatch_should_not_throw_exception_if_data_is_not_null() + public async Task CanPatch_should_throw_exception_if_workflow_blocks_it() { SetupSingleton(false); + SetupCanUpdate(false); + var content = CreateContent(Status.Draft, false); var command = new PatchContent { Data = new NamedContentData() }; - GuardContent.CanPatch(command); + await Assert.ThrowsAsync(() => GuardContent.CanPatch(content, contentWorkflow, command)); } [Fact] - public void CanChangeContentStatus_should_throw_exception_if_status_not_valid() + public async Task CanPatch_should_not_throw_exception_if_data_is_not_null() { SetupSingleton(false); + SetupCanUpdate(true); - var command = new ChangeContentStatus { Status = (Status)10 }; + var content = CreateContent(Status.Draft, false); + var command = new PatchContent { Data = new NamedContentData() }; - ValidationAssert.Throws(() => GuardContent.CanChangeContentStatus(schema, false, Status.Archived, command), - new ValidationError("Status is not a valid value.", "Status")); + await GuardContent.CanPatch(content, contentWorkflow, command); } [Fact] - public void CanChangeContentStatus_should_throw_exception_if_status_flow_not_valid() + public async Task CanChangeStatus_should_throw_exception_if_publishing_without_pending_changes() { SetupSingleton(false); + var content = CreateContent(Status.Published, false); var command = new ChangeContentStatus { Status = Status.Published }; - ValidationAssert.Throws(() => GuardContent.CanChangeContentStatus(schema, false, Status.Archived, command), - new ValidationError("Cannot change status from Archived to Published.", "Status")); + await ValidationAssert.ThrowsAsync(() => GuardContent.CanChangeStatus(schema, content, contentWorkflow, command), + new ValidationError("Content has no changes to publish.", "Status")); } [Fact] - public void CanChangeContentStatus_should_throw_exception_if_due_date_in_past() + public async Task CanChangeStatus_should_throw_exception_if_singleton() { - SetupSingleton(false); + SetupSingleton(true); - var command = new ChangeContentStatus { Status = Status.Published, DueTime = dueTimeInPast }; + var content = CreateContent(Status.Published, false); + var command = new ChangeContentStatus { Status = Status.Draft }; - ValidationAssert.Throws(() => GuardContent.CanChangeContentStatus(schema, false, Status.Draft, command), - new ValidationError("Due time must be in the future.", "DueTime")); + await Assert.ThrowsAsync(() => GuardContent.CanChangeStatus(schema, content, contentWorkflow, command)); } [Fact] - public void CanChangeContentStatus_should_throw_exception_if_publishing_without_pending_changes() + public async Task CanChangeStatus_should_not_throw_exception_if_publishing_with_pending_changes() { - SetupSingleton(false); + SetupSingleton(true); + var content = CreateContent(Status.Published, true); var command = new ChangeContentStatus { Status = Status.Published }; - ValidationAssert.Throws(() => GuardContent.CanChangeContentStatus(schema, false, Status.Published, command), - new ValidationError("Content has no changes to publish.", "Status")); + await GuardContent.CanChangeStatus(schema, content, contentWorkflow, command); } [Fact] - public void CanChangeContentStatus_should_throw_exception_if_singleton() + public async Task CanChangeStatus_should_throw_exception_if_due_date_in_past() { - SetupSingleton(true); + SetupSingleton(false); - var command = new ChangeContentStatus { Status = Status.Draft }; + var content = CreateContent(Status.Draft, false); + var command = new ChangeContentStatus { Status = Status.Published, DueTime = dueTimeInPast }; + + A.CallTo(() => contentWorkflow.IsValidNextStatus(content, command.Status)) + .Returns(true); - Assert.Throws(() => GuardContent.CanChangeContentStatus(schema, false, Status.Published, command)); + await ValidationAssert.ThrowsAsync(() => GuardContent.CanChangeStatus(schema, content, contentWorkflow, command), + new ValidationError("Due time must be in the future.", "DueTime")); } [Fact] - public void CanChangeContentStatus_should_not_throw_exception_if_publishing_with_pending_changes() + public async Task CanChangeStatus_should_throw_exception_if_status_flow_not_valid() { - SetupSingleton(true); + SetupSingleton(false); + var content = CreateContent(Status.Draft, false); var command = new ChangeContentStatus { Status = Status.Published }; - GuardContent.CanChangeContentStatus(schema, true, Status.Published, command); + A.CallTo(() => contentWorkflow.IsValidNextStatus(content, command.Status)) + .Returns(false); + + await ValidationAssert.ThrowsAsync(() => GuardContent.CanChangeStatus(schema, content, contentWorkflow, command), + new ValidationError("Cannot change status from Draft to Published.", "Status")); } [Fact] - public void CanChangeContentStatus_should_not_throw_exception_if_status_flow_valid() + public async Task CanChangeStatus_should_not_throw_exception_if_status_flow_valid() { SetupSingleton(false); + var content = CreateContent(Status.Draft, false); var command = new ChangeContentStatus { Status = Status.Published }; - GuardContent.CanChangeContentStatus(schema, false, Status.Draft, command); + A.CallTo(() => contentWorkflow.IsValidNextStatus(content, command.Status)) + .Returns(true); + + await GuardContent.CanChangeStatus(schema, content, contentWorkflow, command); } [Fact] @@ -218,10 +256,26 @@ namespace Squidex.Domain.Apps.Entities.Contents.Guard GuardContent.CanDelete(schema, command); } + private void SetupCanUpdate(bool canUpdate) + { + A.CallTo(() => contentWorkflow.CanUpdateAsync(A.Ignored)) + .Returns(canUpdate); + } + private void SetupSingleton(bool isSingleton) { A.CallTo(() => schema.SchemaDef) .Returns(new Schema("schema", isSingleton: isSingleton)); } + + private IContentEntity CreateContent(Status status, bool isPending) + { + var content = A.Fake(); + + A.CallTo(() => content.Status).Returns(status); + A.CallTo(() => content.IsPending).Returns(isPending); + + return content; + } } } diff --git a/tests/Squidex.Domain.Apps.Entities.Tests/Contents/MongoDb/StatusSerializerTests.cs b/tests/Squidex.Domain.Apps.Entities.Tests/Contents/MongoDb/StatusSerializerTests.cs index ce50fc208..40556eb16 100644 --- a/tests/Squidex.Domain.Apps.Entities.Tests/Contents/MongoDb/StatusSerializerTests.cs +++ b/tests/Squidex.Domain.Apps.Entities.Tests/Contents/MongoDb/StatusSerializerTests.cs @@ -18,7 +18,7 @@ namespace Squidex.Domain.Apps.Entities.Contents.MongoDb { private sealed class TestObject { - public Status2 Status { get; set; } + public Status Status { get; set; } } [Fact] @@ -28,7 +28,7 @@ namespace Squidex.Domain.Apps.Entities.Contents.MongoDb var source = new TestObject { - Status = new Status2("Published") + Status = Status.Published }; var document = new BsonDocument(); From 987c6e4550b068337075ca0a3477ac0d6669d431 Mon Sep 17 00:00:00 2001 From: Sebastian Stehle Date: Wed, 19 Jun 2019 15:55:54 +0200 Subject: [PATCH 23/47] Method renamed. --- .../Contents/DefaultContentWorkflow.cs | 2 +- .../Contents/Guards/GuardContent.cs | 2 +- .../Contents/IContentWorkflow.cs | 2 +- .../Contents/ContentGrainTests.cs | 4 ++-- .../Contents/DefaultContentWorkflowTests.cs | 2 +- .../Contents/Guard/GuardContentTests.cs | 6 +++--- 6 files changed, 9 insertions(+), 9 deletions(-) diff --git a/src/Squidex.Domain.Apps.Entities/Contents/DefaultContentWorkflow.cs b/src/Squidex.Domain.Apps.Entities/Contents/DefaultContentWorkflow.cs index b1928480a..131bbe6e8 100644 --- a/src/Squidex.Domain.Apps.Entities/Contents/DefaultContentWorkflow.cs +++ b/src/Squidex.Domain.Apps.Entities/Contents/DefaultContentWorkflow.cs @@ -31,7 +31,7 @@ namespace Squidex.Domain.Apps.Entities.Contents return Task.FromResult(Status.Draft); } - public Task IsValidNextStatus(IContentEntity content, Status next) + public Task CanMoveToAsync(IContentEntity content, Status next) { return Task.FromResult(Flow.TryGetValue(content.Status, out var state) && state.Contains(next)); } diff --git a/src/Squidex.Domain.Apps.Entities/Contents/Guards/GuardContent.cs b/src/Squidex.Domain.Apps.Entities/Contents/Guards/GuardContent.cs index 35a3acca7..4395ffd11 100644 --- a/src/Squidex.Domain.Apps.Entities/Contents/Guards/GuardContent.cs +++ b/src/Squidex.Domain.Apps.Entities/Contents/Guards/GuardContent.cs @@ -76,7 +76,7 @@ namespace Squidex.Domain.Apps.Entities.Contents.Guards return Validate.It(() => "Cannot change status.", async e => { - if (!await contentWorkflow.IsValidNextStatus(content, command.Status)) + if (!await contentWorkflow.CanMoveToAsync(content, command.Status)) { if (content.Status == command.Status && content.Status == Status.Published) { diff --git a/src/Squidex.Domain.Apps.Entities/Contents/IContentWorkflow.cs b/src/Squidex.Domain.Apps.Entities/Contents/IContentWorkflow.cs index 06de365be..c812f8a4f 100644 --- a/src/Squidex.Domain.Apps.Entities/Contents/IContentWorkflow.cs +++ b/src/Squidex.Domain.Apps.Entities/Contents/IContentWorkflow.cs @@ -15,7 +15,7 @@ namespace Squidex.Domain.Apps.Entities.Contents { Task GetInitialStatusAsync(ISchemaEntity schema); - Task IsValidNextStatus(IContentEntity content, Status next); + Task CanMoveToAsync(IContentEntity content, Status next); Task CanUpdateAsync(IContentEntity content); diff --git a/tests/Squidex.Domain.Apps.Entities.Tests/Contents/ContentGrainTests.cs b/tests/Squidex.Domain.Apps.Entities.Tests/Contents/ContentGrainTests.cs index 8edba81dd..01da99c81 100644 --- a/tests/Squidex.Domain.Apps.Entities.Tests/Contents/ContentGrainTests.cs +++ b/tests/Squidex.Domain.Apps.Entities.Tests/Contents/ContentGrainTests.cs @@ -105,7 +105,7 @@ namespace Squidex.Domain.Apps.Entities.Contents A.CallTo(() => contentWorkflow.CanUpdateAsync(A.Ignored)) .Returns(true); - A.CallTo(() => contentWorkflow.IsValidNextStatus(A.Ignored, A.Ignored)) + A.CallTo(() => contentWorkflow.CanMoveToAsync(A.Ignored, A.Ignored)) .Returns(true); patched = patch.MergeInto(data); @@ -476,7 +476,7 @@ namespace Squidex.Domain.Apps.Entities.Contents var command = new ChangeContentStatus { Status = Status.Draft, JobId = sut.Snapshot.ScheduleJob.Id }; - A.CallTo(() => contentWorkflow.IsValidNextStatus(sut.Snapshot, command.Status)) + A.CallTo(() => contentWorkflow.CanMoveToAsync(sut.Snapshot, command.Status)) .Returns(false); var result = await sut.ExecuteAsync(CreateContentCommand(command)); diff --git a/tests/Squidex.Domain.Apps.Entities.Tests/Contents/DefaultContentWorkflowTests.cs b/tests/Squidex.Domain.Apps.Entities.Tests/Contents/DefaultContentWorkflowTests.cs index 6a1b5f32a..8c5b35bd1 100644 --- a/tests/Squidex.Domain.Apps.Entities.Tests/Contents/DefaultContentWorkflowTests.cs +++ b/tests/Squidex.Domain.Apps.Entities.Tests/Contents/DefaultContentWorkflowTests.cs @@ -29,7 +29,7 @@ namespace Squidex.Domain.Apps.Entities.Contents { var entity = CreateContent(Status.Published); - var result = await sut.IsValidNextStatus(entity, Status.Draft); + var result = await sut.CanMoveToAsync(entity, Status.Draft); Assert.True(result); } diff --git a/tests/Squidex.Domain.Apps.Entities.Tests/Contents/Guard/GuardContentTests.cs b/tests/Squidex.Domain.Apps.Entities.Tests/Contents/Guard/GuardContentTests.cs index 1f1eb91cb..93b96243b 100644 --- a/tests/Squidex.Domain.Apps.Entities.Tests/Contents/Guard/GuardContentTests.cs +++ b/tests/Squidex.Domain.Apps.Entities.Tests/Contents/Guard/GuardContentTests.cs @@ -182,7 +182,7 @@ namespace Squidex.Domain.Apps.Entities.Contents.Guard var content = CreateContent(Status.Draft, false); var command = new ChangeContentStatus { Status = Status.Published, DueTime = dueTimeInPast }; - A.CallTo(() => contentWorkflow.IsValidNextStatus(content, command.Status)) + A.CallTo(() => contentWorkflow.CanMoveToAsync(content, command.Status)) .Returns(true); await ValidationAssert.ThrowsAsync(() => GuardContent.CanChangeStatus(schema, content, contentWorkflow, command), @@ -197,7 +197,7 @@ namespace Squidex.Domain.Apps.Entities.Contents.Guard var content = CreateContent(Status.Draft, false); var command = new ChangeContentStatus { Status = Status.Published }; - A.CallTo(() => contentWorkflow.IsValidNextStatus(content, command.Status)) + A.CallTo(() => contentWorkflow.CanMoveToAsync(content, command.Status)) .Returns(false); await ValidationAssert.ThrowsAsync(() => GuardContent.CanChangeStatus(schema, content, contentWorkflow, command), @@ -212,7 +212,7 @@ namespace Squidex.Domain.Apps.Entities.Contents.Guard var content = CreateContent(Status.Draft, false); var command = new ChangeContentStatus { Status = Status.Published }; - A.CallTo(() => contentWorkflow.IsValidNextStatus(content, command.Status)) + A.CallTo(() => contentWorkflow.CanMoveToAsync(content, command.Status)) .Returns(true); await GuardContent.CanChangeStatus(schema, content, contentWorkflow, command); From e72945b01d36ce49c3bdf5ae9cbf70535f5f7205 Mon Sep 17 00:00:00 2001 From: Sebastian Stehle Date: Wed, 19 Jun 2019 16:14:53 +0200 Subject: [PATCH 24/47] Small changes finalized. --- .../Contents/StatusChange.cs | 16 ++++++ .../EnrichedContentEventType.cs | 4 +- .../Contents/MongoContentRepository.cs | 1 - .../Contents/ContentChangedTriggerHandler.cs | 17 ++++++- .../Contents/ContentGrain.cs | 27 +++++++--- .../Contents/ContentStatusChanged.cs | 2 + .../pages/content/content-page.component.html | 51 +++++++++---------- .../ContentChangedTriggerHandlerTests.cs | 5 +- .../Contents/ContentGrainTests.cs | 4 +- .../ContentChangedTriggerSchema.cs | 12 +---- 10 files changed, 87 insertions(+), 52 deletions(-) create mode 100644 src/Squidex.Domain.Apps.Core.Model/Contents/StatusChange.cs diff --git a/src/Squidex.Domain.Apps.Core.Model/Contents/StatusChange.cs b/src/Squidex.Domain.Apps.Core.Model/Contents/StatusChange.cs new file mode 100644 index 000000000..eae462221 --- /dev/null +++ b/src/Squidex.Domain.Apps.Core.Model/Contents/StatusChange.cs @@ -0,0 +1,16 @@ +// ========================================================================== +// Squidex Headless CMS +// ========================================================================== +// Copyright (c) Squidex UG (haftungsbeschränkt) +// All rights reserved. Licensed under the MIT license. +// ========================================================================== + +namespace Squidex.Domain.Apps.Core.Contents +{ + public enum StatusChange + { + Change, + Published, + Unpublished + } +} diff --git a/src/Squidex.Domain.Apps.Core.Operations/HandleRules/EnrichedEvents/EnrichedContentEventType.cs b/src/Squidex.Domain.Apps.Core.Operations/HandleRules/EnrichedEvents/EnrichedContentEventType.cs index 7ad49332d..565272ef6 100644 --- a/src/Squidex.Domain.Apps.Core.Operations/HandleRules/EnrichedEvents/EnrichedContentEventType.cs +++ b/src/Squidex.Domain.Apps.Core.Operations/HandleRules/EnrichedEvents/EnrichedContentEventType.cs @@ -11,7 +11,9 @@ namespace Squidex.Domain.Apps.Core.HandleRules.EnrichedEvents { Created, Deleted, + Published, StatusChanged, - Updated + Updated, + Unpublished, } } diff --git a/src/Squidex.Domain.Apps.Entities.MongoDb/Contents/MongoContentRepository.cs b/src/Squidex.Domain.Apps.Entities.MongoDb/Contents/MongoContentRepository.cs index d28d8078d..999ccf990 100644 --- a/src/Squidex.Domain.Apps.Entities.MongoDb/Contents/MongoContentRepository.cs +++ b/src/Squidex.Domain.Apps.Entities.MongoDb/Contents/MongoContentRepository.cs @@ -113,7 +113,6 @@ namespace Squidex.Domain.Apps.Entities.MongoDb.Contents { Guard.NotNull(app, nameof(app)); Guard.NotNull(schema, nameof(schema)); - Guard.NotNull(status, nameof(status)); using (Profiler.TraceMethod()) { diff --git a/src/Squidex.Domain.Apps.Entities/Contents/ContentChangedTriggerHandler.cs b/src/Squidex.Domain.Apps.Entities/Contents/ContentChangedTriggerHandler.cs index 0a155f703..8132c6f28 100644 --- a/src/Squidex.Domain.Apps.Entities/Contents/ContentChangedTriggerHandler.cs +++ b/src/Squidex.Domain.Apps.Entities/Contents/ContentChangedTriggerHandler.cs @@ -8,6 +8,7 @@ using System; using System.Threading.Tasks; using Orleans; +using Squidex.Domain.Apps.Core.Contents; using Squidex.Domain.Apps.Core.HandleRules; using Squidex.Domain.Apps.Core.HandleRules.EnrichedEvents; using Squidex.Domain.Apps.Core.Rules.Triggers; @@ -59,8 +60,20 @@ namespace Squidex.Domain.Apps.Entities.Contents case ContentUpdated _: result.Type = EnrichedContentEventType.Updated; break; - case ContentStatusChanged _: - result.Type = EnrichedContentEventType.StatusChanged; + case ContentStatusChanged contentStatusChanged: + switch (contentStatusChanged.Change) + { + case StatusChange.Published: + result.Type = EnrichedContentEventType.Published; + break; + case StatusChange.Unpublished: + result.Type = EnrichedContentEventType.Unpublished; + break; + default: + result.Type = EnrichedContentEventType.StatusChanged; + break; + } + break; } diff --git a/src/Squidex.Domain.Apps.Entities/Contents/ContentGrain.cs b/src/Squidex.Domain.Apps.Entities/Contents/ContentGrain.cs index 0f73ab461..60af67527 100644 --- a/src/Squidex.Domain.Apps.Entities/Contents/ContentGrain.cs +++ b/src/Squidex.Domain.Apps.Entities/Contents/ContentGrain.cs @@ -127,11 +127,24 @@ namespace Squidex.Domain.Apps.Entities.Contents } else { - var operation = c.Status == Status.Published ? "Published" : "StatusChanged"; - - await ctx.ExecuteScriptAsync(s => s.Change, operation, c, Snapshot.Data); - - ChangeStatus(c); + StatusChange reason; + + if (c.Status == Status.Published) + { + reason = StatusChange.Published; + } + else if (Snapshot.Status == Status.Published) + { + reason = StatusChange.Unpublished; + } + else + { + reason = StatusChange.Change; + } + + await ctx.ExecuteScriptAsync(s => s.Change, reason, c, Snapshot.Data); + + ChangeStatus(c, reason); } } } @@ -261,9 +274,9 @@ namespace Squidex.Domain.Apps.Entities.Contents RaiseEvent(SimpleMapper.Map(command, new ContentStatusScheduled { DueTime = command.DueTime.Value })); } - public void ChangeStatus(ChangeContentStatus command) + public void ChangeStatus(ChangeContentStatus command, StatusChange change) { - RaiseEvent(SimpleMapper.Map(command, new ContentStatusChanged())); + RaiseEvent(SimpleMapper.Map(command, new ContentStatusChanged { Change = change })); } private void RaiseEvent(SchemaEvent @event) diff --git a/src/Squidex.Domain.Apps.Events/Contents/ContentStatusChanged.cs b/src/Squidex.Domain.Apps.Events/Contents/ContentStatusChanged.cs index 2c97f5902..e7b201ffe 100644 --- a/src/Squidex.Domain.Apps.Events/Contents/ContentStatusChanged.cs +++ b/src/Squidex.Domain.Apps.Events/Contents/ContentStatusChanged.cs @@ -13,6 +13,8 @@ namespace Squidex.Domain.Apps.Events.Contents [EventType(nameof(ContentStatusChanged))] public sealed class ContentStatusChanged : ContentEvent { + public StatusChange Change { get; set; } + public Status Status { get; set; } } } diff --git a/src/Squidex/app/features/content/pages/content/content-page.component.html b/src/Squidex/app/features/content/pages/content/content-page.component.html index 22454ce68..29bbe09de 100644 --- a/src/Squidex/app/features/content/pages/content/content-page.component.html +++ b/src/Squidex/app/features/content/pages/content/content-page.component.html @@ -32,8 +32,7 @@ - + - + + } else { @@ -95,7 +95,6 @@ else var redirectButtons = document.getElementsByClassName("redirect-button"); if (redirectButtons.length === 1) { - debugger; redirectButtons[0].click(); } From f4c72783c8e071184803007c27c24c5d80eae3e9 Mon Sep 17 00:00:00 2001 From: Sebastian Stehle Date: Thu, 20 Jun 2019 19:14:03 +0200 Subject: [PATCH 28/47] Categories refactored. --- .../pages/schemas/schemas-page.component.html | 4 +- .../pages/schemas/schemas-page.component.ts | 10 ++- .../pages/schemas/schemas-page.component.html | 5 +- .../pages/schemas/schemas-page.component.ts | 5 +- .../components/schema-category.component.html | 24 +++--- .../components/schema-category.component.ts | 68 ++++++----------- .../app/shared/state/schemas.state.spec.ts | 61 ++++++++++++++-- src/Squidex/app/shared/state/schemas.state.ts | 73 +++++++------------ 8 files changed, 128 insertions(+), 122 deletions(-) diff --git a/src/Squidex/app/features/content/pages/schemas/schemas-page.component.html b/src/Squidex/app/features/content/pages/schemas/schemas-page.component.html index ec3ffec5c..ac121fd9e 100644 --- a/src/Squidex/app/features/content/pages/schemas/schemas-page.component.html +++ b/src/Squidex/app/features/content/pages/schemas/schemas-page.component.html @@ -18,10 +18,8 @@ diff --git a/src/Squidex/app/features/content/pages/schemas/schemas-page.component.ts b/src/Squidex/app/features/content/pages/schemas/schemas-page.component.ts index 273951329..832464b46 100644 --- a/src/Squidex/app/features/content/pages/schemas/schemas-page.component.ts +++ b/src/Squidex/app/features/content/pages/schemas/schemas-page.component.ts @@ -8,7 +8,11 @@ import { Component, OnInit } from '@angular/core'; import { FormControl } from '@angular/forms'; -import { AppsState, SchemasState } from '@app/shared'; +import { + AppsState, + SchemaCategory, + SchemasState +} from '@app/shared'; @Component({ selector: 'sqx-schemas-page', @@ -28,8 +32,8 @@ export class SchemasPageComponent implements OnInit { this.schemasState.load(); } - public trackByCategory(index: number, category: string) { - return category; + public trackByCategory(index: number, category: SchemaCategory) { + return category.name; } } diff --git a/src/Squidex/app/features/schemas/pages/schemas/schemas-page.component.html b/src/Squidex/app/features/schemas/pages/schemas/schemas-page.component.html index 5aa97c034..1c35ce05b 100644 --- a/src/Squidex/app/features/schemas/pages/schemas/schemas-page.component.html +++ b/src/Squidex/app/features/schemas/pages/schemas/schemas-page.component.html @@ -27,10 +27,9 @@ + (remove)="removeCategory(category.name)">
diff --git a/src/Squidex/app/features/schemas/pages/schemas/schemas-page.component.ts b/src/Squidex/app/features/schemas/pages/schemas/schemas-page.component.ts index 7c8aa690f..10b07fade 100644 --- a/src/Squidex/app/features/schemas/pages/schemas/schemas-page.component.ts +++ b/src/Squidex/app/features/schemas/pages/schemas/schemas-page.component.ts @@ -16,6 +16,7 @@ import { DialogModel, MessageBus, ResourceOwner, + SchemaCategory, SchemaDto, SchemasState } from '@app/shared'; @@ -94,8 +95,8 @@ export class SchemasPageComponent extends ResourceOwner implements OnInit { this.addSchemaDialog.show(); } - public trackByCategory(index: number, category: string) { - return category; + public trackByCategory(index: number, category: SchemaCategory) { + return category.name; } } diff --git a/src/Squidex/app/shared/components/schema-category.component.html b/src/Squidex/app/shared/components/schema-category.component.html index 406e91f13..339e189cf 100644 --- a/src/Squidex/app/shared/components/schema-category.component.html +++ b/src/Squidex/app/shared/components/schema-category.component.html @@ -1,4 +1,4 @@ -
+
@@ -6,18 +6,18 @@ -

{{snapshot.displayName}} ({{snapshot.schemasFiltered.length}})

+

{{schemaCategory.name}} ({{snapshot.filtered.length}})

-
diff --git a/src/Squidex/app/shared/components/schema-category.component.ts b/src/Squidex/app/shared/components/schema-category.component.ts index b5d714d9d..7d8e65e0c 100644 --- a/src/Squidex/app/shared/components/schema-category.component.ts +++ b/src/Squidex/app/shared/components/schema-category.component.ts @@ -10,7 +10,9 @@ import { ChangeDetectionStrategy, ChangeDetectorRef, Component, EventEmitter, In import { fadeAnimation, ImmutableArray, + isSameCategory, LocalStoreService, + SchemaCategory, SchemaDetailsDto, SchemaDto, SchemasState, @@ -19,12 +21,9 @@ import { } from '@app/shared/internal'; interface State { - displayName?: string; + filtered: ImmutableArray; - schemasFiltered: ImmutableArray; - schemasForCategory: ImmutableArray; - - isOpen: boolean; + isOpen?: boolean; } @Component({ @@ -38,36 +37,26 @@ interface State { }) export class SchemaCategoryComponent extends StatefulComponent implements OnInit, OnChanges { @Input() - public name: string; - - @Input() - public forContent: boolean; - - @Input() - public routeSingletonToContent = false; + public schemaCategory: SchemaCategory; @Input() public schemasFilter: string; @Input() - public schemas: ImmutableArray; + public forContent: boolean; @Output() public remove = new EventEmitter(); public allowDrop = (schema: any) => { - return (Types.is(schema, SchemaDto) || Types.is(schema, SchemaDetailsDto)) && !this.isSameCategory(schema); + return (Types.is(schema, SchemaDto) || Types.is(schema, SchemaDetailsDto)) && !isSameCategory(this.schemaCategory.name, schema); } constructor(changeDetector: ChangeDetectorRef, private readonly localStore: LocalStoreService, private readonly schemasState: SchemasState ) { - super(changeDetector, { - schemasFiltered: ImmutableArray.empty(), - schemasForCategory: ImmutableArray.empty(), - isOpen: true - }); + super(changeDetector, { filtered: ImmutableArray.empty(), isOpen: true }); } public ngOnInit() { @@ -81,52 +70,37 @@ export class SchemaCategoryComponent extends StatefulComponent implements } public ngOnChanges(changes: SimpleChanges): void { - if (changes['schemas'] || changes['schemasFilter']) { - const isSameCategory = (schema: SchemaDto) => { - return (!this.name && !schema.category) || schema.category === this.name; - }; + if (changes['schemaCategory'] || changes['schemasFilter']) { + let filtered = this.schemaCategory.schemas; - const query = this.schemasFilter; - - const schemasForCategory = this.schemas.filter(x => isSameCategory(x)); - const schemasFiltered = schemasForCategory.filter(x => !query || x.name.indexOf(query) >= 0); + if (this.forContent) { + filtered = filtered.filter(x => x.canReadContents); + } let isOpen = false; - if (query) { + if (this.schemasFilter) { + filtered = filtered.filter(x => x.name.indexOf(this.schemasFilter) >= 0); + isOpen = true; } else { - isOpen = this.localStore.get(`schema-category.${this.name}`) !== 'false'; - } - - this.next(s => ({ ...s, isOpen, schemasFiltered, schemasForCategory })); - } - - if (changes['name']) { - let displayName = 'Schemas'; - - if (this.name && this.name.length > 0) { - displayName = this.name; + isOpen = this.localStore.get(`schema-category.${this.schemaCategory.name}`) !== 'false'; } - this.next(s => ({ ...s, displayName })); + this.next(s => ({ ...s, isOpen, filtered })); } } public schemaRoute(schema: SchemaDto) { - if (schema.isSingleton && this.routeSingletonToContent) { + if (schema.isSingleton && this.forContent) { return [schema.name, schema.id]; } else { return [schema.name]; } } - private isSameCategory(schema: SchemaDto): boolean { - return ((!this.name && !schema.category) || schema.category === this.name) && (!this.forContent || schema.canReadContents); - } - public changeCategory(schema: SchemaDto) { - this.schemasState.changeCategory(schema, this.name); + this.schemasState.changeCategory(schema, this.schemaCategory.name); } public emitRemove() { @@ -138,6 +112,6 @@ export class SchemaCategoryComponent extends StatefulComponent implements } private configKey(): string { - return `squidex.schema.category.${this.name}.closed`; + return `squidex.schema.category.${this.schemaCategory.name}.closed`; } } diff --git a/src/Squidex/app/shared/state/schemas.state.spec.ts b/src/Squidex/app/shared/state/schemas.state.spec.ts index 4e8c74c74..9fe337b67 100644 --- a/src/Squidex/app/shared/state/schemas.state.spec.ts +++ b/src/Squidex/app/shared/state/schemas.state.spec.ts @@ -9,10 +9,11 @@ import { of, throwError } from 'rxjs'; import { IMock, It, Mock, Times } from 'typemoq'; -import { SchemasState } from './schemas.state'; +import { SchemaCategory, SchemasState } from './schemas.state'; import { DialogService, + ImmutableArray, SchemaDetailsDto, SchemasService, UpdateSchemaCategoryDto, @@ -69,7 +70,13 @@ describe('SchemasState', () => { expect(schemasState.snapshot.schemas.values).toEqual(oldSchemas.items); expect(schemasState.snapshot.isLoaded).toBeTruthy(); - expect(schemasState.snapshot.categories).toEqual({ 'category1': false, 'category2': false }); + + const categories = getCategories(schemasState); + + expect(categories!).toEqual([ + { name: 'category1', upper: 'CATEGORY1', schemas: ImmutableArray.of([schema1]) }, + { name: 'category2', upper: 'CATEGORY2', schemas: ImmutableArray.of([schema2]) } + ]); schemasService.verifyAll(); }); @@ -83,7 +90,14 @@ describe('SchemasState', () => { expect(schemasState.snapshot.schemas.values).toEqual(oldSchemas.items); expect(schemasState.snapshot.isLoaded).toBeTruthy(); - expect(schemasState.snapshot.categories).toEqual({ 'category1': false, 'category2': false, 'category3': true }); + + const categories = getCategories(schemasState); + + expect(categories!).toEqual([ + { name: 'category1', upper: 'CATEGORY1', schemas: ImmutableArray.of([schema1]) }, + { name: 'category2', upper: 'CATEGORY2', schemas: ImmutableArray.of([schema2]) }, + { name: 'category3', upper: 'CATEGORY3', schemas: ImmutableArray.empty() } + ]); schemasService.verifyAll(); }); @@ -111,13 +125,36 @@ describe('SchemasState', () => { it('should add category', () => { schemasState.addCategory('category3'); - expect(schemasState.snapshot.categories).toEqual({ 'category1': false, 'category2': false, 'category3': true }); + const categories = getCategories(schemasState); + + expect(categories!).toEqual([ + { name: 'category1', upper: 'CATEGORY1', schemas: ImmutableArray.of([schema1]) }, + { name: 'category2', upper: 'CATEGORY2', schemas: ImmutableArray.of([schema2]) }, + { name: 'category3', upper: 'CATEGORY3', schemas: ImmutableArray.empty() } + ]); + }); + + it('should not remove category with schemas', () => { + schemasState.addCategory('category1'); + + const categories = getCategories(schemasState); + + expect(categories!).toEqual([ + { name: 'category1', upper: 'CATEGORY1', schemas: ImmutableArray.of([schema1]) }, + { name: 'category2', upper: 'CATEGORY2', schemas: ImmutableArray.of([schema2]) } + ]); }); it('should remove category', () => { - schemasState.removeCategory('category1'); + schemasState.addCategory('category3'); + schemasState.removeCategory('category3'); - expect(schemasState.snapshot.categories).toEqual({ 'category2': false }); + const categories = getCategories(schemasState); + + expect(categories!).toEqual([ + { name: 'category1', upper: 'CATEGORY1', schemas: ImmutableArray.of([schema1]) }, + { name: 'category2', upper: 'CATEGORY2', schemas: ImmutableArray.of([schema2]) } + ]); }); it('should return schema on select and reload when already loaded', () => { @@ -482,4 +519,14 @@ describe('SchemasState', () => { }); }); }); -}); \ No newline at end of file +}); + +function getCategories(schemasState: SchemasState) { + let categories: SchemaCategory[]; + + schemasState.categories.subscribe(result => { + categories = result; + }); + + return categories!; +} diff --git a/src/Squidex/app/shared/state/schemas.state.ts b/src/Squidex/app/shared/state/schemas.state.ts index 68c3ea6d5..87dea5d3c 100644 --- a/src/Squidex/app/shared/state/schemas.state.ts +++ b/src/Squidex/app/shared/state/schemas.state.ts @@ -38,7 +38,7 @@ type AnyFieldDto = NestedFieldDto | RootFieldDto; interface Snapshot { // The schema categories. - categories: { [name: string]: boolean }; + categories: string[]; // The current schemas. schemas: SchemasList; @@ -54,8 +54,7 @@ interface Snapshot { } export type SchemasList = ImmutableArray; - -export type Categories = { [name: string]: boolean }; +export type SchemaCategory = { name: string; schemas: SchemasList; upper: string; }; function sameSchema(lhs: SchemaDetailsDto | null, rhs?: SchemaDetailsDto | null): boolean { return lhs === rhs || (!!lhs && !!rhs && lhs.id === rhs.id && lhs.version === rhs.version); @@ -68,7 +67,7 @@ export class SchemasState extends State { } public categories = - this.project2(x => x.categories, x => sortedCategoryNames(x)); + this.project2(x => x, x => buildCategories(x.categories, x.schemas)); public selectedSchema = this.project(x => x.selectedSchema, sameSchema); @@ -90,7 +89,7 @@ export class SchemasState extends State { private readonly dialogs: DialogService, private readonly schemasService: SchemasService ) { - super({ schemas: ImmutableArray.empty(), categories: buildCategories({}) }); + super({ schemas: ImmutableArray.empty(), categories: [] }); } public select(idOrName: string | null): Observable { @@ -126,9 +125,7 @@ export class SchemasState extends State { return this.next(s => { const schemas = ImmutableArray.of(items).sortByStringAsc(x => x.displayName); - const categories = buildCategories(s.categories, schemas); - - return { ...s, schemas, isLoaded: true, categories, canCreate }; + return { ...s, schemas, isLoaded: true, canCreate }; }); }), shareSubscribed(this.dialogs)); @@ -140,9 +137,7 @@ export class SchemasState extends State { this.next(s => { const schemas = s.schemas.push(created).sortByStringAsc(x => x.displayName); - const categories = buildCategories(s.categories, schemas); - - return { ...s, schemas, categories }; + return { ...s, schemas }; }); }), shareSubscribed(this.dialogs, { silent: true })); @@ -163,7 +158,7 @@ export class SchemasState extends State { public addCategory(name: string) { this.next(s => { - const categories = addCategory(s.categories, name); + const categories = [...s.categories, name]; return { ...s, categories: categories }; }); @@ -171,7 +166,7 @@ export class SchemasState extends State { public removeCategory(name: string) { this.next(s => { - const categories = removeCategory(s.categories, name); + const categories = s.categories.filter(x => x !== name); return { ...s, categories: categories }; }); @@ -309,9 +304,7 @@ export class SchemasState extends State { schema : s.selectedSchema; - const categories = buildCategories(s.categories, schemas); - - return { ...s, schemas, selectedSchema, categories }; + return { ...s, schemas, selectedSchema }; }); } @@ -328,46 +321,32 @@ function getField(x: SchemaDetailsDto, request: AddFieldDto, parent?: RootFieldD } } -function buildCategories(categories: { [name: string]: boolean }, schemas?: SchemasList) { - categories = { ...categories }; +function buildCategories(categories: string[], schemas: SchemasList): SchemaCategory[] { + const uniqueCategories: { [name: string]: string } = {}; - for (let category in categories) { - if (categories.hasOwnProperty(category)) { - if (!categories[category]) { - delete categories[category]; - } - } + for (let category of categories) { + uniqueCategories[category] = category; } - if (schemas) { - for (let schema of schemas.values) { - categories[schema.category || ''] = false; - } + for (let schema of schemas.values) { + uniqueCategories[schema.category || 'Schemas'] = schema.category; } - return categories; -} - -function addCategory(categories: Categories, category: string) { - categories = { ...categories }; - - categories[category] = true; + const result: SchemaCategory[] = []; - return categories; -} + for (let name in uniqueCategories) { + if (uniqueCategories.hasOwnProperty(name)) { + const key = uniqueCategories[name]; -function removeCategory(categories: Categories, category: string) { - categories = { ...categories }; + result.push({ name, upper: name.toUpperCase(), schemas: schemas.filter(x => isSameCategory(key, x))}); + } + } - delete categories[category]; + result.sort((a, b) => compareStringsAsc(a.upper, b.upper)); - return categories; + return result; } -function sortedCategoryNames(categories: Categories) { - const names = Object.keys(categories); - - names.sort(compareStringsAsc); - - return names; +export function isSameCategory(name: string, schema: SchemaDto): boolean { + return (!name && !schema.category) || schema.category === name; } \ No newline at end of file From 8d4246ab828c86b4e22e54f1a7427ed65e6ebc39 Mon Sep 17 00:00:00 2001 From: Sebastian Stehle Date: Fri, 21 Jun 2019 14:58:57 +0200 Subject: [PATCH 29/47] Fixed content changed trigger. --- .../rules/triggers/content-changed-trigger.component.html | 8 ++++---- .../rules/triggers/content-changed-trigger.component.ts | 3 --- 2 files changed, 4 insertions(+), 7 deletions(-) diff --git a/src/Squidex/app/features/rules/pages/rules/triggers/content-changed-trigger.component.html b/src/Squidex/app/features/rules/pages/rules/triggers/content-changed-trigger.component.html index f1ae6a0f7..da925bae6 100644 --- a/src/Squidex/app/features/rules/pages/rules/triggers/content-changed-trigger.component.html +++ b/src/Squidex/app/features/rules/pages/rules/triggers/content-changed-trigger.component.html @@ -22,13 +22,13 @@ - @@ -38,12 +38,12 @@
-
- +
diff --git a/src/Squidex/app/features/rules/pages/rules/triggers/content-changed-trigger.component.ts b/src/Squidex/app/features/rules/pages/rules/triggers/content-changed-trigger.component.ts index f169a8ff6..a3e1f140b 100644 --- a/src/Squidex/app/features/rules/pages/rules/triggers/content-changed-trigger.component.ts +++ b/src/Squidex/app/features/rules/pages/rules/triggers/content-changed-trigger.component.ts @@ -29,9 +29,6 @@ export class ContentChangedTriggerComponent implements OnInit { @Input() public schemas: ImmutableArray; - @Input() - public isEditable: boolean; - @Input() public trigger: any; From 5c83dcec1649f2044d1d4dc7b09fd220230f0ad7 Mon Sep 17 00:00:00 2001 From: Sebastian Stehle Date: Fri, 21 Jun 2019 15:57:48 +0200 Subject: [PATCH 30/47] Fix tag names. --- .../Assets/AssetCommandMiddleware.cs | 64 ++++++++++---- .../Assets/AssetCreatedResult.cs | 11 ++- .../Assets/AssetResult.cs | 25 ++++++ .../Assets/Commands/CreateAsset.cs | 9 +- .../Assets/Commands/UpdateAsset.cs | 9 +- .../Assets/Commands/UploadAssetCommand.cs | 20 +++++ .../CollectionExtensions.cs | 8 ++ .../Controllers/Assets/AssetsController.cs | 6 +- .../Api/Controllers/Assets/Models/AssetDto.cs | 7 +- .../app/shared/services/assets.service.ts | 2 +- .../Assets/AssetCommandMiddlewareTests.cs | 84 ++++++++++++++++--- 11 files changed, 189 insertions(+), 56 deletions(-) create mode 100644 src/Squidex.Domain.Apps.Entities/Assets/AssetResult.cs create mode 100644 src/Squidex.Domain.Apps.Entities/Assets/Commands/UploadAssetCommand.cs diff --git a/src/Squidex.Domain.Apps.Entities/Assets/AssetCommandMiddleware.cs b/src/Squidex.Domain.Apps.Entities/Assets/AssetCommandMiddleware.cs index b13c99f29..e45e02645 100644 --- a/src/Squidex.Domain.Apps.Entities/Assets/AssetCommandMiddleware.cs +++ b/src/Squidex.Domain.Apps.Entities/Assets/AssetCommandMiddleware.cs @@ -10,6 +10,7 @@ using System.Collections.Generic; using System.Security.Cryptography; using System.Threading.Tasks; using Orleans; +using Squidex.Domain.Apps.Core.Tags; using Squidex.Domain.Apps.Entities.Assets.Commands; using Squidex.Domain.Apps.Entities.Tags; using Squidex.Infrastructure; @@ -24,25 +25,28 @@ namespace Squidex.Domain.Apps.Entities.Assets private readonly IAssetQueryService assetQuery; private readonly IAssetThumbnailGenerator assetThumbnailGenerator; private readonly IEnumerable> tagGenerators; + private readonly ITagService tagService; public AssetCommandMiddleware( IGrainFactory grainFactory, IAssetQueryService assetQuery, IAssetStore assetStore, IAssetThumbnailGenerator assetThumbnailGenerator, - IEnumerable> tagGenerators) + IEnumerable> tagGenerators, + ITagService tagService) : base(grainFactory) { Guard.NotNull(assetStore, nameof(assetStore)); Guard.NotNull(assetQuery, nameof(assetQuery)); Guard.NotNull(assetThumbnailGenerator, nameof(assetThumbnailGenerator)); Guard.NotNull(tagGenerators, nameof(tagGenerators)); + Guard.NotNull(tagService, nameof(tagService)); this.assetStore = assetStore; this.assetQuery = assetQuery; this.assetThumbnailGenerator = assetThumbnailGenerator; - this.tagGenerators = tagGenerators; + this.tagService = tagService; } public override async Task HandleAsync(CommandContext context, Func next) @@ -56,9 +60,8 @@ namespace Squidex.Domain.Apps.Entities.Assets createAsset.Tags = new HashSet(); } - createAsset.ImageInfo = await assetThumbnailGenerator.GetImageInfoAsync(createAsset.File.OpenRead()); - - createAsset.FileHash = await UploadAsync(context, createAsset.File); + await EnrichWithImageInfosAsync(createAsset); + await EnrichWithHashAndUploadAsync(createAsset, context); try { @@ -70,7 +73,9 @@ namespace Squidex.Domain.Apps.Entities.Assets { if (IsDuplicate(createAsset, existing)) { - result = new AssetCreatedResult(existing, true); + var denormalizedTags = await tagService.DenormalizeTagsAsync(createAsset.AppId.Id, TagGroups.Assets, existing.Tags); + + result = new AssetCreatedResult(existing, true, new HashSet(denormalizedTags.Values)); } break; @@ -85,7 +90,7 @@ namespace Squidex.Domain.Apps.Entities.Assets var asset = (IAssetEntity)await ExecuteCommandAsync(createAsset); - result = new AssetCreatedResult(asset, false); + result = new AssetCreatedResult(asset, false, createAsset.Tags); await assetStore.CopyAsync(context.ContextId.ToString(), createAsset.AssetId.ToString(), asset.FileVersion, null); } @@ -102,16 +107,16 @@ namespace Squidex.Domain.Apps.Entities.Assets case UpdateAsset updateAsset: { - updateAsset.ImageInfo = await assetThumbnailGenerator.GetImageInfoAsync(updateAsset.File.OpenRead()); + await EnrichWithImageInfosAsync(updateAsset); + await EnrichWithHashAndUploadAsync(updateAsset, context); - updateAsset.FileHash = await UploadAsync(context, updateAsset.File); try { - var result = (IAssetEntity)await ExecuteCommandAsync(updateAsset); + var result = (AssetResult)await ExecuteAndAdjustTagsAsync(updateAsset); context.Complete(result); - await assetStore.CopyAsync(context.ContextId.ToString(), updateAsset.AssetId.ToString(), result.FileVersion, null); + await assetStore.CopyAsync(context.ContextId.ToString(), updateAsset.AssetId.ToString(), result.Asset.FileVersion, null); } finally { @@ -121,29 +126,54 @@ namespace Squidex.Domain.Apps.Entities.Assets break; } + case AssetCommand command: + { + var result = await ExecuteAndAdjustTagsAsync(command); + + context.Complete(result); + + break; + } + default: await base.HandleAsync(context, next); + break; } } + private async Task ExecuteAndAdjustTagsAsync(AssetCommand command) + { + var result = await ExecuteCommandAsync(command); + + if (result is IAssetEntity asset) + { + var denormalizedTags = await tagService.DenormalizeTagsAsync(asset.AppId.Id, TagGroups.Assets, asset.Tags); + + return new AssetResult(asset, new HashSet(denormalizedTags.Values)); + } + + return result; + } + private static bool IsDuplicate(CreateAsset createAsset, IAssetEntity asset) { return asset != null && asset.FileName == createAsset.File.FileName && asset.FileSize == createAsset.File.FileSize; } - private async Task UploadAsync(CommandContext context, AssetFile file) + private async Task EnrichWithImageInfosAsync(UploadAssetCommand command) { - string hash; + command.ImageInfo = await assetThumbnailGenerator.GetImageInfoAsync(command.File.OpenRead()); + } - using (var hashStream = new HasherStream(file.OpenRead(), HashAlgorithmName.SHA256)) + private async Task EnrichWithHashAndUploadAsync(UploadAssetCommand command, CommandContext context) + { + using (var hashStream = new HasherStream(command.File.OpenRead(), HashAlgorithmName.SHA256)) { await assetStore.UploadAsync(context.ContextId.ToString(), hashStream); - hash = $"{hashStream.GetHashStringAndReset()}{file.FileName}{file.FileSize}".Sha256Base64(); + command.FileHash = $"{hashStream.GetHashStringAndReset()}{command.File.FileName}{command.File.FileSize}".Sha256Base64(); } - - return hash; } } } diff --git a/src/Squidex.Domain.Apps.Entities/Assets/AssetCreatedResult.cs b/src/Squidex.Domain.Apps.Entities/Assets/AssetCreatedResult.cs index b1502786a..9ccc00763 100644 --- a/src/Squidex.Domain.Apps.Entities/Assets/AssetCreatedResult.cs +++ b/src/Squidex.Domain.Apps.Entities/Assets/AssetCreatedResult.cs @@ -5,18 +5,17 @@ // All rights reserved. Licensed under the MIT license. // ========================================================================== +using System.Collections.Generic; + namespace Squidex.Domain.Apps.Entities.Assets { - public sealed class AssetCreatedResult + public sealed class AssetCreatedResult : AssetResult { - public IAssetEntity Asset { get; } - public bool IsDuplicate { get; } - public AssetCreatedResult(IAssetEntity asset, bool isDuplicate) + public AssetCreatedResult(IAssetEntity asset, bool isDuplicate, HashSet tags) + : base(asset, tags) { - Asset = asset; - IsDuplicate = isDuplicate; } } diff --git a/src/Squidex.Domain.Apps.Entities/Assets/AssetResult.cs b/src/Squidex.Domain.Apps.Entities/Assets/AssetResult.cs new file mode 100644 index 000000000..b43713da5 --- /dev/null +++ b/src/Squidex.Domain.Apps.Entities/Assets/AssetResult.cs @@ -0,0 +1,25 @@ +// ========================================================================== +// Squidex Headless CMS +// ========================================================================== +// Copyright (c) Squidex UG (haftungsbeschraenkt) +// All rights reserved. Licensed under the MIT license. +// ========================================================================== + +using System.Collections.Generic; + +namespace Squidex.Domain.Apps.Entities.Assets +{ + public class AssetResult + { + public IAssetEntity Asset { get; } + + public HashSet Tags { get; } + + public AssetResult(IAssetEntity asset, HashSet tags) + { + Asset = asset; + + Tags = tags; + } + } +} diff --git a/src/Squidex.Domain.Apps.Entities/Assets/Commands/CreateAsset.cs b/src/Squidex.Domain.Apps.Entities/Assets/Commands/CreateAsset.cs index 9c49e67bd..8e869ba40 100644 --- a/src/Squidex.Domain.Apps.Entities/Assets/Commands/CreateAsset.cs +++ b/src/Squidex.Domain.Apps.Entities/Assets/Commands/CreateAsset.cs @@ -8,22 +8,15 @@ using System; using System.Collections.Generic; using Squidex.Infrastructure; -using Squidex.Infrastructure.Assets; namespace Squidex.Domain.Apps.Entities.Assets.Commands { - public sealed class CreateAsset : AssetCommand, IAppCommand + public sealed class CreateAsset : UploadAssetCommand, IAppCommand { public NamedId AppId { get; set; } - public AssetFile File { get; set; } - - public ImageInfo ImageInfo { get; set; } - public HashSet Tags { get; set; } - public string FileHash { get; set; } - public CreateAsset() { AssetId = Guid.NewGuid(); diff --git a/src/Squidex.Domain.Apps.Entities/Assets/Commands/UpdateAsset.cs b/src/Squidex.Domain.Apps.Entities/Assets/Commands/UpdateAsset.cs index 1c998ac7a..16197164d 100644 --- a/src/Squidex.Domain.Apps.Entities/Assets/Commands/UpdateAsset.cs +++ b/src/Squidex.Domain.Apps.Entities/Assets/Commands/UpdateAsset.cs @@ -5,16 +5,9 @@ // All rights reserved. Licensed under the MIT license. // ========================================================================== -using Squidex.Infrastructure.Assets; - namespace Squidex.Domain.Apps.Entities.Assets.Commands { - public sealed class UpdateAsset : AssetCommand + public sealed class UpdateAsset : UploadAssetCommand { - public AssetFile File { get; set; } - - public ImageInfo ImageInfo { get; set; } - - public string FileHash { get; set; } } } diff --git a/src/Squidex.Domain.Apps.Entities/Assets/Commands/UploadAssetCommand.cs b/src/Squidex.Domain.Apps.Entities/Assets/Commands/UploadAssetCommand.cs new file mode 100644 index 000000000..5ef0652cd --- /dev/null +++ b/src/Squidex.Domain.Apps.Entities/Assets/Commands/UploadAssetCommand.cs @@ -0,0 +1,20 @@ +// ========================================================================== +// Squidex Headless CMS +// ========================================================================== +// Copyright (c) Squidex UG (haftungsbeschraenkt) +// All rights reserved. Licensed under the MIT license. +// ========================================================================== + +using Squidex.Infrastructure.Assets; + +namespace Squidex.Domain.Apps.Entities.Assets.Commands +{ + public abstract class UploadAssetCommand : AssetCommand + { + public AssetFile File { get; set; } + + public ImageInfo ImageInfo { get; set; } + + public string FileHash { get; set; } + } +} diff --git a/src/Squidex.Infrastructure/CollectionExtensions.cs b/src/Squidex.Infrastructure/CollectionExtensions.cs index 76be0fd06..cfe546a24 100644 --- a/src/Squidex.Infrastructure/CollectionExtensions.cs +++ b/src/Squidex.Infrastructure/CollectionExtensions.cs @@ -13,6 +13,14 @@ namespace Squidex.Infrastructure { public static class CollectionExtensions { + public static void AddRange(this ICollection target, IEnumerable source) + { + foreach (var value in source) + { + target.Add(value); + } + } + public static IEnumerable Shuffle(this IEnumerable enumerable) { var random = new Random(); diff --git a/src/Squidex/Areas/Api/Controllers/Assets/AssetsController.cs b/src/Squidex/Areas/Api/Controllers/Assets/AssetsController.cs index 8f0f95fa2..965056fbe 100644 --- a/src/Squidex/Areas/Api/Controllers/Assets/AssetsController.cs +++ b/src/Squidex/Areas/Api/Controllers/Assets/AssetsController.cs @@ -182,7 +182,7 @@ namespace Squidex.Areas.Api.Controllers.Assets var context = await CommandBus.PublishAsync(command); var result = context.Result(); - var response = AssetDto.FromAsset(result.Asset, this, app, result.IsDuplicate); + var response = AssetDto.FromAsset(result.Asset, this, app, result.Tags, result.IsDuplicate); return CreatedAtAction(nameof(GetAsset), new { app, id = response.Id }, response); } @@ -267,8 +267,8 @@ namespace Squidex.Areas.Api.Controllers.Assets { var context = await CommandBus.PublishAsync(command); - var result = context.Result(); - var response = AssetDto.FromAsset(result, this, app); + var result = context.Result(); + var response = AssetDto.FromAsset(result.Asset, this, app, result.Tags); return response; } diff --git a/src/Squidex/Areas/Api/Controllers/Assets/Models/AssetDto.cs b/src/Squidex/Areas/Api/Controllers/Assets/Models/AssetDto.cs index f44c9d25a..ec0e68899 100644 --- a/src/Squidex/Areas/Api/Controllers/Assets/Models/AssetDto.cs +++ b/src/Squidex/Areas/Api/Controllers/Assets/Models/AssetDto.cs @@ -118,10 +118,15 @@ namespace Squidex.Areas.Api.Controllers.Assets.Models [JsonProperty("_meta")] public AssetMetadata Metadata { get; set; } - public static AssetDto FromAsset(IAssetEntity asset, ApiController controller, string app, bool isDuplicate = false) + public static AssetDto FromAsset(IAssetEntity asset, ApiController controller, string app, HashSet tags = null, bool isDuplicate = false) { var response = SimpleMapper.Map(asset, new AssetDto { FileType = asset.FileName.FileType() }); + if (tags != null) + { + response.Tags = tags; + } + if (isDuplicate) { response.Metadata = new AssetMetadata { IsDuplicate = "true" }; diff --git a/src/Squidex/app/shared/services/assets.service.ts b/src/Squidex/app/shared/services/assets.service.ts index 429c225e7..8fd9e0fbd 100644 --- a/src/Squidex/app/shared/services/assets.service.ts +++ b/src/Squidex/app/shared/services/assets.service.ts @@ -242,7 +242,7 @@ export class AssetsService { tap(() => { this.analytics.trackEvent('Analytics', 'Updated', appName); }), - pretifyError('Failed to delete asset. Please reload.')); + pretifyError('Failed to update asset. Please reload.')); } public deleteAsset(appName: string, asset: Resource, version: Version): Observable> { diff --git a/tests/Squidex.Domain.Apps.Entities.Tests/Assets/AssetCommandMiddlewareTests.cs b/tests/Squidex.Domain.Apps.Entities.Tests/Assets/AssetCommandMiddlewareTests.cs index 21df10911..00f6856ed 100644 --- a/tests/Squidex.Domain.Apps.Entities.Tests/Assets/AssetCommandMiddlewareTests.cs +++ b/tests/Squidex.Domain.Apps.Entities.Tests/Assets/AssetCommandMiddlewareTests.cs @@ -54,19 +54,23 @@ namespace Squidex.Domain.Apps.Entities.Assets A.CallTo(() => assetQuery.QueryByHashAsync(AppId, A.Ignored)) .Returns(new List()); - A.CallTo(() => tagService.NormalizeTagsAsync(AppId, TagGroups.Assets, A>.Ignored, A>.Ignored)) - .Returns(new Dictionary()); + A.CallTo(() => tagService.DenormalizeTagsAsync(AppId, TagGroups.Assets, A>.Ignored)) + .Returns(new Dictionary + { + ["1"] = "foundTag1", + ["2"] = "foundTag2" + }); A.CallTo(() => grainFactory.GetGrain(Id, null)) .Returns(asset); - sut = new AssetCommandMiddleware(grainFactory, assetQuery, assetStore, assetThumbnailGenerator, new[] { tagGenerator }); + sut = new AssetCommandMiddleware(grainFactory, assetQuery, assetStore, assetThumbnailGenerator, new[] { tagGenerator }, tagService); } [Fact] public async Task Create_should_create_domain_object() { - var command = new CreateAsset { AssetId = assetId, File = file }; + var command = CreateCommand(new CreateAsset { AssetId = assetId, File = file }); var context = CreateContextForCommand(command); SetupTags(command); @@ -80,6 +84,8 @@ namespace Squidex.Domain.Apps.Entities.Assets Assert.Contains("tag1", command.Tags); Assert.Contains("tag2", command.Tags); + Assert.Equal(new HashSet { "tag1", "tag2" }, result.Tags); + AssertAssetHasBeenUploaded(0, context.ContextId); AssertAssetImageChecked(); } @@ -87,7 +93,7 @@ namespace Squidex.Domain.Apps.Entities.Assets [Fact] public async Task Create_should_calculate_hash() { - var command = new CreateAsset { AssetId = assetId, File = file }; + var command = CreateCommand(new CreateAsset { AssetId = assetId, File = file }); var context = CreateContextForCommand(command); SetupImageInfo(); @@ -100,7 +106,7 @@ namespace Squidex.Domain.Apps.Entities.Assets [Fact] public async Task Create_should_return_duplicate_result_if_file_with_same_hash_found() { - var command = new CreateAsset { AssetId = assetId, File = file }; + var command = CreateCommand(new CreateAsset { AssetId = assetId, File = file }); var context = CreateContextForCommand(command); SetupSameHashAsset(file.FileName, file.FileSize, out _); @@ -108,13 +114,15 @@ namespace Squidex.Domain.Apps.Entities.Assets await sut.HandleAsync(context); - Assert.True(context.Result().IsDuplicate); + var result = context.Result(); + + Assert.True(result.IsDuplicate); } [Fact] public async Task Create_should_not_return_duplicate_result_if_file_with_same_hash_but_other_name_found() { - var command = new CreateAsset { AssetId = assetId, File = file }; + var command = CreateCommand(new CreateAsset { AssetId = assetId, File = file }); var context = CreateContextForCommand(command); SetupSameHashAsset("other-name", file.FileSize, out _); @@ -122,13 +130,31 @@ namespace Squidex.Domain.Apps.Entities.Assets await sut.HandleAsync(context); - Assert.False(context.Result().IsDuplicate); + var result = context.Result(); + + Assert.False(result.IsDuplicate); + } + + [Fact] + public async Task Create_should_resolve_tag_names_for_duplicate() + { + var command = CreateCommand(new CreateAsset { AssetId = assetId, File = file }); + var context = CreateContextForCommand(command); + + SetupSameHashAsset(file.FileName, file.FileSize, out _); + SetupImageInfo(); + + await sut.HandleAsync(context); + + var result = context.Result(); + + Assert.Equal(new HashSet { "foundTag1", "foundTag2" }, result.Tags); } [Fact] public async Task Create_should_not_return_duplicate_result_if_file_with_same_hash_but_other_size_found() { - var command = new CreateAsset { AssetId = assetId, File = file }; + var command = CreateCommand(new CreateAsset { AssetId = assetId, File = file }); var context = CreateContextForCommand(command); SetupSameHashAsset(file.FileName, 12345, out _); @@ -142,7 +168,7 @@ namespace Squidex.Domain.Apps.Entities.Assets [Fact] public async Task Update_should_update_domain_object() { - var command = new UpdateAsset { AssetId = assetId, File = file }; + var command = CreateCommand(new UpdateAsset { AssetId = assetId, File = file }); var context = CreateContextForCommand(command); SetupImageInfo(); @@ -158,7 +184,7 @@ namespace Squidex.Domain.Apps.Entities.Assets [Fact] public async Task Update_should_calculate_hash() { - var command = new UpdateAsset { AssetId = assetId, File = file }; + var command = CreateCommand(new UpdateAsset { AssetId = assetId, File = file }); var context = CreateContextForCommand(command); SetupImageInfo(); @@ -170,6 +196,40 @@ namespace Squidex.Domain.Apps.Entities.Assets Assert.True(command.FileHash.Length > 10); } + [Fact] + public async Task Update_should_resolve_tags() + { + var command = CreateCommand(new UpdateAsset { AssetId = assetId, File = file }); + var context = CreateContextForCommand(command); + + SetupImageInfo(); + + await ExecuteCreateAsync(); + + await sut.HandleAsync(context); + + var result = context.Result(); + + Assert.Equal(new HashSet { "foundTag1", "foundTag2" }, result.Tags); + } + + [Fact] + public async Task AnnotateAsset_should_resolve_tags() + { + var command = CreateCommand(new AnnotateAsset { AssetId = assetId, FileName = "newName" }); + var context = CreateContextForCommand(command); + + SetupImageInfo(); + + await ExecuteCreateAsync(); + + await sut.HandleAsync(context); + + var result = context.Result(); + + Assert.Equal(new HashSet { "foundTag1", "foundTag2" }, result.Tags); + } + private Task ExecuteCreateAsync() { return asset.ExecuteAsync(CreateCommand(new CreateAsset { AssetId = Id, File = file })); From ad0ab894fbda4d2d849be24b05417bfa21e4b7d0 Mon Sep 17 00:00:00 2001 From: Sebastian Stehle Date: Fri, 21 Jun 2019 17:01:58 +0200 Subject: [PATCH 31/47] Fix field form after "Create and Edit" --- .../features/schemas/pages/schema/field-wizard.component.html | 1 + src/Squidex/app/shared/components/schema-category.component.ts | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/src/Squidex/app/features/schemas/pages/schema/field-wizard.component.html b/src/Squidex/app/features/schemas/pages/schema/field-wizard.component.html index 1b4866640..cf9681be6 100644 --- a/src/Squidex/app/features/schemas/pages/schema/field-wizard.component.html +++ b/src/Squidex/app/features/schemas/pages/schema/field-wizard.component.html @@ -65,6 +65,7 @@
implements if (query) { isOpen = true; } else { - isOpen = this.localStore.get(`schema-category.${this.name}`) !== 'false'; + isOpen = !this.localStore.getBoolean(this.configKey()); } this.next(s => ({ ...s, isOpen, schemasFiltered, schemasForCategory })); From c00305444905c2f575e1f4537259eda18b6e59a3 Mon Sep 17 00:00:00 2001 From: Sebastian Stehle Date: Fri, 21 Jun 2019 17:07:35 +0200 Subject: [PATCH 32/47] Fixed field deletion. --- .../Areas/Api/Controllers/Schemas/SchemaFieldsController.cs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/Squidex/Areas/Api/Controllers/Schemas/SchemaFieldsController.cs b/src/Squidex/Areas/Api/Controllers/Schemas/SchemaFieldsController.cs index 55e68584b..6c50117dc 100644 --- a/src/Squidex/Areas/Api/Controllers/Schemas/SchemaFieldsController.cs +++ b/src/Squidex/Areas/Api/Controllers/Schemas/SchemaFieldsController.cs @@ -513,9 +513,11 @@ namespace Squidex.Areas.Api.Controllers.Schemas [ApiCosts(1)] public async Task DeleteNestedField(string app, string name, long parentId, long id) { - await CommandBus.PublishAsync(new DeleteField { ParentFieldId = parentId, FieldId = id }); + var command = new DeleteField { ParentFieldId = parentId, FieldId = id }; - return NoContent(); + var response = await InvokeCommandAsync(app, command); + + return Ok(response); } private async Task InvokeCommandAsync(string app, ICommand command) From 2750c74b732852b24a300e173435d858cf4966ea Mon Sep 17 00:00:00 2001 From: Sebastian Stehle Date: Fri, 21 Jun 2019 17:22:05 +0200 Subject: [PATCH 33/47] Fix cancel and enqueue rules. --- .../Controllers/Rules/Models/RuleEventDto.cs | 5 +- .../app/shared/services/rules.service.spec.ts | 67 ++++++++++--------- .../app/shared/services/rules.service.ts | 12 +++- .../shared/state/rule-events.state.spec.ts | 8 +-- 4 files changed, 55 insertions(+), 37 deletions(-) diff --git a/src/Squidex/Areas/Api/Controllers/Rules/Models/RuleEventDto.cs b/src/Squidex/Areas/Api/Controllers/Rules/Models/RuleEventDto.cs index 201e3dadd..a513495ab 100644 --- a/src/Squidex/Areas/Api/Controllers/Rules/Models/RuleEventDto.cs +++ b/src/Squidex/Areas/Api/Controllers/Rules/Models/RuleEventDto.cs @@ -80,7 +80,10 @@ namespace Squidex.Areas.Api.Controllers.Rules.Models AddPutLink("update", controller.Url(x => nameof(x.PutEvent), values)); - AddDeleteLink("delete", controller.Url(x => nameof(x.DeleteEvent), values)); + if (NextAttempt.HasValue) + { + AddDeleteLink("delete", controller.Url(x => nameof(x.DeleteEvent), values)); + } return this; } diff --git a/src/Squidex/app/shared/services/rules.service.spec.ts b/src/Squidex/app/shared/services/rules.service.spec.ts index 399580e53..99c00490a 100644 --- a/src/Squidex/app/shared/services/rules.service.spec.ts +++ b/src/Squidex/app/shared/services/rules.service.spec.ts @@ -288,41 +288,15 @@ describe('RulesService', () => { req.flush({ total: 20, items: [ - { - id: 'id1', - created: '2017-12-12T10:10', - eventName: 'event1', - nextAttempt: '2017-12-12T12:10', - jobResult: 'Failed', - lastDump: 'dump1', - numCalls: 1, - description: 'url1', - result: 'Failed' - }, - { - id: 'id2', - created: '2017-12-13T10:10', - eventName: 'event2', - nextAttempt: '2017-12-13T12:10', - jobResult: 'Failed', - lastDump: 'dump2', - numCalls: 2, - description: 'url2', - result: 'Failed' - } + ruleEventResponse(1), + ruleEventResponse(2) ] }); expect(rules!).toEqual( new RuleEventsDto(20, [ - new RuleEventDto('id1', - DateTime.parseISO_UTC('2017-12-12T10:10'), - DateTime.parseISO_UTC('2017-12-12T12:10'), - 'event1', 'url1', 'dump1', 'Failed', 'Failed', 1), - new RuleEventDto('id2', - DateTime.parseISO_UTC('2017-12-13T10:10'), - DateTime.parseISO_UTC('2017-12-13T12:10'), - 'event2', 'url2', 'dump2', 'Failed', 'Failed', 2) + createRuleEvent(1), + createRuleEvent(2) ])); })); @@ -364,6 +338,23 @@ describe('RulesService', () => { req.flush({}); })); + function ruleEventResponse(id: number, suffix = '') { + return { + id: `id${id}`, + created: `${id % 1000 + 2000}-12-12T10:10:00`, + eventName: `event${id}${suffix}`, + nextAttempt: `${id % 1000 + 2000}-11-11T10:10`, + jobResult: `Failed${id}${suffix}`, + lastDump: `dump${id}${suffix}`, + numCalls: id, + description: `url${id}${suffix}`, + result: `Failed${id}${suffix}`, + _links: { + update: { method: 'PUT', href: `/rules/events/${id}` } + } + }; + } + function ruleResponse(id: number, suffix = '') { return { id: `id${id}`, @@ -390,6 +381,22 @@ describe('RulesService', () => { } }); +export function createRuleEvent(id: number, suffix = '') { + const links: ResourceLinks = { + update: { method: 'PUT', href: `/rules/events/${id}` } + }; + + return new RuleEventDto(links, `id${id}`, + DateTime.parseISO_UTC(`${id % 1000 + 2000}-12-12T10:10:00`), + DateTime.parseISO_UTC(`${id % 1000 + 2000}-11-11T10:10:00`), + `event${id}${suffix}`, + `url${id}${suffix}`, + `dump${id}${suffix}`, + `Failed${id}${suffix}`, + `Failed${id}${suffix}`, + id); +} + export function createRule(id: number, suffix = '') { const links: ResourceLinks = { update: { method: 'PUT', href: `/rules/${id}` } diff --git a/src/Squidex/app/shared/services/rules.service.ts b/src/Squidex/app/shared/services/rules.service.ts index bd44ae278..5c42f7dec 100644 --- a/src/Squidex/app/shared/services/rules.service.ts +++ b/src/Squidex/app/shared/services/rules.service.ts @@ -127,7 +127,10 @@ export class RuleEventsDto extends ResultSet { export class RuleEventDto extends Model { public readonly _links: ResourceLinks; - constructor( + public readonly canDelete: boolean; + public readonly canUpdate: boolean; + + constructor(links: ResourceLinks, public readonly id: string, public readonly created: DateTime, public readonly nextAttempt: DateTime | null, @@ -139,6 +142,11 @@ export class RuleEventDto extends Model { public readonly numCalls: number ) { super(); + + this._links = links; + + this.canDelete = hasAnyLink(links, 'delete'); + this.canUpdate = hasAnyLink(links, 'update'); } } @@ -287,7 +295,7 @@ export class RulesService { const items: any[] = body.items; const ruleEvents = new RuleEventsDto(body.total, items.map(item => - new RuleEventDto( + new RuleEventDto(item._links, item.id, DateTime.parseISO_UTC(item.created), item.nextAttempt ? DateTime.parseISO_UTC(item.nextAttempt) : null, diff --git a/src/Squidex/app/shared/state/rule-events.state.spec.ts b/src/Squidex/app/shared/state/rule-events.state.spec.ts index 5adcd6f4a..cd0ebcab6 100644 --- a/src/Squidex/app/shared/state/rule-events.state.spec.ts +++ b/src/Squidex/app/shared/state/rule-events.state.spec.ts @@ -9,14 +9,14 @@ import { of } from 'rxjs'; import { IMock, It, Mock, Times } from 'typemoq'; import { - DateTime, DialogService, - RuleEventDto, RuleEventsDto, RuleEventsState, RulesService } from '@app/shared/internal'; +import { createRuleEvent } from '../services/rules.service.spec'; + import { TestValues } from './_test-helpers'; describe('RuleEventsState', () => { @@ -26,8 +26,8 @@ describe('RuleEventsState', () => { } = TestValues; const oldRuleEvents = [ - new RuleEventDto('id1', DateTime.now(), null, 'event1', 'description', 'dump1', 'result1', 'result1', 1), - new RuleEventDto('id2', DateTime.now(), null, 'event2', 'description', 'dump2', 'result2', 'result2', 2) + createRuleEvent(1), + createRuleEvent(2) ]; let dialogs: IMock; From 85cd8f539d8de76249862c5e1b925374345bff79 Mon Sep 17 00:00:00 2001 From: Sebastian Stehle Date: Fri, 21 Jun 2019 17:26:39 +0200 Subject: [PATCH 34/47] Due time fixed. --- src/Squidex.Domain.Apps.Entities/Contents/ScheduleJob.cs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/Squidex.Domain.Apps.Entities/Contents/ScheduleJob.cs b/src/Squidex.Domain.Apps.Entities/Contents/ScheduleJob.cs index 9936e98ef..69c580518 100644 --- a/src/Squidex.Domain.Apps.Entities/Contents/ScheduleJob.cs +++ b/src/Squidex.Domain.Apps.Entities/Contents/ScheduleJob.cs @@ -22,17 +22,17 @@ namespace Squidex.Domain.Apps.Entities.Contents public Instant DueTime { get; } - public ScheduleJob(Guid id, Status status, RefToken scheduledBy, Instant due) + public ScheduleJob(Guid id, Status status, RefToken scheduledBy, Instant dueTime) { Id = id; ScheduledBy = scheduledBy; Status = status; - DueTime = due; + DueTime = dueTime; } - public static ScheduleJob Build(Status status, RefToken by, Instant due) + public static ScheduleJob Build(Status status, RefToken by, Instant dueTime) { - return new ScheduleJob(Guid.NewGuid(), status, by, due); + return new ScheduleJob(Guid.NewGuid(), status, by, dueTime); } } } From 362e8d71c63216bc61bf29a0da31a8b33fe9966d Mon Sep 17 00:00:00 2001 From: Sebastian Stehle Date: Fri, 21 Jun 2019 17:58:59 +0200 Subject: [PATCH 35/47] Fix for Create and Edit with nested field. --- .../app/shared/services/schemas.service.ts | 2 +- .../app/shared/state/schemas.state.spec.ts | 17 ++++++++++++++--- src/Squidex/app/shared/state/schemas.state.ts | 2 +- 3 files changed, 16 insertions(+), 5 deletions(-) diff --git a/src/Squidex/app/shared/services/schemas.service.ts b/src/Squidex/app/shared/services/schemas.service.ts index e02391b2a..d2f6f7517 100644 --- a/src/Squidex/app/shared/services/schemas.service.ts +++ b/src/Squidex/app/shared/services/schemas.service.ts @@ -213,7 +213,7 @@ export class SchemaPropertiesDto { export interface AddFieldDto { readonly name: string; - readonly partitioning: string; + readonly partitioning?: string; readonly properties: FieldPropertiesDto; } diff --git a/src/Squidex/app/shared/state/schemas.state.spec.ts b/src/Squidex/app/shared/state/schemas.state.spec.ts index 4e8c74c74..0f0315218 100644 --- a/src/Squidex/app/shared/state/schemas.state.spec.ts +++ b/src/Squidex/app/shared/state/schemas.state.spec.ts @@ -13,6 +13,7 @@ import { SchemasState } from './schemas.state'; import { DialogService, + FieldDto, SchemaDetailsDto, SchemasService, UpdateSchemaCategoryDto, @@ -329,28 +330,38 @@ describe('SchemasState', () => { schemasService.setup(x => x.postField(app, schema1, It.isAny(), version)) .returns(() => of(updated)).verifiable(); - schemasState.addField(schema1, request).subscribe(); + let newField: FieldDto; + + schemasState.addField(schema1, request).subscribe(result => { + newField = result; + }); const schema1New = schemasState.snapshot.schemas.at(0); expect(schema1New).toEqual(updated); expect(schemasState.snapshot.selectedSchema).toEqual(updated); + expect(newField!).toBeDefined(); }); it('should update schema and selected schema when nested field added', () => { - const request = { ...schema.fields[0] }; + const request = { ...schema.fields[0].nested[0] }; const updated = createSchemaDetails(1, newVersion, '-new'); schemasService.setup(x => x.postField(app, schema.fields[0], It.isAny(), version)) .returns(() => of(updated)).verifiable(); - schemasState.addField(schema1, request, schema.fields[0]).subscribe(); + let newField: FieldDto; + + schemasState.addField(schema1, request, schema.fields[0]).subscribe(result => { + newField = result; + }); const schema1New = schemasState.snapshot.schemas.at(0); expect(schema1New).toEqual(updated); expect(schemasState.snapshot.selectedSchema).toEqual(updated); + expect(newField!).toBeDefined(); }); it('should update schema and selected schema when field removed', () => { diff --git a/src/Squidex/app/shared/state/schemas.state.ts b/src/Squidex/app/shared/state/schemas.state.ts index 68c3ea6d5..131fc1ad2 100644 --- a/src/Squidex/app/shared/state/schemas.state.ts +++ b/src/Squidex/app/shared/state/schemas.state.ts @@ -322,7 +322,7 @@ export class SchemasState extends State { function getField(x: SchemaDetailsDto, request: AddFieldDto, parent?: RootFieldDto): FieldDto { if (parent) { - return parent.nested.find(f => f.name === request.name)!; + return x.fields.find(f => f.fieldId === parent.fieldId)!.nested.find(f => f.name === request.name)!; } else { return x.fields.find(f => f.name === request.name)!; } From 880e8bf92dee27f01a26f001cf23ea6eb16bd017 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Adam=20Hlad=C3=ADk?= Date: Fri, 21 Jun 2019 19:50:08 +0200 Subject: [PATCH 36/47] Bad field name in GraphQL schema description (#370) * change nested field name source * nested field unique name * QueryGraphTypeVisitor property --- .../Contents/GraphQL/GraphQLModel.cs | 4 ++-- .../Contents/GraphQL/IGraphModel.cs | 2 +- .../Contents/GraphQL/Types/ContentDataGraphType.cs | 2 +- .../Contents/GraphQL/Types/NestedGraphType.cs | 10 +++++----- .../Contents/GraphQL/Types/QueryGraphTypeVisitor.cs | 6 ++++-- 5 files changed, 13 insertions(+), 11 deletions(-) diff --git a/src/Squidex.Domain.Apps.Entities/Contents/GraphQL/GraphQLModel.cs b/src/Squidex.Domain.Apps.Entities/Contents/GraphQL/GraphQLModel.cs index 1373ee437..9cb3dc67e 100644 --- a/src/Squidex.Domain.Apps.Entities/Contents/GraphQL/GraphQLModel.cs +++ b/src/Squidex.Domain.Apps.Entities/Contents/GraphQL/GraphQLModel.cs @@ -136,9 +136,9 @@ namespace Squidex.Domain.Apps.Entities.Contents.GraphQL return partitionResolver(key); } - public (IGraphType ResolveType, ValueResolver Resolver) GetGraphType(ISchemaEntity schema, IField field) + public (IGraphType ResolveType, ValueResolver Resolver) GetGraphType(ISchemaEntity schema, IField field, string fieldName) { - return field.Accept(new QueryGraphTypeVisitor(schema, GetContentType, this, assetListType)); + return field.Accept(new QueryGraphTypeVisitor(schema, GetContentType, this, assetListType, fieldName)); } public IGraphType GetAssetType() diff --git a/src/Squidex.Domain.Apps.Entities/Contents/GraphQL/IGraphModel.cs b/src/Squidex.Domain.Apps.Entities/Contents/GraphQL/IGraphModel.cs index f44c36b58..1ee303d6a 100644 --- a/src/Squidex.Domain.Apps.Entities/Contents/GraphQL/IGraphModel.cs +++ b/src/Squidex.Domain.Apps.Entities/Contents/GraphQL/IGraphModel.cs @@ -35,6 +35,6 @@ namespace Squidex.Domain.Apps.Entities.Contents.GraphQL IGraphType GetContentDataType(Guid schemaId); - (IGraphType ResolveType, ValueResolver Resolver) GetGraphType(ISchemaEntity schema, IField field); + (IGraphType ResolveType, ValueResolver Resolver) GetGraphType(ISchemaEntity schema, IField field, string fieldName); } } diff --git a/src/Squidex.Domain.Apps.Entities/Contents/GraphQL/Types/ContentDataGraphType.cs b/src/Squidex.Domain.Apps.Entities/Contents/GraphQL/Types/ContentDataGraphType.cs index 7dfd1480b..eb6ef19f5 100644 --- a/src/Squidex.Domain.Apps.Entities/Contents/GraphQL/Types/ContentDataGraphType.cs +++ b/src/Squidex.Domain.Apps.Entities/Contents/GraphQL/Types/ContentDataGraphType.cs @@ -27,7 +27,7 @@ namespace Squidex.Domain.Apps.Entities.Contents.GraphQL.Types foreach (var (field, fieldName, typeName) in schema.SchemaDef.Fields.SafeFields()) { - var (resolvedType, valueResolver) = model.GetGraphType(schema, field); + var (resolvedType, valueResolver) = model.GetGraphType(schema, field, fieldName); if (valueResolver != null) { diff --git a/src/Squidex.Domain.Apps.Entities/Contents/GraphQL/Types/NestedGraphType.cs b/src/Squidex.Domain.Apps.Entities/Contents/GraphQL/Types/NestedGraphType.cs index 7f64227bb..2964ed201 100644 --- a/src/Squidex.Domain.Apps.Entities/Contents/GraphQL/Types/NestedGraphType.cs +++ b/src/Squidex.Domain.Apps.Entities/Contents/GraphQL/Types/NestedGraphType.cs @@ -16,18 +16,18 @@ namespace Squidex.Domain.Apps.Entities.Contents.GraphQL.Types { public sealed class NestedGraphType : ObjectGraphType { - public NestedGraphType(IGraphModel model, ISchemaEntity schema, IArrayField field) + public NestedGraphType(IGraphModel model, ISchemaEntity schema, IArrayField field, string fieldName) { var schemaType = schema.TypeName(); var schemaName = schema.DisplayName(); - var fieldName = field.DisplayName(); + var fieldDisplayName = field.DisplayName(); Name = $"{schemaType}{fieldName}ChildDto"; foreach (var (nestedField, nestedName, _) in field.Fields.SafeFields()) { - var fieldInfo = model.GetGraphType(schema, nestedField); + var fieldInfo = model.GetGraphType(schema, nestedField, nestedName); if (fieldInfo.ResolveType != null) { @@ -38,12 +38,12 @@ namespace Squidex.Domain.Apps.Entities.Contents.GraphQL.Types Name = nestedName, Resolver = resolver, ResolvedType = fieldInfo.ResolveType, - Description = $"The {fieldName}/{nestedField.DisplayName()} nested field." + Description = $"The {fieldDisplayName}/{nestedField.DisplayName()} nested field." }); } } - Description = $"The structure of the {schemaName}.{fieldName} nested schema."; + Description = $"The structure of the {schemaName}.{fieldDisplayName} nested schema."; } private static FuncFieldResolver ValueResolver(NestedField nestedField, (IGraphType ResolveType, ValueResolver Resolver) fieldInfo) diff --git a/src/Squidex.Domain.Apps.Entities/Contents/GraphQL/Types/QueryGraphTypeVisitor.cs b/src/Squidex.Domain.Apps.Entities/Contents/GraphQL/Types/QueryGraphTypeVisitor.cs index 32a9a308f..195eee1a7 100644 --- a/src/Squidex.Domain.Apps.Entities/Contents/GraphQL/Types/QueryGraphTypeVisitor.cs +++ b/src/Squidex.Domain.Apps.Entities/Contents/GraphQL/Types/QueryGraphTypeVisitor.cs @@ -22,13 +22,15 @@ namespace Squidex.Domain.Apps.Entities.Contents.GraphQL.Types private readonly Func schemaResolver; private readonly IGraphModel model; private readonly IGraphType assetListType; + private readonly string fieldName; - public QueryGraphTypeVisitor(ISchemaEntity schema, Func schemaResolver, IGraphModel model, IGraphType assetListType) + public QueryGraphTypeVisitor(ISchemaEntity schema, Func schemaResolver, IGraphModel model, IGraphType assetListType, string fieldName) { this.model = model; this.assetListType = assetListType; this.schema = schema; this.schemaResolver = schemaResolver; + this.fieldName = fieldName; } public (IGraphType ResolveType, ValueResolver Resolver) Visit(IArrayField field) @@ -93,7 +95,7 @@ namespace Squidex.Domain.Apps.Entities.Contents.GraphQL.Types private (IGraphType ResolveType, ValueResolver Resolver) ResolveNested(IArrayField field) { - var schemaFieldType = new ListGraphType(new NonNullGraphType(new NestedGraphType(model, schema, field))); + var schemaFieldType = new ListGraphType(new NonNullGraphType(new NestedGraphType(model, schema, field, this.fieldName))); return (schemaFieldType, NoopResolver); } From 4b7fa30f4aff2d9b8214e4862f89b885f5645bb5 Mon Sep 17 00:00:00 2001 From: Sebastian Date: Fri, 21 Jun 2019 20:05:00 +0200 Subject: [PATCH 37/47] Fix for scheduling. --- .../Contents/ScheduleJob.cs | 11 ++++++----- .../Api/Controllers/Contents/Models/ScheduleJobDto.cs | 10 ++++++---- 2 files changed, 12 insertions(+), 9 deletions(-) diff --git a/src/Squidex.Domain.Apps.Entities/Contents/ScheduleJob.cs b/src/Squidex.Domain.Apps.Entities/Contents/ScheduleJob.cs index 9936e98ef..4145dd954 100644 --- a/src/Squidex.Domain.Apps.Entities/Contents/ScheduleJob.cs +++ b/src/Squidex.Domain.Apps.Entities/Contents/ScheduleJob.cs @@ -1,4 +1,5 @@ -// ========================================================================== + +// ========================================================================== // Squidex Headless CMS // ========================================================================== // Copyright (c) Squidex UG (haftungsbeschraenkt) @@ -22,17 +23,17 @@ namespace Squidex.Domain.Apps.Entities.Contents public Instant DueTime { get; } - public ScheduleJob(Guid id, Status status, RefToken scheduledBy, Instant due) + public ScheduleJob(Guid id, Status status, RefToken scheduledBy, Instant dueTime) { Id = id; ScheduledBy = scheduledBy; Status = status; - DueTime = due; + DueTime = dueTime; } - public static ScheduleJob Build(Status status, RefToken by, Instant due) + public static ScheduleJob Build(Status status, RefToken scheduledBy, Instant dueTime) { - return new ScheduleJob(Guid.NewGuid(), status, by, due); + return new ScheduleJob(Guid.NewGuid(), status, scheduledBy, dueTime); } } } diff --git a/src/Squidex/Areas/Api/Controllers/Contents/Models/ScheduleJobDto.cs b/src/Squidex/Areas/Api/Controllers/Contents/Models/ScheduleJobDto.cs index b0e7b34cb..ef7ebda7b 100644 --- a/src/Squidex/Areas/Api/Controllers/Contents/Models/ScheduleJobDto.cs +++ b/src/Squidex/Areas/Api/Controllers/Contents/Models/ScheduleJobDto.cs @@ -6,6 +6,7 @@ // ========================================================================== using System; +using System.ComponentModel.DataAnnotations; using NodaTime; using Squidex.Domain.Apps.Core.Contents; using Squidex.Infrastructure; @@ -25,13 +26,14 @@ namespace Squidex.Areas.Api.Controllers.Contents.Models public Status Status { get; set; } /// - /// The user who schedule the content. + /// The target date and time when the content should be scheduled. /// - public RefToken ScheduledBy { get; set; } + public Instant DueTime { get; set; } /// - /// The target date and time when the content should be scheduled. + /// The user who schedule the content. /// - public Instant DueTime { get; set; } + [Required] + public RefToken ScheduledBy { get; set; } } } From 1f804e7f83196f7a7ef8e17f570a848717857d23 Mon Sep 17 00:00:00 2001 From: Sebastian Date: Fri, 21 Jun 2019 20:18:23 +0200 Subject: [PATCH 38/47] Changed representation of Status to string. --- src/Squidex/Areas/Api/Config/Swagger/SwaggerServices.cs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/Squidex/Areas/Api/Config/Swagger/SwaggerServices.cs b/src/Squidex/Areas/Api/Config/Swagger/SwaggerServices.cs index f3b32121f..050a7619c 100644 --- a/src/Squidex/Areas/Api/Config/Swagger/SwaggerServices.cs +++ b/src/Squidex/Areas/Api/Config/Swagger/SwaggerServices.cs @@ -14,6 +14,7 @@ using NSwag.SwaggerGeneration; using NSwag.SwaggerGeneration.Processors; using Squidex.Areas.Api.Controllers.Contents.Generator; using Squidex.Areas.Api.Controllers.Rules.Models; +using Squidex.Domain.Apps.Core.Contents; using Squidex.Infrastructure; namespace Squidex.Areas.Api.Config.Swagger @@ -76,7 +77,8 @@ namespace Squidex.Areas.Api.Config.Swagger }), new PrimitiveTypeMapper(typeof(Language), s => s.Type = JsonObjectType.String), - new PrimitiveTypeMapper(typeof(RefToken), s => s.Type = JsonObjectType.String) + new PrimitiveTypeMapper(typeof(RefToken), s => s.Type = JsonObjectType.String), + new PrimitiveTypeMapper(typeof(Status), s => s.Type = JsonObjectType.String), }; } } From c1bc9e7edaf22131217e4adbb7c265dcc0075ef9 Mon Sep 17 00:00:00 2001 From: Sebastian Date: Fri, 21 Jun 2019 22:01:55 +0200 Subject: [PATCH 39/47] DataLoader implemented. --- .../Contents/GraphQL/CachingGraphQLService.cs | 46 ++++------- .../GraphQL/GraphQLExecutionContext.cs | 78 ++++++++++++++++--- .../Contents/GraphQL/GraphQLModel.cs | 18 ++--- .../Contents/ScheduleJob.cs | 3 +- src/Squidex/Config/Domain/EntitiesServices.cs | 14 ++++ .../Contents/GraphQL/GraphQLTestBase.cs | 41 +++++++--- 6 files changed, 137 insertions(+), 63 deletions(-) diff --git a/src/Squidex.Domain.Apps.Entities/Contents/GraphQL/CachingGraphQLService.cs b/src/Squidex.Domain.Apps.Entities/Contents/GraphQL/CachingGraphQLService.cs index e56e28cb3..1a01b229a 100644 --- a/src/Squidex.Domain.Apps.Entities/Contents/GraphQL/CachingGraphQLService.cs +++ b/src/Squidex.Domain.Apps.Entities/Contents/GraphQL/CachingGraphQLService.cs @@ -8,43 +8,25 @@ using System; using System.Linq; using System.Threading.Tasks; +using GraphQL; using Microsoft.Extensions.Caching.Memory; using Squidex.Domain.Apps.Entities.Apps; using Squidex.Domain.Apps.Entities.Assets; using Squidex.Infrastructure; -using Squidex.Infrastructure.Log; namespace Squidex.Domain.Apps.Entities.Contents.GraphQL { public sealed class CachingGraphQLService : CachingProviderBase, IGraphQLService { private static readonly TimeSpan CacheDuration = TimeSpan.FromMinutes(10); - private readonly IContentQueryService contentQuery; - private readonly IGraphQLUrlGenerator urlGenerator; - private readonly ISemanticLog log; - private readonly IAssetQueryService assetQuery; - private readonly IAppProvider appProvider; - - public CachingGraphQLService( - IMemoryCache cache, - IAppProvider appProvider, - IAssetQueryService assetQuery, - IContentQueryService contentQuery, - IGraphQLUrlGenerator urlGenerator, - ISemanticLog log) + private readonly IDependencyResolver resolver; + + public CachingGraphQLService(IMemoryCache cache, IDependencyResolver resolver) : base(cache) { - Guard.NotNull(appProvider, nameof(appProvider)); - Guard.NotNull(assetQuery, nameof(assetQuery)); - Guard.NotNull(contentQuery, nameof(contentQuery)); - Guard.NotNull(urlGenerator, nameof(urlGenerator)); - Guard.NotNull(log, nameof(log)); - - this.appProvider = appProvider; - this.assetQuery = assetQuery; - this.contentQuery = contentQuery; - this.urlGenerator = urlGenerator; - this.log = log; + Guard.NotNull(resolver, nameof(resolver)); + + this.resolver = resolver; } public async Task<(bool HasError, object Response)> QueryAsync(QueryContext context, params GraphQLQuery[] queries) @@ -54,7 +36,7 @@ namespace Squidex.Domain.Apps.Entities.Contents.GraphQL var model = await GetModelAsync(context.App); - var ctx = new GraphQLExecutionContext(context, assetQuery, contentQuery, urlGenerator); + var ctx = new GraphQLExecutionContext(context, resolver); var result = await Task.WhenAll(queries.Select(q => QueryInternalAsync(model, ctx, q))); @@ -68,7 +50,7 @@ namespace Squidex.Domain.Apps.Entities.Contents.GraphQL var model = await GetModelAsync(context.App); - var ctx = new GraphQLExecutionContext(context, assetQuery, contentQuery, urlGenerator); + var ctx = new GraphQLExecutionContext(context, resolver); var result = await QueryInternalAsync(model, ctx, query); @@ -82,7 +64,7 @@ namespace Squidex.Domain.Apps.Entities.Contents.GraphQL return (false, new { data = new object() }); } - var result = await model.ExecuteAsync(ctx, query, log); + var result = await model.ExecuteAsync(ctx, query); if (result.Errors?.Any() == true) { @@ -102,9 +84,13 @@ namespace Squidex.Domain.Apps.Entities.Contents.GraphQL { entry.AbsoluteExpirationRelativeToNow = CacheDuration; - var allSchemas = await appProvider.GetSchemasAsync(app.Id); + var allSchemas = await resolver.Resolve().GetSchemasAsync(app.Id); - return new GraphQLModel(app, allSchemas, contentQuery.DefaultPageSizeGraphQl, assetQuery.DefaultPageSizeGraphQl, urlGenerator); + return new GraphQLModel(app, + allSchemas, + resolver.Resolve().DefaultPageSizeGraphQl, + resolver.Resolve().DefaultPageSizeGraphQl, + resolver.Resolve()); }); } diff --git a/src/Squidex.Domain.Apps.Entities/Contents/GraphQL/GraphQLExecutionContext.cs b/src/Squidex.Domain.Apps.Entities/Contents/GraphQL/GraphQLExecutionContext.cs index 54a2793ab..c2587b747 100644 --- a/src/Squidex.Domain.Apps.Entities/Contents/GraphQL/GraphQLExecutionContext.cs +++ b/src/Squidex.Domain.Apps.Entities/Contents/GraphQL/GraphQLExecutionContext.cs @@ -7,37 +7,93 @@ using System; using System.Collections.Generic; +using System.Linq; using System.Threading.Tasks; +using GraphQL; +using GraphQL.DataLoader; using Squidex.Domain.Apps.Entities.Assets; using Squidex.Infrastructure.Json.Objects; +using Squidex.Infrastructure.Log; namespace Squidex.Domain.Apps.Entities.Contents.GraphQL { public sealed class GraphQLExecutionContext : QueryExecutionContext { + private static readonly List EmptyAssets = new List(); + private static readonly List EmptyContents = new List(); + private readonly IDataLoaderContextAccessor dataLoaderContextAccessor; + private readonly IDependencyResolver resolver; + public IGraphQLUrlGenerator UrlGenerator { get; } - public GraphQLExecutionContext(QueryContext context, - IAssetQueryService assetQuery, - IContentQueryService contentQuery, - IGraphQLUrlGenerator urlGenerator) - : base(context, assetQuery, contentQuery) + public ISemanticLog Log { get; } + + public GraphQLExecutionContext(QueryContext context, IDependencyResolver resolver) + : base(context, + resolver.Resolve(), + resolver.Resolve()) + { + UrlGenerator = resolver.Resolve(); + + dataLoaderContextAccessor = resolver.Resolve(); + + this.resolver = resolver; + } + + public void Setup(ExecutionOptions execution) { - UrlGenerator = urlGenerator; + var loader = resolver.Resolve(); + + execution.Listeners.Add(loader); + execution.FieldMiddleware.Use(LoggingMiddleware.Create(resolver.Resolve())); + + execution.UserContext = this; } - public Task> GetReferencedAssetsAsync(IJsonValue value) + public async Task> GetReferencedAssetsAsync(IJsonValue value) { var ids = ParseIds(value); - return GetReferencedAssetsAsync(ids); + if (ids == null) + { + return EmptyAssets; + } + + var dataLoader = + dataLoaderContextAccessor.Context.GetOrAddBatchLoader("Assets", + async batch => + { + var result = await GetReferencedAssetsAsync(new List(batch)); + + return result.ToDictionary(x => x.Id); + }); + + var assets = await Task.WhenAll(ids.Select(x => dataLoader.LoadAsync(x))); + + return assets.Where(x => x != null).ToList(); } - public Task> GetReferencedContentsAsync(Guid schemaId, IJsonValue value) + public async Task> GetReferencedContentsAsync(Guid schemaId, IJsonValue value) { var ids = ParseIds(value); - return GetReferencedContentsAsync(schemaId, ids); + if (ids == null) + { + return EmptyContents; + } + + var dataLoader = + dataLoaderContextAccessor.Context.GetOrAddBatchLoader($"Schema_{schemaId}", + async batch => + { + var result = await GetReferencedContentsAsync(schemaId, new List(batch)); + + return result.ToDictionary(x => x.Id); + }); + + var contents = await Task.WhenAll(ids.Select(x => dataLoader.LoadAsync(x))); + + return contents.Where(x => x != null).ToList(); } private static ICollection ParseIds(IJsonValue value) @@ -58,7 +114,7 @@ namespace Squidex.Domain.Apps.Entities.Contents.GraphQL } catch { - return new List(); + return null; } } } diff --git a/src/Squidex.Domain.Apps.Entities/Contents/GraphQL/GraphQLModel.cs b/src/Squidex.Domain.Apps.Entities/Contents/GraphQL/GraphQLModel.cs index 9cb3dc67e..5f4ee3be3 100644 --- a/src/Squidex.Domain.Apps.Entities/Contents/GraphQL/GraphQLModel.cs +++ b/src/Squidex.Domain.Apps.Entities/Contents/GraphQL/GraphQLModel.cs @@ -20,7 +20,6 @@ using Squidex.Domain.Apps.Entities.Contents.GraphQL.Types; using Squidex.Domain.Apps.Entities.Contents.GraphQL.Types.Utils; using Squidex.Domain.Apps.Entities.Schemas; using Squidex.Infrastructure; -using Squidex.Infrastructure.Log; using GraphQLSchema = GraphQL.Types.Schema; #pragma warning disable IDE0003 @@ -172,20 +171,17 @@ namespace Squidex.Domain.Apps.Entities.Contents.GraphQL return contentTypes.GetOrAdd(schema, s => new ContentGraphType()); } - public async Task<(object Data, object[] Errors)> ExecuteAsync(GraphQLExecutionContext context, GraphQLQuery query, ISemanticLog log) + public async Task<(object Data, object[] Errors)> ExecuteAsync(GraphQLExecutionContext context, GraphQLQuery query) { Guard.NotNull(context, nameof(context)); - var inputs = query.Variables?.ToInputs(); - - var result = await new DocumentExecuter().ExecuteAsync(options => + var result = await new DocumentExecuter().ExecuteAsync(execution => { - options.FieldMiddleware.Use(LoggingMiddleware.Create(log)); - options.OperationName = query.OperationName; - options.UserContext = context; - options.Schema = graphQLSchema; - options.Inputs = inputs; - options.Query = query.Query; + context.Setup(execution); + + execution.Schema = graphQLSchema; + execution.Inputs = query.Variables?.ToInputs(); + execution.Query = query.Query; }).ConfigureAwait(false); return (result.Data, result.Errors?.Select(x => (object)new { x.Message, x.Locations }).ToArray()); diff --git a/src/Squidex.Domain.Apps.Entities/Contents/ScheduleJob.cs b/src/Squidex.Domain.Apps.Entities/Contents/ScheduleJob.cs index 4145dd954..fe48b89e4 100644 --- a/src/Squidex.Domain.Apps.Entities/Contents/ScheduleJob.cs +++ b/src/Squidex.Domain.Apps.Entities/Contents/ScheduleJob.cs @@ -1,5 +1,4 @@ - -// ========================================================================== +// ========================================================================== // Squidex Headless CMS // ========================================================================== // Copyright (c) Squidex UG (haftungsbeschraenkt) diff --git a/src/Squidex/Config/Domain/EntitiesServices.cs b/src/Squidex/Config/Domain/EntitiesServices.cs index 1b378c173..99092c745 100644 --- a/src/Squidex/Config/Domain/EntitiesServices.cs +++ b/src/Squidex/Config/Domain/EntitiesServices.cs @@ -6,6 +6,8 @@ // ========================================================================== using System; +using GraphQL; +using GraphQL.DataLoader; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Options; @@ -74,6 +76,18 @@ namespace Squidex.Config.Domain services.AddSingletonAs() .As().As(); + services.AddSingletonAs(x => new FuncDependencyResolver(t => x.GetRequiredService(t))) + .As(); + + services.AddSingletonAs() + .As(); + + services.AddSingletonAs() + .AsSelf(); + + services.AddSingletonAs() + .As(); + services.AddSingletonAs() .As(); diff --git a/tests/Squidex.Domain.Apps.Entities.Tests/Contents/GraphQL/GraphQLTestBase.cs b/tests/Squidex.Domain.Apps.Entities.Tests/Contents/GraphQL/GraphQLTestBase.cs index 53e155449..7012ae1fd 100644 --- a/tests/Squidex.Domain.Apps.Entities.Tests/Contents/GraphQL/GraphQLTestBase.cs +++ b/tests/Squidex.Domain.Apps.Entities.Tests/Contents/GraphQL/GraphQLTestBase.cs @@ -9,6 +9,8 @@ using System; using System.Collections.Generic; using System.Security.Claims; using FakeItEasy; +using GraphQL; +using GraphQL.DataLoader; using Microsoft.Extensions.Caching.Memory; using Microsoft.Extensions.Options; using Newtonsoft.Json; @@ -34,7 +36,6 @@ namespace Squidex.Domain.Apps.Entities.Contents.GraphQL { public class GraphQLTestBase { - protected readonly Schema schemaDef; protected readonly Guid schemaId = Guid.NewGuid(); protected readonly Guid appId = Guid.NewGuid(); protected readonly string appName = "my-app"; @@ -42,8 +43,7 @@ namespace Squidex.Domain.Apps.Entities.Contents.GraphQL protected readonly IAssetQueryService assetQuery = A.Fake(); protected readonly ISchemaEntity schema = A.Fake(); protected readonly IJsonSerializer serializer = TestUtils.CreateSerializer(TypeNameHandling.None); - protected readonly IMemoryCache cache = new MemoryCache(Options.Create(new MemoryCacheOptions())); - protected readonly IAppProvider appProvider = A.Fake(); + protected readonly IDependencyResolver dependencyResolver; protected readonly IAppEntity app = A.Dummy(); protected readonly QueryContext context; protected readonly ClaimsPrincipal user = new ClaimsPrincipal(); @@ -51,7 +51,7 @@ namespace Squidex.Domain.Apps.Entities.Contents.GraphQL public GraphQLTestBase() { - schemaDef = + var schemaDef = new Schema("my-schema") .AddJson(1, "my-json", Partitioning.Invariant, new JsonFieldProperties()) @@ -93,11 +93,7 @@ namespace Squidex.Domain.Apps.Entities.Contents.GraphQL A.CallTo(() => schema.Id).Returns(schemaId); A.CallTo(() => schema.SchemaDef).Returns(schemaDef); - var allSchemas = new List { schema }; - - A.CallTo(() => appProvider.GetSchemasAsync(appId)).Returns(allSchemas); - - sut = new CachingGraphQLService(cache, appProvider, assetQuery, contentQuery, new FakeUrlGenerator(), A.Fake()); + sut = CreateSut(); } protected static IContentEntity CreateContent(Guid id, Guid refId, Guid assetId, NamedContentData data = null, NamedContentData dataDraft = null) @@ -210,5 +206,32 @@ namespace Squidex.Domain.Apps.Entities.Contents.GraphQL { return serializer.Serialize(result); } + + private CachingGraphQLService CreateSut() + { + var appProvider = A.Fake(); + + A.CallTo(() => appProvider.GetSchemasAsync(appId)) + .Returns(new List { schema }); + + var dataLoaderContext = new DataLoaderContextAccessor(); + + var services = new Dictionary + { + [typeof(IAppProvider)] = appProvider, + [typeof(IAssetQueryService)] = assetQuery, + [typeof(IContentQueryService)] = contentQuery, + [typeof(IDataLoaderContextAccessor)] = dataLoaderContext, + [typeof(IGraphQLUrlGenerator)] = new FakeUrlGenerator(), + [typeof(ISemanticLog)] = A.Fake(), + [typeof(DataLoaderDocumentListener)] = new DataLoaderDocumentListener(dataLoaderContext) + }; + + var resolver = new FuncDependencyResolver(t => services[t]); + + var cache = new MemoryCache(Options.Create(new MemoryCacheOptions())); + + return new CachingGraphQLService(cache, resolver); + } } } From 0df169ea3430d40009fff50a6b7df383ce2c1786 Mon Sep 17 00:00:00 2001 From: Sebastian Date: Fri, 21 Jun 2019 22:23:02 +0200 Subject: [PATCH 40/47] Just some formatting. --- .../Contents/GraphQL/GraphQLExecutionContext.cs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/Squidex.Domain.Apps.Entities/Contents/GraphQL/GraphQLExecutionContext.cs b/src/Squidex.Domain.Apps.Entities/Contents/GraphQL/GraphQLExecutionContext.cs index c2587b747..aeb62077b 100644 --- a/src/Squidex.Domain.Apps.Entities/Contents/GraphQL/GraphQLExecutionContext.cs +++ b/src/Squidex.Domain.Apps.Entities/Contents/GraphQL/GraphQLExecutionContext.cs @@ -44,8 +44,10 @@ namespace Squidex.Domain.Apps.Entities.Contents.GraphQL { var loader = resolver.Resolve(); + var logger = LoggingMiddleware.Create(resolver.Resolve()); + execution.Listeners.Add(loader); - execution.FieldMiddleware.Use(LoggingMiddleware.Create(resolver.Resolve())); + execution.FieldMiddleware.Use(logger); execution.UserContext = this; } From af6c3808a9c99d9dec57800f5474ee2d9ea7ebb6 Mon Sep 17 00:00:00 2001 From: Sebastian Date: Fri, 21 Jun 2019 23:08:01 +0200 Subject: [PATCH 41/47] More optimizations. --- .../Assets/MongoAssetRepository.cs | 7 +-- .../Contents/MongoContentCollection.cs | 9 +-- .../GraphQL/GraphQLExecutionContext.cs | 59 ++++++++++++------- .../Contents/GraphQL/Types/Extensions.cs | 9 +++ .../Contents/QueryExecutionContext.cs | 4 +- src/Squidex.Domain.Apps.Entities/Q.cs | 5 ++ .../Contents/GraphQL/GraphQLQueriesTests.cs | 48 ++++++++------- 7 files changed, 87 insertions(+), 54 deletions(-) diff --git a/src/Squidex.Domain.Apps.Entities.MongoDb/Assets/MongoAssetRepository.cs b/src/Squidex.Domain.Apps.Entities.MongoDb/Assets/MongoAssetRepository.cs index 44d93d8d4..6444ba638 100644 --- a/src/Squidex.Domain.Apps.Entities.MongoDb/Assets/MongoAssetRepository.cs +++ b/src/Squidex.Domain.Apps.Entities.MongoDb/Assets/MongoAssetRepository.cs @@ -119,12 +119,9 @@ namespace Squidex.Domain.Apps.Entities.MongoDb.Assets { var find = Collection.Find(x => ids.Contains(x.Id)).SortByDescending(x => x.LastModified); - var assetItems = find.ToListAsync(); - var assetCount = find.CountDocumentsAsync(); + var assetItems = await find.ToListAsync(); - await Task.WhenAll(assetItems, assetCount); - - return ResultList.Create(assetCount.Result, assetItems.Result.OfType()); + return ResultList.Create(assetItems.Count, assetItems.OfType()); } } diff --git a/src/Squidex.Domain.Apps.Entities.MongoDb/Contents/MongoContentCollection.cs b/src/Squidex.Domain.Apps.Entities.MongoDb/Contents/MongoContentCollection.cs index 1bb4c6128..9424333c0 100644 --- a/src/Squidex.Domain.Apps.Entities.MongoDb/Contents/MongoContentCollection.cs +++ b/src/Squidex.Domain.Apps.Entities.MongoDb/Contents/MongoContentCollection.cs @@ -137,17 +137,14 @@ namespace Squidex.Domain.Apps.Entities.MongoDb.Contents { var find = Collection.Find(FilterFactory.IdsBySchema(schema.Id, ids, status)); - var contentItems = find.WithoutDraft(includeDraft).ToListAsync(); - var contentCount = find.CountDocumentsAsync(); - - await Task.WhenAll(contentItems, contentCount); + var contentItems = await find.WithoutDraft(includeDraft).ToListAsync(); - foreach (var entity in contentItems.Result) + foreach (var entity in contentItems) { entity.ParseData(schema.SchemaDef, serializer); } - return ResultList.Create(contentCount.Result, contentItems.Result); + return ResultList.Create(contentItems.Count, contentItems); } public async Task FindContentAsync(ISchemaEntity schema, Guid id, Status[] status, bool includeDraft) diff --git a/src/Squidex.Domain.Apps.Entities/Contents/GraphQL/GraphQLExecutionContext.cs b/src/Squidex.Domain.Apps.Entities/Contents/GraphQL/GraphQLExecutionContext.cs index aeb62077b..c5dbf6024 100644 --- a/src/Squidex.Domain.Apps.Entities/Contents/GraphQL/GraphQLExecutionContext.cs +++ b/src/Squidex.Domain.Apps.Entities/Contents/GraphQL/GraphQLExecutionContext.cs @@ -12,6 +12,7 @@ using System.Threading.Tasks; using GraphQL; using GraphQL.DataLoader; using Squidex.Domain.Apps.Entities.Assets; +using Squidex.Domain.Apps.Entities.Contents.GraphQL.Types; using Squidex.Infrastructure.Json.Objects; using Squidex.Infrastructure.Log; @@ -52,6 +53,20 @@ namespace Squidex.Domain.Apps.Entities.Contents.GraphQL execution.UserContext = this; } + public override Task FindAssetAsync(Guid id) + { + var dataLoader = GetAssetsLoader(); + + return dataLoader.LoadAsync(id); + } + + public override Task FindContentAsync(Guid schemaId, Guid id) + { + var dataLoader = GetContentsLoader(schemaId); + + return dataLoader.LoadAsync(id); + } + public async Task> GetReferencedAssetsAsync(IJsonValue value) { var ids = ParseIds(value); @@ -61,18 +76,9 @@ namespace Squidex.Domain.Apps.Entities.Contents.GraphQL return EmptyAssets; } - var dataLoader = - dataLoaderContextAccessor.Context.GetOrAddBatchLoader("Assets", - async batch => - { - var result = await GetReferencedAssetsAsync(new List(batch)); - - return result.ToDictionary(x => x.Id); - }); + var dataLoader = GetAssetsLoader(); - var assets = await Task.WhenAll(ids.Select(x => dataLoader.LoadAsync(x))); - - return assets.Where(x => x != null).ToList(); + return await dataLoader.LoadManyAsync(ids); } public async Task> GetReferencedContentsAsync(Guid schemaId, IJsonValue value) @@ -84,18 +90,31 @@ namespace Squidex.Domain.Apps.Entities.Contents.GraphQL return EmptyContents; } - var dataLoader = - dataLoaderContextAccessor.Context.GetOrAddBatchLoader($"Schema_{schemaId}", - async batch => - { - var result = await GetReferencedContentsAsync(schemaId, new List(batch)); + var dataLoader = GetContentsLoader(schemaId); + + return await dataLoader.LoadManyAsync(ids); + } + + private IDataLoader GetAssetsLoader() + { + return dataLoaderContextAccessor.Context.GetOrAddBatchLoader("Assets", + async batch => + { + var result = await GetReferencedAssetsAsync(new List(batch)); - return result.ToDictionary(x => x.Id); - }); + return result.ToDictionary(x => x.Id); + }); + } - var contents = await Task.WhenAll(ids.Select(x => dataLoader.LoadAsync(x))); + private IDataLoader GetContentsLoader(Guid schemaId) + { + return dataLoaderContextAccessor.Context.GetOrAddBatchLoader($"Schema_{schemaId}", + async batch => + { + var result = await GetReferencedContentsAsync(schemaId, new List(batch)); - return contents.Where(x => x != null).ToList(); + return result.ToDictionary(x => x.Id); + }); } private static ICollection ParseIds(IJsonValue value) diff --git a/src/Squidex.Domain.Apps.Entities/Contents/GraphQL/Types/Extensions.cs b/src/Squidex.Domain.Apps.Entities/Contents/GraphQL/Types/Extensions.cs index 9531680b0..5b78b2728 100644 --- a/src/Squidex.Domain.Apps.Entities/Contents/GraphQL/Types/Extensions.cs +++ b/src/Squidex.Domain.Apps.Entities/Contents/GraphQL/Types/Extensions.cs @@ -7,6 +7,8 @@ using System.Collections.Generic; using System.Linq; +using System.Threading.Tasks; +using GraphQL.DataLoader; using Squidex.Domain.Apps.Core.Schemas; using Squidex.Infrastructure; @@ -37,5 +39,12 @@ namespace Squidex.Domain.Apps.Entities.Contents.GraphQL.Types return value; } + + public static async Task> LoadManyAsync(this IDataLoader dataLoader, ICollection keys) where T : class + { + var contents = await Task.WhenAll(keys.Select(x => dataLoader.LoadAsync(x))); + + return contents.Where(x => x != null).ToList(); + } } } diff --git a/src/Squidex.Domain.Apps.Entities/Contents/QueryExecutionContext.cs b/src/Squidex.Domain.Apps.Entities/Contents/QueryExecutionContext.cs index 666b7474d..b1615f3a1 100644 --- a/src/Squidex.Domain.Apps.Entities/Contents/QueryExecutionContext.cs +++ b/src/Squidex.Domain.Apps.Entities/Contents/QueryExecutionContext.cs @@ -34,7 +34,7 @@ namespace Squidex.Domain.Apps.Entities.Contents this.context = context; } - public async Task FindAssetAsync(Guid id) + public virtual async Task FindAssetAsync(Guid id) { var asset = cachedAssets.GetOrDefault(id); @@ -51,7 +51,7 @@ namespace Squidex.Domain.Apps.Entities.Contents return asset; } - public async Task FindContentAsync(Guid schemaId, Guid id) + public virtual async Task FindContentAsync(Guid schemaId, Guid id) { var content = cachedContents.GetOrDefault(id); diff --git a/src/Squidex.Domain.Apps.Entities/Q.cs b/src/Squidex.Domain.Apps.Entities/Q.cs index 8bd9b0f39..966bdd279 100644 --- a/src/Squidex.Domain.Apps.Entities/Q.cs +++ b/src/Squidex.Domain.Apps.Entities/Q.cs @@ -25,6 +25,11 @@ namespace Squidex.Domain.Apps.Entities return Clone(c => c.ODataQuery = odataQuery); } + public Q WithIds(params Guid[] ids) + { + return Clone(c => c.Ids = ids.ToList()); + } + public Q WithIds(IEnumerable ids) { return Clone(c => c.Ids = ids.ToList()); diff --git a/tests/Squidex.Domain.Apps.Entities.Tests/Contents/GraphQL/GraphQLQueriesTests.cs b/tests/Squidex.Domain.Apps.Entities.Tests/Contents/GraphQL/GraphQLQueriesTests.cs index 09b5afd92..2e503ffdf 100644 --- a/tests/Squidex.Domain.Apps.Entities.Tests/Contents/GraphQL/GraphQLQueriesTests.cs +++ b/tests/Squidex.Domain.Apps.Entities.Tests/Contents/GraphQL/GraphQLQueriesTests.cs @@ -212,8 +212,8 @@ namespace Squidex.Domain.Apps.Entities.Contents.GraphQL } }".Replace("", assetId.ToString()); - A.CallTo(() => assetQuery.FindAssetAsync(MatchsAssetContext(), assetId)) - .Returns(asset); + A.CallTo(() => assetQuery.QueryAsync(MatchsAssetContext(), MatchId(assetId))) + .Returns(ResultList.Create(1, asset)); var result = await sut.QueryAsync(context, new GraphQLQuery { Query = query }); @@ -544,8 +544,8 @@ namespace Squidex.Domain.Apps.Entities.Contents.GraphQL } }".Replace("", contentId.ToString()); - A.CallTo(() => contentQuery.FindContentAsync(MatchsContentContext(), schemaId.ToString(), contentId, EtagVersion.Any)) - .Returns(content); + A.CallTo(() => contentQuery.QueryAsync(MatchsContentContext(), schemaId.ToString(), MatchId(contentId))) + .Returns(ResultList.Create(1, content)); var result = await sut.QueryAsync(context, new GraphQLQuery { Query = query }); @@ -635,8 +635,8 @@ namespace Squidex.Domain.Apps.Entities.Contents.GraphQL } }".Replace("", contentId.ToString()); - A.CallTo(() => contentQuery.FindContentAsync(MatchsContentContext(), schemaId.ToString(), contentId, EtagVersion.Any)) - .Returns(content); + A.CallTo(() => contentQuery.QueryAsync(MatchsContentContext(), schemaId.ToString(), MatchId(contentId))) + .Returns(ResultList.Create(1, content)); var result = await sut.QueryAsync(context, new GraphQLQuery { Query = query }); @@ -730,12 +730,12 @@ namespace Squidex.Domain.Apps.Entities.Contents.GraphQL } }".Replace("", contentId.ToString()); - A.CallTo(() => contentQuery.FindContentAsync(MatchsContentContext(), schemaId.ToString(), contentId, EtagVersion.Any)) - .Returns(content); - A.CallTo(() => contentQuery.QueryAsync(MatchsContentContext(), schemaId.ToString(), A.Ignored)) .Returns(ResultList.Create(0, contentRef)); + A.CallTo(() => contentQuery.QueryAsync(MatchsContentContext(), schemaId.ToString(), MatchId(contentId))) + .Returns(ResultList.Create(1, content)); + var result = await sut.QueryAsync(context, new GraphQLQuery { Query = query }); var expected = new @@ -788,8 +788,8 @@ namespace Squidex.Domain.Apps.Entities.Contents.GraphQL } }".Replace("", contentId.ToString()); - A.CallTo(() => contentQuery.FindContentAsync(MatchsContentContext(), schemaId.ToString(), contentId, EtagVersion.Any)) - .Returns(content); + A.CallTo(() => contentQuery.QueryAsync(MatchsContentContext(), schemaId.ToString(), MatchId(contentId))) + .Returns(ResultList.Create(1, content)); A.CallTo(() => assetQuery.QueryAsync(MatchsAssetContext(), A.Ignored)) .Returns(ResultList.Create(0, assetRef)); @@ -844,10 +844,11 @@ namespace Squidex.Domain.Apps.Entities.Contents.GraphQL } }".Replace("", assetId2.ToString()); - A.CallTo(() => assetQuery.FindAssetAsync(MatchsAssetContext(), assetId1)) - .Returns(asset1); - A.CallTo(() => assetQuery.FindAssetAsync(MatchsAssetContext(), assetId2)) - .Returns(asset2); + A.CallTo(() => assetQuery.QueryAsync(MatchsAssetContext(), MatchId(assetId1))) + .Returns(ResultList.Create(0, asset1)); + + A.CallTo(() => assetQuery.QueryAsync(MatchsAssetContext(), MatchId(assetId2))) + .Returns(ResultList.Create(0, asset2)); var result = await sut.QueryAsync(context, new GraphQLQuery { Query = query1 }, new GraphQLQuery { Query = query2 }); @@ -902,8 +903,8 @@ namespace Squidex.Domain.Apps.Entities.Contents.GraphQL } }".Replace("", contentId.ToString()); - A.CallTo(() => contentQuery.FindContentAsync(MatchsContentContext(), schemaId.ToString(), contentId, EtagVersion.Any)) - .Returns(content); + A.CallTo(() => contentQuery.QueryAsync(MatchsContentContext(), schemaId.ToString(), MatchId(contentId))) + .Returns(ResultList.Create(1, content)); var result = await sut.QueryAsync(context, new GraphQLQuery { Query = query }); @@ -940,8 +941,8 @@ namespace Squidex.Domain.Apps.Entities.Contents.GraphQL } }".Replace("", contentId.ToString()); - A.CallTo(() => contentQuery.FindContentAsync(MatchsContentContext(), schemaId.ToString(), contentId, EtagVersion.Any)) - .Returns(content); + A.CallTo(() => contentQuery.QueryAsync(MatchsContentContext(), schemaId.ToString(), MatchId(contentId))) + .Returns(ResultList.Create(1, content)); var result = await sut.QueryAsync(context, new GraphQLQuery { Query = query }); @@ -986,8 +987,8 @@ namespace Squidex.Domain.Apps.Entities.Contents.GraphQL } }".Replace("", contentId.ToString()); - A.CallTo(() => contentQuery.FindContentAsync(MatchsContentContext(), schemaId.ToString(), contentId, EtagVersion.Any)) - .Returns(content); + A.CallTo(() => contentQuery.QueryAsync(MatchsContentContext(), schemaId.ToString(), MatchId(contentId))) + .Returns(ResultList.Create(1, content)); var result = await sut.QueryAsync(context, new GraphQLQuery { Query = query }); @@ -1005,6 +1006,11 @@ namespace Squidex.Domain.Apps.Entities.Contents.GraphQL AssertResult(expected, result); } + private static Q MatchId(Guid contentId) + { + return A.That.Matches(x => x.Ids.Count == 1 && x.Ids[0] == contentId); + } + private QueryContext MatchsAssetContext() { return A.That.Matches(x => x.App == app && x.User == user); From fc172c8bd92b83b9e2c677ee574907eac44c3bc7 Mon Sep 17 00:00:00 2001 From: Sebastian Date: Sat, 22 Jun 2019 08:38:18 +0200 Subject: [PATCH 42/47] Virtual everywhere. --- .../Contents/QueryExecutionContext.cs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/Squidex.Domain.Apps.Entities/Contents/QueryExecutionContext.cs b/src/Squidex.Domain.Apps.Entities/Contents/QueryExecutionContext.cs index b1615f3a1..8b186cbd4 100644 --- a/src/Squidex.Domain.Apps.Entities/Contents/QueryExecutionContext.cs +++ b/src/Squidex.Domain.Apps.Entities/Contents/QueryExecutionContext.cs @@ -68,7 +68,7 @@ namespace Squidex.Domain.Apps.Entities.Contents return content; } - public async Task> QueryAssetsAsync(string query) + public virtual async Task> QueryAssetsAsync(string query) { var assets = await assetQuery.QueryAsync(context, Q.Empty.WithODataQuery(query)); @@ -80,7 +80,7 @@ namespace Squidex.Domain.Apps.Entities.Contents return assets; } - public async Task> QueryContentsAsync(string schemaIdOrName, string query) + public virtual async Task> QueryContentsAsync(string schemaIdOrName, string query) { var result = await contentQuery.QueryAsync(context, schemaIdOrName, Q.Empty.WithODataQuery(query)); @@ -92,7 +92,7 @@ namespace Squidex.Domain.Apps.Entities.Contents return result; } - public async Task> GetReferencedAssetsAsync(ICollection ids) + public virtual async Task> GetReferencedAssetsAsync(ICollection ids) { Guard.NotNull(ids, nameof(ids)); @@ -111,7 +111,7 @@ namespace Squidex.Domain.Apps.Entities.Contents return ids.Select(cachedAssets.GetOrDefault).Where(x => x != null).ToList(); } - public async Task> GetReferencedContentsAsync(Guid schemaId, ICollection ids) + public virtual async Task> GetReferencedContentsAsync(Guid schemaId, ICollection ids) { Guard.NotNull(ids, nameof(ids)); From b4f3a7ac5e662a93bca7b61f67dda61a85ba75e8 Mon Sep 17 00:00:00 2001 From: Sebastian Stehle Date: Sat, 22 Jun 2019 09:10:54 +0200 Subject: [PATCH 43/47] Fix for v2.1.0 --- CHANGELOG.md | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7941618aa..9037de7bf 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,33 @@ # Changelog +## v2.1.0 - 2019-06-22 + +## Features + +* **Assets**: Parameter to prevent download in Browser. +* **Assets**: FTP asset store. +* **GraphQL**: Logging for field resolvers +* **GraphQL**: Performance optimizations for asset fields and references with DataLoader. +* **MongoDB**: Performance optimizations. +* **MongoDB**: Support for AWS DocumentDB. +* **Schemas**: Separator field. +* **Schemas**: Setting to prevent duplicate references. +* **UI**: Improved styling of DateTime editor. +* **UI**: Custom Editors: Provide all values. +* **UI**: Custom Editors: Provide context with user information and auth token. +* **UI**: Filter by status. +* **UI**: Dropdown field for references. +* **Users**: Email notifications when contributors is added. + +## Bugfixes + +* **Contents**: Fix for scheduled publishing. +* **GraphQL**: Fix query parameters for assets. +* **GraphQL**: Fix for duplicate field names in GraphQL. +* **GraphQL**: Fix for invalid field names. +* **Plans**: Fix when plans reset and extra events. +* **UI**: Unify slugify in Frontend and Backend. + ## v2.0.5 - 2019-04-21 ## Features From bb3ba79ef9a8e6d88a8fab67a39b3baa3e6cd5cc Mon Sep 17 00:00:00 2001 From: Sebastian Stehle Date: Sat, 22 Jun 2019 09:46:29 +0200 Subject: [PATCH 44/47] Update README.md --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index bbf5dfe3b..2f6126a97 100644 --- a/README.md +++ b/README.md @@ -16,7 +16,7 @@ Please join our community forum: https://support.squidex.io ## Status -Current Version v2.0.4. Roadmap: https://trello.com/b/KakM4F3S/squidex-roadmap +Current Version v2.1.0. Roadmap: https://trello.com/b/KakM4F3S/squidex-roadmap ## Prerequisites @@ -50,4 +50,4 @@ Although Squidex is free it is also available as a Saas version on [https://clou ## License -[![FOSSA Status](https://app.fossa.io/api/projects/git%2Bgithub.com%2FSquidex%2Fsquidex.svg?type=large)](https://app.fossa.io/projects/git%2Bgithub.com%2FSquidex%2Fsquidex?ref=badge_large) \ No newline at end of file +[![FOSSA Status](https://app.fossa.io/api/projects/git%2Bgithub.com%2FSquidex%2Fsquidex.svg?type=large)](https://app.fossa.io/projects/git%2Bgithub.com%2FSquidex%2Fsquidex?ref=badge_large) From 0b62ccf15320b01cacaa33e6ef74e4950f3499b2 Mon Sep 17 00:00:00 2001 From: Sebastian Stehle Date: Sat, 22 Jun 2019 09:56:24 +0200 Subject: [PATCH 45/47] Packages updated. --- src/Squidex/package-lock.json | 594 +++++++++++++++++++--------------- src/Squidex/package.json | 64 ++-- 2 files changed, 372 insertions(+), 286 deletions(-) diff --git a/src/Squidex/package-lock.json b/src/Squidex/package-lock.json index 721adebda..2a2d0c8c5 100644 --- a/src/Squidex/package-lock.json +++ b/src/Squidex/package-lock.json @@ -5,9 +5,9 @@ "requires": true, "dependencies": { "@angular-devkit/core": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/@angular-devkit/core/-/core-8.0.1.tgz", - "integrity": "sha512-GQtspR2umZeuTUDTLy2dpUstvQfK7oAwE0o+rWSa8mx0DyhYssrfBbvfE4GzUzKp6OSz1sbZAatSO+iimZjbQw==", + "version": "8.0.3", + "resolved": "https://registry.npmjs.org/@angular-devkit/core/-/core-8.0.3.tgz", + "integrity": "sha512-Q5+jw2JQ7xfrDbo1VYH2cr+NysGV+psZ1TtC9eoVJ44fp8pCQAnvGJkeT7eLVEgMrpoBorUy7nqebCOR3WnkXA==", "dev": true, "requires": { "ajv": "6.10.0", @@ -68,34 +68,34 @@ } }, "@angular/animations": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/@angular/animations/-/animations-8.0.0.tgz", - "integrity": "sha512-hggSRi83rmocLwzrKZtmFcqPdivKSJqp2yiYaiNmJ2yQWJ1JW/Lurypv9H347RWxmwCCwC2kV8embTGbOXIFDQ==", + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/@angular/animations/-/animations-8.0.2.tgz", + "integrity": "sha512-6buaGp6sgyLWbjioGU0Wp/O9nFEQqD2L18uX5g5P5hdpq0bgopAbBee7AefJ8Kc/Kf79FlaKu9fKP5AEkeC8tA==", "requires": { "tslib": "^1.9.0" } }, "@angular/common": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/@angular/common/-/common-8.0.0.tgz", - "integrity": "sha512-iOAJZ0+1zTRHnHE/5G30+4Q66W1pfZkSkxZIXvgijZ+wtuNloYdWNy/IdZ/m7ayBI7A6FsYEhyMUoWz2HVEJNw==", + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/@angular/common/-/common-8.0.2.tgz", + "integrity": "sha512-9lwrKso0XjyS7wu+8dEWa5yN1kCTdbelP6JElFhh0kAt0TbPVHJ/dXEwvIFk9/2MjYv2PbooQo1zsc5kAB2Rlg==", "requires": { "tslib": "^1.9.0" } }, "@angular/compiler": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/@angular/compiler/-/compiler-8.0.0.tgz", - "integrity": "sha512-4rKsVFMNykF83tPL1VE1+j9kZ3cWHUsLOAB/VqmF64EcR/GsbjKog2v23rSso5kqUtPiVq/FWGYllW6qMdxtJA==", + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/@angular/compiler/-/compiler-8.0.2.tgz", + "integrity": "sha512-ktobrxpWX1eCwbDKOIUm5GRj8WGlHW/8MAQvDDFUnsGqXBHfOGiaySiEYX/XjeN8qu34IfXs736QkdzpMM4+iw==", "dev": true, "requires": { "tslib": "^1.9.0" } }, "@angular/compiler-cli": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/@angular/compiler-cli/-/compiler-cli-8.0.0.tgz", - "integrity": "sha512-Z0U0Ih8A7V3J1gq7AXnXbrGAD2ERmz7JbREJJRHDWiUNxIqGQiV3Odo1V8FL5n/cKvLwSYM2Ubvk10gb0+3njA==", + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/@angular/compiler-cli/-/compiler-cli-8.0.2.tgz", + "integrity": "sha512-9jdpB8WC47oSgQ/jA+ExTYqbe4xw3ZCEhgLhPd8BQukBOHodaIHKnkinrVJAPZORpY1CKRaImoAHieSvRhiPjA==", "dev": true, "requires": { "canonical-path": "1.0.0", @@ -1037,17 +1037,17 @@ } }, "@angular/core": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/@angular/core/-/core-8.0.0.tgz", - "integrity": "sha512-mrkP1PTzqCmZGLYll+TDyawLXHzi+FcRPqSuRxCmDMthUUE93SLXT2yISDkx9aMPtFKgFr6KfrIkKuCz16BP/g==", + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/@angular/core/-/core-8.0.2.tgz", + "integrity": "sha512-g8BRvGZxTXb5GZ/xoC5Z94DGK3wMiD2jbmEQEbXGNM+c8E/Mo/W8GF44P7EU2d+V1oJoUh75SRK6U/StC+rLqA==", "requires": { "tslib": "^1.9.0" } }, "@angular/forms": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/@angular/forms/-/forms-8.0.0.tgz", - "integrity": "sha512-T6XdG3mALWzvnrN3fA1hAmfwvraiF1SPMWNXgPk2riuMf8CFdoro+tQZ4eo1islHrTTw5QzmqN8JJALfhAG6bg==", + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/@angular/forms/-/forms-8.0.2.tgz", + "integrity": "sha512-LGu3b/wjNMCki5PnMUsfQlyaVZVOedNO+XccfluP4ZBQ5G/E2cz2tJ0UIHg3RhLbbpWntmqokpYLyd7leUPpIQ==", "requires": { "tslib": "^1.9.0" } @@ -1061,25 +1061,25 @@ } }, "@angular/platform-browser": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/@angular/platform-browser/-/platform-browser-8.0.0.tgz", - "integrity": "sha512-fTD+pTMbq+On9Uv3VXiei2lfuX7GX31dngm/Y4yWTFeW6eXy0+7kkfflzpLOb0hykCZvcXzarqCuEBBYNLrrOg==", + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/@angular/platform-browser/-/platform-browser-8.0.2.tgz", + "integrity": "sha512-iUoyhJ81jqvpmQI6Lu5NzRZR8azmnb2kX2FQ+LbwCvWQLfkLbTaa/Jl09/qN6KWpTsMogNQXVnjjgwoeaObvBw==", "requires": { "tslib": "^1.9.0" } }, "@angular/platform-browser-dynamic": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/@angular/platform-browser-dynamic/-/platform-browser-dynamic-8.0.0.tgz", - "integrity": "sha512-dx7W7JoSFbsveexjZ/BPlsXbMDLWVLmRCo7IqLvibMrTbdpaaOCNJIXJk1X+f7JJrQ7SwlZaVkoLCMoDWw6fmA==", + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/@angular/platform-browser-dynamic/-/platform-browser-dynamic-8.0.2.tgz", + "integrity": "sha512-i9hBmcXauiQpvzRRNbBpMbQSsRh9YMv9phw9Ih54w2LdTUB64Vtrm3scQEWZ0sIONY3QbwEtu57k8euQPASErQ==", "requires": { "tslib": "^1.9.0" } }, "@angular/platform-server": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/@angular/platform-server/-/platform-server-8.0.0.tgz", - "integrity": "sha512-pA6m1okOfyy2qH5A6jUxrhx6z7eAG+ne7IM+j/6JUBDjp4KO9BC84aa/xfpZq5dsskl8E8II9c4hUKocMyeRjA==", + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/@angular/platform-server/-/platform-server-8.0.2.tgz", + "integrity": "sha512-xO8CF/kmJMGe8xOeT+broKsu7z/+FDMzRjth52n1s9FW/kTONXuupwSmDTMYZk5PMfDYv0zlZZH2jcHhrlOrgQ==", "requires": { "domino": "^2.1.2", "tslib": "^1.9.0", @@ -1087,9 +1087,9 @@ } }, "@angular/router": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/@angular/router/-/router-8.0.0.tgz", - "integrity": "sha512-DGUTb8qpndE5m716xh00GxuC8o7qamlqbUruGB+SQD6ynU7s5yLGxtKffxqb1BT63+YewpsVxc2Koruvb1qjDw==", + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/@angular/router/-/router-8.0.2.tgz", + "integrity": "sha512-kgSqkvx3cgY0+ZTzkBVLa0sf0y0Fl7q3N+KX746pbCNjRRGa5gBkN7z+oyPDoG1l0fEiM6NLbFfcmuFwsdBO5w==", "requires": { "tslib": "^1.9.0" } @@ -1265,12 +1265,12 @@ } }, "@ngtools/webpack": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/@ngtools/webpack/-/webpack-8.0.1.tgz", - "integrity": "sha512-ly+KyzD5S8dVbwDv4pWt8+NNevPskmdXYJVxa068nE1dQV+CCK4mi6aR0GqrRR9zPvhgRoQKK8tMbN6WDCJS7g==", + "version": "8.0.3", + "resolved": "https://registry.npmjs.org/@ngtools/webpack/-/webpack-8.0.3.tgz", + "integrity": "sha512-sV/0dumyQdJhz2hNNAh2EtCtSjADD7735YhagqGjZhTWaiUnVTdF0pjFUUTmnw/hTFSqjUPWQy9V1cvUuK6Fmw==", "dev": true, "requires": { - "@angular-devkit/core": "8.0.1", + "@angular-devkit/core": "8.0.3", "enhanced-resolve": "4.1.0", "rxjs": "6.4.0", "tree-kill": "1.2.1", @@ -1299,9 +1299,9 @@ } }, "@types/core-js": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/@types/core-js/-/core-js-2.5.0.tgz", - "integrity": "sha512-qjkHL3wF0JMHMqgm/kmL8Pf8rIiqvueEiZ0g6NVTcBX1WN46GWDr+V5z+gsHUeL0n8TfAmXnYmF7ajsxmBp4PQ==", + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/@types/core-js/-/core-js-2.5.2.tgz", + "integrity": "sha512-+NPqjXgyA02xTHKJDeDca9u8Zr42ts6jhdND4C3PrPeQ35RJa0dmfAedXW7a9K4N1QcBbuWI1nSfGK4r1eVFCQ==", "dev": true }, "@types/events": { @@ -1352,9 +1352,9 @@ "dev": true }, "@types/node": { - "version": "12.0.4", - "resolved": "https://registry.npmjs.org/@types/node/-/node-12.0.4.tgz", - "integrity": "sha512-j8YL2C0fXq7IONwl/Ud5Kt0PeXw22zGERt+HSSnwbKOJVsAGkEz3sFCYwaF9IOuoG1HOtE0vKCj6sXF7Q0+Vaw==", + "version": "12.0.10", + "resolved": "https://registry.npmjs.org/@types/node/-/node-12.0.10.tgz", + "integrity": "sha512-LcsGbPomWsad6wmMNv7nBLw7YYYyfdYcz6xryKYQhx89c3XXan+8Q6AJ43G5XDIaklaVkK3mE4fCb0SBvMiPSQ==", "dev": true }, "@types/prop-types": { @@ -1370,9 +1370,9 @@ "dev": true }, "@types/react": { - "version": "16.8.19", - "resolved": "https://registry.npmjs.org/@types/react/-/react-16.8.19.tgz", - "integrity": "sha512-QzEzjrd1zFzY9cDlbIiFvdr+YUmefuuRYrPxmkwG0UQv5XF35gFIi7a95m1bNVcFU0VimxSZ5QVGSiBmlggQXQ==", + "version": "16.8.22", + "resolved": "https://registry.npmjs.org/@types/react/-/react-16.8.22.tgz", + "integrity": "sha512-C3O1yVqk4sUXqWyx0wlys76eQfhrQhiDhDlHBrjER76lR2S2Agiid/KpOU9oCqj1dISStscz7xXz1Cg8+sCQeA==", "dev": true, "requires": { "@types/prop-types": "*", @@ -2847,13 +2847,14 @@ } }, "browserslist": { - "version": "4.6.1", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.6.1.tgz", - "integrity": "sha512-1MC18ooMPRG2UuVFJTHFIAkk6mpByJfxCrnUyvSlu/hyQSFHMrlhM02SzNuCV+quTP4CKmqtOMAIjrifrpBJXQ==", + "version": "4.6.3", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.6.3.tgz", + "integrity": "sha512-CNBqTCq22RKM8wKJNowcqihHJ4SkI8CGeK7KOR9tPboXUuS5Zk5lQgzzTbs4oxD8x+6HUshZUa2OyNI9lR93bQ==", + "dev": true, "requires": { - "caniuse-lite": "^1.0.30000971", - "electron-to-chromium": "^1.3.137", - "node-releases": "^1.1.21" + "caniuse-lite": "^1.0.30000975", + "electron-to-chromium": "^1.3.164", + "node-releases": "^1.1.23" } }, "buffer": { @@ -3100,9 +3101,10 @@ } }, "caniuse-lite": { - "version": "1.0.30000971", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30000971.tgz", - "integrity": "sha512-TQFYFhRS0O5rdsmSbF1Wn+16latXYsQJat66f7S7lizXW1PVpWJeZw9wqqVLIjuxDRz7s7xRUj13QCfd8hKn6g==" + "version": "1.0.30000976", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30000976.tgz", + "integrity": "sha512-tleNB1IwPRqZiod6nUNum63xQCMN96BUO2JTeiwuRM7p9d616EHsMBjBWJMudX39qCaPuWY8KEWzMZq7A9XQMQ==", + "dev": true }, "canonical-path": { "version": "1.0.0", @@ -3345,12 +3347,12 @@ "dev": true }, "codelyzer": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/codelyzer/-/codelyzer-5.0.1.tgz", - "integrity": "sha512-UVV76+/y1RwaxzCeGPFE3G4GFtfV42r3x8EmRd7XMNFLlLC0ewdtCqWTbvhwPQMxFZZ+OTLEOJNWfyPPn3QFWg==", + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/codelyzer/-/codelyzer-5.1.0.tgz", + "integrity": "sha512-QiyY2/oDQnYx4mAVEDqr+z9MwrOto18tQFjExiuRChXCy0yvngS5fQpWIxvAGpbOmZFiR1PRTRLbEI71u10maA==", "dev": true, "requires": { - "app-root-path": "^2.1.0", + "app-root-path": "^2.2.1", "aria-query": "^3.0.0", "axobject-query": "^2.0.2", "css-selector-tokenizer": "^0.7.1", @@ -3376,14 +3378,14 @@ } }, "codemirror": { - "version": "5.46.0", - "resolved": "https://registry.npmjs.org/codemirror/-/codemirror-5.46.0.tgz", - "integrity": "sha512-3QpMge0vg4QEhHW3hBAtCipJEWjTJrqLLXdIaWptJOblf1vHFeXLNtFhPai/uX2lnFCehWNk4yOdaMR853Z02w==" + "version": "5.48.0", + "resolved": "https://registry.npmjs.org/codemirror/-/codemirror-5.48.0.tgz", + "integrity": "sha512-3Ter+tYtRlTNtxtYdYNPxGxBL/b3cMcvPdPm70gvmcOO2Rauv/fUEewWa0tT596Hosv6ea2mtpx28OXBy1mQCg==" }, "codemirror-graphql": { - "version": "0.7.1", - "resolved": "https://registry.npmjs.org/codemirror-graphql/-/codemirror-graphql-0.7.1.tgz", - "integrity": "sha512-HtHXMJAn6iGJYpijkzi3IlqWIdGrB6V0RqJ607yffJTCKk/OgaNtdLOb8hZJyEtHfkw7PZDaKybMAVCi6ScWSQ==", + "version": "0.8.3", + "resolved": "https://registry.npmjs.org/codemirror-graphql/-/codemirror-graphql-0.8.3.tgz", + "integrity": "sha512-ZipSnPXFKDMThfvfTKTAt1dQmuGctVNann8hTZg6017+vwOcGpIqCuQIZLRDw/Y3zZfCyydRARHgbSydSCXpow==", "requires": { "graphql-language-service-interface": "^1.3.2", "graphql-language-service-parser": "^1.2.2" @@ -3635,10 +3637,18 @@ "integrity": "sha1-Z29us8OZl8LuGsOpJP1hJHSPV40=", "dev": true }, + "copy-to-clipboard": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/copy-to-clipboard/-/copy-to-clipboard-3.2.0.tgz", + "integrity": "sha512-eOZERzvCmxS8HWzugj4Uxl8OJxa7T2k1Gi0X5qavwydHIfuSHq2dTD09LOg/XyGq4Zpb5IsR/2OJ5lbOegz78w==", + "requires": { + "toggle-selection": "^1.0.6" + } + }, "core-js": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.1.3.tgz", - "integrity": "sha512-PWZ+ZfuaKf178BIAg+CRsljwjIMRV8MY00CbZczkR6Zk5LfkSkjGoaab3+bqRQWVITNZxQB7TFYz+CFcyuamvA==" + "version": "3.1.4", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.1.4.tgz", + "integrity": "sha512-YNZN8lt82XIMLnLirj9MhKDFZHalwzzrL9YLt6eb0T5D0EDl4IQ90IGkua8mHbnxNrkj1d8hbdizMc0Qmg1WnQ==" }, "core-util-is": { "version": "1.0.2", @@ -3806,21 +3816,22 @@ } }, "css-loader": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/css-loader/-/css-loader-2.1.1.tgz", - "integrity": "sha512-OcKJU/lt232vl1P9EEDamhoO9iKY3tIjY5GU+XDLblAykTdgs6Ux9P1hTHve8nFKy5KPpOXOsVI/hIwi3841+w==", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/css-loader/-/css-loader-3.0.0.tgz", + "integrity": "sha512-WR6KZuCkFbnMhRrGPlkwAA7SSCtwqPwpyXJAPhotYkYsc0mKU9n/fu5wufy4jl2WhBw9Ia8gUQMIp/1w98DuPw==", "dev": true, "requires": { - "camelcase": "^5.2.0", - "icss-utils": "^4.1.0", + "camelcase": "^5.3.1", + "cssesc": "^3.0.0", + "icss-utils": "^4.1.1", "loader-utils": "^1.2.3", "normalize-path": "^3.0.0", - "postcss": "^7.0.14", + "postcss": "^7.0.17", "postcss-modules-extract-imports": "^2.0.0", - "postcss-modules-local-by-default": "^2.0.6", + "postcss-modules-local-by-default": "^3.0.2", "postcss-modules-scope": "^2.1.0", - "postcss-modules-values": "^2.0.0", - "postcss-value-parser": "^3.3.0", + "postcss-modules-values": "^3.0.0", + "postcss-value-parser": "^4.0.0", "schema-utils": "^1.0.0" }, "dependencies": { @@ -3830,15 +3841,15 @@ "integrity": "sha512-vyL2OymJxmarO8gxMr0mhChsO9QGwhynfuu4+MHTAW6czfq9humCB7rKpUjDd9YUiDPU4mzpyupFSvOClAwbmQ==", "dev": true }, - "camelcase": { - "version": "5.3.1", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", - "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", + "cssesc": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz", + "integrity": "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==", "dev": true }, "json5": { "version": "1.0.1", - "resolved": "http://registry.npmjs.org/json5/-/json5-1.0.1.tgz", + "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.1.tgz", "integrity": "sha512-aKS4WQjPenRxiQsC93MNfjx+nbF4PAdYzmd/1JIj8HYzqfbu86beTuNgXDzPknWk0n0uARlyewZo4s++ES36Ow==", "dev": true, "requires": { @@ -3861,6 +3872,12 @@ "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", "dev": true + }, + "postcss-value-parser": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.0.0.tgz", + "integrity": "sha512-ESPktioptiSUchCKgggAkzdmkgzKfmp0EU8jXH+5kbIUB+unr0Y4CY9SRMvibuvYUBjNh1ACLbxqYNpdTQOteQ==", + "dev": true } } }, @@ -4151,9 +4168,9 @@ } }, "damerau-levenshtein": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/damerau-levenshtein/-/damerau-levenshtein-1.0.4.tgz", - "integrity": "sha1-AxkcQyy27qFou3fzpV/9zLiXhRQ=", + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/damerau-levenshtein/-/damerau-levenshtein-1.0.5.tgz", + "integrity": "sha512-CBCRqFnpu715iPmw1KrdOrzRqbdFwQTwAWyyyYS42+iAgHCuXZ+/TdMgQkUENPomxEz9z1BEzuQU2Xw0kUuAgA==", "dev": true }, "dashdash": { @@ -4566,9 +4583,10 @@ "dev": true }, "electron-to-chromium": { - "version": "1.3.142", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.142.tgz", - "integrity": "sha512-GLOB/wAA2g9l5Hwg1XrPqd6br2WNOPIY8xl/q+g5zZdv3b5fB69oFOooxKxc0DfDfDS1RqaF6hKjwt6v4fuFUw==" + "version": "1.3.168", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.168.tgz", + "integrity": "sha512-Jm2oiuJPzPvsN9Jg4yGbDrflqMFPUtT88Y+ZlCxDdDEXSbt7cVzyzlxGKJkfa0NfcaykDtisCSz7BJ6mDW/NpA==", + "dev": true }, "elliptic": { "version": "6.4.1", @@ -5255,13 +5273,41 @@ } }, "file-loader": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/file-loader/-/file-loader-3.0.1.tgz", - "integrity": "sha512-4sNIOXgtH/9WZq4NvlfU3Opn5ynUsqBwSLyM+I7UOwdGigTBYfVVQEwe/msZNX/j4pCJTIM14Fsw66Svo1oVrw==", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/file-loader/-/file-loader-4.0.0.tgz", + "integrity": "sha512-roAbL6IdSGczwfXxhMi6Zq+jD4IfUpL0jWHD7fvmjdOVb7xBfdRUHe4LpBgO23VtVK5AW1OlWZo0p34Jvx3iWg==", "dev": true, "requires": { - "loader-utils": "^1.0.2", + "loader-utils": "^1.2.2", "schema-utils": "^1.0.0" + }, + "dependencies": { + "big.js": { + "version": "5.2.2", + "resolved": "https://registry.npmjs.org/big.js/-/big.js-5.2.2.tgz", + "integrity": "sha512-vyL2OymJxmarO8gxMr0mhChsO9QGwhynfuu4+MHTAW6czfq9humCB7rKpUjDd9YUiDPU4mzpyupFSvOClAwbmQ==", + "dev": true + }, + "json5": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.1.tgz", + "integrity": "sha512-aKS4WQjPenRxiQsC93MNfjx+nbF4PAdYzmd/1JIj8HYzqfbu86beTuNgXDzPknWk0n0uARlyewZo4s++ES36Ow==", + "dev": true, + "requires": { + "minimist": "^1.2.0" + } + }, + "loader-utils": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-1.2.3.tgz", + "integrity": "sha512-fkpz8ejdnEMG3s37wGL07iSBDg99O9D5yflE9RGNH3hRdx9SOwYfnGYdZOUIZitN8E+E2vkq3MUMYMvPYl5ZZA==", + "dev": true, + "requires": { + "big.js": "^5.2.2", + "emojis-list": "^2.0.0", + "json5": "^1.0.1" + } + } } }, "filename-regex": { @@ -6587,12 +6633,13 @@ "dev": true }, "graphiql": { - "version": "0.13.0", - "resolved": "https://registry.npmjs.org/graphiql/-/graphiql-0.13.0.tgz", - "integrity": "sha512-m2RBtSY1CQLz4XqCftQC0V9ZcbUXEx2Uwvuok3L/TJtsN5HOHUmPxGhOAZs7mESaAsg7Z8Tgy04BmYirDyfWug==", + "version": "0.13.2", + "resolved": "https://registry.npmjs.org/graphiql/-/graphiql-0.13.2.tgz", + "integrity": "sha512-4N2HmQQpUfApS1cxrTtoZ15tnR3EW88oUiqmza6GgNQYZZfDdBGphdQlBYsKcjAB/SnIOJort+RA1dB6kf4M7Q==", "requires": { - "codemirror": "^5.26.0", - "codemirror-graphql": "^0.7.1", + "codemirror": "^5.47.0", + "codemirror-graphql": "^0.8.3", + "copy-to-clipboard": "^3.2.0", "markdown-it": "^8.4.0" } }, @@ -7093,9 +7140,9 @@ } }, "http-parser-js": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/http-parser-js/-/http-parser-js-0.5.0.tgz", - "integrity": "sha512-cZdEF7r4gfRIq7ezX9J0T+kQmJNOub71dWbgAXVHDct80TKP4MCETtZQ31xyv38UwgzkWPYF/Xc0ge55dW9Z9w==", + "version": "0.4.10", + "resolved": "https://registry.npmjs.org/http-parser-js/-/http-parser-js-0.4.10.tgz", + "integrity": "sha1-ksnBN0w1CF912zWexWzCV8u5P6Q=", "dev": true }, "http-proxy": { @@ -7444,16 +7491,10 @@ "safer-buffer": ">= 2.1.2 < 3" } }, - "icss-replace-symbols": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/icss-replace-symbols/-/icss-replace-symbols-1.1.0.tgz", - "integrity": "sha1-Bupvg2ead0njhs/h/oEq5dsiPe0=", - "dev": true - }, "icss-utils": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/icss-utils/-/icss-utils-4.1.0.tgz", - "integrity": "sha512-3DEun4VOeMvSczifM3F2cKQrDQ5Pj6WKhkOq6HD4QTnDUAq8MQRxy5TX6Sy1iY6WPBe4gQ3p5vTECjbIkglkkQ==", + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/icss-utils/-/icss-utils-4.1.1.tgz", + "integrity": "sha512-4aFq7wvWyMHKgxsH8QQtGpvbASCf+eM3wPRLI6R+MgAnTCZ6STYsRvttLvRWK0Nfif5piF394St3HeJDaljGPA==", "dev": true, "requires": { "postcss": "^7.0.14" @@ -9413,32 +9454,55 @@ } }, "karma-webpack": { - "version": "3.0.5", - "resolved": "https://registry.npmjs.org/karma-webpack/-/karma-webpack-3.0.5.tgz", - "integrity": "sha512-nRudGJWstvVuA6Tbju9tyGUfXTtI1UXMXoRHVmM2/78D0q6s/Ye2IC157PKNDC15PWFGR0mVIRtWLAdcfsRJoA==", + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/karma-webpack/-/karma-webpack-4.0.2.tgz", + "integrity": "sha512-970/okAsdUOmiMOCY8sb17A2I8neS25Ad9uhyK3GHgmRSIFJbDcNEFE8dqqUhNe9OHiCC9k3DMrSmtd/0ymP1A==", "dev": true, "requires": { - "async": "^2.0.0", - "babel-runtime": "^6.0.0", - "loader-utils": "^1.0.0", - "lodash": "^4.0.0", - "source-map": "^0.5.6", - "webpack-dev-middleware": "^2.0.6" + "clone-deep": "^4.0.1", + "loader-utils": "^1.1.0", + "neo-async": "^2.6.1", + "schema-utils": "^1.0.0", + "source-map": "^0.7.3", + "webpack-dev-middleware": "^3.7.0" }, "dependencies": { - "async": { + "clone-deep": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/clone-deep/-/clone-deep-4.0.1.tgz", + "integrity": "sha512-neHB9xuzh/wk0dIHweyAXv2aPGZIVk3pLMe+/RNzINf17fe0OG96QroktYAUm7SM1PBnzTabaLboqqxDyMU+SQ==", + "dev": true, + "requires": { + "is-plain-object": "^2.0.4", + "kind-of": "^6.0.2", + "shallow-clone": "^3.0.0" + } + }, + "kind-of": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", + "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==", + "dev": true + }, + "neo-async": { "version": "2.6.1", - "resolved": "https://registry.npmjs.org/async/-/async-2.6.1.tgz", - "integrity": "sha512-fNEiL2+AZt6AlAw/29Cr0UDe4sRAHCpEHh54WMz+Bb7QfNcFw4h3loofyJpLeQs4Yx7yuqu/2dLgM5hKOs6HlQ==", + "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.1.tgz", + "integrity": "sha512-iyam8fBuCUpWeKPGpaNMetEocMt364qkCsfL9JuhjXX6dRnguRVOfk2GZaDpPjcOKiiXCPINZC1GczQ7iTq3Zw==", + "dev": true + }, + "shallow-clone": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/shallow-clone/-/shallow-clone-3.0.1.tgz", + "integrity": "sha512-/6KqX+GVUdqPuPPd2LxDDxzX6CAbjJehAAOKlNpqqUpAqPM6HeL8f+o3a+JsyGjn2lv0WY8UsTgUJjU9Ok55NA==", "dev": true, "requires": { - "lodash": "^4.17.10" + "kind-of": "^6.0.2" } }, "source-map": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", - "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "version": "0.7.3", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.3.tgz", + "integrity": "sha512-CkCj6giN3S+n9qrYiBTX5gystlENnRW5jZeNLHpe6aue+SrHcG5VYwujhW9s4dY31mEGsxBDrHR6oI69fTXsaQ==", "dev": true } } @@ -9603,9 +9667,9 @@ } }, "loglevel": { - "version": "1.6.2", - "resolved": "https://registry.npmjs.org/loglevel/-/loglevel-1.6.2.tgz", - "integrity": "sha512-Jt2MHrCNdtIe1W6co3tF5KXGRkzF+TYffiQstfXa04mrss9IKXzAAXYWak8LbZseAQY03sH2GzMCMU0ZOUc9bg==", + "version": "1.6.3", + "resolved": "https://registry.npmjs.org/loglevel/-/loglevel-1.6.3.tgz", + "integrity": "sha512-LoEDv5pgpvWgPF4kNYuIp0qqSJVWak/dML0RY74xlzMZiT9w77teNAwKYKWBTYjlokMirg+o3jBwp+vlLrcfAA==", "dev": true }, "loglevelnext": { @@ -10210,9 +10274,9 @@ "integrity": "sha512-5mWWBePwvEPsNd/HkdbD543Q9mPyJofL6zkNydl8/Ah3qrrvZT2DaEPbknY08OgkXpI2qUGksc01OzzVlRQ9dQ==" }, "ngx-color-picker": { - "version": "7.5.0", - "resolved": "https://registry.npmjs.org/ngx-color-picker/-/ngx-color-picker-7.5.0.tgz", - "integrity": "sha512-bTW16A3IitWUNGc3kZtE+N1r3FpmUj7uJTG80eym2nQLvsROkMntalKJDo1SQVQhh9Nh4N9C88UezdMg8fjR5Q==" + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/ngx-color-picker/-/ngx-color-picker-8.0.1.tgz", + "integrity": "sha512-aA55g49ZGF1xfc0iJS6xK/qOds2GZC3mId4lcJarCGrjQbg44qYv6BaodLzSFcYRMPN9+O7z6n4+2pWrjQqWfA==" }, "nice-try": { "version": "1.0.5", @@ -10231,7 +10295,7 @@ }, "node-fetch": { "version": "2.1.2", - "resolved": "http://registry.npmjs.org/node-fetch/-/node-fetch-2.1.2.tgz", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.1.2.tgz", "integrity": "sha1-q4hOjn5X44qUR1POxwb3iNF2i7U=" }, "node-forge": { @@ -10269,9 +10333,9 @@ } }, "node-libs-browser": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/node-libs-browser/-/node-libs-browser-2.2.0.tgz", - "integrity": "sha512-5MQunG/oyOaBdttrL40dA7bUfPORLRWMUJLQtMg7nluxUvk5XwnLdL9twQHFAjRx/y7mIMkLKT9++qPbbk6BZA==", + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/node-libs-browser/-/node-libs-browser-2.2.1.tgz", + "integrity": "sha512-h/zcD8H9kaDZ9ALUWwlBUDo6TKF8a7qBSCSEGfjTVIYeqsioSKaAX+BN7NgiMGp6iSIXZ3PxgCu8KS3b71YK5Q==", "dev": true, "requires": { "assert": "^1.1.1", @@ -10284,7 +10348,7 @@ "events": "^3.0.0", "https-browserify": "^1.0.0", "os-browserify": "^0.3.0", - "path-browserify": "0.0.0", + "path-browserify": "0.0.1", "process": "^0.11.10", "punycode": "^1.2.4", "querystring-es3": "^0.2.0", @@ -10296,7 +10360,7 @@ "tty-browserify": "0.0.0", "url": "^0.11.0", "util": "^0.11.0", - "vm-browserify": "0.0.4" + "vm-browserify": "^1.0.1" }, "dependencies": { "punycode": { @@ -10317,9 +10381,10 @@ } }, "node-releases": { - "version": "1.1.22", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-1.1.22.tgz", - "integrity": "sha512-O6XpteBuntW1j86mw6LlovBIwTe+sO2+7vi9avQffNeIW4upgnaCVm6xrBWH+KATz7mNNRNNeEpuWB7dT6Cr3w==", + "version": "1.1.23", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-1.1.23.tgz", + "integrity": "sha512-uq1iL79YjfYC0WXoHbC/z28q/9pOl8kSHaXdWmAAc8No+bDwqkZbzIJz55g/MUsPgSGm9LZ7QSUbzTcH5tz47w==", + "dev": true, "requires": { "semver": "^5.3.0" } @@ -10617,9 +10682,12 @@ "dev": true }, "oidc-client": { - "version": "1.7.1", - "resolved": "https://registry.npmjs.org/oidc-client/-/oidc-client-1.7.1.tgz", - "integrity": "sha512-qsPBQVa/BY6AmdY89erANJbfDXrX1dqu9lKgvYZzkVDzIj5mmw6wGjFeQuV2HDm4TiJA0VT5HSTWOWnXZUYu0g==" + "version": "1.8.2", + "resolved": "https://registry.npmjs.org/oidc-client/-/oidc-client-1.8.2.tgz", + "integrity": "sha512-WwoSY8S6QyNN3qpne88YurjNqjTf6z1Xr0y+OrFVvdnVPYcefkTtXlZ5iOwR2JrmP4vBuq2j8eTjUJyDZFrFNQ==", + "requires": { + "uuid": "^3.3.2" + } }, "on-finished": { "version": "2.3.0", @@ -10817,6 +10885,15 @@ "integrity": "sha512-y3b8Kpd8OAN444hxfBbFfj1FY/RjtTd8tzYwhUqNYXx0fXx2iX4maP4Qr6qhIKbQXI02wTLAda4fYUbDagTUFw==", "dev": true }, + "p-retry": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/p-retry/-/p-retry-3.0.1.tgz", + "integrity": "sha512-XE6G4+YTTkT2a0UWb2kjZe8xNwf8bIbnqpc/IS/idOBVhyves0mK5OJgeocjx7q5pvX/6m23xuzVPYT1uGM73w==", + "dev": true, + "requires": { + "retry": "^0.12.0" + } + }, "p-try": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", @@ -10921,9 +10998,9 @@ "dev": true }, "path-browserify": { - "version": "0.0.0", - "resolved": "https://registry.npmjs.org/path-browserify/-/path-browserify-0.0.0.tgz", - "integrity": "sha1-oLhwcpquIUAFt9UDLsLLuw+0RRo=", + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/path-browserify/-/path-browserify-0.0.1.tgz", + "integrity": "sha512-BapA40NHICOS+USX9SN4tyhq+A2RrN/Ws5F0Z5aMHDp98Fl86lX8Oti8B7uN93L4Ifv4fHOEA+pQw87gmMO/lQ==", "dev": true }, "path-dirname": { @@ -11060,9 +11137,9 @@ "dev": true }, "postcss": { - "version": "7.0.14", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.14.tgz", - "integrity": "sha512-NsbD6XUUMZvBxtQAJuWDJeeC4QFsmWsfozWxCJPWf3M55K9iu2iMDaKqyoOdTJ1R4usBXuxlVFAIo8rZPQD4Bg==", + "version": "7.0.17", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.17.tgz", + "integrity": "sha512-546ZowA+KZ3OasvQZHsbuEpysvwTZNGJv9EfyCQdsIDltPSWHAeTQ5fQy/Npi2ZDtLI3zs7Ps/p6wThErhm9fQ==", "dev": true, "requires": { "chalk": "^2.4.2", @@ -11572,14 +11649,15 @@ } }, "postcss-modules-local-by-default": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/postcss-modules-local-by-default/-/postcss-modules-local-by-default-2.0.6.tgz", - "integrity": "sha512-oLUV5YNkeIBa0yQl7EYnxMgy4N6noxmiwZStaEJUSe2xPMcdNc8WmBQuQCx18H5psYbVxz8zoHk0RAAYZXP9gA==", + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/postcss-modules-local-by-default/-/postcss-modules-local-by-default-3.0.2.tgz", + "integrity": "sha512-jM/V8eqM4oJ/22j0gx4jrp63GSvDH6v86OqyTHHUvk4/k1vceipZsaymiZ5PvocqZOl5SFHiFJqjs3la0wnfIQ==", "dev": true, "requires": { - "postcss": "^7.0.6", - "postcss-selector-parser": "^6.0.0", - "postcss-value-parser": "^3.3.1" + "icss-utils": "^4.1.1", + "postcss": "^7.0.16", + "postcss-selector-parser": "^6.0.2", + "postcss-value-parser": "^4.0.0" }, "dependencies": { "cssesc": { @@ -11600,9 +11678,9 @@ } }, "postcss-value-parser": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz", - "integrity": "sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ==", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.0.0.tgz", + "integrity": "sha512-ESPktioptiSUchCKgggAkzdmkgzKfmp0EU8jXH+5kbIUB+unr0Y4CY9SRMvibuvYUBjNh1ACLbxqYNpdTQOteQ==", "dev": true } } @@ -11637,12 +11715,12 @@ } }, "postcss-modules-values": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/postcss-modules-values/-/postcss-modules-values-2.0.0.tgz", - "integrity": "sha512-Ki7JZa7ff1N3EIMlPnGTZfUMe69FFwiQPnVSXC9mnn3jozCRBYIxiZd44yJOV2AmabOo4qFf8s0dC/+lweG7+w==", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/postcss-modules-values/-/postcss-modules-values-3.0.0.tgz", + "integrity": "sha512-1//E5jCBrZ9DmRX+zCtmQtRSV6PV42Ix7Bzj9GbwJceduuf7IqP8MgeTXuRDHOWj2m0VzZD5+roFWDuU8RQjcg==", "dev": true, "requires": { - "icss-replace-symbols": "^1.1.0", + "icss-utils": "^4.0.0", "postcss": "^7.0.6" } }, @@ -12160,6 +12238,12 @@ "integrity": "sha1-gV7R9uvGWSb4ZbMQwHE7yzMVzks=", "dev": true }, + "prettier": { + "version": "1.18.2", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-1.18.2.tgz", + "integrity": "sha512-OeHeMc0JhFE9idD4ZdtNibzY0+TPHSpSSb9h8FqtP+YnoZZ1sl8Vc9b1sasjfymH3SonAF4QcA2+mzHPhMvIiw==", + "dev": true + }, "pretty-error": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/pretty-error/-/pretty-error-2.1.1.tgz", @@ -12771,6 +12855,12 @@ "integrity": "sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg==", "dev": true }, + "retry": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/retry/-/retry-0.12.0.tgz", + "integrity": "sha1-G0KmJmoh8HQh0bC1S33BZ7AcATs=", + "dev": true + }, "rfdc": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/rfdc/-/rfdc-1.1.2.tgz", @@ -13170,7 +13260,8 @@ "semver": { "version": "5.5.0", "resolved": "https://registry.npmjs.org/semver/-/semver-5.5.0.tgz", - "integrity": "sha512-4SJ3dm0WAwWy/NVeioZh5AntkdJoWKxHxcmyP622fOkgHa4z3R0TdBJICINyaSDE6uNwVc8gZr+ZinwZAH4xIA==" + "integrity": "sha512-4SJ3dm0WAwWy/NVeioZh5AntkdJoWKxHxcmyP622fOkgHa4z3R0TdBJICINyaSDE6uNwVc8gZr+ZinwZAH4xIA==", + "dev": true }, "semver-dsl": { "version": "1.0.1", @@ -13674,18 +13765,18 @@ } }, "faye-websocket": { - "version": "0.11.1", - "resolved": "https://registry.npmjs.org/faye-websocket/-/faye-websocket-0.11.1.tgz", - "integrity": "sha1-8O/hjE9W5PQK/H4Gxxn9XuYYjzg=", + "version": "0.11.3", + "resolved": "https://registry.npmjs.org/faye-websocket/-/faye-websocket-0.11.3.tgz", + "integrity": "sha512-D2y4bovYpzziGgbHYtGCMjlJM36vAl/y+xUyn1C+FVx8szd1E+86KwVw6XvYSzOP8iMpm1X0I4xJD+QtUb36OA==", "dev": true, "requires": { "websocket-driver": ">=0.5.1" } }, "ms": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", - "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==", + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", "dev": true } } @@ -13806,9 +13897,9 @@ } }, "ms": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", - "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==", + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", "dev": true } } @@ -13837,9 +13928,9 @@ } }, "ms": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", - "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==", + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", "dev": true }, "readable-stream": { @@ -14490,6 +14581,11 @@ } } }, + "toggle-selection": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/toggle-selection/-/toggle-selection-1.0.6.tgz", + "integrity": "sha1-bkWxJj8gF/oKzH2J14sVuL932jI=" + }, "toidentifier": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.0.tgz", @@ -14548,9 +14644,9 @@ } }, "ts-loader": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/ts-loader/-/ts-loader-6.0.2.tgz", - "integrity": "sha512-kkF3sGf3oBUehlvXI9fkbItbFTnNgGkYAz91vtWnsKAU4m+LAmQjuby7uTZNo3As+/zHLuyB052SkQDY6vLXtg==", + "version": "6.0.4", + "resolved": "https://registry.npmjs.org/ts-loader/-/ts-loader-6.0.4.tgz", + "integrity": "sha512-p2zJYe7OtwR+49kv4gs7v4dMrfYD1IPpOtqiSPCbe8oR+4zEBtdHwzM7A7M91F+suReqgzZrlClk4LRSSp882g==", "dev": true, "requires": { "chalk": "^2.3.0", @@ -14653,14 +14749,14 @@ } }, "tslib": { - "version": "1.9.3", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.9.3.tgz", - "integrity": "sha512-4krF8scpejhaOgqzBEcGM7yDIEfi0/8+8zDRZhNZZ2kjmHJ4hv3zCbQWxoJGz1iw5U0Jl0nma13xzHXcncMavQ==" + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.10.0.tgz", + "integrity": "sha512-qOebF53frne81cf0S9B41ByenJ3/IuH8yJKngAX35CmiZySA0khhkovshKK+jGCaMnVomla7gVlIcc3EvKPbTQ==" }, "tslint": { - "version": "5.17.0", - "resolved": "https://registry.npmjs.org/tslint/-/tslint-5.17.0.tgz", - "integrity": "sha512-pflx87WfVoYepTet3xLfDOLDm9Jqi61UXIKePOuca0qoAZyrGWonDG9VTbji58Fy+8gciUn8Bt7y69+KEVjc/w==", + "version": "5.18.0", + "resolved": "https://registry.npmjs.org/tslint/-/tslint-5.18.0.tgz", + "integrity": "sha512-Q3kXkuDEijQ37nXZZLKErssQVnwCV/+23gFEMROi8IlbaBG6tXqLPQJ5Wjcyt/yHPKBC+hD5SzuGaMora+ZS6w==", "dev": true, "requires": { "@babel/code-frame": "^7.0.0", @@ -15025,12 +15121,6 @@ } } }, - "url-join": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/url-join/-/url-join-2.0.5.tgz", - "integrity": "sha1-WvIvGMBSoACkjXuCxenC4v7tpyg=", - "dev": true - }, "url-parse": { "version": "1.4.7", "resolved": "https://registry.npmjs.org/url-parse/-/url-parse-1.4.7.tgz", @@ -15106,8 +15196,7 @@ "uuid": { "version": "3.3.2", "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.3.2.tgz", - "integrity": "sha512-yXJmeNaw3DnnKAOKJE51sL/ZaYfWJRl1pK9dr19YFCu0ObS231AB1/LbqTKRAQ5kw8A90rA6fr4riOUpTZvQZA==", - "dev": true + "integrity": "sha512-yXJmeNaw3DnnKAOKJE51sL/ZaYfWJRl1pK9dr19YFCu0ObS231AB1/LbqTKRAQ5kw8A90rA6fr4riOUpTZvQZA==" }, "v8-compile-cache": { "version": "2.0.3", @@ -15149,13 +15238,10 @@ } }, "vm-browserify": { - "version": "0.0.4", - "resolved": "https://registry.npmjs.org/vm-browserify/-/vm-browserify-0.0.4.tgz", - "integrity": "sha1-XX6kW7755Kb/ZflUOOCofDV9WnM=", - "dev": true, - "requires": { - "indexof": "0.0.1" - } + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/vm-browserify/-/vm-browserify-1.1.0.tgz", + "integrity": "sha512-iq+S7vZJE60yejDYM0ek6zg308+UZsdtPExWP9VZoCFCz1zkJoXFnAX7aZfd/ZwrkidzdUZL0C/ryW+JwAiIGw==", + "dev": true }, "void-elements": { "version": "2.0.1", @@ -16109,9 +16195,9 @@ } }, "webpack": { - "version": "4.32.2", - "resolved": "https://registry.npmjs.org/webpack/-/webpack-4.32.2.tgz", - "integrity": "sha512-F+H2Aa1TprTQrpodRAWUMJn7A8MgDx82yQiNvYMaj3d1nv3HetKU0oqEulL9huj8enirKi8KvEXQ3QtuHF89Zg==", + "version": "4.35.0", + "resolved": "https://registry.npmjs.org/webpack/-/webpack-4.35.0.tgz", + "integrity": "sha512-M5hL3qpVvtr8d4YaJANbAQBc4uT01G33eDpl/psRTBCfjxFTihdhin1NtAKB1ruDwzeVdcsHHV3NX+QsAgOosw==", "dev": true, "requires": { "@webassemblyjs/ast": "1.8.5", @@ -16439,9 +16525,9 @@ } }, "webpack-cli": { - "version": "3.3.2", - "resolved": "https://registry.npmjs.org/webpack-cli/-/webpack-cli-3.3.2.tgz", - "integrity": "sha512-FLkobnaJJ+03j5eplxlI0TUxhGCOdfewspIGuvDVtpOlrAuKMFC57K42Ukxqs1tn8947/PM6tP95gQc0DCzRYA==", + "version": "3.3.4", + "resolved": "https://registry.npmjs.org/webpack-cli/-/webpack-cli-3.3.4.tgz", + "integrity": "sha512-ubJGQEKMtBSpT+LiL5hXvn2GIOWiRWItR1DGUqJRhwRBeGhpRXjvF5f0erqdRJLErkfqS5/Ldkkedh4AL5Q1ZQ==", "dev": true, "requires": { "chalk": "^2.4.1", @@ -16452,6 +16538,7 @@ "import-local": "^2.0.0", "interpret": "^1.1.0", "loader-utils": "^1.1.0", + "prettier": "^1.17.0", "supports-color": "^5.5.0", "v8-compile-cache": "^2.0.2", "yargs": "^12.0.5" @@ -16525,24 +16612,45 @@ } }, "webpack-dev-middleware": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/webpack-dev-middleware/-/webpack-dev-middleware-2.0.6.tgz", - "integrity": "sha512-tj5LLD9r4tDuRIDa5Mu9lnY2qBBehAITv6A9irqXhw/HQquZgTx3BCd57zYbU2gMDnncA49ufK2qVQSbaKJwOw==", + "version": "3.7.0", + "resolved": "https://registry.npmjs.org/webpack-dev-middleware/-/webpack-dev-middleware-3.7.0.tgz", + "integrity": "sha512-qvDesR1QZRIAZHOE3iQ4CXLZZSQ1lAUsSpnQmlB1PBfoN/xdRjmge3Dok0W4IdaVLJOGJy3sGI4sZHwjRU0PCA==", "dev": true, "requires": { - "loud-rejection": "^1.6.0", - "memory-fs": "~0.4.1", - "mime": "^2.1.0", - "path-is-absolute": "^1.0.0", - "range-parser": "^1.0.3", - "url-join": "^2.0.2", - "webpack-log": "^1.0.1" + "memory-fs": "^0.4.1", + "mime": "^2.4.2", + "range-parser": "^1.2.1", + "webpack-log": "^2.0.0" + }, + "dependencies": { + "mime": { + "version": "2.4.4", + "resolved": "https://registry.npmjs.org/mime/-/mime-2.4.4.tgz", + "integrity": "sha512-LRxmNwziLPT828z+4YkNzloCFC2YM4wrB99k+AV5ZbEyfGNWfG8SO1FUXLmLDBSo89NrJZ4DIWeLjy1CHGhMGA==", + "dev": true + }, + "range-parser": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", + "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", + "dev": true + }, + "webpack-log": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/webpack-log/-/webpack-log-2.0.0.tgz", + "integrity": "sha512-cX8G2vR/85UYG59FgkoMamwHUIkSSlV3bBMRsbxVXVUk2j6NleCKjQ/WE9eYg9WY4w25O9w8wKP4rzNZFmUcUg==", + "dev": true, + "requires": { + "ansi-colors": "^3.0.0", + "uuid": "^3.3.2" + } + } } }, "webpack-dev-server": { - "version": "3.5.1", - "resolved": "https://registry.npmjs.org/webpack-dev-server/-/webpack-dev-server-3.5.1.tgz", - "integrity": "sha512-0IdMGddJcnK9zesZOeHWl4uAOVfypn7DSrdNWtclROkVBXy/TcBN+6eEG1wNfLT9dXVfaRZZsLTJt0mJtgTQgw==", + "version": "3.7.2", + "resolved": "https://registry.npmjs.org/webpack-dev-server/-/webpack-dev-server-3.7.2.tgz", + "integrity": "sha512-mjWtrKJW2T9SsjJ4/dxDC2fkFVUw8jlpemDERqV0ZJIkjjjamR2AbQlr3oz+j4JLhYCHImHnXZK5H06P2wvUew==", "dev": true, "requires": { "ansi-html": "0.0.7", @@ -16559,8 +16667,9 @@ "internal-ip": "^4.3.0", "ip": "^1.1.5", "killable": "^1.0.1", - "loglevel": "^1.6.2", + "loglevel": "^1.6.3", "opn": "^5.5.0", + "p-retry": "^3.0.1", "portfinder": "^1.0.20", "schema-utils": "^1.0.0", "selfsigned": "^1.10.4", @@ -16697,9 +16806,9 @@ }, "dependencies": { "ms": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", - "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==", + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", "dev": true } } @@ -17530,12 +17639,6 @@ "to-regex": "^3.0.2" } }, - "mime": { - "version": "2.4.3", - "resolved": "https://registry.npmjs.org/mime/-/mime-2.4.3.tgz", - "integrity": "sha512-QgrPRJfE+riq5TPZMcHZOtm8c6K/yYrMbKIoRfapfiGLxS8OTeIfRhUGW5LU7MlRa52KOAGCfUNruqLrIBvWZw==", - "dev": true - }, "nan": { "version": "2.14.0", "resolved": "https://registry.npmjs.org/nan/-/nan-2.14.0.tgz", @@ -17549,12 +17652,6 @@ "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", "dev": true }, - "range-parser": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", - "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", - "dev": true - }, "readdirp": { "version": "2.2.1", "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-2.2.1.tgz", @@ -17581,18 +17678,6 @@ "has-flag": "^3.0.0" } }, - "webpack-dev-middleware": { - "version": "3.7.0", - "resolved": "https://registry.npmjs.org/webpack-dev-middleware/-/webpack-dev-middleware-3.7.0.tgz", - "integrity": "sha512-qvDesR1QZRIAZHOE3iQ4CXLZZSQ1lAUsSpnQmlB1PBfoN/xdRjmge3Dok0W4IdaVLJOGJy3sGI4sZHwjRU0PCA==", - "dev": true, - "requires": { - "memory-fs": "^0.4.1", - "mime": "^2.4.2", - "range-parser": "^1.2.1", - "webpack-log": "^2.0.0" - } - }, "webpack-log": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/webpack-log/-/webpack-log-2.0.0.tgz", @@ -17658,12 +17743,13 @@ } }, "websocket-driver": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/websocket-driver/-/websocket-driver-0.7.0.tgz", - "integrity": "sha1-DK+dLXVdk67gSdS90NP+LMoqJOs=", + "version": "0.7.3", + "resolved": "https://registry.npmjs.org/websocket-driver/-/websocket-driver-0.7.3.tgz", + "integrity": "sha512-bpxWlvbbB459Mlipc5GBzzZwhoZgGEZLuqPaR0INBGnPAY1vdBX6hPnoFXiw+3yWxDuHyQjO2oXTMyS8A5haFg==", "dev": true, "requires": { - "http-parser-js": ">=0.4.0", + "http-parser-js": ">=0.4.0 <0.4.11", + "safe-buffer": ">=5.1.0", "websocket-extensions": ">=0.1.1" } }, @@ -17675,7 +17761,7 @@ }, "whatwg-fetch": { "version": "2.0.4", - "resolved": "http://registry.npmjs.org/whatwg-fetch/-/whatwg-fetch-2.0.4.tgz", + "resolved": "https://registry.npmjs.org/whatwg-fetch/-/whatwg-fetch-2.0.4.tgz", "integrity": "sha512-dcQ1GWpOD/eEQ97k66aiEVpNnapVj90/+R+SXTPYGHpYBBypfKJEQjLrvMZ7YXbKm21gXd4NcuxUTjiv1YtLng==" }, "which": { @@ -17913,9 +17999,9 @@ } }, "yargs-parser": { - "version": "13.1.0", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-13.1.0.tgz", - "integrity": "sha512-Yq+32PrijHRri0vVKQEm+ys8mbqWjLiwQkMFNXEENutzLPP0bE4Lcd4iA3OQY5HF+GD3xXxf0MEHb8E4/SA3AA==", + "version": "13.1.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-13.1.1.tgz", + "integrity": "sha512-oVAVsHz6uFrg3XQheFII8ESO2ssAf9luWuAd6Wexsu4F3OtIW0o8IribPXYrD4WC24LWtPrJlGy87y5udK+dxQ==", "dev": true, "requires": { "camelcase": "^5.0.0", diff --git a/src/Squidex/package.json b/src/Squidex/package.json index 7453f5829..49c4879e3 100644 --- a/src/Squidex/package.json +++ b/src/Squidex/package.json @@ -15,29 +15,27 @@ "build:clean": "rimraf wwwroot/build" }, "dependencies": { - "@angular/animations": "8.0.0", - "@angular/common": "8.0.0", - "@angular/core": "8.0.0", - "@angular/forms": "8.0.0", + "@angular/animations": "8.0.2", + "@angular/common": "8.0.2", + "@angular/core": "8.0.2", + "@angular/forms": "8.0.2", "@angular/http": "7.2.15", - "@angular/platform-browser": "8.0.0", - "@angular/platform-browser-dynamic": "8.0.0", - "@angular/platform-server": "8.0.0", - "@angular/router": "8.0.0", + "@angular/platform-browser": "8.0.2", + "@angular/platform-browser-dynamic": "8.0.2", + "@angular/platform-server": "8.0.2", + "@angular/router": "8.0.2", "angular2-chartjs": "0.5.1", "babel-polyfill": "6.26.0", "bootstrap": "4.3.1", - "browserslist": "^4.6.1", - "caniuse-lite": "^1.0.30000971", - "core-js": "3.1.3", - "graphiql": "0.13.0", + "core-js": "3.1.4", + "graphiql": "0.13.2", "graphql": "14.3.1", "marked": "0.6.2", "moment": "2.24.0", "mousetrap": "1.6.3", "ng2-dnd": "5.0.2", - "ngx-color-picker": "7.5.0", - "oidc-client": "1.7.1", + "ngx-color-picker": "8.0.1", + "oidc-client": "1.8.2", "pikaday": "1.8.0", "progressbar.js": "1.0.1", "react": "16.8.6", @@ -45,43 +43,45 @@ "rxjs": "6.5.2", "slugify": "1.3.4", "sortablejs": "1.9.0", - "tslib": "1.9.3", + "tslib": "1.10.0", "zone.js": "0.9.1" }, "devDependencies": { - "@angular/compiler-cli": "8.0.0", - "@angular/compiler": "8.0.0", - "@ngtools/webpack": "8.0.1", - "@types/core-js": "2.5.0", + "@angular/compiler": "8.0.2", + "@angular/compiler-cli": "8.0.2", + "@ngtools/webpack": "8.0.3", + "@types/core-js": "2.5.2", "@types/jasmine": "3.3.13", "@types/marked": "0.6.5", "@types/mousetrap": "1.6", - "@types/node": "12.0.4", + "@types/node": "12.0.10", + "@types/react": "16.8.22", "@types/react-dom": "16.8.4", - "@types/react": "16.8.19", "@types/sortablejs": "1.7.2", "awesome-typescript-loader": "5.2.1", "babel-core": "6.26.3", + "browserslist": "^4.6.3", + "caniuse-lite": "^1.0.30000976", "circular-dependency-plugin": "5.0.2", - "codelyzer": "5.0.1", + "codelyzer": "5.1.0", "cpx": "1.5.0", - "css-loader": "2.1.1", - "file-loader": "3.0.1", + "css-loader": "3.0.0", + "file-loader": "4.0.0", "html-loader": "0.5.5", "html-webpack-plugin": "3.2.0", "ignore-loader": "0.1.2", "istanbul-instrumenter-loader": "3.0.1", "jasmine-core": "3.4.0", + "karma": "4.1.0", "karma-chrome-launcher": "2.2.0", "karma-cli": "2.0.0", "karma-coverage-istanbul-reporter": "2.0.5", "karma-htmlfile-reporter": "0.3.8", - "karma-jasmine-html-reporter": "1.4.2", "karma-jasmine": "2.0.1", + "karma-jasmine-html-reporter": "1.4.2", "karma-mocha-reporter": "2.2.5", "karma-sourcemap-loader": "0.3.7", - "karma-webpack": "3.0.5", - "karma": "4.1.0", + "karma-webpack": "4.0.2", "mini-css-extract-plugin": "0.7.0", "node-sass": "4.12.0", "optimize-css-assets-webpack-plugin": "5.0.1", @@ -91,16 +91,16 @@ "sass-lint": "1.13.1", "sass-loader": "7.1.0", "style-loader": "0.23.1", - "ts-loader": "6.0.2", + "ts-loader": "6.0.4", "tsconfig-paths-webpack-plugin": "3.2.0", + "tslint": "5.18.0", "tslint-webpack-plugin": "2.0.4", - "tslint": "5.17.0", "typemoq": "2.1.0", "typescript": "3.4.3", "uglifyjs-webpack-plugin": "2.1.3", "underscore": "1.9.1", - "webpack-cli": "3.3.2", - "webpack-dev-server": "3.5.1", - "webpack": "4.32.2" + "webpack": "4.35.0", + "webpack-cli": "3.3.4", + "webpack-dev-server": "3.7.2" } } From c46bd87f8d512e28f9f9e0508fe91059e9a9cb47 Mon Sep 17 00:00:00 2001 From: Sebastian Stehle Date: Sat, 22 Jun 2019 10:57:56 +0200 Subject: [PATCH 46/47] Increase heap space. --- src/Squidex/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Squidex/package.json b/src/Squidex/package.json index 49c4879e3..f70e68d25 100644 --- a/src/Squidex/package.json +++ b/src/Squidex/package.json @@ -11,7 +11,7 @@ "test:coverage": "karma start karma.coverage.conf.js", "test:clean": "rimraf _test-output", "tslint": "tslint -c tslint.json -p tsconfig.json app/**/*.ts", - "build": "npm run copy && webpack --config app-config/webpack.config.js --env.production", + "build": "npm run copy && node --max_old_space_size=4096 node_modules/webpack/bin/webpack.js --config app-config/webpack.config.js --env.production", "build:clean": "rimraf wwwroot/build" }, "dependencies": { From df44646143b2fa3770e8f07b2cf0360aca4c775d Mon Sep 17 00:00:00 2001 From: Sebastian Stehle Date: Sat, 22 Jun 2019 14:39:20 +0200 Subject: [PATCH 47/47] Cleanup. --- .testrunsettings | 6 ------ 1 file changed, 6 deletions(-) delete mode 100644 .testrunsettings diff --git a/.testrunsettings b/.testrunsettings deleted file mode 100644 index 0082141a9..000000000 --- a/.testrunsettings +++ /dev/null @@ -1,6 +0,0 @@ - - - - 4 - - \ No newline at end of file