diff --git a/frontend/package-lock.json b/frontend/package-lock.json index 9c5f6d31a..73e26c53e 100644 --- a/frontend/package-lock.json +++ b/frontend/package-lock.json @@ -49,7 +49,7 @@ "patch-db-client": "file: ../../../patch-db/client", "pbkdf2": "^3.1.2", "rxjs": "^7.5.6", - "start-sdk": "^0.4.0-lib0.alpha9", + "start-sdk": "^0.4.0-lib0.beta3", "swiper": "^8.2.4", "ts-matches": "^5.2.1", "tslib": "^2.3.0", @@ -13771,9 +13771,9 @@ } }, "node_modules/start-sdk": { - "version": "0.4.0-lib0.alpha9", - "resolved": "https://registry.npmjs.org/start-sdk/-/start-sdk-0.4.0-lib0.alpha9.tgz", - "integrity": "sha512-F+ekxjVEKgNv7SU5XCe1rn7PqbKsbqCSS7pecMxcKQmbNlic4iyo3+lIS9JuPBSyTTjJlzJFzkdaxGwf4h83mg==", + "version": "0.4.0-lib0.beta3", + "resolved": "https://registry.npmjs.org/start-sdk/-/start-sdk-0.4.0-lib0.beta3.tgz", + "integrity": "sha512-MuKc4QB6rR2UOVZaT3MApJf5jGtIzUmKGLS4mm6Zqvmud+MP/FQTRB8y7CZjyBmBGXQZcSyFUcEBkR/hQTmLXA==", "dependencies": { "@iarna/toml": "^2.2.5", "lodash": "^4.17.21", diff --git a/frontend/package.json b/frontend/package.json index 033fd2b9f..4655d0eac 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -74,7 +74,7 @@ "patch-db-client": "file: ../../../patch-db/client", "pbkdf2": "^3.1.2", "rxjs": "^7.5.6", - "start-sdk": "^0.4.0-lib0.alpha9", + "start-sdk": "^0.4.0-lib0.beta3", "swiper": "^8.2.4", "ts-matches": "^5.2.1", "tslib": "^2.3.0", diff --git a/frontend/projects/ui/src/app/components/backup-drives/backup-drives.component.ts b/frontend/projects/ui/src/app/components/backup-drives/backup-drives.component.ts index f25957c63..738c29939 100644 --- a/frontend/projects/ui/src/app/components/backup-drives/backup-drives.component.ts +++ b/frontend/projects/ui/src/app/components/backup-drives/backup-drives.component.ts @@ -12,7 +12,7 @@ import { ModalController, } from '@ionic/angular' import { GenericFormPage } from 'src/app/modals/generic-form/generic-form.page' -import { InputSpec } from 'start-sdk/types/config-types' +import { InputSpec } from 'start-sdk/lib/config/config-types' import { ApiService } from 'src/app/services/api/embassy-api.service' import { ErrorToastService } from '@start9labs/shared' import { MappedBackupTarget } from 'src/app/types/mapped-backup-target' @@ -282,7 +282,7 @@ const CifsSpec: InputSpec = { 'The hostname of your target device on the Local Area Network.', placeholder: `e.g. 'My Computer' OR 'my-computer.local'`, pattern: '^[a-zA-Z0-9._-]+( [a-zA-Z0-9]+)*$', - 'pattern-description': `Must be a valid hostname. e.g. 'My Computer' OR 'my-computer.local'`, + patternDescription: `Must be a valid hostname. e.g. 'My Computer' OR 'my-computer.local'`, nullable: false, masked: false, default: null, @@ -295,7 +295,7 @@ const CifsSpec: InputSpec = { description: `On Windows, this is the fully qualified path to the shared folder, (e.g. /Desktop/my-folder).\n\n On Linux and Mac, this is the literal name of the shared folder (e.g. my-shared-folder).`, placeholder: 'e.g. my-shared-folder or /Desktop/my-folder', pattern: null, - 'pattern-description': null, + patternDescription: null, nullable: false, masked: false, default: null, @@ -308,7 +308,7 @@ const CifsSpec: InputSpec = { description: `On Linux, this is the samba username you created when sharing the folder.\n\n On Mac and Windows, this is the username of the user who is sharing the folder.`, placeholder: null, pattern: null, - 'pattern-description': null, + patternDescription: null, nullable: false, masked: false, default: null, @@ -321,7 +321,7 @@ const CifsSpec: InputSpec = { description: `On Linux, this is the samba password you created when sharing the folder.\n\n On Mac and Windows, this is the password of the user who is sharing the folder.`, placeholder: null, pattern: null, - 'pattern-description': null, + patternDescription: null, nullable: true, masked: true, default: null, diff --git a/frontend/projects/ui/src/app/components/form-object/form-object/controls/form-file/form-file.component.ts b/frontend/projects/ui/src/app/components/form-object/form-object/controls/form-file/form-file.component.ts index 83c550b44..b95fbc7a8 100644 --- a/frontend/projects/ui/src/app/components/form-object/form-object/controls/form-file/form-file.component.ts +++ b/frontend/projects/ui/src/app/components/form-object/form-object/controls/form-file/form-file.component.ts @@ -1,6 +1,6 @@ import { Component, Input } from '@angular/core' import { AbstractControl } from '@angular/forms' -import { ValueSpecOf } from 'start-sdk/types/config-types' +import { ValueSpecOf } from 'start-sdk/lib/config/config-types' @Component({ selector: 'form-file', diff --git a/frontend/projects/ui/src/app/components/form-object/form-object/controls/form-input/form-input.component.html b/frontend/projects/ui/src/app/components/form-object/form-object/controls/form-input/form-input.component.html index b4a14447c..639d425bd 100644 --- a/frontend/projects/ui/src/app/components/form-object/form-object/controls/form-input/form-input.component.html +++ b/frontend/projects/ui/src/app/components/form-object/form-object/controls/form-input/form-input.component.html @@ -57,6 +57,6 @@

- {{ errors | getError : $any(spec)['pattern-description'] }} + {{ errors | getError : $any(spec).patternDescription }}

diff --git a/frontend/projects/ui/src/app/components/form-object/form-object/controls/form-input/form-input.component.ts b/frontend/projects/ui/src/app/components/form-object/form-object/controls/form-input/form-input.component.ts index c79cbada2..551608bbb 100644 --- a/frontend/projects/ui/src/app/components/form-object/form-object/controls/form-input/form-input.component.ts +++ b/frontend/projects/ui/src/app/components/form-object/form-object/controls/form-input/form-input.component.ts @@ -1,6 +1,6 @@ import { Component, Input, inject, Output, EventEmitter } from '@angular/core' import { FormControl } from '@angular/forms' -import { ValueSpecOf } from 'start-sdk/types/config-types' +import { ValueSpecOf } from 'start-sdk/lib/config/config-types' import { THEME } from '@start9labs/shared' @Component({ diff --git a/frontend/projects/ui/src/app/components/form-object/form-object/controls/form-select/form-select.component.html b/frontend/projects/ui/src/app/components/form-object/form-object/controls/form-select/form-select.component.html index 8beb43015..d9fe4cb0d 100644 --- a/frontend/projects/ui/src/app/components/form-object/form-object/controls/form-select/form-select.component.html +++ b/frontend/projects/ui/src/app/components/form-object/form-object/controls/form-select/form-select.component.html @@ -31,11 +31,14 @@ [selectedText]=" spec.type === 'multiselect' && control.value?.length > 1 ? '[' + control.value.length + ' selected]' - : spec['value-names'][control.value] + : spec.values[control.value] " > - - {{ spec['value-names'][option] }} + + {{ option.value }} diff --git a/frontend/projects/ui/src/app/components/form-object/form-object/controls/form-select/form-select.component.ts b/frontend/projects/ui/src/app/components/form-object/form-object/controls/form-select/form-select.component.ts index ec49cf9bc..7688b0a9d 100644 --- a/frontend/projects/ui/src/app/components/form-object/form-object/controls/form-select/form-select.component.ts +++ b/frontend/projects/ui/src/app/components/form-object/form-object/controls/form-select/form-select.component.ts @@ -1,6 +1,6 @@ import { Component, Input } from '@angular/core' import { FormControl } from '@angular/forms' -import { ValueSpecOf } from 'start-sdk/types/config-types' +import { ValueSpecOf } from 'start-sdk/lib/config/config-types' @Component({ selector: 'form-select', diff --git a/frontend/projects/ui/src/app/components/form-object/form-object/controls/form-subform/form-subform.component.ts b/frontend/projects/ui/src/app/components/form-object/form-object/controls/form-subform/form-subform.component.ts index 04b44a353..1508a1654 100644 --- a/frontend/projects/ui/src/app/components/form-object/form-object/controls/form-subform/form-subform.component.ts +++ b/frontend/projects/ui/src/app/components/form-object/form-object/controls/form-subform/form-subform.component.ts @@ -1,6 +1,6 @@ import { Component, Input, Output, EventEmitter } from '@angular/core' import { AbstractControl } from '@angular/forms' -import { ValueSpecOf } from 'start-sdk/types/config-types' +import { ValueSpecOf } from 'start-sdk/lib/config/config-types' @Component({ selector: 'form-subform', diff --git a/frontend/projects/ui/src/app/components/form-object/form-object/form-object.component.html b/frontend/projects/ui/src/app/components/form-object/form-object/form-object.component.html index a9f77fcbe..0ba9b727a 100644 --- a/frontend/projects/ui/src/app/components/form-object/form-object/form-object.component.html +++ b/frontend/projects/ui/src/app/components/form-object/form-object/form-object.component.html @@ -90,11 +90,9 @@ let i = index " > - - - + + + -
- {{ errors | getError : $any(spec)['pattern-description'] }} + {{ errors | getError : $any(spec).patternDescription }}

diff --git a/frontend/projects/ui/src/app/components/form-object/form-object/form-object.component.ts b/frontend/projects/ui/src/app/components/form-object/form-object/form-object.component.ts index abba90aa8..f12f08fc1 100644 --- a/frontend/projects/ui/src/app/components/form-object/form-object/form-object.component.ts +++ b/frontend/projects/ui/src/app/components/form-object/form-object/form-object.component.ts @@ -8,7 +8,7 @@ import { SimpleChanges, } from '@angular/core' import { UntypedFormArray, UntypedFormGroup } from '@angular/forms' -import { AlertButton, AlertController, ModalController } from '@ionic/angular' +import { AlertButton, AlertController } from '@ionic/angular' import { InputSpec, ListValueSpecOf, @@ -16,7 +16,7 @@ import { ValueSpecBoolean, ValueSpecList, ValueSpecUnion, -} from 'start-sdk/types/config-types' +} from 'start-sdk/lib/config/config-types' import { FormService } from 'src/app/services/form.service' import { THEME, pauseFor } from '@start9labs/shared' import { v4 } from 'uuid' @@ -49,7 +49,6 @@ export class FormObjectComponent { constructor( private readonly alertCtrl: AlertController, - private readonly modalCtrl: ModalController, private readonly formService: FormService, @Inject(DOCUMENT) private readonly document: Document, ) {} @@ -86,9 +85,7 @@ export class FormObjectComponent { if (spec.type === 'list' && ['object', 'union'].includes(spec.subtype)) { this.objectListDisplay[key] = [] this.formGroup.get(key)?.value.forEach((obj: any, index: number) => { - const displayAs = (spec.spec as ListValueSpecOf<'object'>)[ - 'display-as' - ] + const displayAs = (spec.spec as ListValueSpecOf<'object'>).displayAs this.objectListDisplay[key][index] = { expanded: false, displayAs: displayAs @@ -213,9 +210,7 @@ export class FormObjectComponent { arr.insert(index, newItem) if (['object', 'union'].includes(listSpec.subtype)) { - const displayAs = (listSpec.spec as ListValueSpecOf<'object'>)[ - 'display-as' - ] + const displayAs = (listSpec.spec as ListValueSpecOf<'object'>).displayAs this.objectListDisplay[key].push({ expanded: false, displayAs: displayAs ? Mustache.render(displayAs, newItem.value) : '', diff --git a/frontend/projects/ui/src/app/components/form-object/form-union/form-union.component.html b/frontend/projects/ui/src/app/components/form-object/form-union/form-union.component.html index 861e184c6..e6cad5650 100644 --- a/frontend/projects/ui/src/app/components/form-object/form-union/form-union.component.html +++ b/frontend/projects/ui/src/app/components/form-object/form-union/form-union.component.html @@ -3,8 +3,8 @@ @@ -26,7 +26,7 @@ *ngFor="let option of spec.variants | keyvalue" [value]="option.key" > - {{ spec.tag['variant-names'][option.key] }} + {{ spec.variants[option.key].name }}
diff --git a/frontend/projects/ui/src/app/components/form-object/form-union/form-union.component.ts b/frontend/projects/ui/src/app/components/form-object/form-union/form-union.component.ts index 6994e92c5..064be5660 100644 --- a/frontend/projects/ui/src/app/components/form-object/form-union/form-union.component.ts +++ b/frontend/projects/ui/src/app/components/form-object/form-union/form-union.component.ts @@ -2,7 +2,11 @@ import { ChangeDetectionStrategy, Component, Input } from '@angular/core' import { UntypedFormGroup } from '@angular/forms' import { v4 } from 'uuid' import { FormService } from 'src/app/services/form.service' -import { ValueSpecUnion, InputSpec } from 'start-sdk/types/config-types' +import { + ValueSpecUnion, + InputSpec, + unionSelectKey, +} from 'start-sdk/lib/config/config-types' @Component({ selector: 'form-union', @@ -11,21 +15,23 @@ import { ValueSpecUnion, InputSpec } from 'start-sdk/types/config-types' changeDetection: ChangeDetectionStrategy.OnPush, }) export class FormUnionComponent { + readonly unionSelectKey = unionSelectKey + @Input() formGroup!: UntypedFormGroup @Input() spec!: ValueSpecUnion @Input() current?: Record @Input() original?: Record get selectedVariant(): string { - return this.formGroup.get(this.spec.tag.id)?.value + return this.formGroup.get(unionSelectKey)?.value } get variantName(): string { - return this.spec.tag['variant-names'][this.selectedVariant] + return this.spec.variants[this.selectedVariant].name } get variantSpec(): InputSpec { - return this.spec.variants[this.selectedVariant] + return this.spec.variants[this.selectedVariant].spec } get hasNewOptions(): boolean { @@ -38,10 +44,8 @@ export class FormUnionComponent { constructor(private readonly formService: FormService) {} updateUnion(e: any): void { - const tagId = this.spec.tag.id - Object.keys(this.formGroup.controls).forEach(control => { - if (control === tagId) return + if (control === unionSelectKey) return this.formGroup.removeControl(control) }) @@ -51,7 +55,7 @@ export class FormUnionComponent { ) Object.keys(unionGroup.controls).forEach(control => { - if (control === tagId) return + if (control === unionSelectKey) return this.formGroup.addControl(control, unionGroup.controls[control]) }) } diff --git a/frontend/projects/ui/src/app/components/form-object/form-warning.directive.ts b/frontend/projects/ui/src/app/components/form-object/form-warning.directive.ts index d568062f3..ab87fa01f 100644 --- a/frontend/projects/ui/src/app/components/form-object/form-warning.directive.ts +++ b/frontend/projects/ui/src/app/components/form-object/form-warning.directive.ts @@ -1,5 +1,5 @@ import { Directive } from '@angular/core' -import { ValueSpec, ValueSpecUnion } from 'start-sdk/types/config-types' +import { ValueSpec, ValueSpecUnion } from 'start-sdk/lib/config/config-types' import { AlertButton, AlertController } from '@ionic/angular' @Directive({ diff --git a/frontend/projects/ui/src/app/modals/app-config/app-config.page.ts b/frontend/projects/ui/src/app/modals/app-config/app-config.page.ts index 0fae102f8..867efceb6 100644 --- a/frontend/projects/ui/src/app/modals/app-config/app-config.page.ts +++ b/frontend/projects/ui/src/app/modals/app-config/app-config.page.ts @@ -13,7 +13,7 @@ import { isObject, } from '@start9labs/shared' import { DependentInfo } from 'src/app/types/dependent-info' -import { InputSpec } from 'start-sdk/types/config-types' +import { InputSpec } from 'start-sdk/lib/config/config-types' import { DataModel, PackageDataEntry, diff --git a/frontend/projects/ui/src/app/modals/generic-form/generic-form.page.ts b/frontend/projects/ui/src/app/modals/generic-form/generic-form.page.ts index 6039ab721..4893f7da1 100644 --- a/frontend/projects/ui/src/app/modals/generic-form/generic-form.page.ts +++ b/frontend/projects/ui/src/app/modals/generic-form/generic-form.page.ts @@ -5,7 +5,7 @@ import { convertValuesRecursive, FormService, } from 'src/app/services/form.service' -import { InputSpec } from 'start-sdk/types/config-types' +import { InputSpec } from 'start-sdk/lib/config/config-types' export interface ActionButton { text: string diff --git a/frontend/projects/ui/src/app/modals/marketplace-settings/marketplace-settings.page.ts b/frontend/projects/ui/src/app/modals/marketplace-settings/marketplace-settings.page.ts index b9ee3819c..58f53c662 100644 --- a/frontend/projects/ui/src/app/modals/marketplace-settings/marketplace-settings.page.ts +++ b/frontend/projects/ui/src/app/modals/marketplace-settings/marketplace-settings.page.ts @@ -14,7 +14,7 @@ import { ActionSheetButton } from '@ionic/core' import { ErrorToastService, sameUrl, toUrl } from '@start9labs/shared' import { AbstractMarketplaceService } from '@start9labs/marketplace' import { ApiService } from 'src/app/services/api/embassy-api.service' -import { ValueSpecObject } from 'start-sdk/types/config-types' +import { ValueSpecObject } from 'start-sdk/lib/config/config-types' import { GenericFormPage, GenericFormOptions, @@ -276,7 +276,7 @@ function getMarketplaceValueSpec(): ValueSpecObject { nullable: false, masked: false, pattern: `https?:\/\/[a-zA-Z0-9][a-zA-Z0-9-\.]+[a-zA-Z0-9]\.[^\s]{2,}`, - 'pattern-description': 'Must be a valid URL', + patternDescription: 'Must be a valid URL', placeholder: 'e.g. https://example.org', default: null, textarea: false, diff --git a/frontend/projects/ui/src/app/pages/developer-routes/developer-list/developer-list.page.ts b/frontend/projects/ui/src/app/pages/developer-routes/developer-list/developer-list.page.ts index 1113410f2..b006e6caa 100644 --- a/frontend/projects/ui/src/app/pages/developer-routes/developer-list/developer-list.page.ts +++ b/frontend/projects/ui/src/app/pages/developer-routes/developer-list/developer-list.page.ts @@ -12,7 +12,7 @@ import { } from 'src/app/modals/generic-input/generic-input.component' import { PatchDB } from 'patch-db-client' import { ApiService } from 'src/app/services/api/embassy-api.service' -import { InputSpec } from 'start-sdk/types/config-types' +import { InputSpec } from 'start-sdk/lib/config/config-types' import * as yaml from 'js-yaml' import { v4 } from 'uuid' import { DataModel, DevData } from 'src/app/services/patch-db/data-model' @@ -227,7 +227,7 @@ const SAMPLE_CONFIG: InputSpec = { description: 'Example description for required string input.', placeholder: 'Enter string value', pattern: '^[a-zA-Z0-9! _]+$', - 'pattern-description': 'Must be alphanumeric (may contain underscore).', + patternDescription: 'Must be alphanumeric (may contain underscore).', default: null, textarea: false, warning: null, @@ -256,8 +256,7 @@ const SAMPLE_CONFIG: InputSpec = { 'sample-select': { type: 'multiselect', name: 'Example Enum Select', - values: ['red', 'blue', 'green'], - 'value-names': { + values: { red: 'Red', blue: 'Blue', green: 'Green', diff --git a/frontend/projects/ui/src/app/pages/developer-routes/developer-menu/form-info.ts b/frontend/projects/ui/src/app/pages/developer-routes/developer-menu/form-info.ts index 97bc54804..56b318f0a 100644 --- a/frontend/projects/ui/src/app/pages/developer-routes/developer-menu/form-info.ts +++ b/frontend/projects/ui/src/app/pages/developer-routes/developer-menu/form-info.ts @@ -1,4 +1,4 @@ -import { InputSpec } from 'start-sdk/types/config-types' +import { InputSpec } from 'start-sdk/lib/config/config-types' import { DevProjectData } from 'src/app/services/patch-db/data-model' export type BasicInfo = { @@ -28,7 +28,7 @@ export function getBasicInfoSpec(devData: DevProjectData): InputSpec { nullable: false, masked: false, pattern: '^([a-z][a-z0-9]*)(-[a-z0-9]+)*$', - 'pattern-description': 'Must be kebab case', + patternDescription: 'Must be kebab case', default: basicInfo?.id || '', textarea: false, warning: null, @@ -41,7 +41,7 @@ export function getBasicInfoSpec(devData: DevProjectData): InputSpec { nullable: false, masked: false, pattern: null, - 'pattern-description': null, + patternDescription: null, default: basicInfo ? basicInfo.title : devData.name, textarea: false, warning: null, @@ -55,7 +55,7 @@ export function getBasicInfoSpec(devData: DevProjectData): InputSpec { nullable: false, masked: false, pattern: '^([0-9]+).([0-9]+).([0-9]+).([0-9]+)$', - 'pattern-description': 'Must be valid Emver version', + patternDescription: 'Must be valid Emver version', default: basicInfo?.['service-version-number'] || '', textarea: false, warning: null, @@ -77,7 +77,7 @@ export function getBasicInfoSpec(devData: DevProjectData): InputSpec { textarea: true, default: basicInfo?.description?.short || '', pattern: '^.{1,320}$', - 'pattern-description': 'Must be shorter than 320 characters', + patternDescription: 'Must be shorter than 320 characters', warning: null, }, long: { @@ -90,7 +90,7 @@ export function getBasicInfoSpec(devData: DevProjectData): InputSpec { textarea: true, default: basicInfo?.description?.long || '', pattern: '^.{1,5000}$', - 'pattern-description': 'Must be shorter than 5000 characters', + patternDescription: 'Must be shorter than 5000 characters', warning: null, }, }, @@ -104,7 +104,7 @@ export function getBasicInfoSpec(devData: DevProjectData): InputSpec { nullable: false, masked: false, pattern: null, - 'pattern-description': null, + patternDescription: null, textarea: true, default: basicInfo?.['release-notes'] || '', warning: null, @@ -113,18 +113,7 @@ export function getBasicInfoSpec(devData: DevProjectData): InputSpec { type: 'select', name: 'License', warning: null, - values: [ - 'gnu-agpl-v3', - 'gnu-gpl-v3', - 'gnu-lgpl-v3', - 'mozilla-public-license-2.0', - 'apache-license-2.0', - 'mit', - 'boost-software-license-1.0', - 'the-unlicense', - 'custom', - ], - 'value-names': { + values: { 'gnu-agpl-v3': 'GNU AGPLv3', 'gnu-gpl-v3': 'GNU GPLv3', 'gnu-lgpl-v3': 'GNU LGPLv3', @@ -136,6 +125,7 @@ export function getBasicInfoSpec(devData: DevProjectData): InputSpec { custom: 'Custom', }, description: 'Example description for select', + nullable: false, default: 'mit', }, 'wrapper-repo': { @@ -145,7 +135,7 @@ export function getBasicInfoSpec(devData: DevProjectData): InputSpec { 'The Start9 wrapper repository URL for the package. This repo contains the manifest file (this), any scripts necessary for configuration, backups, actions, or health checks', placeholder: 'e.g. www.github.com/example', pattern: null, - 'pattern-description': null, + patternDescription: null, nullable: false, masked: false, default: basicInfo?.['wrapper-repo'] || '', @@ -158,7 +148,7 @@ export function getBasicInfoSpec(devData: DevProjectData): InputSpec { description: 'The original project repository URL', placeholder: 'e.g. www.github.com/example', pattern: null, - 'pattern-description': null, + patternDescription: null, nullable: true, masked: false, default: basicInfo?.['upstream-repo'] || '', @@ -171,7 +161,7 @@ export function getBasicInfoSpec(devData: DevProjectData): InputSpec { description: 'URL to the support site / channel for the project', placeholder: 'e.g. start9.com/support', pattern: null, - 'pattern-description': null, + patternDescription: null, nullable: true, masked: false, default: basicInfo?.['support-site'] || '', @@ -184,7 +174,7 @@ export function getBasicInfoSpec(devData: DevProjectData): InputSpec { description: 'URL to the marketing site / channel for the project', placeholder: 'e.g. start9.com', pattern: null, - 'pattern-description': null, + patternDescription: null, nullable: true, masked: false, default: basicInfo?.['marketing-site'] || '', diff --git a/frontend/projects/ui/src/app/pages/server-routes/wifi/wifi.page.ts b/frontend/projects/ui/src/app/pages/server-routes/wifi/wifi.page.ts index b6e1b966f..afe928b43 100644 --- a/frontend/projects/ui/src/app/pages/server-routes/wifi/wifi.page.ts +++ b/frontend/projects/ui/src/app/pages/server-routes/wifi/wifi.page.ts @@ -9,7 +9,7 @@ import { import { AlertInput } from '@ionic/core' import { ApiService } from 'src/app/services/api/embassy-api.service' import { ActionSheetButton } from '@ionic/core' -import { ValueSpecObject } from 'start-sdk/types/config-types' +import { ValueSpecObject } from 'start-sdk/lib/config/config-types' import { RR } from 'src/app/services/api/api.types' import { pauseFor, ErrorToastService } from '@start9labs/shared' import { @@ -361,7 +361,7 @@ function getWifiValueSpec( description: null, placeholder: null, pattern: null, - 'pattern-description': null, + patternDescription: null, nullable: false, masked: false, default: ssid || null, @@ -376,7 +376,7 @@ function getWifiValueSpec( nullable: !needsPW, masked: true, pattern: '^.{8,}$', - 'pattern-description': 'Must be longer than 8 characters', + patternDescription: 'Must be longer than 8 characters', default: null, textarea: false, warning: null, 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 016ae95b9..b923f18bb 100644 --- a/frontend/projects/ui/src/app/services/api/api.fixures.ts +++ b/frontend/projects/ui/src/app/services/api/api.fixures.ts @@ -714,46 +714,43 @@ export module Mock { spec: { 'bitcoind-p2p': { type: 'union', - tag: { - id: 'type', - name: 'Bitcoin Core P2P', - description: - '

The Bitcoin Core node to connect to over the peer-to-peer (P2P) interface:

', - 'variant-names': { - internal: 'Bitcoin Core', - external: 'External Node', - }, - warning: null, - }, + name: 'Bitcoin Core P2P', + description: + '

The Bitcoin Core node to connect to over the peer-to-peer (P2P) interface:

', + warning: null, default: 'internal', + nullable: false, variants: { - internal: {}, + internal: { name: 'Internal', spec: {} }, external: { - 'p2p-host': { - type: 'string', - name: 'Public Address', - description: 'The public address of your Bitcoin Core server', - nullable: false, - masked: false, - placeholder: null, - pattern: null, - 'pattern-description': null, - textarea: false, - warning: null, - default: null, - }, - 'p2p-port': { - type: 'number', - name: 'P2P Port', - description: - 'The port that your Bitcoin Core P2P server is bound to', - nullable: false, - range: '[0,65535]', - integral: true, - default: 8333, - placeholder: null, - warning: null, - units: null, + name: 'External', + spec: { + 'p2p-host': { + type: 'string', + name: 'Public Address', + description: 'The public address of your Bitcoin Core server', + nullable: false, + masked: false, + placeholder: null, + pattern: null, + patternDescription: null, + textarea: false, + warning: null, + default: null, + }, + 'p2p-port': { + type: 'number', + name: 'P2P Port', + description: + 'The port that your Bitcoin Core P2P server is bound to', + nullable: false, + range: '[0,65535]', + integral: true, + default: 8333, + placeholder: null, + warning: null, + units: null, + }, }, }, }, @@ -782,7 +779,7 @@ export module Mock { nullable: false, default: 'defaultrpcusername', pattern: '^[a-zA-Z]+$', - 'pattern-description': 'must contain only letters.', + patternDescription: 'must contain only letters.', masked: false, textarea: false, }, @@ -795,7 +792,7 @@ export module Mock { nullable: false, default: 'defaultrpcusername', pattern: '^[a-zA-Z]+$', - 'pattern-description': 'must contain only letters.', + patternDescription: 'must contain only letters.', masked: false, textarea: false, }, @@ -812,7 +809,7 @@ export module Mock { }, masked: true, pattern: null, - 'pattern-description': null, + patternDescription: null, textarea: false, }, rpcpass2: { @@ -828,7 +825,7 @@ export module Mock { }, masked: true, pattern: null, - 'pattern-description': null, + patternDescription: null, textarea: false, }, }, @@ -847,7 +844,6 @@ export module Mock { name: 'Needed File', type: 'file', description: 'A file we need', - placeholder: null, // @TODO delete warning: 'Testing warning', nullable: false, extensions: ['.png'], @@ -873,10 +869,9 @@ export module Mock { ], // the outer spec here, at the list level, says that what's inside (the inner spec) pertains to its inner elements. // it just so happens that ValueSpecObject's have the field { spec: InputSpec } - // see 'union-list' below for a different example. spec: { - 'unique-by': 'last-name', - 'display-as': `I'm {{last-name}}, {{first-name}} {{last-name}}`, + uniqueBy: 'last-name', + displayAs: `I'm {{last-name}}, {{first-name}} {{last-name}}`, spec: { 'first-name': { name: 'First Name', @@ -886,7 +881,7 @@ export module Mock { masked: false, placeholder: null, pattern: null, - 'pattern-description': null, + patternDescription: null, textarea: false, warning: null, default: null, @@ -901,7 +896,7 @@ export module Mock { len: 12, }, pattern: '^[a-zA-Z]+$', - 'pattern-description': 'must contain only letters.', + patternDescription: 'must contain only letters.', masked: false, placeholder: null, textarea: false, @@ -922,77 +917,10 @@ export module Mock { }, }, }, - 'union-list': { - name: 'Union List', - type: 'list', - subtype: 'union', - description: 'This is a sample list of unions', - warning: 'If you change this, things may work.', - // a list of union selections. e.g. 'summer', 'winter',... - default: ['summer'], - range: '[0, 2]', - spec: { - tag: { - id: 'preference', - description: null, - warning: null, - 'variant-names': { - summer: 'Summer', - winter: 'Winter', - other: 'Other', - }, - name: 'Preference', - }, - 'display-as': null, - // this default is used to make a union selection when a new list element is first created - default: 'summer', - variants: { - summer: { - 'favorite-tree': { - name: 'Favorite Tree', - type: 'string', - nullable: false, - description: 'What is your favorite tree?', - default: 'Maple', - masked: false, - placeholder: null, - pattern: null, - 'pattern-description': null, - textarea: false, - warning: null, - }, - 'favorite-flower': { - name: 'Favorite Flower', - type: 'select', - description: 'Select your favorite flower', - warning: null, - 'value-names': { - none: 'Hate Flowers', - red: 'Red', - blue: 'Blue', - purple: 'Purple', - }, - values: ['none', 'red', 'blue', 'purple'], - default: 'none', - }, - }, - winter: { - 'like-snow': { - name: 'Like Snow?', - type: 'boolean', - description: 'Do you like snow or not?', - warning: null, - default: true, - }, - }, - }, - 'unique-by': 'preference', - }, - }, 'random-select': { name: 'Random Select', type: 'select', - 'value-names': { + values: { hello: 'Hello', goodbye: 'Goodbye', sup: 'Sup', @@ -1000,7 +928,7 @@ export module Mock { default: 'sup', description: 'This is not even real.', warning: 'Be careful changing this!', - values: ['hello', 'goodbye', 'sup'], + nullable: false, }, notifications: { name: 'Notification Preferences', @@ -1008,14 +936,13 @@ export module Mock { description: 'how you want to be notified', warning: null, range: '(1,3]', - 'value-names': { + values: { email: 'EEEEmail', text: 'Texxxt', call: 'Ccccall', push: 'PuuuusH', webhook: 'WebHooookkeee', }, - values: ['email', 'text', 'call', 'push', 'webhook'], default: ['email'], }, 'favorite-number': { @@ -1066,7 +993,7 @@ export module Mock { masked: false, placeholder: null, pattern: null, - 'pattern-description': null, + patternDescription: null, textarea: false, warning: null, default: null, @@ -1079,7 +1006,7 @@ export module Mock { masked: false, placeholder: null, pattern: null, - 'pattern-description': null, + patternDescription: null, textarea: false, warning: null, default: null, @@ -1095,8 +1022,8 @@ export module Mock { range: '[0,2]', default: [], spec: { - 'unique-by': null, - 'display-as': null, + uniqueBy: null, + displayAs: null, spec: { rulemakername: { name: 'Rulemaker Name', @@ -1110,7 +1037,7 @@ export module Mock { masked: false, placeholder: null, pattern: null, - 'pattern-description': null, + patternDescription: null, textarea: false, warning: null, }, @@ -1122,7 +1049,7 @@ export module Mock { default: '192.168.1.0', pattern: '^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])$', - 'pattern-description': 'may only contain numbers and periods', + patternDescription: 'may only contain numbers and periods', masked: false, placeholder: null, textarea: false, @@ -1138,7 +1065,7 @@ export module Mock { nullable: false, default: 'defaultrpcusername', pattern: '^[a-zA-Z]+$', - 'pattern-description': 'must contain only letters.', + patternDescription: 'must contain only letters.', masked: false, placeholder: null, textarea: false, @@ -1156,7 +1083,7 @@ export module Mock { masked: true, placeholder: null, pattern: null, - 'pattern-description': null, + patternDescription: null, textarea: false, warning: null, }, @@ -1165,78 +1092,75 @@ export module Mock { 'bitcoin-node': { type: 'union', default: 'internal', - tag: { - id: 'type', - 'variant-names': { - internal: 'Internal', - external: 'External', - }, - name: 'Bitcoin Node Settings', - description: 'Options', - warning: 'Careful changing this', - }, + name: 'Bitcoin Node Settings', + description: 'Options', + warning: 'Careful changing this', + nullable: false, variants: { - internal: {}, + internal: { name: 'Internal', spec: {} }, external: { - 'emergency-contact': { - name: 'Emergency Contact', - type: 'object', - description: 'The person to contact in case of emergency.', - warning: null, - spec: { - name: { - type: 'string', - name: 'Name', - description: null, - nullable: false, - masked: false, - pattern: '^[a-zA-Z]+$', - 'pattern-description': 'Must contain only letters.', - placeholder: null, - textarea: false, - warning: null, - default: null, - }, - email: { - type: 'string', - name: 'Email', - description: null, - nullable: false, - masked: false, - placeholder: null, - pattern: null, - 'pattern-description': null, - textarea: false, - warning: null, - default: null, + name: 'External', + spec: { + 'emergency-contact': { + name: 'Emergency Contact', + type: 'object', + description: 'The person to contact in case of emergency.', + warning: null, + spec: { + name: { + type: 'string', + name: 'Name', + description: null, + nullable: false, + masked: false, + pattern: '^[a-zA-Z]+$', + patternDescription: 'Must contain only letters.', + placeholder: null, + textarea: false, + warning: null, + default: null, + }, + email: { + type: 'string', + name: 'Email', + description: null, + nullable: false, + masked: false, + placeholder: null, + pattern: null, + patternDescription: null, + textarea: false, + warning: null, + default: null, + }, }, }, - }, - 'public-domain': { - name: 'Public Domain', - type: 'string', - description: 'the public address of the node', - nullable: false, - default: 'bitcoinnode.com', - pattern: '.*', - 'pattern-description': 'anything', - masked: false, - placeholder: null, - textarea: false, - warning: null, - }, - 'private-domain': { - name: 'Private Domain', - type: 'string', - description: 'the private address of the node', - nullable: false, - masked: true, - placeholder: null, - pattern: null, - 'pattern-description': null, - textarea: false, - warning: null, - default: null, + 'public-domain': { + name: 'Public Domain', + type: 'string', + description: 'the public address of the node', + nullable: false, + default: 'bitcoinnode.com', + pattern: '.*', + patternDescription: 'anything', + masked: false, + placeholder: null, + textarea: false, + warning: null, + }, + 'private-domain': { + name: 'Private Domain', + type: 'string', + description: 'the private address of the node', + nullable: false, + masked: true, + placeholder: null, + pattern: null, + patternDescription: null, + textarea: false, + warning: null, + default: null, + }, }, }, }, @@ -1263,7 +1187,7 @@ export module Mock { masked: true, placeholder: null, pattern: null, - 'pattern-description': null, + patternDescription: null, textarea: false, warning: null, default: null, @@ -1283,7 +1207,7 @@ export module Mock { placeholder: null, pattern: '((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])|((^(([0-9a-fA-F]{1,4}:){7,7}[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,7}:|([0-9a-fA-F]{1,4}:){1,6}:[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,5}(:[0-9a-fA-F]{1,4}){1,2}|([0-9a-fA-F]{1,4}:){1,4}(:[0-9a-fA-F]{1,4}){1,3}|([0-9a-fA-F]{1,4}:){1,3}(:[0-9a-fA-F]{1,4}){1,4}|([0-9a-fA-F]{1,4}:){1,2}(:[0-9a-fA-F]{1,4}){1,5}|[0-9a-fA-F]{1,4}:((:[0-9a-fA-F]{1,4}){1,6})|:((:[0-9a-fA-F]{1,4}){1,7}|:)|fe80:(:[0-9a-fA-F]{0,4}){0,4}%[0-9a-zA-Z]{1,}|::(ffff(:0{1,4}){0,1}:){0,1}((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9]).){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])|([0-9a-fA-F]{1,4}:){1,4}:((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9]).){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9]))$)|(^[a-z2-7]{16}\\.onion$)|(^([a-z0-9]([a-z0-9-]{0,61}[a-z0-9])?\\.)+[a-z0-9][a-z0-9-]{0,61}[a-z0-9]$))', - 'pattern-description': 'must be a valid ipv4, ipv6, or domain name', + patternDescription: 'must be a valid ipv4, ipv6, or domain name', }, }, rpcauth: { @@ -1298,7 +1222,7 @@ export module Mock { masked: false, placeholder: null, pattern: null, - 'pattern-description': null, + patternDescription: null, }, }, 'more-advanced': { @@ -1328,7 +1252,7 @@ export module Mock { masked: false, placeholder: null, pattern: null, - 'pattern-description': null, + patternDescription: null, textarea: false, warning: null, default: null, @@ -1341,7 +1265,7 @@ export module Mock { masked: false, placeholder: null, pattern: null, - 'pattern-description': null, + patternDescription: null, textarea: false, warning: null, default: null, @@ -1354,7 +1278,7 @@ export module Mock { masked: false, placeholder: null, pattern: null, - 'pattern-description': null, + patternDescription: null, textarea: false, warning: null, default: null, @@ -1368,8 +1292,8 @@ export module Mock { range: '[0,2]', default: [], spec: { - 'unique-by': null, - 'display-as': null, + uniqueBy: null, + displayAs: null, spec: { lawname: { name: 'Law Name', @@ -1383,7 +1307,7 @@ export module Mock { masked: false, placeholder: null, pattern: null, - 'pattern-description': null, + patternDescription: null, textarea: false, warning: null, }, @@ -1395,7 +1319,7 @@ export module Mock { default: '192.168.1.0', pattern: '^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])$', - 'pattern-description': + patternDescription: 'may only contain numbers and periods', masked: false, placeholder: null, @@ -1413,7 +1337,7 @@ export module Mock { masked: false, placeholder: null, pattern: null, - 'pattern-description': null, + patternDescription: null, textarea: false, warning: null, default: null, @@ -1429,8 +1353,8 @@ export module Mock { range: '[0,2]', default: [], spec: { - 'unique-by': null, - 'display-as': null, + uniqueBy: null, + displayAs: null, spec: { rulemakername: { name: 'Rulemaker Name', @@ -1444,7 +1368,7 @@ export module Mock { masked: false, placeholder: null, pattern: null, - 'pattern-description': null, + patternDescription: null, textarea: false, warning: null, }, @@ -1456,8 +1380,7 @@ export module Mock { default: '192.168.1.0', pattern: '^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])$', - 'pattern-description': - 'may only contain numbers and periods', + patternDescription: 'may only contain numbers and periods', masked: false, placeholder: null, textarea: false, @@ -1473,7 +1396,7 @@ export module Mock { nullable: false, default: 'defaultrpcusername', pattern: '^[a-zA-Z]+$', - 'pattern-description': 'must contain only letters.', + patternDescription: 'must contain only letters.', masked: false, placeholder: null, textarea: false, @@ -1491,7 +1414,7 @@ export module Mock { masked: true, placeholder: null, pattern: null, - 'pattern-description': null, + patternDescription: null, textarea: false, warning: null, }, @@ -1520,7 +1443,6 @@ export module Mock { age: 60, }, ], - 'union-list': undefined, 'random-select': ['goodbye'], 'favorite-number': 0, rpcsettings: { @@ -1601,7 +1523,7 @@ export module Mock { nullable: false, masked: false, pattern: '^[a-zA-Z]+$', - 'pattern-description': 'Must contain only letters.', + patternDescription: 'Must contain only letters.', textarea: false, warning: null, default: null, diff --git a/frontend/projects/ui/src/app/services/api/api.types.ts b/frontend/projects/ui/src/app/services/api/api.types.ts index b2b519b3a..d1cd719c8 100644 --- a/frontend/projects/ui/src/app/services/api/api.types.ts +++ b/frontend/projects/ui/src/app/services/api/api.types.ts @@ -1,7 +1,7 @@ import { Dump, Revision } from 'patch-db-client' import { MarketplacePkg, StoreInfo, Manifest } from '@start9labs/marketplace' import { PackagePropertiesVersioned } from 'src/app/util/properties.util' -import { InputSpec } from 'start-sdk/types/config-types' +import { InputSpec } from 'start-sdk/lib/config/config-types' import { DataModel, DependencyError, diff --git a/frontend/projects/ui/src/app/services/form.service.ts b/frontend/projects/ui/src/app/services/form.service.ts index 6b4b8b39b..46447a580 100644 --- a/frontend/projects/ui/src/app/services/form.service.ts +++ b/frontend/projects/ui/src/app/services/form.service.ts @@ -14,7 +14,6 @@ import { ListValueSpecObject, ListValueSpecOf, ListValueSpecString, - ListValueSpecUnion, UniqueBy, ValueSpec, ValueSpecSelect, @@ -25,7 +24,8 @@ import { ValueSpecObject, ValueSpecString, ValueSpecUnion, -} from 'start-sdk/types/config-types' + unionSelectKey, +} from 'start-sdk/lib/config/config-types' import { getDefaultString, Range } from '../util/config-utilities' const Mustache = require('mustache') @@ -37,18 +37,16 @@ export class FormService { createForm( spec: InputSpec, - current: { [key: string]: any } = {}, + current: Record = {}, ): UntypedFormGroup { return this.getFormGroup(spec, [], current) } getUnionObject( - spec: ValueSpecUnion | ListValueSpecUnion, - selection: string, - current?: { [key: string]: any } | null, + spec: ValueSpecUnion, + selection: string | null, ): UntypedFormGroup { - const { variants, tag } = spec - const { name, description, warning, 'variant-names': variantNames } = tag + const { name, description, warning, variants, nullable } = spec const enumSpec: ValueSpecSelect = { type: 'select', @@ -56,14 +54,22 @@ export class FormService { description, warning, default: selection, - values: Object.keys(variants), - 'value-names': variantNames, + nullable, + values: Object.keys(variants).reduce( + (prev, curr) => ({ + ...prev, + [curr]: variants[curr].name, + }), + {}, + ), } - return this.getFormGroup( - { [spec.tag.id]: enumSpec, ...spec.variants[selection] }, - [], - current, - ) + + const selectedSpec = selection ? variants[selection].spec : {} + + return this.getFormGroup({ + ['selectedVariant']: enumSpec, + ...selectedSpec, + }) } getListItem(spec: ValueSpecList, entry: any) { @@ -74,15 +80,13 @@ export class FormService { return this.formBuilder.control(entry, listItemValidators) } else if (isValueSpecListOf(spec, 'object')) { return this.getFormGroup(spec.spec.spec, listItemValidators, entry) - } else if (isValueSpecListOf(spec, 'union')) { - return this.getUnionObject(spec.spec, spec.spec.default, entry) } } private getFormGroup( config: InputSpec, validators: ValidatorFn[] = [], - current?: { [key: string]: any } | null, + current?: Record | null, ): UntypedFormGroup { let group: Record< string, @@ -129,13 +133,12 @@ export class FormService { fileValidators(spec), ) case 'union': - const currentSelection = currentValue?.[spec.tag.id] + const currentSelection = currentValue?.[unionSelectKey] const isValid = !!spec.variants[currentSelection] return this.getUnionObject( spec, isValid ? currentSelection : spec.default, - isValid ? currentValue : undefined, ) case 'boolean': case 'select': @@ -273,23 +276,20 @@ export function listUnique(spec: ValueSpecList): ValidatorFn { for (let idx = 0; idx < list.length; idx++) { for (let idx2 = idx + 1; idx2 < list.length; idx2++) { if (listItemEquals(spec, list[idx], list[idx2])) { + const objSpec = spec.spec let display1: string let display2: string - let uniqueMessage = isObjectOrUnion(spec.spec) - ? uniqueByMessageWrapper( - spec.spec['unique-by'], - spec.spec, - list[idx], - ) + let uniqueMessage = isObject(objSpec) + ? uniqueByMessageWrapper(objSpec.uniqueBy, objSpec, list[idx]) : '' - if (isObjectOrUnion(spec.spec) && spec.spec['display-as']) { + if (isObject(objSpec) && objSpec.displayAs) { display1 = `"${(Mustache as any).render( - spec.spec['display-as'], + objSpec.displayAs, list[idx], )}"` display2 = `"${(Mustache as any).render( - spec.spec['display-as'], + objSpec.displayAs, list[idx2], )}"` } else { @@ -318,11 +318,7 @@ function listItemEquals(spec: ValueSpecList, val1: any, val2: any): boolean { case 'object': const obj: ListValueSpecObject = spec.spec as any - return listObjEquals(obj['unique-by'], obj, val1, val2) - case 'union': - const union: ListValueSpecUnion = spec.spec as any - - return unionEquals(union['unique-by'], union, val1, val2) + return listObjEquals(obj.uniqueBy, obj, val1, val2) default: return false } @@ -425,19 +421,18 @@ function objEquals( function unionEquals( uniqueBy: UniqueBy, - spec: ValueSpecUnion | ListValueSpecUnion, + spec: ValueSpecUnion, val1: any, val2: any, ): boolean { - const tagId = spec.tag.id - const variant = spec.variants[val1[tagId]] + const variantSpec = spec.variants[val1[unionSelectKey]].spec if (!uniqueBy) { return false } else if (typeof uniqueBy === 'string') { - if (uniqueBy === tagId) { - return val1[tagId] === val2[tagId] + if (uniqueBy === unionSelectKey) { + return val1[unionSelectKey] === val2[unionSelectKey] } else { - return itemEquals(variant[uniqueBy], val1[uniqueBy], val2[uniqueBy]) + return itemEquals(variantSpec[uniqueBy], val1[uniqueBy], val2[uniqueBy]) } } else if ('any' in uniqueBy) { for (let subSpec of uniqueBy.any) { @@ -459,19 +454,10 @@ function unionEquals( function uniqueByMessageWrapper( uniqueBy: UniqueBy, - spec: ListValueSpecObject | ListValueSpecUnion, + spec: ListValueSpecObject, obj: Record, ) { - let configSpec: InputSpec - if (isUnion(spec)) { - const tagId = spec.tag.id - configSpec = { - [tagId]: { name: spec.tag.name } as ValueSpec, - ...spec.variants[obj[tagId]], - } - } else { - configSpec = spec.spec - } + let configSpec = spec.spec const message = uniqueByMessage(uniqueBy, configSpec) if (message) { @@ -509,16 +495,9 @@ function uniqueByMessage( : '(' + ret + ')' } -function isObjectOrUnion( - spec: ListValueSpecOf, -): spec is ListValueSpecObject | ListValueSpecUnion { - // only lists of objects and unions have unique-by - return 'unique-by' in spec -} - -function isUnion(spec: any): spec is ListValueSpecUnion { - // only unions have tag - return !!spec.tag +function isObject(spec: ListValueSpecOf): spec is ListValueSpecObject { + // only lists of objects have uniqueBy + return 'uniqueBy' in spec } export function convertValuesRecursive( @@ -540,7 +519,8 @@ export function convertValuesRecursive( convertValuesRecursive(valueSpec.spec, group.get(key) as UntypedFormGroup) } else if (valueSpec.type === 'union') { const formGr = group.get(key) as UntypedFormGroup - const spec = valueSpec.variants[formGr.controls[valueSpec.tag.id].value] + const spec = + valueSpec.variants[formGr.controls[unionSelectKey].value].spec convertValuesRecursive(spec, formGr) } else if (valueSpec.type === 'list') { const formArr = group.get(key) as UntypedFormArray @@ -559,15 +539,6 @@ export function convertValuesRecursive( const objectSpec = valueSpec.spec as ListValueSpecObject convertValuesRecursive(objectSpec.spec, formGroup as UntypedFormGroup) }) - } else if (valueSpec.subtype === 'union') { - controls.forEach(formGroup => { - const unionSpec = valueSpec.spec as ListValueSpecUnion - const spec = - unionSpec.variants[ - (formGroup as UntypedFormGroup).controls[unionSpec.tag.id].value - ] - convertValuesRecursive(spec, formGroup as UntypedFormGroup) - }) } } }) diff --git a/frontend/projects/ui/src/app/services/patch-db/data-model.ts b/frontend/projects/ui/src/app/services/patch-db/data-model.ts index be4d2e98c..8ea218dc8 100644 --- a/frontend/projects/ui/src/app/services/patch-db/data-model.ts +++ b/frontend/projects/ui/src/app/services/patch-db/data-model.ts @@ -1,4 +1,4 @@ -import { InputSpec } from 'start-sdk/types/config-types' +import { InputSpec } from 'start-sdk/lib/config/config-types' import { Url } from '@start9labs/shared' import { Manifest } from '@start9labs/marketplace' import { BasicInfo } from 'src/app/pages/developer-routes/developer-menu/form-info' diff --git a/frontend/projects/ui/src/app/util/config-utilities.ts b/frontend/projects/ui/src/app/util/config-utilities.ts index 207b91ecf..8a9e4afd6 100644 --- a/frontend/projects/ui/src/app/util/config-utilities.ts +++ b/frontend/projects/ui/src/app/util/config-utilities.ts @@ -1,4 +1,4 @@ -import { DefaultString } from 'start-sdk/types/config-types' +import { DefaultString } from 'start-sdk/lib/config/config-types' export class Range { min?: number