Skip to content

Commit

Permalink
feat(admin-ui): Implement adding notes to Order history
Browse files Browse the repository at this point in the history
Relates to #118
  • Loading branch information
michaelbromley committed Jul 3, 2019
1 parent 3f5745d commit 1108914
Show file tree
Hide file tree
Showing 9 changed files with 127 additions and 48 deletions.
14 changes: 14 additions & 0 deletions admin-ui/src/app/common/generated-types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3612,6 +3612,13 @@ export type GetOrderHistoryQueryVariables = {

export type GetOrderHistoryQuery = ({ __typename?: 'Query' } & { order: Maybe<({ __typename?: 'Order' } & Pick<Order, 'id'> & { history: ({ __typename?: 'HistoryEntryList' } & Pick<HistoryEntryList, 'totalItems'> & { items: Array<({ __typename?: 'HistoryEntry' } & Pick<HistoryEntry, 'id' | 'type' | 'createdAt' | 'data'> & { administrator: Maybe<({ __typename?: 'Administrator' } & Pick<Administrator, 'id' | 'firstName' | 'lastName'>)> })> }) })> });

export type AddNoteToOrderMutationVariables = {
input: AddNoteToOrderInput
};


export type AddNoteToOrderMutation = ({ __typename?: 'Mutation' } & { addNoteToOrder: ({ __typename?: 'Order' } & Pick<Order, 'id' | 'updatedAt'> & { history: ({ __typename?: 'HistoryEntryList' } & Pick<HistoryEntryList, 'totalItems'>) }) });

export type AssetFragment = ({ __typename?: 'Asset' } & Pick<Asset, 'id' | 'createdAt' | 'name' | 'fileSize' | 'mimeType' | 'type' | 'preview' | 'source'>);

export type ProductVariantFragment = ({ __typename?: 'ProductVariant' } & Pick<ProductVariant, 'id' | 'enabled' | 'languageCode' | 'name' | 'price' | 'currencyCode' | 'priceIncludesTax' | 'priceWithTax' | 'stockOnHand' | 'trackInventory' | 'sku'> & { taxRateApplied: ({ __typename?: 'TaxRate' } & Pick<TaxRate, 'id' | 'name' | 'value'>), taxCategory: ({ __typename?: 'TaxCategory' } & Pick<TaxCategory, 'id' | 'name'>), options: Array<({ __typename?: 'ProductOption' } & Pick<ProductOption, 'id' | 'code' | 'languageCode' | 'name'>)>, facetValues: Array<({ __typename?: 'FacetValue' } & Pick<FacetValue, 'id' | 'code' | 'name'> & { facet: ({ __typename?: 'Facet' } & Pick<Facet, 'id' | 'name'>) })>, featuredAsset: Maybe<({ __typename?: 'Asset' } & AssetFragment)>, assets: Array<({ __typename?: 'Asset' } & AssetFragment)>, translations: Array<({ __typename?: 'ProductVariantTranslation' } & Pick<ProductVariantTranslation, 'id' | 'languageCode' | 'name'>)> });
Expand Down Expand Up @@ -4430,6 +4437,13 @@ export namespace GetOrderHistory {
export type Administrator = (NonNullable<(NonNullable<(NonNullable<GetOrderHistoryQuery['order']>)['history']['items'][0]>)['administrator']>);
}

export namespace AddNoteToOrder {
export type Variables = AddNoteToOrderMutationVariables;
export type Mutation = AddNoteToOrderMutation;
export type AddNoteToOrder = AddNoteToOrderMutation['addNoteToOrder'];
export type History = AddNoteToOrderMutation['addNoteToOrder']['history'];
}

export namespace Asset {
export type Fragment = AssetFragment;
}
Expand Down
8 changes: 8 additions & 0 deletions admin-ui/src/app/data/definitions/order-definitions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -243,3 +243,11 @@ export const GET_ORDER_HISTORY = gql`
}
}
`;

export const ADD_NOTE_TO_ORDER = gql`
mutation AddNoteToOrder($input: AddNoteToOrderInput!) {
addNoteToOrder(input: $input) {
id
}
}
`;
12 changes: 12 additions & 0 deletions admin-ui/src/app/data/providers/order-data.service.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
import {
AddNoteToOrder,
AddNoteToOrderInput,
CancelOrder,
CancelOrderInput,
CreateFulfillment,
Expand All @@ -14,6 +16,7 @@ import {
SettleRefundInput,
} from '../../common/generated-types';
import {
ADD_NOTE_TO_ORDER,
CANCEL_ORDER,
CREATE_FULFILLMENT,
GET_ORDER,
Expand Down Expand Up @@ -84,4 +87,13 @@ export class OrderDataService {
input,
});
}

addNoteToOrder(input: AddNoteToOrderInput) {
return this.baseDataService.mutate<AddNoteToOrder.Mutation, AddNoteToOrder.Variables>(
ADD_NOTE_TO_ORDER,
{
input,
},
);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,11 @@
</tr>
</table>

<vdr-order-history [order]="order"></vdr-order-history>
<vdr-order-history
[order]="order"
[history]="history$ | async"
(addNote)="addNote($event)"
></vdr-order-history>
</div>
<div class="clr-col-lg-4 order-cards">
<div class="card">
Expand Down
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
import { ChangeDetectionStrategy, ChangeDetectorRef, Component, OnDestroy, OnInit } from '@angular/core';
import { FormGroup } from '@angular/forms';
import { ActivatedRoute, Router } from '@angular/router';
import { Observable, of } from 'rxjs';
import { switchMap, take } from 'rxjs/operators';
import { Observable, of, Subject } from 'rxjs';
import { startWith, switchMap, take } from 'rxjs/operators';
import { omit } from 'shared/omit';
import { _ } from 'src/app/core/providers/i18n/mark-for-extraction';

import { BaseDetailComponent } from '../../../common/base-detail.component';
import { Order, OrderDetail } from '../../../common/generated-types';
import { GetOrderHistory, Order, OrderDetail, SortOrder } from '../../../common/generated-types';
import { NotificationService } from '../../../core/providers/notification/notification.service';
import { DataService } from '../../../data/providers/data.service';
import { ServerConfigService } from '../../../data/server-config';
Expand All @@ -26,6 +26,8 @@ import { SettleRefundDialogComponent } from '../settle-refund-dialog/settle-refu
export class OrderDetailComponent extends BaseDetailComponent<OrderDetail.Fragment>
implements OnInit, OnDestroy {
detailForm = new FormGroup({});
history$: Observable<GetOrderHistory.Items[] | null>;
fetchHistory = new Subject<void>();
constructor(
router: Router,
route: ActivatedRoute,
Expand All @@ -40,6 +42,18 @@ export class OrderDetailComponent extends BaseDetailComponent<OrderDetail.Fragme

ngOnInit() {
this.init();
this.history$ = this.fetchHistory.pipe(
startWith(null),
switchMap(() => {
return this.dataService.order
.getOrderHistory(this.id, {
sort: {
createdAt: SortOrder.DESC,
},
})
.mapStream(data => data.order && data.order.history.items);
}),
);
}

ngOnDestroy() {
Expand Down Expand Up @@ -135,6 +149,18 @@ export class OrderDetailComponent extends BaseDetailComponent<OrderDetail.Fragme
});
}

addNote(note: string) {
this.dataService.order
.addNoteToOrder({
id: this.id,
note,
})
.pipe(switchMap(result => this.refetchOrder(result)))
.subscribe(result => {
this.notificationService.success(_('order.add-note-success'));
});
}

private cancelOrder(order: OrderDetail.Fragment) {
this.modalService
.fromComponent(CancelOrderDialogComponent, {
Expand Down Expand Up @@ -197,6 +223,7 @@ export class OrderDetailComponent extends BaseDetailComponent<OrderDetail.Fragme
}

private refetchOrder(result: object | undefined) {
this.fetchHistory.next();
if (result) {
return this.dataService.order.getOrder(this.id).single$;
} else {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,20 @@
<h4>{{ 'order.order-history' | translate }}</h4>
<div class="entry-list">
<div class="entry"></div>
<div class="entry has-custom-icon">
<div class="timeline">
<div class="custom-icon">
<clr-icon shape="note" size="24" class="compose-note"></clr-icon>
</div>
</div>
<div class="entry-body note-entry">
<textarea [(ngModel)]="note" name="note" class="note"></textarea>
<button class="btn btn-secondary" [disabled]="!note" (click)="addNoteToOrder()">
{{ 'order.add-note' | translate }}
</button>
</div>
</div>
<div
*ngFor="let entry of history$ | async"
*ngFor="let entry of history"
[ngClass]="getClassForEntry(entry)"
[class.has-custom-icon]="!!getTimelineIcon(entry)"
class="entry"
Expand All @@ -27,6 +39,7 @@ <h4>{{ 'order.order-history' | translate }}</h4>
size="24"
class="cancelled"
></clr-icon>
<clr-icon *ngIf="getTimelineIcon(entry) === 'note'" shape="note" size="24"></clr-icon>
</div>
</div>
<div class="entry-body" [ngSwitch]="entry.type">
Expand Down Expand Up @@ -62,7 +75,7 @@ <h4>{{ 'order.order-history' | translate }}</h4>
*ngIf="entry.data.to === 'Settled'; else regularPaymentTransition"
>
<div class="title">
{{ 'order.history-payment-settled' | translate }}
{{ 'order.history-payment-settled' | translate: { id: entry.data.paymentId } }}
</div>
{{ 'order.transaction-id' | translate }}: {{ getPayment(entry)?.transactionId }}
<vdr-history-entry-detail *ngIf="getPayment(entry) as payment">
Expand All @@ -75,14 +88,15 @@ <h4>{{ 'order.order-history' | translate }}</h4>
<ng-template #regularPaymentTransition>
{{
'order.history-payment-transition'
| translate: { from: entry.data.from, to: entry.data.to }
| translate
: { from: entry.data.from, to: entry.data.to, id: entry.data.paymentId }
}}
</ng-template>
</ng-container>
<ng-container *ngSwitchCase="type.ORDER_REFUND_TRANSITION">
{{
'order.history-refund-transition'
| translate: { from: entry.data.from, to: entry.data.to }
| translate: { from: entry.data.from, to: entry.data.to, id: entry.data.refundId }
}}
</ng-container>
<ng-container *ngSwitchCase="type.ORDER_CANCELLATION">
Expand All @@ -92,11 +106,7 @@ <h4>{{ 'order.order-history' | translate }}</h4>
{{ entry.data.reason }}
</vdr-labeled-data>
<vdr-labeled-data [label]="'order.contents' | translate">
<div class="items-list">
<ul>
<li *ngFor="let item of items">{{ item.name }} x {{ item.quantity }}</li>
</ul>
</div>
<vdr-simple-item-list [items]="items"></vdr-simple-item-list>
</vdr-labeled-data>
</vdr-history-entry-detail>
</ng-container>
Expand All @@ -114,6 +124,11 @@ <h4>{{ 'order.order-history' | translate }}</h4>
</vdr-history-entry-detail>
</div>
</ng-container>
<ng-container *ngSwitchCase="type.ORDER_NOTE">
<div class="featured-entry">
<div class="note-text">{{ entry.data.note }}</div>
</div>
</ng-container>
</div>
</div>
</div>
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,9 @@
.cancelled {
color: $color-error-400;
}
.compose-note {
color: $color-grey-400;
}
}
.entry.has-custom-icon {
.timeline:after {
Expand All @@ -76,17 +79,23 @@

.entry-body {
flex: 1;
padding-bottom: 18px;
padding-bottom: 24px;
padding-left: 12px;
line-height: 16px;
margin-left: 12px;
color: $color-grey-500;
}

.featured-entry {
.title {
color: $color-grey-800;
font-size: 16px;
line-height: 26px;
}
.note-text {
color: $color-grey-800;
white-space: pre-wrap;
}
}

.detail {
Expand Down Expand Up @@ -120,10 +129,17 @@
border: 1px solid $color-warning-400;
}
}
.items-list {
font-size: 12px;

ul {
list-style-type: none;
.note-entry {
display: flex;

button {
margin: 0;
}
}
textarea.note {
flex: 1;
height: 36px;
border-radius: 3px;
margin-right: 6px;
}
Original file line number Diff line number Diff line change
@@ -1,48 +1,24 @@
import { ChangeDetectionStrategy, Component, Input, OnChanges, OnInit, SimpleChanges } from '@angular/core';
import { Observable, Subject } from 'rxjs';
import { startWith, switchMap } from 'rxjs/operators';
import { ChangeDetectionStrategy, Component, EventEmitter, Input, Output } from '@angular/core';

import {
GetOrderHistory,
HistoryEntryType,
OrderDetail,
OrderDetailFragment,
SortOrder,
} from '../../../common/generated-types';
import { DataService } from '../../../data/providers/data.service';

@Component({
selector: 'vdr-order-history',
templateUrl: './order-history.component.html',
styleUrls: ['./order-history.component.scss'],
changeDetection: ChangeDetectionStrategy.OnPush,
})
export class OrderHistoryComponent implements OnInit, OnChanges {
export class OrderHistoryComponent {
@Input() order: OrderDetailFragment;
history$: Observable<GetOrderHistory.Items[] | null>;
@Input() history: GetOrderHistory.Items[];
@Output() addNote = new EventEmitter<string>();
note = '';
readonly type = HistoryEntryType;
private orderChange = new Subject<void>();

constructor(private dataService: DataService) {}

ngOnInit() {
this.history$ = this.orderChange.pipe(
startWith(null),
switchMap(() => {
return this.dataService.order
.getOrderHistory(this.order.id, {
sort: {
createdAt: SortOrder.DESC,
},
})
.mapStream(data => data.order && data.order.history.items);
}),
);
}

ngOnChanges(changes: SimpleChanges): void {
this.orderChange.next();
}

getClassForEntry(entry: GetOrderHistory.Items): 'success' | 'error' | 'warning' | undefined {
if (entry.type === HistoryEntryType.ORDER_PAYMENT_TRANSITION) {
Expand Down Expand Up @@ -124,4 +100,9 @@ export class OrderHistoryComponent implements OnInit, OnChanges {
}
return '';
}

addNoteToOrder() {
this.addNote.emit(this.note);
this.note = '';
}
}
2 changes: 2 additions & 0 deletions admin-ui/src/i18n-messages/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -405,6 +405,8 @@
"tax-rates": "Tax Rates"
},
"order": {
"add-note": "Add note",
"add-note-success": "Note successfully added",
"amount": "Amount",
"cancel": "Cancel",
"cancel-order": "Cancel Order",
Expand Down

0 comments on commit 1108914

Please sign in to comment.