Browse Source

feat(admin-ui): Add controls for disabling & deleting a Promotion

Closes #159
Michael Bromley 6 years ago
parent
commit
7568e2047e

+ 13 - 0
packages/admin-ui/src/app/common/generated-types.ts

@@ -4021,6 +4021,13 @@ export type UpdatePromotionMutationVariables = {
 
 export type UpdatePromotionMutation = ({ __typename?: 'Mutation' } & { updatePromotion: ({ __typename?: 'Promotion' } & PromotionFragment) });
 
+export type DeletePromotionMutationVariables = {
+  id: Scalars['ID']
+};
+
+
+export type DeletePromotionMutation = ({ __typename?: 'Mutation' } & { deletePromotion: ({ __typename?: 'DeletionResponse' } & Pick<DeletionResponse, 'result' | 'message'>) });
+
 export type CountryFragment = ({ __typename?: 'Country' } & Pick<Country, 'id' | 'code' | 'name' | 'enabled'> & { translations: Array<({ __typename?: 'CountryTranslation' } & Pick<CountryTranslation, 'id' | 'languageCode' | 'name'>)> });
 
 export type GetCountryListQueryVariables = {
@@ -4957,6 +4964,12 @@ export namespace UpdatePromotion {
   export type UpdatePromotion = PromotionFragment;
 }
 
+export namespace DeletePromotion {
+  export type Variables = DeletePromotionMutationVariables;
+  export type Mutation = DeletePromotionMutation;
+  export type DeletePromotion = DeletePromotionMutation['deletePromotion'];
+}
+
 export namespace Country {
   export type Fragment = CountryFragment;
   export type Translations = (NonNullable<CountryFragment['translations'][0]>);

+ 9 - 0
packages/admin-ui/src/app/data/definitions/promotion-definitions.ts

@@ -69,3 +69,12 @@ export const UPDATE_PROMOTION = gql`
     }
     ${PROMOTION_FRAGMENT}
 `;
+
+export const DELETE_PROMOTION = gql`
+    mutation DeletePromotion($id: ID!) {
+        deletePromotion(id: $id) {
+            result
+            message
+        }
+    }
+`;

+ 9 - 0
packages/admin-ui/src/app/data/providers/promotion-data.service.ts

@@ -1,6 +1,7 @@
 import {
     CreatePromotion,
     CreatePromotionInput,
+    DeletePromotion,
     GetAdjustmentOperations,
     GetPromotion,
     GetPromotionList,
@@ -9,6 +10,7 @@ import {
 } from '../../common/generated-types';
 import {
     CREATE_PROMOTION,
+    DELETE_PROMOTION,
     GET_ADJUSTMENT_OPERATIONS,
     GET_PROMOTION,
     GET_PROMOTION_LIST,
@@ -59,4 +61,11 @@ export class PromotionDataService {
             },
         );
     }
+
+    deletePromotion(id: string) {
+        return this.baseDataService.mutate<DeletePromotion.Mutation, DeletePromotion.Variables>(
+            DELETE_PROMOTION,
+            { id },
+        );
+    }
 }

+ 11 - 1
packages/admin-ui/src/app/marketing/components/promotion-detail/promotion-detail.component.html

@@ -1,5 +1,15 @@
 <vdr-action-bar>
-    <vdr-ab-left></vdr-ab-left>
+    <vdr-ab-left>
+        <clr-toggle-wrapper *vdrIfPermissions="'UpdatePromotion'">
+            <input
+                type="checkbox"
+                clrToggle
+                name="enabled"
+                [formControl]="detailForm.get(['enabled'])"
+            />
+            <label>{{ 'common.enabled' | translate }}</label>
+        </clr-toggle-wrapper>
+    </vdr-ab-left>
 
     <vdr-ab-right>
         <button

+ 7 - 1
packages/admin-ui/src/app/marketing/components/promotion-detail/promotion-detail.component.ts

@@ -51,6 +51,7 @@ export class PromotionDetailComponent extends BaseDetailComponent<Promotion.Frag
         super(route, router, serverConfigService);
         this.detailForm = this.formBuilder.group({
             name: ['', Validators.required],
+            enabled: true,
             conditions: this.formBuilder.array([]),
             actions: this.formBuilder.array([]),
         });
@@ -71,6 +72,10 @@ export class PromotionDetailComponent extends BaseDetailComponent<Promotion.Frag
         this.activeChannel$ = this.dataService.settings
             .getActiveChannel()
             .mapStream(data => data.activeChannel);
+
+        // When creating a new Promotion, the initial bindings do not work
+        // unless explicitly re-running the change detector. Don't know why.
+        setTimeout(() => this.changeDetector.markForCheck(), 0);
     }
 
     ngOnDestroy() {
@@ -164,6 +169,7 @@ export class PromotionDetailComponent extends BaseDetailComponent<Promotion.Frag
                     const input: UpdatePromotionInput = {
                         id: promotion.id,
                         name: formValue.name,
+                        enabled: formValue.enabled,
                         conditions: this.mapOperationsToInputs(this.conditions, formValue.conditions),
                         actions: this.mapOperationsToInputs(this.actions, formValue.actions),
                     };
@@ -190,7 +196,7 @@ export class PromotionDetailComponent extends BaseDetailComponent<Promotion.Frag
      * Update the form values when the entity changes.
      */
     protected setFormValues(entity: Promotion.Fragment, languageCode: LanguageCode): void {
-        this.detailForm.patchValue({ name: entity.name });
+        this.detailForm.patchValue({ name: entity.name, enabled: entity.enabled });
         entity.conditions.forEach(o => {
             this.addOperation('conditions', o);
         });

+ 30 - 5
packages/admin-ui/src/app/marketing/components/promotion-list/promotion-list.component.html

@@ -22,17 +22,42 @@
     <vdr-dt-column>{{ 'common.created-at' | translate }}</vdr-dt-column>
     <vdr-dt-column>{{ 'common.updated-at' | translate }}</vdr-dt-column>
     <vdr-dt-column></vdr-dt-column>
+    <vdr-dt-column></vdr-dt-column>
+    <vdr-dt-column></vdr-dt-column>
     <ng-template let-promotion="item">
-        <td class="left">{{ promotion.id }}</td>
-        <td class="left">{{ promotion.name }}</td>
-        <td class="left">{{ promotion.createdAt | date: 'longDate' }}</td>
-        <td class="left">{{ promotion.updatedAt | date: 'longDate' }}</td>
-        <td class="right">
+        <td class="left align-middle">{{ promotion.id }}</td>
+        <td class="left align-middle">{{ promotion.name }}</td>
+        <td class="left align-middle">{{ promotion.createdAt | date: 'longDate' }}</td>
+        <td class="left align-middle">{{ promotion.updatedAt | date: 'longDate' }}</td>
+        <td class="align-middle">
+            <vdr-chip *ngIf="!promotion.enabled">{{ 'common.disabled' | translate }}</vdr-chip>
+        </td>
+        <td class="right align-middle">
             <vdr-table-row-action
                 iconShape="edit"
                 [label]="'common.edit' | translate"
                 [linkTo]="['./', promotion.id]"
             ></vdr-table-row-action>
         </td>
+        <td class="right align-middle">
+            <vdr-dropdown>
+                <button type="button" class="btn btn-link btn-sm" vdrDropdownTrigger>
+                    {{ 'common.actions' | translate }}
+                    <clr-icon shape="caret down"></clr-icon>
+                </button>
+                <vdr-dropdown-menu vdrPosition="bottom-right">
+                    <button
+                        type="button"
+                        class="delete-button"
+                        (click)="deletePromotion(promotion.id)"
+                        [disabled]="!('DeletePromotion' | hasPermission)"
+                        vdrDropdownItem
+                    >
+                        <clr-icon shape="trash" class="is-danger"></clr-icon>
+                        {{ 'common.delete' | translate }}
+                    </button>
+                </vdr-dropdown-menu>
+            </vdr-dropdown>
+        </td>
     </ng-template>
 </vdr-data-table>

+ 41 - 1
packages/admin-ui/src/app/marketing/components/promotion-list/promotion-list.component.ts

@@ -1,5 +1,10 @@
 import { ChangeDetectionStrategy, Component } from '@angular/core';
 import { ActivatedRoute, Router } from '@angular/router';
+import { _ } from '@vendure/admin-ui/src/app/core/providers/i18n/mark-for-extraction';
+import { NotificationService } from '@vendure/admin-ui/src/app/core/providers/notification/notification.service';
+import { ModalService } from '@vendure/admin-ui/src/app/shared/providers/modal/modal.service';
+import { EMPTY } from 'rxjs';
+import { switchMap } from 'rxjs/operators';
 
 import { BaseListComponent } from '../../../common/base-list.component';
 import { GetPromotionList } from '../../../common/generated-types';
@@ -15,11 +20,46 @@ export class PromotionListComponent extends BaseListComponent<
     GetPromotionList.Query,
     GetPromotionList.Items
 > {
-    constructor(private dataService: DataService, router: Router, route: ActivatedRoute) {
+    constructor(
+        private dataService: DataService,
+        router: Router,
+        route: ActivatedRoute,
+        private notificationService: NotificationService,
+        private modalService: ModalService,
+    ) {
         super(router, route);
         super.setQueryFn(
             (...args: any[]) => this.dataService.promotion.getPromotions(...args),
             data => data.promotions,
         );
     }
+
+    deletePromotion(promotionId: string) {
+        this.modalService
+            .dialog({
+                title: _('catalog.confirm-delete-promotion'),
+                buttons: [
+                    { type: 'seconday', label: _('common.cancel') },
+                    { type: 'danger', label: _('common.delete'), returnValue: true },
+                ],
+            })
+            .pipe(
+                switchMap(response =>
+                    response ? this.dataService.promotion.deletePromotion(promotionId) : EMPTY,
+                ),
+            )
+            .subscribe(
+                () => {
+                    this.notificationService.success(_('common.notify-delete-success'), {
+                        entity: 'Promotion',
+                    });
+                    this.refresh();
+                },
+                err => {
+                    this.notificationService.error(_('common.notify-delete-error'), {
+                        entity: 'Promotion',
+                    });
+                },
+            );
+    }
 }

+ 1 - 0
packages/admin-ui/src/i18n-messages/en.json

@@ -38,6 +38,7 @@
     "confirm-delete-facet-value": "Delete facet value?",
     "confirm-delete-product": "Delete product?",
     "confirm-delete-product-variant": "Delete product variant?",
+    "confirm-delete-promotion": "Delete promotion?",
     "confirm-delete-shipping-method": "Delete shipping method?",
     "create-new-collection": "Create new collection",
     "create-new-facet": "Create new facet",