Просмотр исходного кода

feat(admin-ui): PaymentMethod list/detail components

Relates to #36
Michael Bromley 7 лет назад
Родитель
Сommit
fb6ca746d3

+ 7 - 0
admin-ui/src/app/core/components/main-nav/main-nav.component.html

@@ -102,6 +102,13 @@
                         <clr-icon shape="truck" size="20"></clr-icon>{{ 'nav.shipping-methods' | translate }}
                     </a>
                 </li>
+                <li>
+                    <a class="nav-link"
+                       [routerLink]="['/settings', 'payment-methods']"
+                       routerLinkActive="active">
+                        <clr-icon shape="credit-card" size="20"></clr-icon>{{ 'nav.payment-methods' | translate }}
+                    </a>
+                </li>
                 <li>
                     <a class="nav-link"
                        [routerLink]="['/settings', 'tax-categories']"

+ 43 - 0
admin-ui/src/app/data/definitions/settings-definitions.ts

@@ -283,3 +283,46 @@ export const UPDATE_CHANNEL = gql`
     }
     ${CHANNEL_FRAGMENT}
 `;
+
+export const PAYMENT_METHOD_FRAGMENT = gql`
+    fragment PaymentMethod on PaymentMethod {
+        id
+        code
+        enabled
+        configArgs {
+            name
+            type
+            value
+        }
+    }
+`;
+
+export const GET_PAYMENT_METHOD_LIST = gql`
+    query GetPaymentMethodList($options: PaymentMethodListOptions!) {
+        paymentMethods(options: $options) {
+            items {
+                ...PaymentMethod
+            }
+            totalItems
+        }
+    }
+    ${PAYMENT_METHOD_FRAGMENT}
+`;
+
+export const GET_PAYMENT_METHOD = gql`
+    query GetPaymentMethod($id: ID!) {
+        paymentMethod(id: $id) {
+            ...PaymentMethod
+        }
+    }
+    ${PAYMENT_METHOD_FRAGMENT}
+`;
+
+export const UPDATE_PAYMENT_METHOD = gql`
+    mutation UpdatePaymentMethod($input: UpdatePaymentMethodInput!) {
+        updatePaymentMethod(input: $input) {
+            ...PaymentMethod
+        }
+    }
+    ${PAYMENT_METHOD_FRAGMENT}
+`;

+ 37 - 0
admin-ui/src/app/data/providers/settings-data.service.ts

