Browse Source

feat(admin-ui): Customer address editor opens in modal

Michael Bromley 5 years ago
parent
commit
0a4d460fba

+ 4 - 55
packages/admin-ui/src/lib/customer/src/components/address-card/address-card.component.html

@@ -17,63 +17,12 @@
     </div>
     <div class="card-block">
         <div class="card-text">
-            <vdr-formatted-address [address]="address" *ngIf="!editing"></vdr-formatted-address>
-            <form [formGroup]="addressForm" *ngIf="editing">
-                <clr-input-container>
-                    <label>{{ 'customer.full-name' | translate }}</label>
-                    <input formControlName="fullName" type="text" clrInput />
-                </clr-input-container>
-                <clr-input-container>
-                    <label>{{ 'customer.street-line-1' | translate }}</label>
-                    <input formControlName="streetLine1" type="text" clrInput />
-                </clr-input-container>
-                <clr-input-container>
-                    <label>{{ 'customer.street-line-2' | translate }}</label>
-                    <input formControlName="streetLine2" type="text" clrInput />
-                </clr-input-container>
-                <clr-input-container>
-                    <label>{{ 'customer.city' | translate }}</label>
-                    <input formControlName="city" type="text" clrInput />
-                </clr-input-container>
-                <clr-input-container>
-                    <label>{{ 'customer.province' | translate }}</label>
-                    <input formControlName="province" type="text" clrInput />
-                </clr-input-container>
-                <clr-input-container>
-                    <label>{{ 'customer.postal-code' | translate }}</label>
-                    <input formControlName="postalCode" type="text" clrInput />
-                </clr-input-container>
-                <clr-input-container>
-                    <label>{{ 'customer.country' | translate }}</label>
-                    <select name="countryCode" formControlName="countryCode" clrInput clrSelect>
-                        <option *ngFor="let country of availableCountries" [value]="country.code">
-                            {{ country.name }}
-                        </option>
-                    </select>
-                </clr-input-container>
-                <clr-input-container>
-                    <label>{{ 'customer.phone-number' | translate }}</label>
-                    <input formControlName="phoneNumber" type="text" clrInput />
-                </clr-input-container>
-                <section formGroupName="customFields" *ngIf="addressForm.get('customFields') as customFieldsGroup">
-                    <label>{{ 'common.custom-fields' | translate }}</label>
-                    <ng-container *ngFor="let customField of customFields">
-                        <vdr-custom-field-control
-                            entityName="Facet"
-                            [customFieldsFormGroup]="customFieldsGroup"
-                            [customField]="customField"
-                        ></vdr-custom-field-control>
-                    </ng-container>
-                </section>
-            </form>
+            <vdr-formatted-address [address]="address"></vdr-formatted-address>
         </div>
     </div>
     <div class="card-footer">
         <vdr-entity-info [entity]="address"></vdr-entity-info>
-        <button class="btn btn-sm btn-link" *ngIf="editing" (click)="editing = false">
-            {{ 'common.done' | translate }}
-        </button>
-        <button class="btn btn-sm btn-link" *ngIf="!editing" (click)="editing = true">
+        <button class="btn btn-sm btn-link" (click)="editAddress()">
             {{ 'common.edit' | translate }}
         </button>
         <vdr-dropdown>
@@ -85,7 +34,7 @@
                 <button
                     vdrDropdownItem
                     class="button"
-                    [disabled]="isDefaultShipping || editing"
+                    [disabled]="isDefaultShipping"
                     (click)="setAsDefaultShippingAddress()"
                 >
                     {{ 'customer.set-as-default-shipping-address' | translate }}
@@ -93,7 +42,7 @@
                 <button
                     vdrDropdownItem
                     class="button"
-                    [disabled]="isDefaultBilling || editing"
+                    [disabled]="isDefaultBilling"
                     (click)="setAsDefaultBillingAddress()"
                 >
                     {{ 'customer.set-as-default-billing-address' | translate }}

+ 31 - 4
packages/admin-ui/src/lib/customer/src/components/address-card/address-card.component.ts

