windmill-components 1.305.6 → 1.306.8

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 (42) hide show
  1. package/package/assets/app.css +21 -0
  2. package/package/components/apps/components/buttons/AppButton.svelte +7 -3
  3. package/package/components/apps/components/display/AppDownload.svelte +12 -8
  4. package/package/components/apps/components/display/AppHtml.svelte +6 -23
  5. package/package/components/apps/components/display/AppHtml.svelte.d.ts +0 -2
  6. package/package/components/apps/components/display/AppMap.svelte +62 -70
  7. package/package/components/apps/components/display/AppMap.svelte.d.ts +1 -0
  8. package/package/components/apps/components/display/AppMenu.svelte +13 -9
  9. package/package/components/apps/components/display/AppStatCard.svelte +6 -4
  10. package/package/components/apps/components/display/table/AppAggridTable.svelte +110 -9
  11. package/package/components/apps/components/display/table/AppAggridTable.svelte.d.ts +2 -0
  12. package/package/components/apps/components/display/table/AppAggridTableActions.svelte +232 -0
  13. package/package/components/apps/components/display/table/AppAggridTableActions.svelte.d.ts +30 -0
  14. package/package/components/apps/components/display/table/AppAggridTableEe.svelte +10 -1
  15. package/package/components/apps/components/display/table/AppAggridTableEe.svelte.d.ts +2 -0
  16. package/package/components/apps/components/display/table/AppTable.svelte +0 -1
  17. package/package/components/apps/components/helpers/eval.js +1 -1
  18. package/package/components/apps/components/icon.js +0 -2
  19. package/package/components/apps/components/inputs/AppCheckbox.svelte +1 -0
  20. package/package/components/apps/components/inputs/AppTextInput.svelte +27 -11
  21. package/package/components/apps/editor/AppEditorHeader.svelte +4 -0
  22. package/package/components/apps/editor/AppInputs.svelte +11 -0
  23. package/package/components/apps/editor/SettingsPanel.svelte +22 -3
  24. package/package/components/apps/editor/appUtils.js +30 -0
  25. package/package/components/apps/editor/component/Component.svelte +2 -0
  26. package/package/components/apps/editor/component/ComponentCallbacks.svelte +4 -0
  27. package/package/components/apps/editor/component/components.d.ts +25 -2
  28. package/package/components/apps/editor/component/components.js +12 -0
  29. package/package/components/apps/editor/contextPanel/components/OutputHeader.svelte +13 -0
  30. package/package/components/apps/editor/contextPanel/components/TableActionsOutput.svelte +7 -0
  31. package/package/components/apps/editor/inlineScriptsPanel/InlineScriptsPanelWithTable.svelte +14 -0
  32. package/package/components/apps/editor/inlineScriptsPanel/utils.js +8 -0
  33. package/package/components/apps/editor/settingsPanel/ComponentPanel.svelte +3 -0
  34. package/package/components/apps/editor/settingsPanel/TableActions.svelte +86 -72
  35. package/package/components/apps/editor/settingsPanel/TableActions.svelte.d.ts +1 -1
  36. package/package/components/apps/editor/settingsPanel/inputEditor/IconSelectInput.svelte +1 -0
  37. package/package/components/apps/utils.js +9 -0
  38. package/package/components/common/fileInput/FileInput.svelte +16 -0
  39. package/package/components/common/fileUpload/FileUpload.svelte +19 -19
  40. package/package/user.js +1 -1
  41. package/package/utils.js +1 -1
  42. package/package.json +8 -1
@@ -313,6 +313,12 @@ const aggridcomponentconst = {
313
313
  value: 'normal',
314
314
  selectOptions: ['normal', 'compact', 'comfortable'],
315
315
  tooltip: 'Change the row height'
316
+ },
317
+ wrapActions: {
318
+ type: 'static',
319
+ fieldType: 'boolean',
320
+ value: false,
321
+ tooltip: 'When true, actions will wrap to the next line. Otherwise, the column will grow to fit the actions.'
316
322
  }
317
323
  },
318
324
  componentInput: {
@@ -2409,6 +2415,12 @@ See date-fns format for more information. By default, it is 'dd.MM.yyyy HH:mm'
2409
2415
  title: 'London'
2410
2416
  }
