@raclettejs/workbench 0.1.33-canary.2 → 0.1.33

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (29) hide show
  1. package/.raclette/backend/raclette.config.js +3 -3
  2. package/.raclette/backend/yarn.lock +4 -11
  3. package/.raclette/frontend/raclette.config.js +6 -4
  4. package/.raclette/frontend/yarn.lock +451 -489
  5. package/.raclette/virtual/backend/raclette.config.js +3 -3
  6. package/.raclette/virtual/backend/yarn.lock +4 -11
  7. package/.raclette/virtual/frontend/raclette.config.js +6 -4
  8. package/.raclette/virtual/frontend/yarn.lock +451 -489
  9. package/CHANGELOG.md +19 -3
  10. package/i18n/de-DE.json +15 -0
  11. package/i18n/en-EU.json +15 -0
  12. package/i18n/sk-SK.json +15 -0
  13. package/package.json +5 -4
  14. package/plugins/pacifico__compositions/frontend/widgets/CompositionListWidget.vue +39 -21
  15. package/plugins/pacifico__interactionLinks/frontend/widgets/InteractionLinkListWidget.vue +39 -21
  16. package/plugins/pacifico__plugins/frontend/index.ts +3 -3
  17. package/plugins/pacifico__plugins/frontend/widgets/PluginListWidget.vue +11 -12
  18. package/plugins/pacifico__tags/frontend/widgets/TagListWidget.vue +39 -21
  19. package/plugins/pacifico__users/frontend/widgets/UserListWidget.vue +79 -57
  20. package/services/frontend/src/app/components/dynamicForm/DynamicForm.vue +139 -51
  21. package/services/frontend/src/app/components/dynamicForm/DynamicInput.vue +95 -5
  22. package/services/frontend/src/app/components/dynamicForm/ObjectListInput.vue +78 -41
  23. package/services/frontend/src/app/components/dynamicForm/TextDivider.vue +46 -6
  24. package/services/frontend/src/app/components/dynamicForm/typedInputs/ListInput.vue +118 -27
  25. package/services/frontend/src/app/components/dynamicForm/typedInputs/RecordInput.vue +131 -21
  26. package/services/frontend/src/app/components/dynamicForm/typedInputs/TagsInput.vue +1 -0
  27. package/services/frontend/src/app/components/dynamicForm/typedInputs/TriggerInput.vue +4 -4
  28. package/services/frontend/src/app/composables/useWorkbenchTableActions.ts +29 -0
  29. package/services/frontend/src/orchestrator/assets/styles/themes/light.ts +4 -3
@@ -1,75 +1,110 @@
1
1
  <template>
2
- <div class="tw:grid tw:gap-4">
3
- <v-expansion-panels v-model="openPanels" multiple>
4
- <v-expansion-panel
5
- v-for="(item, index) in internalItems"
6
- :key="index"
7
- :value="index"
2
+ <div class="tw:flex tw:flex-col tw:gap-4">
3
+ <div
4
+ class="tw:rounded-lg tw:border tw:border-solid tw:border-[color:rgb(var(--v-theme-border-default))] tw:bg-[rgb(var(--v-theme-primary)/0.04)] tw:pb-2 tw:pl-2 tw:pr-2 tw:pt-2"
5
+ >
6
+ <v-expansion-panels
7
+ v-model="openPanels"
8
+ class="dynamic-object-list-panels tw:rounded-lg tw:bg-transparent"
9
+ flat
10
+ multiple
11
+ rounded="lg"
8
12
  >