@@ -1,6 +1,16 @@
-import { ChangeDetectionStrategy, Component, EventEmitter, Input, OnInit, Output } from '@angular/core';
+import {
+    ChangeDetectionStrategy,
+    ChangeDetectorRef,
+    Component,
+    EventEmitter,
+    Input,
+    OnInit,
+    Output,
+} from '@angular/core';
 import { FormControl, FormGroup } from '@angular/forms';
-import { CustomFieldConfig, GetAvailableCountries } from '@vendure/admin-ui/core';
+import { CustomFieldConfig, GetAvailableCountries, ModalService } from '@vendure/admin-ui/core';
+
+import { AddressDetailDialogComponent } from '../address-detail-dialog/address-detail-dialog.component';
 
 @Component({
     selector: 'vdr-address-card',
@@ -9,7 +19,6 @@ import { CustomFieldConfig, GetAvailableCountries } from '@vendure/admin-ui/core
     changeDetection: ChangeDetectionStrategy.OnPush,
 })
 export class AddressCardComponent implements OnInit {
-    editing = false;
     @Input() addressForm: FormGroup;
     @Input() customFields: CustomFieldConfig;
     @Input() availableCountries: GetAvailableCountries.Items[] = [];
@@ -18,10 +27,12 @@ export class AddressCardComponent implements OnInit {
     @Output() setAsDefaultShipping = new EventEmitter<string>();
     @Output() setAsDefaultBilling = new EventEmitter<string>();
 
+    constructor(private modalService: ModalService, private changeDetector: ChangeDetectorRef) {}
+
     ngOnInit(): void {
         const streetLine1 = this.addressForm.get('streetLine1') as FormControl;
         if (!streetLine1.value) {
-            this.editing = true;
+            this.editAddress();
         }
     }
 
@@ -42,4 +53,20 @@ export class AddressCardComponent implements OnInit {
         this.setAsDefaultShipping.emit(this.addressForm.value.id);
         this.addressForm.markAsDirty();
     }
+
+    editAddress() {
+        this.modalService
+            .fromComponent(AddressDetailDialogComponent, {
+                locals: {
+                    addressForm: this.addressForm,
+                    customFields: this.customFields,
+                    availableCountries: this.availableCountries,
+                },
+                size: 'md',
+                closable: true,
+            })
+            .subscribe(() => {
+                this.changeDetector.markForCheck();
+            });
+    }
 }

+ 84 - 0
packages/admin-ui/src/lib/customer/src/components/address-detail-dialog/address-detail-dialog.component.html

@@ -0,0 +1,84 @@
+<ng-template vdrDialogTitle>
+    <span *ngIf="addressForm.get('streetLine1')?.value as streetLine1">{{ streetLine1 }},</span>
+    <span *ngIf="addressForm.get('countryCode')?.value as countryCode"> {{ countryCode }}</span>
+</ng-template>
+
+<form [formGroup]="addressForm">
+    <clr-input-container>
+        <label>{{ 'customer.full-name' | translate }}</label>
+        <input formControlName="fullName" type="text" clrInput />
+    </clr-input-container>
+
+    <div class="clr-row">
+        <div class="clr-col-md-4">
+            <clr-input-container>
+                <label>{{ 'customer.street-line-1' | translate }}</label>
+                <input formControlName="streetLine1" type="text" clrInput />
+            </clr-input-container>
+        </div>
+        <div class="clr-col-md-4">
+            <clr-input-container>
+                <label>{{ 'customer.street-line-2' | translate }}</label>
+                <input formControlName="streetLine2" type="text" clrInput />
+            </clr-input-container>
+        </div>
+    </div>
+    <div class="clr-row">
+        <div class="clr-col-md-4">
+            <clr-input-container>
+                <label>{{ 'customer.city' | translate }}</label>
+                <input formControlName="city" type="text" clrInput />
+            </clr-input-container>
+        </div>
+        <div class="clr-col-md-4">
+            <clr-input-container>
+                <label>{{ 'customer.province' | translate }}</label>
+                <input formControlName="province" type="text" clrInput />
+            </clr-input-container>
+        </div>
+    </div>
+    <div class="clr-row">
+        <div class="clr-col-md-4">
+            <clr-input-container>
+                <label>{{ 'customer.postal-code' | translate }}</label>
+                <input formControlName="postalCode" type="text" clrInput />
+            </clr-input-container>
+        </div>
+        <div class="clr-col-md-4">
+            <clr-input-container>
+                <label>{{ 'customer.country' | translate }}</label>
+                <select name="countryCode" formControlName="countryCode" clrInput clrSelect>
+                    <option *ngFor="let country of availableCountries" [value]="country.code">
+                        {{ country.name }}
+                    </option>
+                </select>
+            </clr-input-container>
+        </div>
+    </div>
+    <clr-input-container>
+        <label>{{ 'customer.phone-number' | translate }}</label>
+        <input formControlName="phoneNumber" type="text" clrInput />
+    </clr-input-container>
+    <section formGroupName="customFields" *ngIf="addressForm.get('customFields') as customFieldsGroup">
+        <label>{{ 'common.custom-fields' | translate }}</label>
+        <ng-container *ngFor="let customField of customFields">
+            <vdr-custom-field-control
+                entityName="Facet"
+                [customFieldsFormGroup]="customFieldsGroup"
+                [customField]="customField"
+            ></vdr-custom-field-control>
+        </ng-container>
+    </section>
+</form>
+
+<ng-template vdrDialogButtons>
+    <button type="button" class="btn" (click)="cancel()">{{ 'common.cancel' | translate }}</button>
+    <button
+        type="submit"
+        (click)="save()"
+        [disabled]="!addressForm.valid || !addressForm.touched"
+        class="btn btn-primary"
+    >
+        {{ 'common.update' | translate }}
+    </button>
+</ng-template>

+ 5 - 0
packages/admin-ui/src/lib/customer/src/components/address-detail-dialog/address-detail-dialog.component.scss

@@ -0,0 +1,5 @@
+@import "variables";
+
+clr-input-container {
+    margin-bottom: 12px;
+}

+ 30 - 0
packages/admin-ui/src/lib/customer/src/components/address-detail-dialog/address-detail-dialog.component.ts

@@ -0,0 +1,30 @@
+import { ChangeDetectionStrategy, ChangeDetectorRef, Component, OnInit } from '@angular/core';
+import { FormGroup } from '@angular/forms';
+import { CustomFieldConfig, Dialog, GetAvailableCountries } from '@vendure/admin-ui/core';
+
+@Component({
+    selector: 'vdr-address-detail-dialog',
+    templateUrl: './address-detail-dialog.component.html',
+    styleUrls: ['./address-detail-dialog.component.scss'],
+    changeDetection: ChangeDetectionStrategy.OnPush,
+})
+export class AddressDetailDialogComponent implements Dialog<FormGroup>, OnInit {
+    addressForm: FormGroup;
+    customFields: CustomFieldConfig;
+    availableCountries: GetAvailableCountries.Items[] = [];
+    resolveWith: (result?: FormGroup) => void;
+
+    constructor(private changeDetector: ChangeDetectorRef) {}
+
+    ngOnInit() {
+        this.addressForm.valueChanges.subscribe(() => this.changeDetector.markForCheck());
+    }
+
+    cancel() {
+        this.resolveWith();
+    }
+
+    save() {
+        this.resolveWith(this.addressForm);
+    }
+}

+ 2 - 0
packages/admin-ui/src/lib/customer/src/customer.module.ts

@@ -4,6 +4,7 @@ import { SharedModule } from '@vendure/admin-ui/core';
 
 import { AddCustomerToGroupDialogComponent } from './components/add-customer-to-group-dialog/add-customer-to-group-dialog.component';
 import { AddressCardComponent } from './components/address-card/address-card.component';
+import { AddressDetailDialogComponent } from './components/address-detail-dialog/address-detail-dialog.component';
 import { CustomerDetailComponent } from './components/customer-detail/customer-detail.component';
 import { CustomerGroupDetailDialogComponent } from './components/customer-group-detail-dialog/customer-group-detail-dialog.component';
 import { CustomerGroupListComponent } from './components/customer-group-list/customer-group-list.component';
@@ -27,6 +28,7 @@ import { customerRoutes } from './customer.routes';
         CustomerGroupMemberListComponent,
         SelectCustomerGroupDialogComponent,
         CustomerHistoryComponent,
+        AddressDetailDialogComponent,
     ],
     exports: [AddressCardComponent],
 })