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

Merge branch 'next' into feat-add-language-support

James Read 7 месяцев назад
Родитель
Сommit
9cf79863b3

+ 3 - 6
frontend/resources/vue/components/DashboardComponent.vue

@@ -14,12 +14,9 @@
     </div>
 
     <template v-else-if="component.type == 'fieldset'">
-        <fieldset>
-            <legend>{{ component.title }}</legend>
-            <template v-for="subcomponent in component.contents" :key="subcomponent.title">
-                <DashboardComponent :component="subcomponent" />
-            </template>
-        </fieldset>
+        <template v-for="subcomponent in component.contents" :key="subcomponent.title">
+            <DashboardComponent :component="subcomponent" />
+        </template>
     </template>
 
     <div v-else>

+ 45 - 48
frontend/resources/vue/views/ArgumentForm.vue

@@ -7,30 +7,30 @@
       <form @submit="handleSubmit">
         <template v-if="actionArguments.length > 0">
 
-          <template v-for="arg in actionArguments" :key="arg.name" class="argument-group">
-            <label :for="arg.name">
-              {{ formatLabel(arg.title) }}
-            </label>
-
-            <datalist v-if="arg.suggestions && Object.keys(arg.suggestions).length > 0" :id="`${arg.name}-choices`">
-              <option v-for="(suggestion, key) in arg.suggestions" :key="key" :value="key">
-                {{ suggestion }}
-              </option>
-            </datalist>
-
-            <select v-if="getInputComponent(arg) === 'select'" :id="arg.name" :name="arg.name" :value="getArgumentValue(arg)"
-              :required="arg.required" @input="handleInput(arg, $event)" @change="handleChange(arg, $event)">
-              <option v-for="choice in arg.choices" :key="choice.value" :value="choice.value">
-                {{ choice.title || choice.value }}
-              </option>
-            </select>
-            
-            <component v-else :is="getInputComponent(arg)" :id="arg.name" :name="arg.name" :value="getArgumentValue(arg)"
-              :list="arg.suggestions ? `${arg.name}-choices` : undefined" 
-              :type="getInputComponent(arg) !== 'select' ? getInputType(arg) : undefined"
-              :rows="arg.type === 'raw_string_multiline' ? 5 : undefined"
-              :step="arg.type === 'datetime' ? 1 : undefined" :pattern="getPattern(arg)" :required="arg.required"
-              @input="handleInput(arg, $event)" @change="handleChange(arg, $event)" />
+          <template v-for="arg in actionArguments" :key="arg.name">
+              <label :for="arg.name">
+                {{ formatLabel(arg.title) }}
+              </label>
+
+              <datalist v-if="arg.suggestions && Object.keys(arg.suggestions).length > 0" :id="`${arg.name}-choices`">
+                <option v-for="(suggestion, key) in arg.suggestions" :key="key" :value="key">
+                  {{ suggestion }}
+                </option>
+              </datalist>
+
+              <select v-if="getInputComponent(arg) === 'select'" :id="arg.name" :name="arg.name" :value="getArgumentValue(arg)"
+                :required="arg.required" @input="handleInput(arg, $event)" @change="handleChange(arg, $event)">
+                <option v-for="choice in arg.choices" :key="choice.value" :value="choice.value">
+                  {{ choice.title || choice.value }}
+                </option>
+              </select>
+              
+              <component v-else :is="getInputComponent(arg)" :id="arg.name" :name="arg.name" :value="getArgumentValue(arg)"
+                :list="arg.suggestions ? `${arg.name}-choices` : undefined" 
+                :type="getInputComponent(arg) !== 'select' ? getInputType(arg) : undefined"
+                :rows="arg.type === 'raw_string_multiline' ? 5 : undefined"
+                :step="arg.type === 'datetime' ? 1 : undefined" :pattern="getPattern(arg)" :required="arg.required"
+                @input="handleInput(arg, $event)" @change="handleChange(arg, $event)" />
 
             <span class="argument-description" v-html="arg.description"></span>
           </template>
