mirror of
https://github.com/Start9Labs/start-os.git
synced 2026-03-26 10:21:52 +00:00
feat: add datetime spec support (#2264)
This commit is contained in:
committed by
Aiden McClelland
parent
273b5768c4
commit
f6c09109ba
70
frontend/package-lock.json
generated
70
frontend/package-lock.json
generated
@@ -27,11 +27,11 @@
|
||||
"@ng-web-apis/resize-observer": "^2.0.0",
|
||||
"@start9labs/argon2": "^0.1.0",
|
||||
"@start9labs/emver": "^0.1.5",
|
||||
"@taiga-ui/addon-charts": "3.25.0",
|
||||
"@taiga-ui/cdk": "3.25.0",
|
||||
"@taiga-ui/core": "3.25.0",
|
||||
"@taiga-ui/icons": "3.25.0",
|
||||
"@taiga-ui/kit": "3.25.0",
|
||||
"@taiga-ui/addon-charts": "3.26.0",
|
||||
"@taiga-ui/cdk": "3.26.0",
|
||||
"@taiga-ui/core": "3.26.0",
|
||||
"@taiga-ui/icons": "3.26.0",
|
||||
"@taiga-ui/kit": "3.26.0",
|
||||
"angular-svg-round-progressbar": "^9.0.0",
|
||||
"ansi-to-html": "^0.7.2",
|
||||
"base64-js": "^1.5.1",
|
||||
@@ -3840,9 +3840,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@taiga-ui/addon-charts": {
|
||||
"version": "3.25.0",
|
||||
"resolved": "https://registry.npmjs.org/@taiga-ui/addon-charts/-/addon-charts-3.25.0.tgz",
|
||||
"integrity": "sha512-XE5s6XYjZYgxjO8sygVRVE5Cy2cAGMsRkX+nbpVCFaf0fMLhgpaWYzT7VnuddgVqaYtpLHb+mUMYkV8H83wX5w==",
|
||||
"version": "3.26.0",
|
||||
"resolved": "https://registry.npmjs.org/@taiga-ui/addon-charts/-/addon-charts-3.26.0.tgz",
|
||||
"integrity": "sha512-nkAzI+B4CcPogUrpEwANu3D8n3cJzuIakF//8MyOzxvg0S4olpL81t9/Mx4+zyXxqjVTaU8q2a/rJNaV+7SyRg==",
|
||||
"dependencies": {
|
||||
"tslib": ">=2.0.0"
|
||||
},
|
||||
@@ -3850,15 +3850,15 @@
|
||||
"@angular/common": ">=12.0.0",
|
||||
"@angular/core": ">=12.0.0",
|
||||
"@ng-web-apis/common": ">=2.0.0",
|
||||
"@taiga-ui/cdk": ">=3.25.0",
|
||||
"@taiga-ui/core": ">=3.25.0",
|
||||
"@taiga-ui/cdk": ">=3.26.0",
|
||||
"@taiga-ui/core": ">=3.26.0",
|
||||
"@tinkoff/ng-polymorpheus": ">=4.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@taiga-ui/cdk": {
|
||||
"version": "3.25.0",
|
||||
"resolved": "https://registry.npmjs.org/@taiga-ui/cdk/-/cdk-3.25.0.tgz",
|
||||
"integrity": "sha512-dHV5FdYiq5qBOJRyWqu+iwc2dxHtBHGK6xQXd+yk3FRXuAsfj22cZl1i3TL8RQptQZjL+6AyHKABTga6uUMliA==",
|
||||
"version": "3.26.0",
|
||||
"resolved": "https://registry.npmjs.org/@taiga-ui/cdk/-/cdk-3.26.0.tgz",
|
||||
"integrity": "sha512-vd2CMQ/Z6bhzCQSBSHjSoCIJEE2g4RKmjl3RBK/OdA/L46s9/nQS8oTRBG8I0zk8lNx7YHqqC6u9IY6BZgOeAg==",
|
||||
"dependencies": {
|
||||
"@ng-web-apis/common": "2.1.0",
|
||||
"@ng-web-apis/mutation-observer": "2.0.0",
|
||||
@@ -3868,7 +3868,7 @@
|
||||
"tslib": "2.5.0"
|
||||
},
|
||||
"optionalDependencies": {
|
||||
"ng-morph": "2.1.3",
|
||||
"ng-morph": "2.2.0",
|
||||
"parse5": "6.0.1"
|
||||
},
|
||||
"peerDependencies": {
|
||||
@@ -3880,11 +3880,11 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@taiga-ui/core": {
|
||||
"version": "3.25.0",
|
||||
"resolved": "https://registry.npmjs.org/@taiga-ui/core/-/core-3.25.0.tgz",
|
||||
"integrity": "sha512-I2ezwnWJcVEMqnMXKdBWQn7IPJYbTttFqPVrzW0UhmUGyp8eI++v2A8I+Ns/I8oDCSb/kwhbFIXmXCFZQBoWZg==",
|
||||
"version": "3.26.0",
|
||||
"resolved": "https://registry.npmjs.org/@taiga-ui/core/-/core-3.26.0.tgz",
|
||||
"integrity": "sha512-+IYn0ssZ3dO8Cm1HYAtbL5t+dvhp0RVzljdS72HBcr7IsnEhr2UDWWvsLv4DqsG4tXigWq6sL9wjXqg6/ylH4g==",
|
||||
"dependencies": {
|
||||
"@taiga-ui/i18n": "^3.25.0",
|
||||
"@taiga-ui/i18n": "^3.26.0",
|
||||
"tslib": ">=2.0.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
@@ -3896,17 +3896,17 @@
|
||||
"@angular/router": ">=12.0.0",
|
||||
"@ng-web-apis/common": ">=2.0.0",
|
||||
"@ng-web-apis/mutation-observer": ">=2.0.0",
|
||||
"@taiga-ui/cdk": ">=3.25.0",
|
||||
"@taiga-ui/i18n": ">=3.25.0",
|
||||
"@taiga-ui/cdk": ">=3.26.0",
|
||||
"@taiga-ui/i18n": ">=3.26.0",
|
||||
"@tinkoff/ng-event-plugins": ">=3.1.0",
|
||||
"@tinkoff/ng-polymorpheus": ">=4.0.0",
|
||||
"rxjs": ">=6.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@taiga-ui/i18n": {
|
||||
"version": "3.25.0",
|
||||
"resolved": "https://registry.npmjs.org/@taiga-ui/i18n/-/i18n-3.25.0.tgz",
|
||||
"integrity": "sha512-E/lLv84soT2qgu6q3ilF1bUOriMfW052QYpORYrJQvF9O1hxTLW5yv7AYEPYHnJFXEvt7rLFyvjoI56bFeLryw==",
|
||||
"version": "3.26.0",
|
||||
"resolved": "https://registry.npmjs.org/@taiga-ui/i18n/-/i18n-3.26.0.tgz",
|
||||
"integrity": "sha512-pI8IIQPYe3I7f/HQ4prCNpttEzwR1VA6ooJoaygVcSQDS8KVr03yyl9RBUzKpl57vnemuduVdfqM9LxX4bPeWQ==",
|
||||
"dependencies": {
|
||||
"tslib": ">=2.0.0"
|
||||
},
|
||||
@@ -3916,17 +3916,17 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@taiga-ui/icons": {
|
||||
"version": "3.25.0",
|
||||
"resolved": "https://registry.npmjs.org/@taiga-ui/icons/-/icons-3.25.0.tgz",
|
||||
"integrity": "sha512-kXsKCifldnmrk/HcVZ8HqX68gHyZXsskaH0mrgq4CE3/8iiVmUBtqkgay1Rc6dubmzlPjD7/fr9nl/Wkf9zALA==",
|
||||
"version": "3.26.0",
|
||||
"resolved": "https://registry.npmjs.org/@taiga-ui/icons/-/icons-3.26.0.tgz",
|
||||
"integrity": "sha512-q42C7LYqmOEf1P6GZPl6we5YZe9dboke4kNmbSYxWMT1EWCsgPWK8QmK02BsDeltUwSp7cnCP7jGZG1lkbuzKg==",
|
||||
"dependencies": {
|
||||
"tslib": "^2.2.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@taiga-ui/kit": {
|
||||
"version": "3.25.0",
|
||||
"resolved": "https://registry.npmjs.org/@taiga-ui/kit/-/kit-3.25.0.tgz",
|
||||
"integrity": "sha512-mLTpcwpkMrwo8WPtezhJTBcvNPvQwZOUuMD3LkEWQ9g04o3flg+W9W6TJTQeg7Eqwp8ciq/INuSMcsmzgBd2uA==",
|
||||
"version": "3.26.0",
|
||||
"resolved": "https://registry.npmjs.org/@taiga-ui/kit/-/kit-3.26.0.tgz",
|
||||
"integrity": "sha512-Sdp9FKSi/+C2PgirSLr03YQNyboewhFOaFRtT6cBXzscHJLfTWLSv6nNq1kMDLueVTtuPJjksAXsHj+fpnWIiQ==",
|
||||
"dependencies": {
|
||||
"@ng-web-apis/intersection-observer": "3.0.0",
|
||||
"text-mask-core": "5.1.2",
|
||||
@@ -3940,9 +3940,9 @@
|
||||
"@ng-web-apis/common": ">=2.0.0",
|
||||
"@ng-web-apis/mutation-observer": ">=2.0.0",
|
||||
"@ng-web-apis/resize-observer": ">=2.0.0",
|
||||
"@taiga-ui/cdk": ">=3.25.0",
|
||||
"@taiga-ui/core": ">=3.25.0",
|
||||
"@taiga-ui/i18n": ">=3.25.0",
|
||||
"@taiga-ui/cdk": ">=3.26.0",
|
||||
"@taiga-ui/core": ">=3.26.0",
|
||||
"@taiga-ui/i18n": ">=3.26.0",
|
||||
"@tinkoff/ng-polymorpheus": ">=4.0.0",
|
||||
"rxjs": ">=6.0.0"
|
||||
}
|
||||
@@ -10270,9 +10270,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/ng-morph": {
|
||||
"version": "2.1.3",
|
||||
"resolved": "https://registry.npmjs.org/ng-morph/-/ng-morph-2.1.3.tgz",
|
||||
"integrity": "sha512-bFeSMSn2ORgtYw4ZmwISJ/RGdZxi03IwODrnXB6FbTEvmyfuTCB7x0FyQsm8euNX43fTp3FZclCZpRmO8t5w8w==",
|
||||
"version": "2.2.0",
|
||||
"resolved": "https://registry.npmjs.org/ng-morph/-/ng-morph-2.2.0.tgz",
|
||||
"integrity": "sha512-0CEswQ+QrxPBWv1dBBu/N6idk0wIXkdFmqk+GW55/Ta7DJTKMCPZLVGXpp+Lia9XF55vVyxnOBw9J3QNN2Dv5A==",
|
||||
"optional": true,
|
||||
"dependencies": {
|
||||
"jsonc-parser": "3.0.0",
|
||||
|
||||
@@ -52,11 +52,11 @@
|
||||
"@ng-web-apis/resize-observer": "^2.0.0",
|
||||
"@start9labs/argon2": "^0.1.0",
|
||||
"@start9labs/emver": "^0.1.5",
|
||||
"@taiga-ui/addon-charts": "3.25.0",
|
||||
"@taiga-ui/cdk": "3.25.0",
|
||||
"@taiga-ui/core": "3.25.0",
|
||||
"@taiga-ui/icons": "3.25.0",
|
||||
"@taiga-ui/kit": "3.25.0",
|
||||
"@taiga-ui/addon-charts": "3.26.0",
|
||||
"@taiga-ui/cdk": "3.26.0",
|
||||
"@taiga-ui/core": "3.26.0",
|
||||
"@taiga-ui/icons": "3.26.0",
|
||||
"@taiga-ui/kit": "3.26.0",
|
||||
"angular-svg-round-progressbar": "^9.0.0",
|
||||
"ansi-to-html": "^0.7.2",
|
||||
"base64-js": "^1.5.1",
|
||||
|
||||
@@ -2,10 +2,15 @@ import { APP_INITIALIZER, Provider } from '@angular/core'
|
||||
import { UntypedFormBuilder } from '@angular/forms'
|
||||
import { Router, RouteReuseStrategy } from '@angular/router'
|
||||
import { IonicRouteStrategy, IonNav } from '@ionic/angular'
|
||||
import { TUI_DATE_FORMAT, TUI_DATE_SEPARATOR } from '@taiga-ui/cdk'
|
||||
import {
|
||||
tuiButtonOptionsProvider,
|
||||
tuiNumberFormatProvider,
|
||||
} from '@taiga-ui/core'
|
||||
import {
|
||||
TUI_DATE_TIME_VALUE_TRANSFORMER,
|
||||
TUI_DATE_VALUE_TRANSFORMER,
|
||||
} from '@taiga-ui/kit'
|
||||
import { RELATIVE_URL, THEME, WorkspaceConfig } from '@start9labs/shared'
|
||||
import { ApiService } from './services/api/embassy-api.service'
|
||||
import { MockApiService } from './services/api/embassy-mock-api.service'
|
||||
@@ -14,6 +19,8 @@ import { AuthService } from './services/auth.service'
|
||||
import { ClientStorageService } from './services/client-storage.service'
|
||||
import { FilterPackagesPipe } from '../../../marketplace/src/pipes/filter-packages.pipe'
|
||||
import { ThemeSwitcherService } from './services/theme-switcher.service'
|
||||
import { DateTransformerService } from './services/date-transformer.service'
|
||||
import { DatetimeTransformerService } from './services/datetime-transformer.service'
|
||||
|
||||
const {
|
||||
useMocks,
|
||||
@@ -26,6 +33,22 @@ export const APP_PROVIDERS: Provider[] = [
|
||||
IonNav,
|
||||
tuiNumberFormatProvider({ decimalSeparator: '.', thousandSeparator: '' }),
|
||||
tuiButtonOptionsProvider({ size: 'm' }),
|
||||
{
|
||||
provide: TUI_DATE_FORMAT,
|
||||
useValue: 'MDY',
|
||||
},
|
||||
{
|
||||
provide: TUI_DATE_SEPARATOR,
|
||||
useValue: '/',
|
||||
},
|
||||
{
|
||||
provide: TUI_DATE_VALUE_TRANSFORMER,
|
||||
useClass: DateTransformerService,
|
||||
},
|
||||
{
|
||||
provide: TUI_DATE_TIME_VALUE_TRANSFORMER,
|
||||
useClass: DatetimeTransformerService,
|
||||
},
|
||||
{
|
||||
provide: RouteReuseStrategy,
|
||||
useClass: IonicRouteStrategy,
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
<ng-container [ngSwitch]="spec.type">
|
||||
<form-color *ngSwitchCase="'color'"></form-color>
|
||||
<form-datetime *ngSwitchCase="'datetime'"></form-datetime>
|
||||
<form-file *ngSwitchCase="'file'"></form-file>
|
||||
<form-multiselect *ngSwitchCase="'multiselect'"></form-multiselect>
|
||||
<form-number *ngSwitchCase="'number'"></form-number>
|
||||
|
||||
@@ -0,0 +1,34 @@
|
||||
<ng-container [ngSwitch]="spec.inputmode" [tuiHintContent]="spec.description">
|
||||
<tui-input-time
|
||||
*ngSwitchCase="'time'"
|
||||
[pseudoInvalid]="invalid"
|
||||
[ngModel]="getTime(value)"
|
||||
(ngModelChange)="value = $event?.toString() || null"
|
||||
(focusedChange)="onFocus($event)"
|
||||
>
|
||||
{{ spec.name }}
|
||||
<span *ngIf="spec.required">*</span>
|
||||
</tui-input-time>
|
||||
<tui-input-date
|
||||
*ngSwitchCase="'date'"
|
||||
[pseudoInvalid]="invalid"
|
||||
[min]="spec.min ? (spec.min | tuiMapper : getLimit)[0] : min"
|
||||
[max]="spec.max ? (spec.max | tuiMapper : getLimit)[0] : max"
|
||||
[(ngModel)]="value"
|
||||
(focusedChange)="onFocus($event)"
|
||||
>
|
||||
{{ spec.name }}
|
||||
<span *ngIf="spec.required">*</span>
|
||||
</tui-input-date>
|
||||
<tui-input-date-time
|
||||
*ngSwitchCase="'datetime-local'"
|
||||
[pseudoInvalid]="invalid"
|
||||
[min]="spec.min ? (spec.min | tuiMapper : getLimit) : min"
|
||||
[max]="spec.max ? (spec.max | tuiMapper : getLimit) : max"
|
||||
[(ngModel)]="value"
|
||||
(focusedChange)="onFocus($event)"
|
||||
>
|
||||
{{ spec.name }}
|
||||
<span *ngIf="spec.required">*</span>
|
||||
</tui-input-date-time>
|
||||
</ng-container>
|
||||
@@ -0,0 +1,33 @@
|
||||
import { Component } from '@angular/core'
|
||||
import {
|
||||
TUI_FIRST_DAY,
|
||||
TUI_LAST_DAY,
|
||||
TuiDay,
|
||||
tuiPure,
|
||||
TuiTime,
|
||||
} from '@taiga-ui/cdk'
|
||||
import { ValueSpecDatetime } from 'start-sdk/lib/config/configTypes'
|
||||
import { Control } from '../control'
|
||||
|
||||
@Component({
|
||||
selector: 'form-datetime',
|
||||
templateUrl: './form-datetime.component.html',
|
||||
})
|
||||
export class FormDatetimeComponent extends Control<ValueSpecDatetime, string> {
|
||||
readonly min = TUI_FIRST_DAY
|
||||
readonly max = TUI_LAST_DAY
|
||||
|
||||
@tuiPure
|
||||
getTime(value: string | null) {
|
||||
return value ? TuiTime.fromString(value) : null
|
||||
}
|
||||
|
||||
getLimit(limit: string): [TuiDay, TuiTime] {
|
||||
return [
|
||||
TuiDay.jsonParse(limit.slice(0, 10)),
|
||||
limit.length === 10
|
||||
? new TuiTime(0, 0)
|
||||
: TuiTime.fromString(limit.slice(-5)),
|
||||
]
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,9 @@
|
||||
import { Provider, SkipSelf } from '@angular/core'
|
||||
import { TUI_ARROW_MODE } from '@taiga-ui/kit'
|
||||
import {
|
||||
TUI_ARROW_MODE,
|
||||
tuiInputDateOptionsProvider,
|
||||
tuiInputTimeOptionsProvider,
|
||||
} from '@taiga-ui/kit'
|
||||
import { TUI_DEFAULT_ERROR_MESSAGE } from '@taiga-ui/core'
|
||||
import { ControlContainer } from '@angular/forms'
|
||||
import { identity, of } from 'rxjs'
|
||||
@@ -21,4 +25,10 @@ export const FORM_GROUP_PROVIDERS: Provider[] = [
|
||||
disabled: null,
|
||||
},
|
||||
},
|
||||
tuiInputDateOptionsProvider({
|
||||
nativePicker: true,
|
||||
}),
|
||||
tuiInputTimeOptionsProvider({
|
||||
nativePicker: true,
|
||||
}),
|
||||
]
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
import { NgModule } from '@angular/core'
|
||||
import { CommonModule } from '@angular/common'
|
||||
import { FormsModule, ReactiveFormsModule } from '@angular/forms'
|
||||
import { TuiValueChangesModule } from '@taiga-ui/cdk'
|
||||
import { MaskitoModule } from '@maskito/angular'
|
||||
import { TuiMapperPipeModule, TuiValueChangesModule } from '@taiga-ui/cdk'
|
||||
import {
|
||||
TuiButtonModule,
|
||||
TuiErrorModule,
|
||||
@@ -17,9 +18,12 @@ import {
|
||||
import {
|
||||
TuiElasticContainerModule,
|
||||
TuiFieldErrorPipeModule,
|
||||
TuiInputDateModule,
|
||||
TuiInputDateTimeModule,
|
||||
TuiInputFilesModule,
|
||||
TuiInputModule,
|
||||
TuiInputNumberModule,
|
||||
TuiInputTimeModule,
|
||||
TuiMultiSelectModule,
|
||||
TuiPromptModule,
|
||||
TuiSelectModule,
|
||||
@@ -43,7 +47,7 @@ import { FormControlComponent } from './form-control/form-control.component'
|
||||
import { MustachePipe } from './mustache.pipe'
|
||||
import { ControlDirective } from './control.directive'
|
||||
import { FormColorComponent } from './form-color/form-color.component'
|
||||
import { MaskitoModule } from '@maskito/angular'
|
||||
import { FormDatetimeComponent } from './form-datetime/form-datetime.component'
|
||||
|
||||
@NgModule({
|
||||
imports: [
|
||||
@@ -73,11 +77,16 @@ import { MaskitoModule } from '@maskito/angular'
|
||||
MaskitoModule,
|
||||
TuiSvgModule,
|
||||
TuiWrapperModule,
|
||||
TuiInputDateModule,
|
||||
TuiInputTimeModule,
|
||||
TuiInputDateTimeModule,
|
||||
TuiMapperPipeModule,
|
||||
],
|
||||
declarations: [
|
||||
FormGroupComponent,
|
||||
FormControlComponent,
|
||||
FormColorComponent,
|
||||
FormDatetimeComponent,
|
||||
FormTextComponent,
|
||||
FormToggleComponent,
|
||||
FormTextareaComponent,
|
||||
|
||||
@@ -774,6 +774,50 @@ export module Mock {
|
||||
required: false,
|
||||
default: '#000000',
|
||||
},
|
||||
chronos: {
|
||||
name: 'Chronos',
|
||||
type: 'object',
|
||||
description: 'Various time related settings',
|
||||
warning: null,
|
||||
spec: {
|
||||
time: {
|
||||
name: 'Time',
|
||||
type: 'datetime',
|
||||
inputmode: 'time',
|
||||
description: 'Time of day',
|
||||
warning: null,
|
||||
required: true,
|
||||
min: '12:00',
|
||||
max: '16:00',
|
||||
step: null,
|
||||
default: '12:00',
|
||||
},
|
||||
date: {
|
||||
name: 'Date',
|
||||
type: 'datetime',
|
||||
inputmode: 'date',
|
||||
description: 'Just a date',
|
||||
warning: null,
|
||||
required: true,
|
||||
min: '2023-01-01',
|
||||
max: '2023-12-31',
|
||||
step: null,
|
||||
default: '2023-05-01',
|
||||
},
|
||||
datetime: {
|
||||
name: 'Date and time',
|
||||
type: 'datetime',
|
||||
inputmode: 'datetime-local',
|
||||
description: 'Both date and time',
|
||||
warning: null,
|
||||
required: true,
|
||||
min: '2023-01-01T12:00',
|
||||
max: '2023-12-31T16:00',
|
||||
step: null,
|
||||
default: '2023-05-01T18:30',
|
||||
},
|
||||
},
|
||||
},
|
||||
advanced: {
|
||||
name: 'Advanced',
|
||||
type: 'object',
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
import { Injectable } from '@angular/core'
|
||||
import { AbstractTuiValueTransformer, TuiDay } from '@taiga-ui/cdk'
|
||||
|
||||
type From = TuiDay | null
|
||||
type To = string | null
|
||||
|
||||
@Injectable()
|
||||
export class DateTransformerService extends AbstractTuiValueTransformer<
|
||||
From,
|
||||
To
|
||||
> {
|
||||
fromControlValue(controlValue: To): From {
|
||||
return controlValue ? TuiDay.jsonParse(controlValue) : null
|
||||
}
|
||||
|
||||
toControlValue(componentValue: From): To {
|
||||
return componentValue?.toJSON() || null
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
import { Injectable } from '@angular/core'
|
||||
import { AbstractTuiValueTransformer, TuiDay, TuiTime } from '@taiga-ui/cdk'
|
||||
|
||||
type From = [TuiDay | null, TuiTime | null] | null
|
||||
type To = string | null
|
||||
|
||||
@Injectable()
|
||||
export class DatetimeTransformerService extends AbstractTuiValueTransformer<
|
||||
From,
|
||||
To
|
||||
> {
|
||||
fromControlValue(controlValue: To): From {
|
||||
if (!controlValue) {
|
||||
return null
|
||||
}
|
||||
|
||||
const day = TuiDay.jsonParse(controlValue.slice(0, 10))
|
||||
const time =
|
||||
controlValue.length === 16
|
||||
? TuiTime.fromString(controlValue.slice(-5))
|
||||
: null
|
||||
|
||||
return [day, time]
|
||||
}
|
||||
|
||||
toControlValue(componentValue: From): To {
|
||||
if (!componentValue) {
|
||||
return null
|
||||
}
|
||||
|
||||
const [day, time] = componentValue
|
||||
|
||||
return day?.toJSON() + (time ? `T${time.toString()}` : '')
|
||||
}
|
||||
}
|
||||
@@ -29,6 +29,7 @@ import {
|
||||
ValueSpecTextarea,
|
||||
unionValueKey,
|
||||
ValueSpecColor,
|
||||
ValueSpecDatetime,
|
||||
} from 'start-sdk/lib/config/configTypes'
|
||||
const Mustache = require('mustache')
|
||||
|
||||
@@ -131,6 +132,13 @@ export class FormService {
|
||||
value = spec.default || null
|
||||
}
|
||||
return this.formBuilder.control(value, colorValidators(spec))
|
||||
case 'datetime':
|
||||
if (currentValue !== undefined) {
|
||||
value = currentValue
|
||||
} else {
|
||||
value = spec.default || null
|
||||
}
|
||||
return this.formBuilder.control(value, datetimeValidators(spec))
|
||||
case 'object':
|
||||
return this.getFormGroup(spec.spec, [], currentValue)
|
||||
case 'list':
|
||||
@@ -216,6 +224,28 @@ function colorValidators({ required }: ValueSpecColor): ValidatorFn[] {
|
||||
return validators
|
||||
}
|
||||
|
||||
function datetimeValidators({
|
||||
required,
|
||||
min,
|
||||
max,
|
||||
}: ValueSpecDatetime): ValidatorFn[] {
|
||||
const validators: ValidatorFn[] = []
|
||||
|
||||
if (required) {
|
||||
validators.push(Validators.required)
|
||||
}
|
||||
|
||||
if (min) {
|
||||
validators.push(datetimeMin(min))
|
||||
}
|
||||
|
||||
if (max) {
|
||||
validators.push(datetimeMax(max))
|
||||
}
|
||||
|
||||
return validators
|
||||
}
|
||||
|
||||
function numberValidators(
|
||||
spec: ValueSpecNumber | ListValueSpecNumber,
|
||||
): ValidatorFn[] {
|
||||
@@ -316,6 +346,28 @@ export function listInRange(
|
||||
}
|
||||
}
|
||||
|
||||
export function datetimeMin(min: string): ValidatorFn {
|
||||
return ({ value }) => {
|
||||
if (!value) return null
|
||||
|
||||
const date = new Date(value.length === 5 ? `2000-01-01T${value}` : value)
|
||||
const minDate = new Date(min.length === 5 ? `2000-01-01T${min}` : min)
|
||||
|
||||
return date < minDate ? { datetimeMin: `Minimum is ${min}` } : null
|
||||
}
|
||||
}
|
||||
|
||||
export function datetimeMax(max: string): ValidatorFn {
|
||||
return ({ value }) => {
|
||||
if (!value) return null
|
||||
|
||||
const date = new Date(value.length === 5 ? `2000-01-01T${value}` : value)
|
||||
const maxDate = new Date(max.length === 5 ? `2000-01-01T${max}` : max)
|
||||
|
||||
return date > maxDate ? { datetimeMin: `Maximum is ${max}` } : null
|
||||
}
|
||||
}
|
||||
|
||||
export function textLengthInRange(
|
||||
minLength: number | null,
|
||||
maxLength: number | null,
|
||||
|
||||
Reference in New Issue
Block a user