inputspec and required instead of nullable

This commit is contained in:
Matt Hill
2023-03-31 10:31:23 -06:00
committed by Aiden McClelland
parent 5675fc51a0
commit e4cd4d64d7
14 changed files with 143 additions and 96 deletions

View File

@@ -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.beta5",
"start-sdk": "^0.4.0-lib0.beta6",
"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.beta5",
"resolved": "https://registry.npmjs.org/start-sdk/-/start-sdk-0.4.0-lib0.beta5.tgz",
"integrity": "sha512-dHWn7urjTXtS+CujkRp7U/CiSk/mTuvXjmFt8WMhnPExu2FFdmn72LDOICn5hf8kS0oi1qcYtjzq4juD8HlVFQ==",
"version": "0.4.0-lib0.beta6",
"resolved": "https://registry.npmjs.org/start-sdk/-/start-sdk-0.4.0-lib0.beta6.tgz",
"integrity": "sha512-9dR2noD/rJ4u/Xuhs5S0+lv95nqpERWzxbXlpXDbtjXzMKzX8v1zmKKMNfTir1oxaZC820llLlaCeuPG2VGNpg==",
"dependencies": {
"@iarna/toml": "^2.2.5",
"lodash": "^4.17.21",

View File

@@ -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.beta5",
"start-sdk": "^0.4.0-lib0.beta6",
"swiper": "^8.2.4",
"ts-matches": "^5.2.1",
"tslib": "^2.3.0",

View File

@@ -280,10 +280,11 @@ const CifsSpec: InputSpec = {
name: 'Hostname',
description:
'The hostname of your target device on the Local Area Network.',
inputmode: 'text',
placeholder: `e.g. 'My Computer' OR 'my-computer.local'`,
pattern: '^[a-zA-Z0-9._-]+( [a-zA-Z0-9]+)*$',
patternDescription: `Must be a valid hostname. e.g. 'My Computer' OR 'my-computer.local'`,
nullable: false,
required: true,
masked: false,
default: null,
warning: null,
@@ -292,10 +293,11 @@ const CifsSpec: InputSpec = {
type: 'string',
name: 'Path',
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).`,
inputmode: 'text',
placeholder: 'e.g. my-shared-folder or /Desktop/my-folder',
pattern: null,
patternDescription: null,
nullable: false,
required: true,
masked: false,
default: null,
warning: null,
@@ -304,10 +306,11 @@ const CifsSpec: InputSpec = {
type: 'string',
name: 'Username',
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.`,
inputmode: 'text',
placeholder: null,
pattern: null,
patternDescription: null,
nullable: false,
required: true,
masked: false,
default: null,
warning: null,
@@ -316,10 +319,11 @@ const CifsSpec: InputSpec = {
type: 'string',
name: 'Password',
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.`,
inputmode: 'text',
placeholder: null,
pattern: null,
patternDescription: null,
nullable: true,
required: false,
masked: true,
default: null,
warning: null,

View File

@@ -4,7 +4,7 @@
name: spec.name,
description: spec.description,
edited: control.dirty,
required: !spec.nullable
required: spec.required
}"
></form-label>
<ion-item [color]="(theme$ | async) === 'Light' ? 'light' : 'dark'">

View File

@@ -53,11 +53,11 @@
</div>
<div class="ion-text-right">
<ion-button fill="clear" (click)="cancel()"> Cancel </ion-button>
<ion-button fill="clear" (click)="cancel()">Cancel</ion-button>
<ion-button
fill="clear"
type="submit"
[disabled]="!value && !options.nullable"
[disabled]="!value && !options.required"
>
{{ options.buttonText }}
</ion-button>

View File

@@ -31,8 +31,7 @@ export class GenericInputComponent {
ngOnInit() {
const defaultOptions: Partial<GenericInputOptions> = {
buttonText: 'Submit',
placeholder: 'Enter value',
nullable: false,
required: true,
useMask: false,
initialValue: '',
}
@@ -69,7 +68,7 @@ export class GenericInputComponent {
async submit() {
const value = this.value.trim()
if (!value && !this.options.nullable) return
if (!value && this.options.required) return
try {
await this.options.submitFn(value)
@@ -84,13 +83,13 @@ export interface GenericInputOptions {
// required
title: string
message: string
label: string
submitFn: (value: string) => Promise<any>
// optional
label?: string
warning?: string
buttonText?: string
placeholder?: string
nullable?: boolean
required?: boolean
useMask?: boolean
initialValue?: string | null
}

View File

@@ -273,7 +273,8 @@ function getMarketplaceValueSpec(): ValueSpecObject {
type: 'string',
name: 'URL',
description: 'A fully-qualified URL of the custom registry',
nullable: false,
inputmode: 'url',
required: true,
masked: false,
pattern: `https?:\/\/[a-zA-Z0-9][a-zA-Z0-9-\.]+[a-zA-Z0-9]\.[^\s]{2,}`,
patternDescription: 'Must be a valid URL',

View File

@@ -57,7 +57,7 @@ export class DeveloperListPage {
label: 'New project',
useMask: false,
placeholder: `Project ${projNumber}`,
nullable: true,
required: false,
initialValue: `Project ${projNumber}`,
buttonText: 'Save',
submitFn: (value: string) => this.createProject(value),
@@ -112,7 +112,7 @@ export class DeveloperListPage {
label: 'Name',
useMask: false,
placeholder: curName,
nullable: true,
required: false,
initialValue: curName,
buttonText: 'Save',
submitFn: (value: string) => this.editName(id, value),
@@ -221,7 +221,8 @@ const SAMPLE_CONFIG: InputSpec = {
'sample-string': {
type: 'string',
name: 'Example String Input',
nullable: false,
inputmode: 'text',
required: true,
masked: false,
// optional
description: 'Example description for required string input.',
@@ -234,7 +235,8 @@ const SAMPLE_CONFIG: InputSpec = {
'sample-number': {
type: 'number',
name: 'Example Number Input',
nullable: false,
inputmode: 'decimal',
required: true,
range: '[5,1000000]',
integral: true,
// optional

View File

@@ -22,10 +22,11 @@ export function getBasicInfoSpec(devData: DevProjectData): InputSpec {
return {
id: {
type: 'string',
inputmode: 'text',
name: 'ID',
description: 'The package identifier used by the OS',
placeholder: 'e.g. bitcoind',
nullable: false,
required: true,
masked: false,
pattern: '^([a-z][a-z0-9]*)(-[a-z0-9]+)*$',
patternDescription: 'Must be kebab case',
@@ -34,10 +35,11 @@ export function getBasicInfoSpec(devData: DevProjectData): InputSpec {
},
title: {
type: 'string',
inputmode: 'text',
name: 'Service Name',
description: 'A human readable service title',
placeholder: 'e.g. Bitcoin Core',
nullable: false,
required: true,
masked: false,
pattern: null,
patternDescription: null,
@@ -46,11 +48,12 @@ export function getBasicInfoSpec(devData: DevProjectData): InputSpec {
},
'service-version-number': {
type: 'string',
inputmode: 'text',
name: 'Service Version',
description:
'Service version - accepts up to four digits, where the last confirms to revisions necessary for StartOS - see documentation: https://github.com/Start9Labs/emver-rs. This value will change with each release of the service',
placeholder: 'e.g. 0.1.2.3',
nullable: false,
required: true,
masked: false,
pattern: '^([0-9]+).([0-9]+).([0-9]+).([0-9]+)$',
patternDescription: 'Must be valid Emver version',
@@ -65,11 +68,12 @@ export function getBasicInfoSpec(devData: DevProjectData): InputSpec {
spec: {
short: {
type: 'string',
inputmode: 'text',
name: 'Short Description',
description:
'This is the first description visible to the user in the marketplace',
placeholder: null,
nullable: false,
required: true,
masked: false,
default: basicInfo?.description?.short || '',
pattern: '^.{1,320}$',
@@ -81,18 +85,19 @@ export function getBasicInfoSpec(devData: DevProjectData): InputSpec {
name: 'Long Description',
description: `This description will display with additional details in the service's individual marketplace page`,
placeholder: null,
nullable: false,
required: true,
warning: null,
},
},
},
'release-notes': {
type: 'string',
inputmode: 'text',
name: 'Release Notes',
description:
'Markdown supported release notes for this version of this service.',
placeholder: 'e.g. Markdown _release notes_ for **Bitcoin Core**',
nullable: false,
required: true,
masked: false,
pattern: null,
patternDescription: null,
@@ -115,54 +120,58 @@ export function getBasicInfoSpec(devData: DevProjectData): InputSpec {
custom: 'Custom',
},
description: 'Example description for select',
nullable: false,
required: true,
default: 'mit',
},
'wrapper-repo': {
type: 'string',
inputmode: 'url',
name: 'Wrapper Repo',
description:
'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,
patternDescription: null,
nullable: false,
required: true,
masked: false,
default: basicInfo?.['wrapper-repo'] || '',
warning: null,
},
'upstream-repo': {
type: 'string',
inputmode: 'url',
name: 'Upstream Repo',
description: 'The original project repository URL',
placeholder: 'e.g. www.github.com/example',
pattern: null,
patternDescription: null,
nullable: true,
required: false,
masked: false,
default: basicInfo?.['upstream-repo'] || '',
warning: null,
},
'support-site': {
type: 'string',
inputmode: 'url',
name: 'Support Site',
description: 'URL to the support site / channel for the project',
placeholder: 'e.g. start9.com/support',
pattern: null,
patternDescription: null,
nullable: true,
required: false,
masked: false,
default: basicInfo?.['support-site'] || '',
warning: null,
},
'marketing-site': {
type: 'string',
inputmode: 'url',
name: 'Website',
description: 'URL to the marketing site / channel for the project',
placeholder: 'e.g. start9.com',
pattern: null,
patternDescription: null,
nullable: true,
required: false,
masked: false,
default: basicInfo?.['marketing-site'] || '',
warning: null,

View File

@@ -84,7 +84,7 @@ export class ServerShowPage {
label: 'Device Name',
useMask: false,
placeholder: 'StartOS',
nullable: true,
required: false,
initialValue: chosenName,
buttonText: 'Save',
submitFn: (name: string) => this.setName(name || null),

View File

@@ -45,12 +45,11 @@ export class SSHKeysPage {
}
async presentModalAdd() {
const { name, description } = sshSpec
const options: GenericInputOptions = {
title: name,
message: description,
label: name,
title: 'SSH Key',
message:
'Enter the SSH public key you would like to authorize for root access to your Embassy.',
label: '',
submitFn: (pk: string) => this.add(pk),
}
@@ -114,13 +113,3 @@ export class SSHKeysPage {
}
}
}
const sshSpec = {
type: 'string',
name: 'SSH Key',
description:
'Enter the SSH public key you would like to authorize for root access to your server.',
nullable: false,
masked: false,
copyable: false,
}

View File

@@ -359,10 +359,11 @@ function getWifiValueSpec(
type: 'string',
name: 'Network SSID',
description: null,
inputmode: 'text',
placeholder: null,
pattern: null,
patternDescription: null,
nullable: false,
required: true,
masked: false,
default: ssid || null,
warning: null,
@@ -371,8 +372,9 @@ function getWifiValueSpec(
type: 'string',
name: 'Password',
description: null,
inputmode: 'text',
placeholder: null,
nullable: !needsPW,
required: needsPW,
masked: true,
pattern: '^.{8,}$',
patternDescription: 'Must be longer than 8 characters',

View File

@@ -657,6 +657,7 @@ export module Mock {
data: {
lndconnect: {
type: 'string',
inputmode: 'text',
description: 'This is some information about the thing.',
copyable: true,
qr: true,
@@ -670,6 +671,7 @@ export module Mock {
value: {
'Last Name': {
type: 'string',
inputmode: 'text',
description: 'The last name of the user',
copyable: true,
qr: true,
@@ -678,6 +680,7 @@ export module Mock {
},
Age: {
type: 'string',
inputmode: 'text',
description: 'The age of the user',
copyable: false,
qr: false,
@@ -686,6 +689,7 @@ export module Mock {
},
Password: {
type: 'string',
inputmode: 'text',
description: 'A secret password',
copyable: true,
qr: false,
@@ -696,6 +700,7 @@ export module Mock {
},
'Another Value': {
type: 'string',
inputmode: 'text',
description: 'Some more information about the service.',
copyable: false,
qr: true,
@@ -720,7 +725,7 @@ export module Mock {
'<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: null,
nullable: false,
required: true,
variants: {
internal: { name: 'Internal', spec: {} },
external: {
@@ -728,9 +733,10 @@ export module Mock {
spec: {
'p2p-host': {
type: 'string',
inputmode: 'text',
name: 'Public Address',
description: 'The public address of your Bitcoin Core server',
nullable: false,
required: true,
masked: false,
placeholder: null,
pattern: null,
@@ -740,10 +746,11 @@ export module Mock {
},
'p2p-port': {
type: 'number',
inputmode: 'numeric',
name: 'P2P Port',
description:
'The port that your Bitcoin Core P2P server is bound to',
nullable: false,
required: true,
range: '[0,65535]',
integral: true,
default: 8333,
@@ -773,10 +780,11 @@ export module Mock {
rpcuser2: {
name: 'RPC Username',
type: 'string',
inputmode: 'text',
description: 'rpc username',
warning: null,
placeholder: null,
nullable: false,
required: true,
default: 'defaultrpcusername',
pattern: '^[a-zA-Z]+$',
patternDescription: 'must contain only letters.',
@@ -785,10 +793,11 @@ export module Mock {
rpcuser: {
name: 'RPC Username',
type: 'string',
inputmode: 'text',
description: 'rpc username',
warning: null,
placeholder: null,
nullable: false,
required: true,
default: 'defaultrpcusername',
pattern: '^[a-zA-Z]+$',
patternDescription: 'must contain only letters.',
@@ -797,10 +806,11 @@ export module Mock {
rpcpass: {
name: 'RPC User Password',
type: 'string',
inputmode: 'text',
description: 'rpc password',
placeholder: null,
warning: null,
nullable: false,
required: true,
default: {
charset: 'a-z,A-Z,2-9',
len: 20,
@@ -812,10 +822,11 @@ export module Mock {
rpcpass2: {
name: 'RPC User Password',
type: 'string',
inputmode: 'text',
description: 'rpc password',
warning: null,
placeholder: null,
nullable: false,
required: true,
default: {
charset: 'a-z,A-Z,2-9',
len: 20,
@@ -834,7 +845,7 @@ export module Mock {
description: 'Your personal bio',
placeholder: 'Tell the world about yourself',
warning: null,
nullable: true,
required: false,
},
testnet: {
name: 'Testnet',
@@ -849,7 +860,7 @@ export module Mock {
type: 'file',
description: 'A file we need',
warning: 'Testing warning',
nullable: false,
required: true,
extensions: ['.png'],
},
'object-list': {
@@ -880,8 +891,9 @@ export module Mock {
'first-name': {
name: 'First Name',
type: 'string',
inputmode: 'text',
description: 'User first name',
nullable: true,
required: false,
masked: false,
placeholder: null,
pattern: null,
@@ -892,8 +904,9 @@ export module Mock {
'last-name': {
name: 'Last Name',
type: 'string',
inputmode: 'text',
description: 'User first name',
nullable: true,
required: false,
default: {
charset: 'a-g,2-9',
len: 12,
@@ -906,9 +919,10 @@ export module Mock {
},
age: {
name: 'Age',
inputmode: 'numeric',
type: 'number',
description: 'The age of the user',
nullable: true,
required: false,
integral: false,
warning: 'User must be at least 18.',
range: '[18,*)',
@@ -930,7 +944,7 @@ export module Mock {
default: 'sup',
description: 'This is not even real.',
warning: 'Be careful changing this!',
nullable: false,
required: true,
},
notifications: {
name: 'Notification Preferences',
@@ -949,13 +963,14 @@ export module Mock {
},
'favorite-number': {
name: 'Favorite Number',
inputmode: 'decimal',
type: 'number',
integral: false,
description: 'Your favorite number of all time',
placeholder: null,
warning:
'Once you set this number, it can never be changed without severe consequences.',
nullable: true,
required: false,
default: 7,
range: '(-100,100]',
units: 'BTC',
@@ -967,6 +982,7 @@ export module Mock {
description: 'Numbers that you like but are not your top favorite.',
warning: null,
spec: {
inputmode: 'decimal',
integral: false,
range: '[-100,200)',
units: null,
@@ -990,8 +1006,9 @@ export module Mock {
law1: {
name: 'First Law',
type: 'string',
inputmode: 'text',
description: 'the first law',
nullable: true,
required: false,
masked: false,
placeholder: null,
pattern: null,
@@ -1002,8 +1019,9 @@ export module Mock {
law2: {
name: 'Second Law',
type: 'string',
inputmode: 'text',
description: 'the second law',
nullable: true,
required: false,
masked: false,
placeholder: null,
pattern: null,
@@ -1028,8 +1046,9 @@ export module Mock {
rulemakername: {
name: 'Rulemaker Name',
type: 'string',
inputmode: 'text',
description: 'the name of the rule maker',
nullable: false,
required: true,
default: {
charset: 'a-g,2-9',
len: 12,
@@ -1043,8 +1062,9 @@ export module Mock {
rulemakerip: {
name: 'Rulemaker IP',
type: 'string',
inputmode: 'text',
description: 'the ip of the rule maker',
nullable: false,
required: true,
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])$',
@@ -1059,8 +1079,9 @@ export module Mock {
rpcuser: {
name: 'RPC Username',
type: 'string',
inputmode: 'text',
description: 'rpc username',
nullable: false,
required: true,
default: 'defaultrpcusername',
pattern: '^[a-zA-Z]+$',
patternDescription: 'must contain only letters.',
@@ -1071,8 +1092,9 @@ export module Mock {
rpcpass: {
name: 'RPC User Password',
type: 'string',
inputmode: 'text',
description: 'rpc password',
nullable: false,
required: true,
default: {
charset: 'a-z,A-Z,2-9',
len: 20,
@@ -1091,7 +1113,7 @@ export module Mock {
name: 'Bitcoin Node Settings',
description: 'Options<ul><li>Item 1</li><li>Item 2</li></ul>',
warning: 'Careful changing this',
nullable: false,
required: true,
variants: {
internal: { name: 'Internal', spec: {} },
external: {
@@ -1105,9 +1127,10 @@ export module Mock {
spec: {
name: {
type: 'string',
inputmode: 'text',
name: 'Name',
description: null,
nullable: false,
required: true,
masked: false,
pattern: '^[a-zA-Z]+$',
patternDescription: 'Must contain only letters.',
@@ -1117,9 +1140,10 @@ export module Mock {
},
email: {
type: 'string',
inputmode: 'text',
name: 'Email',
description: null,
nullable: false,
required: true,
masked: false,
placeholder: null,
pattern: null,
@@ -1132,8 +1156,9 @@ export module Mock {
'public-domain': {
name: 'Public Domain',
type: 'string',
inputmode: 'text',
description: 'the public address of the node',
nullable: false,
required: true,
default: 'bitcoinnode.com',
pattern: '.*',
patternDescription: 'anything',
@@ -1144,8 +1169,9 @@ export module Mock {
'private-domain': {
name: 'Private Domain',
type: 'string',
inputmode: 'text',
description: 'the private address of the node',
nullable: false,
required: true,
masked: true,
placeholder: null,
pattern: null,
@@ -1159,12 +1185,13 @@ export module Mock {
},
port: {
name: 'Port',
inputmode: 'numeric',
type: 'number',
integral: true,
description:
'the default port for your Bitcoin node. default: 8333, testnet: 18333, regtest: 18444',
warning: null,
nullable: false,
required: true,
default: 8333,
range: '(0, 9998]',
units: null,
@@ -1173,9 +1200,10 @@ export module Mock {
'favorite-slogan': {
name: 'Favorite Slogan',
type: 'string',
inputmode: 'text',
description:
'You most favorite slogan in the whole world, used for paying you.',
nullable: true,
required: false,
masked: true,
placeholder: null,
pattern: null,
@@ -1194,6 +1222,7 @@ export module Mock {
range: '[1,10]',
default: ['192.168.1.1'],
spec: {
inputmode: 'text',
masked: false,
placeholder: null,
pattern:
@@ -1210,6 +1239,7 @@ export module Mock {
range: '[0,*)',
default: [],
spec: {
inputmode: 'text',
masked: false,
placeholder: null,
pattern: null,
@@ -1238,8 +1268,9 @@ export module Mock {
law1: {
name: 'First Law',
type: 'string',
inputmode: 'text',
description: 'the first law',
nullable: true,
required: false,
masked: false,
placeholder: null,
pattern: null,
@@ -1250,8 +1281,9 @@ export module Mock {
law2: {
name: 'Second Law',
type: 'string',
inputmode: 'text',
description: 'the second law',
nullable: true,
required: false,
masked: false,
placeholder: null,
pattern: null,
@@ -1262,8 +1294,9 @@ export module Mock {
law4: {
name: 'Fourth Law',
type: 'string',
inputmode: 'text',
description: 'the fourth law',
nullable: true,
required: false,
masked: false,
placeholder: null,
pattern: null,
@@ -1286,8 +1319,9 @@ export module Mock {
lawname: {
name: 'Law Name',
type: 'string',
inputmode: 'text',
description: 'the name of the law maker',
nullable: false,
required: true,
default: {
charset: 'a-g,2-9',
len: 12,
@@ -1301,8 +1335,9 @@ export module Mock {
lawagency: {
name: 'Law agency',
type: 'string',
inputmode: 'text',
description: 'the ip of the law maker',
nullable: false,
required: true,
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])$',
@@ -1318,8 +1353,9 @@ export module Mock {
law5: {
name: 'Fifth Law',
type: 'string',
inputmode: 'text',
description: 'the fifth law',
nullable: true,
required: false,
masked: false,
placeholder: null,
pattern: null,
@@ -1344,8 +1380,9 @@ export module Mock {
rulemakername: {
name: 'Rulemaker Name',
type: 'string',
inputmode: 'text',
description: 'the name of the rule maker',
nullable: false,
required: true,
default: {
charset: 'a-g,2-9',
len: 12,
@@ -1359,8 +1396,9 @@ export module Mock {
rulemakerip: {
name: 'Rulemaker IP',
type: 'string',
inputmode: 'text',
description: 'the ip of the rule maker',
nullable: false,
required: true,
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])$',
@@ -1375,8 +1413,9 @@ export module Mock {
rpcuser: {
name: 'RPC Username',
type: 'string',
inputmode: 'text',
description: 'rpc username',
nullable: false,
required: true,
default: 'defaultrpcusername',
pattern: '^[a-zA-Z]+$',
patternDescription: 'must contain only letters.',
@@ -1387,8 +1426,9 @@ export module Mock {
rpcpass: {
name: 'RPC User Password',
type: 'string',
inputmode: 'text',
description: 'rpc password',
nullable: false,
required: true,
default: {
charset: 'a-z,A-Z,2-9',
len: 20,
@@ -1498,10 +1538,11 @@ export module Mock {
'input-spec': {
reason: {
type: 'string',
inputmode: 'text',
name: 'Re-sync Reason',
description: 'Your reason for re-syncing. Why are you doing this?',
placeholder: null,
nullable: false,
required: true,
masked: false,
pattern: '^[a-zA-Z]+$',
patternDescription: 'Must contain only letters.',

View File

@@ -47,7 +47,7 @@ export class FormService {
spec: ValueSpecUnion,
selection: string | null,
): UntypedFormGroup {
const { name, description, warning, variants, nullable } = spec
const { name, description, warning, variants, required } = spec
const selectSpec: ValueSpecSelect = {
type: 'select',
@@ -55,7 +55,7 @@ export class FormService {
description,
warning,
default: selection,
nullable,
required,
values: Object.keys(variants).reduce(
(prev, curr) => ({
...prev,
@@ -172,7 +172,7 @@ function stringValidators(
): ValidatorFn[] {
const validators: ValidatorFn[] = []
if (!(spec as ValueSpecString).nullable) {
if ((spec as ValueSpecString).required) {
validators.push(Validators.required)
}
@@ -186,7 +186,7 @@ function stringValidators(
function textareaValidators(spec: ValueSpecTextarea): ValidatorFn[] {
const validators: ValidatorFn[] = []
if (!spec.nullable) {
if (spec.required) {
validators.push(Validators.required)
}
@@ -200,7 +200,7 @@ function numberValidators(
validators.push(isNumber())
if (!(spec as ValueSpecNumber).nullable) {
if ((spec as ValueSpecNumber).required) {
validators.push(Validators.required)
}
@@ -216,7 +216,7 @@ function numberValidators(
function selectValidators(spec: ValueSpecSelect): ValidatorFn[] {
const validators: ValidatorFn[] = []
if (!spec.nullable) {
if (spec.required) {
validators.push(Validators.required)
}
@@ -239,7 +239,7 @@ function listValidators(spec: ValueSpecList): ValidatorFn[] {
function fileValidators(spec: ValueSpecFile): ValidatorFn[] {
const validators: ValidatorFn[] = []
if (!spec.nullable) {
if (spec.required) {
validators.push(Validators.required)
}