9
- <v-expansion-panel-title class="tw:flex tw:items-center tw:gap-2">
10
- <span class="tw:flex-1">
11
- {{ getPanelTitle(item, index) }}
12
- </span>
13
- <v-btn
14
- icon="mdi-minus"
15
- size="small"
16
- variant="text"
17
- :disabled="disabled"
18
- @click.stop="removeItem(index)"
19
- />
20
- </v-expansion-panel-title>
21
-
22
- <v-expansion-panel-text>
23
- <div class="tw:grid tw:gap-4 tw:pt-4">
24
- <DynamicInput
25
- v-for="field in fields"
26
- :key="field.field as string"
27
- v-model="internalItems[index][field.field]"
28
- :input-type="field.inputType"
29
- :value="field"
13
+ <v-expansion-panel
14
+ v-for="(item, index) in internalItems"
15
+ :key="index"
16
+ :value="index"
17
+ class="tw:bg-[rgb(var(--v-theme-primary)/0.02)] [&:first-child]:tw:rounded-t-lg [&:last-child]:tw:rounded-b-lg"
18
+ >
19
+ <v-expansion-panel-title
20
+ class="tw:flex tw:min-h-14 tw:items-center tw:gap-2 tw:py-4 tw:text-[color:rgb(var(--v-theme-on-surface))]"
21
+ >
22
+ <span class="tw:flex-1 tw:truncate tw:font-semibold tw:text-sm">
23
+ {{ getPanelTitle(item, index) }}
24
+ </span>
25
+ <v-btn
26
+ icon="mdi-minus"
27
+ size="small"
28
+ variant="text"
29
+ color="error"
30
+ class="tw:shrink-0"
31
+ type="button"
32
+ :density="panelButtonDensity"
30
33
  :disabled="disabled"
31
- @update:model-value="onItemChange(index)"
32
- @validate="$emit('validate')"
34
+ :aria-label="t('workbench.dynamicInputs.objectList.removeEntry')"
35
+ @click.stop="removeItem(index)"
33
36
  />
34
- </div>
35
- </v-expansion-panel-text>
36
- </v-expansion-panel>
37
- </v-expansion-panels>
37
+ </v-expansion-panel-title>
38
+
39
+ <v-expansion-panel-text
40
+ class="tw:border-t tw:border-solid tw:border-[color:rgb(var(--v-theme-border-default))]"
41
+ >
42
+ <div class="tw:grid tw:gap-4 tw:pb-4 tw:pt-4">
43
+ <DynamicInput
44
+ v-for="field in fields"
45
+ :key="String(field.field)"
46
+ v-model="internalItems[index][field.field]"
47
+ :input-type="field.inputType"
48
+ :value="field"
49
+ :disabled="disabled"
50
+ :density="density"
51
+ @update:model-value="onItemChange(index)"
52
+ @validate="$emit('validate')"
53
+ />
54
+ </div>
55
+ </v-expansion-panel-text>
56
+ </v-expansion-panel>
57
+ </v-expansion-panels>
58
+ </div>
38
59
 
39
60
  <v-btn
40
61
  v-if="canAddNewItem"
41
- color="primary"
42
- variant="outlined"
62
+ variant="flat"
63
+ color="secondary"
43
64
  prepend-icon="mdi-plus"
65
+ class="tw:self-start tw:!rounded-lg"
66
+ size="small"
67
+ type="button"
68
+ :density="panelButtonDensity"
44
69
  :disabled="disabled"
45
70
  @click="addNewItem"
46
71
  >
47
- Add Entry
72
+ {{ t("workbench.dynamicInputs.objectList.addEntry") }}
48
73
  </v-btn>
49
74
  </div>
50
75
  </template>
51
76
 
52
77
  <script setup lang="ts" generic="T extends Record<string, any>">
53
- import { ref, watch, computed } from "vue"
78
+ import { computed, ref, watch } from "vue"
79
+ import { useI18n } from "vue-i18n"
54
80
  import DynamicInput from "./DynamicInput.vue"
55
81
  import type { DynamicFormField } from "./DynamicFormTypes"
56
82
 
83
+ const { t } = useI18n()
84
+
57
85
  const props = defineProps<{
58
86
  fields?: DynamicFormField<T>[]
59
87
  disabled?: boolean
88
+ density?: "compact" | "comfortable" | "spacious"
60
89
  }>()
61
90
 
