Bläddra i källkod

feat(admin-ui): Implement multiple asset deletion

Relates to #380
Michael Bromley 5 år sedan
förälder
incheckning
b2f3f082ad

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

@@ -1,6 +1,6 @@
 {
-  "generatedOn": "2020-06-30T08:09:29.407Z",
-  "lastCommit": "83347b27acf895b746b7b3288593d6c60d1a14dc",
+  "generatedOn": "2020-07-02T19:47:27.324Z",
+  "lastCommit": "a4e132ac96d7a541f36ee447c5f331db863b0afa",
   "translationStatus": {
     "de": {
       "tokenCount": 651,
@@ -9,7 +9,7 @@
     },
     "en": {
       "tokenCount": 651,
-      "translatedCount": 650,
+      "translatedCount": 651,
       "percentage": 100
     },
     "es": {

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

@@ -22,7 +22,7 @@
     [assets]="(items$ | async)! | paginate: (paginationConfig$ | async) || {}"
     [multiSelect]="true"
     [canDelete]="'DeleteCatalog' | hasPermission"
-    (deleteAsset)="deleteAsset($event)"
+    (deleteAssets)="deleteAssets($event)"
 ></vdr-asset-gallery>
 
 <div class="paging-controls">

+ 17 - 11
packages/admin-ui/src/lib/catalog/src/components/asset-list/asset-list.component.ts

@@ -80,38 +80,42 @@ export class AssetListComponent extends BaseListComponent<GetAssetList.Query, Ge
         }
     }
 
-    deleteAsset(asset: Asset) {
-        this.showModalAndDelete(asset.id)
+    deleteAssets(assets: Asset[]) {
+        this.showModalAndDelete(assets.map((a) => a.id))
             .pipe(
                 switchMap((response) => {
                     if (response.result === DeletionResult.DELETED) {
                         return [true];
                     } else {
-                        return this.showModalAndDelete(asset.id, response.message || '').pipe(
-                            map((r) => r.result === DeletionResult.DELETED),
-                        );
+                        return this.showModalAndDelete(
+                            assets.map((a) => a.id),
+                            response.message || '',
+                        ).pipe(map((r) => r.result === DeletionResult.DELETED));
                     }
                 }),
             )
             .subscribe(
                 () => {
                     this.notificationService.success(_('common.notify-delete-success'), {
-                        entity: 'Asset',
+                        entity: 'Assets',
                     });
                     this.refresh();
                 },
                 (err) => {
                     this.notificationService.error(_('common.notify-delete-error'), {
-                        entity: 'Asset',
+                        entity: 'Assets',
                     });
                 },
             );
     }
 
-    private showModalAndDelete(assetId: string, message?: string) {
+    private showModalAndDelete(assetIds: string[], message?: string) {
         return this.modalService
             .dialog({
-                title: _('catalog.confirm-delete-asset'),
+                title: _('catalog.confirm-delete-assets'),
+                translationVars: {
+                    count: assetIds.length,
+                },
                 body: message,
                 buttons: [
                     { type: 'secondary', label: _('common.cancel') },
@@ -119,8 +123,10 @@ export class AssetListComponent extends BaseListComponent<GetAssetList.Query, Ge
                 ],
             })
             .pipe(
-                switchMap((res) => (res ? this.dataService.product.deleteAsset(assetId, !!message) : EMPTY)),
-                map((res) => res.deleteAsset),
+                switchMap((res) =>
+                    res ? this.dataService.product.deleteAssets(assetIds, !!message) : EMPTY,
+                ),
+                map((res) => res.deleteAssets),
             );
     }
 }

+ 16 - 8
packages/admin-ui/src/lib/core/src/common/generated-types.ts

@@ -1816,6 +1816,8 @@ export type Mutation = {
   createZone: Zone;
   /** Delete an Asset */
   deleteAsset: DeletionResponse;
+  /** Delete multiple Assets */
+  deleteAssets: DeletionResponse;
   /** Delete a Channel */
   deleteChannel: DeletionResponse;
   /** Delete a Collection and all of its descendants */
@@ -2075,6 +2077,12 @@ export type MutationDeleteAssetArgs = {
 };
 
 
+export type MutationDeleteAssetsArgs = {
+  ids: Array<Scalars['ID']>;
+  force?: Maybe<Scalars['Boolean']>;
+};
+
+
 export type MutationDeleteChannelArgs = {
   id: Scalars['ID'];
 };
@@ -5310,15 +5318,15 @@ export type UpdateAssetMutation = (
   ) }
 );
 
-export type DeleteAssetMutationVariables = {
-  id: Scalars['ID'];
+export type DeleteAssetsMutationVariables = {
+  ids: Array<Scalars['ID']>;
   force?: Maybe<Scalars['Boolean']>;
 };
 
 
-export type DeleteAssetMutation = (
+export type DeleteAssetsMutation = (
   { __typename?: 'Mutation' }
-  & { deleteAsset: (
+  & { deleteAssets: (
     { __typename?: 'DeletionResponse' }
     & Pick<DeletionResponse, 'result' | 'message'>
   ) }
@@ -7389,10 +7397,10 @@ export namespace UpdateAsset {
   export type UpdateAsset = AssetFragment;
 }
 
-export namespace DeleteAsset {
-  export type Variables = DeleteAssetMutationVariables;
-  export type Mutation = DeleteAssetMutation;
-  export type DeleteAsset = DeleteAssetMutation['deleteAsset'];
+export namespace DeleteAssets {
+  export type Variables = DeleteAssetsMutationVariables;
+  export type Mutation = DeleteAssetsMutation;
+  export type DeleteAssets = DeleteAssetsMutation['deleteAssets'];
 }
 
 export namespace SearchProducts {

+ 3 - 3
packages/admin-ui/src/lib/core/src/data/definitions/product-definitions.ts

@@ -385,9 +385,9 @@ export const UPDATE_ASSET = gql`
     ${ASSET_FRAGMENT}
 `;
 
-export const DELETE_ASSET = gql`
-    mutation DeleteAsset($id: ID!, $force: Boolean) {
-        deleteAsset(id: $id, force: $force) {
+export const DELETE_ASSETS = gql`
+    mutation DeleteAssets($ids: [ID!]!, $force: Boolean) {
+        deleteAssets(ids: $ids, force: $force) {
             result
             message
         }

+ 5 - 5
packages/admin-ui/src/lib/core/src/data/providers/product-data.service.ts

@@ -13,7 +13,7 @@ import {
     CreateProductOptionInput,
     CreateProductVariantInput,
     CreateProductVariants,
-    DeleteAsset,
+    DeleteAssets,
     DeleteProduct,
     DeleteProductVariant,
     GetAsset,
@@ -46,7 +46,7 @@ import {
     CREATE_PRODUCT,
     CREATE_PRODUCT_OPTION_GROUP,
     CREATE_PRODUCT_VARIANTS,
-    DELETE_ASSET,
+    DELETE_ASSETS,
     DELETE_PRODUCT,
     DELETE_PRODUCT_VARIANT,
     GET_ASSET,
@@ -284,9 +284,9 @@ export class ProductDataService {
         });
     }
 
-    deleteAsset(id: string, force: boolean) {
-        return this.baseDataService.mutate<DeleteAsset.Mutation, DeleteAsset.Variables>(DELETE_ASSET, {
-            id,
+    deleteAssets(ids: string[], force: boolean) {
+        return this.baseDataService.mutate<DeleteAssets.Mutation, DeleteAssets.Variables>(DELETE_ASSETS, {
+            ids,
             force,
         });
     }

+ 3 - 2
packages/admin-ui/src/lib/core/src/providers/modal/modal.service.ts

@@ -32,6 +32,7 @@ export interface DialogButtonConfig<T> {
 export interface DialogConfig<T> {
     title: string;
     body?: string;
+    translationVars?: { [key: string]: string | number };
     buttons: Array<DialogButtonConfig<T>>;
 }
 
@@ -113,13 +114,13 @@ export class ModalService {
         const modalFactory = this.componentFactoryResolver.resolveComponentFactory(ModalDialogComponent);
 
         return from(this.overlayHostService.getHostView()).pipe(
-            mergeMap(hostView => {
+            mergeMap((hostView) => {
                 const modalComponentRef = hostView.createComponent(modalFactory);
                 const modalInstance: ModalDialogComponent<any> = modalComponentRef.instance;
                 modalInstance.childComponentType = component;
                 modalInstance.options = options;
 
-                return new Observable<R>(subscriber => {
+                return new Observable<R>((subscriber) => {
                     modalInstance.closeModal = (result: R) => {
                         modalComponentRef.destroy();
                         subscriber.next(result);

+ 1 - 1
packages/admin-ui/src/lib/core/src/shared/components/asset-gallery/asset-gallery.component.html

@@ -48,7 +48,7 @@
                 </div>
             </ng-container>
             <div *ngIf="canDelete">
-                <button (click)="deleteAsset.emit(lastSelected())" class="btn btn-link">
+                <button (click)="deleteAssets.emit(selection)" class="btn btn-link">
                     <clr-icon shape="trash" class="is-danger"></clr-icon> {{ 'common.delete' | translate }}
                 </button>
             </div>

+ 1 - 1
packages/admin-ui/src/lib/core/src/shared/components/asset-gallery/asset-gallery.component.ts

@@ -18,7 +18,7 @@ export class AssetGalleryComponent implements OnChanges {
     @Input() multiSelect = false;
     @Input() canDelete = false;
     @Output() selectionChange = new EventEmitter<Asset[]>();
-    @Output() deleteAsset = new EventEmitter<Asset>();
+    @Output() deleteAssets = new EventEmitter<Asset[]>();
 
     selection: Asset[] = [];
 

+ 3 - 3
packages/admin-ui/src/lib/core/src/shared/components/simple-dialog/simple-dialog.component.html

@@ -1,5 +1,5 @@
-<ng-template vdrDialogTitle>{{ title | translate }}</ng-template>
-{{ body | translate }}
+<ng-template vdrDialogTitle>{{ title | translate:translationVars }}</ng-template>
+{{ body | translate:translationVars }}
 <ng-template vdrDialogButtons>
     <ng-container *ngFor="let button of buttons">
         <button
@@ -8,7 +8,7 @@
             [class.btn-danger]="button.type === 'danger'"
             (click)="resolveWith(button.returnValue)"
         >
-            {{ button.label | translate }}
+            {{ button.label | translate:translationVars }}
         </button>
     </ng-container>
 </ng-template>

+ 1 - 0
packages/admin-ui/src/lib/core/src/shared/components/simple-dialog/simple-dialog.component.ts

@@ -15,5 +15,6 @@ export class SimpleDialogComponent implements Dialog<any> {
     resolveWith: (result?: any) => void;
     title = '';
     body = '';
+    translationVars = {};
     buttons: Array<DialogButtonConfig<any>> = [];
 }

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

@@ -60,7 +60,7 @@
     "collection-contents": "Inhalt der Sammlung",
     "confirm-adding-options-delete-default-body": "Das Hinzufügen von Optionen zu diesem Produkt führt dazu, dass die vorhandene Standardvariante gelöscht wird. Möchten Sie fortfahren?",
     "confirm-adding-options-delete-default-title": "Standardvariante löschen?",
-    "confirm-delete-asset": "Asset löschen?",
+    "confirm-delete-assets": "{count} {count, plural, one {Asset} other {Assets}} löschen?",
     "confirm-delete-channel": "Kanal löschen?",
     "confirm-delete-collection": "Sammlung löschen?",
     "confirm-delete-collection-and-children-body": "Wenn Sie diese Sammlung löschen, werden auch alle untergeordneten Sammlungen gelöscht.",

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

@@ -60,7 +60,7 @@
     "collection-contents": "Collection contents",
     "confirm-adding-options-delete-default-body": "Adding options to this product will cause the existing default variant to be deleted. Do you wish to proceed?",
     "confirm-adding-options-delete-default-title": "Delete default variant?",
-    "confirm-delete-asset": "Delete asset?",
+    "confirm-delete-assets": "Delete {count} {count, plural, one {asset} other {assets}}?",
     "confirm-delete-channel": "Delete channel?",
     "confirm-delete-collection": "Delete collection?",
     "confirm-delete-collection-and-children-body": "Deleting this collection will also delete all child collections",
@@ -680,4 +680,4 @@
     "job-result": "Job result",
     "job-state": "Job state"
   }
-}
+}

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

@@ -60,7 +60,7 @@
     "collection-contents": "Contenidos de la colección",
     "confirm-adding-options-delete-default-body": "Añadir optiones a este producto eliminará la variante por defecto. ¿Desea continuar?",
     "confirm-adding-options-delete-default-title": "¿Eliminar la variante por defecto?",
-    "confirm-delete-asset": "¿Eliminar archivo?",
+    "confirm-delete-assets": "¿Eliminar archivo?",
     "confirm-delete-channel": "¿Eliminar canal de ventas?",
     "confirm-delete-collection": "¿Eliminar colección?",
     "confirm-delete-collection-and-children-body": "Eliminar esta colección también eliminará las sub-colecciones",

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

@@ -60,7 +60,7 @@
     "collection-contents": "Zawartość kolekcji",
     "confirm-adding-options-delete-default-body": "Dodawanie opcji spowoduje, że obecna domyślna opcja zostanie usunięta. Czy chcesz kontynuować?",
     "confirm-adding-options-delete-default-title": "Usunąć domyślny tytuł?",
-    "confirm-delete-asset": "",
+    "confirm-delete-assets": "",
     "confirm-delete-channel": "Usunąć kanał?",
     "confirm-delete-collection": "Usunąć kolekcje?",
     "confirm-delete-collection-and-children-body": "Usunięcie tej kolekcji spowoduje usunięcie także podkategorii",

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

@@ -60,7 +60,7 @@
     "collection-contents": "系列产品",
     "confirm-adding-options-delete-default-body": "添加新规格到此产品会导致含此规格的产品被删除,确认继续吗?",
     "confirm-adding-options-delete-default-title": "确认删除产品规格么?",
-    "confirm-delete-asset": "",
+    "confirm-delete-assets": "",
     "confirm-delete-channel": "确认删除销售渠道?",
     "confirm-delete-collection": "确认删除商品系列吗?",
     "confirm-delete-collection-and-children-body": "删除这个系列会删除它所包含的子系列,确认删除码?",

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

@@ -60,7 +60,7 @@
     "collection-contents": "系列產品",
     "confirm-adding-options-delete-default-body": "新增規格到此產品會引致包含此規格的產品被移除,確認繼續吗?",
     "confirm-adding-options-delete-default-title": "確認移除產品規格嗎?",
-    "confirm-delete-asset": "",
+    "confirm-delete-assets": "",
     "confirm-delete-channel": "確認移除渠道?",
     "confirm-delete-collection": "確認移除商品系列吗?",
     "confirm-delete-collection-and-children-body": "移除這個系列會移除它所包含的子系列,確認移除嗎?",