|
8 | 8 | import { usePipelineManager } from '$lib/compositions/usePipelineManager.svelte' |
9 | 9 | import { usePremiumFeatures } from '$lib/compositions/usePremiumFeatures.svelte' |
10 | 10 | import { useToast } from '$lib/compositions/useToastNotification' |
11 | | - import { intersect2 } from '$lib/functions/common/array' |
12 | | - import { isPipelineCodeEditable, isPipelineShutdown } from '$lib/functions/pipelines/status' |
13 | | - import type { PipelineAction, PipelineThumb } from '$lib/services/pipelineManager' |
| 11 | + import { isPipelineCodeEditable } from '$lib/functions/pipelines/status' |
| 12 | + import type { PipelineThumb } from '$lib/services/pipelineManager' |
14 | 13 |
|
15 | 14 | let { |
16 | 15 | pipelines, |
|
70 | 69 | (_, p) => p |
71 | 70 | ) |
72 | 71 | ) |
| 72 | + const eligibleFor = (action: (typeof availableActions)[number]) => |
| 73 | + selected |
| 74 | + .filter((pipeline) => statusActions(pipeline).includes(action)) |
| 75 | + .map((p) => p.name) |
| 76 | + .sort() |
73 | 77 | const actions = $derived.by(() => { |
74 | | - const actions = |
75 | | - selected.length === 0 |
76 | | - ? [] |
77 | | - : selected.map(statusActions).reduce( |
78 | | - (acc, cur) => |
79 | | - intersect2( |
80 | | - acc, |
81 | | - cur, |
82 | | - (e) => e, |
83 | | - (e) => e, |
84 | | - (a) => a |
85 | | - ), |
86 | | - availableActions |
87 | | - ) |
88 | | - if ( |
89 | | - selected.length === pipelines.length && |
90 | | - !actions.includes('kill') && |
91 | | - !actions.includes('start') |
92 | | - ) { |
93 | | - // Add 'kill' action if every pipeline is selected |
94 | | - actions.splice(-2, 0, ...stop, 'kill') |
95 | | - } |
96 | | -
|
97 | | - return actions.map((action) => |
98 | | - match(action) |
99 | | - .with('start', () => btnStart) |
100 | | - .with('resume', () => btnResume) |
101 | | - .with('pause', () => btnPause) |
102 | | - .with('stop', () => btnStop) |
103 | | - .with('kill', () => btnKill) |
104 | | - .with('delete', () => btnDelete) |
105 | | - .with('clear', () => btnClear) |
106 | | - .exhaustive() |
107 | | - ) |
| 78 | + if (selected.length === 0) return [] |
| 79 | + const supportedByAny = new Set(selected.flatMap(statusActions)) |
| 80 | + return availableActions |
| 81 | + .filter((action) => supportedByAny.has(action)) |
| 82 | + .map((action) => |
| 83 | + match(action) |
| 84 | + .with('start', () => btnStart) |
| 85 | + .with('resume', () => btnResume) |
| 86 | + .with('pause', () => btnPause) |
| 87 | + .with('stop', () => btnStop) |
| 88 | + .with('kill', () => btnKill) |
| 89 | + .with('delete', () => btnDelete) |
| 90 | + .with('clear', () => btnClear) |
| 91 | + .exhaustive() |
| 92 | + ) |
108 | 93 | }) |
109 | 94 |
|
110 | 95 | const globalDialog = useGlobalDialog() |
111 | 96 | const api = usePipelineManager() |
112 | | - const postPipelinesAction = (action: PipelineAction) => { |
113 | | - selectedPipelines.forEach((pipelineName) => { |
114 | | - api.postPipelineAction(pipelineName, action) |
115 | | - }) |
| 97 | + const postPipelinesAction = (action: Exclude<(typeof availableActions)[number], 'delete'>) => { |
| 98 | + selected |
| 99 | + .filter((pipeline) => statusActions(pipeline).includes(action)) |
| 100 | + .forEach((pipeline) => { |
| 101 | + api.postPipelineAction(pipeline.name, action) |
| 102 | + }) |
116 | 103 | selectedPipelines = [] |
117 | 104 | } |
118 | 105 | const { toastError } = useToast() |
|
207 | 194 | {/snippet} |
208 | 195 |
|
209 | 196 | {#snippet clearDialog()} |
| 197 | + {@const pipelines = eligibleFor('clear')} |
210 | 198 | <DeleteDialog |
211 | 199 | {...deleteDialogProps( |
212 | 200 | 'Clear', |
213 | 201 | () => |
214 | | - selectedPipelines.length === 1 |
| 202 | + pipelines.length === 1 |
215 | 203 | ? 'You are about to clear storage of 1 pipeline:' |
216 | | - : 'You are about to clear storage of ' + |
217 | | - selectedPipelines.length.toFixed() + |
218 | | - ' pipelines:', |
| 204 | + : 'You are about to clear storage of ' + pipelines.length.toFixed() + ' pipelines:', |
219 | 205 | () => postPipelinesAction('clear'), |
220 | | - selectedPipelines.length === 1 |
| 206 | + pipelines.length === 1 |
221 | 207 | ? 'This will delete any checkpoints of this pipeline.' |
222 | 208 | : 'This will delete any checkpoints of these pipelines.', |
223 | | - sortedSelectedPipelines.join('\n') |
| 209 | + pipelines.join('\n') |
224 | 210 | )()} |
225 | 211 | onClose={() => (globalDialog.dialog = null)} |
226 | 212 | ></DeleteDialog> |
227 | 213 | {/snippet} |
228 | 214 |
|
229 | 215 | {#snippet stopDialog()} |
230 | | - {@const stoppablePipelines = sortedSelectedPipelines.filter((name) => |
231 | | - ((status) => !isPipelineShutdown(status))(selected.find((p) => p.name === name)!.status) |
232 | | - )} |
| 216 | + {@const pipelines = eligibleFor('stop')} |
233 | 217 | <DeleteDialog |
234 | 218 | {...deleteDialogProps( |
235 | 219 | 'Stop', |
236 | 220 | () => |
237 | | - stoppablePipelines.length === 1 |
| 221 | + pipelines.length === 1 |
238 | 222 | ? 'You are about to stop 1 pipeline:' |
239 | | - : 'You are about to stop ' + stoppablePipelines.length.toFixed() + ' pipelines:', |
| 223 | + : 'You are about to stop ' + pipelines.length.toFixed() + ' pipelines:', |
240 | 224 | () => postPipelinesAction('stop'), |
241 | | - stoppablePipelines.length === 1 |
| 225 | + pipelines.length === 1 |
242 | 226 | ? 'The pipeline will stop processing inputs and make a checkpoint of its state.' |
243 | 227 | : 'These pipelines will stop processing inputs and make checkpoints of their states.', |
244 | | - stoppablePipelines.join('\n') |
| 228 | + pipelines.join('\n') |
245 | 229 | )()} |
246 | 230 | onClose={() => (globalDialog.dialog = null)} |
247 | 231 | ></DeleteDialog> |
248 | 232 | {/snippet} |
249 | 233 |
|
250 | 234 | {#snippet killDialog()} |
251 | | - {@const stoppablePipelines = sortedSelectedPipelines.filter((name) => |
252 | | - ((status) => !isPipelineShutdown(status))(selected.find((p) => p.name === name)!.status) |
253 | | - )} |
| 235 | + {@const pipelines = eligibleFor('kill')} |
254 | 236 | <DeleteDialog |
255 | 237 | {...deleteDialogProps( |
256 | 238 | 'Force stop', |
257 | 239 | () => |
258 | | - stoppablePipelines.length === 1 |
| 240 | + pipelines.length === 1 |
259 | 241 | ? 'You are about to forcefully stop 1 pipeline:' |
260 | | - : 'You are about to forcefully stop ' + |
261 | | - stoppablePipelines.length.toFixed() + |
262 | | - ' pipelines:', |
| 242 | + : 'You are about to forcefully stop ' + pipelines.length.toFixed() + ' pipelines:', |
263 | 243 | () => postPipelinesAction('kill'), |
264 | | - stoppablePipelines.length === 1 |
| 244 | + pipelines.length === 1 |
265 | 245 | ? 'The pipeline will stop processing inputs without making a checkpoint, leaving only a previous one, if any.' |
266 | 246 | : 'These pipelines will stop processing inputs without making checkpoints, leaving only previous ones, if any.', |
267 | | - stoppablePipelines.join('\n') |
| 247 | + pipelines.join('\n') |
268 | 248 | )()} |
269 | 249 | onClose={() => (globalDialog.dialog = null)} |
270 | 250 | ></DeleteDialog> |
|
0 commit comments