62
91
  defineEmits<{
63
92
  validate: []
64
93
  }>()
65
94
 
95
+ const density = computed(() => props.density ?? "comfortable")
96
+
97
+ const panelButtonDensity = computed(() =>
98
+ density.value === "compact" ? "compact" : "comfortable",
99
+ )
100
+
66
101
  const modelValue = defineModel<T[]>({ required: true, default: () => [] })
67
102
 
68
103
  const internalItems = ref<T[]>([])
69
104
  const openPanels = ref<number[]>([0])
70
105
 
71
106
  const initializeEmptyItem = (): T => {
72
- const item: any = {}
107
+ const item: Record<string, unknown> = {}
73
108
  props.fields?.forEach((field) => {
74
109
  const fieldKey = field.field as string
75
110
 
@@ -127,7 +162,9 @@ const isItemEmpty = (item: T): boolean => {
127
162
 
128
163
  const getPanelTitle = (item: T, index: number): string => {
129
164
  if (!props.fields || props.fields.length === 0) {
130
- return `Entry ${index + 1}`
165
+ return t("workbench.dynamicInputs.objectList.unnamedEntry", {
166
+ n: index + 1,
167
+ })
131
168
  }
132
169
 
133
170
  const firstField = props.fields[0]
@@ -137,7 +174,7 @@ const getPanelTitle = (item: T, index: number): string => {
137
174
  return String(firstValue)
138
175
  }
139
176
 
140
- return `Entry ${index + 1}`
177
+ return t("workbench.dynamicInputs.objectList.unnamedEntry", { n: index + 1 })
141
178
  }
142
179
 
143
180
  const syncToModelValue = () => {
@@ -145,7 +182,7 @@ const syncToModelValue = () => {
145
182
  modelValue.value = nonEmptyItems
146
183
  }
147
184
 
148
- const onItemChange = (index: number) => {
185
+ const onItemChange = (_index: number) => {
149
186
  syncToModelValue()
150
187
  }
151
188
 
@@ -1,13 +1,53 @@
1
1
  <template>
2
- <div class="tw:flex tw:w-full tw:items-center tw:gap-2">
3
- <v-divider />
4
- <div class="tw:text-nowrap">{{ label }}</div>
5
- <v-divider />
2
+ <div
3
+ class="tw:flex tw:w-full tw:items-center"
4
+ :class="containerClasses"
5
+ role="separator"
6
+ :aria-label="label"
7
+ >
8
+ <v-divider
9
+ class="tw:opacity-80"
10
+ color="border-default"
11
+ thickness="1"
12
+ />
13
+ <div
14
+ class="tw:text-nowrap tw:font-medium tw:tracking-wide tw:text-[color:rgb(var(--v-theme-on-surface))]"
15
+ :class="labelClasses"
16
+ >
17
+ {{ label }}
18
+ </div>
19
+ <v-divider
20
+ class="tw:opacity-80"
21
+ color="border-default"
22
+ thickness="1"
23
+ />
6
24
  </div>
7
25
  </template>
8
26
 
9
27
  <script setup lang="ts">
10
- defineProps({
11
- label: { type: String, required: true },
28
+ import { computed } from "vue"
29
+
30
+ const props = defineProps<{
31
+ label: string
32
+ density?: "compact" | "comfortable" | "spacious"
33
+ }>()
34
+
35
+ const density = computed(() => props.density ?? "comfortable")
36
+
37
+ const containerClasses = computed(() => {
38
+ if (density.value === "compact") {
39
+ return "tw:gap-2 tw:py-2"
40
+ }
41
+ if (density.value === "spacious") {
42
+ return "tw:gap-4 tw:py-4"
43
+ }
44
+ return "tw:gap-3 tw:py-3"
45
+ })
46
+
47
+ const labelClasses = computed(() => {
48
+ if (density.value === "compact") {
49
+ return "tw:text-xs"
50
+ }
51
+ return "tw:text-sm"
12
52
  })
13
53
  </script>
@@ -1,50 +1,141 @@
1
1
  <template>
2
- <div class="tw:grid tw:gap-2">
3
- <!-- existing tags -->
4
- <v-text-field
2
+ <div class="tw:grid" :class="listGapClasses" role="list">
3
+ <div
5
4
  v-for="(_, index) in modelValue"
6
- v-bind="$attrs"
7
- :key="index"
8
- :id="index === 0 ? inputId : undefined"
9
- v-model="modelValue[index]"
10
- variant="outlined"
11
- append-icon="mdi-minus"
12
- @click:append="() => modelValue.length > 1 && modelValue.splice(index, 1)"
13
- />
14
-
15
- <!-- add new entry -->
16
- <v-text-field
17
- :id="modelValue?.length === 0 ? inputId : undefined"
18
- v-bind="$attrs"
19
- v-model="virtualInput"
20
- variant="outlined"
21
- hide-details
22
- append-icon="mdi-plus"
23
- @click:append="addVirtualInput"
24
- @blur="addVirtualInput"
25
- />
5
+ :key="`row-${index}`"
6
+ class="tw:flex tw:min-w-0 tw:items-start tw:gap-2"
7
+ role="listitem"
8
+ >
9
+ <v-text-field
10
+ :model-value="modelValue[index]"
11
+ v-bind="passthroughAttrs(index)"
12
+ class="tw:min-w-0 tw:flex-1"
13
+ :id="fieldId(index)"
14
+ variant="outlined"
15
+ color="primary"
16
+ :density="effectiveDensity"
17
+ append-inner-icon="mdi-minus"
18
+ :aria-label="rowLabel(index)"
19
+ @click:append-inner="removeAt(index)"
20
+ @update:model-value="updateAt(index, String($event ?? ''))"
21
+ @blur="onFieldBlur"
22
+ />
23
+ </div>
24
+
25
+ <div role="listitem">
26
+ <v-text-field
27
+ v-model="virtualInput"
28
+ v-bind="passthroughAttrs(-1)"
29
+ class="tw:w-full"
30
+ :id="addFieldDomId"
31
+ variant="outlined"
32
+ color="primary"
33
+ :density="effectiveDensity"
34
+ hide-details
35
+ append-inner-icon="mdi-plus"
36
+ :aria-label="t('workbench.dynamicInputs.list.addNewLabel')"
37
+ @click:append-inner="addVirtualInput"
38
+ @blur="addAndBlur"
39
+ />
40
+ </div>
26
41
  </div>
27
42
  </template>
28
43
 
29
44
  <script setup lang="ts">
30
- import { ref } from "vue"
45
+ import { computed, ref, useAttrs } from "vue"
46
+ import { useI18n } from "vue-i18n"
31
47
 
32
48
  defineOptions({
33
49
  inheritAttrs: false,
34
50
  })
35
51
 
36
- defineProps<{
52
+ const props = defineProps<{
37
53
  inputId?: string
38
54
  }>()
39
55
 
40
- const modelValue = defineModel<string[]>({ required: true })
56
+ const emit = defineEmits<{
57
+ blur: []
58
+ }>()
59
+
60
+ const { t } = useI18n()
61
+ const attrs = useAttrs()
41
62
 
63
+ const modelValue = defineModel<string[]>({ required: true })
42
64
  const virtualInput = ref("")
43
65
 
66
+ const baseId = computed(() => props.inputId ?? "dynamic-list")
67
+
68
+ const densityToken = computed(
69
+ () => (attrs["density"] as string | undefined) ?? "comfortable",
70
+ )
71
+
72
+ const effectiveDensity = computed(() =>
73
+ densityToken.value === "spacious" ? "default" : densityToken.value,
74
+ )
75
+
76
+ const listGapClasses = computed(() => {
77
+ if (densityToken.value === "compact") return "tw:gap-2"
78
+ if (
79
+ densityToken.value === "spacious" ||
80
+ densityToken.value === "default"
81
+ ) {
82
+ return "tw:gap-3"
83
+ }
84
+ return "tw:gap-2 tw:md:gap-3"
85
+ })
86
+
87
+ const passthroughAttrs = (index: number) => {
88
+ const r = { ...(attrs as Record<string, unknown>) }
89
+ if (index > 0 || index === -1) {
90
+ delete r.errorMessages
91
+ delete r["error-messages"]
92
+ delete r.errorMessage
93
+ delete r["error-message"]
94
+ }
95
+ if (index === -1) {
96
+ r.hideDetails = true
97
+ }
98
+ return r
99
+ }
100
+
101
+ function fieldId(index: number): string {
102
+ if (index === 0 && props.inputId) return props.inputId
103
+ return `${baseId.value}-${index}`
104
+ }
105
+
106
+ const addFieldDomId = computed(() =>
107
+ modelValue.value.length === 0 && props.inputId
108
+ ? props.inputId
109
+ : `${baseId.value}-new`,
110
+ )
111
+
112
+ const rowLabel = (index: number) =>
113
+ t("workbench.dynamicInputs.list.rowLabel", { n: index + 1 })
114
+
115
+ const onFieldBlur = () => {
116
+ emit("blur")
117
+ }
118
+
119
+ const addAndBlur = () => {
120
+ addVirtualInput()
121
+ emit("blur")
122
+ }
123
+
124
+ const updateAt = (index: number, value: string) => {
125
+ const next = [...modelValue.value]
126
+ next[index] = value
127
+ modelValue.value = next
128
+ }
129
+
130
+ const removeAt = (index: number) => {
131
+ if (modelValue.value.length <= 1) return
132
+ modelValue.value = modelValue.value.filter((_, i) => i !== index)
133
+ }
134
+
44
135
  const addVirtualInput = () => {
45
136
  const val = virtualInput.value.trim()
46
137
  if (val !== "") {
47
- modelValue.value.push(val)
138
+ modelValue.value = [...modelValue.value, val]
48
139
  virtualInput.value = ""
49
140
  }
50
141
  }
@@ -1,49 +1,154 @@
1
1
  <template>
2
- <div class="tw:grid tw:gap-2">
2
+ <div
3
+ role="group"
4
+ class="tw:grid tw:gap-3"
5
+ v-bind="rootA11yAttrs"
6
+ >
7
+ <div
8
+ v-if="errorSummary"
9
+ role="alert"
10
+ class="tw:text-sm tw:leading-snug tw:text-[color:rgb(var(--v-theme-error))]"
11
+ >
12
+ {{ errorSummary }}
13
+ </div>
14
+
3
15
  <div
4
16
  v-for="(entry, index) in entries"
5
17
  :key="index"
6
- class="tw:grid tw:grid-cols-12 tw:gap-2"
18
+ class="tw:grid tw:grid-cols-1 tw:gap-2 sm:tw:grid-cols-12 sm:tw:items-center sm:tw:gap-2"
7
19
  >
8
20
  <v-text-field
9
21
  :model-value="entry.key"
22
+ v-bind="sharedFieldBindings"
10
23
  @update:model-value="entry.key = $event"
11
- @blur="emitEntries"
12
- label="Key"
13
- class="tw:col-span-5"
14
24
  hide-details
15
25
  variant="outlined"
26
+ color="primary"
27
+ :density="effectiveDensity"
28
+ class="tw:sm:col-span-5"
29
+ :aria-label="
30
+ t('workbench.dynamicInputs.record.keyLabel', { n: index + 1 })
31
+ "
32
+ @blur="emitEntriesAndBlur"
16
33
  />
17
34
 
18
35
  <v-text-field
19
36
  :model-value="entry.value"
37
+ v-bind="sharedFieldBindings"
20
38
  @update:model-value="entry.value = $event"
21
- @blur="emitEntries"
22
- label="Value"
23
- class="tw:col-span-6"
24
39
  hide-details
25
40
  variant="outlined"
41
+ color="primary"
42
+ :density="effectiveDensity"
43
+ class="tw:sm:col-span-6"
44
+ :aria-label="
45
+ t('workbench.dynamicInputs.record.valueLabel', { n: index + 1 })
46
+ "
47
+ @blur="emitEntriesAndBlur"
26
48
  />
49
+ <div class="tw:flex tw:justify-end sm:tw:col-span-1 sm:tw:justify-center">
50
+ <v-btn
51
+ icon="mdi-minus"
52
+ variant="text"
53
+ color="error"
54
+ size="small"
55
+ :density="effectiveDensity"
56
+ class="tw:shrink-0"
57
+ :aria-label="t('workbench.dynamicInputs.record.removeRow')"
58
+ type="button"
59
+ @click="remove(index)"
60
+ />
61
+ </div>
62
+ </div>
63
+
64
+ <div class="tw:flex tw:justify-end">
27
65
  <v-btn
28
- icon="mdi-minus"
29
- color="red"
30
- class="tw:col-span-1"
31
- @click="remove(index)"
66
+ icon="mdi-plus"
67
+ variant="tonal"
68
+ color="secondary"
69
+ size="small"
70
+ :density="effectiveDensity"
71
+ :disabled="hasEmptyKeyEntry"
72
+ type="button"
73
+ :aria-label="t('workbench.dynamicInputs.record.addRow')"
74
+ @click="add"
32
75
  />
33
76
  </div>
34
-
35
- <v-btn
36
- icon="mdi-plus"
37
- color="green"
38
- @click="add"
39
- :disabled="hasEmptyKeyEntry"
40
- />
41
77
  </div>
42
78
  </template>
43
79
 
44
80
  <script setup lang="ts">
45
- import { computed, ref, watch } from "vue"
81
+ import { computed, ref, useAttrs, watch } from "vue"
46
82
  import { equals } from "ramda"
83
+ import { useI18n } from "vue-i18n"
84
+
85
+ defineOptions({
86
+ inheritAttrs: false,
87
+ })
88
+
89
+ const { t } = useI18n()
90
+ const attrs = useAttrs()
91
+ const emit = defineEmits<{ blur: [] }>()
92
+
93
+ const densityToken = computed(
94
+ () => (attrs["density"] as string | undefined) ?? "comfortable",
95
+ )
96
+
97
+ const effectiveDensity = computed(() =>
98
+ densityToken.value === "spacious" ? "default" : densityToken.value,
99
+ )
100
+
101
+ const pickErrorMessages = (raw: Record<string, unknown>): string | undefined => {
102
+ const m =
103
+ raw["errorMessages"] ?? raw["error-messages"] ?? raw["errorMessage"]
104
+ if (m == null) return undefined
105
+ if (Array.isArray(m)) return m.filter(Boolean)[0]?.toString()
106
+ return String(m)
107
+ }
108
+
109
+ const errorSummary = computed(() => pickErrorMessages(attrs))
110
+
111
+ const omitKeys = (
112
+ raw: Record<string, unknown>,
113
+ keys: readonly string[],
114
+ ): Record<string, unknown> => {
115
+ const o = { ...raw }
116
+ for (const k of keys) delete o[k]
117
+ return o
118
+ }
119
+
120
+ const SHARED_OMIT: readonly string[] = [
121
+ "errorMessages",
122
+ "error-messages",
123
+ "errorMessage",
124
+ "hideDetails",
125
+ "hide-details",
126
+ "disabled",
127
+ ]
128
+
129
+ const ROOT_A11Y_KEYS: readonly string[] = [
130
+ "aria-describedby",
131
+ "aria-required",
132
+ "aria-invalid",
133
+ ]
134
+
135
+ const rootA11yAttrs = computed(() => {
136
+ const raw = attrs as Record<string, unknown>
137
+ const pick: Record<string, unknown> = {}
138
+ for (const k of ROOT_A11Y_KEYS) {
139
+ if (raw[k] !== undefined) pick[k] = raw[k]
140
+ }
141
+ return pick
142
+ })
143
+
144
+ const sharedFieldBindings = computed(() => ({
145
+ ...omitKeys(attrs as Record<string, unknown>, [
146
+ ...SHARED_OMIT,
147
+ ...ROOT_A11Y_KEYS,
148
+ ]),
149
+ disabled: attrs.disabled ?? false,
150
+ density: effectiveDensity.value,
151
+ }))
47
152
 
48
153
  const modelValue = defineModel<Record<string, string>>({ required: true })
49
154
 
@@ -64,15 +169,20 @@ const emitEntries = () => {
64
169
  modelValue.value = obj
65
170
  }
66
171
 
172
+ const emitEntriesAndBlur = () => {
173
+ emitEntries()
174
+ emit("blur")
175
+ }
176
+
67
177
  const add = () => {
68
178
  entries.value.push({ key: "", value: "" })
69
179
  }
70
180
 
71
181
  const remove = (index: number) => {
72
182
  entries.value.splice(index, 1)
183
+ emitEntriesAndBlur()
73
184
  }
74
185
 
75
- // synchronize local clone of the modelValue
76
186
  watch(
77
187
  () => modelValue.value,
78
188
  (newVal, oldVal) => {
@@ -10,6 +10,7 @@
10
10
  item-title="title"
11
11
  multiple
12
12
  variant="outlined"
13
+ color="primary"
13
14
  chips
14
15
  >
15
16
  <template #chip="{ internalItem }">
@@ -2,9 +2,9 @@
2
2
  <div class="tw:grid tw:gap-2">
3
3
  <!-- existing triggers -->
4
4
  <div
5
- class="tw:py-2 tw:border-solid tw:rounded"
6
5
  v-for="(trigger, index) in modelValue"
7
6
  :key="index"
7
+ class="tw:grid tw:gap-3 tw:rounded-md tw:pb-4"
8
8
  >
9
9
  <v-select
10
10
  v-model="trigger.type"
@@ -17,10 +17,9 @@
17
17
  @update:model-value="updateTriggerType($event, index)"
18
18
  @click:append="modelValue.splice(index, 1)"
19
19
  :label="$t('workbench.dynamicInputs.triggers.triggerTypeLabel')"
20
- :disabled="true"
21
20
  />
22
21
 
23
- <div class="tw:grid tw:gap-2 tw:p-2">
22
+ <div class="tw:grid tw:gap-2 tw:pl-4">
24
23
  <template
25
24
  v-if="
26
25
  ['app-bar', 'page-navigation', 'user-menu'].includes(trigger.type)
@@ -33,7 +32,8 @@
33
32
  v-bind="$attrs"
34
33
  :input-id="`title-${index}`"
35
34
  :title="$t('workbench.dynamicInputs.triggers.titleLabel')"
36
- />
35
+ hide-details
36
+ />
37
37
 
38
38
  <v-number-input
39
39
  v-model="trigger.settings.sortOrder"
@@ -0,0 +1,29 @@
1
+ import { useRouteState } from "@raclettejs/core/orchestrator/composables"
2
+
3
+ export const useWorkbenchTableActions = () => {
4
+ const routeState = useRouteState()
5
+
6
+ const goToCreate = (interactionLinkId: string) => {
7
+ routeState.triggerInteractionLinkById(interactionLinkId)
8
+ }
9
+
10
+ const goToEditById = (
11
+ interactionLinkId: string,
12
+ id: string | number | undefined | null,
13
+ ) => {
14
+ if (id === undefined || id === null) {
15
+ return
16
+ }
17
+ routeState.triggerInteractionLinkById(interactionLinkId, {
18
+ id: String(id),
19
+ })
20
+ }
21
+
22
+ return {
23
+ routeState,
24
+ goToCreate,
25
+ goToEditById,
26
+ }
27
+ }
28
+
29
+ export default useWorkbenchTableActions