diff --git a/frontend/package-lock.json b/frontend/package-lock.json index b8060cca5..7ffb6ec6d 100644 --- a/frontend/package-lock.json +++ b/frontend/package-lock.json @@ -22,17 +22,14 @@ "@maskito/angular": "^0.10.0", "@maskito/core": "^0.10.0", "@materia-ui/ngx-monaco-editor": "^6.0.0", - "@ng-web-apis/common": "^2.0.0", - "@ng-web-apis/mutation-observer": "^2.0.0", - "@ng-web-apis/resize-observer": "^2.0.0", "@start9labs/argon2": "^0.1.0", "@start9labs/emver": "^0.1.5", - "@start9labs/start-sdk": "0.4.0-rev0.lib0.rc4", - "@taiga-ui/addon-charts": "3.27.0", - "@taiga-ui/cdk": "3.27.0", - "@taiga-ui/core": "3.27.0", - "@taiga-ui/icons": "3.27.0", - "@taiga-ui/kit": "3.27.0", + "@start9labs/start-sdk": "0.4.0-rev0.lib0.rc5", + "@taiga-ui/addon-charts": "3.28.0", + "@taiga-ui/cdk": "3.28.0", + "@taiga-ui/core": "3.28.0", + "@taiga-ui/icons": "3.28.0", + "@taiga-ui/kit": "3.28.0", "angular-svg-round-progressbar": "^9.0.0", "ansi-to-html": "^0.7.2", "base64-js": "^1.5.1", @@ -97,14 +94,14 @@ "uuid": "8.3.2" }, "devDependencies": { - "@types/node": "18.15.0", + "@types/node": "16.4.13", "@types/uuid": "8.3.1", "husky": "^4.3.8", - "lint-staged": "^13.2.0", - "prettier": "^2.8.4", - "ts-node": "10.9.0", + "lint-staged": "^12.3.7", + "prettier": "^2.6.1", + "ts-node": "10.2.0", "tslint": "6.1.3", - "typescript": "4.8.4" + "typescript": "4.3.5" }, "peerDependencies": { "rxjs": ">=7.0.0" @@ -3831,9 +3828,9 @@ "integrity": "sha512-1dhiG03VkfEwSLx/JPKVms6srAbYFQgwfSGhwpUKMDliMXuAHGVaueStmqzVxn3JpH/HEVz0QW8w/PXHqjdiIg==" }, "node_modules/@start9labs/start-sdk": { - "version": "0.4.0-rev0.lib0.rc4", - "resolved": "https://registry.npmjs.org/@start9labs/start-sdk/-/start-sdk-0.4.0-rev0.lib0.rc4.tgz", - "integrity": "sha512-ouOpplLYCFFj5PutVtN5S0TI1UsdXA5nauOrFqKvLyhxazGjHprCpQ/fVHNSspPl/+ujNb7upzFxdZnWOE2oXw==", + "version": "0.4.0-rev0.lib0.rc5", + "resolved": "https://registry.npmjs.org/@start9labs/start-sdk/-/start-sdk-0.4.0-rev0.lib0.rc5.tgz", + "integrity": "sha512-2hAJE1id0VgpU8DJt/I+m/IEePmnspzF8BxUoLO3C+ZgyOZU1tEri1f9QCsS6OLn3J11xPlpY1VuSjP5CyHC+Q==", "dependencies": { "@iarna/toml": "^2.2.5", "ts-matches": "^5.4.1", @@ -3861,9 +3858,9 @@ } }, "node_modules/@taiga-ui/addon-charts": { - "version": "3.27.0", - "resolved": "https://registry.npmjs.org/@taiga-ui/addon-charts/-/addon-charts-3.27.0.tgz", - "integrity": "sha512-PZMwRl8pcbF1UcRXzrnzF6rcdg6ZMHSdiF7Q2VUO8Q39GFguyYNYIFdkRHOLvh1wbsXQKoSxho72RN2yeEybCA==", + "version": "3.28.0", + "resolved": "https://registry.npmjs.org/@taiga-ui/addon-charts/-/addon-charts-3.28.0.tgz", + "integrity": "sha512-ZLsOKrEfni8T+ppteJLULooRqtmvP8aZ0cf7WUEEjEeNR05out6eh8a3uHsnx241HI/or8b4OVKHbTmiFm9Mzg==", "dependencies": { "tslib": ">=2.0.0" }, @@ -3871,22 +3868,22 @@ "@angular/common": ">=12.0.0", "@angular/core": ">=12.0.0", "@ng-web-apis/common": ">=2.0.0", - "@taiga-ui/cdk": ">=3.27.0", - "@taiga-ui/core": ">=3.27.0", + "@taiga-ui/cdk": ">=3.28.0", + "@taiga-ui/core": ">=3.28.0", "@tinkoff/ng-polymorpheus": ">=4.0.0" } }, "node_modules/@taiga-ui/cdk": { - "version": "3.27.0", - "resolved": "https://registry.npmjs.org/@taiga-ui/cdk/-/cdk-3.27.0.tgz", - "integrity": "sha512-53XLDaQzStpjTV7a4X8658YVlaG7bp1JG4cgIamexylXwkWdsHa9o9KnFFOgsGO5I7heiQ2+kotKPWg7sgUwuQ==", + "version": "3.28.0", + "resolved": "https://registry.npmjs.org/@taiga-ui/cdk/-/cdk-3.28.0.tgz", + "integrity": "sha512-U9LTaiaHABanwxssPyutqiK1I8aUKX8ZpJ3CpMvhxszHC3zMYp4/N3RvxYfI8Mb2sqeLR8D+x85EElbWQIxRkA==", "dependencies": { "@ng-web-apis/common": "2.1.0", "@ng-web-apis/mutation-observer": "2.0.0", "@ng-web-apis/resize-observer": "2.0.0", "@tinkoff/ng-event-plugins": "3.1.0", "@tinkoff/ng-polymorpheus": "4.1.0", - "tslib": "2.5.0" + "tslib": "2.5.2" }, "optionalDependencies": { "ng-morph": "2.2.4", @@ -3901,11 +3898,11 @@ } }, "node_modules/@taiga-ui/core": { - "version": "3.27.0", - "resolved": "https://registry.npmjs.org/@taiga-ui/core/-/core-3.27.0.tgz", - "integrity": "sha512-kXODpMjhxR+4YcdEFVpVaC++G7scMCSuSKPuXXoOCWtEZsQTp/pvSCCxcg951/lLRyh0MkzvEHyz7a8BKikgog==", + "version": "3.28.0", + "resolved": "https://registry.npmjs.org/@taiga-ui/core/-/core-3.28.0.tgz", + "integrity": "sha512-7P62xmja4kpEwVe43zgMfSg1UmYzkdMjNr4DF1S1zU8u0gKQGYHcUFQL1hqTJk6W50xSXVyi4tlWKKCXMvEd5Q==", "dependencies": { - "@taiga-ui/i18n": "^3.27.0", + "@taiga-ui/i18n": "^3.28.0", "tslib": ">=2.0.0" }, "peerDependencies": { @@ -3917,17 +3914,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.27.0", - "@taiga-ui/i18n": ">=3.27.0", + "@taiga-ui/cdk": ">=3.28.0", + "@taiga-ui/i18n": ">=3.28.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.27.0", - "resolved": "https://registry.npmjs.org/@taiga-ui/i18n/-/i18n-3.27.0.tgz", - "integrity": "sha512-orOoo4CeecBc4GVMFcMhwvYo83wsudgtbnEbmFecE2NZO3wdntjOGE/TNpVM28JinO3uL5yabgDTd3UaxK6NSw==", + "version": "3.28.0", + "resolved": "https://registry.npmjs.org/@taiga-ui/i18n/-/i18n-3.28.0.tgz", + "integrity": "sha512-wf+BNATdoXhL5MnriF6iQ6xZtCGkD8wTwzosf4zsh7cGoDAPuV5pVWQRVRGGHgjE6gVJhSDdhCBGiM0QqdM3TQ==", "dependencies": { "tslib": ">=2.0.0" }, @@ -3937,17 +3934,17 @@ } }, "node_modules/@taiga-ui/icons": { - "version": "3.27.0", - "resolved": "https://registry.npmjs.org/@taiga-ui/icons/-/icons-3.27.0.tgz", - "integrity": "sha512-uXMe4B3cMgJ1qLfezsrOxvsHD9Bw6y39921GFMvlpeIwSEnXMc/rn1wEQpyd6Qo1Ib9AfFWHRDhBa7NPGnXllA==", + "version": "3.28.0", + "resolved": "https://registry.npmjs.org/@taiga-ui/icons/-/icons-3.28.0.tgz", + "integrity": "sha512-TzQEKgRLP5f+wGsDLMqnBUYPhCN/jgRzQbOWZPIrl+CzaYQTbsFRo1YlKEfMO3Wk55R8QBKv0qpj35+i2Q8Mmg==", "dependencies": { "tslib": "^2.2.0" } }, "node_modules/@taiga-ui/kit": { - "version": "3.27.0", - "resolved": "https://registry.npmjs.org/@taiga-ui/kit/-/kit-3.27.0.tgz", - "integrity": "sha512-2YYiku5wXCr1XeqZHnOgLTH4o3rW3EsCx5O8FRSy2LCtkGFLfLemV7E8x1WQqYzOlTW7cCa2goo+K1NMrUWfMQ==", + "version": "3.28.0", + "resolved": "https://registry.npmjs.org/@taiga-ui/kit/-/kit-3.28.0.tgz", + "integrity": "sha512-jLi/mmIS7kqG1FEY7LT+1uH76pEAiWZsZEQH+3rOwvEGaQBjLE73OPf83f/swaYtFm/DgJemMNnfEMYu661DYA==", "dependencies": { "@maskito/angular": "0.11.1", "@maskito/core": "0.11.1", @@ -3964,9 +3961,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.27.0", - "@taiga-ui/core": ">=3.27.0", - "@taiga-ui/i18n": ">=3.27.0", + "@taiga-ui/cdk": ">=3.28.0", + "@taiga-ui/core": ">=3.28.0", + "@taiga-ui/i18n": ">=3.28.0", "@tinkoff/ng-polymorpheus": ">=4.0.0", "rxjs": ">=6.0.0" } @@ -14517,9 +14514,9 @@ } }, "node_modules/tslib": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.5.0.tgz", - "integrity": "sha512-336iVw3rtn2BUK7ORdIAHTyxHGRIHVReokCR3XjbckJMK7ms8FysBfhLR8IXnAgy7T0PTPNBWKiH514FOW/WSg==" + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.5.2.tgz", + "integrity": "sha512-5svOrSA2w3iGFDs1HibEVBGbDrAY82bFQ3HZ3ixB+88nsbsWQoKqDRb5UBYAUPEzbBn6dAp5gRNXglySbx1MlA==" }, "node_modules/tslint": { "version": "6.1.3", diff --git a/frontend/package.json b/frontend/package.json index 84894f493..b92c8c172 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -47,16 +47,13 @@ "@maskito/angular": "^0.10.0", "@maskito/core": "^0.10.0", "@materia-ui/ngx-monaco-editor": "^6.0.0", - "@ng-web-apis/common": "^2.0.0", - "@ng-web-apis/mutation-observer": "^2.0.0", - "@ng-web-apis/resize-observer": "^2.0.0", "@start9labs/argon2": "^0.1.0", "@start9labs/emver": "^0.1.5", - "@taiga-ui/addon-charts": "3.27.0", - "@taiga-ui/cdk": "3.27.0", - "@taiga-ui/core": "3.27.0", - "@taiga-ui/icons": "3.27.0", - "@taiga-ui/kit": "3.27.0", + "@taiga-ui/addon-charts": "3.28.0", + "@taiga-ui/cdk": "3.28.0", + "@taiga-ui/core": "3.28.0", + "@taiga-ui/icons": "3.28.0", + "@taiga-ui/kit": "3.28.0", "angular-svg-round-progressbar": "^9.0.0", "ansi-to-html": "^0.7.2", "base64-js": "^1.5.1", @@ -78,7 +75,7 @@ "patch-db-client": "file: ../../../patch-db/client", "pbkdf2": "^3.1.2", "rxjs": "^7.5.6", - "@start9labs/start-sdk": "0.4.0-rev0.lib0.rc4", + "@start9labs/start-sdk": "0.4.0-rev0.lib0.rc5", "swiper": "^8.2.4", "ts-matches": "^5.2.1", "tslib": "^2.3.0", diff --git a/frontend/projects/shared/src/public-api.ts b/frontend/projects/shared/src/public-api.ts index 3e88cd75f..c7399173f 100644 --- a/frontend/projects/shared/src/public-api.ts +++ b/frontend/projects/shared/src/public-api.ts @@ -62,6 +62,7 @@ export * from './util/base-64' export * from './util/copy-to-clipboard' export * from './util/get-new-entries' export * from './util/get-pkg-id' +export * from './util/invert' export * from './util/misc.util' export * from './util/rpc.util' export * from './util/to-local-iso-string' diff --git a/frontend/projects/shared/src/util/invert.ts b/frontend/projects/shared/src/util/invert.ts new file mode 100644 index 000000000..6931b3660 --- /dev/null +++ b/frontend/projects/shared/src/util/invert.ts @@ -0,0 +1,12 @@ +export function invert< + T extends string | number | symbol, + D extends string | number | symbol, +>(obj: Record): Record { + const result = {} as Record + + for (const key in obj) { + result[obj[key]] = key + } + + return result +} diff --git a/frontend/projects/ui/src/app/app.providers.ts b/frontend/projects/ui/src/app/app.providers.ts index daa87f24b..67b8e38b5 100644 --- a/frontend/projects/ui/src/app/app.providers.ts +++ b/frontend/projects/ui/src/app/app.providers.ts @@ -6,6 +6,7 @@ import { TUI_DATE_FORMAT, TUI_DATE_SEPARATOR } from '@taiga-ui/cdk' import { tuiButtonOptionsProvider, tuiNumberFormatProvider, + tuiTextfieldOptionsProvider, } from '@taiga-ui/core' import { TUI_DATE_TIME_VALUE_TRANSFORMER, @@ -33,6 +34,7 @@ export const APP_PROVIDERS: Provider[] = [ IonNav, tuiNumberFormatProvider({ decimalSeparator: '.', thousandSeparator: '' }), tuiButtonOptionsProvider({ size: 'm' }), + tuiTextfieldOptionsProvider({ hintOnDisabled: true }), { provide: TUI_DATE_FORMAT, useValue: 'MDY', diff --git a/frontend/projects/ui/src/app/components/form/control.ts b/frontend/projects/ui/src/app/components/form/control.ts index 74756e3f5..e69f576ab 100644 --- a/frontend/projects/ui/src/app/components/form/control.ts +++ b/frontend/projects/ui/src/app/components/form/control.ts @@ -14,6 +14,13 @@ export abstract class Control { return this.control.spec } + // TODO: Properly handle already set immutable value + get readOnly(): boolean { + return ( + !!this.value && !!this.control.control?.pristine && this.control.immutable + ) + } + get value(): Value | null { return this.control.value } diff --git a/frontend/projects/ui/src/app/components/form/form-array/form-array.component.html b/frontend/projects/ui/src/app/components/form/form-array/form-array.component.html index e4921d742..25afe7012 100644 --- a/frontend/projects/ui/src/app/components/form/form-array/form-array.component.html +++ b/frontend/projects/ui/src/app/components/form/form-array/form-array.component.html @@ -1,8 +1,8 @@
{{ spec.name }} diff --git a/frontend/projects/ui/src/app/components/form/form-text/form-text.component.scss b/frontend/projects/ui/src/app/components/form/form-text/form-text.component.scss index a191523f7..eb42a700a 100644 --- a/frontend/projects/ui/src/app/components/form/form-text/form-text.component.scss +++ b/frontend/projects/ui/src/app/components/form/form-text/form-text.component.scss @@ -1,6 +1,6 @@ -.toggle { +.button { pointer-events: auto; - margin-left: auto; + margin-left: 0.25rem; } .masked { diff --git a/frontend/projects/ui/src/app/components/form/form-text/form-text.component.ts b/frontend/projects/ui/src/app/components/form/form-text/form-text.component.ts index 37da806c8..6be9d19bb 100644 --- a/frontend/projects/ui/src/app/components/form/form-text/form-text.component.ts +++ b/frontend/projects/ui/src/app/components/form/form-text/form-text.component.ts @@ -1,6 +1,7 @@ import { Component } from '@angular/core' import { ValueSpecText } from '@start9labs/start-sdk/lib/config/configTypes' import { Control } from '../control' +import { getDefaultString } from '../../../util/config-utilities' @Component({ selector: 'form-text', @@ -9,4 +10,8 @@ import { Control } from '../control' }) export class FormTextComponent extends Control { masked = true + + generate() { + this.value = getDefaultString(this.spec.generate || '') + } } diff --git a/frontend/projects/ui/src/app/components/form/form-textarea/form-textarea.component.html b/frontend/projects/ui/src/app/components/form/form-textarea/form-textarea.component.html index 38809fac4..7a2bf5149 100644 --- a/frontend/projects/ui/src/app/components/form/form-textarea/form-textarea.component.html +++ b/frontend/projects/ui/src/app/components/form/form-textarea/form-textarea.component.html @@ -1,5 +1,7 @@ diff --git a/frontend/projects/ui/src/app/components/form/form.module.ts b/frontend/projects/ui/src/app/components/form/form.module.ts index 4f2028f43..29e63a629 100644 --- a/frontend/projects/ui/src/app/components/form/form.module.ts +++ b/frontend/projects/ui/src/app/components/form/form.module.ts @@ -48,6 +48,7 @@ import { MustachePipe } from './mustache.pipe' import { ControlDirective } from './control.directive' import { FormColorComponent } from './form-color/form-color.component' import { FormDatetimeComponent } from './form-datetime/form-datetime.component' +import { HintPipe } from './hint.pipe' @NgModule({ imports: [ @@ -98,6 +99,7 @@ import { FormDatetimeComponent } from './form-datetime/form-datetime.component' FormObjectComponent, FormArrayComponent, MustachePipe, + HintPipe, ControlDirective, ], exports: [FormGroupComponent], diff --git a/frontend/projects/ui/src/app/components/form/hint.pipe.ts b/frontend/projects/ui/src/app/components/form/hint.pipe.ts new file mode 100644 index 000000000..ecc8258ea --- /dev/null +++ b/frontend/projects/ui/src/app/components/form/hint.pipe.ts @@ -0,0 +1,21 @@ +import { Pipe, PipeTransform } from '@angular/core' +import { ValueSpec } from '@start9labs/start-sdk/lib/config/configTypes' + +@Pipe({ + name: 'hint', +}) +export class HintPipe implements PipeTransform { + transform(spec: ValueSpec): string { + const hint = [] + + if (spec.description) { + hint.push(spec.description) + } + + if ('disabled' in spec && typeof spec.disabled === 'string') { + hint.push(`Disabled: ${spec.disabled}`) + } + + return hint.join('\n\n') + } +} diff --git a/frontend/projects/ui/src/app/services/api/api.fixures.ts b/frontend/projects/ui/src/app/services/api/api.fixures.ts index fcc35e7a4..9920ff1fb 100644 --- a/frontend/projects/ui/src/app/services/api/api.fixures.ts +++ b/frontend/projects/ui/src/app/services/api/api.fixures.ts @@ -717,6 +717,18 @@ export module Mock { ), }), ), + users: Value.multiselect({ + name: 'Users', + default: [], + maxLength: 2, + disabled: ['matt'], + values: { + matt: 'Matt Hill', + alex: 'Alex Inkin', + blue: 'Blue J', + lucy: 'Lucy', + }, + }), advanced: Value.object( { name: 'Advanced', @@ -900,19 +912,19 @@ export module Mock { }, ), ), - 'random-enum': Value.select({ - name: 'Random Enum', + 'random-select': Value.select({ + name: 'Random select', description: 'This is not even real.', warning: 'Be careful changing this!', required: { - default: 'null', + default: null, }, values: { - null: 'null', option1: 'option1', option2: 'option2', option3: 'option3', }, + disabled: ['option2'], }), 'favorite-number': /* TODO: Convert range for this value ((-100,100])*/ Value.number({ @@ -1037,8 +1049,13 @@ export module Mock { description: 'Options
  • Item 1
  • Item 2
', warning: 'Careful changing this', required: { default: 'internal' }, + disabled: ['fake'], }, Variants.of({ + fake: { + name: 'Fake', + spec: Config.of({}), + }, internal: { name: 'Internal', spec: Config.of({}), @@ -1113,6 +1130,10 @@ export module Mock { }), 'favorite-slogan': Value.text({ name: 'Favorite Slogan', + generate: { + charset: 'a-z,A-Z,2-9', + len: 20, + }, required: false, description: 'You most favorite slogan in the whole world, used for paying you.', diff --git a/frontend/projects/ui/src/app/services/form.service.ts b/frontend/projects/ui/src/app/services/form.service.ts index b50763208..0b57acd83 100644 --- a/frontend/projects/ui/src/app/services/form.service.ts +++ b/frontend/projects/ui/src/app/services/form.service.ts @@ -52,8 +52,6 @@ export class FormService { ): ValueSpecSelect { return { ...spec, - // TODO: implement disabled - disabled: false, type: 'select', default: selection, values: Object.fromEntries(