@@ -15,6 +15,8 @@ import {
     GetChannels,
     GetCountry,
     GetCountryList,
+    GetPaymentMethod,
+    GetPaymentMethodList,
     GetTaxCategories,
     GetTaxCategory,
     GetTaxRate,
@@ -26,6 +28,8 @@ import {
     UpdateChannelInput,
     UpdateCountry,
     UpdateCountryInput,
+    UpdatePaymentMethod,
+    UpdatePaymentMethodInput,
     UpdateTaxCategory,
     UpdateTaxCategoryInput,
     UpdateTaxRate,
@@ -47,6 +51,8 @@ import {
     GET_CHANNELS,
     GET_COUNTRY,
     GET_COUNTRY_LIST,
+    GET_PAYMENT_METHOD,
+    GET_PAYMENT_METHOD_LIST,
     GET_TAX_CATEGORIES,
     GET_TAX_CATEGORY,
     GET_TAX_RATE,
@@ -55,6 +61,7 @@ import {
     REMOVE_MEMBERS_FROM_ZONE,
     UPDATE_CHANNEL,
     UPDATE_COUNTRY,
+    UPDATE_PAYMENT_METHOD,
     UPDATE_TAX_CATEGORY,
     UPDATE_TAX_RATE,
     UPDATE_ZONE,
@@ -212,4 +219,34 @@ export class SettingsDataService {
             input,
         });
     }
+
+    getPaymentMethods(take: number = 10, skip: number = 0) {
+        return this.baseDataService.query<GetPaymentMethodList.Query, GetPaymentMethodList.Variables>(
+            GET_PAYMENT_METHOD_LIST,
+            {
+                options: {
+                    skip,
+                    take,
+                },
+            },
+        );
+    }
+
+    getPaymentMethod(id: string) {
+        return this.baseDataService.query<GetPaymentMethod.Query, GetPaymentMethod.Variables>(
+            GET_PAYMENT_METHOD,
+            {
+                id,
+            },
+        );
+    }
+
+    updatePaymentMethod(input: UpdatePaymentMethodInput) {
+        return this.baseDataService.mutate<UpdatePaymentMethod.Mutation, UpdatePaymentMethod.Variables>(
+            UPDATE_PAYMENT_METHOD,
+            {
+                input,
+            },
+        );
+    }
 }

+ 52 - 0
admin-ui/src/app/settings/components/payment-method-detail/payment-method-detail.component.html

@@ -0,0 +1,52 @@
+<vdr-action-bar>
+    <vdr-ab-left>
+    </vdr-ab-left>
+
+    <vdr-ab-right>
+        <button class="btn btn-primary"
+                *ngIf="isNew$ | async; else updateButton"
+                (click)="create()"
+                [disabled]="paymentMethodForm.pristine || paymentMethodForm.invalid">{{ 'common.create' | translate }}</button>
+        <ng-template #updateButton>
+            <button class="btn btn-primary"
+                    (click)="save()"
+                    [disabled]="paymentMethodForm.pristine || paymentMethodForm.invalid">{{ 'common.update' | translate }}</button>
+        </ng-template>
+    </vdr-ab-right>
+</vdr-action-bar>
+
+<form class="form" [formGroup]="paymentMethodForm" >
+    <section class="form-block">
+        <vdr-form-field [label]="'common.code' | translate" for="code">
+            <input id="code" type="text" formControlName="code">
+        </vdr-form-field>
+    </section>
+    <section class="form-block">
+        <vdr-form-field [label]="'common.enabled' | translate" for="description">
+            <div class="toggle-switch">
+                <input type="checkbox" id="enabled" formControlName="enabled">
+                <label for="enabled"></label>
+            </div>
+        </vdr-form-field>
+    </section>
+
+    <div class="clr-row" formGroupName="configArgs" *ngIf="(entity$ | async).configArgs?.length">
+        <div class="clr-col">
+            <label>{{ 'settings.payment-method-config-options' | translate }}</label>
+            <section class="form-block" *ngFor="let arg of (entity$ | async).configArgs">
+                <vdr-form-field [label]="arg.name" [for]="arg.name" *ngIf="arg.type === 'string'">
+                    <input [id]="arg.name" type="text" [formControlName]="arg.name" >
+                </vdr-form-field>
+                <vdr-form-field [label]="arg.name" [for]="arg.name" *ngIf="arg.type === 'int'">
+                    <input [id]="arg.name" type="number" [formControlName]="arg.name" >
+                </vdr-form-field>
+                <vdr-form-field [label]="arg.name" [for]="arg.name" *ngIf="arg.type === 'boolean'">
+                    <div class="toggle-switch" *ngIf="arg.type === 'boolean'">
+                        <input type="checkbox" [id]="arg.name" [formControlName]="arg.name">
+                        <label [for]="arg.name"></label>
+                    </div>
+                </vdr-form-field>
+            </section>
+        </div>
+    </div>
+</form>

+ 0 - 0
admin-ui/src/app/settings/components/payment-method-detail/payment-method-detail.component.scss


+ 116 - 0
admin-ui/src/app/settings/components/payment-method-detail/payment-method-detail.component.ts

@@ -0,0 +1,116 @@
+import { ChangeDetectionStrategy, ChangeDetectorRef, Component, OnDestroy, OnInit } from '@angular/core';
+import { FormArray, FormBuilder, FormGroup, Validators } from '@angular/forms';
+import { ActivatedRoute, Router } from '@angular/router';
+import { mergeMap, take } from 'rxjs/operators';
+import {
+    AdjustmentOperation,
+    AdjustmentOperationInput,
+    ConfigArg,
+    PaymentMethod,
+    UpdatePaymentMethodInput,
+} from 'shared/generated-types';
+
+import { BaseDetailComponent } from '../../../common/base-detail.component';
+import { _ } from '../../../core/providers/i18n/mark-for-extraction';
+import { NotificationService } from '../../../core/providers/notification/notification.service';
+import { DataService } from '../../../data/providers/data.service';
+import { ServerConfigService } from '../../../data/server-config';
+
+@Component({
+    selector: 'vdr-payment-method-detail',
+    templateUrl: './payment-method-detail.component.html',
+    styleUrls: ['./payment-method-detail.component.scss'],
+    changeDetection: ChangeDetectionStrategy.OnPush,
+})
+export class PaymentMethodDetailComponent extends BaseDetailComponent<PaymentMethod.Fragment>
+    implements OnInit, OnDestroy {
+    paymentMethodForm: FormGroup;
+
+    constructor(
+        router: Router,
+        route: ActivatedRoute,
+        serverConfigService: ServerConfigService,
+        private changeDetector: ChangeDetectorRef,
+        private dataService: DataService,
+        private formBuilder: FormBuilder,
+        private notificationService: NotificationService,
+    ) {
+        super(route, router, serverConfigService);
+        this.paymentMethodForm = this.formBuilder.group({
+            code: ['', Validators.required],
+            enabled: [true, Validators.required],
+            configArgs: this.formBuilder.group({}),
+        });
+    }
+
+    ngOnInit() {
+        this.init();
+    }
+
+    ngOnDestroy(): void {
+        this.destroy();
+    }
+
+    save() {
+        this.entity$
+            .pipe(
+                take(1),
+                mergeMap(({ id }) => {
+                    const formValue = this.paymentMethodForm.value;
+                    const input: UpdatePaymentMethodInput = {
+                        id,
+                        code: formValue.code,
+                        enabled: formValue.enabled,
+                        configArgs: Object.entries(formValue.configArgs).map(([name, value]) => ({
+                            name,
+                            value: value.toString(),
+                        })),
+                    };
+                    return this.dataService.settings.updatePaymentMethod(input);
+                }),
+            )
+            .subscribe(
+                data => {
+                    this.notificationService.success(_('common.notify-update-success'), {
+                        entity: 'PaymentMethod',
+                    });
+                    this.paymentMethodForm.markAsPristine();
+                    this.changeDetector.markForCheck();
+                },
+                err => {
+                    this.notificationService.error(_('common.notify-update-error'), {
+                        entity: 'PaymentMethod',
+                    });
+                },
+            );
+    }
+
+    protected setFormValues(paymentMethod: PaymentMethod.Fragment): void {
+        this.paymentMethodForm.patchValue({
+            code: paymentMethod.code,
+            enabled: paymentMethod.enabled,
+        });
+        const configArgsGroup = this.paymentMethodForm.get('configArgs') as FormGroup;
+        if (configArgsGroup) {
+            for (const arg of paymentMethod.configArgs) {
+                const control = configArgsGroup.get(arg.name);
+                if (control) {
+                    control.patchValue(this.parseArgValue(arg));
+                } else {
+                    configArgsGroup.addControl(arg.name, this.formBuilder.control(this.parseArgValue(arg)));
+                }
+            }
+        }
+    }
+
+    private parseArgValue(arg: ConfigArg): string | number | boolean {
+        switch (arg.type) {
+            case 'int':
+                return Number.parseInt(arg.value || '0', 10);
+            case 'boolean':
+                return arg.value === 'false' ? false : true;
+            default:
+                return arg.value || '';
+        }
+    }
+}

+ 25 - 0
admin-ui/src/app/settings/components/payment-method-list/payment-method-list.component.html

@@ -0,0 +1,25 @@
+<vdr-action-bar>
+    <vdr-ab-right>
+    </vdr-ab-right>
+</vdr-action-bar>
+
+<vdr-data-table [items]="items$ | async"
+                [itemsPerPage]="itemsPerPage$ | async"
+                [totalItems]="totalItems$ | async"
+                [currentPage]="currentPage$ | async"
+                (pageChange)="setPageNumber($event)"
+                (itemsPerPageChange)="setItemsPerPage($event)">
+    <vdr-dt-column>{{ 'common.code' | translate }}</vdr-dt-column>
+    <vdr-dt-column>{{ 'common.enabled' | translate }}</vdr-dt-column>
+    <vdr-dt-column></vdr-dt-column>
+    <ng-template let-paymentMethod="item">
+        <td class="left">{{ paymentMethod.code }}</td>
+        <td class="left">{{ paymentMethod.enabled }}</td>
+        <td class="right">
+            <vdr-table-row-action iconShape="edit"
+                                  [label]="'common.edit' | translate"
+                                  [linkTo]="['./', paymentMethod.id]">
+            </vdr-table-row-action>
+        </td>
+    </ng-template>
+</vdr-data-table>

+ 0 - 0
admin-ui/src/app/settings/components/payment-method-list/payment-method-list.component.scss


+ 25 - 0
admin-ui/src/app/settings/components/payment-method-list/payment-method-list.component.ts

@@ -0,0 +1,25 @@
+import { ChangeDetectionStrategy, Component } from '@angular/core';
+import { ActivatedRoute, Router } from '@angular/router';
+import { GetPaymentMethodList } from 'shared/generated-types';
+
+import { BaseListComponent } from '../../../common/base-list.component';
+import { DataService } from '../../../data/providers/data.service';
+
+@Component({
+    selector: 'vdr-payment-method-list',
+    templateUrl: './payment-method-list.component.html',
+    styleUrls: ['./payment-method-list.component.scss'],
+    changeDetection: ChangeDetectionStrategy.OnPush,
+})
+export class PaymentMethodListComponent extends BaseListComponent<
+    GetPaymentMethodList.Query,
+    GetPaymentMethodList.Items
+> {
+    constructor(private dataService: DataService, router: Router, route: ActivatedRoute) {
+        super(router, route);
+        super.setQueryFn(
+            (...args: any[]) => this.dataService.settings.getPaymentMethods(...args),
+            data => data.paymentMethods,
+        );
+    }
+}

+ 24 - 0
admin-ui/src/app/settings/providers/routing/payment-method-resolver.ts

@@ -0,0 +1,24 @@
+import { Injectable } from '@angular/core';
+import { PaymentMethod } from 'shared/generated-types';
+
+import { BaseEntityResolver } from '../../../common/base-entity-resolver';
+import { DataService } from '../../../data/providers/data.service';
+
+/**
+ * Resolves the id from the path into a Customer entity.
+ */
+@Injectable()
+export class PaymentMethodResolver extends BaseEntityResolver<PaymentMethod.Fragment> {
+    constructor(private dataService: DataService) {
+        super(
+            {
+                __typename: 'PaymentMethod',
+                id: '',
+                code: '',
+                enabled: true,
+                configArgs: [],
+            },
+            id => this.dataService.settings.getPaymentMethod(id).mapStream(data => data.paymentMethod),
+        );
+    }
+}

+ 6 - 0
admin-ui/src/app/settings/settings.module.ts

@@ -9,6 +9,8 @@ import { ChannelDetailComponent } from './components/channel-detail/channel-deta
 import { ChannelListComponent } from './components/channel-list/channel-list.component';
 import { CountryDetailComponent } from './components/country-detail/country-detail.component';
 import { CountryListComponent } from './components/country-list/country-list.component';
+import { PaymentMethodDetailComponent } from './components/payment-method-detail/payment-method-detail.component';
+import { PaymentMethodListComponent } from './components/payment-method-list/payment-method-list.component';
 import { PermissionGridComponent } from './components/permission-grid/permission-grid.component';
 import { RoleDetailComponent } from './components/role-detail/role-detail.component';
 import { RoleListComponent } from './components/role-list/role-list.component';
@@ -22,6 +24,7 @@ import { ZoneSelectorDialogComponent } from './components/zone-selector-dialog/z
 import { AdministratorResolver } from './providers/routing/administrator-resolver';
 import { ChannelResolver } from './providers/routing/channel-resolver';
 import { CountryResolver } from './providers/routing/country-resolver';
+import { PaymentMethodResolver } from './providers/routing/payment-method-resolver';
 import { RoleResolver } from './providers/routing/role-resolver';
 import { ShippingMethodResolver } from './providers/routing/shipping-method-resolver';
 import { TaxCategoryResolver } from './providers/routing/tax-category-resolver';
@@ -47,6 +50,8 @@ import { settingsRoutes } from './settings.routes';
         ChannelDetailComponent,
         ShippingMethodListComponent,
         ShippingMethodDetailComponent,
+        PaymentMethodListComponent,
+        PaymentMethodDetailComponent,
     ],
     entryComponents: [ZoneSelectorDialogComponent],
     providers: [
@@ -57,6 +62,7 @@ import { settingsRoutes } from './settings.routes';
         TaxRateResolver,
         ChannelResolver,
         ShippingMethodResolver,
+        PaymentMethodResolver,
     ],
 })
 export class SettingsModule {}

