Prompt user to confirm workflow crawl deletion (#1401)

- Adds confirmation dialog for workflow crawls
- Changes archived item confirmation from default browser dialog to
shoelace dialog
- Increase dialog title size
- Out of scope: Localizes other workflow detail confirmation buttons
- Out of scope: Reword missed "Archive" reference in file uploader
This commit is contained in:
sua yoo 2023-11-22 12:40:49 -08:00 committed by GitHub
parent d64def00c2
commit 006ce5a013
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 137 additions and 42 deletions

View File

@ -1,40 +1,48 @@
import { css } from "lit";
import SLDialog from "@shoelace-style/shoelace/dist/components/dialog/dialog.js";
import SlDialog from "@shoelace-style/shoelace/dist/components/dialog/dialog.js";
import dialogStyles from "@shoelace-style/shoelace/dist/components/dialog/dialog.styles.js";
import { customElement } from "lit/decorators.js";
/**
* Customized <sl-dialog>
* <sl-dialog> with custom CSS
*
* Usage: see https://shoelace.style/components/dialog
*/
@customElement("btrix-dialog")
export class Dialog extends SLDialog {
static styles = css`
${dialogStyles} .dialog__panel {
overflow: hidden;
}
export class Dialog extends SlDialog {
static styles = [
dialogStyles,
css`
.dialog__panel {
overflow: hidden;
}
.dialog__header {
background-color: var(--sl-color-neutral-50);
border-bottom: 1px solid var(--sl-color-neutral-100);
}
.dialog__header {
background-color: var(--sl-color-neutral-50);
border-bottom: 1px solid var(--sl-color-neutral-100);
}
.dialog__title {
padding-top: var(--sl-spacing-small);
padding-bottom: var(--sl-spacing-small);
font-size: var(--sl-font-size-medium);
font-weight: var(--sl-font-weight-medium);
}
.dialog__title {
padding-top: calc(var(--sl-spacing-small) + 0.2rem);
padding-bottom: var(--sl-spacing-small);
font-size: var(--font-size-base);
font-weight: var(--sl-font-weight-medium);
line-height: 1;
}
.dialog__close {
--header-spacing: var(--sl-spacing-2x-small);
}
.dialog__close {
--header-spacing: var(--sl-spacing-x-small);
}
.dialog__footer {
padding-top: var(--sl-spacing-small);
padding-bottom: var(--sl-spacing-small);
border-top: 1px solid var(--sl-color-neutral-100);
}
`;
.dialog__body {
line-height: var(--sl-line-height-normal);
}
.dialog__footer {
padding-top: var(--sl-spacing-small);
padding-bottom: var(--sl-spacing-small);
border-top: 1px solid var(--sl-color-neutral-100);
}
`,
];
}

View File

