Skip to content

Commit 6a5e070

Browse files
authored
fix: Allow deleting workflows without any crawls (#2285)
- Uses crawl count to determine whether workflow can be deleted instead of last crawl ID - Display delete confirmation dialog when trying to delete a workflow
1 parent 1260aec commit 6a5e070

File tree

3 files changed

+118
-18
lines changed

3 files changed

+118
-18
lines changed

frontend/src/pages/org/workflow-detail.ts

Lines changed: 44 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ import type { CrawlLog } from "@/features/archived-items/crawl-logs";
1818
import { CrawlStatus } from "@/features/archived-items/crawl-status";
1919
import { ExclusionEditor } from "@/features/crawl-workflows/exclusion-editor";
2020
import { pageNav, type Breadcrumb } from "@/layouts/pageHeader";
21+
import { deleteConfirmation } from "@/strings/ui";
2122
import type { APIPaginatedList } from "@/types/api";
2223
import { type CrawlState } from "@/types/crawlState";
2324
import { isApiError } from "@/utils/api";
@@ -54,7 +55,13 @@ export class WorkflowDetail extends BtrixElement {
5455
isCrawler!: boolean;
5556

5657
@property({ type: String })
57-
openDialogName?: "scale" | "exclusions" | "cancel" | "stop" | "delete";
58+
openDialogName?:
59+
| "scale"
60+
| "exclusions"
61+
| "cancel"
62+
| "stop"
63+
| "delete"
64+
| "deleteCrawl";
5865

5966
@property({ type: String })
6067
initialActivePanel?: Tab;
@@ -255,14 +262,14 @@ export class WorkflowDetail extends BtrixElement {
255262
render() {
256263
if (this.isEditing && this.isCrawler) {
257264
return html`
258-
<div class="grid grid-cols-1 gap-7">
265+
<div class="grid grid-cols-1 gap-7 pb-7">
259266
${when(this.workflow, this.renderEditor)}
260267
</div>
261268
`;
262269
}
263270

264271
return html`
265-
<div class="grid grid-cols-1 gap-7">
272+
<div class="grid grid-cols-1 gap-7 pb-7">
266273
<div class="col-span-1">${this.renderBreadcrumbs()}</div>
267274
268275
<div>
@@ -355,7 +362,7 @@ export class WorkflowDetail extends BtrixElement {
355362
</btrix-dialog>
356363
<btrix-dialog
357364
.label=${msg("Delete Crawl?")}
358-
.open=${this.openDialogName === "delete"}
365+
.open=${this.openDialogName === "deleteCrawl"}
359366
@sl-request-close=${() => (this.openDialogName = undefined)}
360367
@sl-show=${this.showDialog}
361368
@sl-after-hide=${() => (this.isDialogVisible = false)}
@@ -392,6 +399,32 @@ export class WorkflowDetail extends BtrixElement {
392399
>
393400
${this.isDialogVisible ? this.renderEditScale() : ""}
394401
</btrix-dialog>
402+
<btrix-dialog
403+
.label=${msg("Delete Workflow?")}
404+
.open=${this.openDialogName === "delete"}
405+
@sl-request-close=${() => (this.openDialogName = undefined)}
406+
@sl-show=${this.showDialog}
407+
@sl-after-hide=${() => (this.isDialogVisible = false)}
408+
>
409+
${deleteConfirmation(this.renderName())}
410+
<div slot="footer" class="flex justify-between">
411+
<sl-button
412+
size="small"
413+
.autofocus=${true}
414+
@click=${() => (this.openDialogName = undefined)}
415+
>${msg("Cancel")}</sl-button
416+
>
417+
<sl-button
418+
size="small"
419+
variant="danger"
420+
@click=${async () => {
421+
void this.delete();
422+
this.openDialogName = undefined;
423+
}}
424+
>${msg("Delete Workflow")}</sl-button
425+
>
426+
</div>
427+
</btrix-dialog>
395428
`;
396429
}
397430

@@ -736,12 +769,12 @@ export class WorkflowDetail extends BtrixElement {
736769
${msg("Duplicate Workflow")}
737770
</sl-menu-item>
738771
${when(
739-
!this.lastCrawlId,
772+
!workflow.crawlCount,
740773
() => html`
741774
<sl-divider></sl-divider>
742775
<sl-menu-item
743776
style="--sl-color-neutral-700: var(--danger)"
744-
@click=${() => void this.delete()}
777+
@click=${() => (this.openDialogName = "delete")}
745778
>
746779
<sl-icon name="trash3" slot="prefix"></sl-icon>
747780
${msg("Delete Workflow")}
@@ -842,7 +875,7 @@ export class WorkflowDetail extends BtrixElement {
842875

843876
private renderCrawls() {
844877
return html`
845-
<section>
878+
<section class="h-56 min-h-max">
846879
<div
847880
class="mb-3 flex items-center justify-end rounded-lg border bg-neutral-50 p-4"
848881
>
@@ -1643,7 +1676,7 @@ export class WorkflowDetail extends BtrixElement {
16431676

16441677
private readonly confirmDeleteCrawl = (crawl: Crawl) => {
16451678
this.crawlToDelete = crawl;
1646-
this.openDialogName = "delete";
1679+
this.openDialogName = "deleteCrawl";
16471680
};
16481681

16491682
private async deleteCrawl(crawl: Crawl) {
@@ -1666,6 +1699,9 @@ export class WorkflowDetail extends BtrixElement {
16661699
id: "archived-item-delete-status",
16671700
});
16681701
void this.fetchCrawls();
1702+
1703+
// Update crawl count
1704+
void this.fetchWorkflow();
16691705
} catch (e) {
16701706
if (this.crawlToDelete) {
16711707
this.confirmDeleteCrawl(this.crawlToDelete);

frontend/src/pages/org/workflows-list.ts

Lines changed: 65 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,11 @@
11
import { localized, msg, str } from "@lit/localize";
2-
import type { SlCheckbox, SlSelectEvent } from "@shoelace-style/shoelace";
2+
import type {
3+
SlCheckbox,
4+
SlDialog,
5+
SlSelectEvent,
6+
} from "@shoelace-style/shoelace";
37
import { html, type PropertyValues } from "lit";
4-
import { customElement, state } from "lit/decorators.js";
8+
import { customElement, query, state } from "lit/decorators.js";
59
import { ifDefined } from "lit/directives/if-defined.js";
610
import { when } from "lit/directives/when.js";
711
import queryString from "query-string";
@@ -21,6 +25,7 @@ import { type SelectEvent } from "@/components/ui/search-combobox";
2125
import type { SelectJobTypeEvent } from "@/features/crawl-workflows/new-workflow-dialog";
2226
import { pageHeader } from "@/layouts/pageHeader";
2327
import scopeTypeLabels from "@/strings/crawl-workflows/scopeType";
28+
import { deleteConfirmation } from "@/strings/ui";
2429
import type { APIPaginatedList, APIPaginationQuery } from "@/types/api";
2530
import { NewWorkflowOnlyScopeType } from "@/types/workflow";
2631
import { isApiError } from "@/utils/api";
@@ -91,6 +96,9 @@ export class WorkflowsList extends BtrixElement {
9196
@state()
9297
private fetchErrorStatusCode?: number;
9398

99+
@state()
100+
private workflowToDelete?: ListWorkflow;
101+
94102
@state()
95103
private orderBy: {
96104
field: SortField;
@@ -106,6 +114,9 @@ export class WorkflowsList extends BtrixElement {
106114
@state()
107115
private filterByCurrentUser = false;
108116

117+
@query("#deleteDialog")
118+
private readonly deleteDialog?: SlDialog | null;
119+
109120
// For fuzzy search:
110121
private readonly searchKeys = ["name", "firstSeed"];
111122

@@ -311,12 +322,52 @@ export class WorkflowsList extends BtrixElement {
311322
</btrix-alert>
312323
</div>
313324
`,
314-
() =>
315-
this.workflows
316-
? this.workflows.total
317-
? this.renderWorkflowList()
318-
: this.renderEmptyState()
319-
: this.renderLoading(),
325+
() => html`
326+
<div class="pb-10">
327+
${this.workflows
328+
? this.workflows.total
329+
? this.renderWorkflowList()
330+
: this.renderEmptyState()
331+
: this.renderLoading()}
332+
</div>
333+
`,
334+
)}
335+
${this.renderDialogs()}
336+
`;
337+
}
338+
339+
private renderDialogs() {
340+
return html`
341+
${when(
342+
this.workflowToDelete,
343+
(workflow) => html`
344+
<btrix-dialog id="deleteDialog" .label=${msg("Delete Workflow?")}>
345+
${deleteConfirmation(this.renderName(workflow))}
346+
<div slot="footer" class="flex justify-between">
347+
<sl-button
348+
size="small"
349+
.autofocus=${true}
350+
@click=${() => void this.deleteDialog?.hide()}
351+
>${msg("Cancel")}</sl-button
352+
>
353+
<sl-button
354+
size="small"
355+
variant="danger"
356+
@click=${async () => {
357+
void this.deleteDialog?.hide();
358+
359+
try {
360+
await this.delete(workflow);
361+
this.workflowToDelete = undefined;
362+
} catch {
363+
void this.deleteDialog?.show();
364+
}
365+
}}
366+
>${msg("Delete Workflow")}</sl-button
367+
>
368+
</div>
369+
</btrix-dialog>
370+
`,
320371
)}
321372
`;
322373
}
@@ -593,12 +644,16 @@ export class WorkflowsList extends BtrixElement {
593644
${msg("Duplicate Workflow")}
594645
</sl-menu-item>
595646
${when(
596-
!workflow.lastCrawlId,
647+
!workflow.crawlCount,
597648
() => html`
598649
<sl-divider></sl-divider>
599650
<sl-menu-item
600651
style="--sl-color-neutral-700: var(--danger)"
601-
@click=${() => void this.delete(workflow)}
652+
@click=${async () => {
653+
this.workflowToDelete = workflow;
654+
await this.updateComplete;
655+
void this.deleteDialog?.show();
656+
}}
602657
>
603658
<sl-icon name="trash3" slot="prefix"></sl-icon>
604659
${msg("Delete Workflow")}

frontend/src/strings/ui.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
import { msg } from "@lit/localize";
2+
import { html, type TemplateResult } from "lit";
3+
4+
// TODO Refactor all generic confirmation messages to use utility
5+
export const deleteConfirmation = (name: string | TemplateResult) =>
6+
msg(html`
7+
Are you sure you want to delete
8+
<strong class="font-semibold">${name}</strong>?
9+
`);

0 commit comments

Comments
 (0)