Browse Source

feat(admin-ui): Support for facet value selection in PromotionDetail

Relates to #29
Michael Bromley 7 years ago
parent
commit
96209cd60d

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

@@ -14,7 +14,6 @@ import { CreateOptionGroupDialogComponent } from './components/create-option-gro
 import { CreateOptionGroupFormComponent } from './components/create-option-group-form/create-option-group-form.component';
 import { FacetDetailComponent } from './components/facet-detail/facet-detail.component';
 import { FacetListComponent } from './components/facet-list/facet-list.component';
-import { FacetValueSelectorComponent } from './components/facet-value-selector/facet-value-selector.component';
 import { GenerateProductVariantsComponent } from './components/generate-product-variants/generate-product-variants.component';
 import { ProductAssetsComponent } from './components/product-assets/product-assets.component';
 import { ProductCategoryDetailComponent } from './components/product-category-detail/product-category-detail.component';
@@ -47,7 +46,6 @@ import { ProductResolver } from './providers/routing/product-resolver';
         FacetDetailComponent,
         GenerateProductVariantsComponent,
         ProductVariantsListComponent,
-        FacetValueSelectorComponent,
         ApplyFacetDialogComponent,
         AssetListComponent,
         AssetGalleryComponent,

+ 0 - 41
admin-ui/src/app/catalog/components/facet-value-selector/facet-value-selector.component.ts

@@ -1,41 +0,0 @@
-import { ChangeDetectionStrategy, Component, EventEmitter, Input, OnInit, Output } from '@angular/core';
-import { FacetValue, FacetWithValues } from 'shared/generated-types';
-
-import { flattenFacetValues } from '../../../common/utilities/flatten-facet-values';
-import { DataService } from '../../../data/providers/data.service';
-
-export type FacetValueSeletorItem = {
-    name: string;
-    facetName: string;
-    id: string;
-    value: FacetValue.Fragment;
-};
-
-@Component({
-    selector: 'vdr-facet-value-selector',
-    templateUrl: './facet-value-selector.component.html',
-    styleUrls: ['./facet-value-selector.component.scss'],
-    changeDetection: ChangeDetectionStrategy.OnPush,
-})
-export class FacetValueSelectorComponent implements OnInit {
-    @Output() selectedValuesChange = new EventEmitter<FacetValue.Fragment[]>();
-    @Input() facets: FacetWithValues.Fragment[];
-
-    facetValues: FacetValueSeletorItem[] = [];
-    constructor(private dataService: DataService) {}
-
-    ngOnInit() {
-        this.facetValues = flattenFacetValues(this.facets).map(value => {
-            return {
-                name: value.name,
-                facetName: value.facet.name,
-                id: value.id,
-                value,
-            };
-        });
-    }
-
-    onChange(selected: FacetValueSeletorItem[]) {
-        this.selectedValuesChange.emit(selected.map(s => s.value));
-    }
-}

+ 2 - 0
admin-ui/src/app/marketing/components/promotion-detail/promotion-detail.component.html

@@ -31,6 +31,7 @@
             <ng-container *ngFor="let condition of conditions; index as i">
                 <vdr-adjustment-operation-input
                     (remove)="removeCondition($event)"
+                    [facets]="facets$ | async"
                     [operation]="condition"
                     [formControlName]="i"
                 ></vdr-adjustment-operation-input>
@@ -62,6 +63,7 @@
             <vdr-adjustment-operation-input
                 *ngFor="let action of actions; index as i"
                 (remove)="removeAction($event)"
+                [facets]="facets$ | async"
                 [operation]="action"
                 [formControlName]="i"
             ></vdr-adjustment-operation-input>

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

