Skip to content

Commit

Permalink
feat(admin-ui): Dates respect UI language setting
Browse files Browse the repository at this point in the history
Relates to #568
  • Loading branch information
michaelbromley committed Jan 13, 2021
1 parent 7af51d0 commit dd0e73a
Show file tree
Hide file tree
Showing 15 changed files with 142 additions and 15 deletions.
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<div class="input-wrapper">
<input
readonly
[ngModel]="selected$ | async | date: 'medium'"
[ngModel]="selected$ | async | localeDate: 'medium'"
class="selected-datetime"
(keydown.enter)="dropdownComponent.toggleOpen()"
(keydown.space)="dropdownComponent.toggleOpen()"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,10 @@
{{ entity.id }}
</vdr-labeled-data>
<vdr-labeled-data *ngIf="entity.createdAt" [label]="'common.created-at' | translate">
{{ entity.createdAt | date: 'medium' }}
{{ entity.createdAt | localeDate: 'medium' }}
</vdr-labeled-data>
<vdr-labeled-data *ngIf="entity.updatedAt" [label]="'common.updated-at' | translate">
{{ entity.updatedAt | date: 'medium' }}
{{ entity.updatedAt | localeDate: 'medium' }}
</vdr-labeled-data>
</div>
</vdr-dropdown-menu>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
<div class="entry-body">
<div class="detail">
<div class="time">
{{ createdAt | date: 'short' }}
{{ createdAt | localeDate: 'short' }}
</div>
<div class="name">
{{ name }}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import { LanguageCode } from '../../common/generated-types';

import { LocaleDatePipe } from './locale-date.pipe';

