diff --git a/projects/netgrif-components-core/src/lib/data-fields/base-component/abstract-base-data-field.component.ts b/projects/netgrif-components-core/src/lib/data-fields/base-component/abstract-base-data-field.component.ts index da8699a951..8d4777115d 100644 --- a/projects/netgrif-components-core/src/lib/data-fields/base-component/abstract-base-data-field.component.ts +++ b/projects/netgrif-components-core/src/lib/data-fields/base-component/abstract-base-data-field.component.ts @@ -10,6 +10,9 @@ import {WrappedBoolean} from "../data-field-template/models/wrapped-boolean"; }) export abstract class AbstractBaseDataFieldComponent> implements OnDestroy { + private static readonly TRUE_VALUES = ['true', '1', 'yes', 'y', 'ano', 'áno', 'pravda']; + private static readonly FALSE_VALUES = ['false', '0', 'no', 'n', 'nie', 'nepravda']; + @Input() public dataField: T; @Input() public formControlRef: FormControl; @Input() public showLargeLayout: WrappedBoolean; @@ -21,7 +24,7 @@ export abstract class AbstractBaseDataFieldComponent) { - super(_translate, _adapter, _locale, _languageService, dataFieldPortalData) + super(_translate, _adapter, _locale, _languageService, dataFieldPortalData); + } + + public get showSeconds(): boolean { + return this.dataField?.showSeconds ?? false; + } + + public get stepHour(): number { + return this.dataField?.stepHour ?? 1; + } + + public get stepMinute(): number { + return this.dataField?.stepMinute ?? 5; + } + + public get stepSecond(): number { + return this.dataField?.stepSecond ?? 1; + } + + public get enableMeridian(): boolean { + return this.dataField?.enableMeridian ?? false; } getErrorMessage() { diff --git a/projects/netgrif-components-core/src/lib/data-fields/date-time-field/models/date-time-field.ts b/projects/netgrif-components-core/src/lib/data-fields/date-time-field/models/date-time-field.ts index b13fab0be9..c9032f9f73 100644 --- a/projects/netgrif-components-core/src/lib/data-fields/date-time-field/models/date-time-field.ts +++ b/projects/netgrif-components-core/src/lib/data-fields/date-time-field/models/date-time-field.ts @@ -4,19 +4,64 @@ import {AbstractTimeInstanceField} from '../../time-instance-abstract-field/mode import {Layout} from '../../models/layout'; import {Validation} from '../../models/validation'; import {Component, ComponentPrefixes} from '../../models/component'; +import {AbstractBaseDataFieldComponent} from '../../base-component/abstract-base-data-field.component'; export class DateTimeField extends AbstractTimeInstanceField { + public static readonly SHOW_SECONDS_PROPERTY = 'showSeconds'; + + public static readonly ENABLE_MERIDIAN_PROPERTY = 'enableMeridian'; + + public static readonly STEP_HOUR_PROPERTY = 'stepHour'; + public static readonly STEP_MINUTE_PROPERTY = 'stepMinute'; + public static readonly STEP_SECOND_PROPERTY = 'stepSecond'; + constructor(stringId: string, title: string, value: Moment, behavior: Behavior, placeholder?: string, description?: string, layout?: Layout, validations?: Array, component?: Component, parentTaskId?: string) { super(stringId, title, value, behavior, placeholder, description, layout, validations, component, parentTaskId); } + public get showSeconds(): boolean { + return AbstractBaseDataFieldComponent.resolveBooleanProperty( + this.component?.properties?.[DateTimeField.SHOW_SECONDS_PROPERTY], + false + ); + } + + public get stepHour(): number { + return AbstractBaseDataFieldComponent.resolveNumberProperty( + this.component?.properties?.[DateTimeField.STEP_HOUR_PROPERTY], + 1 + ); + } + + public get stepMinute(): number { + return AbstractBaseDataFieldComponent.resolveNumberProperty( + this.component?.properties?.[DateTimeField.STEP_MINUTE_PROPERTY], + 5 + ); + } + + + public get stepSecond(): number { + return AbstractBaseDataFieldComponent.resolveNumberProperty( + this.component?.properties?.[DateTimeField.STEP_SECOND_PROPERTY], + 1 + ); + } + + public get enableMeridian(): boolean { + return AbstractBaseDataFieldComponent.resolveBooleanProperty( + this.component?.properties?.[DateTimeField.ENABLE_MERIDIAN_PROPERTY], + false + ); + } + public getTypedComponentType(): string { return ComponentPrefixes.DATE_TIME + this.getComponentType(); } protected valueEquality(a: Moment, b: Moment): boolean { - return AbstractTimeInstanceField.isEqual(a, b, 'minute'); + return AbstractTimeInstanceField.isEqual(a, b, 'second'); } } diff --git a/projects/netgrif-components-core/src/lib/moment/time-formats.ts b/projects/netgrif-components-core/src/lib/moment/time-formats.ts index df01960302..780fd33710 100644 --- a/projects/netgrif-components-core/src/lib/moment/time-formats.ts +++ b/projects/netgrif-components-core/src/lib/moment/time-formats.ts @@ -1,5 +1,6 @@ export const DATE_FORMAT_STRING = 'DD.MM.YYYY'; export const DATE_TIME_FORMAT_STRING = 'DD.MM.YYYY HH:mm'; +export const DATE_TIME_SECONDS_FORMAT_STRING = 'DD.MM.YYYY HH:mm:ss'; // https://momentjs.com/docs/#/displaying/format/ export const DATE_FORMAT = { @@ -25,3 +26,18 @@ export const DATE_TIME_FORMAT = { monthYearA11yLabel: 'MMMM YYYY', }, }; + +export const DATE_TIME_SECONDS_FORMAT = { + parse: { + dateInput: [ + DATE_TIME_SECONDS_FORMAT_STRING, + DATE_TIME_FORMAT_STRING + ], + }, + display: { + dateInput: DATE_TIME_SECONDS_FORMAT_STRING, + monthYearLabel: 'MMM YYYY', + dateA11yLabel: 'Do MMMM YYYY HH:mm:ss', + monthYearA11yLabel: 'MMMM YYYY', + }, +}; diff --git a/projects/netgrif-components-core/src/lib/task-content/services/field-converter.service.ts b/projects/netgrif-components-core/src/lib/task-content/services/field-converter.service.ts index aec119d6ee..e0c44b31bf 100644 --- a/projects/netgrif-components-core/src/lib/task-content/services/field-converter.service.ts +++ b/projects/netgrif-components-core/src/lib/task-content/services/field-converter.service.ts @@ -11,7 +11,7 @@ import {DateTimeField} from '../../data-fields/date-time-field/models/date-time- import {UserField} from '../../data-fields/user-field/models/user-field'; import {ButtonField} from '../../data-fields/button-field/models/button-field'; import {FileField, FileUploadMIMEType} from '../../data-fields/file-field/models/file-field'; -import moment from 'moment'; +import moment, {Moment} from 'moment'; import {UserValue} from '../../data-fields/user-field/models/user-value'; import {FieldTypeResource} from '../model/field-type-resource'; import {FileListField} from '../../data-fields/file-list-field/models/file-list-field'; @@ -23,7 +23,7 @@ import {FilterField} from '../../data-fields/filter-field/models/filter-field'; import {I18nField} from '../../data-fields/i18n-field/models/i18n-field'; import {UserListField} from '../../data-fields/user-list-field/models/user-list-field'; import {UserListValue} from '../../data-fields/user-list-field/models/user-list-value'; -import {decodeBase64, encodeBase64} from "../../utility/base64"; +import {decodeBase64, encodeBase64} from '../../utility/base64'; import {CaseRefField} from '../../data-fields/case-ref-field/model/case-ref-field'; import {StringCollectionField} from '../../data-fields/string-collection-field/models/string-collection-field'; @@ -31,7 +31,8 @@ import {StringCollectionField} from '../../data-fields/string-collection-field/m providedIn: 'root' }) export class FieldConverterService { - private textFieldNames = [ 'richtextarea', 'htmltextarea', 'editor', 'htmlEditor' ] + + private textFieldNames = ['richtextarea', 'htmltextarea', 'editor', 'htmlEditor']; constructor() { } @@ -41,6 +42,7 @@ export class FieldConverterService { case FieldTypeResource.BOOLEAN: return new BooleanField(item.stringId, item.name, item.value as boolean, item.behavior, item.placeholder, item.description, item.layout, item.validations, item.component, item.parentTaskId); + case FieldTypeResource.TEXT: if (this.textFieldNames.includes(item.component?.name)) { return new TextAreaField(item.stringId, item.name, this.resolveTextValue(item, item.value), item.behavior, @@ -70,12 +72,7 @@ export class FieldConverterService { return new DateField(item.stringId, item.name, date, item.behavior, item.placeholder, item.description, item.layout, item.validations, item.component, item.parentTaskId); case FieldTypeResource.DATE_TIME: - let dateTime; - if (item.value) { - dateTime = moment(new Date(item.value[0], item.value[1] - 1, item.value[2], item.value[3], item.value[4])); - } - return new DateTimeField(item.stringId, item.name, dateTime, item.behavior, - item.placeholder, item.description, item.layout, item.validations, item.component, item.parentTaskId); + return new DateTimeField(item.stringId, item.name, this.resolveDateTime(item.value), item.behavior, item.placeholder, item.description, item.layout, item.validations, item.component, item.parentTaskId); case FieldTypeResource.USER: let user; if (item.value) { @@ -291,7 +288,7 @@ export class FieldConverterService { return new UserValue(value.id, value.name, value.surname, value.email); } if (this.resolveType(field) === FieldTypeResource.DATE_TIME) { - return moment(new Date(value[0], value[1] - 1, value[2], value[3], value[4])); + return this.resolveDateTime(value); } if (this.resolveType(field) === FieldTypeResource.MULTICHOICE) { const array = []; @@ -317,8 +314,33 @@ export class FieldConverterService { return value; } + protected resolveDateTime(value: any): Moment | undefined { + if (!value) { + return undefined; + } + if (moment.isMoment(value)) { + return value; + } + if (value instanceof Date) { + return moment(value); + } + if (Array.isArray(value)) { + const [year, month, day, hour = 0, minute = 0, second = 0, millisecond = 0] = value; + return moment({ + year, + month: month - 1, + date: day, + hour, + minute, + second, + millisecond + }); + } + return moment(value); + } + protected resolveAllowedTypes(allowTypes: string[]) { - return allowTypes?.length > 0 ? (allowTypes.length > 1 ? allowTypes as FileUploadMIMEType[] : allowTypes[0]) : null + return allowTypes?.length > 0 ? (allowTypes.length > 1 ? allowTypes as FileUploadMIMEType[] : allowTypes[0]) : null; } protected resolveByteSize(bytesSize) { diff --git a/projects/netgrif-components/src/lib/data-fields/date-time-field/date-time-default-field/date-time-default-field.component.html b/projects/netgrif-components/src/lib/data-fields/date-time-field/date-time-default-field/date-time-default-field.component.html index 5147fef117..7ce75bf04c 100644 --- a/projects/netgrif-components/src/lib/data-fields/date-time-field/date-time-default-field/date-time-default-field.component.html +++ b/projects/netgrif-components/src/lib/data-fields/date-time-field/date-time-default-field/date-time-default-field.component.html @@ -11,11 +11,12 @@ + [enableMeridian]="enableMeridian"> {{dataField.description}} {{getErrorMessage()}} diff --git a/projects/netgrif-components/src/lib/data-fields/date-time-field/date-time-default-field/date-time-default-field.component.ts b/projects/netgrif-components/src/lib/data-fields/date-time-field/date-time-default-field/date-time-default-field.component.ts index 15507b39f7..5aa375be43 100644 --- a/projects/netgrif-components/src/lib/data-fields/date-time-field/date-time-default-field/date-time-default-field.component.ts +++ b/projects/netgrif-components/src/lib/data-fields/date-time-field/date-time-default-field/date-time-default-field.component.ts @@ -5,28 +5,38 @@ import { DataFieldPortalData, DateTimeField, DATE_TIME_FORMAT, + DATE_TIME_SECONDS_FORMAT, LanguageService -} from '@netgrif/components-core' -import {TranslateService} from "@ngx-translate/core"; -import {NGX_MAT_DATE_FORMATS, NgxMatDateAdapter} from "@angular-material-components/datetime-picker"; -import {MAT_DATE_LOCALE} from "@angular/material/core"; +} from '@netgrif/components-core'; +import {TranslateService} from '@ngx-translate/core'; +import {NGX_MAT_DATE_FORMATS, NgxMatDateAdapter} from '@angular-material-components/datetime-picker'; +import {MAT_DATE_LOCALE} from '@angular/material/core'; + +export function dateTimeDefaultFormatsFactory(dataFieldPortalData?: DataFieldPortalData) { + return dataFieldPortalData?.dataField?.showSeconds + ? DATE_TIME_SECONDS_FORMAT + : DATE_TIME_FORMAT; +} @Component({ - selector: 'nc-date-time-default-field', - templateUrl: './date-time-default-field.component.html', - styleUrls: ['./date-time-default-field.component.scss'], + selector: 'nc-date-time-default-field', + templateUrl: './date-time-default-field.component.html', + styleUrls: ['./date-time-default-field.component.scss'], providers: [ - {provide: NGX_MAT_DATE_FORMATS, useValue: DATE_TIME_FORMAT} + { + provide: NGX_MAT_DATE_FORMATS, + useFactory: dateTimeDefaultFormatsFactory, + deps: [[new Optional(), DATA_FIELD_PORTAL_DATA]] + } ] }) export class DateTimeDefaultFieldComponent extends AbstractDateTimeDefaultFieldComponent { - constructor(_translate: TranslateService, - _adapter: NgxMatDateAdapter, - @Inject(MAT_DATE_LOCALE) protected _locale: string, - _languageService: LanguageService, - @Optional() @Inject(DATA_FIELD_PORTAL_DATA) dataFieldPortalData: DataFieldPortalData) { - super(_translate, _adapter, _locale, _languageService, dataFieldPortalData); - } - + constructor(_translate: TranslateService, + _adapter: NgxMatDateAdapter, + @Inject(MAT_DATE_LOCALE) protected _locale: string, + _languageService: LanguageService, + @Optional() @Inject(DATA_FIELD_PORTAL_DATA) dataFieldPortalData: DataFieldPortalData) { + super(_translate, _adapter, _locale, _languageService, dataFieldPortalData); + } }