+ 28 - 0
admin-ui/src/app/settings/settings.routes.ts

@@ -19,6 +19,8 @@ import { ChannelDetailComponent } from './components/channel-detail/channel-deta
 import { ChannelListComponent } from './components/channel-list/channel-list.component';
 import { CountryDetailComponent } from './components/country-detail/country-detail.component';
 import { CountryListComponent } from './components/country-list/country-list.component';
+import { PaymentMethodDetailComponent } from './components/payment-method-detail/payment-method-detail.component';
+import { PaymentMethodListComponent } from './components/payment-method-list/payment-method-list.component';
 import { RoleDetailComponent } from './components/role-detail/role-detail.component';
 import { RoleListComponent } from './components/role-list/role-list.component';
 import { ShippingMethodDetailComponent } from './components/shipping-method-detail/shipping-method-detail.component';
@@ -30,6 +32,7 @@ import { TaxRateListComponent } from './components/tax-rate-list/tax-rate-list.c
 import { AdministratorResolver } from './providers/routing/administrator-resolver';
 import { ChannelResolver } from './providers/routing/channel-resolver';
 import { CountryResolver } from './providers/routing/country-resolver';
+import { PaymentMethodResolver } from './providers/routing/payment-method-resolver';
 import { RoleResolver } from './providers/routing/role-resolver';
 import { ShippingMethodResolver } from './providers/routing/shipping-method-resolver';
 import { TaxCategoryResolver } from './providers/routing/tax-category-resolver';
