Bladeren bron

feat(admin-ui): Create list/detail components for StockLocation

Also change the "products" route to "inventory", to reflect the broader scope it now has.
Michael Bromley 2 jaren geleden
bovenliggende
commit
dce73e40fc
46 gewijzigde bestanden met toevoegingen van 5414 en 5008 verwijderingen
  1. 2 1
      packages/admin-ui/angular.json
  2. 38 38
      packages/admin-ui/i18n-coverage.json
  3. 31 7
      packages/admin-ui/src/lib/catalog/src/catalog.module.ts
  4. 25 29
      packages/admin-ui/src/lib/catalog/src/catalog.routes.ts
  5. 1 1
      packages/admin-ui/src/lib/catalog/src/components/collection-contents/collection-contents.component.html
  6. 1 1
      packages/admin-ui/src/lib/catalog/src/components/product-variant-list/product-variant-list.component.html
  7. 1 1
      packages/admin-ui/src/lib/catalog/src/components/product-variant-quick-jump/product-variant-quick-jump.component.ts
  8. 78 0
      packages/admin-ui/src/lib/catalog/src/components/stock-location-detail/stock-location-detail.component.html
  9. 0 0
      packages/admin-ui/src/lib/catalog/src/components/stock-location-detail/stock-location-detail.component.scss
  10. 168 0
      packages/admin-ui/src/lib/catalog/src/components/stock-location-detail/stock-location-detail.component.ts
  11. 77 0
      packages/admin-ui/src/lib/catalog/src/components/stock-location-list/stock-location-list.component.html
  12. 0 0
      packages/admin-ui/src/lib/catalog/src/components/stock-location-list/stock-location-list.component.scss
  13. 92 0
      packages/admin-ui/src/lib/catalog/src/components/stock-location-list/stock-location-list.component.ts
  14. 3 0
      packages/admin-ui/src/lib/core/src/common/component-registry-types.ts
  15. 40 0
      packages/admin-ui/src/lib/core/src/common/generated-types.ts
  16. 3 3
      packages/admin-ui/src/lib/core/src/components/base-nav/base-nav.component.ts
  17. 1 1
      packages/admin-ui/src/lib/core/src/core.module.ts
  18. 1 0
      packages/admin-ui/src/lib/core/src/providers/bulk-action-registry/bulk-action-types.ts
  19. 1 1
      packages/admin-ui/src/lib/core/src/shared/dynamic-form-inputs/relation-form-input/product-variant/relation-product-variant-input.component.html
  20. 1 1
      packages/admin-ui/src/lib/core/src/shared/dynamic-form-inputs/relation-form-input/product/relation-product-input.component.html
  21. 7 2
      packages/admin-ui/src/lib/static/i18n-messages/cs.json
  22. 7 2
      packages/admin-ui/src/lib/static/i18n-messages/de.json
  23. 8 3
      packages/admin-ui/src/lib/static/i18n-messages/en.json
  24. 7 2
      packages/admin-ui/src/lib/static/i18n-messages/es.json
  25. 7 2
      packages/admin-ui/src/lib/static/i18n-messages/fr.json
  26. 7 2
      packages/admin-ui/src/lib/static/i18n-messages/it.json
  27. 7 2
      packages/admin-ui/src/lib/static/i18n-messages/pl.json
  28. 7 2
      packages/admin-ui/src/lib/static/i18n-messages/pt_BR.json
  29. 7 2
      packages/admin-ui/src/lib/static/i18n-messages/pt_PT.json
  30. 7 2
      packages/admin-ui/src/lib/static/i18n-messages/ru.json
  31. 7 2
      packages/admin-ui/src/lib/static/i18n-messages/uk.json
  32. 7 2
      packages/admin-ui/src/lib/static/i18n-messages/zh_Hans.json
  33. 7 2
      packages/admin-ui/src/lib/static/i18n-messages/zh_Hant.json
  34. 561 580
      packages/asset-server-plugin/e2e/graphql/generated-e2e-asset-server-plugin-types.ts
  35. 638 656
      packages/common/src/generated-shop-types.ts
  36. 8 0
      packages/common/src/generated-types.ts
  37. 561 580
      packages/core/e2e/graphql/generated-e2e-admin-types.ts
  38. 610 628
      packages/core/e2e/graphql/generated-e2e-shop-types.ts
  39. 5 5
      packages/core/src/api/resolvers/admin/stock-location.resolver.ts
  40. 1 0
      packages/core/src/common/constants.ts
  41. 561 580
      packages/elasticsearch-plugin/e2e/graphql/generated-e2e-elasticsearch-plugin-types.ts
  42. 561 580
      packages/payments-plugin/e2e/graphql/generated-admin-types.ts
  43. 610 628
      packages/payments-plugin/e2e/graphql/generated-shop-types.ts
  44. 642 660
      packages/payments-plugin/src/mollie/graphql/generated-shop-types.ts
  45. 0 0
      schema-admin.json
  46. 0 0
      schema-shop.json

+ 2 - 1
packages/admin-ui/angular.json