@ -454,7 +454,7 @@ export class FileUploader extends LiteElement {
class="underline hover:no-underline"
href="${this.orgBasePath}/items/upload/${data.id}"
@click="${this.navLink.bind(this)}"
>View Archive</a
>View Item</a
> `),
variant: "success",
icon: "check2-circle",

View File

@ -10,7 +10,7 @@ import { CrawlStatus } from "../../components/crawl-status";
import type { PageChangeEvent } from "../../components/pagination";
import type { AuthState } from "../../utils/AuthService";
import LiteElement, { html } from "../../utils/LiteElement";
import type { Crawl, CrawlState, Workflow, WorkflowParams } from "./types";
import type { Crawl, CrawlState, Workflow, Upload } from "./types";
import type { APIPaginatedList, APIPaginationQuery } from "../../types/api";
import {
isActive,
@ -97,11 +97,17 @@ export class CrawlsList extends LiteElement {
private filterBy: Partial<Record<keyof Crawl, any>> = {};
@state()
private itemToEdit: Crawl | null = null;
private itemToEdit: Crawl | Upload | null = null;
@state()
private isEditingItem = false;
@state()
private itemToDelete: Crawl | Upload | null = null;
@state()
private isDeletingItem = false;
@state()
private isUploadingArchive = false;
@ -439,6 +445,38 @@ export class CrawlsList extends LiteElement {
/* TODO fetch current page or single crawl */ this.fetchArchivedItems
}
></btrix-crawl-metadata-editor>
<btrix-dialog
label=${msg("Delete Archived Item?")}
?open=${this.isDeletingItem}
@sl-after-hide=${() => (this.isDeletingItem = false)}
>
${msg("This item will be removed from any Collection it is a part of.")}
${when(this.itemToDelete?.type === "crawl", () =>
msg(
"All files and logs associated with this item will also be deleted, and the crawl will no longer be visible in its associated Workflow."
)
)}
<div slot="footer" class="flex justify-between">
<sl-button size="small" autofocus>${msg("Cancel")}</sl-button>
<sl-button
size="small"
variant="danger"
@click=${async () => {
this.isDeletingItem = false;
if (this.itemToDelete) {
await this.deleteItem(this.itemToDelete);
}
}}
>${msg(
str`Delete ${
this.itemToDelete?.type === "upload"
? msg("Upload")
: msg("Crawl")
}`
)}</sl-button
>
</div>
</btrix-dialog>
`;
}
@ -504,7 +542,7 @@ export class CrawlsList extends LiteElement {
<sl-divider></sl-divider>
<sl-menu-item
style="--sl-color-neutral-700: var(--danger)"
@click=${() => this.deleteItem(item)}
@click=${() => this.confirmDeleteItem(item)}
>
<sl-icon name="trash3" slot="prefix"></sl-icon>
${msg("Delete Item")}
@ -658,13 +696,12 @@ export class CrawlsList extends LiteElement {
}
}
private async deleteItem(item: Crawl) {
if (
!window.confirm(msg(str`Are you sure you want to delete ${item.name}?`))
) {
return;
}
private confirmDeleteItem = (item: Crawl | Upload) => {
this.itemToDelete = item;
this.isDeletingItem = true;
};
private async deleteItem(item: Crawl | Upload) {
let apiPath;
switch (this.itemType) {
@ -691,6 +728,7 @@ export class CrawlsList extends LiteElement {
}
);
const { items, ...crawlsData } = this.archivedItems!;
this.itemToDelete = null;
this.archivedItems = {
...crawlsData,
items: items.filter((c) => c.id !== item.id),
@ -702,6 +740,9 @@ export class CrawlsList extends LiteElement {
});
this.fetchArchivedItems();
} catch (e: any) {
if (this.itemToDelete) {
this.confirmDeleteItem(this.itemToDelete);
}
let message = msg(
str`Sorry, couldn't delete archived item at this time.`
);

View File

@ -64,7 +64,7 @@ export class WorkflowDetail extends LiteElement {
isCrawler!: boolean;
@property({ type: String })
openDialogName?: "scale" | "exclusions" | "cancel" | "stop";
openDialogName?: "scale" | "exclusions" | "cancel" | "stop" | "delete";
@property({ type: String })
initialActivePanel?: Tab;
@ -107,6 +107,9 @@ export class WorkflowDetail extends LiteElement {
@state()
private isCancelingOrStoppingCrawl: boolean = false;
@state()
private crawlToDelete: Crawl | null = null;
@state()
private filterBy: Partial<Record<keyof Crawl, any>> = {};
@ -321,8 +324,9 @@ export class WorkflowDetail extends LiteElement {
<div slot="footer" class="flex justify-between">
<sl-button
size="small"
autofocus
@click=${() => (this.openDialogName = undefined)}
>Keep Crawling</sl-button
>${msg("Keep Crawling")}</sl-button
>
<sl-button
size="small"
@ -332,7 +336,7 @@ export class WorkflowDetail extends LiteElement {
await this.stop();
this.openDialogName = undefined;
}}
>Stop Crawling</sl-button
>${msg("Stop Crawling")}</sl-button
>
</div>
</btrix-dialog>
@ -349,8 +353,9 @@ export class WorkflowDetail extends LiteElement {
<div slot="footer" class="flex justify-between">
<sl-button
size="small"
autofocus
@click=${() => (this.openDialogName = undefined)}
>Keep Crawling</sl-button
>${msg("Keep Crawling")}</sl-button
>
<sl-button
size="small"
@ -360,7 +365,37 @@ export class WorkflowDetail extends LiteElement {
await this.cancel();
this.openDialogName = undefined;
}}
>Cancel & Discard Crawl</sl-button
>${msg("Cancel & Discard Crawl")}</sl-button
>
</div>
</btrix-dialog>
<btrix-dialog
label=${msg("Delete Crawl?")}
?open=${this.openDialogName === "delete"}
@sl-request-close=${() => (this.openDialogName = undefined)}
@sl-show=${this.showDialog}
@sl-after-hide=${() => (this.isDialogVisible = false)}
>
${msg(
"All files and logs associated with this crawl will also be deleted, and the crawl will be removed from any Collection it is a part of."
)}
<div slot="footer" class="flex justify-between">
<sl-button
size="small"
autofocus
@click=${() => (this.openDialogName = undefined)}
>${msg("Cancel")}</sl-button
>
<sl-button
size="small"
variant="danger"
@click=${async () => {
this.openDialogName = undefined;
if (this.crawlToDelete) {
await this.deleteCrawl(this.crawlToDelete);
}
}}
>${msg("Delete Crawl")}</sl-button
>
</div>
</btrix-dialog>
@ -855,7 +890,7 @@ export class WorkflowDetail extends LiteElement {
() => html` <sl-menu slot="menu">
<sl-menu-item
style="--sl-color-neutral-700: var(--danger)"
@click=${() => this.deleteCrawl(crawl)}
@click=${() => this.confirmDeleteCrawl(crawl)}
>
<sl-icon name="trash3" slot="prefix"></sl-icon>
${msg("Delete Crawl")}
@ -1644,6 +1679,11 @@ export class WorkflowDetail extends LiteElement {
}
}
private confirmDeleteCrawl = (crawl: Crawl) => {
this.crawlToDelete = crawl;
this.openDialogName = "delete";
};
private async deleteCrawl(crawl: Crawl) {
try {
const data = await this.apiFetch(
@ -1656,6 +1696,7 @@ export class WorkflowDetail extends LiteElement {
}),
}
);
this.crawlToDelete = null;
this.crawls = {
...this.crawls!,
items: this.crawls!.items.filter((c) => c.id !== crawl.id),
@ -1667,6 +1708,10 @@ export class WorkflowDetail extends LiteElement {
});
this.fetchCrawls();
} catch (e: any) {
if (this.crawlToDelete) {
this.confirmDeleteCrawl(this.crawlToDelete);
}
let message = msg(
str`Sorry, couldn't delete archived item at this time.`
);

View File

@ -23,6 +23,7 @@ const theme = css`
/* Custom font variables */
--font-monostyle-family: var(--sl-font-mono);
--font-monostyle-variation: "MONO" 0.51, "CASL" 0, "slnt" 0, "CRSV" 0;
--font-size-base: 1rem;
/*
* Shoelace Theme Tokens