diff --git a/frontend/src/components/dialog.ts b/frontend/src/components/dialog.ts index 84d8cd82..57dd58e8 100644 --- a/frontend/src/components/dialog.ts +++ b/frontend/src/components/dialog.ts @@ -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 + * 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); + } + `, + ]; } diff --git a/frontend/src/pages/org/components/file-uploader.ts b/frontend/src/pages/org/components/file-uploader.ts index 43e24027..3165b156 100644 --- a/frontend/src/pages/org/components/file-uploader.ts +++ b/frontend/src/pages/org/components/file-uploader.ts @@ -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 ArchiveView Item `), variant: "success", icon: "check2-circle", diff --git a/frontend/src/pages/org/crawls-list.ts b/frontend/src/pages/org/crawls-list.ts index cec5a52e..08ea3fca 100644 --- a/frontend/src/pages/org/crawls-list.ts +++ b/frontend/src/pages/org/crawls-list.ts @@ -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> = {}; @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 } > + (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." + ) + )} +
+ ${msg("Cancel")} + { + this.isDeletingItem = false; + if (this.itemToDelete) { + await this.deleteItem(this.itemToDelete); + } + }} + >${msg( + str`Delete ${ + this.itemToDelete?.type === "upload" + ? msg("Upload") + : msg("Crawl") + }` + )} +
+
`; } @@ -504,7 +542,7 @@ export class CrawlsList extends LiteElement { this.deleteItem(item)} + @click=${() => this.confirmDeleteItem(item)} > ${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.` ); diff --git a/frontend/src/pages/org/workflow-detail.ts b/frontend/src/pages/org/workflow-detail.ts index b54a4168..9e12732f 100644 --- a/frontend/src/pages/org/workflow-detail.ts +++ b/frontend/src/pages/org/workflow-detail.ts @@ -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> = {}; @@ -321,8 +324,9 @@ export class WorkflowDetail extends LiteElement {
(this.openDialogName = undefined)} - >Keep Crawling${msg("Keep Crawling")} Stop Crawling${msg("Stop Crawling")}
@@ -349,8 +353,9 @@ export class WorkflowDetail extends LiteElement {
(this.openDialogName = undefined)} - >Keep Crawling${msg("Keep Crawling")} Cancel & Discard Crawl${msg("Cancel & Discard Crawl")} +
+ + (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." + )} +
+ (this.openDialogName = undefined)} + >${msg("Cancel")} + { + this.openDialogName = undefined; + if (this.crawlToDelete) { + await this.deleteCrawl(this.crawlToDelete); + } + }} + >${msg("Delete Crawl")}
@@ -855,7 +890,7 @@ export class WorkflowDetail extends LiteElement { () => html` this.deleteCrawl(crawl)} + @click=${() => this.confirmDeleteCrawl(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) { 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.` ); diff --git a/frontend/src/theme.ts b/frontend/src/theme.ts index 7231f3ee..c57c5c34 100644 --- a/frontend/src/theme.ts +++ b/frontend/src/theme.ts @@ -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