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:
parent
d64def00c2
commit
006ce5a013
@ -1,17 +1,19 @@
|
|||||||
import { css } from "lit";
|
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 dialogStyles from "@shoelace-style/shoelace/dist/components/dialog/dialog.styles.js";
|
||||||
import { customElement } from "lit/decorators.js";
|
import { customElement } from "lit/decorators.js";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Customized <sl-dialog>
|
* <sl-dialog> with custom CSS
|
||||||
*
|
*
|
||||||
* Usage: see https://shoelace.style/components/dialog
|
* Usage: see https://shoelace.style/components/dialog
|
||||||
*/
|
*/
|
||||||
@customElement("btrix-dialog")
|
@customElement("btrix-dialog")
|
||||||
export class Dialog extends SLDialog {
|
export class Dialog extends SlDialog {
|
||||||
static styles = css`
|
static styles = [
|
||||||
${dialogStyles} .dialog__panel {
|
dialogStyles,
|
||||||
|
css`
|
||||||
|
.dialog__panel {
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -21,14 +23,19 @@ export class Dialog extends SLDialog {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.dialog__title {
|
.dialog__title {
|
||||||
padding-top: var(--sl-spacing-small);
|
padding-top: calc(var(--sl-spacing-small) + 0.2rem);
|
||||||
padding-bottom: var(--sl-spacing-small);
|
padding-bottom: var(--sl-spacing-small);
|
||||||
font-size: var(--sl-font-size-medium);
|
font-size: var(--font-size-base);
|
||||||
font-weight: var(--sl-font-weight-medium);
|
font-weight: var(--sl-font-weight-medium);
|
||||||
|
line-height: 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
.dialog__close {
|
.dialog__close {
|
||||||
--header-spacing: var(--sl-spacing-2x-small);
|
--header-spacing: var(--sl-spacing-x-small);
|
||||||
|
}
|
||||||
|
|
||||||
|
.dialog__body {
|
||||||
|
line-height: var(--sl-line-height-normal);
|
||||||
}
|
}
|
||||||
|
|
||||||
.dialog__footer {
|
.dialog__footer {
|
||||||
@ -36,5 +43,6 @@ export class Dialog extends SLDialog {
|
|||||||
padding-bottom: var(--sl-spacing-small);
|
padding-bottom: var(--sl-spacing-small);
|
||||||
border-top: 1px solid var(--sl-color-neutral-100);
|
border-top: 1px solid var(--sl-color-neutral-100);
|
||||||
}
|
}
|
||||||
`;
|
`,
|
||||||
|
];
|
||||||
}
|
}
|
||||||
|
|||||||
@ -454,7 +454,7 @@ export class FileUploader extends LiteElement {
|
|||||||
class="underline hover:no-underline"
|
class="underline hover:no-underline"
|
||||||
href="${this.orgBasePath}/items/upload/${data.id}"
|
href="${this.orgBasePath}/items/upload/${data.id}"
|
||||||
@click="${this.navLink.bind(this)}"
|
@click="${this.navLink.bind(this)}"
|
||||||
>View Archive</a
|
>View Item</a
|
||||||
> `),
|
> `),
|
||||||
variant: "success",
|
variant: "success",
|
||||||
icon: "check2-circle",
|
icon: "check2-circle",
|
||||||
|
|||||||
@ -10,7 +10,7 @@ import { CrawlStatus } from "../../components/crawl-status";
|
|||||||
import type { PageChangeEvent } from "../../components/pagination";
|
import type { PageChangeEvent } from "../../components/pagination";
|
||||||
import type { AuthState } from "../../utils/AuthService";
|
import type { AuthState } from "../../utils/AuthService";
|
||||||
import LiteElement, { html } from "../../utils/LiteElement";
|
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 type { APIPaginatedList, APIPaginationQuery } from "../../types/api";
|
||||||
import {
|
import {
|
||||||
isActive,
|
isActive,
|
||||||
@ -97,11 +97,17 @@ export class CrawlsList extends LiteElement {
|
|||||||
private filterBy: Partial<Record<keyof Crawl, any>> = {};
|
private filterBy: Partial<Record<keyof Crawl, any>> = {};
|
||||||
|
|
||||||
@state()
|
@state()
|
||||||
private itemToEdit: Crawl | null = null;
|
private itemToEdit: Crawl | Upload | null = null;
|
||||||
|
|
||||||
@state()
|
@state()
|
||||||
private isEditingItem = false;
|
private isEditingItem = false;
|
||||||
|
|
||||||
|
@state()
|
||||||
|
private itemToDelete: Crawl | Upload | null = null;
|
||||||
|
|
||||||
|
@state()
|
||||||
|
private isDeletingItem = false;
|
||||||
|
|
||||||
@state()
|
@state()
|
||||||
private isUploadingArchive = false;
|
private isUploadingArchive = false;
|
||||||
|
|
||||||
@ -439,6 +445,38 @@ export class CrawlsList extends LiteElement {
|
|||||||
/* TODO fetch current page or single crawl */ this.fetchArchivedItems
|
/* TODO fetch current page or single crawl */ this.fetchArchivedItems
|
||||||
}
|
}
|
||||||
></btrix-crawl-metadata-editor>
|
></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-divider></sl-divider>
|
||||||
<sl-menu-item
|
<sl-menu-item
|
||||||
style="--sl-color-neutral-700: var(--danger)"
|
style="--sl-color-neutral-700: var(--danger)"
|
||||||
@click=${() => this.deleteItem(item)}
|
@click=${() => this.confirmDeleteItem(item)}
|
||||||
>
|
>
|
||||||
<sl-icon name="trash3" slot="prefix"></sl-icon>
|
<sl-icon name="trash3" slot="prefix"></sl-icon>
|
||||||
${msg("Delete Item")}
|
${msg("Delete Item")}
|
||||||
@ -658,13 +696,12 @@ export class CrawlsList extends LiteElement {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private async deleteItem(item: Crawl) {
|
private confirmDeleteItem = (item: Crawl | Upload) => {
|
||||||
if (
|
this.itemToDelete = item;
|
||||||
!window.confirm(msg(str`Are you sure you want to delete ${item.name}?`))
|
this.isDeletingItem = true;
|
||||||
) {
|
};
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
private async deleteItem(item: Crawl | Upload) {
|
||||||
let apiPath;
|
let apiPath;
|
||||||
|
|
||||||
switch (this.itemType) {
|
switch (this.itemType) {
|
||||||
@ -691,6 +728,7 @@ export class CrawlsList extends LiteElement {
|
|||||||
}
|
}
|
||||||
);
|
);
|
||||||
const { items, ...crawlsData } = this.archivedItems!;
|
const { items, ...crawlsData } = this.archivedItems!;
|
||||||
|
this.itemToDelete = null;
|
||||||
this.archivedItems = {
|
this.archivedItems = {
|
||||||
...crawlsData,
|
...crawlsData,
|
||||||
items: items.filter((c) => c.id !== item.id),
|
items: items.filter((c) => c.id !== item.id),
|
||||||
@ -702,6 +740,9 @@ export class CrawlsList extends LiteElement {
|
|||||||
});
|
});
|
||||||
this.fetchArchivedItems();
|
this.fetchArchivedItems();
|
||||||
} catch (e: any) {
|
} catch (e: any) {
|
||||||
|
if (this.itemToDelete) {
|
||||||
|
this.confirmDeleteItem(this.itemToDelete);
|
||||||
|
}
|
||||||
let message = msg(
|
let message = msg(
|
||||||
str`Sorry, couldn't delete archived item at this time.`
|
str`Sorry, couldn't delete archived item at this time.`
|
||||||
);
|
);
|
||||||
|
|||||||
@ -64,7 +64,7 @@ export class WorkflowDetail extends LiteElement {
|
|||||||
isCrawler!: boolean;
|
isCrawler!: boolean;
|
||||||
|
|
||||||
@property({ type: String })
|
@property({ type: String })
|
||||||
openDialogName?: "scale" | "exclusions" | "cancel" | "stop";
|
openDialogName?: "scale" | "exclusions" | "cancel" | "stop" | "delete";
|
||||||
|
|
||||||
@property({ type: String })
|
@property({ type: String })
|
||||||
initialActivePanel?: Tab;
|
initialActivePanel?: Tab;
|
||||||
@ -107,6 +107,9 @@ export class WorkflowDetail extends LiteElement {
|
|||||||
@state()
|
@state()
|
||||||
private isCancelingOrStoppingCrawl: boolean = false;
|
private isCancelingOrStoppingCrawl: boolean = false;
|
||||||
|
|
||||||
|
@state()
|
||||||
|
private crawlToDelete: Crawl | null = null;
|
||||||
|
|
||||||
@state()
|
@state()
|
||||||
private filterBy: Partial<Record<keyof Crawl, any>> = {};
|
private filterBy: Partial<Record<keyof Crawl, any>> = {};
|
||||||
|
|
||||||
@ -321,8 +324,9 @@ export class WorkflowDetail extends LiteElement {
|
|||||||
<div slot="footer" class="flex justify-between">
|
<div slot="footer" class="flex justify-between">
|
||||||
<sl-button
|
<sl-button
|
||||||
size="small"
|
size="small"
|
||||||
|
autofocus
|
||||||
@click=${() => (this.openDialogName = undefined)}
|
@click=${() => (this.openDialogName = undefined)}
|
||||||
>Keep Crawling</sl-button
|
>${msg("Keep Crawling")}</sl-button
|
||||||
>
|
>
|
||||||
<sl-button
|
<sl-button
|
||||||
size="small"
|
size="small"
|
||||||
@ -332,7 +336,7 @@ export class WorkflowDetail extends LiteElement {
|
|||||||
await this.stop();
|
await this.stop();
|
||||||
this.openDialogName = undefined;
|
this.openDialogName = undefined;
|
||||||
}}
|
}}
|
||||||
>Stop Crawling</sl-button
|
>${msg("Stop Crawling")}</sl-button
|
||||||
>
|
>
|
||||||
</div>
|
</div>
|
||||||
</btrix-dialog>
|
</btrix-dialog>
|
||||||
@ -349,8 +353,9 @@ export class WorkflowDetail extends LiteElement {
|
|||||||
<div slot="footer" class="flex justify-between">
|
<div slot="footer" class="flex justify-between">
|
||||||
<sl-button
|
<sl-button
|
||||||
size="small"
|
size="small"
|
||||||
|
autofocus
|
||||||
@click=${() => (this.openDialogName = undefined)}
|
@click=${() => (this.openDialogName = undefined)}
|
||||||
>Keep Crawling</sl-button
|
>${msg("Keep Crawling")}</sl-button
|
||||||
>
|
>
|
||||||
<sl-button
|
<sl-button
|
||||||
size="small"
|
size="small"
|
||||||
@ -360,7 +365,37 @@ export class WorkflowDetail extends LiteElement {
|
|||||||
await this.cancel();
|
await this.cancel();
|
||||||
this.openDialogName = undefined;
|
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>
|
</div>
|
||||||
</btrix-dialog>
|
</btrix-dialog>
|
||||||
@ -855,7 +890,7 @@ export class WorkflowDetail extends LiteElement {
|
|||||||
() => html` <sl-menu slot="menu">
|
() => html` <sl-menu slot="menu">
|
||||||
<sl-menu-item
|
<sl-menu-item
|
||||||
style="--sl-color-neutral-700: var(--danger)"
|
style="--sl-color-neutral-700: var(--danger)"
|
||||||
@click=${() => this.deleteCrawl(crawl)}
|
@click=${() => this.confirmDeleteCrawl(crawl)}
|
||||||
>
|
>
|
||||||
<sl-icon name="trash3" slot="prefix"></sl-icon>
|
<sl-icon name="trash3" slot="prefix"></sl-icon>
|
||||||
${msg("Delete Crawl")}
|
${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) {
|
private async deleteCrawl(crawl: Crawl) {
|
||||||
try {
|
try {
|
||||||
const data = await this.apiFetch(
|
const data = await this.apiFetch(
|
||||||
@ -1656,6 +1696,7 @@ export class WorkflowDetail extends LiteElement {
|
|||||||
}),
|
}),
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
this.crawlToDelete = null;
|
||||||
this.crawls = {
|
this.crawls = {
|
||||||
...this.crawls!,
|
...this.crawls!,
|
||||||
items: this.crawls!.items.filter((c) => c.id !== crawl.id),
|
items: this.crawls!.items.filter((c) => c.id !== crawl.id),
|
||||||
@ -1667,6 +1708,10 @@ export class WorkflowDetail extends LiteElement {
|
|||||||
});
|
});
|
||||||
this.fetchCrawls();
|
this.fetchCrawls();
|
||||||
} catch (e: any) {
|
} catch (e: any) {
|
||||||
|
if (this.crawlToDelete) {
|
||||||
|
this.confirmDeleteCrawl(this.crawlToDelete);
|
||||||
|
}
|
||||||
|
|
||||||
let message = msg(
|
let message = msg(
|
||||||
str`Sorry, couldn't delete archived item at this time.`
|
str`Sorry, couldn't delete archived item at this time.`
|
||||||
);
|
);
|
||||||
|
|||||||
@ -23,6 +23,7 @@ const theme = css`
|
|||||||
/* Custom font variables */
|
/* Custom font variables */
|
||||||
--font-monostyle-family: var(--sl-font-mono);
|
--font-monostyle-family: var(--sl-font-mono);
|
||||||
--font-monostyle-variation: "MONO" 0.51, "CASL" 0, "slnt" 0, "CRSV" 0;
|
--font-monostyle-variation: "MONO" 0.51, "CASL" 0, "slnt" 0, "CRSV" 0;
|
||||||
|
--font-size-base: 1rem;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Shoelace Theme Tokens
|
* Shoelace Theme Tokens
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user