Browse Source

feat(core): Implement deleteAssets mutation

Relates to #380
Michael Bromley 5 years ago
parent
commit
6f12014577

+ 7 - 0
packages/asset-server-plugin/e2e/graphql/generated-e2e-asset-server-plugin-types.ts

@@ -1767,6 +1767,8 @@ export type Mutation = {
     updateAsset: Asset;
     /** Delete an Asset */
     deleteAsset: DeletionResponse;
+    /** Delete multiple Assets */
+    deleteAssets: DeletionResponse;
     login: LoginResult;
     logout: Scalars['Boolean'];
     /** Create a new Channel */
@@ -1934,6 +1936,11 @@ export type MutationDeleteAssetArgs = {
     force?: Maybe<Scalars['Boolean']>;
 };
 
+export type MutationDeleteAssetsArgs = {
+    ids: Array<Scalars['ID']>;
+    force?: Maybe<Scalars['Boolean']>;
+};
+
 export type MutationLoginArgs = {
     username: Scalars['String'];
     password: Scalars['String'];

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

@@ -1766,6 +1766,8 @@ export type Mutation = {
   updateAsset: Asset;
   /** Delete an Asset */
   deleteAsset: DeletionResponse;
+  /** Delete multiple Assets */
+  deleteAssets: DeletionResponse;
   login: LoginResult;
   logout: Scalars['Boolean'];
   /** Create a new Channel */
@@ -1940,6 +1942,12 @@ export type MutationDeleteAssetArgs = {
 };
 
 
+export type MutationDeleteAssetsArgs = {
+  ids: Array<Scalars['ID']>;
+  force?: Maybe<Scalars['Boolean']>;
+};
+
+
 export type MutationLoginArgs = {
   username: Scalars['String'];
   password: Scalars['String'];

+ 7 - 0
packages/core/e2e/graphql/generated-e2e-admin-types.ts

@@ -1767,6 +1767,8 @@ export type Mutation = {
     updateAsset: Asset;
     /** Delete an Asset */
     deleteAsset: DeletionResponse;
+    /** Delete multiple Assets */
+    deleteAssets: DeletionResponse;
     login: LoginResult;
     logout: Scalars['Boolean'];
     /** Create a new Channel */
@@ -1934,6 +1936,11 @@ export type MutationDeleteAssetArgs = {
     force?: Maybe<Scalars['Boolean']>;
 };
 
+export type MutationDeleteAssetsArgs = {
+    ids: Array<Scalars['ID']>;
+    force?: Maybe<Scalars['Boolean']>;
+};
+
 export type MutationLoginArgs = {
     username: Scalars['String'];
     password: Scalars['String'];

+ 8 - 1
packages/core/src/api/resolvers/admin/asset.resolver.ts

@@ -2,6 +2,7 @@ import { Args, Mutation, Query, Resolver } from '@nestjs/graphql';
 import {
     MutationCreateAssetsArgs,
     MutationDeleteAssetArgs,
+    MutationDeleteAssetsArgs,
     MutationUpdateAssetArgs,
     Permission,
     QueryAssetArgs,
@@ -53,6 +54,12 @@ export class AssetResolver {
     @Mutation()
     @Allow(Permission.DeleteCatalog)
     async deleteAsset(@Ctx() ctx: RequestContext, @Args() { id, force }: MutationDeleteAssetArgs) {
-        return this.assetService.delete(ctx, id, force || undefined);
+        return this.assetService.delete(ctx, [id], force || undefined);
+    }
+
+    @Mutation()
+    @Allow(Permission.DeleteCatalog)
+    async deleteAssets(@Ctx() ctx: RequestContext, @Args() { ids, force }: MutationDeleteAssetsArgs) {
+        return this.assetService.delete(ctx, ids, force || undefined);
     }
 }

+ 2 - 0
packages/core/src/api/schema/admin-api/asset.api.graphql

@@ -12,6 +12,8 @@ type Mutation {
     updateAsset(input: UpdateAssetInput!): Asset!
     "Delete an Asset"
     deleteAsset(id: ID!, force: Boolean): DeletionResponse!
+    "Delete multiple Assets"
+    deleteAssets(ids: [ID!]!, force: Boolean): DeletionResponse!
 }
 
 # generated by generateListOptions function

+ 1 - 1
packages/core/src/i18n/messages/en.json

@@ -79,7 +79,7 @@
     "unexpected-password-on-registration": "Do not provide a password when `authOptions.requireVerification` is set to \"true\""
   },
   "message": {
-    "asset-to-be-deleted-is-featured": "The selected Asset is featured by {products, plural, =0 {} one {1 Product} other {# Products}}{variants, plural, =0 {} one { 1 ProductVariant} other { # ProductVariants}}{collections, plural, =0 {} one { 1 Collection} other { # Collections}}",
+    "asset-to-be-deleted-is-featured": "The selected {assetCount, plural, one {Asset is} other {Assets are}} featured by {products, plural, =0 {} one {1 Product} other {# Products}} {variants, plural, =0 {} one { 1 ProductVariant} other { # ProductVariants}} {collections, plural, =0 {} one { 1 Collection} other { # Collections}}",
     "country-used-in-addresses": "The selected Country cannot be deleted as it is used in {count, plural, one {1 Address} other {# Addresses}}",
     "facet-force-deleted": "The Facet was deleted and its FacetValues were removed from {products, plural, =0 {} one {1 Product} other {# Products}}{both, select, both { , } single {}}{variants, plural, =0 {} one {1 ProductVariant} other {# ProductVariants}}",
     "facet-used": "The selected Facet includes FacetValues which are assigned to {products, plural, =0 {} one {1 Product} other {# Products}}{both, select, both { , } single {}}{variants, plural, =0 {} one {1 ProductVariant} other {# ProductVariants}}",

+ 30 - 17
packages/core/src/service/services/asset.service.ts

@@ -155,31 +155,44 @@ export class AssetService {
         return updatedAsset;
     }
 
-    async delete(ctx: RequestContext, id: ID, force: boolean = false): Promise<DeletionResponse> {
-        const asset = await getEntityOrThrow(this.connection, Asset, id);
-        const usages = await this.findAssetUsages(asset);
-        const hasUsages = !!(usages.products.length || usages.variants.length || usages.collections.length);
+    async delete(ctx: RequestContext, ids: ID[], force: boolean = false): Promise<DeletionResponse> {
+        const assets = await this.connection.getRepository(Asset).findByIds(ids);
+        const usageCount = {
+            products: 0,
+            variants: 0,
+            collections: 0,
+        };
+        for (const asset of assets) {
+            const usages = await this.findAssetUsages(asset);
+            usageCount.products += usages.products.length;
+            usageCount.variants += usages.variants.length;
+            usageCount.collections += usages.collections.length;
+        }
+        const hasUsages = !!(usageCount.products || usageCount.variants || usageCount.collections);
         if (hasUsages && !force) {
             return {
                 result: DeletionResult.NOT_DELETED,
                 message: ctx.translate('message.asset-to-be-deleted-is-featured', {
-                    products: usages.products.length,
-                    variants: usages.variants.length,
-                    collections: usages.collections.length,
+                    assetCount: assets.length,
+                    products: usageCount.products,
+                    variants: usageCount.variants,
+                    collections: usageCount.collections,
                 }),
             };
         }
-        // Create a new asset so that the id is still available
-        // after deletion (the .remove() method sets it to undefined)
-        const deletedAsset = new Asset(asset);
-        await this.connection.getRepository(Asset).remove(asset);
-        try {
-            await this.configService.assetOptions.assetStorageStrategy.deleteFile(asset.source);
-            await this.configService.assetOptions.assetStorageStrategy.deleteFile(asset.preview);
-        } catch (e) {
-            Logger.error(`error.could-not-delete-asset-file`, undefined, e.stack);
+        for (const asset of assets) {
+            // Create a new asset so that the id is still available
+            // after deletion (the .remove() method sets it to undefined)
+            const deletedAsset = new Asset(asset);
+            await this.connection.getRepository(Asset).remove(asset);
+            try {
+                await this.configService.assetOptions.assetStorageStrategy.deleteFile(asset.source);
+                await this.configService.assetOptions.assetStorageStrategy.deleteFile(asset.preview);
+            } catch (e) {
+                Logger.error(`error.could-not-delete-asset-file`, undefined, e.stack);
+            }
+            this.eventBus.publish(new AssetEvent(ctx, deletedAsset, 'deleted'));
         }
-        this.eventBus.publish(new AssetEvent(ctx, deletedAsset, 'deleted'));
         return {
             result: DeletionResult.DELETED,
         };

+ 7 - 0
packages/elasticsearch-plugin/e2e/graphql/generated-e2e-elasticsearch-plugin-types.ts

@@ -1767,6 +1767,8 @@ export type Mutation = {
     updateAsset: Asset;
     /** Delete an Asset */
     deleteAsset: DeletionResponse;
+    /** Delete multiple Assets */
+    deleteAssets: DeletionResponse;
     login: LoginResult;
     logout: Scalars['Boolean'];
     /** Create a new Channel */
@@ -1934,6 +1936,11 @@ export type MutationDeleteAssetArgs = {
     force?: Maybe<Scalars['Boolean']>;
 };
 
+export type MutationDeleteAssetsArgs = {
+    ids: Array<Scalars['ID']>;
+    force?: Maybe<Scalars['Boolean']>;
+};
+
 export type MutationLoginArgs = {
     username: Scalars['String'];
     password: Scalars['String'];

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


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