@@ -96,18 +96,27 @@ async function setup() {
 
   // Initialize values from query params or defaults
   actionArguments.value.forEach(arg => {
-    const paramValue = getQueryParamValue(arg.name)
-    argValues.value[arg.name] = paramValue !== null ? paramValue : arg.defaultValue || ''
-
     if (arg.type === 'confirmation') {
       hasConfirmation.value = true
+      const paramValue = getQueryParamValue(arg.name)
+      let checkedValue = false
+      if (paramValue !== null) {
+        checkedValue = paramValue === '1' || paramValue === 'true' || paramValue === true
+      } else if (arg.defaultValue !== undefined && arg.defaultValue !== '') {
+        checkedValue = arg.defaultValue === '1' || arg.defaultValue === 'true' || arg.defaultValue === true
+      }
+      argValues.value[arg.name] = checkedValue
+      confirmationChecked.value = checkedValue
+    } else {
+      const paramValue = getQueryParamValue(arg.name)
+      argValues.value[arg.name] = paramValue !== null ? paramValue : arg.defaultValue || ''
     }
   })
 
   // Run initial validation on all fields after DOM is updated
   await nextTick()
   for (const arg of actionArguments.value) {
-    if (arg.type && !arg.type.startsWith('regex:') && arg.type !== 'select' && arg.type !== '') {
+    if (arg.type && !arg.type.startsWith('regex:') && arg.type !== 'select' && arg.type !== '' && arg.type !== 'confirmation') {
       await validateArgument(arg, argValues.value[arg.name])
     }
   }
@@ -143,7 +152,11 @@ function getInputType(arg) {
     return undefined
   }
 
-  if (arg.type === 'ascii_identifier') {
+  if (arg.type === 'confirmation') {
+    return 'checkbox'
+  }
+
+  if (arg.type === 'ascii_identifier' || arg.type === 'ascii') {
     return 'text'
   }
 
@@ -158,8 +171,8 @@ function getPattern(arg) {
 }
 
 function getArgumentValue(arg) {
-  if (arg.type === 'checkbox') {
-    return argValues.value[arg.name] === '1' || argValues.value[arg.name] === true
+  if (arg.type === 'checkbox' || arg.type === 'confirmation') {
+    return argValues.value[arg.name] === '1' || argValues.value[arg.name] === true || argValues.value[arg.name] === 'true'
   }
   return argValues.value[arg.name] || ''
 }
@@ -240,7 +253,7 @@ function getArgumentValues() {
   for (const arg of actionArguments.value) {
     let value = argValues.value[arg.name] || ''
 
-    if (arg.type === 'checkbox') {
+    if (arg.type === 'checkbox' || arg.type === 'confirmation') {
       value = value ? '1' : '0'
     }
 
@@ -348,22 +361,6 @@ form {
   grid-template-columns: max-content auto auto;
 }
 
-.argument-group {
-  display: flex;
-  flex-direction: column;
-  gap: 0.25rem;
-}
-
-.argument-group label {
-  font-weight: 500;
-  color: #333;
-}
-
-.argument-group input:invalid,
-.argument-group select:invalid,
-.argument-group textarea:invalid {
-  border-color: #dc3545;
-}
 
 .argument-description {
   font-size: 0.875rem;

+ 12 - 1
frontend/resources/vue/views/ExecutionView.vue

@@ -104,7 +104,7 @@ let terminal = null
 function initializeTerminal() {
   terminal = new OutputTerminal(executionTrackingId.value)
   terminal.open(xtermOutput.value)
-  terminal.resize(80, 24)
+  terminal.resize(80, 40)
 
   window.terminal = terminal
 }
@@ -327,6 +327,17 @@ function goBack() {
 }
 
 onMounted(() => {
+  document.addEventListener('fullscreenchange', (e) => {
+    setTimeout(() => { // Wait for the DOM to settle
+      if (document.fullscreenElement) {
+        window.terminal.fit()
+      } else {
+        window.terminal.resize(80, 40)
+        window.terminal.fit()
+      }
+    }, 100)
+  })
+
   initializeTerminal()
   fetchExecutionResult(props.executionTrackingId)
 

+ 1 - 1
integration-tests/test/dashboardsWithBasicFieldsets.js

@@ -43,7 +43,7 @@ describe('config: dashboards with basic fieldsets', function () {
 
     // Check that we have the expected number of fieldsets
     const allFieldsets = await webdriver.findElements(By.css('fieldset'))
-    expect(allFieldsets).to.have.length(5, 'Expected 5 fieldsets total')
+    expect(allFieldsets).to.have.length(3, 'Expected 3 fieldsets total')
     
     // Check that we have fieldsets with the expected titles
     const fieldsetTitles = []

+ 3 - 6
service/internal/api/dashboards.go

@@ -89,13 +89,10 @@ func buildDefaultDashboard(rr *DashboardRenderRequest) *apiv1.Dashboard {
 }
 
 func sortActions(components []*apiv1.DashboardComponent) []*apiv1.DashboardComponent {
+	log.Infof("sortActions: %+v", components)
 	sort.Slice(components, func(i, j int) bool {
-		if components[i].Action == nil {
-			return false
-		}
-
-		if components[j].Action == nil {
-			return true
+		if components[i].Action == nil || components[j].Action == nil {
+			return components[i].Title < components[j].Title
 		}
 
 		if components[i].Action.Order == components[j].Action.Order {