Merge branch 'RED-7387' into 'master'
RED-7387: Custom date adapter Closes RED-7387 See merge request redactmanager/red-ui!129
This commit is contained in:
commit
126b6590e6
@ -25,15 +25,29 @@ const downloadTypes = ['ORIGINAL', 'PREVIEW', 'DELTA_PREVIEW', 'REDACTED'].map(t
|
|||||||
styleUrls: ['./add-edit-clone-dossier-template-dialog.component.scss'],
|
styleUrls: ['./add-edit-clone-dossier-template-dialog.component.scss'],
|
||||||
})
|
})
|
||||||
export class AddEditCloneDossierTemplateDialogComponent extends BaseDialogComponent {
|
export class AddEditCloneDossierTemplateDialogComponent extends BaseDialogComponent {
|
||||||
private _previousValidFrom: Dayjs;
|
|
||||||
private _previousValidTo: Dayjs;
|
|
||||||
private _lastValidFrom: Dayjs;
|
|
||||||
private _lastValidTo: Dayjs;
|
|
||||||
readonly isDocumine = getConfig().IS_DOCUMINE;
|
readonly isDocumine = getConfig().IS_DOCUMINE;
|
||||||
hasValidFrom: boolean;
|
hasValidFrom: boolean;
|
||||||
hasValidTo: boolean;
|
hasValidTo: boolean;
|
||||||
readonly downloadTypes = downloadTypes;
|
readonly downloadTypes = downloadTypes;
|
||||||
readonly dossierTemplate: DossierTemplate;
|
readonly dossierTemplate: DossierTemplate;
|
||||||
|
private _previousValidFrom: Dayjs;
|
||||||
|
private _previousValidTo: Dayjs;
|
||||||
|
private _lastValidFrom: Dayjs;
|
||||||
|
private _lastValidTo: Dayjs;
|
||||||
|
|
||||||
|
get disabled(): boolean {
|
||||||
|
if (!this.data?.clone) {
|
||||||
|
return super.disabled;
|
||||||
|
}
|
||||||
|
return !this.valid;
|
||||||
|
}
|
||||||
|
|
||||||
|
get translateParams() {
|
||||||
|
return {
|
||||||
|
type: this.dossierTemplate ? (this.data.clone ? 'clone' : 'edit') : 'create',
|
||||||
|
name: this.dossierTemplate?.name,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
private readonly _dossierTemplatesService: DossierTemplatesService,
|
private readonly _dossierTemplatesService: DossierTemplatesService,
|
||||||
@ -51,20 +65,6 @@ export class AddEditCloneDossierTemplateDialogComponent extends BaseDialogCompon
|
|||||||
this._previousValidTo = this._lastValidTo = this.form.get('validTo').value;
|
this._previousValidTo = this._lastValidTo = this.form.get('validTo').value;
|
||||||
}
|
}
|
||||||
|
|
||||||
get disabled(): boolean {
|
|
||||||
if (!this.data?.clone) {
|
|
||||||
return super.disabled;
|
|
||||||
}
|
|
||||||
return !this.valid;
|
|
||||||
}
|
|
||||||
|
|
||||||
get translateParams() {
|
|
||||||
return {
|
|
||||||
type: this.dossierTemplate ? (this.data.clone ? 'clone' : 'edit') : 'create',
|
|
||||||
name: this.dossierTemplate?.name,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
toggleHasValid(extremity: string) {
|
toggleHasValid(extremity: string) {
|
||||||
if (extremity === 'from') {
|
if (extremity === 'from') {
|
||||||
this.hasValidFrom = !this.hasValidFrom;
|
this.hasValidFrom = !this.hasValidFrom;
|
||||||
@ -117,11 +117,11 @@ export class AddEditCloneDossierTemplateDialogComponent extends BaseDialogCompon
|
|||||||
name: [this.#getCloneName(), Validators.required],
|
name: [this.#getCloneName(), Validators.required],
|
||||||
description: [this.dossierTemplate?.description],
|
description: [this.dossierTemplate?.description],
|
||||||
validFrom: [
|
validFrom: [
|
||||||
this.dossierTemplate?.validFrom ? dayjs(this.dossierTemplate?.validFrom).toDate() : null,
|
this.dossierTemplate?.validFrom ? dayjs(this.dossierTemplate?.validFrom) : null,
|
||||||
this.#requiredIfValidator(() => this.hasValidFrom),
|
this.#requiredIfValidator(() => this.hasValidFrom),
|
||||||
],
|
],
|
||||||
validTo: [
|
validTo: [
|
||||||
this.dossierTemplate?.validTo ? dayjs(this.dossierTemplate?.validTo).toDate() : null,
|
this.dossierTemplate?.validTo ? dayjs(this.dossierTemplate?.validTo) : null,
|
||||||
this.#requiredIfValidator(() => this.hasValidTo),
|
this.#requiredIfValidator(() => this.hasValidTo),
|
||||||
],
|
],
|
||||||
applyDictionaryUpdatesToAllDossiersByDefault: [this.dossierTemplate?.applyDictionaryUpdatesToAllDossiersByDefault],
|
applyDictionaryUpdatesToAllDossiersByDefault: [this.dossierTemplate?.applyDictionaryUpdatesToAllDossiersByDefault],
|
||||||
|
|||||||
@ -1,17 +1,238 @@
|
|||||||
import { NativeDateAdapter } from '@angular/material/core';
|
/**
|
||||||
import dayjs from 'dayjs';
|
* https://github.com/tabuckner/material-dayjs-adapter/blob/master/projects/material-dayjs-adapter/src/lib/adapter/dayjs-date-adapter.ts
|
||||||
|
* The above library is no longer maintained for our version of Angular.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { Inject, Injectable, InjectionToken, Optional } from '@angular/core';
|
||||||
|
import { DateAdapter, MAT_DATE_LOCALE } from '@angular/material/core';
|
||||||
|
import dayjs, { Dayjs } from 'dayjs';
|
||||||
|
import utc from 'dayjs/plugin/utc';
|
||||||
|
import localeData from 'dayjs/plugin/localeData';
|
||||||
|
import LocalizedFormat from 'dayjs/plugin/localizedFormat';
|
||||||
import customParseFormat from 'dayjs/plugin/customParseFormat';
|
import customParseFormat from 'dayjs/plugin/customParseFormat';
|
||||||
import { Injectable } from '@angular/core';
|
|
||||||
|
|
||||||
dayjs.extend(customParseFormat);
|
export interface DayJsDateAdapterOptions {
|
||||||
|
/**
|
||||||
|
* Turns the use of utc dates on or off.
|
||||||
|
* Changing this will change how Angular Material components like DatePicker output dates.
|
||||||
|
* {@default false}
|
||||||
|
*/
|
||||||
|
useUtc?: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** InjectionToken for Dayjs date adapter to configure options. */
|
||||||
|
export const MAT_DAYJS_DATE_ADAPTER_OPTIONS = new InjectionToken<DayJsDateAdapterOptions>('MAT_DAYJS_DATE_ADAPTER_OPTIONS', {
|
||||||
|
providedIn: 'root',
|
||||||
|
factory: MAT_DAYJS_DATE_ADAPTER_OPTIONS_FACTORY,
|
||||||
|
});
|
||||||
|
|
||||||
|
export function MAT_DAYJS_DATE_ADAPTER_OPTIONS_FACTORY(): DayJsDateAdapterOptions {
|
||||||
|
return {
|
||||||
|
useUtc: false,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Creates an array and fills it with values. */
|
||||||
|
function range<T>(length: number, valueFunction: (index: number) => T): T[] {
|
||||||
|
const valuesArray = Array(length);
|
||||||
|
for (let i = 0; i < length; i++) {
|
||||||
|
valuesArray[i] = valueFunction(i);
|
||||||
|
}
|
||||||
|
return valuesArray;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Adapts Dayjs Dates for use with Angular Material. */
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class CustomDateAdapter extends NativeDateAdapter {
|
export class CustomDateAdapter extends DateAdapter<Dayjs> {
|
||||||
parse(value: any, parseFormat: string): Date | null {
|
private _localeData: {
|
||||||
return dayjs(value, parseFormat).toDate();
|
firstDayOfWeek: number;
|
||||||
|
longMonths: string[];
|
||||||
|
shortMonths: string[];
|
||||||
|
dates: string[];
|
||||||
|
longDaysOfWeek: string[];
|
||||||
|
shortDaysOfWeek: string[];
|
||||||
|
narrowDaysOfWeek: string[];
|
||||||
|
};
|
||||||
|
|
||||||
|
private get _shouldUseUtc(): boolean {
|
||||||
|
const { useUtc }: DayJsDateAdapterOptions = this._options || {};
|
||||||
|
return !!useUtc;
|
||||||
}
|
}
|
||||||
|
|
||||||
format(date: Date, displayFormat: string): string {
|
constructor(
|
||||||
return dayjs(date).format(displayFormat);
|
@Optional() @Inject(MAT_DATE_LOCALE) public dateLocale: string,
|
||||||
|
@Optional() @Inject(MAT_DAYJS_DATE_ADAPTER_OPTIONS) private _options?: DayJsDateAdapterOptions,
|
||||||
|
) {
|
||||||
|
super();
|
||||||
|
|
||||||
|
this._initializeParser(dateLocale);
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: Implement
|
||||||
|
setLocale(locale: string) {
|
||||||
|
super.setLocale(locale);
|
||||||
|
|
||||||
|
const dayJsLocaleData = this._dayJs().localeData();
|
||||||
|
this._localeData = {
|
||||||
|
firstDayOfWeek: dayJsLocaleData.firstDayOfWeek(),
|
||||||
|
longMonths: dayJsLocaleData.months(),
|
||||||
|
shortMonths: dayJsLocaleData.monthsShort(),
|
||||||
|
dates: range(31, i => this.createDate(2017, 0, i + 1).format('D')),
|
||||||
|
longDaysOfWeek: range(7, i => this._dayJs().set('day', i).format('dddd')),
|
||||||
|
shortDaysOfWeek: dayJsLocaleData.weekdaysShort(),
|
||||||
|
narrowDaysOfWeek: dayJsLocaleData.weekdaysMin(),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
getYear(date: Dayjs): number {
|
||||||
|
return this._dayJs(date).year();
|
||||||
|
}
|
||||||
|
|
||||||
|
getMonth(date: Dayjs): number {
|
||||||
|
return this._dayJs(date).month();
|
||||||
|
}
|
||||||
|
|
||||||
|
getDate(date: Dayjs): number {
|
||||||
|
return this._dayJs(date).date();
|
||||||
|
}
|
||||||
|
|
||||||
|
getDayOfWeek(date: Dayjs): number {
|
||||||
|
return this._dayJs(date).day();
|
||||||
|
}
|
||||||
|
|
||||||
|
getMonthNames(style: 'long' | 'short' | 'narrow'): string[] {
|
||||||
|
return style === 'long' ? this._localeData.longMonths : this._localeData.shortMonths;
|
||||||
|
}
|
||||||
|
|
||||||
|
getDateNames(): string[] {
|
||||||
|
return this._localeData.dates;
|
||||||
|
}
|
||||||
|
|
||||||
|
getDayOfWeekNames(style: 'long' | 'short' | 'narrow'): string[] {
|
||||||
|
if (style === 'long') {
|
||||||
|
return this._localeData.longDaysOfWeek;
|
||||||
|
}
|
||||||
|
if (style === 'short') {
|
||||||
|
return this._localeData.shortDaysOfWeek;
|
||||||
|
}
|
||||||
|
return this._localeData.narrowDaysOfWeek;
|
||||||
|
}
|
||||||
|
|
||||||
|
getYearName(date: Dayjs): string {
|
||||||
|
return this._dayJs(date).format('YYYY');
|
||||||
|
}
|
||||||
|
|
||||||
|
getFirstDayOfWeek(): number {
|
||||||
|
return this._localeData.firstDayOfWeek;
|
||||||
|
}
|
||||||
|
|
||||||
|
getNumDaysInMonth(date: Dayjs): number {
|
||||||
|
return this._dayJs(date).daysInMonth();
|
||||||
|
}
|
||||||
|
|
||||||
|
clone(date: Dayjs): Dayjs {
|
||||||
|
return date.clone();
|
||||||
|
}
|
||||||
|
|
||||||
|
createDate(year: number, month: number, date: number): Dayjs {
|
||||||
|
const returnDayjs = this._dayJs().set('year', year).set('month', month).set('date', date);
|
||||||
|
return returnDayjs;
|
||||||
|
}
|
||||||
|
|
||||||
|
today(): Dayjs {
|
||||||
|
return this._dayJs();
|
||||||
|
}
|
||||||
|
|
||||||
|
parse(value: any, parseFormat: string): Dayjs | null {
|
||||||
|
if (value && typeof value === 'string') {
|
||||||
|
return this._dayJs(value, dayjs().localeData().longDateFormat(parseFormat), this.locale);
|
||||||
|
}
|
||||||
|
return value ? this._dayJs(value).locale(this.locale) : null;
|
||||||
|
}
|
||||||
|
|
||||||
|
format(date: Dayjs, displayFormat: string): string {
|
||||||
|
if (!this.isValid(date)) {
|
||||||
|
throw Error('DayjsDateAdapter: Cannot format invalid date.');
|
||||||
|
}
|
||||||
|
return date.locale(this.locale).format(displayFormat);
|
||||||
|
}
|
||||||
|
|
||||||
|
addCalendarYears(date: Dayjs, years: number): Dayjs {
|
||||||
|
return date.add(years, 'year');
|
||||||
|
}
|
||||||
|
|
||||||
|
addCalendarMonths(date: Dayjs, months: number): Dayjs {
|
||||||
|
return date.add(months, 'month');
|
||||||
|
}
|
||||||
|
|
||||||
|
addCalendarDays(date: Dayjs, days: number): Dayjs {
|
||||||
|
return date.add(days, 'day');
|
||||||
|
}
|
||||||
|
|
||||||
|
toIso8601(date: Dayjs): string {
|
||||||
|
return date.toISOString();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Attempts to deserialize a value to a valid date object. This is different from parsing in that
|
||||||
|
* deserialize should only accept non-ambiguous, locale-independent formats (e.g. a ISO 8601
|
||||||
|
* string). The default implementation does not allow any deserialization, it simply checks that
|
||||||
|
* the given value is already a valid date object or null. The `<mat-datepicker>` will call this
|
||||||
|
* method on all of it's `@Input()` properties that accept dates. It is therefore possible to
|
||||||
|
* support passing values from your backend directly to these properties by overriding this method
|
||||||
|
* to also deserialize the format used by your backend.
|
||||||
|
* @param value The value to be deserialized into a date object.
|
||||||
|
* @returns The deserialized date object, either a valid date, null if the value can be
|
||||||
|
* deserialized into a null date (e.g. the empty string), or an invalid date.
|
||||||
|
*/
|
||||||
|
deserialize(value: any): Dayjs | null {
|
||||||
|
let date;
|
||||||
|
if (value instanceof Date) {
|
||||||
|
date = this._dayJs(value);
|
||||||
|
} else if (this.isDateInstance(value)) {
|
||||||
|
// NOTE: assumes that cloning also sets the correct locale.
|
||||||
|
return this.clone(value);
|
||||||
|
}
|
||||||
|
if (typeof value === 'string') {
|
||||||
|
if (!value) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
date = this._dayJs(value).toISOString();
|
||||||
|
}
|
||||||
|
if (date && this.isValid(date)) {
|
||||||
|
return this._dayJs(date); // NOTE: Is this necessary since Dayjs is immutable and Moment was not?
|
||||||
|
}
|
||||||
|
return super.deserialize(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
isDateInstance(obj: any): boolean {
|
||||||
|
return dayjs.isDayjs(obj);
|
||||||
|
}
|
||||||
|
|
||||||
|
isValid(date: Dayjs): boolean {
|
||||||
|
return this._dayJs(date).isValid();
|
||||||
|
}
|
||||||
|
|
||||||
|
invalid(): Dayjs {
|
||||||
|
return this._dayJs(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
private _dayJs(input?: any, format?: string, locale?: string): Dayjs {
|
||||||
|
if (!this._shouldUseUtc) {
|
||||||
|
return dayjs(input, { format, locale }, locale);
|
||||||
|
}
|
||||||
|
return dayjs(input, { format, locale, utc: this._shouldUseUtc }, locale).utc();
|
||||||
|
}
|
||||||
|
|
||||||
|
private _initializeParser(dateLocale: string) {
|
||||||
|
if (this._shouldUseUtc) {
|
||||||
|
dayjs.extend(utc);
|
||||||
|
}
|
||||||
|
|
||||||
|
dayjs.extend(LocalizedFormat);
|
||||||
|
dayjs.extend(customParseFormat);
|
||||||
|
dayjs.extend(localeData);
|
||||||
|
|
||||||
|
this.setLocale(dateLocale);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user