poe-svelte-ui-lib 1.6.1 → 1.6.3

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.
@@ -1,15 +1,15 @@
1
1
  <script lang="ts">
2
- import { getContext } from 'svelte'
3
- import { t } from '../locales/i18n'
4
- import { type UIComponent, type ITableProps, type ITableHeader, updateProperty, type IUIComponentHandler } from '../types'
5
- import * as UI from '..'
6
- import ButtonDelete from '../libIcons/ButtonDelete.svelte'
7
- import ButtonAdd from '../libIcons/ButtonAdd.svelte'
8
- import { optionsStore } from '../options'
9
- import { twMerge } from 'tailwind-merge'
10
- import Modal from '../Modal.svelte'
11
- import { ICONS } from '../icons'
12
- import CrossIcon from '../libIcons/CrossIcon.svelte'
2
+ import { getContext } from "svelte"
3
+ import { t } from "../locales/i18n"
4
+ import { type UIComponent, type ITableProps, type ITableHeader, updateProperty, type IUIComponentHandler } from "../types"
5
+ import * as UI from ".."
6
+ import ButtonDelete from "../libIcons/ButtonDelete.svelte"
7
+ import ButtonAdd from "../libIcons/ButtonAdd.svelte"
8
+ import { optionsStore } from "../options"
9
+ import { twMerge } from "tailwind-merge"
10
+ import Modal from "../Modal.svelte"
11
+ import { ICONS } from "../icons"
12
+ import CrossIcon from "../libIcons/CrossIcon.svelte"
13
13
 
14
14
  const {
15
15
  component,
@@ -21,27 +21,27 @@
21
21
  forConstructor?: boolean
22
22
  }>()
23
23
 
24
- const DeviceVariables = getContext<{ id: string; value: string; name: string }[]>('DeviceVariables')
24
+ const DeviceVariables = getContext<{ id: string; value: string; name: string }[]>("DeviceVariables")
25
25
  let VARIABLE_OPTIONS = $derived(DeviceVariables && Array.isArray(DeviceVariables) ? DeviceVariables : [])
26
26
 
27
- let defaultIcon = $derived({ isModalOpen: false, columnIndex: 0, column: component.properties.header ? component.properties.header[0] : '' })
27
+ let defaultIcon = $derived({ isModalOpen: false, columnIndex: 0, column: component.properties.header ? component.properties.header[0] : "" })
28
28
 
