windmill-components 1.377.8 → 1.379.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.
Files changed (81) hide show
  1. package/package/ata/apis.d.ts +1 -0
  2. package/package/ata/apis.js +5 -3
  3. package/package/ata/index.d.ts +1 -1
  4. package/package/ata/index.js +2 -1
  5. package/package/components/DateInput.svelte +30 -3
  6. package/package/components/DisplayResult.svelte +19 -10
  7. package/package/components/DisplayResult.svelte.d.ts +1 -0
  8. package/package/components/FlowStatusViewer.svelte +2 -0
  9. package/package/components/FlowStatusViewer.svelte.d.ts +1 -0
  10. package/package/components/FlowStatusViewerInner.svelte +13 -10
  11. package/package/components/FlowStatusViewerInner.svelte.d.ts +1 -0
  12. package/package/components/FlowViewer.svelte.d.ts +1 -1
  13. package/package/components/InstanceSettings.svelte +1 -0
  14. package/package/components/LightweightArgInput.svelte +13 -6
  15. package/package/components/LightweightSchemaForm.svelte +4 -1
  16. package/package/components/LightweightSchemaForm.svelte.d.ts +1 -0
  17. package/package/components/LogViewer.svelte +0 -3
  18. package/package/components/Login.svelte +68 -80
  19. package/package/components/Login.svelte.d.ts +0 -2
  20. package/package/components/ModulePreview.svelte +1 -1
  21. package/package/components/ObjectStoreConfigSettings.svelte +2 -2
  22. package/package/components/Password.svelte +1 -1
  23. package/package/components/Portal.svelte +2 -2
  24. package/package/components/apps/components/GroupWrapper.svelte +3 -2
  25. package/package/components/apps/components/GroupWrapper.svelte.d.ts +2 -1
  26. package/package/components/apps/components/buttons/AppSchemaForm.svelte +16 -13
  27. package/package/components/apps/components/display/AppJobIdLogComponent.svelte +1 -1
  28. package/package/components/apps/components/display/AppRecomputeAll.svelte +2 -2
  29. package/package/components/apps/components/display/table/AppCell.svelte +5 -1
  30. package/package/components/apps/components/display/table/AppTableFooter.svelte +4 -1
  31. package/package/components/apps/components/helpers/InputValue.svelte +4 -3
  32. package/package/components/apps/components/helpers/RunnableComponent.svelte +4 -3
  33. package/package/components/apps/components/helpers/eval.d.ts +2 -1
  34. package/package/components/apps/components/helpers/eval.js +45 -14
  35. package/package/components/apps/components/inputs/AppTextInput.svelte +1 -0
  36. package/package/components/apps/components/layout/AppContainer.svelte +13 -3
  37. package/package/components/apps/editor/AppEditor.svelte +4 -7
  38. package/package/components/apps/editor/AppEditorHeader.svelte +22 -16
  39. package/package/components/apps/editor/AppPreview.svelte +8 -20
  40. package/package/components/apps/editor/AppPreview.svelte.d.ts +3 -1
  41. package/package/components/apps/editor/DeploymentHistory.svelte +1 -1
  42. package/package/components/apps/editor/RunnableJobPanel.svelte +8 -8
  43. package/package/components/apps/editor/inlineScriptsPanel/InlineScriptEditor.svelte +2 -2
  44. package/package/components/apps/editor/settingsPanel/ComponentInputTypeEditor.svelte +5 -1
  45. package/package/components/apps/editor/settingsPanel/GridGroup.svelte +13 -1
  46. package/package/components/apps/types.d.ts +7 -2
  47. package/package/components/apps/utils.js +30 -3
  48. package/package/components/common/drawer/Drawer.svelte +1 -1
  49. package/package/components/common/table/AppRow.svelte +2 -1
  50. package/package/components/common/table/FlowRow.svelte +2 -1
  51. package/package/components/common/table/RawAppRow.svelte +1 -1
  52. package/package/components/common/table/ScriptRow.svelte +2 -1
  53. package/package/components/flows/previousResults.js +1 -0
  54. package/package/components/jobs/JobPreview.svelte +1 -1
  55. package/package/components/propertyPicker/PropPicker.svelte +2 -1
  56. package/package/components/runs/JobLoader.svelte +19 -7
  57. package/package/components/runs/JobLoader.svelte.d.ts +2 -1
  58. package/package/components/runs/JobPreview.svelte +2 -2
  59. package/package/components/runs/QueuePopover.svelte +1 -1
  60. package/package/components/runs/RunRow.svelte +14 -7
  61. package/package/components/runs/RunRow.svelte.d.ts +1 -0
  62. package/package/components/runs/RunsFilter.svelte +78 -15
  63. package/package/components/runs/RunsFilter.svelte.d.ts +3 -2
  64. package/package/components/runs/RunsQueue.svelte +23 -11
  65. package/package/components/runs/RunsQueue.svelte.d.ts +5 -1
  66. package/package/components/runs/RunsTable.svelte +65 -63
  67. package/package/components/runs/RunsTable.svelte.d.ts +1 -0
  68. package/package/components/scriptEditor/LogPanel.svelte +1 -1
  69. package/package/gen/core/OpenAPI.js +1 -1
  70. package/package/gen/services.gen.d.ts +8 -3
  71. package/package/gen/services.gen.js +16 -4
  72. package/package/gen/types.gen.d.ts +22 -0
  73. package/package/refreshUser.d.ts +1 -1
  74. package/package/refreshUser.js +3 -2
  75. package/package/utils.d.ts +1 -4
  76. package/package/utils.js +0 -19
  77. package/package/utils_deployable.d.ts +5 -0
  78. package/package/utils_deployable.js +19 -0
  79. package/package.json +2 -9
  80. package/package/components/AppEmbed.svelte +0 -154
  81. package/package/components/AppEmbed.svelte.d.ts +0 -21
