فهرست منبع

style: Apply tslint & prettier to all .ts files

Michael Bromley 7 سال پیش
والد
کامیت
15e89453f6
100فایلهای تغییر یافته به همراه1093 افزوده شده و 940 حذف شده
  1. 21 11
      admin-ui/generate-graphql-types.ts
  2. 5 5
      admin-ui/src/app/app.component.ts
  3. 1 0
      admin-ui/src/app/app.config.ts
  4. 2 4
      admin-ui/src/app/app.module.ts
  5. 1 0
      admin-ui/src/app/app.routes.ts
  6. 2 6
      admin-ui/src/app/catalog/catalog.module.ts
  7. 11 9
      admin-ui/src/app/catalog/catalog.routes.ts
  8. 3 5
      admin-ui/src/app/catalog/components/create-option-group-dialog/create-option-group-dialog.component.spec.ts
  9. 25 19
      admin-ui/src/app/catalog/components/create-option-group-dialog/create-option-group-dialog.component.ts
  10. 37 32
      admin-ui/src/app/catalog/components/product-detail/product-detail.component.ts
  11. 9 7
      admin-ui/src/app/catalog/components/product-list/product-list.component.ts
  12. 6 4
      admin-ui/src/app/catalog/providers/routing/product-resolver.ts
  13. 0 1
      admin-ui/src/app/common/utilities/common.ts
  14. 0 1
      admin-ui/src/app/common/utilities/normalize-string.spec.ts
  15. 5 8
      admin-ui/src/app/core/components/app-shell/app-shell.component.ts
  16. 104 75
      admin-ui/src/app/core/components/breadcrumb/breadcrumb.component.spec.ts
  17. 44 33
      admin-ui/src/app/core/components/breadcrumb/breadcrumb.component.ts
  18. 4 6
      admin-ui/src/app/core/components/main-nav/main-nav.component.ts
  19. 3 2
      admin-ui/src/app/core/components/notification/notification.component.ts
  20. 2 2
      admin-ui/src/app/core/components/overlay-host/overlay-host.component.ts
  21. 2 4
      admin-ui/src/app/core/components/ui-language-switcher/ui-language-switcher.component.ts
  22. 2 5
      admin-ui/src/app/core/components/user-menu/user-menu.component.ts
  23. 4 9
      admin-ui/src/app/core/core.module.ts
  24. 2 3
      admin-ui/src/app/core/providers/auth/auth.service.ts
  25. 2 4
      admin-ui/src/app/core/providers/guard/auth.guard.ts
  26. 9 5
      admin-ui/src/app/core/providers/i18n/custom-http-loader.ts
  27. 2 1
      admin-ui/src/app/core/providers/i18n/mark-for-extraction.ts
  28. 1 2
      admin-ui/src/app/core/providers/local-storage/local-storage.service.ts
  29. 64 60
      admin-ui/src/app/core/providers/notification/notification.service.spec.ts
  30. 9 11
      admin-ui/src/app/core/providers/notification/notification.service.ts
  31. 1 2
      admin-ui/src/app/core/providers/overlay-host/overlay-host.service.ts
  32. 1 1
      admin-ui/src/app/dashboard/components/dashboard/dashboard.component.spec.ts
  33. 1 2
      admin-ui/src/app/dashboard/components/dashboard/dashboard.component.ts
  34. 2 5
      admin-ui/src/app/dashboard/dashboard.module.ts
  35. 4 2
      admin-ui/src/app/data/client-state/client-resolvers.ts
  36. 9 8
      admin-ui/src/app/data/data.module.ts
  37. 1 1
      admin-ui/src/app/data/fragments/product-fragments.ts
  38. 9 6
      admin-ui/src/app/data/mutations/product-mutations.ts
  39. 1 1
      admin-ui/src/app/data/omit-typename-link.ts
  40. 23 23
      admin-ui/src/app/data/providers/base-data.service.ts
  41. 12 3
      admin-ui/src/app/data/providers/client-data.service.ts
  42. 1 3
      admin-ui/src/app/data/providers/data.service.mock.ts
  43. 0 1
      admin-ui/src/app/data/providers/data.service.ts
  44. 15 8
      admin-ui/src/app/data/providers/interceptor.ts
  45. 32 12
      admin-ui/src/app/data/providers/product-data.service.ts
  46. 0 2
      admin-ui/src/app/data/providers/user-data.service.ts
  47. 3 2
      admin-ui/src/app/data/queries/product-queries.ts
  48. 415 431
      admin-ui/src/app/data/types/gql-generated-types.ts
  49. 3 10
      admin-ui/src/app/data/types/query-result.ts
  50. 17 19
      admin-ui/src/app/login/components/login/login.component.ts
  51. 2 6
      admin-ui/src/app/login/login.module.ts
  52. 2 2
      admin-ui/src/app/login/login.routes.ts
  53. 4 3
      admin-ui/src/app/shared/components/data-table/data-table.component.spec.ts
  54. 1 1
      admin-ui/src/app/shared/components/data-table/data-table.component.ts
  55. 10 2
      admin-ui/src/app/shared/components/form-field/form-field-control.directive.ts
  56. 1 0
      admin-ui/src/app/shared/components/form-field/form-field.component.ts
  57. 4 3
      admin-ui/src/app/shared/components/modal-dialog/dialog-buttons.directive.ts
  58. 14 2
      admin-ui/src/app/shared/components/modal-dialog/dialog-component-outlet.component.ts
  59. 4 3
      admin-ui/src/app/shared/components/modal-dialog/dialog-title.directive.ts
  60. 15 4
      admin-ui/src/app/shared/components/modal-dialog/modal-dialog.component.ts
  61. 3 3
      admin-ui/src/app/shared/components/table-row-action/table-row-action.component.ts
  62. 5 3
      admin-ui/src/app/shared/providers/modal/modal.service.ts
  63. 2 3
      admin-ui/src/app/shared/shared.module.ts
  64. 1 1
      admin-ui/src/environments/environment.prod.ts
  65. 1 1
      admin-ui/src/environments/environment.ts
  66. 7 6
      admin-ui/src/main.ts
  67. 5 5
      admin-ui/src/polyfills.ts
  68. 3 6
      admin-ui/src/test.ts
  69. 1 0
      server/dev-config.ts
  70. 1 0
      server/e2e/app.e2e-spec.ts
  71. 12 3
      server/mock-data/mock-data-client.service.ts
  72. 1 0
      server/mock-data/populate.ts
  73. 1 0
      server/src/api/administrator/administrator.resolver.ts
  74. 2 0
      server/src/api/auth/auth.controller.ts
  75. 1 0
      server/src/api/customer/customer.controller.ts
  76. 11 3
      server/src/api/customer/customer.resolver.ts
  77. 1 0
      server/src/api/product-option/product-option.resolver.ts
  78. 1 0
      server/src/api/product/product.resolver.ts
  79. 2 1
      server/src/app.module.ts
  80. 2 0
      server/src/auth/auth.service.ts
  81. 2 0
      server/src/auth/jwt.strategy.ts
  82. 4 1
      server/src/auth/roles-guard.ts
  83. 2 1
      server/src/bootstrap.ts
  84. 1 0
      server/src/config/merge-config.spec.ts
  85. 1 0
      server/src/config/merge-config.ts
  86. 2 0
      server/src/config/vendure-config.ts
  87. 1 0
      server/src/entity/address/address.entity.ts
  88. 1 0
      server/src/entity/administrator/administrator.entity.ts
  89. 1 0
      server/src/entity/base/base.entity.ts
  90. 1 0
      server/src/entity/customer/customer.entity.ts
  91. 2 0
      server/src/entity/product-option-group/product-option-group-translation.entity.ts
  92. 1 0
      server/src/entity/product-option-group/product-option-group.dto.ts
  93. 2 0
      server/src/entity/product-option-group/product-option-group.entity.ts
  94. 2 0
      server/src/entity/product-option/product-option-translation.entity.ts
  95. 1 0
      server/src/entity/product-option/product-option.dto.ts
  96. 2 0
      server/src/entity/product-option/product-option.entity.ts
  97. 1 0
      server/src/entity/product-variant/create-product-variant.dto.ts
  98. 10 1
      server/src/entity/product-variant/product-variant-translation.entity.ts
  99. 2 0
      server/src/entity/product-variant/product-variant.entity.ts
  100. 2 0
      server/src/entity/product/product-translation.entity.ts

+ 21 - 11
admin-ui/generate-graphql-types.ts