@@ -2,11 +2,12 @@ import { ChangeDetectionStrategy, ChangeDetectorRef, Component, OnDestroy, OnIni
 import { FormArray, FormBuilder, FormGroup, Validators } from '@angular/forms';
 import { ActivatedRoute, Router } from '@angular/router';
 import { Observable } from 'rxjs';
-import { mergeMap, take } from 'rxjs/operators';
+import { mergeMap, shareReplay, take } from 'rxjs/operators';
 import {
     AdjustmentOperation,
     AdjustmentOperationInput,
     CreatePromotionInput,
+    FacetWithValues,
     LanguageCode,
     Promotion,
     UpdatePromotionInput,
@@ -30,6 +31,7 @@ export class PromotionDetailComponent extends BaseDetailComponent<Promotion.Frag
     detailForm: FormGroup;
     conditions: AdjustmentOperation[] = [];
     actions: AdjustmentOperation[] = [];
+    facets$: Observable<FacetWithValues.Fragment[]>;
 
     private allConditions: AdjustmentOperation[];
     private allActions: AdjustmentOperation[];
@@ -53,6 +55,11 @@ export class PromotionDetailComponent extends BaseDetailComponent<Promotion.Frag
 
     ngOnInit() {
         this.init();
+        this.facets$ = this.dataService.facet
+            .getFacets(9999999, 0)
+            .mapSingle(data => data.facets.items)
+            .pipe(shareReplay(1));
+
         this.promotion$ = this.entity$;
         this.dataService.promotion.getAdjustmentOperations().single$.subscribe(data => {
             this.allActions = data.adjustmentOperations.actions;

+ 9 - 11
admin-ui/src/app/shared/components/adjustment-operation-input/adjustment-operation-input.component.html

@@ -1,16 +1,15 @@
 <div class="card" *ngIf="operation">
     <div class="card-block">{{ interpolateDescription() }}</div>
     <div class="card-block" *ngIf="operation.args?.length">
-        <form clrForm [formGroup]="form" *ngIf="operation" class="operation-inputs">
-            <clr-input-container *ngFor="let arg of operation.args">
+        <form [formGroup]="form" *ngIf="operation" class="operation-inputs">
+            <div *ngFor="let arg of operation.args" class="arg-row">
                 <label>{{ arg.name | titlecase }}</label>
-                <div *ngIf="arg.type === 'boolean'" clrInput class="checkbox">
+                <div *ngIf="arg.type === 'boolean'" class="checkbox">
                     <input type="checkbox" [formControlName]="arg.name" [id]="arg.name" />
                     <label [for]="arg.name"></label>
                 </div>
                 <input
                     *ngIf="arg.type === 'int'"
-                    clrInput
                     [name]="arg.name"
                     type="number"
                     step="1"
@@ -18,31 +17,30 @@
                 />
                 <input
                     *ngIf="arg.type === 'string'"
-                    clrInput
                     [name]="arg.name"
                     type="text"
                     [formControlName]="arg.name"
                 />
                 <input
                     *ngIf="arg.type === 'datetime'"
-                    clrInput
                     [name]="arg.name"
                     type="date"
                     [formControlName]="arg.name"
                 />
                 <vdr-currency-input
                     *ngIf="arg.type === 'money'"
-                    clrInput
                     [formControlName]="arg.name"
                 ></vdr-currency-input>
                 <vdr-percentage-suffix-input
                     *ngIf="arg.type === 'percentage'"
                     [formControlName]="arg.name"
-                    clrInput
                 ></vdr-percentage-suffix-input>
-
-                <clr-control-error>{{ 'error.this-field-is-required' | translate }}</clr-control-error>
-            </clr-input-container>
+                <vdr-facet-value-selector
+                    [facets]="facets"
+                    [formControlName]="arg.name"
+                    *ngIf="arg.type === 'facetValueIds' && facets"
+                ></vdr-facet-value-selector>
+            </div>
         </form>
     </div>
     <div class="card-footer">

+ 2 - 8
admin-ui/src/app/shared/components/adjustment-operation-input/adjustment-operation-input.component.scss

@@ -4,15 +4,9 @@
 }
 
 .operation-inputs {
-    display: flex;
-    flex-wrap: wrap;
 
-    .clr-form-control {
-        margin-top: 0;
-    }
-
-    clr-input-container:not(:last-child) {
-        margin-right: 12px;
+    .arg-row {
+        margin-bottom: 24px;
     }
 
     .hidden {

+ 2 - 1
admin-ui/src/app/shared/components/adjustment-operation-input/adjustment-operation-input.component.ts

@@ -21,7 +21,7 @@ import {
     Validators,
 } from '@angular/forms';
 import { Subscription } from 'rxjs';
-import { AdjustmentOperation } from 'shared/generated-types';
+import { AdjustmentOperation, FacetWithValues } from 'shared/generated-types';
 
 import { interpolateDescription } from '../../../common/utilities/interpolate-description';
 
@@ -49,6 +49,7 @@ import { interpolateDescription } from '../../../common/utilities/interpolate-de
 export class AdjustmentOperationInputComponent
     implements OnChanges, OnDestroy, ControlValueAccessor, Validator {
     @Input() operation: AdjustmentOperation;
+    @Input() facets: FacetWithValues.Fragment[] = [];
     @Output() remove = new EventEmitter<AdjustmentOperation>();
     argValues: { [name: string]: any } = {};
     onChange: (val: any) => void;

+ 3 - 1
admin-ui/src/app/catalog/components/facet-value-selector/facet-value-selector.component.html → admin-ui/src/app/shared/components/facet-value-selector/facet-value-selector.component.html

@@ -3,9 +3,11 @@
     [addTag]="false"
     [hideSelected]="true"
     groupBy="facetName"
-    bindValue="value"
+    bindValue="id"
     multiple="true"
     appendTo="body"
     bindLabel="name"
+    [disabled]="disabled"
+    [ngModel]="value"
     (change)="onChange($event)"
 ></ng-select>

+ 0 - 0
admin-ui/src/app/catalog/components/facet-value-selector/facet-value-selector.component.scss → admin-ui/src/app/shared/components/facet-value-selector/facet-value-selector.component.scss


+ 84 - 0
admin-ui/src/app/shared/components/facet-value-selector/facet-value-selector.component.ts

@@ -0,0 +1,84 @@
+import { ChangeDetectionStrategy, Component, EventEmitter, Input, OnInit, Output } from '@angular/core';
+import { ControlValueAccessor, NG_VALUE_ACCESSOR } from '@angular/forms';
+import { FacetValue, FacetWithValues } from 'shared/generated-types';
+
+import { flattenFacetValues } from '../../../common/utilities/flatten-facet-values';
+import { DataService } from '../../../data/providers/data.service';
+
+export type FacetValueSeletorItem = {
+    name: string;
+    facetName: string;
+    id: string;
+    value: FacetValue.Fragment;
+};
+
+@Component({
+    selector: 'vdr-facet-value-selector',
+    templateUrl: './facet-value-selector.component.html',
+    styleUrls: ['./facet-value-selector.component.scss'],
+    changeDetection: ChangeDetectionStrategy.OnPush,
+    providers: [
+        {
+            provide: NG_VALUE_ACCESSOR,
+            useExisting: FacetValueSelectorComponent,
+            multi: true,
+        },
+    ],
+})
+export class FacetValueSelectorComponent implements OnInit, ControlValueAccessor {
+    @Output() selectedValuesChange = new EventEmitter<FacetValue.Fragment[]>();
+    @Input() facets: FacetWithValues.Fragment[];
+
+    facetValues: FacetValueSeletorItem[] = [];
+    onChangeFn: (val: any) => void;
+    onTouchFn: () => void;
+    disabled = false;
+    value: string[];
+    constructor(private dataService: DataService) {}
+
+    ngOnInit() {
+        this.facetValues = flattenFacetValues(this.facets).map(this.toSelectorItem);
+    }
+
+    onChange(selected: FacetValueSeletorItem[]) {
+        this.selectedValuesChange.emit(selected.map(s => s.value));
+        if (this.onChangeFn) {
+            this.onChangeFn(JSON.stringify(selected.map(s => s.id)));
+        }
+    }
+
+    registerOnChange(fn: any) {
+        this.onChangeFn = fn;
+    }
+
+    registerOnTouched(fn: any) {
+        this.onTouchFn = fn;
+    }
+
+    setDisabledState(isDisabled: boolean): void {
+        this.disabled = isDisabled;
+    }
+
+    writeValue(obj: string | FacetValue.Fragment[] | null): void {
+        if (typeof obj === 'string') {
+            try {
+                const facetIds = JSON.parse(obj) as string[];
+                this.value = facetIds;
+            } catch (err) {
+                // TODO: log error
+                throw err;
+            }
+        } else if (obj) {
+            this.value = obj.map(fv => fv.id);
+        }
+    }
+
+    private toSelectorItem = (facetValue: FacetValue.Fragment): FacetValueSeletorItem => {
+        return {
+            name: facetValue.name,
+            facetName: facetValue.facet.name,
+            id: facetValue.id,
+            value: facetValue,
+        };
+    };
+}

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

@@ -23,6 +23,7 @@ import { CustomerLabelComponent } from './components/customer-label/customer-lab
 import { DataTableColumnComponent } from './components/data-table/data-table-column.component';
 import { DataTableComponent } from './components/data-table/data-table.component';
 import { FacetValueChipComponent } from './components/facet-value-chip/facet-value-chip.component';
+import { FacetValueSelectorComponent } from './components/facet-value-selector/facet-value-selector.component';
 import { FormFieldControlDirective } from './components/form-field/form-field-control.directive';
 import { FormFieldComponent } from './components/form-field/form-field.component';
 import { FormItemComponent } from './components/form-item/form-item.component';
@@ -66,6 +67,7 @@ const DECLARATIONS = [
     CustomFieldControlComponent,
     DataTableComponent,
     DataTableColumnComponent,
+    FacetValueSelectorComponent,
     ItemsPerPageControlsComponent,
     PaginationControlsComponent,
     TableRowActionComponent,