@@ -135,6 +138,21 @@ export const settingsRoutes: Route[] = [
             breadcrumb: shippingMethodBreadcrumb,
         },
     },
+    {
+        path: 'payment-methods',
+        component: PaymentMethodListComponent,
+        data: {
+            breadcrumb: _('breadcrumb.payment-methods'),
+        },
+    },
+    {
+        path: 'payment-methods/:id',
+        component: PaymentMethodDetailComponent,
+        resolve: createResolveData(PaymentMethodResolver),
+        data: {
+            breadcrumb: paymentMethodBreadcrumb,
+        },
+    },
 ];
 
 export function administratorBreadcrumb(data: any, params: any) {
@@ -206,3 +224,13 @@ export function shippingMethodBreadcrumb(data: any, params: any) {
         route: 'shipping-methods',
     });
 }
+
+export function paymentMethodBreadcrumb(data: any, params: any) {
+    return detailBreadcrumb<ShippingMethod.Fragment>({
+        entity: data.entity,
+        id: params.id,
+        breadcrumbKey: 'breadcrumb.payment-methods',
+        getName: method => method.code,
+        route: 'payment-methods',
+    });
+}

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

@@ -11,6 +11,7 @@
     "dashboard": "Dashboard",
     "facets": "Facets",
     "orders": "Orders",