@@ -4,6 +4,7 @@ import { execute, GraphQLSchema, IntrospectionQuery, IntrospectionSchema, parse
 import { makeExecutableSchema } from 'graphql-tools';
 import { buildClientSchema, introspectionQuery, printSchema } from 'graphql/utilities';
 import { fileLoader, mergeTypes } from 'merge-graphql-schemas';
+
 import { API_PATH, API_PORT } from '../shared/shared-constants';
 
 // tslint:disable:no-console
@@ -30,7 +31,11 @@ async function main(): Promise<void> {
     fs.writeFileSync(SCHEMA_JSON_FILE, JSON.stringify(combinedSchema));
     console.log(`Generated schema file: ${SCHEMA_JSON_FILE}`);
 
-    await generateTypeScriptTypesFromSchema(SCHEMA_JSON_FILE, CLIENT_QUERY_FILES, TYPESCRIPT_DEFINITIONS_FILE);
+    await generateTypeScriptTypesFromSchema(
+        SCHEMA_JSON_FILE,
+        CLIENT_QUERY_FILES,
+        TYPESCRIPT_DEFINITIONS_FILE,
+    );
 
     console.log('Generated TypeScript definitions!');
 }
@@ -41,12 +46,7 @@ async function main(): Promise<void> {
  */
 async function downloadSchemaFromApi(apiEndpoint: string): Promise<IntrospectionQuery> {
     const TEMP_API_SCHEMA = '../schema.temp.json';
-    await runCommand('yarn', [
-        'apollo',
-        'schema:download',
-        TEMP_API_SCHEMA,
-        `--endpoint=${API_URL}`,
-    ]);
+    await runCommand('yarn', ['apollo', 'schema:download', TEMP_API_SCHEMA, `--endpoint=${API_URL}`]);
 
     console.log(`Downloaded schema from ${API_URL}`);
 
@@ -68,14 +68,20 @@ async function introspectionFromSchema(schema: GraphQLSchema): Promise<Introspec
  * Combines the IntrospectionQuery from the GraphQL API with any client-side schemas as defined by the
  * clientSchemaFiles glob.
  */
-async function combineSchemas(introspectionQueryFromApi: IntrospectionQuery, clientSchemaFiles: string): Promise<IntrospectionQuery> {
+async function combineSchemas(
+    introspectionQueryFromApi: IntrospectionQuery,
+    clientSchemaFiles: string,
+): Promise<IntrospectionQuery> {
     const schemaFromApi = buildClientSchema(introspectionQueryFromApi);
     const clientSchemas = fileLoader(clientSchemaFiles);
     const remoteSchema = printSchema(schemaFromApi);
     const typeDefs = mergeTypes([...clientSchemas, remoteSchema], {
         all: true,
     });
-    const executableSchema = makeExecutableSchema({ typeDefs, resolverValidationOptions: { requireResolversForResolveType: false } });
+    const executableSchema = makeExecutableSchema({
+        typeDefs,
+        resolverValidationOptions: { requireResolversForResolveType: false },
+    });
     const introspection = await introspectionFromSchema(executableSchema);
     return introspection;
 }
@@ -83,7 +89,11 @@ async function combineSchemas(introspectionQueryFromApi: IntrospectionQuery, cli
 /**
  * Generates TypeScript definitions from the provided schema json file sing the `apollo codegen:generate` cli command.
  */
-async function generateTypeScriptTypesFromSchema(schemaFile: string, queryFiles: string, outputFile: string): Promise<number> {
+async function generateTypeScriptTypesFromSchema(
+    schemaFile: string,
+    queryFiles: string,
+    outputFile: string,
+): Promise<number> {
     return runCommand('yarn', [
         'apollo',
         'codegen:generate',
@@ -102,7 +112,7 @@ function runCommand(command: string, args: string[]): Promise<number> {
         const cp = spawn(command, args, { shell: true });
 
         cp.on('error', reject);
-        cp.stdout.on('data', (data) => {
+        cp.stdout.on('data', data => {
             if (4 < data.length) {
                 console.log(`${data}`);
             }

+ 5 - 5
admin-ui/src/app/app.component.ts

@@ -1,6 +1,7 @@
 import { Component, OnInit } from '@angular/core';
 import { Observable } from 'rxjs';
 import { map } from 'rxjs/operators';
+
 import { DataService } from './data/providers/data.service';
 
 @Component({
@@ -11,12 +12,11 @@ import { DataService } from './data/providers/data.service';
 export class AppComponent implements OnInit {
     loading$: Observable<boolean>;
 
-    constructor(private dataService: DataService) {
-    }
+    constructor(private dataService: DataService) {}
 
     ngOnInit() {
-        this.loading$ = this.dataService.client.getNetworkStatus().stream$.pipe(
-            map(data => 0 < data.networkStatus.inFlightRequests),
-        );
+        this.loading$ = this.dataService.client
+            .getNetworkStatus()
+            .stream$.pipe(map(data => 0 < data.networkStatus.inFlightRequests));
     }
 }

+ 1 - 0
admin-ui/src/app/app.config.ts

@@ -1,4 +1,5 @@
 import { API_PORT } from '../../../shared/shared-constants';
+
 import { LanguageCode } from './data/types/gql-generated-types';
 
 export const API_URL = `http://localhost:${API_PORT}`;

+ 2 - 4
admin-ui/src/app/app.module.ts

@@ -4,6 +4,7 @@ import { BrowserModule } from '@angular/platform-browser';
 import { RouterModule } from '@angular/router';
 import { TranslateCompiler, TranslateLoader, TranslateModule } from '@ngx-translate/core';
 import { TranslateMessageFormatCompiler } from 'ngx-translate-messageformat-compiler';
+
 import { AppComponent } from './app.component';
 import { routes } from './app.routes';
 import { getDefaultLanguage } from './common/utilities/get-default-language';
@@ -16,9 +17,7 @@ export function HttpLoaderFactory(http: HttpClient) {
 }
 
 @NgModule({
-    declarations: [
-        AppComponent,
-    ],
+    declarations: [AppComponent],
     imports: [
         BrowserModule,
         RouterModule.forRoot(routes, { useHash: false }),
@@ -36,7 +35,6 @@ export function HttpLoaderFactory(http: HttpClient) {
     bootstrap: [AppComponent],
 })
 export class AppModule {
-
     constructor(private dataService: DataService) {
         this.dataService.client.setUiLanguage(getDefaultLanguage());
     }

+ 1 - 0
admin-ui/src/app/app.routes.ts

@@ -1,4 +1,5 @@
 import { Route } from '@angular/router';
+
 import { AppShellComponent } from './core/components/app-shell/app-shell.component';
 import { AuthGuard } from './core/providers/guard/auth.guard';
 import { _ } from './core/providers/i18n/mark-for-extraction';

+ 2 - 6
admin-ui/src/app/catalog/catalog.module.ts

@@ -10,14 +10,10 @@ import { ProductListComponent } from './components/product-list/product-list.com
 import { ProductResolver } from './providers/routing/product-resolver';
 
 @NgModule({
-    imports: [
-        SharedModule,
-        RouterModule.forChild(catalogRoutes),
-    ],
+    imports: [SharedModule, RouterModule.forChild(catalogRoutes)],
     exports: [],
     declarations: [ProductListComponent, ProductDetailComponent, CreateOptionGroupDialogComponent],
     entryComponents: [CreateOptionGroupDialogComponent],
     providers: [ProductResolver],
 })
-export class CatalogModule {
-}
+export class CatalogModule {}

+ 11 - 9
admin-ui/src/app/catalog/catalog.routes.ts

@@ -1,7 +1,9 @@
 import { Route } from '@angular/router';
 import { map } from 'rxjs/operators';
+
 import { _ } from '../core/providers/i18n/mark-for-extraction';
 import { DataService } from '../data/providers/data.service';
+
 import { ProductDetailComponent } from './components/product-detail/product-detail.component';
 import { ProductListComponent } from './components/product-list/product-list.component';
 import { ProductResolver } from './providers/routing/product-resolver';
@@ -30,15 +32,15 @@ export function productBreadcrumb(data: any, params: any, dataService: DataServi
     return dataService.product.getProduct(params.id).stream$.pipe(
         map(productData => {
             return [
-                   {
-                       label: _('breadcrumb.products'),
-                       link: ['../', 'products'],
-                   },
-                   {
-                       label: `#${params.id} (${productData.product.name})`,
-                       link: [params.id],
-                   },
-               ];
+                {
+                    label: _('breadcrumb.products'),
+                    link: ['../', 'products'],
+                },
+                {
+                    label: `#${params.id} (${productData.product.name})`,
+                    link: [params.id],
+                },
+            ];
         }),
     );
 }

+ 3 - 5
admin-ui/src/app/catalog/components/create-option-group-dialog/create-option-group-dialog.component.spec.ts

@@ -1,12 +1,13 @@
 import { async, ComponentFixture, TestBed } from '@angular/core/testing';
-
 import { ReactiveFormsModule } from '@angular/forms';
 import { IconCustomTag, Tooltip, TooltipContent, TooltipTrigger } from '@clr/angular';
+
 import { MockTranslatePipe } from '../../../../testing/translate.pipe.mock';
 import { DataService } from '../../../data/providers/data.service';
 import { MockDataService } from '../../../data/providers/data.service.mock';
 import { FormFieldControlDirective } from '../../../shared/components/form-field/form-field-control.directive';
 import { FormFieldComponent } from '../../../shared/components/form-field/form-field.component';
+
 import { CreateOptionGroupDialogComponent } from './create-option-group-dialog.component';
 
 describe('CreateOptionGroupDialogComponent', () => {
@@ -26,16 +27,13 @@ describe('CreateOptionGroupDialogComponent', () => {
                 TooltipTrigger,
                 Tooltip,
             ],
-            providers: [
-                { provide: DataService, useClass: MockDataService },
-            ],
+            providers: [{ provide: DataService, useClass: MockDataService }],
         }).compileComponents();
     }));
 
     beforeEach(() => {
         fixture = TestBed.createComponent(CreateOptionGroupDialogComponent);
         component = fixture.componentInstance;
-
     });
 
     it('should create', () => {

+ 25 - 19
admin-ui/src/app/catalog/components/create-option-group-dialog/create-option-group-dialog.component.ts

@@ -1,12 +1,16 @@
-import { ChangeDetectionStrategy, Component } from '@angular/core';
+import { ChangeDetectionStrategy, Component, OnInit } from '@angular/core';
 import { FormBuilder, FormGroup } from '@angular/forms';
-
 import { mergeMap } from 'rxjs/operators';
+
 import { ID } from '../../../../../../shared/shared-types';
 import { getDefaultLanguage } from '../../../common/utilities/get-default-language';
 import { normalizeString } from '../../../common/utilities/normalize-string';
 import { DataService } from '../../../data/providers/data.service';
-import { CreateProductOptionGroupInput, CreateProductOptionInput, LanguageCode } from '../../../data/types/gql-generated-types';
+import {
+    CreateProductOptionGroupInput,
+    CreateProductOptionInput,
+    LanguageCode,
+} from '../../../data/types/gql-generated-types';
 import { Dialog } from '../../../shared/providers/modal/modal.service';
 
 @Component({
@@ -15,7 +19,7 @@ import { Dialog } from '../../../shared/providers/modal/modal.service';
     styleUrls: ['./create-option-group-dialog.component.scss'],
     changeDetection: ChangeDetectionStrategy.OnPush,
 })
-export class CreateOptionGroupDialogComponent implements Dialog {
+export class CreateOptionGroupDialogComponent implements Dialog, OnInit {
     resolveWith: (result?: any) => void;
     optionGroupForm: FormGroup;
     productName = '';
@@ -23,8 +27,7 @@ export class CreateOptionGroupDialogComponent implements Dialog {
     editCode = false;
     readonly defaultLanguage = getDefaultLanguage();
 
-    constructor(private formBuilder: FormBuilder,
-                private dataService: DataService) {}
+    constructor(private formBuilder: FormBuilder, private dataService: DataService) {}
 
     ngOnInit() {
         this.optionGroupForm = this.formBuilder.group({
@@ -42,18 +45,20 @@ export class CreateOptionGroupDialogComponent implements Dialog {
     }
 
     createOptionGroup() {
-        this.dataService.product.createProductOptionGroups(this.createGroupFromForm()).pipe(
-            mergeMap(data => {
-                const optionGroup = data.createProductOptionGroup;
-                if (optionGroup) {
-                    return this.dataService.product.addOptionGroupToProduct({
-                        productId: this.productId,
-                        optionGroupId: optionGroup.id,
-                    });
-                }
-                return [];
-            }),
-        )
+        this.dataService.product
+            .createProductOptionGroups(this.createGroupFromForm())
+            .pipe(
+                mergeMap(data => {
+                    const optionGroup = data.createProductOptionGroup;
+                    if (optionGroup) {
+                        return this.dataService.product.addOptionGroupToProduct({
+                            productId: this.productId,
+                            optionGroupId: optionGroup.id,
+                        });
+                    }
+                    return [];
+                }),
+            )
             .subscribe(product => this.resolveWith(product));
     }
 
@@ -78,7 +83,8 @@ export class CreateOptionGroupDialogComponent implements Dialog {
     }
 
     private createGroupOptions(rawOptions: string): CreateProductOptionInput[] {
-        return rawOptions.split('\n')
+        return rawOptions
+            .split('\n')
             .map(line => line.trim())
             .map(name => {
                 return {

+ 37 - 32
admin-ui/src/app/catalog/components/product-detail/product-detail.component.ts

@@ -1,4 +1,4 @@
-import { Component } from '@angular/core';
+import { Component, OnDestroy } from '@angular/core';
 import { FormBuilder, FormGroup, Validators } from '@angular/forms';
 import { ActivatedRoute, Router } from '@angular/router';
 import { combineLatest, Observable, Subject } from 'rxjs';
@@ -15,19 +15,20 @@ import { CreateOptionGroupDialogComponent } from '../create-option-group-dialog/
     templateUrl: './product-detail.component.html',
     styleUrls: ['./product-detail.component.scss'],
 })
-export class ProductDetailComponent {
-
+export class ProductDetailComponent implements OnDestroy {
     product$: Observable<GetProductWithVariants_product>;
     availableLanguages$: Observable<LanguageCode[]>;
     languageCode$: Observable<LanguageCode>;
     productForm: FormGroup;
     private destroy$ = new Subject<void>();
 
-    constructor(private dataService: DataService,
-                private router: Router,
-                private route: ActivatedRoute,
-                private formBuilder: FormBuilder,
-                private modalService: ModalService) {
+    constructor(
+        private dataService: DataService,
+        private router: Router,
+        private route: ActivatedRoute,
+        private formBuilder: FormBuilder,
+        private modalService: ModalService,
+    ) {
         this.product$ = this.route.snapshot.data.product;
         this.productForm = this.formBuilder.group({
             name: ['', Validators.required],
@@ -37,16 +38,13 @@ export class ProductDetailComponent {
 
         this.languageCode$ = this.route.queryParamMap.pipe(
             map(qpm => qpm.get('lang')),
-            map(lang => !lang ? getDefaultLanguage() : lang as LanguageCode),
+            map(lang => (!lang ? getDefaultLanguage() : (lang as LanguageCode))),
         );
 
-        this.availableLanguages$ = this.product$.pipe(
-            map(p => p.translations.map(t => t.languageCode)),
-        );
+        this.availableLanguages$ = this.product$.pipe(map(p => p.translations.map(t => t.languageCode)));
 
-        combineLatest(this.product$, this.languageCode$).pipe(
-            takeUntil(this.destroy$),
-        )
+        combineLatest(this.product$, this.languageCode$)
+            .pipe(takeUntil(this.destroy$))
             .subscribe(([product, languageCode]) => {
                 const currentTranslation = product.translations.find(t => t.languageCode === languageCode);
                 if (currentTranslation) {
@@ -69,25 +67,28 @@ export class ProductDetailComponent {
     }
 
     createNewOptionGroup() {
-        this.product$.pipe(
-            take(1),
-            mergeMap(product => {
-                const nameControl = this.productForm.get('name');
-                const productName = nameControl ? nameControl.value : '';
-                return this.modalService.fromComponent(CreateOptionGroupDialogComponent, {
-                    closable: true,
-                    size: 'lg',
-                    locals: {
-                        productName,
-                        productId: product.id,
-                    },
-                });
-            }),
-        ).subscribe();
+        this.product$
+            .pipe(
+                take(1),
+                mergeMap(product => {
+                    const nameControl = this.productForm.get('name');
+                    const productName = nameControl ? nameControl.value : '';
+                    return this.modalService.fromComponent(CreateOptionGroupDialogComponent, {
+                        closable: true,
+                        size: 'lg',
+                        locals: {
+                            productName,
+                            productId: product.id,
+                        },
+                    });
+                }),
+            )
+            .subscribe();
     }
 
     save() {
-        combineLatest(this.product$, this.languageCode$).pipe(take(1))
+        combineLatest(this.product$, this.languageCode$)
+            .pipe(take(1))
             .subscribe(([product, languageCode]) => {
                 const currentTranslation = product.translations.find(t => t.languageCode === languageCode);
                 if (!currentTranslation) {
@@ -103,6 +104,10 @@ export class ProductDetailComponent {
     }
 
     private setQueryParam(key: string, value: any) {
-        this.router.navigate(['./'], { queryParams: { [key]: value }, relativeTo: this.route, queryParamsHandling: 'merge' });
+        this.router.navigate(['./'], {
+            queryParams: { [key]: value },
+            relativeTo: this.route,
+            queryParamsHandling: 'merge',
+        });
     }
 }

+ 9 - 7
admin-ui/src/app/catalog/components/product-list/product-list.component.ts

@@ -2,6 +2,7 @@ import { Component, OnDestroy, OnInit } from '@angular/core';
 import { ActivatedRoute, Router } from '@angular/router';
 import { BehaviorSubject, combineLatest, Observable, Subject } from 'rxjs';
 import { map, takeUntil } from 'rxjs/operators';
+
 import { DataService } from '../../../data/providers/data.service';
 
 @Component({
@@ -10,16 +11,13 @@ import { DataService } from '../../../data/providers/data.service';
     styleUrls: ['./product-list.component.scss'],
 })
 export class ProductListComponent implements OnInit, OnDestroy {
-
     products$: Observable<any[]>;
     totalItems$: Observable<number>;
     itemsPerPage$: Observable<number>;
     currentPage$: Observable<number>;
     private destroy$ = new Subject<void>();
 
-    constructor(private dataService: DataService,
-                private router: Router,
-                private route: ActivatedRoute) { }
+    constructor(private dataService: DataService, private router: Router, private route: ActivatedRoute) {}
 
     ngOnInit() {
         const productsQuery = this.dataService.product.getProducts(10, 0);
@@ -34,11 +32,11 @@ export class ProductListComponent implements OnInit, OnDestroy {
         this.totalItems$ = productsQuery.stream$.pipe(map(data => data.products.totalItems));
         this.currentPage$ = this.route.queryParamMap.pipe(
             map(qpm => qpm.get('page')),
-            map(page => !page ? 1 : +page),
+            map(page => (!page ? 1 : +page)),
         );
         this.itemsPerPage$ = this.route.queryParamMap.pipe(
             map(qpm => qpm.get('perPage')),
-            map(perPage => !perPage ? 10 : +perPage),
+            map(perPage => (!perPage ? 10 : +perPage)),
         );
 
         combineLatest(this.currentPage$, this.itemsPerPage$)
@@ -60,6 +58,10 @@ export class ProductListComponent implements OnInit, OnDestroy {
     }
 
     private setQueryParam(key: string, value: any) {
-        this.router.navigate(['./'], { queryParams: { [key]: value }, relativeTo: this.route, queryParamsHandling: 'merge' });
+        this.router.navigate(['./'], {
+            queryParams: { [key]: value },
+            relativeTo: this.route,
+            queryParamsHandling: 'merge',
+        });
     }
 }

+ 6 - 4
admin-ui/src/app/catalog/providers/routing/product-resolver.ts

@@ -1,20 +1,22 @@
-
 import { Injectable } from '@angular/core';
 import { ActivatedRouteSnapshot, Resolve, RouterStateSnapshot } from '@angular/router';
 import { Observable, of } from 'rxjs';
+import { finalize, map, take, tap } from 'rxjs/operators';
+
 import { DataService } from '../../../data/providers/data.service';
 import { GetProductWithVariants_product } from '../../../data/types/gql-generated-types';
-import { finalize, map, take, tap } from 'rxjs/operators';
 /**
  * Resolves the id from the path into a Customer entity.
  */
 
 @Injectable()
 export class ProductResolver implements Resolve<Observable<GetProductWithVariants_product>> {
-
     constructor(private dataService: DataService) {}
 
-    resolve(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<Observable<GetProductWithVariants_product>> {
+    resolve(
+        route: ActivatedRouteSnapshot,
+        state: RouterStateSnapshot,
+    ): Observable<Observable<GetProductWithVariants_product>> {
         const id = route.paramMap.get('id');
 
         if (id) {

+ 0 - 1
admin-ui/src/app/common/utilities/common.ts

@@ -1,4 +1,3 @@
-
 /**
  * Like assertNever, but at runtime this will be reached due to the way that all actions
  * are dispatched and piped through all reducers. So this just provides a compile-time

+ 0 - 1
admin-ui/src/app/common/utilities/normalize-string.spec.ts

@@ -1,7 +1,6 @@
 import { normalizeString } from './normalize-string';
 
 describe('normalizeString()', () => {
-
     it('lowercases the string', () => {
         expect(normalizeString('FOO')).toBe('foo');
         expect(normalizeString('Foo Bar')).toBe('foo bar');

+ 5 - 8
admin-ui/src/app/core/components/app-shell/app-shell.component.ts

@@ -2,6 +2,7 @@ import { Component, OnInit } from '@angular/core';
 import { Router } from '@angular/router';
 import { Observable } from 'rxjs';
 import { map } from 'rxjs/operators';
+
 import { DataService } from '../../../data/providers/data.service';
 import { AuthService } from '../../providers/auth/auth.service';
 
@@ -11,22 +12,18 @@ import { AuthService } from '../../providers/auth/auth.service';
     styleUrls: ['./app-shell.component.scss'],
 })
 export class AppShellComponent implements OnInit {
-
     userName$: Observable<string>;
 
-    constructor(private authService: AuthService,
-                private dataService: DataService,
-                private router: Router) { }
+    constructor(private authService: AuthService, private dataService: DataService, private router: Router) {}
 
     ngOnInit() {
-        this.userName$ = this.dataService.client.userStatus().single$.pipe(
-            map(data => data.userStatus.username),
-        );
+        this.userName$ = this.dataService.client
+            .userStatus()
+            .single$.pipe(map(data => data.userStatus.username));
     }
 
     logOut() {
         this.authService.logOut();
         this.router.navigate(['/login']);
     }
-
 }

+ 104 - 75
admin-ui/src/app/core/components/breadcrumb/breadcrumb.component.spec.ts

@@ -5,13 +5,14 @@ import { Resolve, Router, Routes } from '@angular/router';
 import { RouterTestingModule } from '@angular/router/testing';
 import { Observable, of as observableOf } from 'rxjs';
 import { BehaviorSubject } from 'rxjs/BehaviorSubject';
+
 import { notNullOrUndefined } from '../../../../../../shared/shared-utils';
 import { MockTranslatePipe } from '../../../../testing/translate.pipe.mock';
 import { DataService } from '../../../data/providers/data.service';
+
 import { BreadcrumbComponent, BreadcrumbLabelLinkPair } from './breadcrumb.component';
 
 describe('BeadcrumbsComponent', () => {
-
     let baseRouteConfig: Routes;
     let router: Router;
     let breadcrumbSubject: BehaviorSubject<string>;
@@ -99,16 +100,17 @@ describe('BeadcrumbsComponent', () => {
                         path: 'pair-function-child',
                         component: TestParentComponent,
                         data: {
-                            breadcrumb: () => [
-                                {
-                                    label: 'PairA',
-                                    link: ['foo', 'bar'],
-                                },
-                                {
-                                    label: 'PairB',
-                                    link: ['baz', 'quux'],
-                                },
-                            ] as BreadcrumbLabelLinkPair[],
+                            breadcrumb: () =>
+                                [
+                                    {
+                                        label: 'PairA',
+                                        link: ['foo', 'bar'],
+                                    },
+                                    {
+                                        label: 'PairB',
+                                        link: ['baz', 'quux'],
+                                    },
+                                ] as BreadcrumbLabelLinkPair[],
                         },
                         children: [leafRoute],
                     },
@@ -152,20 +154,21 @@ describe('BeadcrumbsComponent', () => {
                                 path: 'deep-pair-child-2',
                                 component: TestParentComponent,
                                 data: {
-                                    breadcrumb: () => [
-                                        {
-                                            label: 'PairA',
-                                            link: ['./', 'child', 'path'],
-                                        },
-                                        {
-                                            label: 'PairB',
-                                            link: ['../', 'sibling', 'path'],
-                                        },
-                                        {
-                                            label: 'PairC',
-                                            link: ['absolute', 'path'],
-                                        },
-                                    ] as BreadcrumbLabelLinkPair[],
+                                    breadcrumb: () =>
+                                        [
+                                            {
+                                                label: 'PairA',
+                                                link: ['./', 'child', 'path'],
+                                            },
+                                            {
+                                                label: 'PairB',
+                                                link: ['../', 'sibling', 'path'],
+                                            },
+                                            {
+                                                label: 'PairC',
+                                                link: ['absolute', 'path'],
+                                            },
+                                        ] as BreadcrumbLabelLinkPair[],
                                 },
                                 children: [leafRoute],
                             },
@@ -224,19 +227,9 @@ describe('BeadcrumbsComponent', () => {
         ];
 
         TestBed.configureTestingModule({
-            imports: [
-                RouterTestingModule.withRoutes(baseRouteConfig),
-            ],
-            declarations: [
-                BreadcrumbComponent,
-                TestParentComponent,
-                TestChildComponent,
-                MockTranslatePipe,
-            ],
-            providers: [
-                FooResolver,
-                { provide: DataService, useClass: class {} },
-            ],
+            imports: [RouterTestingModule.withRoutes(baseRouteConfig)],
+            declarations: [BreadcrumbComponent, TestParentComponent, TestChildComponent, MockTranslatePipe],
+            providers: [FooResolver, { provide: DataService, useClass: class {} }],
         }).compileComponents();
 
         router = TestBed.get(Router);
@@ -245,7 +238,10 @@ describe('BeadcrumbsComponent', () => {
     /**
      * Navigates to the provided route and returns the fixture for the TestChildComponent at that route.
      */
-    function getFixtureForRoute(route: string[], testFn: (fixture: ComponentFixture<TestComponent>) => void): () => void {
+    function getFixtureForRoute(
+        route: string[],
+        testFn: (fixture: ComponentFixture<TestComponent>) => void,
+    ): () => void {
         return fakeAsync(() => {
             const fixture = TestBed.createComponent(TestChildComponent);
             router.navigate(route);
@@ -256,83 +252,106 @@ describe('BeadcrumbsComponent', () => {
         });
     }
 
-    it('shows correct labels for string breadcrumbs',
+    it(
+        'shows correct labels for string breadcrumbs',
         getFixtureForRoute(['', 'string-child', 'string-grandchild'], fixture => {
             const labels = getBreadcrumbLabels(fixture);
             expect(labels).toEqual(['Root', 'Child', 'Grandchild']);
-        }));
+        }),
+    );
 
-    it('links have correct href',
+    it(
+        'links have correct href',
         getFixtureForRoute(['', 'string-child', 'string-grandchild'], fixture => {
             const links = getBreadcrumbLinks(fixture);
             expect(links).toEqual(['/', '/string-child']);
-        }));
+        }),
+    );
 
-    it('skips a route with no breadcrumbs configured',
+    it(
+        'skips a route with no breadcrumbs configured',
         getFixtureForRoute(['', 'no-breadcrumb-child', 'string-grandchild'], fixture => {
             const labels = getBreadcrumbLabels(fixture);
             expect(labels).toEqual(['Root', 'Grandchild']);
-        }));
+        }),
+    );
 
-    it('shows correct label for function breadcrumb',
+    it(
+        'shows correct label for function breadcrumb',
         getFixtureForRoute(['', 'simple-function-child', 'string-grandchild'], fixture => {
             const labels = getBreadcrumbLabels(fixture);
             expect(labels).toEqual(['Root', 'String From Function', 'Grandchild']);
-        }));
+        }),
+    );
 
-    it('works with resolved data',
+    it(
+        'works with resolved data',
         getFixtureForRoute(['', 'resolved-function-child', 'string-grandchild'], fixture => {
             const labels = getBreadcrumbLabels(fixture);
             expect(labels).toEqual(['Root', 'Foo', 'Grandchild']);
-        }));
+        }),
+    );
 
-    it('works with data from parameters',
+    it(
+        'works with data from parameters',
         getFixtureForRoute(['', 'params-child', 'Bar', 'string-grandchild'], fixture => {
             const labels = getBreadcrumbLabels(fixture);
             expect(labels).toEqual(['Root', 'Bar', 'Grandchild']);
-        }));
+        }),
+    );
 
-    it('works with a BreadcrumbLabelLinkPair',
+    it(
+        'works with a BreadcrumbLabelLinkPair',
         getFixtureForRoute(['', 'single-pair-child', 'string-grandchild'], fixture => {
             const labels = getBreadcrumbLabels(fixture);
             const links = getBreadcrumbLinks(fixture);
             expect(labels).toEqual(['Root', 'Pair', 'Grandchild']);
             expect(links).toEqual(['/', '/foo/bar;p=1']);
-        }));
+        }),
+    );
 
-    it('works with array of BreadcrumbLabelLinkPairs',
+    it(
+        'works with array of BreadcrumbLabelLinkPairs',
         getFixtureForRoute(['', 'array-pair-child', 'string-grandchild'], fixture => {
             const labels = getBreadcrumbLabels(fixture);
             const links = getBreadcrumbLinks(fixture);
             expect(labels).toEqual(['Root', 'PairA', 'PairB', 'Grandchild']);
             expect(links).toEqual(['/', '/foo/bar', '/baz/quux']);
-        }));
+        }),
+    );
 
-    it('works with function returning BreadcrumbLabelLinkPairs',
+    it(
+        'works with function returning BreadcrumbLabelLinkPairs',
         getFixtureForRoute(['', 'pair-function-child', 'string-grandchild'], fixture => {
             const labels = getBreadcrumbLabels(fixture);
             const links = getBreadcrumbLinks(fixture);
             expect(labels).toEqual(['Root', 'PairA', 'PairB', 'Grandchild']);
             expect(links).toEqual(['/', '/foo/bar', '/baz/quux']);
-        }));
+        }),
+    );
 
-    it('works with relative child paths in a BreadcrumbLabelLinkPair',
+    it(
+        'works with relative child paths in a BreadcrumbLabelLinkPair',
         getFixtureForRoute(['', 'relative-parent', 'relative-child', 'string-grandchild'], fixture => {
             const labels = getBreadcrumbLabels(fixture);
             const links = getBreadcrumbLinks(fixture);
             expect(labels).toEqual(['Root', 'Parent', 'Child', 'Grandchild']);
             expect(links).toEqual(['/', '/relative-parent', '/relative-parent/relative-child/foo;p=1']);
-        }));
+        }),
+    );
 
-    it('works with relative sibling paths in a BreadcrumbLabelLinkPair',
+    it(
+        'works with relative sibling paths in a BreadcrumbLabelLinkPair',
         getFixtureForRoute(['', 'relative-parent', 'relative-sibling', 'string-grandchild'], fixture => {
             const labels = getBreadcrumbLabels(fixture);
             const links = getBreadcrumbLinks(fixture);
             expect(labels).toEqual(['Root', 'Parent', 'Sibling', 'Grandchild']);
             expect(links).toEqual(['/', '/relative-parent', '/relative-parent/foo;p=1']);
-        }));
+        }),
+    );
 
-    it('array of BreadcrumbLabelLinkPairs paths compose correctly',
+    it(
+        'array of BreadcrumbLabelLinkPairs paths compose correctly',
         getFixtureForRoute(['', 'deep-pair-child-1', 'deep-pair-child-2', 'string-grandchild'], fixture => {
             const labels = getBreadcrumbLabels(fixture);
             const links = getBreadcrumbLinks(fixture);
@@ -344,44 +363,55 @@ describe('BeadcrumbsComponent', () => {
                 '/deep-pair-child-1/sibling/path',
                 '/absolute/path',
             ]);
-        }));
+        }),
+    );
 
-    it('shows correct labels for observable of string',
+    it(
+        'shows correct labels for observable of string',
         getFixtureForRoute(['', 'observable-string'], fixture => {
             const labels = getBreadcrumbLabels(fixture);
             const links = getBreadcrumbLinks(fixture);
             expect(labels).toEqual(['Root', 'Observable String']);
-        }));
+        }),
+    );
 
-    it('shows correct labels for observable of BreadcrumbLabelLinkPair',
+    it(
+        'shows correct labels for observable of BreadcrumbLabelLinkPair',
         getFixtureForRoute(['', 'observable-pair'], fixture => {
             const labels = getBreadcrumbLabels(fixture);
             const links = getBreadcrumbLinks(fixture);
             expect(labels).toEqual(['Root', 'Observable Pair']);
-        }));
+        }),
+    );
 
-    it('shows correct labels for observable of BreadcrumbLabelLinkPair array',
+    it(
+        'shows correct labels for observable of BreadcrumbLabelLinkPair array',
         getFixtureForRoute(['', 'observable-array-pair'], fixture => {
             const labels = getBreadcrumbLabels(fixture);
             const links = getBreadcrumbLinks(fixture);
             expect(labels).toEqual(['Root', 'Observable PairA', 'Observable PairB']);
             expect(links).toEqual(['/', '/foo/bar']);
-        }));
+        }),
+    );
 
-    it('shows correct labels for function returning observable string',
+    it(
+        'shows correct labels for function returning observable string',
         getFixtureForRoute(['', 'function-observable'], fixture => {
             const labels = getBreadcrumbLabels(fixture);
             const links = getBreadcrumbLinks(fixture);
             expect(labels).toEqual(['Root', 'Observable String From Function']);
-        }));
+        }),
+    );
 
-    it('labels update when observables emit new values',
+    it(
+        'labels update when observables emit new values',
         getFixtureForRoute(['', 'observable-string-subject', 'string-grandchild'], fixture => {
             expect(getBreadcrumbLabels(fixture)).toEqual(['Root', 'Initial Value', 'Grandchild']);
             breadcrumbSubject.next('New Value');
             fixture.detectChanges();
             expect(getBreadcrumbLabels(fixture)).toEqual(['Root', 'New Value', 'Grandchild']);
-        }));
+        }),
+    );
 });
 
 function getBreadcrumbsElement(fixture: ComponentFixture<TestComponent>): DebugElement {
@@ -389,8 +419,7 @@ function getBreadcrumbsElement(fixture: ComponentFixture<TestComponent>): DebugE
 }
 
 function getBreadcrumbListItems(fixture: ComponentFixture<TestComponent>): HTMLLIElement[] {
-    return fixture.debugElement.queryAll(By.css('.breadcrumbs li'))
-        .map(de => de.nativeElement);
+    return fixture.debugElement.queryAll(By.css('.breadcrumbs li')).map(de => de.nativeElement);
 }
 
 function getBreadcrumbLabels(fixture: ComponentFixture<TestComponent>): string[] {

+ 44 - 33
admin-ui/src/app/core/components/breadcrumb/breadcrumb.component.ts

@@ -3,6 +3,7 @@ import { ActivatedRoute, Data, NavigationEnd, Params, PRIMARY_OUTLET, Router } f
 import { flatten } from 'lodash';
 import { combineLatest as observableCombineLatest, Observable, of as observableOf, Subject } from 'rxjs';
 import { filter, map, startWith, switchMap, takeUntil } from 'rxjs/operators';
+
 import { DataService } from '../../../data/providers/data.service';
 
 export type BreadcrumbString = string;
@@ -11,7 +12,11 @@ export interface BreadcrumbLabelLinkPair {
     link: any[];
 }
 export type BreadcrumbValue = BreadcrumbString | BreadcrumbLabelLinkPair | BreadcrumbLabelLinkPair[];
-export type BreadcrumbFunction = (data: Data, params: Params, dataService: DataService) => BreadcrumbValue | Observable<BreadcrumbValue>;
+export type BreadcrumbFunction = (
+    data: Data,
+    params: Params,
+    dataService: DataService,
+) => BreadcrumbValue | Observable<BreadcrumbValue>;
 export type BreadcrumbDefinition = BreadcrumbValue | BreadcrumbFunction | Observable<BreadcrumbValue>;
 
 /**
@@ -29,13 +34,10 @@ export type BreadcrumbDefinition = BreadcrumbValue | BreadcrumbFunction | Observ
     styleUrls: ['./breadcrumb.component.scss'],
 })
 export class BreadcrumbComponent implements OnDestroy {
-
-    breadcrumbs$: Observable<Array<{ link: string | any[]; label: string; }>>;
+    breadcrumbs$: Observable<Array<{ link: string | any[]; label: string }>>;
     private destroy$ = new Subject<void>();
 
-    constructor(private router: Router,
-                private route: ActivatedRoute,
-                private dataService: DataService) {
+    constructor(private router: Router, private route: ActivatedRoute, private dataService: DataService) {
         this.breadcrumbs$ = this.router.events.pipe(
             filter(event => event instanceof NavigationEnd),
             takeUntil(this.destroy$),
@@ -49,31 +51,32 @@ export class BreadcrumbComponent implements OnDestroy {
         this.destroy$.complete();
     }
 
-    private generateBreadcrumbs(rootRoute: ActivatedRoute): Observable<Array<{ link: Array<string | any>; label: string; }>> {
+    private generateBreadcrumbs(
+        rootRoute: ActivatedRoute,
+    ): Observable<Array<{ link: Array<string | any>; label: string }>> {
         const breadcrumbParts = this.assembleBreadcrumbParts(rootRoute);
-        const breadcrumbObservables$ = breadcrumbParts
-            .map(({ value$, path }) => {
-                return value$.pipe(
-                    map(value => {
-                        if (isBreadcrumbLabelLinkPair(value)) {
-                            return {
-                                label: value.label,
-                                link: this.normalizeRelativeLinks(value.link, path),
-                            };
-                        } else if (isBreadcrumbPairArray(value)) {
-                            return value.map(val => ({
-                                label: val.label,
-                                link: this.normalizeRelativeLinks(val.link, path),
-                            }));
-                        } else {
-                            return {
-                                label: value,
-                                link: '/' + path.join('/'),
-                            };
-                        }
-                    }),
-                ) as Observable<BreadcrumbLabelLinkPair | BreadcrumbLabelLinkPair[]>;
-            });
+        const breadcrumbObservables$ = breadcrumbParts.map(({ value$, path }) => {
+            return value$.pipe(
+                map(value => {
+                    if (isBreadcrumbLabelLinkPair(value)) {
+                        return {
+                            label: value.label,
+                            link: this.normalizeRelativeLinks(value.link, path),
+                        };
+                    } else if (isBreadcrumbPairArray(value)) {
+                        return value.map(val => ({
+                            label: val.label,
+                            link: this.normalizeRelativeLinks(val.link, path),
+                        }));
+                    } else {
+                        return {
+                            label: value,
+                            link: '/' + path.join('/'),
+                        };
+                    }
+                }),
+            ) as Observable<BreadcrumbLabelLinkPair | BreadcrumbLabelLinkPair[]>;
+        });
 
         return observableCombineLatest(breadcrumbObservables$).pipe(map(links => flatten(links)));
     }
@@ -81,7 +84,9 @@ export class BreadcrumbComponent implements OnDestroy {
     /**
      * Walks the route definition tree to assemble an array from which the breadcrumbs can be derived.
      */
-    private assembleBreadcrumbParts(rootRoute: ActivatedRoute): Array<{ value$: Observable<BreadcrumbValue>; path: string[] }> {
+    private assembleBreadcrumbParts(
+        rootRoute: ActivatedRoute,
+    ): Array<{ value$: Observable<BreadcrumbValue>; path: string[] }> {
         const breadcrumbParts: Array<{ value$: Observable<BreadcrumbValue>; path: string[] }> = [];
         const inferredUrl = '';
         const segmentPaths: string[] = [];
@@ -98,9 +103,15 @@ export class BreadcrumbComponent implements OnDestroy {
 
                     if (breadcrumbDef) {
                         if (isBreadcrumbFunction(breadcrumbDef)) {
-                            breadcrumbDef = breadcrumbDef(routeSnapshot.data, routeSnapshot.params, this.dataService);
+                            breadcrumbDef = breadcrumbDef(
+                                routeSnapshot.data,
+                                routeSnapshot.params,
+                                this.dataService,
+                            );
                         }
-                        const observableValue = isObservable(breadcrumbDef) ? breadcrumbDef : observableOf(breadcrumbDef);
+                        const observableValue = isObservable(breadcrumbDef)
+                            ? breadcrumbDef
+                            : observableOf(breadcrumbDef);
                         breadcrumbParts.push({ value$: observableValue, path: segmentPaths.slice() });
                     }
                     currentRoute = route;

+ 4 - 6
admin-ui/src/app/core/components/main-nav/main-nav.component.ts

@@ -1,10 +1,8 @@
 import { Component, OnInit } from '@angular/core';
 
 @Component({
-  selector: 'vdr-main-nav',
-  templateUrl: './main-nav.component.html',
-  styleUrls: ['./main-nav.component.scss'],
+    selector: 'vdr-main-nav',
+    templateUrl: './main-nav.component.html',
+    styleUrls: ['./main-nav.component.scss'],
 })
-export class MainNavComponent {
-
-}
+export class MainNavComponent {}

+ 3 - 2
admin-ui/src/app/core/components/notification/notification.component.ts

@@ -8,13 +8,14 @@ import { NotificationType } from '../../providers/notification/notification.serv
     styleUrls: ['./notification.component.scss'],
 })
 export class NotificationComponent {
-
     @ViewChild('wrapper') wrapper: ElementRef;
     offsetTop = 0;
     message = '';
     type: NotificationType = 'info';
     isVisible = true;
-    private onClickFn: () => void = () => { /* */ };
+    private onClickFn: () => void = () => {
+        /* */
+    };
 
     registerOnClickFn(fn: () => void): void {
         this.onClickFn = fn;

+ 2 - 2
admin-ui/src/app/core/components/overlay-host/overlay-host.component.ts

@@ -1,6 +1,6 @@
-import {Component, ViewContainerRef} from '@angular/core';
+import { Component, ViewContainerRef } from '@angular/core';
 
-import {OverlayHostService} from '../../providers/overlay-host/overlay-host.service';
+import { OverlayHostService } from '../../providers/overlay-host/overlay-host.service';
 
 /**
  * The OverlayHostComponent is a placeholder component which provides a location in the DOM into which overlay

+ 2 - 4
admin-ui/src/app/core/components/ui-language-switcher/ui-language-switcher.component.ts

@@ -1,6 +1,7 @@
 import { ChangeDetectionStrategy, Component, OnInit } from '@angular/core';
 import { Observable } from 'rxjs';
 import { map, tap } from 'rxjs/operators';
+
 import { DataService } from '../../../data/providers/data.service';
 import { LanguageCode } from '../../../data/types/gql-generated-types';
 import { I18nService } from '../../providers/i18n/i18n.service';
@@ -12,11 +13,9 @@ import { I18nService } from '../../providers/i18n/i18n.service';
     changeDetection: ChangeDetectionStrategy.OnPush,
 })
 export class UiLanguageSwitcherComponent implements OnInit {
-
     uiLanguage$: Observable<LanguageCode>;
 
-    constructor(private dataService: DataService,
-                private i18nService: I18nService) { }
+    constructor(private dataService: DataService, private i18nService: I18nService) {}
 
     ngOnInit() {
         this.uiLanguage$ = this.dataService.client.uiState().stream$.pipe(
@@ -28,5 +27,4 @@ export class UiLanguageSwitcherComponent implements OnInit {
     setLanguage(languageCode: LanguageCode) {
         this.dataService.client.setUiLanguage(languageCode).subscribe();
     }
-
 }

+ 2 - 5
admin-ui/src/app/core/components/user-menu/user-menu.component.ts

@@ -6,10 +6,7 @@ import { Component, EventEmitter, Input, OnInit, Output } from '@angular/core';
     styleUrls: ['./user-menu.component.scss'],
 })
 export class UserMenuComponent {
+    @Input() userName = '';
 
-    @Input()
-    userName = '';
-
-    @Output()
-    logOut = new EventEmitter<void>();
+    @Output() logOut = new EventEmitter<void>();
 }

+ 4 - 9
admin-ui/src/app/core/core.module.ts

@@ -1,7 +1,9 @@
 import { NgModule } from '@angular/core';
 import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
+
 import { DataModule } from '../data/data.module';
 import { SharedModule } from '../shared/shared.module';
+
 import { AppShellComponent } from './components/app-shell/app-shell.component';
 import { BreadcrumbComponent } from './components/breadcrumb/breadcrumb.component';
 import { MainNavComponent } from './components/main-nav/main-nav.component';
@@ -17,15 +19,8 @@ import { NotificationService } from './providers/notification/notification.servi
 import { OverlayHostService } from './providers/overlay-host/overlay-host.service';
 
 @NgModule({
-    imports: [
-        DataModule,
-        SharedModule,
-        BrowserAnimationsModule,
-    ],
-    exports: [
-        SharedModule,
-        OverlayHostComponent,
-    ],
+    imports: [DataModule, SharedModule, BrowserAnimationsModule],
+    exports: [SharedModule, OverlayHostComponent],
     providers: [
         LocalStorageService,
         AuthGuard,

+ 2 - 3
admin-ui/src/app/core/providers/auth/auth.service.ts

@@ -1,6 +1,7 @@
 import { Injectable } from '@angular/core';
 import { Observable, of } from 'rxjs';
 import { catchError, map, mergeMap, switchMap } from 'rxjs/operators';
+
 import { DataService } from '../../../data/providers/data.service';
 import { LogIn } from '../../../data/types/gql-generated-types';
 import { LocalStorageService } from '../local-storage/local-storage.service';
@@ -10,9 +11,7 @@ import { LocalStorageService } from '../local-storage/local-storage.service';
  */
 @Injectable()
 export class AuthService {
-
-    constructor(private localStorageService: LocalStorageService,
-                private dataService: DataService) {}
+    constructor(private localStorageService: LocalStorageService, private dataService: DataService) {}
 
     /**
      * Attempts to log in via the REST login endpoint and updates the app

+ 2 - 4
admin-ui/src/app/core/providers/guard/auth.guard.ts

@@ -2,6 +2,7 @@ import { Injectable } from '@angular/core';
 import { ActivatedRouteSnapshot, CanActivate, Router } from '@angular/router';
 import { Observable } from 'rxjs';
 import { tap } from 'rxjs/operators';
+
 import { AuthService } from '../auth/auth.service';
 
 /**
@@ -10,12 +11,9 @@ import { AuthService } from '../auth/auth.service';
  */
 @Injectable()
 export class AuthGuard implements CanActivate {
-
-    constructor(private router: Router,
-                private authService: AuthService) {}
+    constructor(private router: Router, private authService: AuthService) {}
 
     canActivate(route: ActivatedRouteSnapshot): Observable<boolean> {
-
         return this.authService.checkAuthenticatedStatus().pipe(
             tap(authenticated => {
                 if (authenticated) {

+ 9 - 5
admin-ui/src/app/core/providers/i18n/custom-http-loader.ts

@@ -15,12 +15,16 @@ export type Dictionary = {
  * Orignally from https://github.com/ngx-translate/core/issues/662#issuecomment-377010232
  */
 export class CustomHttpTranslationLoader implements TranslateLoader {
-    constructor(private http: HttpClient, private prefix: string = '/assets/i18n/', private suffix: string = '.json') {
-    }
+    constructor(
+        private http: HttpClient,
+        private prefix: string = '/assets/i18n/',
+        private suffix: string = '.json',
+    ) {}
 
     public getTranslation(lang: string): Observable<any> {
-        return this.http.get(`${this.prefix}${lang}${this.suffix}`).pipe(
-            map((res: any) => this.process(res)));
+        return this.http
+            .get(`${this.prefix}${lang}${this.suffix}`)
+            .pipe(map((res: any) => this.process(res)));
     }
 
     private process(object: Dictionary): Dictionary {
@@ -31,7 +35,7 @@ export class CustomHttpTranslationLoader implements TranslateLoader {
                 const value = object[key];
                 if (typeof value !== 'string') {
                     newObject[key] = this.process(value);
-                } else if ((typeof value === 'string') && (value === '')) {
+                } else if (typeof value === 'string' && value === '') {
                     // do not copy empty strings
                 } else {
                     newObject[key] = object[key];

+ 2 - 1
admin-ui/src/app/core/providers/i18n/mark-for-extraction.ts

@@ -1,7 +1,8 @@
+// tslint:disable:max-line-length
 /**
  * The purpose of this function is to mark strings for extraction by ngx-translate-extract.
  * See https://github.com/biesbjerg/ngx-translate-extract/tree/7d5d38e6a17c2232407bf6b0bc65808d5f81208d#mark-strings-for-extraction-using-a-marker-function
  */
 export function _(key: string | string[]): string | string[] {
-	return key;
+    return key;
 }

+ 1 - 2
admin-ui/src/app/core/providers/local-storage/local-storage.service.ts

@@ -1,4 +1,4 @@
-import {Injectable} from '@angular/core';
+import { Injectable } from '@angular/core';
 
 export type LocalStorageKey = 'authToken';
 const PREFIX = 'vnd_';
@@ -8,7 +8,6 @@ const PREFIX = 'vnd_';
  */
 @Injectable()
 export class LocalStorageService {
-
     /**
      * Set a key-value pair in the browser's LocalStorage
      */

+ 64 - 60
admin-ui/src/app/core/providers/notification/notification.service.spec.ts

@@ -1,26 +1,18 @@
 import { Component, CUSTOM_ELEMENTS_SCHEMA } from '@angular/core';
-import {ComponentFixture, fakeAsync, TestBed, tick} from '@angular/core/testing';
-import {BrowserDynamicTestingModule} from '@angular/platform-browser-dynamic/testing';
+import { ComponentFixture, fakeAsync, TestBed, tick } from '@angular/core/testing';
+import { BrowserDynamicTestingModule } from '@angular/platform-browser-dynamic/testing';
 
-import {NotificationComponent} from '../../components/notification/notification.component';
-import {OverlayHostComponent} from '../../components/overlay-host/overlay-host.component';
-import {OverlayHostService} from '../overlay-host/overlay-host.service';
+import { NotificationComponent } from '../../components/notification/notification.component';
+import { OverlayHostComponent } from '../../components/overlay-host/overlay-host.component';
+import { OverlayHostService } from '../overlay-host/overlay-host.service';
 
-import {NotificationService} from './notification.service';
+import { NotificationService } from './notification.service';
 
 describe('NotificationService:', () => {
-
     beforeEach(() => {
         TestBed.configureTestingModule({
-            declarations: [
-                NotificationComponent,
-                OverlayHostComponent,
-                TestComponent,
-            ],
-            providers: [
-                NotificationService,
-                OverlayHostService,
-            ],
+            declarations: [NotificationComponent, OverlayHostComponent, TestComponent],
+            providers: [NotificationService, OverlayHostService],
             schemas: [CUSTOM_ELEMENTS_SCHEMA],
         });
         // TODO: it looks like there will be an easier way to declare the entryComponents,
@@ -33,7 +25,6 @@ describe('NotificationService:', () => {
     });
 
     describe('notification():', () => {
-
         // The ToastComponent relies heavily on async calls to schedule the dismissal of a notify.
         function runDismissTimers(): void {
             tick(5000); // duration timeout
@@ -44,49 +35,62 @@ describe('NotificationService:', () => {
 
         let fixture: ComponentFixture<TestComponent>;
 
-        beforeEach(fakeAsync(() => {
-            fixture = TestBed.createComponent(TestComponent);
-            tick();
-            fixture.detectChanges();
-        }));
-
-        it('should insert notify next to OverlayHost', fakeAsync(() => {
-            const instance: TestComponent = fixture.componentInstance;
-
-            instance.notificationService.notify({ message: 'test'});
-            fixture.detectChanges();
-            tick();
-
-            expect(fixture.nativeElement.querySelector('vdr-notification')).not.toBeNull();
-            runDismissTimers();
-        }));
-
-        it('should bind the message', fakeAsync(() => {
-            const instance: TestComponent = fixture.componentInstance;
-
-            instance.notificationService.notify({ message: 'test'});
-            tick();
-            fixture.detectChanges();
-
-            expect(fixture.nativeElement.querySelector('.notification-wrapper').innerHTML).toContain('test');
-            runDismissTimers();
-        }));
-
-        it('should dismiss after duration elapses', fakeAsync(() => {
-            const instance: TestComponent = fixture.componentInstance;
-
-            instance.notificationService.notify({
-                message: 'test',
-                duration: 1000,
-            });
-            tick();
-            fixture.detectChanges();
-            expect(fixture.nativeElement.querySelector('vdr-notification')).not.toBeNull();
-
-            runDismissTimers();
-
-            expect(fixture.nativeElement.querySelector('vdr-notification')).toBeNull();
-        }));
+        beforeEach(
+            fakeAsync(() => {
+                fixture = TestBed.createComponent(TestComponent);
+                tick();
+                fixture.detectChanges();
+            }),
+        );
+
+        it(
+            'should insert notify next to OverlayHost',
+            fakeAsync(() => {
+                const instance: TestComponent = fixture.componentInstance;
+
+                instance.notificationService.notify({ message: 'test' });
+                fixture.detectChanges();
+                tick();
+
+                expect(fixture.nativeElement.querySelector('vdr-notification')).not.toBeNull();
+                runDismissTimers();
+            }),
+        );
+
+        it(
+            'should bind the message',
+            fakeAsync(() => {
+                const instance: TestComponent = fixture.componentInstance;
+
+                instance.notificationService.notify({ message: 'test' });
+                tick();
+                fixture.detectChanges();
+
+                expect(fixture.nativeElement.querySelector('.notification-wrapper').innerHTML).toContain(
+                    'test',
+                );
+                runDismissTimers();
+            }),
+        );
+
+        it(
+            'should dismiss after duration elapses',
+            fakeAsync(() => {
+                const instance: TestComponent = fixture.componentInstance;
+
+                instance.notificationService.notify({
+                    message: 'test',
+                    duration: 1000,
+                });
+                tick();
+                fixture.detectChanges();
+                expect(fixture.nativeElement.querySelector('vdr-notification')).not.toBeNull();
+
+                runDismissTimers();
+
+                expect(fixture.nativeElement.querySelector('vdr-notification')).toBeNull();
+            }),
+        );
     });
 });
 

+ 9 - 11
admin-ui/src/app/core/providers/notification/notification.service.ts

@@ -1,8 +1,8 @@
-import {ComponentFactoryResolver, ComponentRef, Injectable, ViewContainerRef} from '@angular/core';
+import { ComponentFactoryResolver, ComponentRef, Injectable, ViewContainerRef } from '@angular/core';
 
-import {OverlayHostService} from '../overlay-host/overlay-host.service';
+import { OverlayHostService } from '../overlay-host/overlay-host.service';
 
-import {NotificationComponent} from '../../components/notification/notification.component';
+import { NotificationComponent } from '../../components/notification/notification.component';
 
 export type NotificationType = 'info' | 'success' | 'error' | 'warning';
 export interface ToastConfig {
@@ -19,9 +19,8 @@ const TOAST_DURATION = 3000;
  */
 @Injectable()
 export class NotificationService {
-
     private hostView: ViewContainerRef;
-    private openToastRefs: Array<{ ref: ComponentRef<NotificationComponent>, timerId: any }> = [];
+    private openToastRefs: Array<{ ref: ComponentRef<NotificationComponent>; timerId: any }> = [];
 
     constructor(private resolver: ComponentFactoryResolver, overlayHostService: OverlayHostService) {
         overlayHostService.getHostView().then(view => {
@@ -111,12 +110,11 @@ export class NotificationService {
                 clearTimeout(this.openToastRefs[index].timerId);
             }
 
-            toast.fadeOut()
-                .then(() => {
-                    ref.destroy();
-                    this.openToastRefs.splice(index, 1);
-                    this.calculatePositions();
-                });
+            toast.fadeOut().then(() => {
+                ref.destroy();
+                this.openToastRefs.splice(index, 1);
+                this.calculatePositions();
+            });
         };
     }
 

+ 1 - 2
admin-ui/src/app/core/providers/overlay-host/overlay-host.service.ts

@@ -1,4 +1,4 @@
-import {Injectable, ViewContainerRef} from '@angular/core';
+import { Injectable, ViewContainerRef } from '@angular/core';
 
 /**
  * The OverlayHostService is used to get a reference to the ViewConainerRef of the
@@ -7,7 +7,6 @@ import {Injectable, ViewContainerRef} from '@angular/core';
  */
 @Injectable()
 export class OverlayHostService {
-
     private hostView: ViewContainerRef;
     private promiseResolveFns: Array<(result: any) => void> = [];
 

+ 1 - 1
admin-ui/src/app/dashboard/components/dashboard/dashboard.component.spec.ts

@@ -3,7 +3,7 @@ import { async, ComponentFixture, TestBed } from '@angular/core/testing';
 import { DashboardComponent } from './dashboard.component';
 
 describe('DashboardComponent', () => {
- /*   let component: DashboardComponent;
+    /*   let component: DashboardComponent;
     let fixture: ComponentFixture<DashboardComponent>;
 
     beforeEach(async(() => {

+ 1 - 2
admin-ui/src/app/dashboard/components/dashboard/dashboard.component.ts

@@ -5,5 +5,4 @@ import { Component } from '@angular/core';
     templateUrl: './dashboard.component.html',
     styleUrls: ['./dashboard.component.scss'],
 })
-export class DashboardComponent {
-}
+export class DashboardComponent {}

+ 2 - 5
admin-ui/src/app/dashboard/dashboard.module.ts

@@ -8,10 +8,7 @@ import { DashboardComponent } from './components/dashboard/dashboard.component';
 import { dashboardRoutes } from './dashboard.routes';
 
 @NgModule({
-    imports: [
-        SharedModule,
-        RouterModule.forChild(dashboardRoutes),
-    ],
+    imports: [SharedModule, RouterModule.forChild(dashboardRoutes)],
     declarations: [DashboardComponent],
 })
-export class DashboardModule { }
+export class DashboardModule {}

+ 4 - 2
admin-ui/src/app/data/client-state/client-resolvers.ts

@@ -1,11 +1,13 @@
 import { InMemoryCache } from 'apollo-cache-inmemory';
 import { GraphQLFieldResolver } from 'graphql';
+
 import { GET_NEWTORK_STATUS } from '../queries/local-queries';
 import {
     GetNetworkStatus,
     GetUiState,
     GetUserStatus,
-    GetUserStatus_userStatus, LanguageCode,
+    GetUserStatus_userStatus,
+    LanguageCode,
     LogInVariables,
     SetUiLanguageVariables,
 } from '../types/gql-generated-types';
@@ -19,7 +21,7 @@ export type ResolverContext = {
 export type ResolverDefinition = {
     Mutation: {
         [name: string]: GraphQLFieldResolver<any, ResolverContext, any>;
-    },
+    };
 };
 
 export const clientResolvers: ResolverDefinition = {

+ 9 - 8
admin-ui/src/app/data/data.module.ts

@@ -5,9 +5,11 @@ import { HttpLink, HttpLinkModule } from 'apollo-angular-link-http';
 import { InMemoryCache } from 'apollo-cache-inmemory';
 import { ApolloLink } from 'apollo-link';
 import { withClientState } from 'apollo-link-state';
+
 import { API_PATH } from '../../../../shared/shared-constants';
 import { environment } from '../../environments/environment';
 import { API_URL } from '../app.config';
+
 import { clientDefaults } from './client-state/client-defaults';
 import { clientResolvers } from './client-state/client-resolvers';
 import { OmitTypenameLink } from './omit-typename-link';
@@ -30,7 +32,11 @@ const stateLink = withClientState({
 
 export function createApollo(httpLink: HttpLink) {
     return {
-        link:  ApolloLink.from([stateLink, new OmitTypenameLink(), httpLink.create({ uri: `${API_URL}/${API_PATH}` })]),
+        link: ApolloLink.from([
+            stateLink,
+            new OmitTypenameLink(),
+            httpLink.create({ uri: `${API_URL}/${API_PATH}` }),
+        ]),
         cache: apolloCache,
     };
 }
@@ -40,11 +46,7 @@ export function createApollo(httpLink: HttpLink) {
  * state via the apollo-link-state package.
  */
 @NgModule({
-    imports: [
-        ApolloModule,
-        HttpLinkModule,
-        HttpClientModule,
-    ],
+    imports: [ApolloModule, HttpLinkModule, HttpClientModule],
     exports: [],
     declarations: [],
     providers: [
@@ -58,5 +60,4 @@ export function createApollo(httpLink: HttpLink) {
         { provide: HTTP_INTERCEPTORS, useClass: DefaultInterceptor, multi: true },
     ],
 })
-export class DataModule {
-}
+export class DataModule {}

+ 1 - 1
admin-ui/src/app/data/fragments/product-fragments.ts

@@ -13,7 +13,7 @@ export const PRODUCT_WITH_VARIANTS_FRAGMENT = gql`
             name
             slug
             description
-        },
+        }
         optionGroups {
             id
             languageCode

+ 9 - 6
admin-ui/src/app/data/mutations/product-mutations.ts

@@ -1,13 +1,16 @@
 import gql from 'graphql-tag';
 
-import { PRODUCT_OPTION_GROUP_FRAGMENT, PRODUCT_WITH_VARIANTS_FRAGMENT } from '../fragments/product-fragments';
+import {
+    PRODUCT_OPTION_GROUP_FRAGMENT,
+    PRODUCT_WITH_VARIANTS_FRAGMENT,
+} from '../fragments/product-fragments';
 
 export const UPDATE_PRODUCT = gql`
     mutation UpdateProduct($input: UpdateProductInput!) {
-    	updateProduct(input: $input) {
-    		...ProductWithVariants
-    	}
-    },
+        updateProduct(input: $input) {
+            ...ProductWithVariants
+        }
+    }
     ${PRODUCT_WITH_VARIANTS_FRAGMENT}
 `;
 
@@ -16,7 +19,7 @@ export const CREATE_PRODUCT_OPTION_GROUP = gql`
         createProductOptionGroup(input: $input) {
             ...ProductOptionGroup
         }
-    },
+    }
     ${PRODUCT_OPTION_GROUP_FRAGMENT}
 `;
 

+ 1 - 1
admin-ui/src/app/data/omit-typename-link.ts

@@ -19,6 +19,6 @@ export class OmitTypenameLink extends ApolloLink {
     }
 
     private omitTypename(key: string, value: string): string | undefined {
-      return key === '__typename' ? undefined : value;
+        return key === '__typename' ? undefined : value;
     }
 }

+ 23 - 23
admin-ui/src/app/data/providers/base-data.service.ts

@@ -4,16 +4,18 @@ import { Apollo } from 'apollo-angular';
 import { DocumentNode } from 'graphql/language/ast';
 import { Observable } from 'rxjs';
 import { map } from 'rxjs/operators';
+
 import { API_URL } from '../../app.config';
 import { LocalStorageService } from '../../core/providers/local-storage/local-storage.service';
 import { QueryResult } from '../types/query-result';
 
 @Injectable()
 export class BaseDataService {
-
-    constructor(private apollo: Apollo,
-                private httpClient: HttpClient,
-                private localStorageService: LocalStorageService) {}
+    constructor(
+        private apollo: Apollo,
+        private httpClient: HttpClient,
+        private localStorageService: LocalStorageService,
+    ) {}
 
     /**
      * Performs a GraphQL watch query
@@ -35,41 +37,39 @@ export class BaseDataService {
      * Performs a GraphQL mutation
      */
     mutate<T, V = Record<string, any>>(mutation: DocumentNode, variables?: V): Observable<T> {
-        return this.apollo.mutate<T, V>({ mutation, variables }).pipe(
-            map(result => result.data as T));
+        return this.apollo.mutate<T, V>({ mutation, variables }).pipe(map(result => result.data as T));
     }
 
     /**
      * Perform REST-like POST
      */
     post(path: string, payload: Record<string, any>): Observable<any> {
-        return this.httpClient.post(`${API_URL}/${path}`, payload, {
-            headers: {
-                Authorization: this.getAuthHeader(),
-            },
-            observe: 'response',
-        }).pipe(
-            map(response => response.body),
-        );
+        return this.httpClient
+            .post(`${API_URL}/${path}`, payload, {
+                headers: {
+                    Authorization: this.getAuthHeader(),
+                },
+                observe: 'response',
+            })
+            .pipe(map(response => response.body));
     }
 
     /**
      * Perform REST-like GET
      */
     get(path: string): Observable<any> {
-        return this.httpClient.get(`${API_URL}/${path}`, {
-            headers: {
-                Authorization: this.getAuthHeader(),
-            },
-            observe: 'response',
-        }).pipe(
-            map(response => response.body),
-        );
+        return this.httpClient
+            .get(`${API_URL}/${path}`, {
+                headers: {
+                    Authorization: this.getAuthHeader(),
+                },
+                observe: 'response',
+            })
+            .pipe(map(response => response.body));
     }
 
     private getAuthHeader(): string {
         const authToken = this.localStorageService.get('authToken');
         return `Bearer ${authToken}`;
     }
-
 }

+ 12 - 3
admin-ui/src/app/data/providers/client-data.service.ts

@@ -1,5 +1,12 @@
 import { Observable } from 'rxjs';
-import { LOG_IN, LOG_OUT, REQUEST_COMPLETED, REQUEST_STARTED, SET_UI_LANGUAGE } from '../mutations/local-mutations';
+
+import {
+    LOG_IN,
+    LOG_OUT,
+    REQUEST_COMPLETED,
+    REQUEST_STARTED,
+    SET_UI_LANGUAGE,
+} from '../mutations/local-mutations';
 import { GET_NEWTORK_STATUS, GET_UI_STATE, GET_USER_STATUS } from '../queries/local-queries';
 import {
     GetNetworkStatus,
@@ -15,10 +22,10 @@ import {
     SetUiLanguageVariables,
 } from '../types/gql-generated-types';
 import { QueryResult } from '../types/query-result';
+
 import { BaseDataService } from './base-data.service';
 
 export class ClientDataService {
-
     constructor(private baseDataService: BaseDataService) {}
 
     startRequest(): Observable<RequestStarted> {
@@ -53,6 +60,8 @@ export class ClientDataService {
     }
 
     setUiLanguage(languageCode: LanguageCode): Observable<SetUiLanguage> {
-        return this.baseDataService.mutate<SetUiLanguage, SetUiLanguageVariables>(SET_UI_LANGUAGE, { languageCode });
+        return this.baseDataService.mutate<SetUiLanguage, SetUiLanguageVariables>(SET_UI_LANGUAGE, {
+            languageCode,
+        });
     }
 }

+ 1 - 3
admin-ui/src/app/data/providers/data.service.mock.ts

@@ -1,3 +1 @@
-export class MockDataService {
-
-}
+export class MockDataService {}

+ 0 - 1
admin-ui/src/app/data/providers/data.service.ts

@@ -16,5 +16,4 @@ export class DataService {
         this.product = new ProductDataService(baseDataService);
         this.client = new ClientDataService(baseDataService);
     }
-
 }

+ 15 - 8
admin-ui/src/app/data/providers/interceptor.ts

@@ -1,10 +1,18 @@
 /** Pass untouched request through to the next request handler. */
-import { HttpErrorResponse, HttpEvent, HttpHandler, HttpInterceptor, HttpRequest, HttpResponse } from '@angular/common/http';
+import {
+    HttpErrorResponse,
+    HttpEvent,
+    HttpHandler,
+    HttpInterceptor,
+    HttpRequest,
+    HttpResponse,
+} from '@angular/common/http';
 import { Injectable } from '@angular/core';
 import { Observable, throwError } from 'rxjs';
 import { catchError, tap } from 'rxjs/operators';
 
 import { NotificationService } from '../../core/providers/notification/notification.service';
+
 import { DataService } from './data.service';
 
 /**
@@ -13,15 +21,13 @@ import { DataService } from './data.service';
  */
 @Injectable()
 export class DefaultInterceptor implements HttpInterceptor {
+    constructor(private dataService: DataService, private notification: NotificationService) {}
 
-    constructor(private dataService: DataService,
-                private notification: NotificationService) {}
-
-    intercept(req: HttpRequest<any>, next: HttpHandler):
-        Observable<HttpEvent<any>> {
+    intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
         this.dataService.client.startRequest().subscribe();
         return next.handle(req).pipe(
-            tap(event => {
+            tap(
+                event => {
                     if (event instanceof HttpResponse) {
                         this.notifyOnGraphQLErrors(event);
                         this.dataService.client.completeRequest().subscribe();
@@ -32,7 +38,8 @@ export class DefaultInterceptor implements HttpInterceptor {
                         this.notification.error(err.message);
                         this.dataService.client.completeRequest().subscribe();
                     }
-                }),
+                },
+            ),
         );
     }
 

+ 32 - 12
admin-ui/src/app/data/providers/product-data.service.ts

@@ -1,6 +1,11 @@
 import { Observable } from 'rxjs';
+
 import { getDefaultLanguage } from '../../common/utilities/get-default-language';
-import { ADD_OPTION_GROUP_TO_PRODUCT, CREATE_PRODUCT_OPTION_GROUP, UPDATE_PRODUCT } from '../mutations/product-mutations';
+import {
+    ADD_OPTION_GROUP_TO_PRODUCT,
+    CREATE_PRODUCT_OPTION_GROUP,
+    UPDATE_PRODUCT,
+} from '../mutations/product-mutations';
 import { GET_PRODUCT_LIST, GET_PRODUCT_WITH_VARIANTS } from '../queries/product-queries';
 import {
     AddOptionGroupToProduct,
@@ -21,19 +26,24 @@ import { QueryResult } from '../types/query-result';
 import { BaseDataService } from './base-data.service';
 
 export class ProductDataService {
-
     constructor(private baseDataService: BaseDataService) {}
 
     getProducts(take: number = 10, skip: number = 0): QueryResult<GetProductList, GetProductListVariables> {
-        return this.baseDataService
-            .query<GetProductList, GetProductListVariables>(GET_PRODUCT_LIST, { take, skip, languageCode: getDefaultLanguage() });
+        return this.baseDataService.query<GetProductList, GetProductListVariables>(GET_PRODUCT_LIST, {
+            take,
+            skip,
+            languageCode: getDefaultLanguage(),
+        });
     }
 
     getProduct(id: string): QueryResult<GetProductWithVariants, GetProductWithVariantsVariables> {
-        return this.baseDataService.query<GetProductWithVariants, GetProductWithVariantsVariables>(GET_PRODUCT_WITH_VARIANTS, {
-            id,
-            languageCode: getDefaultLanguage(),
-        });
+        return this.baseDataService.query<GetProductWithVariants, GetProductWithVariantsVariables>(
+            GET_PRODUCT_WITH_VARIANTS,
+            {
+                id,
+                languageCode: getDefaultLanguage(),
+            },
+        );
     }
 
     updateProduct(product: UpdateProductInput): Observable<UpdateProduct> {
@@ -47,14 +57,24 @@ export class ProductDataService {
         return this.baseDataService.mutate<UpdateProduct, UpdateProductVariables>(UPDATE_PRODUCT, input);
     }
 
-    createProductOptionGroups(productOptionGroup: CreateProductOptionGroupInput): Observable<CreateProductOptionGroup> {
+    createProductOptionGroups(
+        productOptionGroup: CreateProductOptionGroupInput,
+    ): Observable<CreateProductOptionGroup> {
         const input: CreateProductOptionGroupVariables = {
             input: productOptionGroup,
         };
-        return this.baseDataService.mutate<CreateProductOptionGroup, CreateProductOptionGroupVariables>(CREATE_PRODUCT_OPTION_GROUP, input);
+        return this.baseDataService.mutate<CreateProductOptionGroup, CreateProductOptionGroupVariables>(
+            CREATE_PRODUCT_OPTION_GROUP,
+            input,
+        );
     }
 
-    addOptionGroupToProduct(variables: AddOptionGroupToProductVariables): Observable<AddOptionGroupToProduct> {
-        return this.baseDataService.mutate<AddOptionGroupToProduct, AddOptionGroupToProductVariables>(ADD_OPTION_GROUP_TO_PRODUCT, variables);
+    addOptionGroupToProduct(
+        variables: AddOptionGroupToProductVariables,
+    ): Observable<AddOptionGroupToProduct> {
+        return this.baseDataService.mutate<AddOptionGroupToProduct, AddOptionGroupToProductVariables>(
+            ADD_OPTION_GROUP_TO_PRODUCT,
+            variables,
+        );
     }
 }

+ 0 - 2
admin-ui/src/app/data/providers/user-data.service.ts

@@ -5,7 +5,6 @@ import { LoginResponse, UserResponse } from '../types/response';
 import { BaseDataService } from './base-data.service';
 
 export class UserDataService {
-
     constructor(private baseDataService: BaseDataService) {}
 
     checkLoggedIn(): Observable<UserResponse> {
@@ -18,5 +17,4 @@ export class UserDataService {
             password,
         });
     }
-
 }

+ 3 - 2
admin-ui/src/app/data/queries/product-queries.ts

@@ -1,8 +1,9 @@
 import gql from 'graphql-tag';
+
 import { PRODUCT_WITH_VARIANTS_FRAGMENT } from '../fragments/product-fragments';
 
 export const GET_PRODUCT_WITH_VARIANTS = gql`
-    query GetProductWithVariants($id: ID!, $languageCode: LanguageCode){
+    query GetProductWithVariants($id: ID!, $languageCode: LanguageCode) {
         product(languageCode: $languageCode, id: $id) {
             ...ProductWithVariants
         }
@@ -11,7 +12,7 @@ export const GET_PRODUCT_WITH_VARIANTS = gql`
 `;
 
 export const GET_PRODUCT_LIST = gql`
-    query GetProductList($take: Int, $skip: Int, $languageCode: LanguageCode){
+    query GetProductList($take: Int, $skip: Int, $languageCode: LanguageCode) {
         products(languageCode: $languageCode, take: $take, skip: $skip) {
             items {
                 id

+ 415 - 431
admin-ui/src/app/data/types/gql-generated-types.ts

@@ -1,5 +1,3 @@
-
-
 /* tslint:disable */
 // This file was automatically generated and should not be edited.
 
@@ -8,10 +6,9 @@
 // ====================================================
 
 export interface RequestStarted {
-  requestStarted: number;
+    requestStarted: number;
 }
 
-
 /* tslint:disable */
 // This file was automatically generated and should not be edited.
 
@@ -20,10 +17,9 @@ export interface RequestStarted {
 // ====================================================
 
 export interface RequestCompleted {
-  requestCompleted: number;
+    requestCompleted: number;
 }
 
-
 /* tslint:disable */
 // This file was automatically generated and should not be edited.
 
@@ -32,22 +28,21 @@ export interface RequestCompleted {
 // ====================================================
 
 export interface LogIn_logIn {
-  __typename: "UserStatus";
-  username: string;
-  isLoggedIn: boolean;
-  loginTime: string;
+    __typename: 'UserStatus';
+    username: string;
+    isLoggedIn: boolean;
+    loginTime: string;
 }
 
 export interface LogIn {
-  logIn: LogIn_logIn | null;
+    logIn: LogIn_logIn | null;
 }
 
 export interface LogInVariables {
-  username: string;
-  loginTime: string;
+    username: string;
+    loginTime: string;
 }
 
-
 /* tslint:disable */
 // This file was automatically generated and should not be edited.
 
@@ -56,17 +51,16 @@ export interface LogInVariables {
 // ====================================================
 
 export interface LogOut_logOut {
-  __typename: "UserStatus";
-  username: string;
-  isLoggedIn: boolean;
-  loginTime: string;
+    __typename: 'UserStatus';
+    username: string;
+    isLoggedIn: boolean;
+    loginTime: string;
 }
 
 export interface LogOut {
-  logOut: LogOut_logOut | null;
+    logOut: LogOut_logOut | null;
 }
 
-
 /* tslint:disable */
 // This file was automatically generated and should not be edited.
 
@@ -75,14 +69,13 @@ export interface LogOut {
 // ====================================================
 
 export interface SetUiLanguage {
-  setUiLanguage: LanguageCode | null;
+    setUiLanguage: LanguageCode | null;
 }
 
 export interface SetUiLanguageVariables {
-  languageCode: LanguageCode;
+    languageCode: LanguageCode;
 }
 
-
 /* tslint:disable */
 // This file was automatically generated and should not be edited.
 
@@ -91,70 +84,69 @@ export interface SetUiLanguageVariables {
 // ====================================================
 
 export interface UpdateProduct_updateProduct_translations {
-  __typename: "ProductTranslation";
-  languageCode: LanguageCode;
-  name: string;
-  slug: string;
-  description: string | null;
+    __typename: 'ProductTranslation';
+    languageCode: LanguageCode;
+    name: string;
+    slug: string;
+    description: string | null;
 }
 
 export interface UpdateProduct_updateProduct_optionGroups {
-  __typename: "ProductOptionGroup";
-  id: string;
-  languageCode: LanguageCode | null;
-  code: string | null;
-  name: string | null;
+    __typename: 'ProductOptionGroup';
+    id: string;
+    languageCode: LanguageCode | null;
+    code: string | null;
+    name: string | null;
 }
 
 export interface UpdateProduct_updateProduct_variants_options {
-  __typename: "ProductOption";
-  id: string;
-  code: string | null;
-  languageCode: LanguageCode | null;
-  name: string | null;
+    __typename: 'ProductOption';
+    id: string;
+    code: string | null;
+    languageCode: LanguageCode | null;
+    name: string | null;
 }
 
 export interface UpdateProduct_updateProduct_variants_translations {
-  __typename: "ProductVariantTranslation";
-  id: string;
-  languageCode: LanguageCode;
-  name: string;
+    __typename: 'ProductVariantTranslation';
+    id: string;
+    languageCode: LanguageCode;
+    name: string;
 }
 
 export interface UpdateProduct_updateProduct_variants {
-  __typename: "ProductVariant";
-  id: string;
-  languageCode: LanguageCode;
-  name: string | null;
-  price: number | null;
-  sku: string | null;
-  image: string | null;
-  options: UpdateProduct_updateProduct_variants_options[];
-  translations: UpdateProduct_updateProduct_variants_translations[];
+    __typename: 'ProductVariant';
+    id: string;
+    languageCode: LanguageCode;
+    name: string | null;
+    price: number | null;
+    sku: string | null;
+    image: string | null;
+    options: UpdateProduct_updateProduct_variants_options[];
+    translations: UpdateProduct_updateProduct_variants_translations[];
 }
 
 export interface UpdateProduct_updateProduct {
-  __typename: "Product";
-  id: string;
-  languageCode: LanguageCode;
-  name: string | null;
-  slug: string | null;
-  image: string | null;
-  description: string | null;
-  translations: UpdateProduct_updateProduct_translations[];
-  optionGroups: UpdateProduct_updateProduct_optionGroups[];
-  variants: UpdateProduct_updateProduct_variants[];
+    __typename: 'Product';
+    id: string;
+    languageCode: LanguageCode;
+    name: string | null;
+    slug: string | null;
+    image: string | null;
+    description: string | null;
+    translations: UpdateProduct_updateProduct_translations[];
+    optionGroups: UpdateProduct_updateProduct_optionGroups[];
+    variants: UpdateProduct_updateProduct_variants[];
 }
 
 export interface UpdateProduct {
-  updateProduct: UpdateProduct_updateProduct;  // Update an existing Product
+    updateProduct: UpdateProduct_updateProduct; // Update an existing Product
 }
 
 export interface UpdateProductVariables {
-  input: UpdateProductInput;
+    input: UpdateProductInput;
 }
 
-
 /* tslint:disable */
 // This file was automatically generated and should not be edited.
 
@@ -163,42 +155,41 @@ export interface UpdateProductVariables {
 // ====================================================
 
 export interface CreateProductOptionGroup_createProductOptionGroup_translations {
-  __typename: "ProductOptionGroupTranslation";
-  name: string;
+    __typename: 'ProductOptionGroupTranslation';
+    name: string;
 }
 
 export interface CreateProductOptionGroup_createProductOptionGroup_options_translations {
-  __typename: "ProductOptionTranslation";
-  name: string;
+    __typename: 'ProductOptionTranslation';
+    name: string;
 }
 
 export interface CreateProductOptionGroup_createProductOptionGroup_options {
-  __typename: "ProductOption";
-  id: string;
-  languageCode: LanguageCode | null;
-  code: string | null;
-  translations: CreateProductOptionGroup_createProductOptionGroup_options_translations[];
+    __typename: 'ProductOption';
+    id: string;
+    languageCode: LanguageCode | null;
+    code: string | null;
+    translations: CreateProductOptionGroup_createProductOptionGroup_options_translations[];
 }
 
 export interface CreateProductOptionGroup_createProductOptionGroup {
-  __typename: "ProductOptionGroup";
-  id: string;
-  languageCode: LanguageCode | null;
-  code: string | null;
-  name: string | null;
-  translations: (CreateProductOptionGroup_createProductOptionGroup_translations | null)[] | null;
-  options: (CreateProductOptionGroup_createProductOptionGroup_options | null)[] | null;
+    __typename: 'ProductOptionGroup';
+    id: string;
+    languageCode: LanguageCode | null;
+    code: string | null;
+    name: string | null;
+    translations: (CreateProductOptionGroup_createProductOptionGroup_translations | null)[] | null;
+    options: (CreateProductOptionGroup_createProductOptionGroup_options | null)[] | null;
 }
 
 export interface CreateProductOptionGroup {
-  createProductOptionGroup: CreateProductOptionGroup_createProductOptionGroup | null;  // Create a new ProductOptionGroup
+    createProductOptionGroup: CreateProductOptionGroup_createProductOptionGroup | null; // Create a new ProductOptionGroup
 }
 
 export interface CreateProductOptionGroupVariables {
-  input: CreateProductOptionGroupInput;
+    input: CreateProductOptionGroupInput;
 }
 
-
 /* tslint:disable */
 // This file was automatically generated and should not be edited.
 
@@ -207,34 +198,33 @@ export interface CreateProductOptionGroupVariables {
 // ====================================================
 
 export interface AddOptionGroupToProduct_addOptionGroupToProduct_optionGroups_options {
-  __typename: "ProductOption";
-  id: string;
-  code: string | null;
+    __typename: 'ProductOption';
+    id: string;
+    code: string | null;
 }
 
 export interface AddOptionGroupToProduct_addOptionGroupToProduct_optionGroups {
-  __typename: "ProductOptionGroup";
-  id: string;
-  code: string | null;
-  options: (AddOptionGroupToProduct_addOptionGroupToProduct_optionGroups_options | null)[] | null;
+    __typename: 'ProductOptionGroup';
+    id: string;
+    code: string | null;
+    options: (AddOptionGroupToProduct_addOptionGroupToProduct_optionGroups_options | null)[] | null;
 }
 
 export interface AddOptionGroupToProduct_addOptionGroupToProduct {
-  __typename: "Product";
-  id: string;
-  optionGroups: AddOptionGroupToProduct_addOptionGroupToProduct_optionGroups[];
+    __typename: 'Product';
+    id: string;
+    optionGroups: AddOptionGroupToProduct_addOptionGroupToProduct_optionGroups[];
 }
 
 export interface AddOptionGroupToProduct {
-  addOptionGroupToProduct: AddOptionGroupToProduct_addOptionGroupToProduct;  // Add an OptionGroup to a Product
+    addOptionGroupToProduct: AddOptionGroupToProduct_addOptionGroupToProduct; // Add an OptionGroup to a Product
 }
 
 export interface AddOptionGroupToProductVariables {
-  productId: string;
-  optionGroupId: string;
+    productId: string;
+    optionGroupId: string;
 }
 
-
 /* tslint:disable */
 // This file was automatically generated and should not be edited.
 
@@ -243,15 +233,14 @@ export interface AddOptionGroupToProductVariables {
 // ====================================================
 
 export interface GetNetworkStatus_networkStatus {
-  __typename: "NetworkStatus";
-  inFlightRequests: number;
+    __typename: 'NetworkStatus';
+    inFlightRequests: number;
 }
 
 export interface GetNetworkStatus {
-  networkStatus: GetNetworkStatus_networkStatus;
+    networkStatus: GetNetworkStatus_networkStatus;
 }
 
-
 /* tslint:disable */
 // This file was automatically generated and should not be edited.
 
@@ -260,17 +249,16 @@ export interface GetNetworkStatus {
 // ====================================================
 
 export interface GetUserStatus_userStatus {
-  __typename: "UserStatus";
-  username: string;
-  isLoggedIn: boolean;
-  loginTime: string;
+    __typename: 'UserStatus';
+    username: string;
+    isLoggedIn: boolean;
+    loginTime: string;
 }
 
 export interface GetUserStatus {
-  userStatus: GetUserStatus_userStatus;
+    userStatus: GetUserStatus_userStatus;
 }
 
-
 /* tslint:disable */
 // This file was automatically generated and should not be edited.
 
@@ -279,15 +267,14 @@ export interface GetUserStatus {
 // ====================================================
 
 export interface GetUiState_uiState {
-  __typename: "UiState";
-  language: LanguageCode;
+    __typename: 'UiState';
+    language: LanguageCode;
 }
 
 export interface GetUiState {
-  uiState: GetUiState_uiState;
+    uiState: GetUiState_uiState;
 }
 
-
 /* tslint:disable */
 // This file was automatically generated and should not be edited.
 
@@ -296,71 +283,70 @@ export interface GetUiState {
 // ====================================================
 
 export interface GetProductWithVariants_product_translations {
-  __typename: "ProductTranslation";
-  languageCode: LanguageCode;
-  name: string;
-  slug: string;
-  description: string | null;
+    __typename: 'ProductTranslation';
+    languageCode: LanguageCode;
+    name: string;
+    slug: string;
+    description: string | null;
 }
 
 export interface GetProductWithVariants_product_optionGroups {
-  __typename: "ProductOptionGroup";
-  id: string;
-  languageCode: LanguageCode | null;
-  code: string | null;
-  name: string | null;
+    __typename: 'ProductOptionGroup';
+    id: string;
+    languageCode: LanguageCode | null;
+    code: string | null;
+    name: string | null;
 }
 
 export interface GetProductWithVariants_product_variants_options {
-  __typename: "ProductOption";
-  id: string;
-  code: string | null;
-  languageCode: LanguageCode | null;
-  name: string | null;
+    __typename: 'ProductOption';
+    id: string;
+    code: string | null;
+    languageCode: LanguageCode | null;
+    name: string | null;
 }
 
 export interface GetProductWithVariants_product_variants_translations {
-  __typename: "ProductVariantTranslation";
-  id: string;
-  languageCode: LanguageCode;
-  name: string;
+    __typename: 'ProductVariantTranslation';
+    id: string;
+    languageCode: LanguageCode;
+    name: string;
 }
 
 export interface GetProductWithVariants_product_variants {
-  __typename: "ProductVariant";
-  id: string;
-  languageCode: LanguageCode;
-  name: string | null;
-  price: number | null;
-  sku: string | null;
-  image: string | null;
-  options: GetProductWithVariants_product_variants_options[];
-  translations: GetProductWithVariants_product_variants_translations[];
+    __typename: 'ProductVariant';
+    id: string;
+    languageCode: LanguageCode;
+    name: string | null;
+    price: number | null;
+    sku: string | null;
+    image: string | null;
+    options: GetProductWithVariants_product_variants_options[];
+    translations: GetProductWithVariants_product_variants_translations[];
 }
 
 export interface GetProductWithVariants_product {
-  __typename: "Product";
-  id: string;
-  languageCode: LanguageCode;
-  name: string | null;
-  slug: string | null;
-  image: string | null;
-  description: string | null;
-  translations: GetProductWithVariants_product_translations[];
-  optionGroups: GetProductWithVariants_product_optionGroups[];
-  variants: GetProductWithVariants_product_variants[];
+    __typename: 'Product';
+    id: string;
+    languageCode: LanguageCode;
+    name: string | null;
+    slug: string | null;
+    image: string | null;
+    description: string | null;
+    translations: GetProductWithVariants_product_translations[];
+    optionGroups: GetProductWithVariants_product_optionGroups[];
+    variants: GetProductWithVariants_product_variants[];
 }
 
 export interface GetProductWithVariants {
-  product: GetProductWithVariants_product;
+    product: GetProductWithVariants_product;
 }
 
 export interface GetProductWithVariantsVariables {
-  id: string;
-  languageCode?: LanguageCode | null;
+    id: string;
+    languageCode?: LanguageCode | null;
 }
 
-
 /* tslint:disable */
 // This file was automatically generated and should not be edited.
 
@@ -369,31 +355,30 @@ export interface GetProductWithVariantsVariables {
 // ====================================================
 
 export interface GetProductList_products_items {
-  __typename: "Product";
-  id: string;
-  languageCode: LanguageCode;
-  name: string | null;
-  slug: string | null;
-  description: string | null;
+    __typename: 'Product';
+    id: string;
+    languageCode: LanguageCode;
+    name: string | null;
+    slug: string | null;
+    description: string | null;
 }
 
 export interface GetProductList_products {
-  __typename: "ProductList";
-  items: GetProductList_products_items[];
-  totalItems: number;
+    __typename: 'ProductList';
+    items: GetProductList_products_items[];
+    totalItems: number;
 }
 
 export interface GetProductList {
-  products: GetProductList_products;
+    products: GetProductList_products;
 }
 
 export interface GetProductListVariables {
-  take?: number | null;
-  skip?: number | null;
-  languageCode?: LanguageCode | null;
+    take?: number | null;
+    skip?: number | null;
+    languageCode?: LanguageCode | null;
 }
 
-
 /* tslint:disable */
 // This file was automatically generated and should not be edited.
 
@@ -402,62 +387,61 @@ export interface GetProductListVariables {
 // ====================================================
 
 export interface ProductWithVariants_translations {
-  __typename: "ProductTranslation";
-  languageCode: LanguageCode;
-  name: string;
-  slug: string;
-  description: string | null;
+    __typename: 'ProductTranslation';
+    languageCode: LanguageCode;
+    name: string;
+    slug: string;
+    description: string | null;
 }
 
 export interface ProductWithVariants_optionGroups {
-  __typename: "ProductOptionGroup";
-  id: string;
-  languageCode: LanguageCode | null;
-  code: string | null;
-  name: string | null;
+    __typename: 'ProductOptionGroup';
+    id: string;
+    languageCode: LanguageCode | null;
+    code: string | null;
+    name: string | null;
 }
 
 export interface ProductWithVariants_variants_options {
-  __typename: "ProductOption";
-  id: string;
-  code: string | null;
-  languageCode: LanguageCode | null;
-  name: string | null;
+    __typename: 'ProductOption';
+    id: string;
+    code: string | null;
+    languageCode: LanguageCode | null;
+    name: string | null;
 }
 
 export interface ProductWithVariants_variants_translations {
-  __typename: "ProductVariantTranslation";
-  id: string;
-  languageCode: LanguageCode;
-  name: string;
+    __typename: 'ProductVariantTranslation';
+    id: string;
+    languageCode: LanguageCode;
+    name: string;
 }
 
 export interface ProductWithVariants_variants {
-  __typename: "ProductVariant";
-  id: string;
-  languageCode: LanguageCode;
-  name: string | null;
-  price: number | null;
-  sku: string | null;
-  image: string | null;
-  options: ProductWithVariants_variants_options[];
-  translations: ProductWithVariants_variants_translations[];
+    __typename: 'ProductVariant';
+    id: string;
+    languageCode: LanguageCode;
+    name: string | null;
+    price: number | null;
+    sku: string | null;
+    image: string | null;
+    options: ProductWithVariants_variants_options[];
+    translations: ProductWithVariants_variants_translations[];
 }
 
 export interface ProductWithVariants {
-  __typename: "Product";
-  id: string;
-  languageCode: LanguageCode;
-  name: string | null;
-  slug: string | null;
-  image: string | null;
-  description: string | null;
-  translations: ProductWithVariants_translations[];
-  optionGroups: ProductWithVariants_optionGroups[];
-  variants: ProductWithVariants_variants[];
+    __typename: 'Product';
+    id: string;
+    languageCode: LanguageCode;
+    name: string | null;
+    slug: string | null;
+    image: string | null;
+    description: string | null;
+    translations: ProductWithVariants_translations[];
+    optionGroups: ProductWithVariants_optionGroups[];
+    variants: ProductWithVariants_variants[];
 }
 
-
 /* tslint:disable */
 // This file was automatically generated and should not be edited.
 
@@ -466,31 +450,31 @@ export interface ProductWithVariants {
 // ====================================================
 
 export interface ProductOptionGroup_translations {
-  __typename: "ProductOptionGroupTranslation";
-  name: string;
+    __typename: 'ProductOptionGroupTranslation';
+    name: string;
 }
 
 export interface ProductOptionGroup_options_translations {
-  __typename: "ProductOptionTranslation";
-  name: string;
+    __typename: 'ProductOptionTranslation';
+    name: string;
 }
 
 export interface ProductOptionGroup_options {
-  __typename: "ProductOption";
-  id: string;
-  languageCode: LanguageCode | null;
-  code: string | null;
-  translations: ProductOptionGroup_options_translations[];
+    __typename: 'ProductOption';
+    id: string;
+    languageCode: LanguageCode | null;
+    code: string | null;
+    translations: ProductOptionGroup_options_translations[];
 }
 
 export interface ProductOptionGroup {
-  __typename: "ProductOptionGroup";
-  id: string;
-  languageCode: LanguageCode | null;
-  code: string | null;
-  name: string | null;
-  translations: (ProductOptionGroup_translations | null)[] | null;
-  options: (ProductOptionGroup_options | null)[] | null;
+    __typename: 'ProductOptionGroup';
+    id: string;
+    languageCode: LanguageCode | null;
+    code: string | null;
+    name: string | null;
+    translations: (ProductOptionGroup_translations | null)[] | null;
+    options: (ProductOptionGroup_options | null)[] | null;
 }
 
 /* tslint:disable */
@@ -502,229 +486,229 @@ export interface ProductOptionGroup {
 
 // ISO 639-1 language code
 export enum LanguageCode {
-  aa = "aa",
-  ab = "ab",
-  ae = "ae",
-  af = "af",
-  ak = "ak",
-  am = "am",
-  an = "an",
-  ar = "ar",
-  as = "as",
-  av = "av",
-  ay = "ay",
-  az = "az",
-  ba = "ba",
-  be = "be",
-  bg = "bg",
-  bh = "bh",
-  bi = "bi",
-  bm = "bm",
-  bn = "bn",
-  bo = "bo",
-  br = "br",
-  bs = "bs",
-  ca = "ca",
-  ce = "ce",
-  ch = "ch",
-  co = "co",
-  cr = "cr",
-  cs = "cs",
-  cu = "cu",
-  cv = "cv",
-  cy = "cy",
-  da = "da",
-  de = "de",
-  dv = "dv",
-  dz = "dz",
-  ee = "ee",
-  el = "el",
-  en = "en",
-  eo = "eo",
-  es = "es",
-  et = "et",
-  eu = "eu",
-  fa = "fa",
-  ff = "ff",
-  fi = "fi",
-  fj = "fj",
-  fo = "fo",
-  fr = "fr",
-  fy = "fy",
-  ga = "ga",
-  gd = "gd",
-  gl = "gl",
-  gn = "gn",
-  gu = "gu",
-  gv = "gv",
-  ha = "ha",
-  he = "he",
-  hi = "hi",
-  ho = "ho",
-  hr = "hr",
-  ht = "ht",
-  hu = "hu",
-  hy = "hy",
-  hz = "hz",
-  ia = "ia",
-  id = "id",
-  ie = "ie",
-  ig = "ig",
-  ii = "ii",
-  ik = "ik",
-  io = "io",
-  is = "is",
-  it = "it",
-  iu = "iu",
-  ja = "ja",
-  jv = "jv",
-  ka = "ka",
-  kg = "kg",
-  ki = "ki",
-  kj = "kj",
-  kk = "kk",
-  kl = "kl",
-  km = "km",
-  kn = "kn",
-  ko = "ko",
-  kr = "kr",
-  ks = "ks",
-  ku = "ku",
-  kv = "kv",
-  kw = "kw",
-  ky = "ky",
-  la = "la",
-  lb = "lb",
-  lg = "lg",
-  li = "li",
-  ln = "ln",
-  lo = "lo",
-  lt = "lt",
-  lu = "lu",
-  lv = "lv",
-  mg = "mg",
-  mh = "mh",
-  mi = "mi",
-  mk = "mk",
-  ml = "ml",
-  mn = "mn",
-  mr = "mr",
-  ms = "ms",
-  mt = "mt",
-  my = "my",
-  na = "na",
-  nb = "nb",
-  nd = "nd",
-  ne = "ne",
-  ng = "ng",
-  nl = "nl",
-  nn = "nn",
-  no = "no",
-  nr = "nr",
-  nv = "nv",
-  ny = "ny",
-  oc = "oc",
-  oj = "oj",
-  om = "om",
-  or = "or",
-  os = "os",
-  pa = "pa",
-  pi = "pi",
-  pl = "pl",
-  ps = "ps",
-  pt = "pt",
-  qu = "qu",
-  rm = "rm",
-  rn = "rn",
-  ro = "ro",
-  ru = "ru",
-  rw = "rw",
-  sa = "sa",
-  sc = "sc",
-  sd = "sd",
-  se = "se",
-  sg = "sg",
-  si = "si",
-  sk = "sk",
-  sl = "sl",
-  sm = "sm",
-  sn = "sn",
-  so = "so",
-  sq = "sq",
-  sr = "sr",
-  ss = "ss",
-  st = "st",
-  su = "su",
-  sv = "sv",
-  sw = "sw",
-  ta = "ta",
-  te = "te",
-  tg = "tg",
-  th = "th",
-  ti = "ti",
-  tk = "tk",
-  tl = "tl",
-  tn = "tn",
-  to = "to",
-  tr = "tr",
-  ts = "ts",
-  tt = "tt",
-  tw = "tw",
-  ty = "ty",
-  ug = "ug",
-  uk = "uk",
-  ur = "ur",
-  uz = "uz",
-  ve = "ve",
-  vi = "vi",
-  vo = "vo",
-  wa = "wa",
-  wo = "wo",
-  xh = "xh",
-  yi = "yi",
-  yo = "yo",
-  za = "za",
-  zh = "zh",
-  zu = "zu",
-}
-
-// 
+    aa = 'aa',
+    ab = 'ab',
+    ae = 'ae',
+    af = 'af',
+    ak = 'ak',
+    am = 'am',
+    an = 'an',
+    ar = 'ar',
+    as = 'as',
+    av = 'av',
+    ay = 'ay',
+    az = 'az',
+    ba = 'ba',
+    be = 'be',
+    bg = 'bg',
+    bh = 'bh',
+    bi = 'bi',
+    bm = 'bm',
+    bn = 'bn',
+    bo = 'bo',
+    br = 'br',
+    bs = 'bs',
+    ca = 'ca',
+    ce = 'ce',
+    ch = 'ch',
+    co = 'co',
+    cr = 'cr',
+    cs = 'cs',
+    cu = 'cu',
+    cv = 'cv',
+    cy = 'cy',
+    da = 'da',
+    de = 'de',
+    dv = 'dv',
+    dz = 'dz',
+    ee = 'ee',
+    el = 'el',
+    en = 'en',
+    eo = 'eo',
+    es = 'es',
+    et = 'et',
+    eu = 'eu',
+    fa = 'fa',
+    ff = 'ff',
+    fi = 'fi',
+    fj = 'fj',
+    fo = 'fo',
+    fr = 'fr',
+    fy = 'fy',
+    ga = 'ga',
+    gd = 'gd',
+    gl = 'gl',
+    gn = 'gn',
+    gu = 'gu',
+    gv = 'gv',
+    ha = 'ha',
+    he = 'he',
+    hi = 'hi',
+    ho = 'ho',
+    hr = 'hr',
+    ht = 'ht',
+    hu = 'hu',
+    hy = 'hy',
+    hz = 'hz',
+    ia = 'ia',
+    id = 'id',
+    ie = 'ie',
+    ig = 'ig',
+    ii = 'ii',
+    ik = 'ik',
+    io = 'io',
+    is = 'is',
+    it = 'it',
+    iu = 'iu',
+    ja = 'ja',
+    jv = 'jv',
+    ka = 'ka',
+    kg = 'kg',
+    ki = 'ki',
+    kj = 'kj',
+    kk = 'kk',
+    kl = 'kl',
+    km = 'km',
+    kn = 'kn',
+    ko = 'ko',
+    kr = 'kr',
+    ks = 'ks',
+    ku = 'ku',
+    kv = 'kv',
+    kw = 'kw',
+    ky = 'ky',
+    la = 'la',
+    lb = 'lb',
+    lg = 'lg',
+    li = 'li',
+    ln = 'ln',
+    lo = 'lo',
+    lt = 'lt',
+    lu = 'lu',
+    lv = 'lv',
+    mg = 'mg',
+    mh = 'mh',
+    mi = 'mi',
+    mk = 'mk',
+    ml = 'ml',
+    mn = 'mn',
+    mr = 'mr',
+    ms = 'ms',
+    mt = 'mt',
+    my = 'my',
+    na = 'na',
+    nb = 'nb',
+    nd = 'nd',
+    ne = 'ne',
+    ng = 'ng',
+    nl = 'nl',
+    nn = 'nn',
+    no = 'no',
+    nr = 'nr',
+    nv = 'nv',
+    ny = 'ny',
+    oc = 'oc',
+    oj = 'oj',
+    om = 'om',
+    or = 'or',
+    os = 'os',
+    pa = 'pa',
+    pi = 'pi',
+    pl = 'pl',
+    ps = 'ps',
+    pt = 'pt',
+    qu = 'qu',
+    rm = 'rm',
+    rn = 'rn',
+    ro = 'ro',
+    ru = 'ru',
+    rw = 'rw',
+    sa = 'sa',
+    sc = 'sc',
+    sd = 'sd',
+    se = 'se',
+    sg = 'sg',
+    si = 'si',
+    sk = 'sk',
+    sl = 'sl',
+    sm = 'sm',
+    sn = 'sn',
+    so = 'so',
+    sq = 'sq',
+    sr = 'sr',
+    ss = 'ss',
+    st = 'st',
+    su = 'su',
+    sv = 'sv',
+    sw = 'sw',
+    ta = 'ta',
+    te = 'te',
+    tg = 'tg',
+    th = 'th',
+    ti = 'ti',
+    tk = 'tk',
+    tl = 'tl',
+    tn = 'tn',
+    to = 'to',
+    tr = 'tr',
+    ts = 'ts',
+    tt = 'tt',
+    tw = 'tw',
+    ty = 'ty',
+    ug = 'ug',
+    uk = 'uk',
+    ur = 'ur',
+    uz = 'uz',
+    ve = 've',
+    vi = 'vi',
+    vo = 'vo',
+    wa = 'wa',
+    wo = 'wo',
+    xh = 'xh',
+    yi = 'yi',
+    yo = 'yo',
+    za = 'za',
+    zh = 'zh',
+    zu = 'zu',
+}
+
+//
 export interface UpdateProductInput {
-  id: string;
-  image?: string | null;
-  translations: (ProductTranslationInput | null)[];
-  optionGroupCodes?: (string | null)[] | null;
+    id: string;
+    image?: string | null;
+    translations: (ProductTranslationInput | null)[];
+    optionGroupCodes?: (string | null)[] | null;
 }
 
-// 
+//
 export interface ProductTranslationInput {
-  id?: string | null;
-  languageCode: LanguageCode;
-  name: string;
-  slug?: string | null;
-  description?: string | null;
+    id?: string | null;
+    languageCode: LanguageCode;
+    name: string;
+    slug?: string | null;
+    description?: string | null;
 }
 
-// 
+//
 export interface CreateProductOptionGroupInput {
-  code: string;
-  translations: (ProductOptionGroupTranslationInput | null)[];
-  options?: (CreateProductOptionInput | null)[] | null;
+    code: string;
+    translations: (ProductOptionGroupTranslationInput | null)[];
+    options?: (CreateProductOptionInput | null)[] | null;
 }
 
-// 
+//
 export interface ProductOptionGroupTranslationInput {
-  id?: string | null;
-  languageCode: LanguageCode;
-  name: string;
+    id?: string | null;
+    languageCode: LanguageCode;
+    name: string;
 }
 
-// 
+//
 export interface CreateProductOptionInput {
-  code: string;
-  translations: (ProductOptionGroupTranslationInput | null)[];
+    code: string;
+    translations: (ProductOptionGroupTranslationInput | null)[];
 }
 
 //==============================================================
 // END Enums and Input Objects
-//==============================================================
+//==============================================================

+ 3 - 10
admin-ui/src/app/data/types/query-result.ts

@@ -23,9 +23,7 @@ export class QueryResult<T, V = Record<string, any>> {
      * Returns an Observable which emits until unsubscribed.
      */
     get stream$(): Observable<T> {
-        return this.queryRef.valueChanges.pipe(
-            map(result => result.data),
-        );
+        return this.queryRef.valueChanges.pipe(map(result => result.data));
     }
 
     get ref(): QueryRef<T, V> {
@@ -36,18 +34,13 @@ export class QueryResult<T, V = Record<string, any>> {
      * Returns a single-result Observable after applying the map function.
      */
     mapSingle<R>(mapFn: (item: T) => R): Observable<R> {
-        return this.single$.pipe(
-            map(mapFn),
-        );
+        return this.single$.pipe(map(mapFn));
     }
 
     /**
      * Returns a multiple-result Observable after applying the map function.
      */
     mapStream<R>(mapFn: (item: T) => R): Observable<R> {
-        return this.stream$.pipe(
-            map(mapFn),
-        );
+        return this.stream$.pipe(map(mapFn));
     }
-
 }

+ 17 - 19
admin-ui/src/app/login/components/login/login.component.ts

@@ -1,6 +1,7 @@
 import { HttpErrorResponse } from '@angular/common/http';
 import { Component } from '@angular/core';
 import { Router } from '@angular/router';
+
 import { API_URL } from '../../../app.config';
 import { AuthService } from '../../../core/providers/auth/auth.service';
 
@@ -10,30 +11,27 @@ import { AuthService } from '../../../core/providers/auth/auth.service';
     styleUrls: ['./login.component.scss'],
 })
 export class LoginComponent {
-
     username = '';
     password = '';
     lastError = '';
 
-    constructor(private authService: AuthService,
-                private router: Router) { }
+    constructor(private authService: AuthService, private router: Router) {}
 
     logIn(): void {
-        this.authService.logIn(this.username, this.password)
-            .subscribe(
-                () => this.router.navigate(['/']),
-                (err: HttpErrorResponse) => {
-                    switch (err.status) {
-                        case 401:
-                            this.lastError = 'Invalid username or password';
-                            break;
-                        case 0:
-                            this.lastError = `Could not connect to the Vendure server at ${API_URL}`;
-                            break;
-                        default:
-                            this.lastError = err.message;
-                    }
-                });
+        this.authService.logIn(this.username, this.password).subscribe(
+            () => this.router.navigate(['/']),
+            (err: HttpErrorResponse) => {
+                switch (err.status) {
+                    case 401:
+                        this.lastError = 'Invalid username or password';
+                        break;
+                    case 0:
+                        this.lastError = `Could not connect to the Vendure server at ${API_URL}`;
+                        break;
+                    default:
+                        this.lastError = err.message;
+                }
+            },
+        );
     }
-
 }

+ 2 - 6
admin-ui/src/app/login/login.module.ts

@@ -7,13 +7,9 @@ import { LoginComponent } from './components/login/login.component';
 import { loginRoutes } from './login.routes';
 
 @NgModule({
-    imports: [
-        SharedModule,
-        RouterModule.forChild(loginRoutes),
-    ],
+    imports: [SharedModule, RouterModule.forChild(loginRoutes)],
     exports: [],
     declarations: [LoginComponent],
     providers: [],
 })
-export class LoginModule {
-}
+export class LoginModule {}

+ 2 - 2
admin-ui/src/app/login/login.routes.ts

@@ -1,6 +1,6 @@
-import {Routes} from '@angular/router';
+import { Routes } from '@angular/router';
 
-import {LoginComponent} from './components/login/login.component';
+import { LoginComponent } from './components/login/login.component';
 
 export const loginRoutes: Routes = [
     {

+ 4 - 3
admin-ui/src/app/shared/components/data-table/data-table.component.spec.ts

@@ -1,6 +1,8 @@
 import { async, ComponentFixture, TestBed } from '@angular/core/testing';
 import { NgxPaginationModule } from 'ngx-pagination';
+
 import { PaginationControlsComponent } from '../pagination-controls/pagination-controls.component';
+
 import { DataTableColumnComponent } from './data-table-column.component';
 import { DataTableComponent } from './data-table.component';
 
@@ -11,9 +13,8 @@ describe('DataTableComponent', () => {
     beforeEach(async(() => {
         TestBed.configureTestingModule({
             imports: [NgxPaginationModule],
-            declarations: [ DataTableComponent, DataTableColumnComponent, PaginationControlsComponent ],
-        })
-            .compileComponents();
+            declarations: [DataTableComponent, DataTableColumnComponent, PaginationControlsComponent],
+        }).compileComponents();
     }));
 
     beforeEach(() => {

+ 1 - 1
admin-ui/src/app/shared/components/data-table/data-table.component.ts

@@ -10,6 +10,7 @@ import {
     TemplateRef,
 } from '@angular/core';
 import { PaginationService } from 'ngx-pagination';
+
 import { DataTableColumnComponent } from './data-table-column.component';
 
 @Component({
@@ -20,7 +21,6 @@ import { DataTableColumnComponent } from './data-table-column.component';
     providers: [PaginationService],
 })
 export class DataTableComponent {
-
     @Input() items: any[];
     @Input() itemsPerPage: number;
     @Input() currentPage: number;

+ 10 - 2
admin-ui/src/app/shared/components/form-field/form-field-control.directive.ts

@@ -1,7 +1,15 @@
 import { Directive, ElementRef, Optional, Self } from '@angular/core';
-import { FormControl, FormControlDirective, FormControlName, FormGroup, FormGroupDirective, NgForm } from '@angular/forms';
+import {
+    FormControl,
+    FormControlDirective,
+    FormControlName,
+    FormGroup,
+    FormGroupDirective,
+    NgForm,
+} from '@angular/forms';
 
-@Directive({selector: 'input, textarea, select'})
+// tslint:disable:directive-selector
+@Directive({ selector: 'input, textarea, select' })
 export class FormFieldControlDirective {
     formControl: FormControl;
     constructor(@Optional() private formControlName: FormControlName) {}

+ 1 - 0
admin-ui/src/app/shared/components/form-field/form-field.component.ts

@@ -1,4 +1,5 @@
 import { AfterContentInit, ChangeDetectionStrategy, Component, ContentChild, Input } from '@angular/core';
+
 import { FormFieldControlDirective } from './form-field-control.directive';
 
 /**

+ 4 - 3
admin-ui/src/app/shared/components/modal-dialog/dialog-buttons.directive.ts

@@ -1,11 +1,12 @@
-import { Directive, TemplateRef } from '@angular/core';
+import { Directive, OnInit, TemplateRef } from '@angular/core';
+
 import { ModalDialogComponent } from './modal-dialog.component';
 
 /**
  * A helper directive used to correctly embed the modal buttons in the {@link ModalDialogComponent}.
  */
-@Directive({selector: '[vdrDialogButtons]'})
-export class DialogButtonsDirective {
+@Directive({ selector: '[vdrDialogButtons]' })
+export class DialogButtonsDirective implements OnInit {
     constructor(private modal: ModalDialogComponent<any>, private templateRef: TemplateRef<any>) {}
 
     ngOnInit() {

+ 14 - 2
admin-ui/src/app/shared/components/modal-dialog/dialog-component-outlet.component.ts

@@ -1,4 +1,13 @@
-import { Component, ComponentFactoryResolver, EventEmitter, Input, OnInit, Output, Type, ViewContainerRef } from '@angular/core';
+import {
+    Component,
+    ComponentFactoryResolver,
+    EventEmitter,
+    Input,
+    OnInit,
+    Output,
+    Type,
+    ViewContainerRef,
+} from '@angular/core';
 
 /**
  * A helper component used to embed a component instance into the {@link ModalDialogComponent}
@@ -11,7 +20,10 @@ export class DialogComponentOutletComponent implements OnInit {
     @Input() component: Type<any>;
     @Output() create = new EventEmitter<any>();
 
-    constructor(private viewContainerRef: ViewContainerRef, private componentFactoryResolver: ComponentFactoryResolver) {}
+    constructor(
+        private viewContainerRef: ViewContainerRef,
+        private componentFactoryResolver: ComponentFactoryResolver,
+    ) {}
 
     ngOnInit() {
         const factory = this.componentFactoryResolver.resolveComponentFactory(this.component);

+ 4 - 3
admin-ui/src/app/shared/components/modal-dialog/dialog-title.directive.ts

@@ -1,11 +1,12 @@
-import { Directive, TemplateRef } from '@angular/core';
+import { Directive, OnInit, TemplateRef } from '@angular/core';
+
 import { ModalDialogComponent } from './modal-dialog.component';
 
 /**
  * A helper directive used to correctly embed the modal title in the {@link ModalDialogComponent}.
  */
-@Directive({selector: '[vdrDialogTitle]'})
-export class DialogTitleDirective {
+@Directive({ selector: '[vdrDialogTitle]' })
+export class DialogTitleDirective implements OnInit {
     constructor(private modal: ModalDialogComponent<any>, private templateRef: TemplateRef<any>) {}
 
     ngOnInit() {

+ 15 - 4
admin-ui/src/app/shared/components/modal-dialog/modal-dialog.component.ts

@@ -1,6 +1,17 @@
-import { Component, ContentChild, ContentChildren, QueryList, TemplateRef, Type, ViewChild, ViewChildren } from '@angular/core';
+import {
+    Component,
+    ContentChild,
+    ContentChildren,
+    QueryList,
+    TemplateRef,
+    Type,
+    ViewChild,
+    ViewChildren,
+} from '@angular/core';
 import { Observable, Subject } from 'rxjs';
+
 import { Dialog, ModalOptions } from '../../providers/modal/modal.service';
+
 import { DialogButtonsDirective } from './dialog-buttons.directive';
 
 /**
@@ -8,9 +19,9 @@ import { DialogButtonsDirective } from './dialog-buttons.directive';
  * directly in templates. See {@link ModalService.fromComponent} method for more detail.
  */
 @Component({
-  selector: 'vdr-modal-dialog',
-  templateUrl: './modal-dialog.component.html',
-  styleUrls: ['./modal-dialog.component.scss'],
+    selector: 'vdr-modal-dialog',
+    templateUrl: './modal-dialog.component.html',
+    styleUrls: ['./modal-dialog.component.scss'],
 })
 export class ModalDialogComponent<T extends Dialog> {
     childComponentType: Type<T>;

+ 3 - 3
admin-ui/src/app/shared/components/table-row-action/table-row-action.component.ts

@@ -4,9 +4,9 @@ import { Component, Input, OnInit } from '@angular/core';
  * A button link to be used as actions in rows of a table.
  */
 @Component({
-  selector: 'vdr-table-row-action',
-  templateUrl: './table-row-action.component.html',
-  styleUrls: ['./table-row-action.component.scss'],
+    selector: 'vdr-table-row-action',
+    templateUrl: './table-row-action.component.html',
+    styleUrls: ['./table-row-action.component.scss'],
 })
 export class TableRowActionComponent {
     @Input() linkTo: any[];

+ 5 - 3
admin-ui/src/app/shared/providers/modal/modal.service.ts

@@ -1,6 +1,7 @@
 import { ComponentFactoryResolver, Injectable, ViewContainerRef } from '@angular/core';
 import { Type } from '@angular/core/src/type';
 import { Observable, of } from 'rxjs';
+
 import { OverlayHostService } from '../../../core/providers/overlay-host/overlay-host.service';
 import { ModalDialogComponent } from '../../components/modal-dialog/modal-dialog.component';
 
@@ -40,11 +41,12 @@ export interface ModalOptions<T> {
  */
 @Injectable()
 export class ModalService {
-
     hostView: ViewContainerRef;
 
-    constructor(private componentFactoryResolver: ComponentFactoryResolver,
-                overlayHostService: OverlayHostService) {
+    constructor(
+        private componentFactoryResolver: ComponentFactoryResolver,
+        overlayHostService: OverlayHostService,
+    ) {
         overlayHostService.getHostView().then(view => {
             this.hostView = view;
         });

+ 2 - 3
admin-ui/src/app/shared/shared.module.ts

@@ -5,6 +5,7 @@ import { RouterModule } from '@angular/router';
 import { ClarityModule } from '@clr/angular';
 import { TranslateModule } from '@ngx-translate/core';
 import { NgxPaginationModule } from 'ngx-pagination';
+
 import { DataTableColumnComponent } from './components/data-table/data-table-column.component';
 import { DataTableComponent } from './components/data-table/data-table.component';
 import { FormFieldControlDirective } from './components/form-field/form-field-control.directive';
@@ -55,6 +56,4 @@ const DECLARATIONS = [
     ],
     entryComponents: [ModalDialogComponent],
 })
-export class SharedModule {
-
-}
+export class SharedModule {}

+ 1 - 1
admin-ui/src/environments/environment.prod.ts

@@ -1,3 +1,3 @@
 export const environment = {
-  production: true,
+    production: true,
 };

+ 1 - 1
admin-ui/src/environments/environment.ts

@@ -3,7 +3,7 @@
 // The list of file replacements can be found in `angular.json`.
 
 export const environment = {
-  production: false,
+    production: false,
 };
 
 /*

+ 7 - 6
admin-ui/src/main.ts

@@ -5,11 +5,12 @@ import { AppModule } from './app/app.module';
 import { environment } from './environments/environment';
 
 if (environment.production) {
-  enableProdMode();
+    enableProdMode();
 }
 
-platformBrowserDynamic().bootstrapModule(AppModule)
-  .catch(err => {
-      // tslint:disable:no-console
-      console.log(err);
-  });
+platformBrowserDynamic()
+    .bootstrapModule(AppModule)
+    .catch(err => {
+        // tslint:disable:no-console
+        console.log(err);
+    });

+ 5 - 5
admin-ui/src/polyfills.ts

@@ -56,11 +56,11 @@ import 'core-js/es7/reflect';
  * user can disable parts of macroTask/DomEvents patch by setting following flags
  */
 
- // (window as any).__Zone_disable_requestAnimationFrame = true; // disable patch requestAnimationFrame
- // (window as any).__Zone_disable_on_property = true; // disable patch onProperty such as onclick
- // (window as any).__zone_symbol__BLACK_LISTED_EVENTS = ['scroll', 'mousemove']; // disable patch specified eventNames
+// (window as any).__Zone_disable_requestAnimationFrame = true; // disable patch requestAnimationFrame
+// (window as any).__Zone_disable_on_property = true; // disable patch onProperty such as onclick
+// (window as any).__zone_symbol__BLACK_LISTED_EVENTS = ['scroll', 'mousemove']; // disable patch specified eventNames
 
- /*
+/*
  * in IE/Edge developer tools, the addEventListener will also be wrapped by zone.js
  * with the following flag, it will bypass `zone.js` patch for IE/Edge
  */
@@ -69,7 +69,7 @@ import 'core-js/es7/reflect';
 /***************************************************************************************************
  * Zone JS is required by default for Angular itself.
  */
-import 'zone.js/dist/zone';  // Included with Angular CLI.
+import 'zone.js/dist/zone'; // Included with Angular CLI.
 
 /***************************************************************************************************
  * APPLICATION IMPORTS

+ 3 - 6
admin-ui/src/test.ts

@@ -3,17 +3,14 @@
 import 'zone.js/dist/zone-testing';
 import { getTestBed } from '@angular/core/testing';
 import {
-  BrowserDynamicTestingModule,
-  platformBrowserDynamicTesting,
+    BrowserDynamicTestingModule,
+    platformBrowserDynamicTesting,
 } from '@angular/platform-browser-dynamic/testing';
 
 declare const require: any;
 
 // First, initialize the Angular testing environment.
-getTestBed().initTestEnvironment(
-  BrowserDynamicTestingModule,
-  platformBrowserDynamicTesting(),
-);
+getTestBed().initTestEnvironment(BrowserDynamicTestingModule, platformBrowserDynamicTesting());
 // Then we find all the tests.
 const context = require.context('./', true, /\.spec\.ts$/);
 // And load the modules.

+ 1 - 0
server/dev-config.ts

@@ -1,4 +1,5 @@
 import { API_PATH, API_PORT } from '../shared/shared-constants';
+
 import { VendureConfig } from './src/config/vendure-config';
 
 /**

+ 1 - 0
server/e2e/app.e2e-spec.ts

@@ -1,6 +1,7 @@
 import { INestApplication } from '@nestjs/common';
 import { Test } from '@nestjs/testing';
 import request from 'supertest';
+
 import { AppModule } from '../src/app.module';
 
 describe('AppController (e2e)', () => {

+ 12 - 3
server/mock-data/mock-data-client.service.ts

@@ -1,5 +1,6 @@
 import * as faker from 'faker/locale/en_GB';
 import { request } from 'graphql-request';
+
 import { PasswordService } from '../src/auth/password.service';
 import { VendureConfig } from '../src/config/vendure-config';
 import { CreateAddressDto } from '../src/entity/address/address.dto';
@@ -36,11 +37,17 @@ export class MockDataClientService {
                 options: [
                     {
                         code: 'small',
-                        translations: [{ languageCode: 'en', name: 'Small' }, { languageCode: 'de', name: 'Klein' }],
+                        translations: [
+                            { languageCode: 'en', name: 'Small' },
+                            { languageCode: 'de', name: 'Klein' },
+                        ],
                     },
                     {
                         code: 'large',
-                        translations: [{ languageCode: 'en', name: 'Large' }, { languageCode: 'de', name: 'Groß' }],
+                        translations: [
+                            { languageCode: 'en', name: 'Large' },
+                            { languageCode: 'de', name: 'Groß' },
+                        ],
                     },
                 ],
             } as CreateProductOptionGroupDto,
@@ -149,7 +156,9 @@ export class MockDataClientService {
                 input: {
                     image: faker.image.imageUrl(),
                     optionGroupCodes: ['size'],
-                    translations: languageCodes.map(code => this.makeProductTranslation(code, name, slug, description)),
+                    translations: languageCodes.map(code =>
+                        this.makeProductTranslation(code, name, slug, description),
+                    ),
                     variants: [
                         this.makeProductVariant(`${name} Variant 1`, languageCodes),
                         this.makeProductVariant(`${name} Variant 2`, languageCodes),

+ 1 - 0
server/mock-data/populate.ts

@@ -1,4 +1,5 @@
 import { devConfig } from '../dev-config';
+
 import { clearAllTables } from './clear-all-tables';
 import { MockDataClientService } from './mock-data-client.service';
 

+ 1 - 0
server/src/api/administrator/administrator.resolver.ts

@@ -1,4 +1,5 @@
 import { Mutation, Query, Resolver } from '@nestjs/graphql';
+
 import { Administrator } from '../../entity/administrator/administrator.entity';
 import { AdministratorService } from '../../service/administrator.service';
 

+ 2 - 0
server/src/api/auth/auth.controller.ts

@@ -1,8 +1,10 @@
 import { Body, Controller, Get, Post, Req } from '@nestjs/common';
+
 import { AuthService } from '../../auth/auth.service';
 import { Role } from '../../auth/role';
 import { RolesGuard } from '../../auth/roles-guard';
 import { User } from '../../entity/user/user.entity';
+
 import { LoginDto } from './login.dto';
 
 @Controller('auth')

+ 1 - 0
server/src/api/customer/customer.controller.ts

@@ -1,4 +1,5 @@
 import { Controller, Get, Param } from '@nestjs/common';
+
 import { PaginatedList } from '../../../../shared/shared-types';
 import { Customer } from '../../entity/customer/customer.entity';
 import { CustomerService } from '../../service/customer.service';

+ 11 - 3
server/src/api/customer/customer.resolver.ts

@@ -1,4 +1,5 @@
 import { Mutation, Query, ResolveProperty, Resolver } from '@nestjs/graphql';
+
 import { PaginatedList } from '../../../../shared/shared-types';
 import { Address } from '../../entity/address/address.entity';
 import { CreateCustomerDto } from '../../entity/customer/customer.dto';
@@ -12,7 +13,9 @@ export class CustomerResolver {
 
     @Query('customers')
     async customers(obj, args): Promise<PaginatedList<Customer>> {
-        return this.customerService.findAll(args.take, args.skip).then(list => this.idCodecService.encode(list));
+        return this.customerService
+            .findAll(args.take, args.skip)
+            .then(list => this.idCodecService.encode(list));
     }
 
     @Query('customer')
@@ -24,7 +27,9 @@ export class CustomerResolver {
 
     @ResolveProperty('addresses')
     async addresses(customer: Customer): Promise<Address[]> {
-        const address = await this.customerService.findAddressesByCustomerId(this.idCodecService.decode(customer).id);
+        const address = await this.customerService.findAddressesByCustomerId(
+            this.idCodecService.decode(customer).id,
+        );
         return this.idCodecService.encode(address);
     }
 
@@ -38,7 +43,10 @@ export class CustomerResolver {
     @Mutation()
     async createCustomerAddress(_, args): Promise<Address> {
         const { customerId, input } = args;
-        const address = await this.customerService.createAddress(this.idCodecService.decode(customerId), input);
+        const address = await this.customerService.createAddress(
+            this.idCodecService.decode(customerId),
+            input,
+        );
         return this.idCodecService.encode(address);
     }
 }

+ 1 - 0
server/src/api/product-option/product-option.resolver.ts

@@ -1,4 +1,5 @@
 import { Mutation, Query, Resolver } from '@nestjs/graphql';
+
 import { ProductOptionGroup } from '../../entity/product-option-group/product-option-group.entity';
 import { Product } from '../../entity/product/product.entity';
 import { ProductOptionGroupService } from '../../service/product-option-group.service';

+ 1 - 0
server/src/api/product/product.resolver.ts

@@ -1,4 +1,5 @@
 import { Mutation, Query, Resolver } from '@nestjs/graphql';
+
 import { PaginatedList } from '../../../../shared/shared-types';
 import { Product } from '../../entity/product/product.entity';
 import { IdCodecService } from '../../service/id-codec.service';

+ 2 - 1
server/src/app.module.ts

@@ -2,6 +2,7 @@ import { MiddlewareConsumer, Module, NestModule } from '@nestjs/common';
 import { GraphQLFactory, GraphQLModule } from '@nestjs/graphql';
 import { TypeOrmModule } from '@nestjs/typeorm';
 import { graphiqlExpress, graphqlExpress } from 'apollo-server-express';
+
 import { AdministratorResolver } from './api/administrator/administrator.resolver';
 import { AuthController } from './api/auth/auth.controller';
 import { CustomerController } from './api/customer/customer.controller';
@@ -74,7 +75,7 @@ export class AppModule implements NestModule {
                     context: req,
                     formatError: this.i18nService.translateError(req),
                 })),
-            ])
+            ] as any)
             .forRoutes(this.configService.apiPath);
     }
 

+ 2 - 0
server/src/auth/auth.service.ts

@@ -2,8 +2,10 @@ import { Injectable, UnauthorizedException } from '@nestjs/common';
 import { InjectConnection } from '@nestjs/typeorm';
 import * as jwt from 'jsonwebtoken';
 import { Connection } from 'typeorm';
+
 import { User } from '../entity/user/user.entity';
 import { ConfigService } from '../service/config.service';
+
 import { JwtPayload } from './auth-types';
 import { PasswordService } from './password.service';
 import { Role } from './role';

+ 2 - 0
server/src/auth/jwt.strategy.ts

@@ -1,7 +1,9 @@
 import { Injectable, UnauthorizedException } from '@nestjs/common';
 import { PassportStrategy } from '@nestjs/passport';
 import { ExtractJwt, Strategy } from 'passport-jwt';
+
 import { ConfigService } from '../service/config.service';
+
 import { JwtPayload } from './auth-types';
 import { AuthService } from './auth.service';
 

+ 4 - 1
server/src/auth/roles-guard.ts

@@ -1,7 +1,9 @@
 import { CanActivate, ExecutionContext, UseGuards } from '@nestjs/common';
 import { AuthGuard } from '@nestjs/passport';
 import { ExtractJwt, Strategy } from 'passport-jwt';
+
 import { User } from '../entity/user/user.entity';
+
 import { Role } from './role';
 
 /**
@@ -18,7 +20,8 @@ import { Role } from './role';
  * ```
  */
 export function RolesGuard(roles: Role[]) {
-    const guards: CanActivate[] = [AuthGuard('jwt')];
+    // tslint:disable-next-line:ban-types
+    const guards: Array<CanActivate | Function> = [AuthGuard('jwt')];
 
     if (roles.length && !authenticatedOnly(roles)) {
         guards.push(forRoles(roles));

+ 2 - 1
server/src/bootstrap.ts

@@ -1,4 +1,5 @@
 import { NestFactory } from '@nestjs/core';
+
 import { getConfig, setConfig, VendureConfig } from './config/vendure-config';
 
 /**
@@ -16,7 +17,7 @@ export async function bootstrap(userConfig?: Partial<VendureConfig>) {
     const entities = await import('./entity/entities');
     setConfig({
         dbConnectionOptions: {
-            entities: entities.coreEntities,
+            entities: entities.coreEntities as any,
         },
     });
 

+ 1 - 0
server/src/config/merge-config.spec.ts

@@ -1,4 +1,5 @@
 import { LanguageCode } from '../locale/language-code';
+
 import { mergeConfig } from './merge-config';
 import { VendureConfig } from './vendure-config';
 

+ 1 - 0
server/src/config/merge-config.ts

@@ -1,4 +1,5 @@
 import { DeepPartial } from '../../../shared/shared-types';
+
 import { VendureConfig } from './vendure-config';
 
 /**

+ 2 - 0
server/src/config/vendure-config.ts

@@ -1,8 +1,10 @@
 import { CorsOptions } from '@nestjs/common/interfaces/external/cors-options.interface';
 import { ConnectionOptions } from 'typeorm';
+
 import { DeepPartial } from '../../../shared/shared-types';
 import { ReadOnlyRequired } from '../common/common-types';
 import { LanguageCode } from '../locale/language-code';
+
 import { AutoIncrementIdStrategy } from './auto-increment-id-strategy';
 import { EntityIdStrategy } from './entity-id-strategy';
 import { mergeConfig } from './merge-config';

+ 1 - 0
server/src/entity/address/address.entity.ts

@@ -1,4 +1,5 @@
 import { Column, Entity, ManyToOne } from 'typeorm';
+
 import { DeepPartial } from '../../../../shared/shared-types';
 import { VendureEntity } from '../base/base.entity';
 import { Customer } from '../customer/customer.entity';

+ 1 - 0
server/src/entity/administrator/administrator.entity.ts

@@ -1,4 +1,5 @@
 import { Column, Entity, JoinColumn, OneToOne } from 'typeorm';
+
 import { DeepPartial } from '../../../../shared/shared-types';
 import { VendureEntity } from '../base/base.entity';
 import { User } from '../user/user.entity';

+ 1 - 0
server/src/entity/base/base.entity.ts

@@ -1,4 +1,5 @@
 import { CreateDateColumn, PrimaryGeneratedColumn, UpdateDateColumn } from 'typeorm';
+
 import { DeepPartial, ID } from '../../../../shared/shared-types';
 import { getConfig } from '../../config/vendure-config';
 

+ 1 - 0
server/src/entity/customer/customer.entity.ts

@@ -1,4 +1,5 @@
 import { Column, Entity, JoinColumn, OneToMany, OneToOne } from 'typeorm';
+
 import { DeepPartial } from '../../../../shared/shared-types';
 import { Address } from '../address/address.entity';
 import { VendureEntity } from '../base/base.entity';

+ 2 - 0
server/src/entity/product-option-group/product-option-group-translation.entity.ts

@@ -1,8 +1,10 @@
 import { Column, Entity, ManyToOne } from 'typeorm';
+
 import { DeepPartial } from '../../../../shared/shared-types';
 import { LanguageCode } from '../../locale/language-code';
 import { Translation } from '../../locale/locale-types';
 import { VendureEntity } from '../base/base.entity';
+
 import { ProductOptionGroup } from './product-option-group.entity';
 
 @Entity()

+ 1 - 0
server/src/entity/product-option-group/product-option-group.dto.ts

@@ -1,5 +1,6 @@
 import { TranslatedInput } from '../../locale/locale-types';
 import { CreateProductOptionDto } from '../product-option/product-option.dto';
+
 import { ProductOptionGroup } from './product-option-group.entity';
 
 export interface CreateProductOptionGroupDto extends TranslatedInput<ProductOptionGroup> {

+ 2 - 0
server/src/entity/product-option-group/product-option-group.entity.ts

@@ -1,8 +1,10 @@
 import { Column, Entity, OneToMany } from 'typeorm';
+
 import { DeepPartial } from '../../../../shared/shared-types';
 import { LocaleString, Translatable, Translation } from '../../locale/locale-types';
 import { VendureEntity } from '../base/base.entity';
 import { ProductOption } from '../product-option/product-option.entity';
+
 import { ProductOptionGroupTranslation } from './product-option-group-translation.entity';
 
 @Entity()

+ 2 - 0
server/src/entity/product-option/product-option-translation.entity.ts

@@ -1,8 +1,10 @@
 import { Column, Entity, ManyToOne } from 'typeorm';
+
 import { DeepPartial } from '../../../../shared/shared-types';
 import { LanguageCode } from '../../locale/language-code';
 import { Translation } from '../../locale/locale-types';
 import { VendureEntity } from '../base/base.entity';
+
 import { ProductOption } from './product-option.entity';
 
 @Entity()

+ 1 - 0
server/src/entity/product-option/product-option.dto.ts

@@ -1,4 +1,5 @@
 import { TranslatedInput } from '../../locale/locale-types';
+
 import { ProductOption } from './product-option.entity';
 
 export interface CreateProductOptionDto extends TranslatedInput<ProductOption> {

+ 2 - 0
server/src/entity/product-option/product-option.entity.ts

@@ -1,8 +1,10 @@
 import { Column, Entity, ManyToOne, OneToMany } from 'typeorm';
+
 import { DeepPartial } from '../../../../shared/shared-types';
 import { LocaleString, Translatable, Translation } from '../../locale/locale-types';
 import { VendureEntity } from '../base/base.entity';
 import { ProductOptionGroup } from '../product-option-group/product-option-group.entity';
+
 import { ProductOptionTranslation } from './product-option-translation.entity';
 
 @Entity()

+ 1 - 0
server/src/entity/product-variant/create-product-variant.dto.ts

@@ -1,4 +1,5 @@
 import { TranslatedInput } from '../../locale/locale-types';
+
 import { ProductVariant } from './product-variant.entity';
 
 export interface CreateProductVariantDto extends TranslatedInput<ProductVariant> {

+ 10 - 1
server/src/entity/product-variant/product-variant-translation.entity.ts

@@ -1,8 +1,17 @@
-import { Column, CreateDateColumn, Entity, ManyToOne, PrimaryGeneratedColumn, UpdateDateColumn } from 'typeorm';
+import {
+    Column,
+    CreateDateColumn,
+    Entity,
+    ManyToOne,
+    PrimaryGeneratedColumn,
+    UpdateDateColumn,
+} from 'typeorm';
+
 import { DeepPartial } from '../../../../shared/shared-types';
 import { LanguageCode } from '../../locale/language-code';
 import { Translation } from '../../locale/locale-types';
 import { VendureEntity } from '../base/base.entity';
+
 import { ProductVariant } from './product-variant.entity';
 
 @Entity()

+ 2 - 0
server/src/entity/product-variant/product-variant.entity.ts

@@ -1,9 +1,11 @@
 import { Column, Entity, JoinTable, ManyToMany, ManyToOne, OneToMany } from 'typeorm';
+
 import { DeepPartial } from '../../../../shared/shared-types';
 import { LocaleString, Translatable, Translation } from '../../locale/locale-types';
 import { VendureEntity } from '../base/base.entity';
 import { ProductOption } from '../product-option/product-option.entity';
 import { Product } from '../product/product.entity';
+
 import { ProductVariantTranslation } from './product-variant-translation.entity';
 
 @Entity()

+ 2 - 0
server/src/entity/product/product-translation.entity.ts

@@ -1,8 +1,10 @@
 import { Column, Entity, ManyToOne } from 'typeorm';
+
 import { DeepPartial } from '../../../../shared/shared-types';
 import { LanguageCode } from '../../locale/language-code';
 import { Translation, TranslationInput } from '../../locale/locale-types';
 import { VendureEntity } from '../base/base.entity';
+
 import { Product } from './product.entity';
 
 @Entity()

برخی فایل ها در این مقایسه diff نمایش داده نمی شوند زیرا تعداد فایل ها بسیار زیاد است