Skip to content

Commit e91708a

Browse files
authored
Add toast instead of redirect on Start Workflow with link to workflow (#2402)
* Add toast instead of redirect on start workflow with link to workflow * Keep error alert
1 parent c2047bf commit e91708a

File tree

5 files changed

+118
-107
lines changed

5 files changed

+118
-107
lines changed

Diff for: src/lib/holocene/toaster.svelte

+9-2
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
<script lang="ts">
22
import type { Toaster } from '../stores/toaster';
33
4+
import Link from './link.svelte';
45
import ToastComponent from './toast.svelte';
56
67
export let pop: Toaster['pop'];
@@ -16,9 +17,15 @@
1617
class="fixed bottom-5 right-5 z-[99999] flex flex-col items-end gap-2"
1718
role="log"
1819
>
19-
{#each $toasts as { message, variant, id } (id)}
20+
{#each $toasts as { message, variant, id, link } (id)}
2021
<ToastComponent {closeButtonLabel} {variant} {id} on:dismiss={dismissToast}>
21-
{message}
22+
{#if link}
23+
<Link href={link}>
24+
{message}
25+
</Link>
26+
{:else}
27+
{message}
28+
{/if}
2229
</ToastComponent>
2330
{/each}
2431
</div>

Diff for: src/lib/i18n/locales/en/workflows.ts

+2-1
Original file line numberDiff line numberDiff line change
@@ -247,5 +247,6 @@ export const Strings = {
247247
'pending-workflow-task': 'Pending Workflow Task',
248248
'original-scheduled-time': 'Original Scheduled Time',
249249
'started-time': 'Started Time',
250-
'starting-workflow': 'Starting Workflow...',
250+
'start-workflow-success': 'Workflow started successfully',
251+
'start-workflow-error': 'Error starting Workflow',
251252
} as const;

Diff for: src/lib/pages/start-workflow.svelte

+105-103
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@
44
import { onMount } from 'svelte';
55
import { v4 } from 'uuid';
66
7-
import { goto } from '$app/navigation';
87
import { page } from '$app/stores';
98
109
import PayloadInput, {
@@ -15,7 +14,6 @@
1514
import Button from '$lib/holocene/button.svelte';
1615
import Input from '$lib/holocene/input/input.svelte';
1716
import Link from '$lib/holocene/link.svelte';
18-
import Loading from '$lib/holocene/loading.svelte';
1917
import { translate } from '$lib/i18n/translate';
2018
import { getPollers } from '$lib/services/pollers-service';
2119
import {
@@ -26,9 +24,11 @@
2624
customSearchAttributes,
2725
type SearchAttributeInput,
2826
} from '$lib/stores/search-attributes';
27+
import { toaster } from '$lib/stores/toaster';
2928
import { workflowsSearchParams } from '$lib/stores/workflows';
3029
import { pluralize } from '$lib/utilities/pluralize';
3130
import {
31+
routeForEventHistory,
3232
routeForTaskQueue,
3333
routeForWorkflows,
3434
} from '$lib/utilities/route-for';
@@ -37,8 +37,6 @@
3737
3838
$: ({ namespace } = $page.params);
3939
40-
let loading = false;
41-
4240
let workflowId = '';
4341
let taskQueue = '';
4442
let workflowType = '';
@@ -70,10 +68,9 @@
7068
});
7169
7270
const onWorkflowStart = async () => {
73-
loading = true;
7471
try {
7572
error = '';
76-
await startWorkflow({
73+
const { runId } = await startWorkflow({
7774
namespace,
7875
workflowId,
7976
taskQueue,
@@ -82,11 +79,22 @@
8279
encoding: $encoding,
8380
searchAttributes,
8481
});
85-
await new Promise((resolve) => setTimeout(resolve, 2000));
86-
goto(routeForWorkflows({ namespace }));
82+
toaster.push({
83+
variant: 'success',
84+
duration: 5000,
85+
message: translate('workflows.start-workflow-success'),
86+
link: routeForEventHistory({
87+
namespace,
88+
workflow: workflowId,
89+
run: runId,
90+
}),
91+
});
8792
} catch (e) {
88-
error = e?.message || 'Error starting Workflow';
89-
loading = false;
93+
error = e?.message || translate('workflows.start-workflow-error');
94+
toaster.push({
95+
variant: 'error',
96+
message: translate('workflows.start-workflow-error'),
97+
});
9098
}
9199
};
92100
@@ -161,103 +169,97 @@
161169
</script>
162170

163171
<div class="flex w-full flex-col items-center pb-24">
164-
{#if loading}
165-
<Loading title={translate('workflows.starting-workflow')} />
166-
{:else}
167-
<div class="mb-6 flex w-full items-start">
168-
<Link
169-
href={`${routeForWorkflows({
170-
namespace,
171-
})}?${$workflowsSearchParams}`}
172-
data-testid="back-to-workflows"
173-
icon="chevron-left"
172+
<div class="mb-6 flex w-full items-start">
173+
<Link
174+
href={`${routeForWorkflows({
175+
namespace,
176+
})}?${$workflowsSearchParams}`}
177+
data-testid="back-to-workflows"
178+
icon="chevron-left"
179+
>
180+
{translate('workflows.back-to-workflows')}
181+
</Link>
182+
</div>
183+
<div class="flex w-full flex-col gap-4 lg:w-2/3 2xl:w-1/2">
184+
<h1 class="mb-4 overflow-hidden" data-testid="start-workflow">
185+
Start a Workflow
186+
</h1>
187+
<div
188+
class="flex w-full flex-col items-center justify-between gap-2 md:flex-row md:gap-4"
189+
>
190+
<Input
191+
id="workflowId"
192+
required
193+
bind:value={workflowId}
194+
label="Workflow ID"
195+
class="w-full grow"
196+
on:blur={(e) => onInputChange(e, 'workflowId')}
197+
/>
198+
<Button
199+
class="mt-0 md:mt-6"
200+
variant="secondary"
201+
leadingIcon="retry"
202+
on:click={generateRandomWorkflowId}>Random UUID</Button
174203
>
175-
{translate('workflows.back-to-workflows')}
176-
</Link>
177204
</div>
178-
<div class="flex w-full flex-col gap-4 lg:w-2/3 2xl:w-1/2">
179-
<h1 class="mb-4 overflow-hidden" data-testid="start-workflow">
180-
Start a Workflow
181-
</h1>
182-
<div
183-
class="flex w-full flex-col items-center justify-between gap-2 md:flex-row md:gap-4"
184-
>
185-
<Input
186-
id="workflowId"
187-
required
188-
bind:value={workflowId}
189-
label="Workflow ID"
190-
class="w-full grow"
191-
on:blur={(e) => onInputChange(e, 'workflowId')}
192-
/>
193-
<Button
194-
class="mt-0 md:mt-6"
195-
variant="secondary"
196-
leadingIcon="retry"
197-
on:click={generateRandomWorkflowId}>Random UUID</Button
198-
>
199-
</div>
200-
<div class="flex w-full items-center justify-between gap-4">
201-
<Input
202-
id="taskQueue"
203-
required
204-
bind:value={taskQueue}
205-
label="Task Queue"
206-
class="grow"
207-
on:blur={(e) => onInputChange(e, 'taskQueue')}
208-
/>
209-
</div>
210-
{#if pollerCount !== undefined}
211-
<Alert
212-
intent={pollerCount > 0 ? 'success' : 'warning'}
213-
title={pollerCount
214-
? 'Task Queue is Active'
215-
: 'Task Queue is Inactive'}
216-
>
217-
<div class="flex w-full items-center justify-between">
218-
<p>
219-
{pollerCount}
220-
{pluralize('Worker', pollerCount)}
221-
</p>
222-
<Link
223-
href={routeForTaskQueue({ namespace, queue: taskQueue })}
224-
newTab
225-
>
226-
View Task Queue
227-
</Link>
228-
</div></Alert
229-
>
230-
{/if}
205+
<div class="flex w-full items-center justify-between gap-4">
231206
<Input
232-
id="workflowType"
207+
id="taskQueue"
233208
required
234-
bind:value={workflowType}
235-
label="Workflow Type"
236-
on:blur={(e) => onInputChange(e, 'workflowType')}
209+
bind:value={taskQueue}
210+
label="Task Queue"
211+
class="grow"
212+
on:blur={(e) => onInputChange(e, 'taskQueue')}
237213
/>
238-
{#key inputRetrieved}
239-
<PayloadInput bind:input bind:encoding />
240-
{/key}
241-
{#if viewAdvancedOptions}
242-
<AddSearchAttributes bind:attributesToAdd={searchAttributes} />
243-
{/if}
244-
<div class="mt-4 flex w-full justify-between">
245-
<Button
246-
variant="ghost"
247-
trailingIcon={viewAdvancedOptions ? 'chevron-up' : 'chevron-down'}
248-
on:click={() => (viewAdvancedOptions = !viewAdvancedOptions)}
249-
>{translate('common.more-options')}</Button
250-
>
251-
<Button
252-
disabled={!enableStart}
253-
on:click={onWorkflowStart}
254-
data-testid="start-workflow-button"
255-
>{translate('workflows.start-workflow')}</Button
256-
>
257-
</div>
258-
{#if error}
259-
<Alert intent="error" title={error} />
260-
{/if}
261214
</div>
262-
{/if}
215+
{#if pollerCount !== undefined}
216+
<Alert
217+
intent={pollerCount > 0 ? 'success' : 'warning'}
218+
title={pollerCount ? 'Task Queue is Active' : 'Task Queue is Inactive'}
219+
>
220+
<div class="flex w-full items-center justify-between">
221+
<p>
222+
{pollerCount}
223+
{pluralize('Worker', pollerCount)}
224+
</p>
225+
<Link
226+
href={routeForTaskQueue({ namespace, queue: taskQueue })}
227+
newTab
228+
>
229+
View Task Queue
230+
</Link>
231+
</div></Alert
232+
>
233+
{/if}
234+
<Input
235+
id="workflowType"
236+
required
237+
bind:value={workflowType}
238+
label="Workflow Type"
239+
on:blur={(e) => onInputChange(e, 'workflowType')}
240+
/>
241+
{#key inputRetrieved}
242+
<PayloadInput bind:input bind:encoding />
243+
{/key}
244+
{#if viewAdvancedOptions}
245+
<AddSearchAttributes bind:attributesToAdd={searchAttributes} />
246+
{/if}
247+
<div class="mt-4 flex w-full justify-between">
248+
<Button
249+
variant="ghost"
250+
trailingIcon={viewAdvancedOptions ? 'chevron-up' : 'chevron-down'}
251+
on:click={() => (viewAdvancedOptions = !viewAdvancedOptions)}
252+
>{translate('common.more-options')}</Button
253+
>
254+
<Button
255+
disabled={!enableStart}
256+
on:click={onWorkflowStart}
257+
data-testid="start-workflow-button"
258+
>{translate('workflows.start-workflow')}</Button
259+
>
260+
</div>
261+
{#if error}
262+
<Alert intent="error" title={error} />
263+
{/if}
264+
</div>
263265
</div>

Diff for: src/lib/services/workflow-service.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -500,7 +500,7 @@ export async function startWorkflow({
500500
input,
501501
encoding,
502502
searchAttributes,
503-
}: StartWorkflowOptions) {
503+
}: StartWorkflowOptions): Promise<{ runId: string }> {
504504
const route = routeForApi('workflow', {
505505
namespace,
506506
workflowId,

Diff for: src/lib/types/holocene.ts

+1
Original file line numberDiff line numberDiff line change
@@ -10,4 +10,5 @@ export interface Toast {
1010
variant?: ToastVariant;
1111
id?: string;
1212
duration?: number;
13+
link?: string;
1314
}

0 commit comments

Comments
 (0)