mirror of
https://github.com/Start9Labs/start-os.git
synced 2026-03-30 12:11:56 +00:00
update union types and camel case for specs
This commit is contained in:
committed by
Aiden McClelland
parent
4a6a3da36c
commit
c7438c4aff
@@ -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,
|
||||
|
||||
@@ -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',
|
||||
|
||||
@@ -57,6 +57,6 @@
|
||||
</ion-item>
|
||||
<p class="error-message">
|
||||
<span *ngIf="control.errors as errors">
|
||||
{{ errors | getError : $any(spec)['pattern-description'] }}
|
||||
{{ errors | getError : $any(spec).patternDescription }}
|
||||
</span>
|
||||
</p>
|
||||
|
||||
@@ -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({
|
||||
|
||||
@@ -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]
|
||||
"
|
||||
>
|
||||
<ion-select-option *ngFor="let option of spec.values" [value]="option">
|
||||
{{ spec['value-names'][option] }}
|
||||
<ion-select-option
|
||||
*ngFor="let option of spec.values | keyvalue"
|
||||
[value]="option.key"
|
||||
>
|
||||
{{ option.value }}
|
||||
</ion-select-option>
|
||||
</ion-select>
|
||||
</ion-item>
|
||||
|
||||
@@ -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',
|
||||
|
||||
@@ -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',
|
||||
|
||||
@@ -90,11 +90,9 @@
|
||||
let i = index
|
||||
"
|
||||
>
|
||||
<!-- object or union -->
|
||||
<ng-container
|
||||
*ngIf="spec.subtype === 'object' || spec.subtype === 'union'"
|
||||
>
|
||||
<!-- object/union label -->
|
||||
<!-- object -->
|
||||
<ng-container *ngIf="spec.subtype === 'object'">
|
||||
<!-- object label -->
|
||||
<ion-item
|
||||
button
|
||||
(click)="toggleExpandListObject(entry.key, i)"
|
||||
@@ -137,16 +135,6 @@
|
||||
updateLabel(entry.key, i, $any(spec.spec)['display-as'])
|
||||
"
|
||||
></form-object>
|
||||
<form-union
|
||||
*ngIf="spec.subtype === 'union'"
|
||||
[spec]="$any(spec.spec)"
|
||||
[formGroup]="abstractControl"
|
||||
[current]="current?.[entry.key]?.[i]"
|
||||
[original]="original?.[entry.key]?.[i]"
|
||||
(onInputChange)="
|
||||
updateLabel(entry.key, i, $any(spec.spec)['display-as'])
|
||||
"
|
||||
></form-union>
|
||||
<div style="text-align: right; padding-top: 12px">
|
||||
<ion-button
|
||||
fill="clear"
|
||||
@@ -191,7 +179,7 @@
|
||||
$any(formGroup.get(entry.key))?.at(i)?.errors as errors
|
||||
"
|
||||
>
|
||||
{{ errors | getError : $any(spec)['pattern-description'] }}
|
||||
{{ errors | getError : $any(spec).patternDescription }}
|
||||
</span>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
@@ -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) : '',
|
||||
|
||||
@@ -3,8 +3,8 @@
|
||||
<ion-item-divider [class.error-border]="formGroup.invalid">
|
||||
<form-label
|
||||
[data]="{
|
||||
name: spec.tag.name,
|
||||
description: spec.tag.description,
|
||||
name: spec.name,
|
||||
description: spec.description,
|
||||
newOptions: hasNewOptions,
|
||||
edited: formGroup.dirty
|
||||
}"
|
||||
@@ -12,13 +12,13 @@
|
||||
<!-- class enter-click disables the enter click on the modal behind the select -->
|
||||
<ion-select
|
||||
[interfaceOptions]="{
|
||||
header: spec.tag.name,
|
||||
message: spec.tag.warning | toWarningText,
|
||||
header: spec.name,
|
||||
message: spec.warning | toWarningText,
|
||||
cssClass: 'enter-click'
|
||||
}"
|
||||
slot="end"
|
||||
placeholder="Select"
|
||||
[formControlName]="spec.tag.id"
|
||||
[formControlName]="unionSelectKey"
|
||||
[selectedText]="variantName"
|
||||
(ionChange)="updateUnion($event)"
|
||||
>
|
||||
@@ -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 }}
|
||||
</ion-select-option>
|
||||
</ion-select>
|
||||
</ion-item-divider>
|
||||
|
||||
@@ -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<string, any>
|
||||
@Input() original?: Record<string, any>
|
||||
|
||||
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])
|
||||
})
|
||||
}
|
||||
|
||||
@@ -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({
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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',
|
||||
|
||||
@@ -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'] || '',
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -714,46 +714,43 @@ export module Mock {
|
||||
spec: {
|
||||
'bitcoind-p2p': {
|
||||
type: 'union',
|
||||
tag: {
|
||||
id: 'type',
|
||||
name: 'Bitcoin Core P2P',
|
||||
description:
|
||||
'<p>The Bitcoin Core node to connect to over the peer-to-peer (P2P) interface:</p><ul><li><strong>Bitcoin Core</strong>: The Bitcoin Core service installed on this device</li><li><strong>External Node</strong>: A Bitcoin node running on a different device</li></ul>',
|
||||
'variant-names': {
|
||||
internal: 'Bitcoin Core',
|
||||
external: 'External Node',
|
||||
},
|
||||
warning: null,
|
||||
},
|
||||
name: 'Bitcoin Core P2P',
|
||||
description:
|
||||
'<p>The Bitcoin Core node to connect to over the peer-to-peer (P2P) interface:</p><ul><li><strong>Bitcoin Core</strong>: The Bitcoin Core service installed on this device</li><li><strong>External Node</strong>: A Bitcoin node running on a different device</li></ul>',
|
||||
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<ul><li>Item 1</li><li>Item 2</li></ul>',
|
||||
warning: 'Careful changing this',
|
||||
},
|
||||
name: 'Bitcoin Node Settings',
|
||||
description: 'Options<ul><li>Item 1</li><li>Item 2</li></ul>',
|
||||
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,
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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<string, any> = {},
|
||||
): 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<string, any> | 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<string, string>,
|
||||
) {
|
||||
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<any>,
|
||||
): 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<any>): 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)
|
||||
})
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
@@ -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'
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user