describe('LocaleDatePipe', () => {
const testDate = new Date('2021-01-12T09:12:42');
it('medium format', () => {
const pipe = new LocaleDatePipe();
expect(pipe.transform(testDate, 'medium', LanguageCode.en)).toBe('Jan 12, 2021, 9:12:42 AM');
});
it('mediumTime format', () => {
const pipe = new LocaleDatePipe();
expect(pipe.transform(testDate, 'mediumTime', LanguageCode.en)).toBe('9:12:42 AM');
});
it('short format', () => {
const pipe = new LocaleDatePipe();
expect(pipe.transform(testDate, 'short', LanguageCode.en)).toBe('1/12/21, 9:12 AM');
});
it('longDate format', () => {
const pipe = new LocaleDatePipe();
expect(pipe.transform(testDate, 'longDate', LanguageCode.en)).toBe('January 12, 2021');
});

it('medium format German', () => {
const pipe = new LocaleDatePipe();
expect(pipe.transform(testDate, 'medium', LanguageCode.de)).toBe('12. Jan. 2021, 9:12:42 AM');
});

it('medium format Chinese', () => {
const pipe = new LocaleDatePipe();
expect(pipe.transform(testDate, 'medium', LanguageCode.zh)).toBe('2021年1月12日 上午9:12:42');
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
import { ChangeDetectorRef, OnDestroy, Optional, Pipe, PipeTransform } from '@angular/core';
import { DataService } from '@vendure/admin-ui/core';
import { Subscription } from 'rxjs';

import { LanguageCode } from '../../common/generated-types';

/**
* @description
* A replacement of the Angular DatePipe which makes use of the Intl API
* to format dates according to the selected UI language.
*/
@Pipe({
name: 'localeDate',
pure: false,
})
export class LocaleDatePipe implements PipeTransform, OnDestroy {
private locale: string;
private readonly subscription: Subscription;

constructor(
@Optional() private dataService?: DataService,
@Optional() changeDetectorRef?: ChangeDetectorRef,
) {
if (this.dataService && changeDetectorRef) {
this.subscription = this.dataService.client
.uiState()
.mapStream(data => data.uiState.language)
.subscribe(languageCode => {
this.locale = languageCode.replace(/_/g, '-');
changeDetectorRef.markForCheck();
});
}
}

ngOnDestroy() {
if (this.subscription) {
this.subscription.unsubscribe();
}
}

transform(value: unknown, ...args: unknown[]): unknown {
const [format, locale] = args;
if (this.locale || typeof locale === 'string') {
const activeLocale = typeof locale === 'string' ? locale : this.locale;
const date =
value instanceof Date ? value : typeof value === 'string' ? new Date(value) : undefined;
if (date) {
const options = this.getOptionsForFormat(typeof format === 'string' ? format : 'medium');
return new Intl.DateTimeFormat(activeLocale, options).format(date);
}
}
}

private getOptionsForFormat(dateFormat: string): Intl.DateTimeFormatOptions | undefined {
switch (dateFormat) {
case 'medium':
return {
month: 'short',
year: 'numeric',
day: 'numeric',
hour: 'numeric',
minute: 'numeric',
second: 'numeric',
hour12: true,
};
case 'mediumTime':
return {
hour: 'numeric',
minute: 'numeric',
second: 'numeric',
hour12: true,
};
case 'longDate':
return {
year: 'numeric',
month: 'long',
day: 'numeric',
};
case 'short':
return {
day: 'numeric',
month: 'numeric',
year: '2-digit',
hour: 'numeric',
minute: 'numeric',
hour12: true,
};
default:
return;
}
}
}
2 changes: 2 additions & 0 deletions packages/admin-ui/src/lib/core/src/shared/shared.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,7 @@ import { CustomFieldLabelPipe } from './pipes/custom-field-label.pipe';
import { DurationPipe } from './pipes/duration.pipe';
import { FileSizePipe } from './pipes/file-size.pipe';
import { HasPermissionPipe } from './pipes/has-permission.pipe';
import { LocaleDatePipe } from './pipes/locale-date.pipe';
import { SentenceCasePipe } from './pipes/sentence-case.pipe';
import { SortPipe } from './pipes/sort.pipe';
import { StateI18nTokenPipe } from './pipes/state-i18n-token.pipe';
Expand Down Expand Up @@ -193,6 +194,7 @@ const DECLARATIONS = [
HelpTooltipComponent,
CustomerGroupFormInputComponent,
AddressFormComponent,
LocaleDatePipe,
];

const DYNAMIC_FORM_INPUTS = [
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
<div class="flex clr-align-items-center">
<vdr-entity-info [entity]="entity$ | async"></vdr-entity-info>
<vdr-customer-status-label [customer]="entity$ | async"></vdr-customer-status-label>
<div class="last-login" *ngIf="(entity$ | async)?.user?.lastLogin as lastLogin" [title]="lastLogin | date:'medium'">
<div class="last-login" *ngIf="(entity$ | async)?.user?.lastLogin as lastLogin" [title]="lastLogin | localeDate:'medium'">
{{ 'customer.last-login' | translate }}: {{ lastLogin | timeAgo }}
</div>
</div>
Expand Down Expand Up @@ -140,7 +140,7 @@ <h3>{{ 'customer.orders' | translate }}</h3>
<td class="left">{{ order.code }}</td>
<td class="left">{{ order.state }}</td>
<td class="left">{{ order.total / 100 | currency: order.currencyCode }}</td>
<td class="left">{{ order.updatedAt | date: 'medium' }}</td>
<td class="left">{{ order.updatedAt | localeDate: 'medium' }}</td>
<td class="right">
<vdr-table-row-action
iconShape="shopping-cart"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,6 @@
</div>

<div class="date-range p5" *ngIf="dateRange$ | async as range">
{{ range.start | date }} - {{ range.end | date }}
{{ range.start | localeDate }} - {{ range.end | localeDate }}
</div>
</div>
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,8 @@
{{ promotion.couponCode }}
</vdr-chip>
</td>
<td class="left align-middle">{{ promotion.startsAt | date: 'longDate' }}</td>
<td class="left align-middle">{{ promotion.endsAt | date: 'longDate' }}</td>
<td class="left align-middle">{{ promotion.startsAt | localeDate: 'longDate' }}</td>
<td class="left align-middle">{{ promotion.endsAt | localeDate: 'longDate' }}</td>
<td class="align-middle">
<vdr-chip *ngIf="!promotion.enabled">{{ 'common.disabled' | translate }}</vdr-chip>
</td>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
<vdr-labeled-data [label]="'common.created-at' | translate">
{{ fulfillment?.createdAt | date: 'medium' }}
{{ fulfillment?.createdAt | localeDate: 'medium' }}
</vdr-labeled-data>
<vdr-labeled-data [label]="'order.fulfillment-method' | translate">
{{ fulfillment?.method }}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@
}})
</div>
<vdr-labeled-data [label]="'common.created-at' | translate">
{{ item.fulfillment.createdAt | date: 'medium' }}
{{ item.fulfillment.createdAt | localeDate: 'medium' }}
</vdr-labeled-data>
<vdr-labeled-data [label]="'order.fulfillment-method' | translate">
{{ item.fulfillment.method }}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@
</td>
<td class="left align-middle">{{ order.total / 100 | currency: order.currencyCode }}</td>
<td class="left align-middle">{{ order.updatedAt | timeAgo }}</td>
<td class="left align-middle">{{ order.orderPlacedAt | date: 'medium' }}</td>
<td class="left align-middle">{{ order.orderPlacedAt | localeDate: 'medium' }}</td>
<td class="left align-middle">{{ getShippingNames(order) }}</td>
<td class="right align-middle">
<vdr-table-row-action
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
</div>
<div class="card-block">
<vdr-labeled-data [label]="'common.created-at' | translate">
{{ refund.createdAt | date: 'medium' }}
{{ refund.createdAt | localeDate: 'medium' }}
</vdr-labeled-data>
<vdr-labeled-data [label]="'order.refund-total' | translate">
{{ refund.total / 100 | currency: currencyCode }}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@
<ng-container [ngSwitch]="customField.type">
<ng-template [ngSwitchCase]="'datetime'">
<span [title]="line.customFields[customField.name]">{{
line.customFields[customField.name] | date: 'short'
line.customFields[customField.name] | localeDate: 'short'
}}</span>
</ng-template>
<ng-template [ngSwitchCase]="'boolean'">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
</ng-template>
<div class="last-checked">
{{ 'system.health-last-checked' | translate }}:
{{ healthCheckService.lastCheck$ | async | date: 'mediumTime' }}
{{ healthCheckService.lastCheck$ | async | localeDate: 'mediumTime' }}
</div>
</div>
</div>
Expand Down

0 comments on commit dd0e73a

Please sign in to comment.