Skip to content

Commit

Permalink
feat(admin-ui): Handle Fulfillments state from Order detail view
Browse files Browse the repository at this point in the history
Relates to #426
  • Loading branch information
michaelbromley committed Sep 15, 2020
1 parent 8232ddc commit 7883a7a
Show file tree
Hide file tree
Showing 28 changed files with 350 additions and 77 deletions.
44 changes: 22 additions & 22 deletions packages/admin-ui/i18n-coverage.json
Original file line number Diff line number Diff line change
@@ -1,41 +1,41 @@
{
"generatedOn": "2020-08-26T08:49:50.552Z",
"lastCommit": "8881aee83b25f57edba537fbdcb85c77bf5f3c4e",
"generatedOn": "2020-09-15T15:16:07.529Z",
"lastCommit": "8232ddce0b03f8f1b30e8d02563d5fe2d5f5ebe8",
"translationStatus": {
"de": {
"tokenCount": 662,
"translatedCount": 610,
"percentage": 92
"tokenCount": 670,
"translatedCount": 609,
"percentage": 91
},
"en": {
"tokenCount": 662,
"translatedCount": 662,
"tokenCount": 670,
"translatedCount": 669,
"percentage": 100
},
"es": {
"tokenCount": 662,
"translatedCount": 467,
"percentage": 71
"tokenCount": 670,
"translatedCount": 466,
"percentage": 70
},
"pl": {
"tokenCount": 662,
"translatedCount": 566,
"percentage": 85
"tokenCount": 669,
"translatedCount": 564,
"percentage": 84
},
"pt_BR": {
"tokenCount": 662,
"translatedCount": 657,
"percentage": 99
"tokenCount": 669,
"translatedCount": 655,
"percentage": 98
},
"zh_Hans": {
"tokenCount": 662,
"translatedCount": 550,
"percentage": 83
"tokenCount": 669,
"translatedCount": 548,
"percentage": 82
},
"zh_Hant": {
"tokenCount": 662,
"translatedCount": 550,
"percentage": 83
"tokenCount": 669,
"translatedCount": 548,
"percentage": 82
}
}
}
22 changes: 21 additions & 1 deletion packages/admin-ui/src/lib/core/src/common/generated-types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4841,7 +4841,7 @@ export type OrderFragment = (

export type FulfillmentFragment = (
{ __typename?: 'Fulfillment' }
& Pick<Fulfillment, 'id' | 'createdAt' | 'updatedAt' | 'method' | 'trackingCode'>
& Pick<Fulfillment, 'id' | 'state' | 'nextStates' | 'createdAt' | 'updatedAt' | 'method' | 'trackingCode'>
);

export type OrderLineFragment = (
Expand Down Expand Up @@ -5094,6 +5094,20 @@ export type UpdateOrderCustomFieldsMutation = (
)> }
);

export type TransitionFulfillmentToStateMutationVariables = {
id: Scalars['ID'];
state: Scalars['String'];
};


export type TransitionFulfillmentToStateMutation = (
{ __typename?: 'Mutation' }
& { transitionFulfillmentToState: (
{ __typename?: 'Fulfillment' }
& FulfillmentFragment
) }
);