29
29
  const initialColor = $derived(
30
- $optionsStore.COLOR_OPTIONS.find((c) =>
31
- (c.value as string).includes(component.properties.wrapperClass?.split(' ').find((cls: string) => cls.startsWith('bg-'))),
30
+ $optionsStore.COLOR_OPTIONS.find(c =>
31
+ (c.value as string).includes(component.properties.wrapperClass?.split(" ").find((cls: string) => cls.startsWith("bg-"))),
32
32
  ),
33
33
  )
34
34
 
35
35
  const initialAlign = $derived(
36
- $optionsStore.TEXT_ALIGN_OPTIONS.find((a) =>
37
- (a.value as string).includes(component.properties.label?.class?.split(' ').find((cls: string) => cls.startsWith('text-'))),
36
+ $optionsStore.TEXT_ALIGN_OPTIONS.find(a =>
37
+ (a.value as string).includes(component.properties.label?.class?.split(" ").find((cls: string) => cls.startsWith("text-"))),
38
38
  ),
39
39
  )
40
40
 
41
41
  const updateTableHeader = (index: number, field: string, value: any) => {
42
42
  const headers = [...component.properties.header]
43
43
  headers[index] = { ...headers[index], [field]: value }
44
- updateProperty('header', headers, component, onPropertyChange)
44
+ updateProperty("header", headers, component, onPropertyChange)
45
45
  }
46
46
 
47
47
  const updateTableBody = (typeChange?: boolean, loggerType?: boolean) => {
@@ -50,9 +50,9 @@
50
50
  if (typeChange) {
51
51
  newBody = []
52
52
  if (loggerType) {
53
- newBody.push({ loglevel: 'error', payload: 'error log' })
54
- newBody.push({ loglevel: 'warning', payload: 'warning log' })
55
- newBody.push({ loglevel: 'info', payload: 'info log' })
53
+ newBody.push({ loglevel: "error", payload: "error log" })
54
+ newBody.push({ loglevel: "warning", payload: "warning log" })
55
+ newBody.push({ loglevel: "info", payload: "info log" })
56
56
  } else {
57
57
  const newRow: { [key: string]: any } = {}
58
58
  component.properties.header.forEach((col: ITableHeader<any>) => {
@@ -72,15 +72,25 @@
72
72
  return newRow
73
73
  })
74
74
  }
75
- updateProperty('body', newBody, component, onPropertyChange)
75
+ updateProperty("body", newBody, component, onPropertyChange)
76
76
  }
77
77
 
78
78
  const updateButtonProperty = (columnIndex: number, buttonIndex: number, field: string, value: any) => {
79
79
  const headers = [...component.properties.header]
80
- const buttons = [...headers[columnIndex].buttons]
80
+ const buttons = [...headers[columnIndex].action.buttons]
81
+
81
82
  buttons[buttonIndex] = { ...buttons[buttonIndex], [field]: value }
82
- headers[columnIndex].buttons = buttons
83
- updateProperty('header', headers, component, onPropertyChange)
83
+ headers[columnIndex].action.buttons = buttons
84
+ updateProperty("header", headers, component, onPropertyChange)
85
+ }
86
+
87
+ const updateSelectProperty = (columnIndex: number, field: string, value: any) => {
88
+ const headers = [...component.properties.header]
89
+ let select = headers[columnIndex].action.select
90
+
91
+ select = { ...select, [field]: value }
92
+ headers[columnIndex].action.select = select
93
+ updateProperty("header", headers, component, onPropertyChange)
84
94
  }
85
95
 
86
96
  const removeButtonFromColumn = (columnIndex: number, buttonIndex: number) => {
@@ -88,7 +98,7 @@
88
98
  const buttons = [...headers[columnIndex].buttons]
89
99
  buttons.splice(buttonIndex, 1)
90
100
  headers[columnIndex].buttons = buttons.length ? buttons : undefined
91
- updateProperty('header', headers, component, onPropertyChange)
101
+ updateProperty("header", headers, component, onPropertyChange)
92
102
  }
93
103
  </script>
94
104
 
@@ -96,273 +106,299 @@
96
106
  <div class="relative flex flex-row items-start justify-center pb-4">
97
107
  <div class="flex w-1/3 flex-col px-2">
98
108
  <UI.Select
99
- label={{ name: $t('constructor.props.variable') }}
109
+ label={{ name: $t("constructor.props.variable") }}
100
110
  options={VARIABLE_OPTIONS}
101
- value={VARIABLE_OPTIONS.find((opt) => opt.value === component.properties.id)}
102
- onUpdate={(value) => {
103
- updateProperty('id', value.value as string, component, onPropertyChange)
104
- onPropertyChange({ name: value.name?.split('')[1].trim(), eventHandler: { Variables: [value.value as string] } })
105
- }}
106
- />
111
+ value={VARIABLE_OPTIONS.find(opt => opt.value === component.properties.id)}
112
+ onUpdate={value => {
113
+ updateProperty("id", value.value as string, component, onPropertyChange)
114
+ onPropertyChange({ name: value.name?.split("")[1].trim(), eventHandler: { Variables: [value.value as string] } })
115
+ }} />
107
116
  <UI.Select
108
- label={{ name: $t('constructor.props.access') }}
117
+ label={{ name: $t("constructor.props.access") }}
109
118
  type="buttons"
110
119
  options={$optionsStore.ACCESS_OPTION}
111
- value={$optionsStore.ACCESS_OPTION.find((o) => o.value === component.access)}
112
- onUpdate={(option) => onPropertyChange({ access: option.value })}
113
- />
120
+ value={$optionsStore.ACCESS_OPTION.find(o => o.value === component.access)}
121
+ onUpdate={option => onPropertyChange({ access: option.value })} />
114
122
  <UI.Select
115
- label={{ name: $t('constructor.props.table.type') }}
123
+ label={{ name: $t("constructor.props.table.type") }}
116
124
  type="buttons"
117
125
  options={$optionsStore.TABLE_TYPE_OPTIONS}
118
- value={$optionsStore.TABLE_TYPE_OPTIONS.find((o) => o.value === component.properties.type)}
119
- onUpdate={(option) => {
120
- if (option.value === 'logger') {
121
- updateProperty('dataBuffer.stashData', true, component, onPropertyChange)
122
- updateProperty('dataBuffer.clearButton', true, component, onPropertyChange)
126
+ value={$optionsStore.TABLE_TYPE_OPTIONS.find(o => o.value === component.properties.type)}
127
+ onUpdate={option => {
128
+ if (option.value === "logger") {
129
+ updateProperty("dataBuffer.stashData", true, component, onPropertyChange)
130
+ updateProperty("dataBuffer.clearButton", true, component, onPropertyChange)
123
131
 
124
132
  const headers = [
125
133
  {
126
- key: 'color',
127
- label: { name: 'Type' },
128
- width: '3rem',
134
+ key: "color",
135
+ label: { name: "Type" },
136
+ width: "3rem",
129
137
  } as ITableHeader<any>,
130
138
  {
131
- key: 'data',
132
- label: { name: 'Data' },
133
- width: 'calc(100% - 3rem)',
139
+ key: "data",
140
+ label: { name: "Data" },
141
+ width: "calc(100% - 3rem)",
134
142
  } as ITableHeader<any>,
135
143
  ]
136
- updateProperty('header', headers, component, onPropertyChange)
144
+ updateProperty("header", headers, component, onPropertyChange)
137
145
  updateTableBody(true, true)
138
146
  } else {
139
- updateProperty('dataBuffer.stashData', false, component, onPropertyChange)
140
- updateProperty('dataBuffer.clearButton', false, component, onPropertyChange)
147
+ updateProperty("dataBuffer.stashData", false, component, onPropertyChange)
148
+ updateProperty("dataBuffer.clearButton", false, component, onPropertyChange)
141
149
  const headers = [
142
150
  {
143
- key: 'id',
144
- label: { name: 'ID' },
145
- width: '40%',
151
+ key: "id",
152
+ label: { name: "ID" },
153
+ width: "40%",
146
154
  sortable: true,
147
155
  image: {
148
- width: '0rem',
149
- height: '0rem',
156
+ width: "0rem",
157
+ height: "0rem",
150
158
  },
151
- align: 'left',
159
+ align: "left",
152
160
  } as ITableHeader<any>,
153
161
  {
154
- key: 'device',
155
- label: { name: 'Device' },
156
- width: '60%',
162
+ key: "device",
163
+ label: { name: "Device" },
164
+ width: "60%",
157
165
  sortable: false,
158
166
  image: {
159
- width: '0rem',
160
- height: '0rem',
167
+ width: "0rem",
168
+ height: "0rem",
161
169
  },
162
- align: 'left',
170
+ align: "left",
163
171
  overflow: {
164
172
  truncated: true,
165
173
  },
166
174
  } as ITableHeader<any>,
167
175
  ]
168
- updateProperty('header', headers, component, onPropertyChange)
176
+ updateProperty("header", headers, component, onPropertyChange)
169
177
  updateTableBody(true, false)
170
178
  }
171
- updateProperty('type', option.value as string, component, onPropertyChange)
172
- }}
173
- />
179
+ updateProperty("type", option.value as string, component, onPropertyChange)
180
+ }} />
174
181
  </div>
175
182
  <div class="flex w-1/3 flex-col px-2">
176
183
  <UI.Select
177
184
  wrapperClass="!h-14"
178
- label={{ name: $t('constructor.props.colors') }}
185
+ label={{ name: $t("constructor.props.colors") }}
179
186
  type="buttons"
180
187
  options={$optionsStore.COLOR_OPTIONS}
181
188
  value={initialColor}
182
- onUpdate={(option) => updateProperty('wrapperClass', twMerge(component.properties.wrapperClass, option.value), component, onPropertyChange)}
183
- />
189
+ onUpdate={option => updateProperty("wrapperClass", twMerge(component.properties.wrapperClass, option.value), component, onPropertyChange)} />
184
190
  <UI.Switch
185
- label={{ name: $t('constructor.props.outline') }}
191
+ label={{ name: $t("constructor.props.outline") }}
186
192
  value={component.properties.outline}
187
- options={[{ id: crypto.randomUUID(), value: 0, class: '' }]}
188
- onChange={(value) => updateProperty('outline', value, component, onPropertyChange)}
189
- />
193
+ options={[{ id: crypto.randomUUID(), value: 0, class: "" }]}
194
+ onChange={value => updateProperty("outline", value, component, onPropertyChange)} />
190
195
  </div>
191
196
  <div class="flex w-1/3 flex-col px-2">
192
197
  <UI.Input
193
- label={{ name: $t('constructor.props.label') }}
198
+ label={{ name: $t("constructor.props.label") }}
194
199
  value={component.properties.label.name}
195
- onUpdate={(value) => updateProperty('label.name', value as string, component, onPropertyChange)}
196
- />
200
+ onUpdate={value => updateProperty("label.name", value as string, component, onPropertyChange)} />
197
201
  <UI.Select
198
- label={{ name: $t('constructor.props.align') }}
202
+ label={{ name: $t("constructor.props.align") }}
199
203
  type="buttons"
200
204
  value={initialAlign}
201
205
  options={$optionsStore.TEXT_ALIGN_OPTIONS}
202
- onUpdate={(option) => updateProperty('label.class', twMerge(component.properties.label.class, option.value), component, onPropertyChange)}
203
- />
206
+ onUpdate={option => updateProperty("label.class", twMerge(component.properties.label.class, option.value), component, onPropertyChange)} />
204
207
  {#if component.properties.dataBuffer.stashData}
205
208
  <UI.Select
206
- label={{ name: $t('constructor.props.table.buffersize') }}
209
+ label={{ name: $t("constructor.props.table.buffersize") }}
207
210
  type="buttons"
208
211
  options={$optionsStore.BUFFER_SIFE_OPTIONS}
209
- value={$optionsStore.BUFFER_SIFE_OPTIONS.find((o) => o.value === component.properties.dataBuffer.rowsAmmount)}
210
- onUpdate={(value) => updateProperty('dataBuffer.rowsAmmount', value.value as number, component, onPropertyChange)}
211
- />
212
+ value={$optionsStore.BUFFER_SIFE_OPTIONS.find(o => o.value === component.properties.dataBuffer.rowsAmmount)}
213
+ onUpdate={value => updateProperty("dataBuffer.rowsAmmount", value.value as number, component, onPropertyChange)} />
212
214
  {/if}
213
215
  </div>
214
216
  </div>
215
- {#if component.properties.type === 'table'}
217
+ {#if component.properties.type === "table"}
216
218
  <hr class="border-(--border-color)" />
217
219
 
218
220
  <!-- Настройки столбцов таблицы -->
219
221
  <div>
220
222
  <div class=" flex items-center justify-center gap-2">
221
- <h4>{$t('constructor.props.table.columns')}</h4>
223
+ <h4>{$t("constructor.props.table.columns")}</h4>
222
224
  <UI.Button
223
225
  wrapperClass="w-8"
224
226
  content={{ icon: ButtonAdd }}
225
227
  onClick={() => {
226
228
  const newColumn: ITableHeader<any> = {
227
229
  key: `column${(component.properties.header?.length || 0) + 1}`,
228
- label: { name: `Column ${(component.properties.header?.length || 0) + 1}`, class: '' },
229
- width: '10%',
230
+ label: { name: `Column ${(component.properties.header?.length || 0) + 1}`, class: "" },
231
+ width: "10%",
230
232
  sortable: false,
231
233
  }
232
234
  const headers = [...(component.properties.header || []), newColumn]
233
- updateProperty('header', headers, component, onPropertyChange)
234
- headers.forEach((h) => {
235
- updateTableHeader(headers.indexOf(h), 'width', `${(100 / headers.length).toFixed(2)}%`)
235
+ updateProperty("header", headers, component, onPropertyChange)
236
+ headers.forEach(h => {
237
+ updateTableHeader(headers.indexOf(h), "width", `${(100 / headers.length).toFixed(2)}%`)
236
238
  })
237
239
  updateTableBody()
238
- }}
239
- />
240
+ }} />
240
241
  </div>
241
242
 
242
243
  {#each component.properties.header as column, columnIndex (columnIndex)}
243
244
  <div class="mr-2 grid grid-cols-[minmax(5rem,10rem)_1fr_minmax(5rem,10rem)_minmax(10rem,21rem)_6rem_6rem_2rem_2rem] items-end gap-6">
244
245
  <UI.Input
245
- label={{ name: $t('constructor.props.table.columns.key') }}
246
+ label={{ name: $t("constructor.props.table.columns.key") }}
246
247
  value={column.key}
247
248
  help={{ regExp: /^[0-9a-zA-Z_-]{0,16}$/ }}
248
- onUpdate={(value) => {
249
- updateTableHeader(columnIndex, 'key', value)
249
+ onUpdate={value => {
250
+ updateTableHeader(columnIndex, "key", value)
250
251
  updateTableBody()
251
- }}
252
- />
252
+ }} />
253
253
  <UI.Input
254
- label={{ name: $t('constructor.props.table.columns.label') }}
254
+ label={{ name: $t("constructor.props.table.columns.label") }}
255
255
  value={column.label.name}
256
- onUpdate={(value) => {
257
- updateTableHeader(columnIndex, 'label', { ['name']: value })
258
- }}
259
- />
256
+ onUpdate={value => {
257
+ updateTableHeader(columnIndex, "label", { ["name"]: value })
258
+ }} />
260
259
  <UI.Input
261
- label={{ name: $t('constructor.props.table.columns.width') }}
260
+ label={{ name: $t("constructor.props.table.columns.width") }}
262
261
  type="number"
263
- value={Number(column.width.replace('%', ''))}
264
- onUpdate={(value) => updateTableHeader(columnIndex, 'width', `${value}%`)}
265
- />
262
+ value={Number(column.width.replace("%", ""))}
263
+ onUpdate={value => updateTableHeader(columnIndex, "width", `${value}%`)} />
266
264
  <UI.Select
267
- label={{ name: $t('constructor.props.align.content') }}
265
+ label={{ name: $t("constructor.props.align.content") }}
268
266
  type="buttons"
269
- value={$optionsStore.ALIGN_OPTIONS.find((a) => (a.value as string).includes(column.align))}
267
+ value={$optionsStore.ALIGN_OPTIONS.find(a => (a.value as string).includes(column.align))}
270
268
  options={$optionsStore.ALIGN_OPTIONS}
271
- onUpdate={(option) => updateTableHeader(columnIndex, 'align', option.value)}
272
- />
269
+ onUpdate={option => updateTableHeader(columnIndex, "align", option.value)} />
273
270
  <UI.Switch
274
- label={{ name: $t('constructor.props.table.columns.sortable'), class: 'px-0' }}
275
- options={[{ id: crypto.randomUUID(), value: 0, class: '' }]}
271
+ label={{ name: $t("constructor.props.table.columns.sortable"), class: "px-0" }}
272
+ options={[{ id: crypto.randomUUID(), value: 0, class: "" }]}
276
273
  value={column.sortable}
277
- onChange={(value) => updateTableHeader(columnIndex, 'sortable', value)}
278
- />
274
+ onChange={value => updateTableHeader(columnIndex, "sortable", value)} />
279
275
  <UI.Switch
280
- label={{ name: $t('constructor.props.copy'), class: 'px-0' }}
281
- options={[{ id: crypto.randomUUID(), value: 0, class: '' }]}
276
+ label={{ name: $t("constructor.props.copy"), class: "px-0" }}
277
+ options={[{ id: crypto.randomUUID(), value: 0, class: "" }]}
282
278
  value={column.overflow?.copy}
283
- onChange={(value) => updateTableHeader(columnIndex, 'overflow', { copy: value })}
284
- />
279
+ onChange={value => updateTableHeader(columnIndex, "overflow", { copy: value })} />
285
280
  <UI.Button
286
- wrapperClass="w-8"
287
- content={{ icon: ButtonAdd, info: { text: $t('constructor.props.table.addaction'), side: 'top' } }}
281
+ wrapperClass="w-8 {column.action && column.action.type != 'none' ? 'invisible' : ''}"
282
+ content={{ icon: ButtonAdd, info: { text: $t("constructor.props.table.addaction"), side: "top" } }}
288
283
  onClick={() => {
289
- const newButton = {
290
- name: `button${(component.properties.header[columnIndex].buttons ? component.properties.header[columnIndex].buttons.length : 0) + 1}`,
291
- class: 'bg-blue',
292
- eventHandler: { Header: 'SET', Argument: 'Save', Variables: [] },
293
- onClick: () => {},
284
+ column.action = { type: "buttons", select: { key: "" } }
285
+ if (!(column.action && column.action.buttons)) {
294
286
  }
295
- const buttons = [...(component.properties.header[columnIndex].buttons || []), newButton]
296
- updateTableHeader(columnIndex, 'buttons', buttons)
297
- }}
298
- />
287
+ }} />
299
288
  <UI.Button
300
289
  wrapperClass="w-8"
301
290
  content={{ icon: ButtonDelete }}
302
291
  onClick={() => {
303
292
  const headers = [...(component.properties.header || [])]
304
293
  headers.splice(columnIndex, 1)
305
- updateProperty('header', headers, component, onPropertyChange)
306
- headers.forEach((h) => {
307
- updateTableHeader(headers.indexOf(h), 'width', `${(100 / headers.length).toFixed(2)}%`)
294
+ updateProperty("header", headers, component, onPropertyChange)
295
+ headers.forEach(h => {
296
+ updateTableHeader(headers.indexOf(h), "width", `${(100 / headers.length).toFixed(2)}%`)
308
297
  })
309
- }}
310
- />
298
+ }} />
311
299
  </div>
312
- {#if column.buttons && column.buttons.length > 0}
313
- <div class="mb-5 rounded-lg py-1">
314
- {#each column.buttons as button, buttonIndex (buttonIndex)}
315
- <div class="ml-14 flex items-end justify-around gap-2">
316
- <UI.Input
317
- label={{ name: $t('constructor.props.name') }}
318
- wrapperClass="!w-3/10"
319
- value={button.name}
320
- onUpdate={(value) => updateButtonProperty(columnIndex, buttonIndex, 'name', value)}
321
- />
300
+ {#if column.action && column.action.type != "none"}
301
+ <hr class="border-(--border-color) py-2" />
302
+ <div class="relative flex w-full justify-center">
303
+ <UI.Select
304
+ type="buttons"
305
+ wrapperClass="w-[50%]"
306
+ options={$optionsStore.ACTION_TYPE_OPTIONS}
307
+ value={$optionsStore.ACTION_TYPE_OPTIONS.find(h => h.value === column.action?.type) || $optionsStore.ACTION_TYPE_OPTIONS[0]}
308
+ onUpdate={value => {
309
+ column.action.type = value.value
310
+ }} />
311
+
312
+ <UI.Button
313
+ wrapperClass="w-8 {column.action.type == 'select' ? 'invisible' : ''}"
314
+ content={{ icon: ButtonAdd, info: { text: $t("constructor.props.table.addbutton"), side: "top" } }}
315
+ onClick={() => {
316
+ const newButton = {
317
+ name: `button${(component.properties.header[columnIndex].action.buttons ? component.properties.header[columnIndex].action.buttons.length : 0) + 1}`,
318
+ class: "bg-blue",
319
+ eventHandler: { Header: "SET", Argument: "Save", Variables: [] },
320
+ onClick: () => {},
321
+ }
322
+ let action = { ...component.properties.header[columnIndex].action }
323
+
324
+ if (!action) {
325
+ action = { type: "buttons", buttons: [newButton], select: { key: "", onChange: () => {} } }
326
+ } else if (action.type === "buttons") {
327
+ const buttons = [...(action.buttons || []), newButton]
328
+ action = { ...action, buttons }
329
+ } else {
330
+ action = { type: "buttons", buttons: [newButton], select: action.select }
331
+ }
332
+
333
+ updateTableHeader(columnIndex, "action", action)
334
+ }} />
335
+
336
+ <UI.Button
337
+ wrapperClass="w-8 absolute right-0"
338
+ content={{ icon: CrossIcon }}
339
+ onClick={() => {
340
+ column.action.type = "none"
341
+ }} />
342
+ </div>
343
+
344
+ <div class="mb-5 rounded-lg p-1">
345
+ {#if column.action.type == "buttons"}
346
+ {#each column.action.buttons as button, buttonIndex (buttonIndex)}
347
+ <div class="ml-14 flex items-end justify-between gap-2">
348
+ <UI.Input
349
+ label={{ name: $t("constructor.props.name") }}
350
+ wrapperClass="!w-3/10"
351
+ value={button.name}
352
+ onUpdate={value => updateButtonProperty(columnIndex, buttonIndex, "name", value)} />
353
+ <UI.Select
354
+ wrapperClass="!w-2/10"
355
+ label={{ name: $t("constructor.props.header") }}
356
+ type="buttons"
357
+ value={$optionsStore.HEADER_OPTIONS.find(h => h.value === button.eventHandler?.Header)}
358
+ options={$optionsStore.HEADER_OPTIONS}
359
+ onUpdate={option => {
360
+ const handler = button.eventHandler
361
+ handler.Header = option.value as string
362
+ updateButtonProperty(columnIndex, buttonIndex, "eventHandler", handler)
363
+ }} />
364
+ <UI.Input
365
+ wrapperClass="!w-2/10"
366
+ label={{ name: $t("constructor.props.argument") }}
367
+ value={button.eventHandler?.Argument}
368
+ onUpdate={value => {
369
+ const handler = button.eventHandler
370
+ handler.Argument = value as string
371
+ updateButtonProperty(columnIndex, buttonIndex, "eventHandler", handler)
372
+ }} />
373
+ <UI.Input
374
+ wrapperClass="!w-2/10"
375
+ label={{ name: $t("constructor.props.table.keys") }}
376
+ value={button.eventHandler?.Variables.join(" ")}
377
+ maxlength={500}
378
+ help={{ info: $t("constructor.props.table.keys.info"), regExp: /^[a-zA-Z0-9\-_ ]{0,500}$/ }}
379
+ onUpdate={value => {
380
+ const handler = { ...button.eventHandler }
381
+ handler.Variables = (value as string).trim().split(/\s+/)
382
+ updateButtonProperty(columnIndex, buttonIndex, "eventHandler", handler)
383
+ }} />
384
+ <UI.Button wrapperClass="w-8" content={{ icon: ButtonDelete }} onClick={() => removeButtonFromColumn(columnIndex, buttonIndex)} />
385
+ </div>
386
+ {/each}
387
+ {:else if column.action.type == "select"}
388
+ <div class="ml-14 flex items-end justify-between gap-2">
322
389
  <UI.Select
323
- wrapperClass="!w-2/10"
324
- label={{ name: $t('constructor.props.header') }}
325
- type="buttons"
326
- value={$optionsStore.HEADER_OPTIONS.find((h) => h.value === button.eventHandler?.Header)}
327
- options={$optionsStore.HEADER_OPTIONS}
328
- onUpdate={(option) => {
329
- const handler = button.eventHandler
330
- handler.Header = option.value as string
331
- updateButtonProperty(columnIndex, buttonIndex, 'eventHandler', handler)
332
- }}
333
- />
334
- <UI.Input
335
- wrapperClass="!w-2/10"
336
- label={{ name: $t('constructor.props.argument') }}
337
- value={button.eventHandler?.Argument}
338
- onUpdate={(value) => {
339
- const handler = button.eventHandler
340
- handler.Argument = value as string
341
- updateButtonProperty(columnIndex, buttonIndex, 'eventHandler', handler)
342
- }}
343
- />
344
- <UI.Input
345
- wrapperClass="!w-2/10"
346
- label={{ name: $t('constructor.props.table.keys') }}
347
- value={button.eventHandler?.Variables.join(' ')}
348
- maxlength={500}
349
- help={{ info: $t('constructor.props.table.keys.info'), regExp: /^[a-zA-Z0-9\-_ ]{0,500}$/ }}
350
- onUpdate={(value) => {
351
- const handler = { ...button.eventHandler }
352
- handler.Variables = (value as string).trim().split(/\s+/)
353
- updateButtonProperty(columnIndex, buttonIndex, 'eventHandler', handler)
354
- }}
355
- />
356
- <UI.Button
357
- wrapperClass="w-8"
358
- content={{ icon: ButtonDelete }}
359
- onClick={() => {
360
- removeButtonFromColumn(columnIndex, buttonIndex)
361
- }}
362
- />
390
+ label={{ name: $t("constructor.props.variable") }}
391
+ options={VARIABLE_OPTIONS}
392
+ value={VARIABLE_OPTIONS.find(opt => opt.value === column.action.select.key)}
393
+ onUpdate={value => {
394
+ updateSelectProperty(columnIndex, "key", value.value as string)
395
+ onPropertyChange({ name: value.name?.split("—")[1].trim(), eventHandler: { Variables: [value.value as string] } })
396
+ }} />
363
397
  </div>
364
- {/each}
398
+ {/if}
365
399
  </div>
400
+
401
+ <hr class="border-(--border-color) py-2" />
366
402
  {/if}
367
403
  {/each}
368
404
  </div>
@@ -371,150 +407,126 @@
371
407
  <div class="relative flex flex-row items-start justify-center pb-4">
372
408
  <div class="flex w-1/3 flex-col px-2">
373
409
  <UI.Input
374
- label={{ name: $t('constructor.props.id') }}
410
+ label={{ name: $t("constructor.props.id") }}
375
411
  value={component.properties.id}
376
- onUpdate={(value) => updateProperty('id', value as string, component, onPropertyChange)}
377
- />
412
+ onUpdate={value => updateProperty("id", value as string, component, onPropertyChange)} />
378
413
 
379
414
  <UI.Input
380
- label={{ name: $t('constructor.props.wrapperclass') }}
415
+ label={{ name: $t("constructor.props.wrapperclass") }}
381
416
  value={component.properties.wrapperClass}
382
- onUpdate={(value) => updateProperty('wrapperClass', value as string, component, onPropertyChange)}
383
- />
417
+ onUpdate={value => updateProperty("wrapperClass", value as string, component, onPropertyChange)} />
384
418
  <UI.Select
385
419
  wrapperClass=" h-14"
386
- label={{ name: $t('constructor.props.colors') }}
420
+ label={{ name: $t("constructor.props.colors") }}
387
421
  type="buttons"
388
422
  options={$optionsStore.COLOR_OPTIONS}
389
423
  value={initialColor}
390
- onUpdate={(option) => {
391
- updateProperty('wrapperClass', twMerge(component.properties.wrapperClass, option.value), component, onPropertyChange)
424
+ onUpdate={option => {
425
+ updateProperty("wrapperClass", twMerge(component.properties.wrapperClass, option.value), component, onPropertyChange)
392
426
  const options = [...(component.properties?.options || [])]
393
- options.forEach((o) => {
394
- o['class'] = option.value
427
+ options.forEach(o => {
428
+ o["class"] = option.value
395
429
  })
396
- updateProperty('options', options, component, onPropertyChange)
397
- }}
398
- />
430
+ updateProperty("options", options, component, onPropertyChange)
431
+ }} />
399
432
  <UI.Switch
400
- label={{ name: $t('constructor.props.outline') }}
433
+ label={{ name: $t("constructor.props.outline") }}
401
434
  value={component.properties.outline}
402
- options={[{ id: crypto.randomUUID(), value: 0, class: '' }]}
403
- onChange={(value) => updateProperty('outline', value, component, onPropertyChange)}
404
- />
435
+ options={[{ id: crypto.randomUUID(), value: 0, class: "" }]}
436
+ onChange={value => updateProperty("outline", value, component, onPropertyChange)} />
405
437
  </div>
438
+
406
439
  <div class="flex w-1/3 flex-col px-2">
407
440
  <UI.Select
408
- label={{ name: $t('constructor.props.access') }}
441
+ label={{ name: $t("constructor.props.access") }}
409
442
  type="buttons"
410
443
  options={$optionsStore.ACCESS_OPTION}
411
- value={$optionsStore.ACCESS_OPTION.find((o) => o.value === component.access)}
412
- onUpdate={(option) => onPropertyChange({ access: option.value })}
413
- />
444
+ value={$optionsStore.ACCESS_OPTION.find(o => o.value === component.access)}
445
+ onUpdate={option => onPropertyChange({ access: option.value })} />
414
446
  <UI.Input
415
- label={{ name: $t('constructor.props.label') }}
447
+ label={{ name: $t("constructor.props.label") }}
416
448
  value={component.properties.label.name}
417
- onUpdate={(value) => updateProperty('label.name', value as string, component, onPropertyChange)}
418
- />
449
+ onUpdate={value => updateProperty("label.name", value as string, component, onPropertyChange)} />
419
450
  <UI.Input
420
- label={{ name: $t('constructor.props.label.class') }}
451
+ label={{ name: $t("constructor.props.label.class") }}
421
452
  value={component.properties.label.class}
422
- onUpdate={(value) => updateProperty('label.class', value as string, component, onPropertyChange)}
423
- />
453
+ onUpdate={value => updateProperty("label.class", value as string, component, onPropertyChange)} />
424
454
  <UI.Input
425
- label={{ name: $t('constructor.props.footer') }}
455
+ label={{ name: $t("constructor.props.footer") }}
426
456
  value={component.properties.footer}
427
- onUpdate={(value) => updateProperty('footer', value as string, component, onPropertyChange)}
428
- />
457
+ onUpdate={value => updateProperty("footer", value as string, component, onPropertyChange)} />
429
458
  </div>
430
459
 
431
460
  <div class="flex w-1/3 flex-col px-2">
432
461
  <UI.Select
433
- label={{ name: $t('constructor.props.table.type') }}
462
+ label={{ name: $t("constructor.props.table.type") }}
434
463
  type="buttons"
435
464
  options={$optionsStore.TABLE_TYPE_OPTIONS}
436
- value={$optionsStore.TABLE_TYPE_OPTIONS.find((o) => o.value === component.properties.type)}
437
- onUpdate={(option) => {
438
- updateProperty('type', option.value as string, component, onPropertyChange)
439
- if (option.value === 'logger') {
440
- updateProperty('dataBuffer.stashData', true, component, onPropertyChange)
441
- updateProperty('dataBuffer.clearButton', true, component, onPropertyChange)
442
-
443
- const headers = [
444
- {
445
- key: 'color',
446
- label: { name: 'Type' },
447
- width: '3rem',
448
- } as ITableHeader<any>,
449
- {
450
- key: 'data',
451
- label: { name: 'Data' },
452
- width: 'calc(100% - 3rem)',
453
- } as ITableHeader<any>,
454
- ]
455
- updateProperty('header', headers, component, onPropertyChange)
465
+ value={$optionsStore.TABLE_TYPE_OPTIONS.find(o => o.value === component.properties.type)}
466
+ onUpdate={option => {
467
+ updateProperty("type", option.value as string, component, onPropertyChange)
468
+ if (option.value === "logger") {
469
+ updateProperty("dataBuffer.stashData", true, component, onPropertyChange)
470
+ updateProperty("dataBuffer.clearButton", true, component, onPropertyChange)
456
471
  } else {
457
- updateProperty('dataBuffer.clearButton', false, component, onPropertyChange)
472
+ updateProperty("dataBuffer.stashData", false, component, onPropertyChange)
473
+ updateProperty("dataBuffer.clearButton", false, component, onPropertyChange)
458
474
  const headers = [
459
475
  {
460
- key: 'id',
461
- label: { name: 'ID' },
462
- width: '40%',
476
+ key: "id",
477
+ label: { name: "ID" },
478
+ width: "40%",
463
479
  sortable: true,
464
480
  image: {
465
- width: '0rem',
466
- height: '0rem',
481
+ width: "0rem",
482
+ height: "0rem",
467
483
  },
468
- align: 'left',
484
+ align: "left",
469
485
  } as ITableHeader<any>,
470
486
  {
471
- key: 'device',
472
- label: { name: 'Device' },
473
- width: '60%',
487
+ key: "device",
488
+ label: { name: "Device" },
489
+ width: "60%",
474
490
  sortable: false,
475
491
  image: {
476
- width: '0rem',
477
- height: '0rem',
492
+ width: "0rem",
493
+ height: "0rem",
478
494
  },
479
- align: 'left',
495
+ align: "left",
480
496
  overflow: {
481
497
  truncated: true,
482
498
  },
483
499
  } as ITableHeader<any>,
484
500
  ]
485
- updateProperty('header', headers, component, onPropertyChange)
501
+ updateProperty("header", headers, component, onPropertyChange)
486
502
  }
487
- }}
488
- />
503
+ }} />
489
504
  <div class="flex">
490
505
  <UI.Switch
491
- label={{ name: $t('constructor.props.table.stashData') }}
506
+ label={{ name: $t("constructor.props.table.stashData") }}
492
507
  value={component.properties.dataBuffer.stashData}
493
- options={[{ id: crypto.randomUUID(), value: 0, class: '', disabled: component.properties.type === 'logger' }]}
494
- onChange={(value) => {
495
- updateProperty('dataBuffer.stashData', value, component, onPropertyChange)
496
- }}
497
- />
498
- {#if component.properties.type === 'logger'}
508
+ options={[{ id: crypto.randomUUID(), value: 0, class: "", disabled: component.properties.type === "logger" }]}
509
+ onChange={value => {
510
+ updateProperty("dataBuffer.stashData", value, component, onPropertyChange)
511
+ }} />
512
+ {#if component.properties.type === "logger"}
499
513
  <UI.Switch
500
- label={{ name: $t('constructor.props.table.clearButton') }}
514
+ label={{ name: $t("constructor.props.table.clearButton") }}
501
515
  value={component.properties.dataBuffer.clearButton}
502
- options={[{ id: crypto.randomUUID(), value: 0, class: '' }]}
503
- onChange={(value) => {
504
- updateProperty('dataBuffer.clearButton', value, component, onPropertyChange)
505
- }}
506
- />
516
+ options={[{ id: crypto.randomUUID(), value: 0, class: "" }]}
517
+ onChange={value => {
518
+ updateProperty("dataBuffer.clearButton", value, component, onPropertyChange)
519
+ }} />
507
520
  {/if}
508
521
  </div>
509
522
 
510
523
  {#if component.properties.dataBuffer.stashData}
511
524
  <UI.Select
512
- label={{ name: $t('constructor.props.table.buffersize') }}
525
+ label={{ name: $t("constructor.props.table.buffersize") }}
513
526
  type="buttons"
514
527
  options={$optionsStore.BUFFER_SIFE_OPTIONS}
515
- value={$optionsStore.BUFFER_SIFE_OPTIONS.find((o) => o.value === component.properties.dataBuffer.rowsAmmount)}
516
- onUpdate={(value) => updateProperty('dataBuffer.rowsAmmount', value.value as number, component, onPropertyChange)}
517
- />
528
+ value={$optionsStore.BUFFER_SIFE_OPTIONS.find(o => o.value === component.properties.dataBuffer.rowsAmmount)}
529
+ onUpdate={value => updateProperty("dataBuffer.rowsAmmount", value.value as number, component, onPropertyChange)} />
518
530
  {/if}
519
531
  </div>
520
532
  </div>
@@ -524,26 +536,25 @@
524
536
  <!-- Настройки столбцов таблицы -->
525
537
  <div>
526
538
  <div class=" flex items-center justify-center gap-2">
527
- <h4>{$t('constructor.props.table.columns')}</h4>
539
+ <h4>{$t("constructor.props.table.columns")}</h4>
528
540
  <UI.Button
529
541
  wrapperClass="w-8"
530
542
  content={{ icon: ButtonAdd }}
531
543
  onClick={() => {
532
544
  const newColumn: ITableHeader<any> = {
533
545
  key: `column${(component.properties.header?.length || 0) + 1}`,
534
- label: { name: `Column ${(component.properties.header?.length || 0) + 1}`, class: '' },
535
- width: '10%',
546
+ label: { name: `Column ${(component.properties.header?.length || 0) + 1}`, class: "" },
547
+ width: "10%",
536
548
  sortable: false,
537
- image: { width: '0rem', height: '0rem' },
549
+ image: { width: "0rem", height: "0rem" },
538
550
  }
539
551
  const headers = [...(component.properties.header || []), newColumn]
540
- updateProperty('header', headers, component, onPropertyChange)
541
- headers.forEach((h) => {
542
- updateTableHeader(headers.indexOf(h), 'width', `${(100 / headers.length).toFixed(2)}%`)
552
+ updateProperty("header", headers, component, onPropertyChange)
553
+ headers.forEach(h => {
554
+ updateTableHeader(headers.indexOf(h), "width", `${(100 / headers.length).toFixed(2)}%`)
543
555
  })
544
556
  updateTableBody()
545
- }}
546
- />
557
+ }} />
547
558
  </div>
548
559
  <div class="flex flex-col gap-2">
549
560
  {#each component.properties.header as column, columnIndex (columnIndex)}
@@ -551,192 +562,225 @@
551
562
  <div class="mb-5">
552
563
  <div class="mr-2 grid grid-cols-[minmax(5rem,10rem)_1fr_minmax(5rem,10rem)_minmax(10rem,21rem)_6rem_6rem_2rem_2rem] items-end gap-6">
553
564
  <UI.Input
554
- label={{ name: $t('constructor.props.table.columns.key') }}
565
+ label={{ name: $t("constructor.props.table.columns.key") }}
555
566
  value={column.key}
556
567
  help={{ regExp: /^[0-9a-zA-Z_-]{0,16}$/ }}
557
- onUpdate={(value) => {
558
- updateTableHeader(columnIndex, 'key', value)
568
+ onUpdate={value => {
569
+ updateTableHeader(columnIndex, "key", value)
559
570
  updateTableBody()
560
- }}
561
- />
571
+ }} />
562
572
  <UI.Input
563
- label={{ name: $t('constructor.props.table.columns.label') }}
573
+ label={{ name: $t("constructor.props.table.columns.label") }}
564
574
  value={column.label.name}
565
- onUpdate={(value) => {
566
- updateTableHeader(columnIndex, 'label', { ['name']: value })
567
- }}
568
- />
575
+ onUpdate={value => {
576
+ updateTableHeader(columnIndex, "label", { ["name"]: value })
577
+ }} />
569
578
  <UI.Input
570
- label={{ name: $t('constructor.props.table.columns.width'), class: 'px-0' }}
579
+ label={{ name: $t("constructor.props.table.columns.width"), class: "px-0" }}
571
580
  type="number"
572
- value={Number(column.width.replace('%', ''))}
573
- onUpdate={(value) => updateTableHeader(columnIndex, 'width', `${value}%`)}
574
- />
581
+ value={Number(column.width.replace("%", ""))}
582
+ onUpdate={value => updateTableHeader(columnIndex, "width", `${value}%`)} />
575
583
  <UI.Select
576
- label={{ name: $t('constructor.props.align.content') }}
584
+ label={{ name: $t("constructor.props.align.content") }}
577
585
  type="buttons"
578
- value={$optionsStore.ALIGN_OPTIONS.find((a) => (a.value as string).includes(column.align))}
586
+ value={$optionsStore.ALIGN_OPTIONS.find(a => (a.value as string).includes(column.align))}
579
587
  options={$optionsStore.ALIGN_OPTIONS}
580
- onUpdate={(option) => updateTableHeader(columnIndex, 'align', option.value)}
581
- />
588
+ onUpdate={option => updateTableHeader(columnIndex, "align", option.value)} />
582
589
  <UI.Switch
583
- label={{ name: $t('constructor.props.table.columns.sortable'), class: 'px-0' }}
584
- options={[{ id: crypto.randomUUID(), value: 0, class: '' }]}
590
+ label={{ name: $t("constructor.props.table.columns.sortable"), class: "px-0" }}
591
+ options={[{ id: crypto.randomUUID(), value: 0, class: "" }]}
585
592
  value={column.sortable}
586
- onChange={(value) => updateTableHeader(columnIndex, 'sortable', value)}
587
- />
593
+ onChange={value => updateTableHeader(columnIndex, "sortable", value)} />
588
594
  <UI.Switch
589
- label={{ name: $t('constructor.props.copy'), class: 'px-0' }}
590
- options={[{ id: crypto.randomUUID(), value: 0, class: '' }]}
595
+ label={{ name: $t("constructor.props.copy"), class: "px-0" }}
596
+ options={[{ id: crypto.randomUUID(), value: 0, class: "" }]}
591
597
  value={column.overflow?.copy}
592
- onChange={(value) => updateTableHeader(columnIndex, 'overflow', { copy: value, truncated: column.overflow?.truncated })}
593
- />
598
+ onChange={value => updateTableHeader(columnIndex, "overflow", { copy: value, truncated: column.overflow?.truncated })} />
599
+
594
600
  <UI.Button
595
- wrapperClass="w-8"
596
- content={{ icon: ButtonAdd, info: { text: $t('constructor.props.table.addaction'), side: 'top' } }}
601
+ wrapperClass="w-8 {column.action && column.action.type != 'none' ? 'invisible' : ''}"
602
+ content={{ icon: ButtonAdd, info: { text: $t("constructor.props.table.addaction"), side: "top" } }}
597
603
  onClick={() => {
598
- const newButton = {
599
- name: `button${(component.properties.header[columnIndex].buttons ? component.properties.header[columnIndex].buttons.length : 0) + 1}`,
600
- class: 'bg-blue',
601
- eventHandler: { Header: 'SET', Argument: 'Save', Variables: [] },
602
- onClick: () => {},
604
+ column.action = { type: "buttons", select: { key: "" } }
605
+ if (!(column.action && column.action.buttons)) {
603
606
  }
604
- const buttons = [...(component.properties.header[columnIndex].buttons || []), newButton]
605
- updateTableHeader(columnIndex, 'buttons', buttons)
606
- }}
607
- />
607
+ }} />
608
+
608
609
  <UI.Button
609
610
  wrapperClass="w-8"
610
611
  content={{ icon: ButtonDelete }}
611
612
  onClick={() => {
612
613
  const headers = [...(component.properties.header || [])]
613
614
  headers.splice(columnIndex, 1)
614
- updateProperty('header', headers, component, onPropertyChange)
615
- headers.forEach((h) => {
616
- updateTableHeader(headers.indexOf(h), 'width', `${(100 / headers.length).toFixed(2)}%`)
615
+ updateProperty("header", headers, component, onPropertyChange)
616
+ headers.forEach(h => {
617
+ updateTableHeader(headers.indexOf(h), "width", `${(100 / headers.length).toFixed(2)}%`)
617
618
  })
618
- }}
619
- />
619
+ }} />
620
620
  </div>
621
621
  <div class="mr-2 grid grid-cols-[5rem_minmax(8rem,16rem)_1fr_minmax(8rem,12rem)_minmax(8rem,12rem)] items-end justify-between gap-6">
622
622
  <UI.Switch
623
- label={{ name: $t('constructor.props.table.columns.truncated'), class: 'px-0' }}
624
- options={[{ id: crypto.randomUUID(), value: 0, class: '' }]}
623
+ label={{ name: $t("constructor.props.table.columns.truncated"), class: "px-0" }}
624
+ options={[{ id: crypto.randomUUID(), value: 0, class: "" }]}
625
625
  value={column.overflow?.truncated}
626
- onChange={(value) => updateTableHeader(columnIndex, 'overflow', { truncated: value, copy: column.overflow?.copy })}
627
- />
626
+ onChange={value => updateTableHeader(columnIndex, "overflow", { truncated: value, copy: column.overflow?.copy })} />
628
627
  <div class="relative mt-6 flex items-center w-full gap-2">
629
628
  <UI.Button
630
- content={{ name: $t('constructor.props.table.columns.defaultIcon') }}
631
- onClick={() => (defaultIcon = { isModalOpen: true, columnIndex: columnIndex, column: column })}
632
- />
629
+ content={{ name: $t("constructor.props.table.columns.defaultIcon") }}
630
+ onClick={() => (defaultIcon = { isModalOpen: true, columnIndex: columnIndex, column: column })} />
633
631
  {#if column.image?.defaultIcon}
634
632
  <UI.Button
635
633
  wrapperClass="w-8.5 "
636
634
  componentClass="p-0.5 bg-red"
637
635
  content={{ icon: CrossIcon }}
638
636
  onClick={() => {
639
- updateTableHeader(columnIndex, 'image', {
637
+ updateTableHeader(columnIndex, "image", {
640
638
  class: column.image?.class,
641
639
  width: column.image?.width,
642
640
  height: column.image?.height,
643
- defaultIcon: '',
641
+ defaultIcon: "",
644
642
  })
645
- }}
646
- />
643
+ }} />
647
644
  {/if}
648
645
  </div>
649
646
  <UI.Input
650
- label={{ name: $t('constructor.props.table.columns.class') }}
647
+ label={{ name: $t("constructor.props.table.columns.class") }}
651
648
  value={column.image?.class}
652
- onUpdate={(value) => {
653
- updateTableHeader(columnIndex, 'image', {
649
+ onUpdate={value => {
650
+ updateTableHeader(columnIndex, "image", {
654
651
  class: value,
655
652
  width: column.image?.width,
656
653
  height: column.image?.height,
657
654
  defaultIcon: column.image.defaultIcon,
658
655
  })
659
- }}
660
- />
656
+ }} />
661
657
  <UI.Input
662
- label={{ name: $t('constructor.props.table.columns.image.width'), class: 'px-0' }}
658
+ label={{ name: $t("constructor.props.table.columns.image.width"), class: "px-0" }}
663
659
  type="number"
664
660
  number={{ minNum: 0, maxNum: 1000, step: 1 }}
665
- value={Number(column.image?.width.replace('rem', '')) ?? 0}
666
- onUpdate={(value) => {
667
- updateTableHeader(columnIndex, 'image', {
661
+ value={Number(column.image?.width.replace("rem", "")) ?? 0}
662
+ onUpdate={value => {
663
+ updateTableHeader(columnIndex, "image", {
668
664
  class: column.image?.class,
669
665
  width: `${value ?? 0}rem`,
670
666
  height: column.image?.height,
671
667
  defaultIcon: column.image.defaultIcon,
672
668
  })
673
- }}
674
- />
669
+ }} />
675
670
  <UI.Input
676
- label={{ name: $t('constructor.props.table.columns.image.height'), class: 'px-0' }}
671
+ label={{ name: $t("constructor.props.table.columns.image.height"), class: "px-0" }}
677
672
  type="number"
678
673
  number={{ minNum: 0, maxNum: 1000, step: 1 }}
679
- value={Number(column.image?.height.replace('rem', ''))}
680
- onUpdate={(value) => {
681
- updateTableHeader(columnIndex, 'image', {
674
+ value={Number(column.image?.height.replace("rem", ""))}
675
+ onUpdate={value => {
676
+ updateTableHeader(columnIndex, "image", {
682
677
  class: column.image?.class,
683
678
  width: column.image?.width,
684
679
  height: `${value}rem`,
685
680
  defaultIcon: column.image.defaultIcon,
686
681
  })
687
- }}
688
- />
682
+ }} />
689
683
  </div>
690
684
  </div>
691
685
 
692
- {#if column.buttons && column.buttons.length > 0}
693
- <hr class="border-(--border-color)" />
686
+ {#if column.action && column.action.type != "none"}
687
+ <hr class="border-(--border-color) py-2" />
688
+ <div class="relative flex w-full justify-center">
689
+ <UI.Select
690
+ type="buttons"
691
+ wrapperClass="w-[50%]"
692
+ options={$optionsStore.ACTION_TYPE_OPTIONS}
693
+ value={$optionsStore.ACTION_TYPE_OPTIONS.find(h => h.value === column.action?.type) || $optionsStore.ACTION_TYPE_OPTIONS[0]}
694
+ onUpdate={value => {
695
+ column.action.type = value.value
696
+ }} />
697
+
698
+ <UI.Button
699
+ wrapperClass="w-8 {column.action.type == 'select' ? 'invisible' : ''}"
700
+ content={{ icon: ButtonAdd, info: { text: $t("constructor.props.table.addbutton"), side: "top" } }}
701
+ onClick={() => {
702
+ const newButton = {
703
+ name: `button${(component.properties.header[columnIndex].action.buttons ? component.properties.header[columnIndex].action.buttons.length : 0) + 1}`,
704
+ class: "bg-blue",
705
+ eventHandler: { Header: "SET", Argument: "Save", Variables: [] },
706
+ onClick: () => {},
707
+ }
708
+ let action = { ...component.properties.header[columnIndex].action }
709
+
710
+ if (!action) {
711
+ action = { type: "buttons", buttons: [newButton], select: { key: "", onChange: () => {} } }
712
+ } else if (action.type === "buttons") {
713
+ const buttons = [...(action.buttons || []), newButton]
714
+ action = { ...action, buttons }
715
+ } else {
716
+ action = { type: "buttons", buttons: [newButton], select: action.select }
717
+ }
718
+
719
+ updateTableHeader(columnIndex, "action", action)
720
+ }} />
721
+
722
+ <UI.Button
723
+ wrapperClass="w-8 absolute right-0"
724
+ content={{ icon: CrossIcon }}
725
+ onClick={() => {
726
+ column.action.type = "none"
727
+ }} />
728
+ </div>
729
+
694
730
  <div class="mb-5 rounded-lg p-1">
695
- {#each column.buttons as button, buttonIndex (buttonIndex)}
731
+ {#if column.action.type == "buttons"}
732
+ {#each column.action.buttons as button, buttonIndex (buttonIndex)}
733
+ <div class="ml-14 flex items-end justify-between gap-2">
734
+ <UI.Input
735
+ label={{ name: $t("constructor.props.name") }}
736
+ wrapperClass="!w-3/10"
737
+ value={button.name}
738
+ onUpdate={value => updateButtonProperty(columnIndex, buttonIndex, "name", value)} />
739
+ <UI.Select
740
+ wrapperClass="!w-2/10"
741
+ label={{ name: $t("constructor.props.header") }}
742
+ type="buttons"
743
+ value={$optionsStore.HEADER_OPTIONS.find(h => h.value === button.eventHandler?.Header)}
744
+ options={$optionsStore.HEADER_OPTIONS}
745
+ onUpdate={option => {
746
+ const handler = button.eventHandler
747
+ handler.Header = option.value as string
748
+ updateButtonProperty(columnIndex, buttonIndex, "eventHandler", handler)
749
+ }} />
750
+ <UI.Input
751
+ wrapperClass="!w-2/10"
752
+ label={{ name: $t("constructor.props.argument") }}
753
+ value={button.eventHandler?.Argument}
754
+ onUpdate={value => {
755
+ const handler = button.eventHandler
756
+ handler.Argument = value as string
757
+ updateButtonProperty(columnIndex, buttonIndex, "eventHandler", handler)
758
+ }} />
759
+ <UI.Input
760
+ wrapperClass="!w-2/10"
761
+ label={{ name: $t("constructor.props.table.keys") }}
762
+ value={button.eventHandler?.Variables.join(" ")}
763
+ maxlength={500}
764
+ help={{ info: $t("constructor.props.table.keys.info"), regExp: /^[a-zA-Z0-9\-_ ]{0,500}$/ }}
765
+ onUpdate={value => {
766
+ const handler = { ...button.eventHandler }
767
+ handler.Variables = (value as string).trim().split(/\s+/)
768
+ updateButtonProperty(columnIndex, buttonIndex, "eventHandler", handler)
769
+ }} />
770
+ <UI.Button wrapperClass="w-8" content={{ icon: ButtonDelete }} onClick={() => removeButtonFromColumn(columnIndex, buttonIndex)} />
771
+ </div>
772
+ {/each}
773
+ {:else if column.action.type == "select"}
696
774
  <div class="ml-14 flex items-end justify-between gap-2">
697
- <UI.Input
698
- label={{ name: $t('constructor.props.name') }}
699
- wrapperClass="!w-3/10"
700
- value={button.name}
701
- onUpdate={(value) => updateButtonProperty(columnIndex, buttonIndex, 'name', value)}
702
- />
703
775
  <UI.Select
704
- wrapperClass="!w-2/10"
705
- label={{ name: $t('constructor.props.header') }}
706
- type="buttons"
707
- value={$optionsStore.HEADER_OPTIONS.find((h) => h.value === button.eventHandler?.Header)}
708
- options={$optionsStore.HEADER_OPTIONS}
709
- onUpdate={(option) => {
710
- const handler = button.eventHandler
711
- handler.Header = option.value as string
712
- updateButtonProperty(columnIndex, buttonIndex, 'eventHandler', handler)
713
- }}
714
- />
715
- <UI.Input
716
- wrapperClass="!w-2/10"
717
- label={{ name: $t('constructor.props.argument') }}
718
- value={button.eventHandler?.Argument}
719
- onUpdate={(value) => {
720
- const handler = button.eventHandler
721
- handler.Argument = value as string
722
- updateButtonProperty(columnIndex, buttonIndex, 'eventHandler', handler)
723
- }}
724
- />
725
- <UI.Input
726
- wrapperClass="!w-2/10"
727
- label={{ name: $t('constructor.props.table.keys') }}
728
- value={button.eventHandler?.Variables.join(' ')}
729
- maxlength={500}
730
- help={{ info: $t('constructor.props.table.keys.info'), regExp: /^[a-zA-Z0-9\-_ ]{0,500}$/ }}
731
- onUpdate={(value) => {
732
- const handler = { ...button.eventHandler }
733
- handler.Variables = (value as string).trim().split(/\s+/)
734
- updateButtonProperty(columnIndex, buttonIndex, 'eventHandler', handler)
735
- }}
736
- />
737
- <UI.Button wrapperClass="w-8" content={{ icon: ButtonDelete }} onClick={() => removeButtonFromColumn(columnIndex, buttonIndex)} />
738
- </div>
739
- {/each}
776
+ label={{ name: $t("constructor.props.variable") }}
777
+ options={VARIABLE_OPTIONS}
778
+ value={VARIABLE_OPTIONS.find(opt => opt.value === column.action.select.key)}
779
+ onUpdate={value => {
780
+ updateSelectProperty(columnIndex, "key", value.value as string)
781
+ onPropertyChange({ name: value.name?.split("—")[1].trim(), eventHandler: { Variables: [value.value as string] } })
782
+ }} />
783
+ </div>{/if}
740
784
  </div>
741
785
  {/if}
742
786
  </div>
@@ -753,14 +797,13 @@
753
797
  <button
754
798
  class="h-8 w-8 cursor-pointer [&_svg]:h-full [&_svg]:max-h-full [&_svg]:w-full [&_svg]:max-w-full"
755
799
  onclick={() => {
756
- updateTableHeader(defaultIcon.columnIndex, 'image', {
800
+ updateTableHeader(defaultIcon.columnIndex, "image", {
757
801
  class: defaultIcon.column.image?.class,
758
802
  width: defaultIcon.column.image?.width,
759
803
  height: defaultIcon.column.image?.height,
760
804
  defaultIcon: icon as string,
761
805
  })
762
- }}
763
- >
806
+ }}>
764
807
  {@html icon}
765
808
  </button>{/each}
766
809
  </div>