@@ -172,7 +172,8 @@
   "schematics": {
     "@schematics/angular:component": {
       "skipTests": true,
-      "changeDetection": "OnPush"
+      "changeDetection": "OnPush",
+      "project": "vendure-admin-lib"
     }
   },
   "cli": {

+ 38 - 38
packages/admin-ui/i18n-coverage.json

@@ -1,70 +1,70 @@
 {
-  "generatedOn": "2023-05-30T11:56:35.756Z",
-  "lastCommit": "be9b0a40cb64dbae58cdb03584d29c0dd1c8974a",
+  "generatedOn": "2023-06-01T14:33:50.530Z",
+  "lastCommit": "20d205bfb09cc05f848ae71358e45c16eeda665b",
   "translationStatus": {
     "cs": {
-      "tokenCount": 719,
-      "translatedCount": 549,
+      "tokenCount": 724,
+      "translatedCount": 547,
       "percentage": 76
     },
     "de": {
-      "tokenCount": 719,
-      "translatedCount": 532,
-      "percentage": 74
+      "tokenCount": 724,
+      "translatedCount": 530,
+      "percentage": 73
     },
     "en": {
-      "tokenCount": 719,
-      "translatedCount": 712,
-      "percentage": 99
+      "tokenCount": 724,
+      "translatedCount": 724,
+      "percentage": 100
     },
     "es": {
-      "tokenCount": 719,
-      "translatedCount": 574,
-      "percentage": 80
+      "tokenCount": 724,
+      "translatedCount": 572,
+      "percentage": 79
     },
     "fr": {
-      "tokenCount": 719,
-      "translatedCount": 569,
-      "percentage": 79
+      "tokenCount": 724,
+      "translatedCount": 567,
+      "percentage": 78
     },
     "it": {
-      "tokenCount": 719,
-      "translatedCount": 573,
-      "percentage": 80
+      "tokenCount": 724,
+      "translatedCount": 571,
+      "percentage": 79
     },
     "pl": {
-      "tokenCount": 719,
-      "translatedCount": 383,
+      "tokenCount": 724,
+      "translatedCount": 381,
       "percentage": 53
     },
     "pt_BR": {
-      "tokenCount": 719,
-      "translatedCount": 547,
-      "percentage": 76
+      "tokenCount": 724,
+      "translatedCount": 545,
+      "percentage": 75
     },
     "pt_PT": {
-      "tokenCount": 719,
-      "translatedCount": 582,
-      "percentage": 81
+      "tokenCount": 724,
+      "translatedCount": 580,
+      "percentage": 80
     },
     "ru": {
-      "tokenCount": 719,
-      "translatedCount": 572,
-      "percentage": 80
+      "tokenCount": 724,
+      "translatedCount": 570,
+      "percentage": 79
     },
     "uk": {
-      "tokenCount": 719,
-      "translatedCount": 572,
-      "percentage": 80
+      "tokenCount": 724,
+      "translatedCount": 570,
+      "percentage": 79
     },
     "zh_Hans": {
-      "tokenCount": 719,
-      "translatedCount": 518,
-      "percentage": 72
+      "tokenCount": 724,
+      "translatedCount": 516,
+      "percentage": 71
     },
     "zh_Hant": {
-      "tokenCount": 719,
-      "translatedCount": 363,
+      "tokenCount": 724,
+      "translatedCount": 361,
       "percentage": 50
     }
   }

+ 31 - 7
packages/admin-ui/src/lib/catalog/src/catalog.module.ts

@@ -9,6 +9,7 @@ import {
     GetFacetDetailDocument,
     GetProductDetailDocument,
     GetProductVariantDetailDocument,
+    GetStockLocationDetailDocument,
     PageService,
     SharedModule,
 } from '@vendure/admin-ui/core';
@@ -63,6 +64,8 @@ import { ProductVariantsTableComponent } from './components/product-variants-tab
 import { UpdateProductOptionDialogComponent } from './components/update-product-option-dialog/update-product-option-dialog.component';
 import { VariantPriceDetailComponent } from './components/variant-price-detail/variant-price-detail.component';
 import { ProductVariantQuickJumpComponent } from './components/product-variant-quick-jump/product-variant-quick-jump.component';
+import { StockLocationListComponent } from './components/stock-location-list/stock-location-list.component';
+import { StockLocationDetailComponent } from './components/stock-location-detail/stock-location-detail.component';
 
 const CATALOG_COMPONENTS = [
     ProductListComponent,
@@ -95,17 +98,16 @@ const CATALOG_COMPONENTS = [
     ProductVariantListComponent,
     ProductDetailComponent,
     ProductVariantDetailComponent,
+    CreateProductVariantDialogComponent,
+    CreateProductOptionGroupDialogComponent,
+    ProductVariantQuickJumpComponent,
+    StockLocationListComponent,
 ];
 
 @NgModule({
     imports: [SharedModule, RouterModule.forChild([])],
     exports: [...CATALOG_COMPONENTS],
-    declarations: [
-        ...CATALOG_COMPONENTS,
-        CreateProductVariantDialogComponent,
-        CreateProductOptionGroupDialogComponent,
-        ProductVariantQuickJumpComponent,
-    ],
+    declarations: [...CATALOG_COMPONENTS, StockLocationDetailComponent],
     providers: [
         {
             provide: ROUTES,
@@ -162,6 +164,28 @@ export class CatalogModule {
             route: 'variants',
             component: ProductVariantListComponent,
         });
+        pageService.registerPageTab({
+            location: 'stock-location-detail',
+            tab: _('catalog.stock-location'),
+            route: '',
+            component: detailComponentWithResolver({
+                component: StockLocationDetailComponent,
+                query: GetStockLocationDetailDocument,
+                entityKey: 'stockLocation',
+                getBreadcrumbs: entity => [
+                    {
+                        label: entity ? entity.name : _('catalog.create-new-stock-location'),
+                        link: [entity?.id],
+                    },
+                ],
+            }),
+        });
+        pageService.registerPageTab({
+            location: 'product-list',
+            tab: _('catalog.stock-locations'),
+            route: 'stock-locations',
+            component: StockLocationListComponent,
+        });
         pageService.registerPageTab({
             location: 'product-variant-detail',
             tab: _('catalog.product-variants'),
@@ -173,7 +197,7 @@ export class CatalogModule {
                 getBreadcrumbs: entity => [
                     {
                         label: `${entity?.product.name}`,
-                        link: ['/catalog', 'products', entity?.product.id],
+                        link: ['/catalog', 'inventory', entity?.product.id],
                     },
                     {
                         label: `${entity?.name} (${entity?.sku})`,

+ 25 - 29
packages/admin-ui/src/lib/catalog/src/catalog.routes.ts

@@ -17,20 +17,20 @@ import { ProductVariantsResolver } from './providers/routing/product-variants-re
 
 export const createRoutes = (pageService: PageService): Route[] => [
     {
-        path: 'products',
+        path: 'inventory',
         component: PageComponent,
         data: {
             locationId: 'product-list',
-            breadcrumb: _('breadcrumb.products'),
+            breadcrumb: _('breadcrumb.inventory'),
         },
         children: pageService.getPageTabRoutes('product-list'),
     },
     {
-        path: 'products/:id',
+        path: 'inventory/:id',
         component: PageComponent,
         data: {
             locationId: 'product-detail',
-            breadcrumb: { label: _('breadcrumb.products'), link: ['../', 'products'] },
+            breadcrumb: { label: _('breadcrumb.inventory'), link: ['../', 'inventory'] },
         },
         children: [
             {
@@ -60,16 +60,16 @@ export const createRoutes = (pageService: PageService): Route[] => [
         ],
     },
     {
-        path: 'products/:productId/variants/:id',
+        path: 'inventory/:productId/variants/:id',
         component: PageComponent,
         data: {
             locationId: 'product-variant-detail',
-            breadcrumb: { label: _('breadcrumb.products'), link: ['../', 'products'] },
+            breadcrumb: { label: _('breadcrumb.inventory'), link: ['../', 'inventory'] },
         },
         children: pageService.getPageTabRoutes('product-variant-detail'),
     },
     {
-        path: 'products/:id/options',
+        path: 'inventory/:id/options',
         component: ProductOptionsEditorComponent,
         resolve: createResolveData(ProductVariantsResolver),
         canDeactivate: [CanDeactivateDetailGuard],
@@ -77,6 +77,21 @@ export const createRoutes = (pageService: PageService): Route[] => [
             breadcrumb: productOptionsEditorBreadcrumb,
         },
     },
+    {
+        path: 'inventory/stock-locations/:id',
+        component: PageComponent,
+        data: {
+            locationId: 'stock-location-detail',
+            breadcrumb: [
+                { label: _('breadcrumb.inventory'), link: ['../', 'inventory'] },
+                {
+                    label: _('breadcrumb.stock-locations'),
+                    link: ['../', 'inventory', 'stock-locations'],
+                },
+            ],
+        },
+        children: pageService.getPageTabRoutes('stock-location-detail'),
+    },
     {
         path: 'facets',
         component: PageComponent,
@@ -133,35 +148,16 @@ export const createRoutes = (pageService: PageService): Route[] => [
     },
 ];
 
-export function productVariantEditorBreadcrumb(data: any, params: any) {
-    return data.entity.pipe(
-        map((entity: any) => [
-            {
-                label: _('breadcrumb.products'),
-                link: ['../', 'products'],
-            },
-            {
-                label: `${entity.name}`,
-                link: ['../', 'products', params.id, { tab: 'variants' }],
-            },
-            {
-                label: _('breadcrumb.manage-variants'),
-                link: ['manage-variants'],
-            },
-        ]),
-    );
-}
-
 export function productOptionsEditorBreadcrumb(data: any, params: any) {
     return data.entity.pipe(
         map((entity: any) => [
             {
-                label: _('breadcrumb.products'),
-                link: ['../', 'products'],
+                label: _('breadcrumb.inventory'),
+                link: ['../', 'inventory'],
             },
             {
                 label: `${entity.name}`,
-                link: ['../', 'products', params.id, { tab: 'variants' }],
+                link: ['../', 'inventory', params.id, { tab: 'variants' }],
             },
             {
                 label: _('breadcrumb.product-options'),

+ 1 - 1
packages/admin-ui/src/lib/catalog/src/components/collection-contents/collection-contents.component.html

@@ -36,7 +36,7 @@
         </vdr-dt2-column>
         <vdr-dt2-column [heading]="'common.name' | translate" [optional]="false">
             <ng-template let-variant="item">
-                <a class="button-ghost" [routerLink]="['/catalog/products', variant.productId]"
+                <a class="button-ghost" [routerLink]="['/catalog/inventory', variant.productId]"
                     ><span>{{ variant.name }}</span
                     ><clr-icon shape="arrow right"
                 /></a>

+ 1 - 1
packages/admin-ui/src/lib/catalog/src/components/product-variant-list/product-variant-list.component.html

@@ -65,7 +65,7 @@
     </vdr-dt2-column>
     <vdr-dt2-column [heading]="'catalog.name' | translate" [optional]="false" [sort]="sorts.get('name')">
         <ng-template let-variant="item">
-            <a class="button-ghost" [routerLink]="['/catalog/products', variant.productId, 'variants', variant.id]"
+            <a class="button-ghost" [routerLink]="['/catalog/inventory', variant.productId, 'variants', variant.id]"
                 ><span>{{ variant.name }}</span
                 ><clr-icon shape="arrow right"
             /></a>

+ 1 - 1
packages/admin-ui/src/lib/catalog/src/components/product-variant-quick-jump/product-variant-quick-jump.component.ts

@@ -51,7 +51,7 @@ export class ProductVariantQuickJumpComponent implements OnInit {
     onSelect(item?: NonNullable<GetProductVariantsQuickJumpQuery['product']>['variants'][number]) {
         if (item) {
             this.router
-                .navigate(['catalog', 'products', this.productId, 'variants', item.id])
+                .navigate(['catalog', 'inventory', this.productId, 'variants', item.id])
                 .then(() => (this.selectedVariantId = undefined));
         }
     }

+ 78 - 0
packages/admin-ui/src/lib/catalog/src/components/stock-location-detail/stock-location-detail.component.html

@@ -0,0 +1,78 @@
+<vdr-page-block>
+    <vdr-action-bar>
+        <vdr-ab-left></vdr-ab-left>
+
+        <vdr-ab-right>
+            <vdr-action-bar-items locationId="stock-location-detail"></vdr-action-bar-items>
+            <button
+                class="btn btn-primary"
+                *ngIf="isNew$ | async; else updateButton"
+                (click)="create()"
+                [disabled]="detailForm.invalid || detailForm.pristine"
+            >
+                {{ 'common.create' | translate }}
+            </button>
+            <ng-template #updateButton>
+                <button
+                    class="btn btn-primary"
+                    (click)="save()"
+                    [disabled]="detailForm.invalid || detailForm.pristine"
+                    *vdrIfPermissions="'UpdateStockLocation'"
+                >
+                    {{ 'common.update' | translate }}
+                </button>
+            </ng-template>
+        </vdr-ab-right>
+    </vdr-action-bar>
+</vdr-page-block>
+
+<form class="form" [formGroup]="detailForm">
+    <vdr-page-detail-layout>
+        <vdr-page-detail-sidebar>
+            <vdr-card *ngIf="entity$ | async as entity">
+                <vdr-page-entity-info [entity]="entity" />
+            </vdr-card>
+        </vdr-page-detail-sidebar>
+        <vdr-page-block>
+            <vdr-card>
+                <div class="form-grid">
+                    <vdr-form-field [label]="'common.name' | translate" for="name">
+                        <input
+                            id="name"
+                            type="text"
+                            formControlName="name"
+                            [readonly]="!('UpdateStockLocation' | hasPermission)"
+                        />
+                    </vdr-form-field>
+                    <vdr-form-field
+                        class="form-grid-span"
+                        [label]="'common.description' | translate"
+                        for="slug"
+                        [errors]="{ pattern: 'catalog.slug-pattern-error' | translate }"
+                    >
+                        <vdr-rich-text-editor
+                            formControlName="description"
+                            [readonly]="!('UpdateStockLocation' | hasPermission)"
+                        ></vdr-rich-text-editor>
+                    </vdr-form-field>
+                </div>
+            </vdr-card>
+            <vdr-card
+                formGroupName="customFields"
+                *ngIf="customFields.length"
+                [title]="'common.custom-fields' | translate"
+            >
+                <vdr-tabbed-custom-fields
+                    entityName="StockLocation"
+                    [customFields]="customFields"
+                    [customFieldsFormGroup]="detailForm.get('customFields')"
+                ></vdr-tabbed-custom-fields>
+            </vdr-card>
+            <vdr-custom-detail-component-host
+                locationId="stock-location-detail"
+                [entity$]="entity$"
+                [detailForm]="detailForm"
+            ></vdr-custom-detail-component-host>
+        </vdr-page-block>
+    </vdr-page-detail-layout>
+</form>

+ 0 - 0
packages/admin-ui/src/lib/catalog/src/components/stock-location-detail/stock-location-detail.component.scss


+ 168 - 0
packages/admin-ui/src/lib/catalog/src/components/stock-location-detail/stock-location-detail.component.ts

@@ -0,0 +1,168 @@
+import { ChangeDetectionStrategy, ChangeDetectorRef, Component, OnDestroy, OnInit } from '@angular/core';
+import { FormBuilder, Validators } from '@angular/forms';
+import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker';
+import {
+    CreateStockLocationDocument,
+    CreateStockLocationInput,
+    DataService,
+    GetStockLocationDetailDocument,
+    NotificationService,
+    StockLocationDetailFragment,
+    TypedBaseDetailComponent,
+    UpdateStockLocationDocument,
+    UpdateStockLocationInput,
+} from '@vendure/admin-ui/core';
+import { gql } from 'apollo-angular';
+import { mergeMap, take } from 'rxjs/operators';
+
+const STOCK_LOCATION_DETAIL_FRAGMENT = gql`
+    fragment StockLocationDetail on StockLocation {
+        id
+        createdAt
+        updatedAt
+        name
+        description
+    }
+`;
+
+export const GET_STOCK_LOCATION_DETAIL = gql`
+    query GetStockLocationDetail($id: ID!) {
+        stockLocation(id: $id) {
+            ...StockLocationDetail
+        }
+    }
+    ${STOCK_LOCATION_DETAIL_FRAGMENT}
+`;
+
+export const CREATE_STOCK_LOCATION = gql`
+    mutation CreateStockLocation($input: CreateStockLocationInput!) {
+        createStockLocation(input: $input) {
+            ...StockLocationDetail
+        }
+    }
+    ${STOCK_LOCATION_DETAIL_FRAGMENT}
+`;
+
+export const UPDATE_STOCK_LOCATION = gql`
+    mutation UpdateStockLocation($input: UpdateStockLocationInput!) {
+        updateStockLocation(input: $input) {
+            ...StockLocationDetail
+        }
+    }
+    ${STOCK_LOCATION_DETAIL_FRAGMENT}
+`;
+
+@Component({
+    selector: 'vdr-stock-location-detail',
+    templateUrl: './stock-location-detail.component.html',
+    styleUrls: ['./stock-location-detail.component.scss'],
+    changeDetection: ChangeDetectionStrategy.OnPush,
+})
+export class StockLocationDetailComponent
+    extends TypedBaseDetailComponent<typeof GetStockLocationDetailDocument, 'stockLocation'>
+    implements OnInit, OnDestroy
+{
+    customFields = this.getCustomFieldConfig('TaxRate');
+    detailForm = this.formBuilder.group({
+        name: ['', Validators.required],
+        description: [''],
+        customFields: this.formBuilder.group(
+            this.customFields.reduce((hash, field) => ({ ...hash, [field.name]: '' }), {}),
+        ),
+    });
+
+    constructor(
+        private changeDetector: ChangeDetectorRef,
+        protected dataService: DataService,
+        private formBuilder: FormBuilder,
+        private notificationService: NotificationService,
+    ) {
+        super();
+    }
+
+    ngOnInit() {
+        this.init();
+    }
+
+    ngOnDestroy() {
+        this.destroy();
+    }
+
+    create() {
+        if (!this.detailForm.dirty) {
+            return;
+        }
+        const { name, description, customFields } = this.detailForm.value;
+        if (!name) {
+            return;
+        }
+        const formValue = this.detailForm.value;
+        const input = {
+            name,
+            description,
+            customFields: formValue.customFields,
+        } satisfies CreateStockLocationInput;
+        this.dataService.mutate(CreateStockLocationDocument, { input }).subscribe(
+            data => {
+                this.notificationService.success(_('common.notify-create-success'), {
+                    entity: 'StockLocation',
+                });
+                this.detailForm.markAsPristine();
+                this.changeDetector.markForCheck();
+                this.router.navigate(['../', data.createStockLocation.id], { relativeTo: this.route });
+            },
+            err => {
+                this.notificationService.error(_('common.notify-create-error'), {
+                    entity: 'StockLocation',
+                });
+            },
+        );
+    }
+
+    save() {
+        if (!this.detailForm.dirty) {
+            return;
+        }
+        const formValue = this.detailForm.value;
+        this.entity$
+            .pipe(
+                take(1),
+                mergeMap(taxRate => {
+                    const input = {
+                        id: taxRate.id,
+                        name: formValue.name,
+                        description: formValue.description,
+                        customFields: formValue.customFields,
+                    } satisfies UpdateStockLocationInput;
+                    return this.dataService.mutate(UpdateStockLocationDocument, { input });
+                }),
+            )
+            .subscribe(
+                data => {
+                    this.notificationService.success(_('common.notify-update-success'), {
+                        entity: 'StockLocation',
+                    });
+                    this.detailForm.markAsPristine();
+                    this.changeDetector.markForCheck();
+                },
+                err => {
+                    this.notificationService.error(_('common.notify-update-error'), {
+                        entity: 'StockLocation',
+                    });
+                },
+            );
+    }
+
+    /**
+     * Update the form values when the entity changes.
+     */
+    protected setFormValues(entity: StockLocationDetailFragment): void {
+        this.detailForm.patchValue({
+            name: entity.name,
+            description: entity.description,
+        });
+        if (this.customFields.length) {
+            this.setCustomFieldFormValues(this.customFields, this.detailForm.get('customFields'), entity);
+        }
+    }
+}

+ 77 - 0
packages/admin-ui/src/lib/catalog/src/components/stock-location-list/stock-location-list.component.html

@@ -0,0 +1,77 @@
+<vdr-page-block>
+    <vdr-action-bar>
+        <vdr-ab-left> </vdr-ab-left>
+        <vdr-ab-right>
+            <vdr-action-bar-items locationId="stock-location-list"></vdr-action-bar-items>
+            <a
+                class="button primary"
+                *vdrIfPermissions="['CreateStockLocation']"
+                [routerLink]="['./', 'create']"
+            >
+                <clr-icon shape="plus"></clr-icon>
+                {{ 'catalog.create-new-stock-location' | translate }}
+            </a>
+        </vdr-ab-right>
+    </vdr-action-bar>
+</vdr-page-block>
+<vdr-data-table-2
+    class="mt-2"
+    id="stock-location-list"
+    [items]="items$ | async"
+    [itemsPerPage]="itemsPerPage$ | async"
+    [totalItems]="totalItems$ | async"
+    [currentPage]="currentPage$ | async"
+    [filters]="filters"
+    (pageChange)="setPageNumber($event)"
+    (itemsPerPageChange)="setItemsPerPage($event)"
+>
+    <vdr-bulk-action-menu
+        locationId="stock-location-list"
+        [hostComponent]="this"
+        [selectionManager]="selectionManager"
+    />
+    <vdr-dt2-search
+        [searchTermControl]="searchTermControl"
+        [searchTermPlaceholder]="'catalog.filter-by-name' | translate"
+    />
+    <vdr-dt2-column [heading]="'common.id' | translate" [hiddenByDefault]="true" [sort]="sorts.get('id')">
+        <ng-template let-stockLocation="item">
+            {{ stockLocation.id }}
+        </ng-template>
+    </vdr-dt2-column>
+    <vdr-dt2-column
+        [heading]="'common.created-at' | translate"
+        [hiddenByDefault]="true"
+        [sort]="sorts.get('createdAt')"
+    >
+        <ng-template let-stockLocation="item">
+            {{ stockLocation.createdAt | localeDate : 'short' }}
+        </ng-template>
+    </vdr-dt2-column>
+    <vdr-dt2-column
+        [heading]="'common.updated-at' | translate"
+        [hiddenByDefault]="true"
+        [sort]="sorts.get('updatedAt')"
+    >
+        <ng-template let-stockLocation="item">
+            {{ stockLocation.updatedAt | localeDate : 'short' }}
+        </ng-template>
+    </vdr-dt2-column>
+    <vdr-dt2-column [heading]="'common.name' | translate" [optional]="false" [sort]="sorts.get('name')">
+        <ng-template let-stockLocation="item">
+            <a class="button-ghost" [routerLink]="['./', stockLocation.id]"
+                ><span>{{ stockLocation.name }}</span
+                ><clr-icon shape="arrow right"
+            /></a>
+        </ng-template>
+    </vdr-dt2-column>
+    <vdr-dt2-column [heading]="'common.description' | translate" [sort]="sorts.get('description')">
+        <ng-template let-stockLocation="item">
+            {{ stockLocation.description }}
+        </ng-template>
+    </vdr-dt2-column>
+    <vdr-dt2-custom-field-column
+        *ngFor="let field of customFields"
+        [customField]="field"
+        [sorts]="sorts" />
+</vdr-data-table-2>

+ 0 - 0
packages/admin-ui/src/lib/catalog/src/components/stock-location-list/stock-location-list.component.scss


+ 92 - 0
packages/admin-ui/src/lib/catalog/src/components/stock-location-list/stock-location-list.component.ts

@@ -0,0 +1,92 @@
+import { ChangeDetectionStrategy, Component, OnInit } from '@angular/core';
+import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker';
+import { GetStockLocationListDocument, TypedBaseListComponent } from '@vendure/admin-ui/core';
+import { gql } from 'apollo-angular';
+
+export const GET_STOCK_LOCATION_LIST = gql`
+    query GetStockLocationList($options: StockLocationListOptions) {
+        stockLocations(options: $options) {
+            items {
+                ...StockLocationListItem
+            }
+            totalItems
+        }
+    }
+    fragment StockLocationListItem on StockLocation {
+        id
+        createdAt
+        updatedAt
+        name
+        description
+    }
+`;
+
+@Component({
+    selector: 'vdr-stock-location-list',
+    templateUrl: './stock-location-list.component.html',
+    styleUrls: ['./stock-location-list.component.scss'],
+    changeDetection: ChangeDetectionStrategy.OnPush,
+})
+export class StockLocationListComponent
+    extends TypedBaseListComponent<typeof GetStockLocationListDocument, 'stockLocations'>
+    implements OnInit
+{
+    readonly customFields = this.getCustomFieldConfig('StockLocation');
+    readonly filters = this.createFilterCollection()
+        .addDateFilters()
+        .addFilters([
+            {
+                name: 'id',
+                type: { kind: 'text' },
+                label: _('common.id'),
+                filterField: 'id',
+            },
+            {
+                name: 'enabled',
+                type: { kind: 'text' },
+                label: _('common.enabled'),
+                filterField: 'name',
+            },
+            {
+                name: 'sku',
+                type: { kind: 'text' },
+                label: _('catalog.sku'),
+                filterField: 'description',
+            },
+        ])
+        .addCustomFieldFilters(this.customFields)
+        .connectToRoute(this.route);
+
+    readonly sorts = this.createSortCollection()
+        .addSorts([
+            { name: 'id' },
+            { name: 'createdAt' },
+            { name: 'updatedAt' },
+            { name: 'name' },
+            { name: 'description' },
+        ])
+        .addCustomFieldSorts(this.customFields)
+        .connectToRoute(this.route);
+
+    constructor() {
+        super();
+        this.configure({
+            document: GetStockLocationListDocument,
+            getItems: data => data.stockLocations,
+            setVariables: (skip, take) => ({
+                options: {
+                    skip,
+                    take,
+                    filter: {
+                        name: {
+                            contains: this.searchTermControl.value,
+                        },
+                        ...this.filters.createFilterInput(),
+                    },
+                    sort: this.sorts.createSortInput(),
+                },
+            }),
+            refreshListOnChanges: [this.sorts.valueChanges, this.filters.valueChanges],
+        });
+    }
+}

+ 3 - 0
packages/admin-ui/src/lib/core/src/common/component-registry-types.ts

@@ -78,6 +78,8 @@ export type PageLocationId =
     | 'seller-list'
     | 'shipping-method-detail'
     | 'shipping-method-list'
+    | 'stock-location-detail'
+    | 'stock-location-list'
     | 'tax-category-detail'
     | 'tax-category-list'
     | 'tax-rate-detail'
@@ -116,6 +118,7 @@ export type CustomDetailComponentLocationId =
     | 'promotion-detail'
     | 'seller-detail'
     | 'shipping-method-detail'
+    | 'stock-location-detail'
     | 'tax-category-detail'
     | 'tax-rate-detail'
     | 'zone-detail';

File diff suppressed because it is too large
+ 40 - 0
packages/admin-ui/src/lib/core/src/common/generated-types.ts


+ 3 - 3
packages/admin-ui/src/lib/core/src/components/base-nav/base-nav.component.ts

@@ -89,10 +89,10 @@ export class BaseNavComponent implements OnInit, OnDestroy {
                 items: [
                     {
                         requiresPermission: allow(Permission.ReadCatalog, Permission.ReadProduct),
-                        id: 'products',
-                        label: _('nav.products'),
+                        id: 'inventory',
+                        label: _('nav.inventory'),
                         icon: 'library',
-                        routerLink: ['/catalog', 'products'],
+                        routerLink: ['/catalog', 'inventory'],
                     },
                     {
                         requiresPermission: allow(Permission.ReadCatalog, Permission.ReadFacet),

+ 1 - 1
packages/admin-ui/src/lib/core/src/core.module.ts

@@ -99,7 +99,7 @@ export class CoreModule {
     }
 
     private initUiTitle() {
-        const title = getAppConfig().brand || 'VendureAdmin';
+        const title = getAppConfig().brand || 'Vendure Admin';
 
         this.titleService.setTitle(title);
     }

+ 1 - 0
packages/admin-ui/src/lib/core/src/providers/bulk-action-registry/bulk-action-types.ts

@@ -23,6 +23,7 @@ export type BulkActionLocationId =
     | 'administrator-list'
     | 'role-list'
     | 'shipping-method-list'
+    | 'stock-location-list'
     | 'payment-method-list'
     | 'tax-category-list'
     | 'tax-rate-list'

+ 1 - 1
packages/admin-ui/src/lib/core/src/shared/dynamic-form-inputs/relation-form-input/product-variant/relation-product-variant-input.component.html

@@ -19,7 +19,7 @@
         </ng-template>
     </ng-template>
     <ng-template vdrRelationCardDetail let-variant="entity">
-        <a [routerLink]="['/catalog/products', variant.product.id, { tab: 'variants' }]">{{ variant.name }}</a>
+        <a [routerLink]="['/catalog/inventory', variant.product.id, { tab: 'variants' }]">{{ variant.name }}</a>
         <div class="">{{ variant.sku }}</div>
     </ng-template>
 </vdr-relation-card>

+ 1 - 1
packages/admin-ui/src/lib/core/src/shared/dynamic-form-inputs/relation-form-input/product/relation-product-input.component.html

@@ -14,7 +14,7 @@
         </div>
     </ng-template>
     <ng-template vdrRelationCardDetail let-product="entity">
-        <a [routerLink]="['/catalog/products', product.id]">{{ product.name }}</a>
+        <a [routerLink]="['/catalog/inventory', product.id]">{{ product.name }}</a>
     </ng-template>
 </vdr-relation-card>
 

+ 7 - 2
packages/admin-ui/src/lib/static/i18n-messages/cs.json

@@ -35,19 +35,20 @@
     "dashboard": "Nástěnka",
     "facets": "Atributy",
     "global-settings": "Všeobecné nastavení",
+    "inventory": "",
     "job-queue": "Fronta úloh",
     "manage-variants": "Správa variant",
     "modifying": "Úpravy",
     "orders": "Objednávky",
     "payment-methods": "Platební metody",
     "product-options": "",
-    "products": "Produkty",
     "profile": "Profil",
     "promotions": "Propagace",
     "roles": "Role",
     "seller-orders": "",
     "sellers": "",
     "shipping-methods": "Dopravní metody",
+    "stock-locations": "",
     "system-status": "Status systému",
     "tax-categories": "Daňové kategorie",
     "tax-rates": "Daňové sazby",
@@ -93,6 +94,7 @@
     "create-new-collection": "Vytvořit kolekci",
     "create-new-facet": "Vytvořit nový atribut",
     "create-new-product": "Nový produkt",
+    "create-new-stock-location": "",
     "create-product-option-group": "",
     "create-product-variant": "",
     "do-not-inherit-filters": "",
@@ -170,6 +172,8 @@
     "slug-pattern-error": "Špatný formát odkazu",
     "stock-allocated": "Alokováno",
     "stock-levels": "",
+    "stock-location": "",
+    "stock-locations": "",
     "stock-on-hand": "Sklad",
     "tax-category": "Skupina daní",
     "taxes": "Daně",
@@ -482,11 +486,11 @@
     "customers": "Zákazníci",
     "facets": "Atributy",
     "global-settings": "Globální nastavení",
+    "inventory": "",
     "job-queue": "Fronta úloh",
     "marketing": "Marketing",
     "orders": "Objednávky",
     "payment-methods": "Platební metody",
-    "products": "Produkty",
     "promotions": "Propagace",
     "roles": "Role",
     "sales": "Prodeje",
@@ -579,6 +583,7 @@
     "note-visible-to-customer": "Pro adminy i zákazníka",
     "order": "",
     "order-history": "Historie objednávky",
+    "order-is-empty": "",
     "order-state-diagram": "Přehled stavu objednávky",
     "order-type": "",
     "orders": "",

+ 7 - 2
packages/admin-ui/src/lib/static/i18n-messages/de.json

@@ -35,19 +35,20 @@
     "dashboard": "Dashboard",
     "facets": "Facetten",
     "global-settings": "Globale Einstellungen",
+    "inventory": "",
     "job-queue": "Job-Warteschlange",
     "manage-variants": "Varianten verwalten",
     "modifying": "Bearbeiten",
     "orders": "Bestellungen",
     "payment-methods": "Zahlungsarten",
     "product-options": "",
-    "products": "Produkte",
     "profile": "Profil",
     "promotions": "Promotionen",
     "roles": "Rollen",
     "seller-orders": "",
     "sellers": "",
     "shipping-methods": "Versandarten",
+    "stock-locations": "",
     "system-status": "Systemstatus",
     "tax-categories": "Steuerkategorien",
     "tax-rates": "Steuersätze",
@@ -93,6 +94,7 @@
     "create-new-collection": "Neue Kollektion anlegen",
     "create-new-facet": "Neue Facette erstellen",
     "create-new-product": "Neues Produkt",
+    "create-new-stock-location": "",
     "create-product-option-group": "",
     "create-product-variant": "",
     "do-not-inherit-filters": "",
@@ -170,6 +172,8 @@
     "slug-pattern-error": "Ungültiger Slug",
     "stock-allocated": "Lagerbestand reserviert",
     "stock-levels": "",
+    "stock-location": "",
+    "stock-locations": "",
     "stock-on-hand": "Lagerbestand",
     "tax-category": "Steuerkategorie",
     "taxes": "Steuern",
@@ -482,11 +486,11 @@
     "customers": "Kunden",
     "facets": "Facetten",
     "global-settings": "Globale Einstellungen",
+    "inventory": "",
     "job-queue": "Job-Warteschlange",
     "marketing": "Marketing",
     "orders": "Bestellungen",
     "payment-methods": "Zahlungsarten",
-    "products": "Produkte",
     "promotions": "Werbeaktionen",
     "roles": "Rollen",
     "sales": "Verkäufe",
@@ -579,6 +583,7 @@
     "note-visible-to-customer": "Sichtbar für Administratoren und Kunden",
     "order": "",
     "order-history": "Bestellhistorie",
+    "order-is-empty": "",
     "order-state-diagram": "",
     "order-type": "",
     "orders": "",

+ 8 - 3
packages/admin-ui/src/lib/static/i18n-messages/en.json

@@ -35,19 +35,20 @@
     "dashboard": "Dashboard",
     "facets": "Facets",
     "global-settings": "Global settings",
+    "inventory": "Inventory",
     "job-queue": "Job queue",
     "manage-variants": "Manage variants",
     "modifying": "Modifying",
     "orders": "Orders",
     "payment-methods": "Payment methods",
     "product-options": "Product options",
-    "products": "Products",
     "profile": "Profile",
     "promotions": "Promotions",
     "roles": "Roles",
     "seller-orders": "Seller orders",
     "sellers": "Sellers",
     "shipping-methods": "Shipping methods",
+    "stock-locations": "Stock locations",
     "system-status": "System status",
     "tax-categories": "Tax categories",
     "tax-rates": "Tax rates",
@@ -93,6 +94,7 @@
     "create-new-collection": "Create new collection",
     "create-new-facet": "Create new facet",
     "create-new-product": "New product",
+    "create-new-stock-location": "Create new stock location",
     "create-product-option-group": "Create product option group",
     "create-product-variant": "Create product variant",
     "do-not-inherit-filters": "Do not inherit filters",
@@ -170,6 +172,8 @@
     "slug-pattern-error": "Slug is invalid",
     "stock-allocated": "Allocated",
     "stock-levels": "Stock levels",
+    "stock-location": "Stock location",
+    "stock-locations": "Stock locations",
     "stock-on-hand": "Stock",
     "tax-category": "Tax category",
     "taxes": "Taxes",
@@ -482,11 +486,11 @@
     "customers": "Customers",
     "facets": "Facets",
     "global-settings": "Global settings",
+    "inventory": "Inventory",
     "job-queue": "Job queue",
     "marketing": "Marketing",
     "orders": "Orders",
     "payment-methods": "Payment methods",
-    "products": "Products",
     "promotions": "Promotions",
     "roles": "Roles",
     "sales": "Sales",
@@ -579,6 +583,7 @@
     "note-visible-to-customer": "Visible to admins and customer",
     "order": "Order",
     "order-history": "Order history",
+    "order-is-empty": "Order is empty",
     "order-state-diagram": "Order state diagram",
     "order-type": "Order type",
     "orders": "Orders",
@@ -750,4 +755,4 @@
     "job-result": "Job result",
     "job-state": "Job state"
   }
-}
+}

+ 7 - 2
packages/admin-ui/src/lib/static/i18n-messages/es.json

@@ -35,19 +35,20 @@
     "dashboard": "Panel de control",
     "facets": "Etiquetas",
     "global-settings": "Ajustes globales",
+    "inventory": "",
     "job-queue": "Cola de tareas",
     "manage-variants": "Gestionar variantes",
     "modifying": "Modificando",
     "orders": "Pedidos",
     "payment-methods": "Métodos de pago",
     "product-options": "Opciones de producto",
-    "products": "Productos",
     "profile": "Perfil",
     "promotions": "Promociones",
     "roles": "Roles",
     "seller-orders": "",
     "sellers": "",
     "shipping-methods": "Métodos de envío",
+    "stock-locations": "",
     "system-status": "Estado del sistema",
     "tax-categories": "Categorías de impuestos",
     "tax-rates": "Tasas de impuestos",
@@ -93,6 +94,7 @@
     "create-new-collection": "Crear nueva colección",
     "create-new-facet": "Crear nueva faceta",
     "create-new-product": "Crear nuevo producto",
+    "create-new-stock-location": "",
     "create-product-option-group": "",
     "create-product-variant": "",
     "do-not-inherit-filters": "",
@@ -170,6 +172,8 @@
     "slug-pattern-error": "Slug inválido",
     "stock-allocated": "Asignado",
     "stock-levels": "",
+    "stock-location": "",
+    "stock-locations": "",
     "stock-on-hand": "Stock disponible",
     "tax-category": "Categoría de impuestos",
     "taxes": "Impuestos",
@@ -482,11 +486,11 @@
     "customers": "Clientes",
     "facets": "Etiquetas",
     "global-settings": "Ajustes globales",
+    "inventory": "",
     "job-queue": "Cola de trabajos",
     "marketing": "Marketing",
     "orders": "Pedidos",
     "payment-methods": "Pagos",
-    "products": "Productos",
     "promotions": "Promociones",
     "roles": "Roles",
     "sales": "Ventas",
@@ -579,6 +583,7 @@
     "note-visible-to-customer": "Visible para administradores y clientes",
     "order": "",
     "order-history": "Historial de pedidos",
+    "order-is-empty": "",
     "order-state-diagram": "Diagrama de estado de los pedidos",
     "order-type": "",
     "orders": "",

+ 7 - 2
packages/admin-ui/src/lib/static/i18n-messages/fr.json

@@ -35,19 +35,20 @@
     "dashboard": "Tableau de Bord",
     "facets": "Composants",
     "global-settings": "Paramètres globaux",
+    "inventory": "",
     "job-queue": "File d'attente de tâches",
     "manage-variants": "Gestion des variations",
     "modifying": "Modification",
     "orders": "Commandes",
     "payment-methods": "Modes de paiement",
     "product-options": "",
-    "products": "Produits",
     "profile": "Profil",
     "promotions": "Promotions",
     "roles": "Roles",
     "seller-orders": "",
     "sellers": "",
     "shipping-methods": "Modes d'expédition",
+    "stock-locations": "",
     "system-status": "Statut du système",
     "tax-categories": "Catégories des taxes",
     "tax-rates": "Taux de taxe",
@@ -93,6 +94,7 @@
     "create-new-collection": "Créer nouvelle collection",
     "create-new-facet": "Créer nouveau composant",
     "create-new-product": "Nouveau produit",
+    "create-new-stock-location": "",
     "create-product-option-group": "",
     "create-product-variant": "",
     "do-not-inherit-filters": "",
@@ -170,6 +172,8 @@
     "slug-pattern-error": "Identifiant invalide",
     "stock-allocated": "Attribué",
     "stock-levels": "",
+    "stock-location": "",
+    "stock-locations": "",
     "stock-on-hand": "Stock",
     "tax-category": "Catégorie de taxe",
     "taxes": "Taxes",
@@ -482,11 +486,11 @@
     "customers": "Clients",
     "facets": "Composants",
     "global-settings": "Réglages globaux",
+    "inventory": "",
     "job-queue": "File d'attente de tâches",
     "marketing": "Marketing",
     "orders": "Commandes",
     "payment-methods": "Mode de paiement",
-    "products": "Produits",
     "promotions": "Promotions",
     "roles": "Roles",
     "sales": "Ventes",
@@ -579,6 +583,7 @@
     "note-visible-to-customer": "Visible par les admins et le client",
     "order": "",
     "order-history": "Historique de la commande",
+    "order-is-empty": "",
     "order-state-diagram": "Diagramme des états de la commande",
     "order-type": "",
     "orders": "",

+ 7 - 2
packages/admin-ui/src/lib/static/i18n-messages/it.json

@@ -35,19 +35,20 @@
     "dashboard": "Pannello",
     "facets": "Attributi",
     "global-settings": "Impostazioni Globali",
+    "inventory": "",
     "job-queue": "Coda operazioni",
     "manage-variants": "Gestione varianti",
     "modifying": "Modifica",
     "orders": "Ordini",
     "payment-methods": "Metodi di pagamento",
     "product-options": "",
-    "products": "Prodotti",
     "profile": "Profilo",
     "promotions": "Promozioni",
     "roles": "Ruoli",
     "seller-orders": "",
     "sellers": "",
     "shipping-methods": "Metodi di spedizione",
+    "stock-locations": "",
     "system-status": "Stato del sistema",
     "tax-categories": "Impostazioni Tasse",
     "tax-rates": "Importo Tasse",
@@ -93,6 +94,7 @@
     "create-new-collection": "Crea nuova Collezione",
     "create-new-facet": "Crea nuovo attributo",
     "create-new-product": "Crea nuovo prodotto",
+    "create-new-stock-location": "",
     "create-product-option-group": "",
     "create-product-variant": "",
     "do-not-inherit-filters": "",
@@ -170,6 +172,8 @@
     "slug-pattern-error": "Lo slug non è valido",
     "stock-allocated": "Allocato",
     "stock-levels": "",
+    "stock-location": "",
+    "stock-locations": "",
     "stock-on-hand": "Scorte",
     "tax-category": "Categoria Tassa",
     "taxes": "Tasse",
@@ -482,11 +486,11 @@
     "customers": "Clienti",
     "facets": "Attributi",
     "global-settings": "Impostazioni globali",
+    "inventory": "",
     "job-queue": "Coda operazioni",
     "marketing": "Marketing",
     "orders": "Ordini",
     "payment-methods": "Metodi di Pagamento",
-    "products": "Prodotti",
     "promotions": "Promozioni",
     "roles": "Ruoli",
     "sales": "Vendite",
@@ -579,6 +583,7 @@
     "note-visible-to-customer": "Visibile agli amministratori e al cliente",
     "order": "",
     "order-history": "Storico ordine",
+    "order-is-empty": "",
     "order-state-diagram": "Diagramma di stato dell'ordine",
     "order-type": "",
     "orders": "",

+ 7 - 2
packages/admin-ui/src/lib/static/i18n-messages/pl.json

@@ -35,19 +35,20 @@
     "dashboard": "Dashboard",
     "facets": "Fasety",
     "global-settings": "Ustawienia globalne",
+    "inventory": "",
     "job-queue": "Kolejka zadań",
     "manage-variants": "Zarządzaj wariantami",
     "modifying": "",
     "orders": "Zamówienia",
     "payment-methods": "Metody płatności",
     "product-options": "",
-    "products": "Produkty",
     "profile": "",
     "promotions": "Promocje",
     "roles": "Role",
     "seller-orders": "",
     "sellers": "",
     "shipping-methods": "Metody wysyłki",
+    "stock-locations": "",
     "system-status": "",
     "tax-categories": "Kategorie podatkowe",
     "tax-rates": "Stawki podatkowe",
@@ -93,6 +94,7 @@
     "create-new-collection": "Utwórz nową kolekcje",
     "create-new-facet": "Utwórz faset",
     "create-new-product": "Nowy produkt",
+    "create-new-stock-location": "",
     "create-product-option-group": "",
     "create-product-variant": "",
     "do-not-inherit-filters": "",
@@ -170,6 +172,8 @@
     "slug-pattern-error": "",
     "stock-allocated": "",
     "stock-levels": "",
+    "stock-location": "",
+    "stock-locations": "",
     "stock-on-hand": "Stan magazynowy",
     "tax-category": "Kategoria podatkowa",
     "taxes": "Podatki",
@@ -482,11 +486,11 @@
     "customers": "Klienci",
     "facets": "Facets",
     "global-settings": "Ustawienia globalne",
+    "inventory": "",
     "job-queue": "Kolejka zadań",
     "marketing": "Marketing",
     "orders": "Zamówienia",
     "payment-methods": "Metody płatności",
-    "products": "Produkty",
     "promotions": "Promocje",
     "roles": "Role",
     "sales": "Sprzedaż",
@@ -579,6 +583,7 @@
     "note-visible-to-customer": "Widoczne dla administratora i klienta",
     "order": "",
     "order-history": "Historia zamówienia",
+    "order-is-empty": "",
     "order-state-diagram": "",
     "order-type": "",
     "orders": "",

+ 7 - 2
packages/admin-ui/src/lib/static/i18n-messages/pt_BR.json

@@ -35,19 +35,20 @@
     "dashboard": "Painel de controle",
     "facets": "Etiquetas",
     "global-settings": "Configurações globais",
+    "inventory": "",
     "job-queue": "Fila de tabalho",
     "manage-variants": "Gerenciamento de variações",
     "modifying": "Modificando",
     "orders": "Pedidos",
     "payment-methods": "Métodos de pagamentos",
     "product-options": "",
-    "products": "Produtos",
     "profile": "Perfil",
     "promotions": "Promoções",
     "roles": "Regras",
     "seller-orders": "",
     "sellers": "",
     "shipping-methods": "Métodos de envio",
+    "stock-locations": "",
     "system-status": "Status do sistema",
     "tax-categories": "Categorias de taxas e impostos",
     "tax-rates": "Taxas de impostos",
@@ -93,6 +94,7 @@
     "create-new-collection": "Criar nova categoria",
     "create-new-facet": "Criar nova etiqueta",
     "create-new-product": "Novo produto",
+    "create-new-stock-location": "",
     "create-product-option-group": "",
     "create-product-variant": "",
     "do-not-inherit-filters": "",
@@ -170,6 +172,8 @@
     "slug-pattern-error": "Padrão de slug errado",
     "stock-allocated": "Estoque alocado",
     "stock-levels": "",
+    "stock-location": "",
+    "stock-locations": "",
     "stock-on-hand": "Estoque",
     "tax-category": "Categoria de impostos",
     "taxes": "Impostos",
@@ -482,11 +486,11 @@
     "customers": "Clientes",
     "facets": "Etiquetas",
     "global-settings": "Configurações Gerais",
+    "inventory": "",
     "job-queue": "Fila de trabalho",
     "marketing": "Marketing",
     "orders": "Pedidos",
     "payment-methods": "Métodos de pagamentos",
-    "products": "Produtos",
     "promotions": "Promoções",
     "roles": "Regras de permissão",
     "sales": "Vendas",
@@ -579,6 +583,7 @@
     "note-visible-to-customer": "Visível para administradores e clientes",
     "order": "",
     "order-history": "Histórico de pedidos",
+    "order-is-empty": "",
     "order-state-diagram": "Diagrama do estado do pedido",
     "order-type": "",
     "orders": "",

+ 7 - 2
packages/admin-ui/src/lib/static/i18n-messages/pt_PT.json

@@ -35,19 +35,20 @@
     "dashboard": "Painel de controlo",
     "facets": "Etiquetas",
     "global-settings": "Configurações globais",
+    "inventory": "",
     "job-queue": "Fila de tabalho",
     "manage-variants": "Gerir variações",
     "modifying": "A modificar",
     "orders": "Encomendas",
     "payment-methods": "Métodos de pagamentos",
     "product-options": "Opções",
-    "products": "Produtos",
     "profile": "Perfil",
     "promotions": "Promoções",
     "roles": "Regras",
     "seller-orders": "",
     "sellers": "",
     "shipping-methods": "Métodos de envio",
+    "stock-locations": "",
     "system-status": "Estado do sistema",
     "tax-categories": "Categorias de taxas e impostos",
     "tax-rates": "Taxas de impostos",
@@ -93,6 +94,7 @@
     "create-new-collection": "Criar nova categoria",
     "create-new-facet": "Criar nova etiqueta",
     "create-new-product": "Novo produto",
+    "create-new-stock-location": "",
     "create-product-option-group": "",
     "create-product-variant": "",
     "do-not-inherit-filters": "",
@@ -170,6 +172,8 @@
     "slug-pattern-error": "Slug inválido",
     "stock-allocated": "Estoque reservado",
     "stock-levels": "",
+    "stock-location": "",
+    "stock-locations": "",
     "stock-on-hand": "Estoque",
     "tax-category": "Categoria de impostos",
     "taxes": "Impostos",
@@ -482,11 +486,11 @@
     "customers": "Clientes",
     "facets": "Etiquetas",
     "global-settings": "Configurações Gerais",
+    "inventory": "",
     "job-queue": "Fila de trabalho",
     "marketing": "Marketing",
     "orders": "Encomendas",
     "payment-methods": "Métodos de pagamentos",
-    "products": "Produtos",
     "promotions": "Promoções",
     "roles": "Gerir permissões",
     "sales": "Vendas",
@@ -579,6 +583,7 @@
     "note-visible-to-customer": "Visível para administradores e clientes",
     "order": "",
     "order-history": "Histórico de encomendas",
+    "order-is-empty": "",
     "order-state-diagram": "Diagrama do estado da encomenda",
     "order-type": "",
     "orders": "",

+ 7 - 2
packages/admin-ui/src/lib/static/i18n-messages/ru.json

@@ -35,19 +35,20 @@
     "dashboard": "Дашборд",
     "facets": "Теги",
     "global-settings": "Глобальные настройки",
+    "inventory": "",
     "job-queue": "Очередь заданий",
     "manage-variants": "Управление вариантами",
     "modifying": "Изменение",
     "orders": "Заказы",
     "payment-methods": "Способы оплаты",
     "product-options": "",
-    "products": "Товары",
     "profile": "Профиль",
     "promotions": "Акции",
     "roles": "Роли",
     "seller-orders": "",
     "sellers": "",
     "shipping-methods": "Способы доставки",
+    "stock-locations": "",
     "system-status": "Состояние системы",
     "tax-categories": "Категории налогов",
     "tax-rates": "Налоговые ставки",
@@ -93,6 +94,7 @@
     "create-new-collection": "Создать новую коллекцию",
     "create-new-facet": "Создать новый тег",
     "create-new-product": "Создать новый товар",
+    "create-new-stock-location": "",
     "create-product-option-group": "",
     "create-product-variant": "",
     "do-not-inherit-filters": "",
@@ -170,6 +172,8 @@
     "slug-pattern-error": "Код задан некорректно",
     "stock-allocated": "Зарезервировано",
     "stock-levels": "",
+    "stock-location": "",
+    "stock-locations": "",
     "stock-on-hand": "На складе",
     "tax-category": "Налоговая категория",
     "taxes": "Налоги",
@@ -482,11 +486,11 @@
     "customers": "Клиенты",
     "facets": "Теги",
     "global-settings": "Глобальные настройки",
+    "inventory": "",
     "job-queue": "Очередь заданий",
     "marketing": "Маркетинг",
     "orders": "Заказы",
     "payment-methods": "Способы оплаты",
-    "products": "Товары",
     "promotions": "Промо-акции",
     "roles": "Роли",
     "sales": "Продажи",
@@ -579,6 +583,7 @@
     "note-visible-to-customer": "Доступно администраторам и клиентам",
     "order": "",
     "order-history": "История заказов",
+    "order-is-empty": "",
     "order-state-diagram": "Диаграмма состояния заказа",
     "order-type": "",
     "orders": "",

+ 7 - 2
packages/admin-ui/src/lib/static/i18n-messages/uk.json

@@ -35,19 +35,20 @@
     "dashboard": "Дашборд",
     "facets": "Теги",
     "global-settings": "Глобальні налаштування",
+    "inventory": "",
     "job-queue": "Черга завдань",
     "manage-variants": "Управління варіантами",
     "modifying": "Зміна",
     "orders": "Замовлення",
     "payment-methods": "Способи оплати",
     "product-options": "",
-    "products": "Товари",
     "profile": "Профіль",
     "promotions": "Акції",
     "roles": "Ролі",
     "seller-orders": "",
     "sellers": "",
     "shipping-methods": "Способи доставки",
+    "stock-locations": "",
     "system-status": "Стан системи",
     "tax-categories": "Категорії податків",
     "tax-rates": "Податкові ставки",
@@ -93,6 +94,7 @@
     "create-new-collection": "Створити нову колекцію",
     "create-new-facet": "Створити новий тег",
     "create-new-product": "Створити новий товар",
+    "create-new-stock-location": "",
     "create-product-option-group": "",
     "create-product-variant": "",
     "do-not-inherit-filters": "",
@@ -170,6 +172,8 @@
     "slug-pattern-error": "Код заданий некоректно",
     "stock-allocated": "Зарезервовано",
     "stock-levels": "",
+    "stock-location": "",
+    "stock-locations": "",
     "stock-on-hand": "На складі",
     "tax-category": "Податкова категорія",
     "taxes": "Податки",
@@ -482,11 +486,11 @@
     "customers": "Клієнти",
     "facets": "Теги",
     "global-settings": "Глобальні налаштування",
+    "inventory": "",
     "job-queue": "Черга завдань",
     "marketing": "Маркетинг",
     "orders": "Замовлення",
     "payment-methods": "Способи оплати",
-    "products": "Товари",
     "promotions": "Промо-акції",
     "roles": "Ролі",
     "sales": "Продажі",
@@ -579,6 +583,7 @@
     "note-visible-to-customer": "Доступно адміністраторам і клієнтам",
     "order": "",
     "order-history": "Історія замовлень",
+    "order-is-empty": "",
     "order-state-diagram": "Діаграма стану замовлення",
     "order-type": "",
     "orders": "",

+ 7 - 2
packages/admin-ui/src/lib/static/i18n-messages/zh_Hans.json

@@ -35,19 +35,20 @@
     "dashboard": "总览",
     "facets": "商品特征",
     "global-settings": "语言设置",
+    "inventory": "",
     "job-queue": "任务队列",
     "manage-variants": "商品规格管理",
     "modifying": "正在修改",
     "orders": "订单管理",
     "payment-methods": "支付管理",
     "product-options": "",
-    "products": "商品列表",
     "profile": "个人资料",
     "promotions": "优惠券管理",
     "roles": "角色管理",
     "seller-orders": "",
     "sellers": "",
     "shipping-methods": "配送方式管理",
+    "stock-locations": "",
     "system-status": "系统状态",
     "tax-categories": "税表分类",
     "tax-rates": "税率管理",
@@ -93,6 +94,7 @@
     "create-new-collection": "添加系列",
     "create-new-facet": "添加特征",
     "create-new-product": "添加商品",
+    "create-new-stock-location": "",
     "create-product-option-group": "",
     "create-product-variant": "",
     "do-not-inherit-filters": "",
@@ -170,6 +172,8 @@
     "slug-pattern-error": "名称缩写无效",
     "stock-allocated": "已分配",
     "stock-levels": "",
+    "stock-location": "",
+    "stock-locations": "",
     "stock-on-hand": "当前库存",
     "tax-category": "税表分类",
     "taxes": "价格(含税)",
@@ -482,11 +486,11 @@
     "customers": "客户管理",
     "facets": "产品特征",
     "global-settings": "语言设置",
+    "inventory": "",
     "job-queue": "任务队列",
     "marketing": "市场营销",
     "orders": "订单管理",
     "payment-methods": "支付管理",
-    "products": "商品列表",
     "promotions": "优惠券管理",
     "roles": "角色管理",
     "sales": "销售管理",
@@ -579,6 +583,7 @@
     "note-visible-to-customer": "管理员及客户可见",
     "order": "",
     "order-history": "历史订单",
+    "order-is-empty": "",
     "order-state-diagram": "",
     "order-type": "",
     "orders": "",

+ 7 - 2
packages/admin-ui/src/lib/static/i18n-messages/zh_Hant.json

@@ -35,19 +35,20 @@
     "dashboard": "總覽",
     "facets": "商品特徵",
     "global-settings": "語言",
+    "inventory": "",
     "job-queue": "",
     "manage-variants": "商品規格管理",
     "modifying": "",
     "orders": "訂單管理",
     "payment-methods": "支付方式",
     "product-options": "",
-    "products": "商品",
     "profile": "",
     "promotions": "優惠",
     "roles": "角色管理",
     "seller-orders": "",
     "sellers": "",
     "shipping-methods": "配送方式管理",
+    "stock-locations": "",
     "system-status": "",
     "tax-categories": "稅項類別",
     "tax-rates": "税率",
@@ -93,6 +94,7 @@
     "create-new-collection": "新增系列",
     "create-new-facet": "新增特徵",
     "create-new-product": "新增商品",
+    "create-new-stock-location": "",
     "create-product-option-group": "",
     "create-product-variant": "",
     "do-not-inherit-filters": "",
@@ -170,6 +172,8 @@
     "slug-pattern-error": "",
     "stock-allocated": "",
     "stock-levels": "",
+    "stock-location": "",
+    "stock-locations": "",
     "stock-on-hand": "庫存",
     "tax-category": "税表分類",
     "taxes": "價格(連税)",
@@ -482,11 +486,11 @@
     "customers": "客户",
     "facets": "特徵",
     "global-settings": "語言設定",
+    "inventory": "",
     "job-queue": "",
     "marketing": "推銷",
     "orders": "訂單管理",
     "payment-methods": "付款方法",
-    "products": "商品",
     "promotions": "優惠券管理",
     "roles": "角色管理",
     "sales": "銷售管理",
@@ -579,6 +583,7 @@
     "note-visible-to-customer": "管理員及客户可瀏覽",
     "order": "",
     "order-history": "訂單",
+    "order-is-empty": "",
     "order-state-diagram": "",
     "order-type": "",
     "orders": "",

File diff suppressed because it is too large
+ 561 - 580
packages/asset-server-plugin/e2e/graphql/generated-e2e-asset-server-plugin-types.ts


File diff suppressed because it is too large
+ 638 - 656
packages/common/src/generated-shop-types.ts


+ 8 - 0
packages/common/src/generated-types.ts

@@ -4199,6 +4199,8 @@ export enum Permission {
   CreateSettings = 'CreateSettings',
   /** Grants permission to create ShippingMethod */
   CreateShippingMethod = 'CreateShippingMethod',
+  /** Grants permission to create StockLocation */
+  CreateStockLocation = 'CreateStockLocation',
   /** Grants permission to create System */
   CreateSystem = 'CreateSystem',
   /** Grants permission to create Tag */
@@ -4241,6 +4243,8 @@ export enum Permission {
   DeleteSettings = 'DeleteSettings',
   /** Grants permission to delete ShippingMethod */
   DeleteShippingMethod = 'DeleteShippingMethod',
+  /** Grants permission to delete StockLocation */
+  DeleteStockLocation = 'DeleteStockLocation',
   /** Grants permission to delete System */
   DeleteSystem = 'DeleteSystem',
   /** Grants permission to delete Tag */
@@ -4287,6 +4291,8 @@ export enum Permission {
   ReadSettings = 'ReadSettings',
   /** Grants permission to read ShippingMethod */
   ReadShippingMethod = 'ReadShippingMethod',
+  /** Grants permission to read StockLocation */
+  ReadStockLocation = 'ReadStockLocation',
   /** Grants permission to read System */
   ReadSystem = 'ReadSystem',
   /** Grants permission to read Tag */
@@ -4333,6 +4339,8 @@ export enum Permission {
   UpdateSettings = 'UpdateSettings',
   /** Grants permission to update ShippingMethod */
   UpdateShippingMethod = 'UpdateShippingMethod',
+  /** Grants permission to update StockLocation */
+  UpdateStockLocation = 'UpdateStockLocation',
   /** Grants permission to update System */
   UpdateSystem = 'UpdateSystem',
   /** Grants permission to update Tag */

File diff suppressed because it is too large
+ 561 - 580
packages/core/e2e/graphql/generated-e2e-admin-types.ts


File diff suppressed because it is too large
+ 610 - 628
packages/core/e2e/graphql/generated-e2e-shop-types.ts


+ 5 - 5
packages/core/src/api/resolvers/admin/stock-location.resolver.ts

@@ -20,34 +20,34 @@ export class StockLocationResolver {
     constructor(private stockLocationService: StockLocationService) {}
 
     @Query()
-    @Allow(Permission.ReadCatalog, Permission.ReadProduct)
+    @Allow(Permission.ReadCatalog, Permission.ReadStockLocation)
     stockLocation(@Ctx() ctx: RequestContext, @Args() args: QueryStockLocationArgs) {
         return this.stockLocationService.findOne(ctx, args.id);
     }
 
     @Query()
-    @Allow(Permission.ReadCatalog, Permission.ReadProduct)
+    @Allow(Permission.ReadCatalog, Permission.ReadStockLocation)
     stockLocations(@Ctx() ctx: RequestContext, @Args() args: QueryStockLocationsArgs) {
         return this.stockLocationService.findAll(ctx, args.options);
     }
 
     @Mutation()
     @Transaction()
-    @Allow(Permission.CreateCatalog, Permission.CreateProduct)
+    @Allow(Permission.CreateStockLocation)
     createStockLocation(@Ctx() ctx: RequestContext, @Args() args: MutationCreateStockLocationArgs) {
         return this.stockLocationService.create(ctx, args.input);
     }
 
     @Mutation()
     @Transaction()
-    @Allow(Permission.UpdateCatalog, Permission.UpdateProduct)
+    @Allow(Permission.UpdateStockLocation)
     updateStockLocation(@Ctx() ctx: RequestContext, @Args() args: MutationUpdateStockLocationArgs) {
         return this.stockLocationService.update(ctx, args.input);
     }
 
     @Mutation()
     @Transaction()
-    @Allow(Permission.DeleteCatalog, Permission.DeleteProduct)
+    @Allow(Permission.DeleteStockLocation)
     deleteStockLocation(@Ctx() ctx: RequestContext, @Args() args: MutationDeleteStockLocationArgs) {
         return this.stockLocationService.delete(ctx, args.input);
     }

+ 1 - 0
packages/core/src/common/constants.ts

@@ -67,6 +67,7 @@ export const DEFAULT_PERMISSIONS: PermissionDefinition[] = [
     new CrudPermissionDefinition('TaxCategory'),
     new CrudPermissionDefinition('TaxRate'),
     new CrudPermissionDefinition('Seller'),
+    new CrudPermissionDefinition('StockLocation'),
     new CrudPermissionDefinition('System'),
     new CrudPermissionDefinition('Zone'),
 ];

File diff suppressed because it is too large
+ 561 - 580
packages/elasticsearch-plugin/e2e/graphql/generated-e2e-elasticsearch-plugin-types.ts


File diff suppressed because it is too large
+ 561 - 580
packages/payments-plugin/e2e/graphql/generated-admin-types.ts


File diff suppressed because it is too large
+ 610 - 628
packages/payments-plugin/e2e/graphql/generated-shop-types.ts


File diff suppressed because it is too large
+ 642 - 660
packages/payments-plugin/src/mollie/graphql/generated-shop-types.ts


File diff suppressed because it is too large
+ 0 - 0
schema-admin.json


File diff suppressed because it is too large
+ 0 - 0
schema-shop.json


Some files were not shown because too many files changed in this diff