Skip to content

Commit c6214c7

Browse files
committed
[web-console] Simplify batch actions UX by allowing all actions on selected pipelines
Signed-off-by: Karakatiza666 <bulakh.96@gmail.com>
1 parent ea0b778 commit c6214c7

File tree

3 files changed

+46
-66
lines changed

3 files changed

+46
-66
lines changed

js-packages/web-console/src/lib/components/pipelines/table/AvailableActions.svelte

Lines changed: 43 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,8 @@
88
import { usePipelineManager } from '$lib/compositions/usePipelineManager.svelte'
99
import { usePremiumFeatures } from '$lib/compositions/usePremiumFeatures.svelte'
1010
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'
1413
1514
let {
1615
pipelines,
@@ -70,49 +69,37 @@
7069
(_, p) => p
7170
)
7271
)
72+
const eligibleFor = (action: (typeof availableActions)[number]) =>
73+
selected
74+
.filter((pipeline) => statusActions(pipeline).includes(action))
75+
.map((p) => p.name)
76+
.sort()
7377
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+
)
10893
})
10994
11095
const globalDialog = useGlobalDialog()
11196
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+
})
116103
selectedPipelines = []
117104
}
118105
const { toastError } = useToast()
@@ -207,64 +194,57 @@
207194
{/snippet}
208195

209196
{#snippet clearDialog()}
197+
{@const pipelines = eligibleFor('clear')}
210198
<DeleteDialog
211199
{...deleteDialogProps(
212200
'Clear',
213201
() =>
214-
selectedPipelines.length === 1
202+
pipelines.length === 1
215203
? '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:',
219205
() => postPipelinesAction('clear'),
220-
selectedPipelines.length === 1
206+
pipelines.length === 1
221207
? 'This will delete any checkpoints of this pipeline.'
222208
: 'This will delete any checkpoints of these pipelines.',
223-
sortedSelectedPipelines.join('\n')
209+
pipelines.join('\n')
224210
)()}
225211
onClose={() => (globalDialog.dialog = null)}
226212
></DeleteDialog>
227213
{/snippet}
228214

229215
{#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')}
233217
<DeleteDialog
234218
{...deleteDialogProps(
235219
'Stop',
236220
() =>
237-
stoppablePipelines.length === 1
221+
pipelines.length === 1
238222
? '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:',
240224
() => postPipelinesAction('stop'),
241-
stoppablePipelines.length === 1
225+
pipelines.length === 1
242226
? 'The pipeline will stop processing inputs and make a checkpoint of its state.'
243227
: 'These pipelines will stop processing inputs and make checkpoints of their states.',
244-
stoppablePipelines.join('\n')
228+
pipelines.join('\n')
245229
)()}
246230
onClose={() => (globalDialog.dialog = null)}
247231
></DeleteDialog>
248232
{/snippet}
249233

250234
{#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')}
254236
<DeleteDialog
255237
{...deleteDialogProps(
256238
'Force stop',
257239
() =>
258-
stoppablePipelines.length === 1
240+
pipelines.length === 1
259241
? '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:',
263243
() => postPipelinesAction('kill'),
264-
stoppablePipelines.length === 1
244+
pipelines.length === 1
265245
? 'The pipeline will stop processing inputs without making a checkpoint, leaving only a previous one, if any.'
266246
: 'These pipelines will stop processing inputs without making checkpoints, leaving only previous ones, if any.',
267-
stoppablePipelines.join('\n')
247+
pipelines.join('\n')
268248
)()}
269249
onClose={() => (globalDialog.dialog = null)}
270250
></DeleteDialog>

js-packages/web-console/src/lib/functions/configs/felderaEndpoint.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,5 +3,5 @@ export const felderaEndpoint =
33
? // If we're running locally with `bun run dev`, we point to the
44
// backend server running on port 8080
55
// Otherwise the API and UI URL will be the same
6-
window.location.origin.replace(/:([45]173)$/, ':8080')
6+
window.location.origin.replace(/:([45]17[34])$/, ':8080')
77
: 'http://localhost:8080'

scripts/claude.sh

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
set -e
44

5-
FILES=$(git ls-tree -r --name-only claude-context | grep 'CLAUDE\.md')
6-
git checkout claude-context -- $FILES
5+
FILES=$(git ls-tree -r --name-only origin/claude-context | grep 'CLAUDE\.md')
6+
git checkout origin/claude-context -- $FILES
77
git restore --staged $FILES
88
echo "✅ Pulled Claude context files from claude-context branch."

0 commit comments

Comments
 (0)