export type AssetFragment = (
{ __typename?: 'Asset' }
& Pick<Asset, 'id' | 'createdAt' | 'updatedAt' | 'name' | 'fileSize' | 'mimeType' | 'type' | 'preview' | 'source' | 'width' | 'height'>
Expand Down Expand Up @@ -7452,6 +7466,12 @@ export namespace UpdateOrderCustomFields {
export type SetOrderCustomFields = OrderFragment;
}

export namespace TransitionFulfillmentToState {
export type Variables = TransitionFulfillmentToStateMutationVariables;
export type Mutation = TransitionFulfillmentToStateMutation;
export type TransitionFulfillmentToState = FulfillmentFragment;
}

export namespace Asset {
export type Fragment = AssetFragment;
export type FocalPoint = (NonNullable<AssetFragment['focalPoint']>);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,8 @@ export const ORDER_FRAGMENT = gql`
export const FULFILLMENT_FRAGMENT = gql`
fragment Fulfillment on Fulfillment {
id
state
nextStates
createdAt
updatedAt
method
Expand Down Expand Up @@ -310,3 +312,12 @@ export const UPDATE_ORDER_CUSTOM_FIELDS = gql`
}
${ORDER_FRAGMENT}
`;

export const TRANSITION_FULFILLMENT_TO_STATE = gql`
mutation TransitionFulfillmentToState($id: ID!, $state: String!) {
transitionFulfillmentToState(id: $id, state: $state) {
...Fulfillment
}
}
${FULFILLMENT_FRAGMENT}
`;
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import {
SettlePayment,
SettleRefund,
SettleRefundInput,
TransitionFulfillmentToState,
TransitionOrderToState,
UpdateOrderCustomFields,
UpdateOrderInput,
Expand All @@ -32,6 +33,7 @@ import {
REFUND_ORDER,
SETTLE_PAYMENT,
SETTLE_REFUND,
TRANSITION_FULFILLMENT_TO_STATE,
TRANSITION_ORDER_TO_STATE,
UPDATE_ORDER_CUSTOM_FIELDS,
UPDATE_ORDER_NOTE,
Expand Down Expand Up @@ -80,6 +82,16 @@ export class OrderDataService {
);
}

transitionFulfillmentToState(id: string, state: string) {
return this.baseDataService.mutate<
TransitionFulfillmentToState.Mutation,
TransitionFulfillmentToState.Variables
>(TRANSITION_FULFILLMENT_TO_STATE, {
id,
state,
});
}

cancelOrder(input: CancelOrderInput) {
return this.baseDataService.mutate<CancelOrder.Mutation, CancelOrder.Variables>(CANCEL_ORDER, {
input,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ export class OrderStateLabelComponent {
case 'PaymentAuthorized':
case 'PaymentSettled':
case 'PartiallyDelivered':
case 'PartiallyShipped':
case 'Shipped':
return 'warning';
case 'Delivered':
return 'success';
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ export class OrderStateI18nTokenPipe implements PipeTransform {
ArrangingPayment: _('order.state-arranging-payment'),
PaymentAuthorized: _('order.state-payment-authorized'),
PaymentSettled: _('order.state-payment-settled'),
PartiallyShipped: _('order.state-partially-shipped'),
Shipped: _('order.state-shipped'),
PartiallyDelivered: _('order.state-partially-delivered'),
Delivered: _('order.state-delivered'),
Cancelled: _('order.state-cancelled'),
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
<div class="card">
<div class="card-header fulfillment-header">
<div>{{ 'order.fulfillment' | translate }}</div>
<div class="fulfillment-state">
<vdr-fulfillment-state-label [state]="fulfillment?.state"></vdr-fulfillment-state-label>
</div>
</div>
<div class="card-block">
<vdr-fulfillment-detail
*ngIf="!!fulfillment"
[fulfillmentId]="fulfillment?.id"
[order]="order"
></vdr-fulfillment-detail>
</div>
<div class="card-footer">
<ng-container *ngIf="nextSuggestedState() as suggestedState">
<button class="btn btn-sm btn-primary" (click)="transitionState.emit(suggestedState)">
{{ 'order.set-fulfillment-state' | translate: { state: suggestedState } }}
</button>
</ng-container>
<vdr-dropdown>
<button class="icon-button" vdrDropdownTrigger>
<clr-icon shape="ellipsis-vertical"></clr-icon>
</button>
<vdr-dropdown-menu vdrPosition="bottom-right">
<ng-container *ngFor="let nextState of nextOtherStates()">
<button
type="button"
class="btn"
vdrDropdownItem
(click)="transitionState.emit(nextState)"
>
<ng-container *ngIf="nextState !== 'Cancelled'; else cancel">
<clr-icon shape="step-forward-2"></clr-icon>
{{ 'order.transition-to-state' | translate: { state: nextState } }}
</ng-container>
<ng-template #cancel>
<clr-icon shape="error-standard" class="is-error"></clr-icon>
{{ 'order.cancel-fulfillment' | translate }}
</ng-template>
</button>
</ng-container>
</vdr-dropdown-menu>
</vdr-dropdown>
</div>
</div>
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@

.fulfillment-header {
display: flex;
justify-content: space-between;
align-items: center;
}

.card-footer {
display: flex;
align-items: center;
justify-content: flex-end;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import { ChangeDetectionStrategy, Component, EventEmitter, Input, Output } from '@angular/core';
import { Fulfillment, OrderDetail } from '@vendure/admin-ui/core';

@Component({
selector: 'vdr-fulfillment-card',
templateUrl: './fulfillment-card.component.html',
styleUrls: ['./fulfillment-card.component.scss'],
changeDetection: ChangeDetectionStrategy.OnPush,
})
export class FulfillmentCardComponent {
@Input() fulfillment: Fulfillment.Fragment | undefined;
@Input() order: OrderDetail.Fragment;
@Output() transitionState = new EventEmitter<string>();

nextSuggestedState(): string | undefined {
if (!this.fulfillment) {
return;
}
const { nextStates } = this.fulfillment;
const namedStateOrDefault = (targetState: string) =>
nextStates.includes(targetState) ? targetState : nextStates[0];
switch (this.fulfillment?.state) {
case 'Pending':
return namedStateOrDefault('Shipped');
case 'Shipped':
return namedStateOrDefault('Delivered');
default:
return nextStates.find(s => s !== 'Cancelled');
}
}

nextOtherStates(): string[] {
if (!this.fulfillment) {
return [];
}
const suggested = this.nextSuggestedState();
return this.fulfillment.nextStates.filter(s => s !== suggested);
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import { ChangeDetectionStrategy, Component, Input } from '@angular/core';

import { OrderDetail } from '@vendure/admin-ui/core';

@Component({
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
<vdr-chip [title]="'order.payment-state' | translate" [colorType]="chipColorType">
<clr-icon shape="check-circle" *ngIf="state === 'Delivered'"></clr-icon>
{{ state }}
</vdr-chip>
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
:host {
font-size: 14px;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import { ChangeDetectionStrategy, Component, Input } from '@angular/core';

@Component({
selector: 'vdr-fulfillment-state-label',
templateUrl: './fulfillment-state-label.component.html',
styleUrls: ['./fulfillment-state-label.component.scss'],
changeDetection: ChangeDetectionStrategy.OnPush,
})
export class FulfillmentStateLabelComponent {
@Input() state: string;

get chipColorType() {
switch (this.state) {
case 'Pending':
case 'Shipped':
return 'warning';
case 'Delivered':
return 'success';
case 'Cancelled':
return 'error';
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,12 @@
<div class="flex clr-align-items-center">
<vdr-entity-info [entity]="entity$ | async"></vdr-entity-info>
<vdr-order-state-label [state]="order.state">
<button class="icon-button" (click)="openStateDiagram()" [title]="'order.order-state-diagram' | translate">
<clr-icon shape="list"></clr-icon>
<button
class="icon-button"
(click)="openStateDiagram()"
[title]="'order.order-state-diagram' | translate"
>
<clr-icon shape="list"></clr-icon>
</button>
</vdr-order-state-label>
</div>
Expand Down Expand Up @@ -258,25 +262,20 @@ <h6 *ngIf="getOrderAddressLines(order.billingAddress).length">
</div>
</div>
<ng-container *ngIf="order.payments && order.payments.length">
<vdr-order-payment-detail
<vdr-order-payment-card
*ngFor="let payment of order.payments"
[currencyCode]="order.currencyCode"
[payment]="payment"
(settlePayment)="settlePayment($event)"
(settleRefund)="settleRefund($event)"
></vdr-order-payment-detail>
></vdr-order-payment-card>
</ng-container>
<ng-container *ngIf="order.fulfillments && order.fulfillments.length">
<div class="card">
<div class="card-header">
{{ 'order.fulfillment' | translate }}
</div>
<div class="card-block">
<div class="fulfillment-detail" *ngFor="let fulfillment of order.fulfillments">
<vdr-fulfillment-detail [fulfillmentId]="fulfillment.id" [order]="order"></vdr-fulfillment-detail>
</div>
</div>
</div>
<ng-container *ngFor="let fulfillment of order.fulfillments">
<vdr-fulfillment-card
[fulfillment]="fulfillment"
[order]="order"
(transitionState)="transitionFulfillment(fulfillment.id, $event)"
></vdr-fulfillment-card>
</ng-container>
</div>
</div>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -67,8 +67,3 @@
color: $color-grey-500;
}
}

.fulfillment-detail:not(:last-of-type) {
border-bottom: 1px dashed $color-grey-300;
margin-bottom: 12px;
}
Original file line number Diff line number Diff line change
Expand Up @@ -211,6 +211,15 @@ export class OrderDetailComponent extends BaseDetailComponent<OrderDetail.Fragme
});
}

transitionFulfillment(id: string, state: string) {
this.dataService.order
.transitionFulfillmentToState(id, state)
.pipe(switchMap(result => this.refetchOrder(result)))
.subscribe(() => {
this.notificationService.success(_('order.successfully-updated-fulfillment'));
});
}

cancelOrRefund(order: OrderDetail.Fragment) {
if (order.state === 'PaymentAuthorized' || order.active === true) {
this.cancelOrder(order);
Expand Down
Loading

0 comments on commit 7883a7a

Please sign in to comment.