2411
2417
  ]
2418
+ },
2419
+ lock: {
2420
+ fieldType: 'boolean',
2421
+ type: 'static',
2422
+ value: false,
2423
+ tooltip: 'Lock the map to prevent user interaction'
2412
2424
  }
2413
2425
  }
2414
2426
  }
@@ -67,6 +67,13 @@ function renameId(newId) {
67
67
  propagateRename(old, c.id);
68
68
  }
69
69
  }
70
+ if (item?.data.type == 'aggridcomponent' || item?.data.type == 'aggridcomponentee') {
71
+ for (let c of item.data.actions ?? []) {
72
+ let old = c.id;
73
+ c.id = c.id.replace(id + '_', newId + '_');
74
+ propagateRename(old, c.id);
75
+ }
76
+ }
70
77
  if (item?.data.type === 'menucomponent') {
71
78
  for (let c of item.data.menuItems) {
72
79
  let old = c.id;
@@ -84,6 +91,12 @@ function renameComponent(from, to, data) {
84
91
  renameComponent(from, to, c);
85
92
  }
86
93
  }
94
+ if ((data.type == 'aggridcomponent' || data.type == 'aggridcomponentee') &&
95
+ Array.isArray(data.actions)) {
96
+ for (let c of data.actions) {
97
+ renameComponent(from, to, c);
98
+ }
99
+ }
87
100
  if (data.type === 'menucomponent') {
88
101
  for (let c of data.menuItems) {
89
102
  renameComponent(from, to, c);
@@ -10,4 +10,11 @@ export let gridItem;
10
10
  {/each}
11
11
  </div>
12
12
  {/if}
13
+ {#if (gridItem.data.type === 'aggridcomponent' || gridItem.data.type === 'aggridcomponentee') && gridItem.data.actions?.length > 0}
14
+ <div class="ml-2 border-l">
15
+ {#each gridItem.data.actions as action, index}
16
+ <Output id={action.id} first={index === 0} label="Table action" />
17
+ {/each}
18
+ </div>
19
+ {/if}
13
20
  </div>
@@ -30,6 +30,20 @@ export let gridItem;
30
30
  {/each}
31
31
  {/if}
32
32
 
33
+ {#if (gridItem?.data?.type === 'aggridcomponent' || gridItem?.data?.type === 'aggridcomponentee') && Array.isArray(gridItem.data.actions)}
34
+ {#each gridItem.data.actions as actionButton, index (index)}
35
+ {#if actionButton?.id === $selectedComponentInEditor || actionButton?.id + '_transformer' === $selectedComponentInEditor}
36
+ <InlineScriptEditorPanel
37
+ on:createScriptFromInlineScript
38
+ componentType={actionButton.type}
39
+ id={actionButton.id}
40
+ transformer={$selectedComponentInEditor?.endsWith('_transformer')}
41
+ bind:componentInput={actionButton.componentInput}
42
+ />
43
+ {/if}
44
+ {/each}
45
+ {/if}
46
+
33
47
  {#if gridItem?.data?.type === 'menucomponent'}
34
48
  {#each gridItem.data.menuItems as actionButton, index (index)}
35
49
  {#if actionButton?.id === $selectedComponentInEditor || actionButton?.id + '_transformer' === $selectedComponentInEditor}
@@ -46,6 +46,14 @@ function processGridItemRunnable(gridItem, list) {
46
46
  processRunnable(actionButton.componentInput.runnable, actionButton.componentInput.transformer, actionButton.id, list);
47
47
  });
48
48
  }
49
+ if (component.type === 'aggridcomponent' || component.type === 'aggridcomponentee') {
50
+ component.actions?.forEach((actionButton) => {
51
+ if (actionButton.componentInput?.type !== 'runnable') {
52
+ return;
53
+ }
54
+ processRunnable(actionButton.componentInput.runnable, actionButton.componentInput.transformer, actionButton.id, list);
55
+ });
56
+ }
49
57
  if (component.type === 'menucomponent') {
50
58
  component.menuItems?.forEach((menuItem) => {
51
59
  if (menuItem.componentInput?.type !== 'runnable') {
@@ -294,6 +294,7 @@ function isMac() {
294
294
  />
295
295
  {:else if componentSettings.item.data.type === 'aggridcomponentee'}
296
296
  <GridAgGridLicenseKey bind:license={componentSettings.item.data.license} />
297
+ <TableActions id={component.id} bind:components={componentSettings.item.data.actions} />
297
298
  {:else if componentSettings.item.data.type === 'agchartscomponentee'}
298
299
  <GridAgChartsLicenseKe bind:license={componentSettings.item.data.license} />
299
300
  {:else if componentSettings.item.data.type === 'steppercomponent'}
@@ -323,6 +324,8 @@ function isMac() {
323
324
  bind:panes={componentSettings.item.data.panes}
324
325
  bind:component={componentSettings.item.data}
325
326
  />
327
+ {:else if componentSettings.item.data.type === 'aggridcomponent'}
328
+ <TableActions id={component.id} bind:components={componentSettings.item.data.actions} />
326
329
  {:else if componentSettings.item.data.type === 'tablecomponent' && Array.isArray(componentSettings.item.data.actionButtons)}
327
330
  <TableActions id={component.id} bind:components={componentSettings.item.data.actionButtons} />
328
331
  {:else if componentSettings.item.data.type === 'menucomponent' && Array.isArray(componentSettings.item.data.menuItems)}
@@ -2,14 +2,23 @@
2
2
  import Button from '../../../common/button/Button.svelte';
3
3
  import { getNextId } from '../../../flows/idUtils';
4
4
  import { classNames } from '../../../../utils';
5
- import { getContext } from 'svelte';
5
+ import { getContext, onMount } from 'svelte';
6
6
  import { appComponentFromType } from '../appUtils';
7
7
  import PanelSection from './common/PanelSection.svelte';
8
8
  import { Inspect, List, ToggleRightIcon, Trash } from 'lucide-svelte';
9
9
  export let components;
10
+ // Migration code:
11
+ onMount(() => {
12
+ if (components === undefined) {
13
+ components = [];
14
+ }
15
+ });
10
16
  export let id;
11
17
  const { selectedComponent, app, errorByComponent } = getContext('AppViewerContext');
12
18
  function addComponent(typ) {
19
+ if (!components) {
20
+ return;
21
+ }
13
22
  const actionId = getNextId(components.map((x) => x.id.split('_')[1]));
14
23
  const newComponent = {
15
24
  ...appComponentFromType(typ)(`${id}_${actionId}`),
@@ -19,6 +28,9 @@ function addComponent(typ) {
19
28
  $app = $app;
20
29
  }
21
30
  function deleteComponent(cid) {
31
+ if (!components) {
32
+ return;
33
+ }
22
34
  components = components.filter((x) => x.id !== cid);
23
35
  delete $errorByComponent[cid];
24
36
  $selectedComponent = [id];
@@ -26,77 +38,79 @@ function deleteComponent(cid) {
26
38
  }
27
39
  </script>
28
40
 
29
- <PanelSection title={`Table Actions`}>
30
- {#if components.length == 0}
31
- <span class="text-xs text-tertiary">No action buttons</span>
32
- {/if}
33
- {#each components as component}
34
- <!-- svelte-ignore a11y-no-static-element-interactions -->
35
- <div
36
- class={classNames(
37
- 'w-full text-xs font-bold gap-1 truncate py-1.5 px-2 cursor-pointer transition-all justify-between flex items-center border border-gray-3 rounded-md',
38
- 'bg-surface hover:bg-surface-hover focus:border-primary text-secondary',
39
- $selectedComponent?.includes(component.id) ? 'outline outline-blue-500 bg-red-400' : ''
40
- )}
41
- on:click={() => {
42
- $selectedComponent = [component.id]
43
- }}
44
- on:keypress
45
- >
46
- <Badge color="dark-indigo">
47
- {component.id}
48
- </Badge>
41
+ {#if components}
42
+ <PanelSection title={`Table Actions`}>
43
+ {#if components.length == 0}
44
+ <span class="text-xs text-tertiary">No action buttons</span>
45
+ {/if}
46
+ {#each components as component}
47
+ <!-- svelte-ignore a11y-no-static-element-interactions -->
48
+ <div
49
+ class={classNames(
50
+ 'w-full text-xs font-bold gap-1 truncate py-1.5 px-2 cursor-pointer transition-all justify-between flex items-center border border-gray-3 rounded-md',
51
+ 'bg-surface hover:bg-surface-hover focus:border-primary text-secondary',
52
+ $selectedComponent?.includes(component.id) ? 'outline outline-blue-500 bg-red-400' : ''
53
+ )}
54
+ on:click={() => {
55
+ $selectedComponent = [component.id]
56
+ }}
57
+ on:keypress
58
+ >
59
+ <Badge color="dark-indigo">
60
+ {component.id}
61
+ </Badge>
49
62
 
50
- <div>
51
- {#if component.type == 'buttoncomponent'}
52
- Button
53
- {:else if component.type == 'selectcomponent'}
54
- Select
55
- {:else if component.type == 'checkboxcomponent'}
56
- Toggle
57
- {/if}
58
- </div>
59
- <div>
60
- <Button
61
- variant="border"
62
- color="red"
63
- on:click={() => deleteComponent(component.id)}
64
- startIcon={{ icon: Trash }}
65
- iconOnly
66
- />
63
+ <div>
64
+ {#if component.type == 'buttoncomponent'}
65
+ Button
66
+ {:else if component.type == 'selectcomponent'}
67
+ Select
68
+ {:else if component.type == 'checkboxcomponent'}
69
+ Toggle
70
+ {/if}
71
+ </div>
72
+ <div>
73
+ <Button
74
+ variant="border"
75
+ color="red"
76
+ on:click={() => deleteComponent(component.id)}
77
+ startIcon={{ icon: Trash }}
78
+ iconOnly
79
+ />
80
+ </div>
67
81
  </div>
82
+ {/each}
83
+ <div class="w-full flex gap-2">
84
+ <Button
85
+ btnClasses="gap-1 flex items-center text-sm text-tertiary"
86
+ wrapperClasses="w-full"
87
+ color="light"
88
+ variant="border"
89
+ on:click={() => addComponent('buttoncomponent')}
90
+ title="Add Button"
91
+ >
92
+ + <Inspect size={14} />
93
+ </Button>
94
+ <Button
95
+ btnClasses="gap-1 flex items-center text-sm text-tertiary"
96
+ wrapperClasses="w-full"
97
+ color="light"
98
+ variant="border"
99
+ on:click={() => addComponent('checkboxcomponent')}
100
+ title="Add Toggle"
101
+ >
102
+ + <ToggleRightIcon size={14} />
103
+ </Button>
104
+ <Button
105
+ btnClasses="gap-1 flex items-center text-sm text-tertiary"
106
+ wrapperClasses="w-full"
107
+ color="light"
108
+ variant="border"
109
+ on:click={() => addComponent('selectcomponent')}
110
+ title="Add Select"
111
+ >
112
+ + <List size={14} />
113
+ </Button>
68
114
  </div>
69
- {/each}
70
- <div class="w-full flex gap-2">
71
- <Button
72
- btnClasses="gap-1 flex items-center text-sm text-tertiary"
73
- wrapperClasses="w-full"
74
- color="light"
75
- variant="border"
76
- on:click={() => addComponent('buttoncomponent')}
77
- title="Add Button"
78
- >
79
- + <Inspect size={14} />
80
- </Button>
81
- <Button
82
- btnClasses="gap-1 flex items-center text-sm text-tertiary"
83
- wrapperClasses="w-full"
84
- color="light"
85
- variant="border"
86
- on:click={() => addComponent('checkboxcomponent')}
87
- title="Add Toggle"
88
- >
89
- + <ToggleRightIcon size={14} />
90
- </Button>
91
- <Button
92
- btnClasses="gap-1 flex items-center text-sm text-tertiary"
93
- wrapperClasses="w-full"
94
- color="light"
95
- variant="border"
96
- on:click={() => addComponent('selectcomponent')}
97
- title="Add Select"
98
- >
99
- + <List size={14} />
100
- </Button>
101
- </div>
102
- </PanelSection>
115
+ </PanelSection>
116
+ {/if}
@@ -3,7 +3,7 @@ import type { BaseAppComponent } from '../../types';
3
3
  import type { ButtonComponent, CheckboxComponent, SelectComponent } from '../component';
4
4
  declare const __propDef: {
5
5
  props: {
6
- components: (BaseAppComponent & (ButtonComponent | CheckboxComponent | SelectComponent))[];
6
+ components: (BaseAppComponent & (ButtonComponent | CheckboxComponent | SelectComponent))[] | undefined;
7
7
  id: string;
8
8
  };
9
9
  events: {
@@ -80,6 +80,7 @@ function select(label) {
80
80
  {label === componentInput.value ? 'text-blue-600 bg-blue-50 pointer-events-none' : ''}"
81
81
  >
82
82
  <img
83
+ class="dark:invert"
83
84
  loading="lazy"
84
85
  src="https://cdn.jsdelivr.net/npm/lucide-static@0.367.0/icons/{label}.svg"
85
86
  />
@@ -235,6 +235,15 @@ export function getAllScriptNames(app) {
235
235
  }
236
236
  });
237
237
  }
238
+ if (gridItem.data.type === 'aggridcomponent' || gridItem.data.type === 'aggridcomponentee') {
239
+ gridItem.data.actions?.forEach((actionButton) => {
240
+ if (actionButton.componentInput?.type === 'runnable') {
241
+ if (actionButton.componentInput.runnable?.type === 'runnableByName') {
242
+ acc.push(actionButton.componentInput.runnable.name);
243
+ }
244
+ }
245
+ });
246
+ }
238
247
  if (gridItem.data.type === 'menucomponent') {
239
248
  gridItem.data.menuItems.forEach((menuItem) => {
240
249
  if (menuItem.componentInput?.type === 'runnable') {
@@ -64,6 +64,20 @@ async function convertFile(file) {
64
64
  }
65
65
  });
66
66
  }
67
+ function handleDragOver(event) {
68
+ event.preventDefault();
69
+ if (event.dataTransfer) {
70
+ event.dataTransfer.dropEffect = 'copy';
71
+ }
72
+ }
73
+ function handleDrop(event) {
74
+ event.preventDefault();
75
+ if (event.dataTransfer) {
76
+ if (event.dataTransfer.files && event.dataTransfer.files.length) {
77
+ onChange(event.dataTransfer.files);
78
+ }
79
+ }
80
+ }
67
81
  function removeFile(index) {
68
82
  if (!files)
69
83
  return;
@@ -99,6 +113,8 @@ export function clearFiles() {
99
113
  duration-200 rounded-lg p-1`,
100
114
  c
101
115
  )}
116
+ on:dragover={handleDragOver}
117
+ on:drop={handleDrop}
102
118
  {style}
103
119
  >
104
120
  {#if !hideIcon && !files}
@@ -27,7 +27,7 @@ async function handleChange(files) {
27
27
  uploadFileToS3(file, file.name);
28
28
  }
29
29
  }
30
- let xhr = undefined;
30
+ let activeUploads = [];
31
31
  async function uploadFileToS3(fileToUpload, fileToUploadKey) {
32
32
  if (fileToUpload === undefined || fileToUploadKey === undefined) {
33
33
  return;
@@ -99,7 +99,8 @@ async function uploadFileToS3(fileToUpload, fileToUploadKey) {
99
99
  // duplex: 'half'
100
100
  // }
101
101
  // )
102
- xhr = new XMLHttpRequest();
102
+ let xhr = new XMLHttpRequest();
103
+ activeUploads.push({ xhr, fileName: fileToUpload.name });
103
104
  const response = (await new Promise((resolve, reject) => {
104
105
  xhr?.upload.addEventListener('progress', (event) => {
105
106
  if (event.lengthComputable) {
@@ -126,7 +127,7 @@ async function uploadFileToS3(fileToUpload, fileToUploadKey) {
126
127
  reject(response);
127
128
  }
128
129
  }
129
- xhr = undefined;
130
+ activeUploads = activeUploads.filter((x) => x.fileName !== fileToUpload.name);
130
131
  });
131
132
  xhr?.open('POST', `/api/w/${$workspaceStore}/job_helpers/upload_s3_file?${params.toString()}`, true);
132
133
  xhr?.setRequestHeader('Content-Type', 'application/octet-stream');
@@ -165,11 +166,19 @@ async function deleteFile(fileKey) {
165
166
  dispatch('deletion', { path: fileKey });
166
167
  sendUserToast('File deleted!');
167
168
  }
168
- onDestroy(() => {
169
- if (xhr) {
170
- xhr?.abort;
171
- xhr = undefined;
169
+ function clearRequests() {
170
+ activeUploads.forEach(({ xhr }) => xhr.abort());
171
+ activeUploads = [];
172
+ }
173
+ function abortUpload(fileName) {
174
+ const upload = activeUploads.find((x) => x.fileName === fileName);
175
+ if (upload) {
176
+ upload.xhr.abort();
177
+ activeUploads = activeUploads.filter((x) => x.fileName !== fileName);
172
178
  }
179
+ }
180
+ onDestroy(() => {
181
+ clearRequests();
173
182
  });
174
183
  </script>
175
184
 
@@ -207,10 +216,7 @@ onDestroy(() => {
207
216
  return
208
217
  }
209
218
 
210
- if (xhr) {
211
- xhr.abort()
212
- xhr = undefined
213
- }
219
+ abortUpload(fileUpload.name)
214
220
 
215
221
  $fileUploads = $fileUploads.filter(
216
222
  (_fileUpload) => _fileUpload.name !== fileUpload.name
@@ -235,10 +241,7 @@ onDestroy(() => {
235
241
  return
236
242
  }
237
243
 
238
- if (xhr) {
239
- xhr.abort()
240
- xhr = undefined
241
- }
244
+ clearRequests()
242
245
 
243
246
  $fileUploads = $fileUploads.filter(
244
247
  (_fileUpload) => _fileUpload.name !== fileUpload.name
@@ -281,10 +284,7 @@ onDestroy(() => {
281
284
  if (fileUpload.path) {
282
285
  deleteFile(fileUpload.path)
283
286
  }
284
- if (xhr) {
285
- xhr.abort()
286
- xhr = undefined
287
- }
287
+ abortUpload(fileUpload.name)
288
288
  }}
289
289
  startIcon={{
290
290
  icon: Trash
package/package/user.js CHANGED
@@ -11,7 +11,7 @@ export async function getUserExt(workspace) {
11
11
  function mapUserToUserExt(user) {
12
12
  return {
13
13
  ...user,
14
- groups: user.groups,
14
+ groups: user.groups ?? [],
15
15
  pgroups: user.groups.map((x) => `g/${x}`)
16
16
  };
17
17
  }
package/package/utils.js CHANGED
@@ -624,7 +624,7 @@ export function cleanValueProperties(obj) {
624
624
  }
625
625
  export function orderedJsonStringify(obj, space) {
626
626
  const allKeys = new Set();
627
- JSON.stringify(obj, (key, value) => (allKeys.add(key), value));
627
+ JSON.stringify(obj, (key, value) => (value != undefined && value != null && allKeys.add(key), value));
628
628
  return JSON.stringify(obj, Array.from(allKeys).sort(), space);
629
629
  }
630
630
  function sortObjectKeys(obj) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "windmill-components",
3
- "version": "1.305.6",
3
+ "version": "1.306.8",
4
4
  "scripts": {
5
5
  "dev": "vite dev",
6
6
  "build": "vite build",
@@ -291,6 +291,10 @@
291
291
  "types": "./package/gen/core/OpenAPI.d.ts",
292
292
  "default": "./package/gen/core/OpenAPI.js"
293
293
  },
294
+ "./gen/core": {
295
+ "default": "./package/gen/core/index.js",
296
+ "types": "./package/gen/core/index.d.ts"
297
+ },
294
298
  "./components/DropdownV2.svelte": {
295
299
  "types": "./package/components/DropdownV2.svelte.d.ts",
296
300
  "svelte": "./package/components/DropdownV2.svelte",
@@ -377,6 +381,9 @@
377
381
  "stores": [
378
382
  "./package/stores.d.ts"
379
383
  ],
384
+ "gen/core": [
385
+ "./package/gen/core/index.d.ts"
386
+ ],
380
387
  "components/flows/flowStore": [
381
388
  "./package/components/flows/flowStore.d.ts"
382
389
  ],