Просмотр исходного кода

fix: style count and other fields

jamesread 1 день назад
Родитель
Сommit
a69eef637c

+ 22 - 0
frontend/resources/vue/utils/argumentInputType.js

@@ -0,0 +1,22 @@
+const typesWithoutInputType = ['html', 'raw_string_multiline', 'select']
+
+const htmlInputTypesByArgumentType = {
+  checkbox: 'checkbox',
+  confirmation: 'checkbox',
+  datetime: 'datetime-local',
+  email: 'email',
+  int: 'number',
+  password: 'password',
+  url: 'url'
+}
+
+// Argument types are OliveTin validation types, not HTML input types; anything
+// without a matching HTML type renders as text so that it is styled and the
+// browser does not have to guess.
+export function argumentInputType (arg) {
+  if (typesWithoutInputType.includes(arg.type)) {
+    return undefined
+  }
+
+  return htmlInputTypesByArgumentType[arg.type] ?? 'text'
+}

+ 29 - 0
frontend/resources/vue/utils/argumentInputType.test.mjs

@@ -0,0 +1,29 @@
+import test from 'node:test'
+import assert from 'node:assert/strict'
+
+import { argumentInputType } from './argumentInputType.js'
+
+test('argumentInputType renders int arguments as number inputs', () => {
+  assert.equal(argumentInputType({ type: 'int' }), 'number')
+})
+
+test('argumentInputType maps argument types to valid HTML input types', () => {
+  assert.equal(argumentInputType({ type: 'confirmation' }), 'checkbox')
+  assert.equal(argumentInputType({ type: 'checkbox' }), 'checkbox')
+  assert.equal(argumentInputType({ type: 'datetime' }), 'datetime-local')
+  assert.equal(argumentInputType({ type: 'email' }), 'email')
+  assert.equal(argumentInputType({ type: 'password' }), 'password')
+  assert.equal(argumentInputType({ type: 'url' }), 'url')
+})
+
+test('argumentInputType renders validation-only types as text inputs', () => {
+  for (const type of ['', 'ascii', 'ascii_identifier', 'ascii_sentence', 'dnsname', 'shell_safe_identifier', 'unicode_identifier', 'very_dangerous_raw_string', 'regex:^[a-z]+$']) {
+    assert.equal(argumentInputType({ type }), 'text', type)
+  }
+})
+
+test('argumentInputType has no input type for non-input arguments', () => {
+  for (const type of ['html', 'raw_string_multiline', 'select']) {
+    assert.equal(argumentInputType({ type }), undefined, type)
+  }
+})

+ 2 - 21
frontend/resources/vue/views/ArgumentForm.vue

@@ -87,7 +87,7 @@
               :value="(arg.type === 'checkbox' || arg.type === 'confirmation') ? undefined : getArgumentValue(arg)"
               :checked="(arg.type === 'checkbox' || arg.type === 'confirmation') ? getArgumentValue(arg) : undefined"
               :list="(arg.suggestions || getBrowserSuggestions(arg).length > 0) ? argumentFieldChoicesId(arg.name) : undefined"
-              :type="getInputComponent(arg) !== 'select' ? getInputType(arg) : undefined"
+              :type="getInputComponent(arg) !== 'select' ? argumentInputType(arg) : undefined"
               :rows="arg.type === 'raw_string_multiline' ? 5 : undefined"
               :step="arg.type === 'datetime' ? 1 : undefined"
               :pattern="getPattern(arg)"
@@ -158,6 +158,7 @@ import {
   argumentFieldId,
   argumentFieldValidationElementId
 } from '../utils/argumentFieldIds.js'
+import { argumentInputType } from '../utils/argumentInputType.js'
 import { getInitialArgumentValue, readPrefilledArgumentsFromNavigation } from '../utils/prefilledArguments.js'
 
 const router = useRouter()
@@ -285,26 +286,6 @@ function getInputComponent (arg) {
   }
 }
 
-function getInputType (arg) {
-  if (arg.type === 'html' || arg.type === 'raw_string_multiline' || arg.type === 'select') {
-    return undefined
-  }
-
-  if (arg.type === 'confirmation') {
-    return 'checkbox'
-  }
-
-  if (arg.type === 'ascii_identifier' || arg.type === 'dnsname' || arg.type === 'shell_safe_identifier' || arg.type === 'ascii' || arg.type === 'ascii_sentence') {
-    return 'text'
-  }
-
-  if (arg.type === 'datetime') {
-    return 'datetime-local'
-  }
-
-  return arg.type
-}
-
 function getPattern (arg) {
   if (arg.type && arg.type.startsWith('regex:')) {
     return arg.type.replace('regex:', '')