+    "payment-methods": "Payment methods",
     "products": "Products",
     "promotions": "Promotions",
     "roles": "Roles",
@@ -140,6 +141,7 @@
     "facets": "Facets",
     "marketing": "Marketing",
     "orders": "Orders",
+    "payment-methods": "Payment methods",
     "products": "Products",
     "promotions": "Promotions",
     "roles": "Roles",
@@ -185,6 +187,7 @@
     "last-name": "Last name",
     "order": "Order",
     "password": "Password",
+    "payment-method-config-options": "Payment method configuration",
     "permissions": "Permissions",
     "prices-include-tax": "Prices include tax for the default Zone",
     "rate": "Rate",

+ 62 - 0
shared/generated-types.ts

@@ -5449,6 +5449,51 @@ export namespace UpdateChannel {
     export type UpdateChannel = Channel.Fragment;
 }
 
+export namespace GetPaymentMethodList {
+    export type Variables = {
+        options: PaymentMethodListOptions;
+    };
+
+    export type Query = {
+        __typename?: 'Query';
+        paymentMethods: PaymentMethods;
+    };
+
+    export type PaymentMethods = {
+        __typename?: 'PaymentMethodList';
+        items: Items[];
+        totalItems: number;
+    };
+
+    export type Items = PaymentMethod.Fragment;
+}
+
+export namespace GetPaymentMethod {
+    export type Variables = {
+        id: string;
+    };
+
+    export type Query = {
+        __typename?: 'Query';
+        paymentMethod?: PaymentMethod | null;
+    };
+
+    export type PaymentMethod = PaymentMethod.Fragment;
+}
+
+export namespace UpdatePaymentMethod {
+    export type Variables = {
+        input: UpdatePaymentMethodInput;
+    };
+
+    export type Mutation = {
+        __typename?: 'Mutation';
+        updatePaymentMethod: UpdatePaymentMethod;
+    };
+
+    export type UpdatePaymentMethod = PaymentMethod.Fragment;
+}
+
 export namespace GetShippingMethodList {
     export type Variables = {
         options?: ShippingMethodListOptions | null;
@@ -6025,6 +6070,23 @@ export namespace Channel {
     };
 }
 
+export namespace PaymentMethod {
+    export type Fragment = {
+        __typename?: 'PaymentMethod';
+        id: string;
+        code: string;
+        enabled: boolean;
+        configArgs: ConfigArgs[];
+    };
+
+    export type ConfigArgs = {
+        __typename?: 'ConfigArg';
+        name: string;
+        type: string;
+        value?: string | null;
+    };
+}
+
 export namespace ShippingMethod {
     export type Fragment = {
         __typename?: 'ShippingMethod';