@@ -127,13 +127,40 @@ export function buildExtraLib(components, idToExclude, state, goto) {
127
127
  const cs = Object.entries(components)
128
128
  .filter(([k, v]) => k != idToExclude && k != 'state')
129
129
  .map(([k, v]) => [k, Object.fromEntries(Object.entries(v).map(([k, v]) => [k, v.peak()]))])
130
- .map(([k, v]) => `declare const ${k}: ${JSON.stringify(v)};
130
+ .map(([k, v]) => `declare const ${k}: WidenRo<${JSON.stringify(v)}>;
131
131
  `)
132
132
  .join('\n');
133
- return `${cs}
133
+ return `
134
+
135
+ type Widen<T> = T extends string
136
+ ? string
137
+ : T extends number
138
+ ? number
139
+ : T extends boolean
140
+ ? boolean
141
+ : T extends Array<infer U>
142
+ ? Array<Widen<U>>
143
+ : T extends object
144
+ ? Partial<{ [K in keyof T]: Widen<T[K]> } & {[key: string]: any}>
145
+ : T;
146
+
147
+ type WidenRo<T> = T extends string
148
+ ? string
149
+ : T extends number
150
+ ? number
151
+ : T extends boolean
152
+ ? boolean
153
+ : T extends Array<infer U>
154
+ ? Readonly<Array<WidenRo<U>>>
155
+ : T extends object
156
+ ? Readonly<{ [K in keyof T]: WidenRo<T[K]> }>
157
+ : T;
158
+
134
159
 
135
160
  /** The mutable state of the app */
136
- declare const state: ${JSON.stringify(state)} & {[key: string]: any};
161
+ declare const state: Widen<${JSON.stringify(state)}> & {[key: string]: any};
162
+
163
+ ${cs}
137
164
 
138
165
  ${goto
139
166
  ? `
@@ -57,7 +57,7 @@ onMount(() => {
57
57
  on:close
58
58
  >
59
59
  <aside
60
- class="windmill-app drawer windmill-drawer {$$props.class ?? ''} {$$props.positionClass ??
60
+ class="drawer windmill-app windmill-drawer {$$props.class ?? ''} {$$props.positionClass ??
61
61
  ''}"
62
62
  class:open
63
63
  class:close={!open && timeout}
@@ -11,9 +11,10 @@ import Badge from '../badge/Badge.svelte';
11
11
  import { ExternalLink, Eye, File, FileJson, FileUp, GitFork, Globe, History, Pen, Share, Trash, Clipboard } from 'lucide-svelte';
12
12
  import { goto as gotoUrl } from '$app/navigation';
13
13
  import { page } from '$app/stores';
14
- import { DELETE, copyToClipboard, isDeployable } from '../../../utils';
14
+ import { DELETE, copyToClipboard } from '../../../utils';
15
15
  import AppDeploymentHistory from '../../apps/editor/AppDeploymentHistory.svelte';
16
16
  import AppJsonEditor from '../../apps/editor/AppJsonEditor.svelte';
17
+ import { isDeployable } from '../../../utils_deployable';
17
18
  export let app;
18
19
  export let marked;
19
20
  export let starred;
@@ -11,7 +11,8 @@ import Button from '../button/Button.svelte';
11
11
  import Row from './Row.svelte';
12
12
  import DraftBadge from '../../DraftBadge.svelte';
13
13
  import { sendUserToast } from '../../../toast';
14
- import { DELETE, copyToClipboard, isDeployable, isOwner } from '../../../utils';
14
+ import { DELETE, copyToClipboard, isOwner } from '../../../utils';
15
+ import { isDeployable } from '../../../utils_deployable';
15
16
  import { Pen, GitFork, Trash, List, FileUp, Globe, Calendar, Share, Archive, Clipboard, Eye, HistoryIcon } from 'lucide-svelte';
16
17
  import FlowHistory from '../../flows/FlowHistory.svelte';
17
18
  export let flow;
@@ -11,7 +11,7 @@ import DrawerContent from '../drawer/DrawerContent.svelte';
11
11
  import FileInput from '../fileInput/FileInput.svelte';
12
12
  import { goto } from '../../../navigation';
13
13
  import { FileUp, Globe, Pen, Share, Trash } from 'lucide-svelte';
14
- import { isDeployable } from '../../../utils';
14
+ import { isDeployable } from '../../../utils_deployable';
15
15
  export let app;
16
16
  export let marked;
17
17
  export let starred;
@@ -11,7 +11,8 @@ import Button from '../button/Button.svelte';
11
11
  import Row from './Row.svelte';
12
12
  import DraftBadge from '../../DraftBadge.svelte';
13
13
  import { sendUserToast } from '../../../toast';
14
- import { copyToClipboard, DELETE, isDeployable, isOwner } from '../../../utils';
14
+ import { copyToClipboard, DELETE, isOwner } from '../../../utils';
15
+ import { isDeployable } from '../../../utils_deployable';
15
16
  import { LanguageIcon } from '../languageIcons';
16
17
  import { Archive, Calendar, Code, Copy, Eye, FileUp, GitFork, List, Pen, Share, Trash, History } from 'lucide-svelte';
17
18
  import ScriptVersionHistory from '../../ScriptVersionHistory.svelte';
@@ -106,6 +106,7 @@ declare const error: {
106
106
  message: string
107
107
  name: string
108
108
  stack: string
109
+ step_id: string
109
110
  }
110
111
 
111
112
  /**
@@ -131,7 +131,7 @@ onDestroy(() => {
131
131
  duration={job?.['duration_ms']}
132
132
  mem={job?.['mem_peak']}
133
133
  content={job?.logs}
134
- isLoading
134
+ isLoading={job?.['running'] == false}
135
135
  tag={job?.tag}
136
136
  />
137
137
  {/if}
@@ -91,7 +91,8 @@ async function loadResources() {
91
91
  error: {
92
92
  message: 'The error message',
93
93
  name: 'The error name',
94
- stack: 'The error stack'
94
+ stack: 'The error stack',
95
+ step_id: 'The step id'
95
96
  }
96
97
  }}
97
98
  on:select
@@ -21,6 +21,7 @@ export let minTs = undefined;
21
21
  export let maxTs = undefined;
22
22
  export let jobKinds = '';
23
23
  export let queue_count = undefined;
24
+ export let suspended_count = undefined;
24
25
  export let autoRefresh = true;
25
26
  export let completedJobs = undefined;
26
27
  export let externalJobs = undefined;
@@ -50,6 +51,7 @@ $: ($workspaceStore ||
50
51
  lookback &&
51
52
  user &&
52
53
  folder &&
54
+ schedulePath != undefined &&
53
55
  showFutureJobs != undefined &&
54
56
  showSchedules != undefined &&
55
57
  allWorkspaces != undefined &&
@@ -119,16 +121,17 @@ async function fetchJobs(startedBefore, startedAfter, startedAfterCompletedJobs)
119
121
  scriptPathStart: scriptPathStart,
120
122
  jobKinds,
121
123
  success: success == 'success' ? true : success == 'failure' ? false : undefined,
122
- running: success == 'running' ? true : undefined,
124
+ running: (success == 'running' || success == 'suspended') ? true : (success == 'waiting') ? false : undefined,
123
125
  isSkipped: isSkipped ? undefined : false,
124
126
  // isFlowStep: jobKindsCat != 'all' ? false : undefined,
125
- hasNullParent: scriptPathExact != undefined || scriptPathStart != undefined || jobKinds != 'all'
127
+ hasNullParent: scriptPathExact != undefined || scriptPathStart != undefined || jobKindsCat != 'all'
126
128
  ? true
127
129
  : undefined,
128
130
  label: label === null || label === '' ? undefined : label,
129
131
  tag: tag === null || tag === '' ? undefined : tag,
130
132
  isNotSchedule: showSchedules == false ? true : undefined,
131
- scheduledForBeforeNow: showFutureJobs == false ? true : undefined,
133
+ suspended: success == 'waiting' ? false : success == 'suspended' ? true : undefined,
134
+ scheduledForBeforeNow: showFutureJobs == false || (success == 'waiting' || success == 'suspended') ? true : undefined,
132
135
  args: argFilter && argFilter != '{}' && argFilter != '' && argError == ''
133
136
  ? argFilter
134
137
  : undefined,
@@ -256,16 +259,25 @@ async function loadJobsIntern(shouldGetCount) {
256
259
  loading = false;
257
260
  }
258
261
  async function getCount() {
259
- const qc = (await JobService.getQueueCount({ workspace: $workspaceStore, allWorkspaces }))
260
- .database_length;
262
+ const { database_length, suspended } = (await JobService.getQueueCount({ workspace: $workspaceStore, allWorkspaces }));
261
263
  if (queue_count) {
262
- queue_count.set(qc);
264
+ queue_count.set(database_length);
265
+ }
266
+ else {
267
+ queue_count = tweened(database_length, { duration: 1000 });
268
+ }
269
+ if (suspended_count) {
270
+ suspended_count.set(suspended ?? 0);
263
271
  }
264
272
  else {
265
- queue_count = tweened(qc, { duration: 1000 });
273
+ suspended_count = tweened(suspended ?? 0, { duration: 1000 });
266
274
  }
267
275
  }
268
276
  async function syncer() {
277
+ if (success == 'waiting') {
278
+ minTs = undefined;
279
+ maxTs = undefined;
280
+ }
269
281
  if (loadingFetch) {
270
282
  return;
271
283
  }
@@ -8,7 +8,7 @@ declare const __propDef: {
8
8
  label?: string | null | undefined;
9
9
  folder: string | null;
10
10
  path: string | null;
11
- success?: 'success' | 'failure' | 'running' | undefined;
11
+ success?: 'success' | 'suspended' | 'waiting' | 'failure' | 'running' | undefined;
12
12
  isSkipped?: boolean | undefined;
13
13
  showSchedules?: boolean | undefined;
14
14
  showFutureJobs?: boolean | undefined;
@@ -20,6 +20,7 @@ declare const __propDef: {
20
20
  maxTs?: string | undefined;
21
21
  jobKinds?: string | undefined;
22
22
  queue_count?: Tweened<number> | undefined;
23
+ suspended_count?: Tweened<number> | undefined;
23
24
  autoRefresh?: boolean | undefined;
24
25
  completedJobs?: CompletedJob[] | undefined;
25
26
  externalJobs?: Job[] | undefined;
@@ -173,7 +173,7 @@ const dispatch = createEventDispatcher();
173
173
  jobId={job.id}
174
174
  duration={job?.['duration_ms']}
175
175
  mem={job?.['mem_peak']}
176
- isLoading={!(job && 'logs' in job && job.logs)}
176
+ isLoading={job?.['running'] == false}
177
177
  content={job?.logs}
178
178
  tag={job?.tag}
179
179
  />
@@ -214,7 +214,7 @@ const dispatch = createEventDispatcher();
214
214
  duration={job?.['duration_ms']}
215
215
  mem={job?.['mem_peak']}
216
216
  content={job?.logs}
217
- isLoading
217
+ isLoading={job?.['running'] == false}
218
218
  tag={job?.tag}
219
219
  />
220
220
  {/if}
@@ -30,7 +30,7 @@ async function getQueuedJobs() {
30
30
  <div class="text-secondary text-xs">Only showing the first 100 jobs</div>
31
31
  {/if}
32
32
 
33
- {#each jobs.slice(0, 100) as job}
33
+ {#each jobs.slice(0, 1000) as job}
34
34
  <div class="flex">
35
35
  <a
36
36
  target="_blank"
@@ -20,7 +20,6 @@ export let activeLabel;
20
20
  export let isSelectingJobsToCancel = false;
21
21
  let scheduleEditor;
22
22
  $: isExternal = job && job.id === '-';
23
- let triggeredByWidth = 0;
24
23
  function isJobCancelable(j) {
25
24
  return j.type === 'QueuedJob' && !j.schedule_path;
26
25
  }
@@ -132,6 +131,7 @@ function isJobCancelable(j) {
132
131
  {job.script_path}
133
132
  </a>
134
133
  <Button
134
+ title="Filter by path"
135
135
  size="xs2"
136
136
  color="light"
137
137
  on:click={() => {
@@ -143,6 +143,7 @@ function isJobCancelable(j) {
143
143
  {/if}
144
144
  {#if job.script_path?.startsWith('f/')}
145
145
  <Button
146
+ title="Filter by folder"
146
147
  size="xs2"
147
148
  color="light"
148
149
  on:click={() => {
@@ -218,7 +219,7 @@ function isJobCancelable(j) {
218
219
  {/if}
219
220
  </div>
220
221
  {/if}
221
- <div class="w-3/12 flex justify-start" bind:clientWidth={triggeredByWidth}>
222
+ <div class="w-3/12 flex justify-start">
222
223
  {#if job && job.schedule_path}
223
224
  <div class="flex flex-row items-center gap-1">
224
225
  <Calendar size={14} />
@@ -228,13 +229,19 @@ function isJobCancelable(j) {
228
229
  btnClasses="font-normal"
229
230
  on:click={() => scheduleEditor?.openEdit(job.schedule_path ?? '', job.job_kind == 'flow')}
230
231
  >
231
- <div
232
- class="truncate text-ellipsis text-left"
233
- style="max-width: {triggeredByWidth - 48}px"
234
- >
235
- {job.schedule_path}
232
+ <div class="truncate text-ellipsis text-left">
233
+ {truncateRev(job.schedule_path, 20)}
236
234
  </div>
237
235
  </Button>
236
+ <Button
237
+ size="xs2"
238
+ color="light"
239
+ on:click={() => {
240
+ dispatch('filterBySchedule', job.schedule_path)
241
+ }}
242
+ >
243
+ <ListFilter size={10} />
244
+ </Button>
238
245
  </div>
239
246
  {:else}
240
247
  <div class="flex flex-row gap-1 items-center">
@@ -14,6 +14,7 @@ declare const __propDef: {
14
14
  filterByPath: CustomEvent<any>;
15
15
  filterByFolder: CustomEvent<any>;
16
16
  filterByLabel: CustomEvent<any>;
17
+ filterBySchedule: CustomEvent<any>;
17
18
  filterByUser: CustomEvent<any>;
18
19
  } & {
19
20
  [evt: string]: CustomEvent<any>;
@@ -3,7 +3,7 @@ import ToggleButton from '../common/toggleButton-v2/ToggleButton.svelte';
3
3
  import ToggleButtonGroup from '../common/toggleButton-v2/ToggleButtonGroup.svelte';
4
4
  import Tooltip from '../Tooltip.svelte';
5
5
  import AutoComplete from 'simple-svelte-autocomplete';
6
- import { AlertCircle, CheckCircle2, ChevronDown, Filter, PlayCircle, X } from 'lucide-svelte';
6
+ import { AlertCircle, CheckCircle2, ChevronDown, Filter, Hourglass, PlayCircle, X } from 'lucide-svelte';
7
7
  import JsonEditor from '../apps/editor/settingsPanel/inputEditor/JsonEditor.svelte';
8
8
  import Toggle from '../Toggle.svelte';
9
9
  import Label from '../Label.svelte';
@@ -27,6 +27,7 @@ export let jobKindsCat;
27
27
  export let user = null;
28
28
  export let folder = null;
29
29
  export let mobile = false;
30
+ export let schedulePath;
30
31
  // Autocomplete data
31
32
  export let paths = [];
32
33
  export let usernames = [];
@@ -35,42 +36,49 @@ export let allWorkspaces = false;
35
36
  $: displayedLabel = label;
36
37
  $: displayedConcurrencyKey = concurrencyKey;
37
38
  $: displayedTag = tag;
39
+ $: displayedSchedule = schedulePath;
38
40
  let copyArgFilter = argFilter;
39
41
  let copyResultFilter = resultFilter;
40
42
  export let filterBy = 'path';
41
43
  const dispatch = createEventDispatcher();
42
- let manuallySet = false;
43
- $: {
44
+ let autoSet = false;
45
+ $: (path || user || folder || label || concurrencyKey || tag || schedulePath) && autosetFilter();
46
+ function autosetFilter() {
44
47
  if (path !== null && path !== '' && filterBy !== 'path') {
45
- manuallySet = true;
48
+ autoSet = true;
46
49
  filterBy = 'path';
47
50
  }
48
51
  else if (user !== null && user !== '' && filterBy !== 'user') {
49
- manuallySet = true;
52
+ autoSet = true;
50
53
  filterBy = 'user';
51
54
  }
52
55
  else if (folder !== null && folder !== '' && filterBy !== 'folder') {
53
- manuallySet = true;
56
+ autoSet = true;
54
57
  filterBy = 'folder';
55
58
  }
56
59
  else if (label !== null && label !== '' && filterBy !== 'label') {
57
- manuallySet = true;
60
+ autoSet = true;
58
61
  filterBy = 'label';
59
62
  }
60
63
  else if (concurrencyKey !== null && concurrencyKey !== '' && filterBy !== 'concurrencyKey') {
61
- manuallySet = true;
64
+ autoSet = true;
62
65
  filterBy = 'concurrencyKey';
63
66
  }
64
67
  else if (tag !== null && tag !== '' && filterBy !== 'tag') {
65
- manuallySet = true;
68
+ autoSet = true;
66
69
  filterBy = 'tag';
67
70
  }
71
+ else if (schedulePath !== undefined && schedulePath !== '' && filterBy !== 'schedulePath') {
72
+ autoSet = true;
73
+ filterBy = 'schedulePath';
74
+ }
68
75
  }
69
76
  let labelTimeout = undefined;
70
77
  let concurrencyKeyTimeout = undefined;
71
78
  let tagTimeout = undefined;
72
79
  </script>
73
-
80
+ {autoSet}
81
+ {filterBy}
74
82
  <div class="flex gap-4">
75
83
  {#if !mobile}
76
84
  <div class="flex gap-2">
@@ -89,15 +97,16 @@ let tagTimeout = undefined;
89
97
  <ToggleButtonGroup
90
98
  bind:selected={filterBy}
91
99
  on:selected={() => {
92
- if (!manuallySet) {
100
+ if (!autoSet) {
93
101
  path = null
94
102
  user = null
95
103
  folder = null
96
104
  label = null
97
105
  concurrencyKey = null
98
106
  tag = null
107
+ schedulePath = undefined
99
108
  } else {
100
- manuallySet = false
109
+ autoSet = false
101
110
  }
102
111
  }}
103
112
  >
@@ -106,7 +115,8 @@ let tagTimeout = undefined;
106
115
  <ToggleButton value="folder" label="Folder" />
107
116
  <ToggleButtonMore
108
117
  togglableItems={[
109
- { label: 'Concurrency key', value: 'concurrencyKey' },
118
+ { label: 'Schedule Path', value: 'schedulePath' },
119
+ { label: 'Concurrency Key', value: 'concurrencyKey' },
110
120
  { label: 'Label', value: 'label' },
111
121
  { label: 'Tag', value: 'tag' }
112
122
  ]}
@@ -331,6 +341,39 @@ let tagTimeout = undefined;
331
341
  />
332
342
  </div>
333
343
  {/key}
344
+ {:else if filterBy === 'schedulePath'}
345
+ {#key tag}
346
+ <div class="relative">
347
+ {#if tag}
348
+ <button
349
+ class="absolute top-2 right-2 z-50"
350
+ on:click={() => {
351
+ schedulePath = undefined
352
+ dispatch('reset')
353
+ }}
354
+ >
355
+ <X size={14} />
356
+ </button>
357
+ {/if}
358
+ <span class="text-xs absolute -top-4"> Schedule Path </span>
359
+
360
+ <input
361
+ autofocus
362
+ type="text"
363
+ class="!h-[32px] py-1 !text-xs !w-64"
364
+ bind:value={displayedSchedule}
365
+ on:keydown={(e) => {
366
+ if (tagTimeout) {
367
+ clearTimeout(tagTimeout)
368
+ }
369
+
370
+ tagTimeout = setTimeout(() => {
371
+ schedulePath = displayedSchedule
372
+ }, 1000)
373
+ }}
374
+ />
375
+ </div>
376
+ {/key}
334
377
  {/if}
335
378
  </div>
336
379
  <div class="relative">
@@ -388,6 +431,23 @@ let tagTimeout = undefined;
388
431
  icon={AlertCircle}
389
432
  iconProps={{ color: success === 'failure' ? 'red' : 'gray' }}
390
433
  />
434
+ {#if success == 'waiting'}
435
+ <ToggleButton
436
+ value={'waiting'}
437
+ tooltip="Waiting"
438
+ class="whitespace-nowrap"
439
+ icon={Hourglass}
440
+ iconProps={{ color: 'blue'}}
441
+ />
442
+ {:else if success == 'suspended'}
443
+ <ToggleButton
444
+ value={'suspended'}
445
+ tooltip="Suspended"
446
+ class="whitespace-nowrap"
447
+ icon={Hourglass}
448
+ iconProps={{ color: 'blue'}}
449
+ />
450
+ {/if}
391
451
  </ToggleButtonGroup>
392
452
  </div>
393
453
  {/if}
@@ -414,24 +474,27 @@ let tagTimeout = undefined;
414
474
  <ToggleButtonGroup
415
475
  bind:selected={filterBy}
416
476
  on:selected={() => {
417
- if (!manuallySet) {
477
+ if (!autoSet) {
418
478
  path = null
419
479
  user = null
420
480
  folder = null
421
481
  label = null
422
482
  concurrencyKey = null
423
483
  tag = null
484
+ schedulePath = undefined
424
485
  } else {
425
- manuallySet = false
486
+ autoSet = false
426
487
  }
427
488
  }}
428
489
  >
429
490
  <ToggleButton value="path" label="Path" />
430
491
  <ToggleButton value="user" label="User" />
431
492
  <ToggleButton value="folder" label="Folder" />
493
+ <ToggleButton value="schedulePath" label="Schedule" />
432
494
  <ToggleButton value="concurrencyKey" label="Concurrency" />
433
495
  <ToggleButton value="tag" label="Tag" />
434
496
  <ToggleButton value="label" label="Label" />
497
+
435
498
  </ToggleButtonGroup>
436
499
  </Label>
437
500
 
@@ -5,7 +5,7 @@ declare const __propDef: {
5
5
  label?: string | null | undefined;
6
6
  concurrencyKey?: string | null | undefined;
7
7
  tag?: string | null | undefined;
8
- success?: 'running' | 'success' | 'failure' | undefined;
8
+ success?: 'running' | 'waiting' | 'suspended' | 'queued' | 'success' | 'failure' | undefined;
9
9
  isSkipped?: boolean | undefined;
10
10
  argFilter: string;
11
11
  argError: string;
@@ -15,11 +15,12 @@ declare const __propDef: {
15
15
  user?: string | null | undefined;
16
16
  folder?: string | null | undefined;
17
17
  mobile?: boolean | undefined;
18
+ schedulePath: string | undefined;
18
19
  paths?: string[] | undefined;
19
20
  usernames?: string[] | undefined;
20
21
  folders?: string[] | undefined;
21
22
  allWorkspaces?: boolean | undefined;
22
- filterBy?: "path" | "tag" | "folder" | "user" | "label" | "concurrencyKey" | undefined;
23
+ filterBy?: "path" | "tag" | "folder" | "user" | "label" | "concurrencyKey" | "schedulePath" | undefined;
23
24
  };
24
25
  events: {
25
26
  reset: CustomEvent<any>;
@@ -1,20 +1,32 @@
1
- <script>import QueuePopover from './QueuePopover.svelte';
2
- import Popup from '../common/popup/Popup.svelte';
1
+
2
+
3
+ <script>import { createEventDispatcher } from 'svelte';
4
+ import { Button } from '../common';
5
+ import { FilterX, ListFilter } from 'lucide-svelte';
6
+ import Tooltip from '../Tooltip.svelte';
3
7
  export let queue_count = undefined;
4
- export let allWorkspaces = false;
8
+ export let suspended_count = undefined;
9
+ export let success;
10
+ const dispatch = createEventDispatcher();
5
11
  </script>
6
12
 
7
13
  <div class="flex gap-1 relative max-w-36 min-w-[50px] items-baseline">
8
- <div class="text-xs absolute -top-4 truncate">Jobs waiting for a worker</div>
14
+ <div class="text-xs absolute -top-4 truncate flex items-baseline gap-1">Waiting for workers <Tooltip small>Jobs waiting for a worker being available to be executed</Tooltip></div>
9
15
  <div class="mt-1">{queue_count ? ($queue_count ?? 0).toFixed(0) : '...'}</div>
10
- <div class="truncate text-2xs text-blue-400">
16
+ <div class="truncate text-2xs !text-secondary mt-0.5">
11
17
  {#if queue_count && ($queue_count ?? 0) > 0}
12
- <Popup>
13
- <svelte:fragment slot="button">
14
- <span class="text-2xs truncate">jobs</span>
15
- </svelte:fragment>
16
- <QueuePopover {allWorkspaces} />
17
- </Popup>
18
+ <Button size="xs2" color="light" on:click={() => dispatch('jobs_waiting')}>{#if success == 'waiting'}<FilterX size={12}></FilterX>{:else}<ListFilter size={12}></ListFilter>{/if}</Button>
18
19
  {/if}
20
+
19
21
  </div>
20
22
  </div>
23
+
24
+ {#if suspended_count && ($suspended_count ?? 0) > 0}
25
+ <div class="flex gap-1 relative max-w-36 min-w-[50px] items-baseline ml-20 mr-8">
26
+ <div class="text-xs absolute -top-4 truncate flex items-baseline gap-1">Suspended <Tooltip small>Jobs waiting for an event or approval before being resumed</Tooltip></div>
27
+ <div class="mt-1">{suspended_count ? ($suspended_count ?? 0).toFixed(0) : '...'}</div>
28
+ <div class="truncate text-2xs !text-secondary mt-0.5">
29
+ <Button size="xs2" color="light" on:click={() => dispatch('jobs_suspended')}>{#if success == 'waiting'}<FilterX size={12}></FilterX>{:else}<ListFilter size={12}></ListFilter>{/if}</Button>
30
+ </div>
31
+ </div>
32
+ {/if}
@@ -3,9 +3,13 @@ import type { Tweened } from 'svelte/motion';
3
3
  declare const __propDef: {
4
4
  props: {
5
5
  queue_count?: Tweened<number> | undefined;
6
- allWorkspaces?: boolean | undefined;
6
+ suspended_count?: Tweened<number> | undefined;
7
+ success: string | undefined;
7
8
  };
8
9
  events: {
10
+ jobs_waiting: CustomEvent<any>;
11
+ jobs_suspended: CustomEvent<any>;
12
+ } & {
9
13
  [evt: string]: CustomEvent<any>;
10
14
  };
11
15
  slots: {};