Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions backend/btrixcloud/crawls.py
Original file line number Diff line number Diff line change
Expand Up @@ -291,6 +291,8 @@ async def list_crawls(
"qaRunCount",
"lastQAState",
"lastQAStarted",
"crawlExecSeconds",
"pageCount",
):
raise HTTPException(status_code=400, detail="invalid_sort_by")
if sort_direction not in (1, -1):
Expand Down
4 changes: 2 additions & 2 deletions frontend/docs/docs/user-guide/archived-items.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,10 @@ The status of an archived item depends on its type. Uploads will always have the
| <span class="status-success">:bootstrap-check-circle-fill: Complete</span> | The crawl completed according to the workflow's settings. Workflows with [crawl limits](workflow-setup.md#crawl-limits) set may stop running before they capture every queued page, but the resulting archived item will still be marked as "Complete". |
| <span class="status-neutral">:bootstrap-dash-square-fill: Stopped</span> | The crawl workflow was _stopped_ gracefully by a user and data is saved. |
| <span class="status-neutral">:bootstrap-exclamation-square-fill: Stopped: Reason</span> | A workflow limit (listed as the reason) was reached and data is saved. |
| <span class="status-warning">:bootstrap-x-octagon-fill: Canceled</span> | The crawl workflow was _canceled_ by a user, no data is saved. |
| <span class="status-neutral">:bootstrap-exclamation-octagon: Canceled</span> | The crawl workflow was _canceled_ by a user, no data is saved. |
| <span class="status-danger">:bootstrap-diamond-triangle-fill: Failed</span> | A serious error occurred while crawling, no data is saved.|

Because <span class="status-warning">:bootstrap-x-octagon-fill: Canceled</span> and <span class="status-danger">:bootstrap-exclamation-diamond-fill: Failed</span> crawls do not contain data, they are omitted from the archived items list page and cannot be added to a collection.
Because <span class="status-neutral">:bootstrap-exclamation-octagon: Canceled</span> and <span class="status-danger">:bootstrap-exclamation-diamond-fill: Failed</span> crawls do not contain data, they are omitted from the archived items list page and cannot be added to a collection.

## Archived Item Details

Expand Down
19 changes: 14 additions & 5 deletions frontend/src/components/ui/badge.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,9 @@ export class Badge extends TailwindElement {
@property({ type: String })
variant: BadgeVariant = "neutral";

@property({ type: String })
size?: "medium" | "large" = "medium";

@property({ type: Boolean })
outline = false;

Expand All @@ -47,15 +50,16 @@ export class Badge extends TailwindElement {
return html`
<span
class=${clsx(
tw`inline-flex min-h-4 items-center justify-center align-[1px] text-xs leading-none`,
tw`inline-flex min-h-4 items-center justify-center align-[1px] leading-none`,
this.size === "medium" && tw`text-xs`,
this.outline
? [
tw`ring-1`,
tw`mx-px ring-1`,
{
success: tw`bg-success-500 text-success-500 ring-success-500`,
success: tw`bg-success-50 text-success-700 ring-success-400`,
warning: tw`bg-warning-600 text-warning-600 ring-warning-600`,
danger: tw`bg-danger-500 text-danger-500 ring-danger-500`,
neutral: tw`bg-neutral-100 text-neutral-600 ring-neutral-600`,
neutral: tw`bg-neutral-100 text-neutral-600 ring-neutral-300`,
"high-contrast": tw`bg-neutral-600 text-neutral-0 ring-neutral-0`,
primary: tw`bg-white text-primary ring-primary`,
cyan: tw`bg-cyan-50 text-cyan-600 ring-cyan-600`,
Expand All @@ -72,7 +76,12 @@ export class Badge extends TailwindElement {
cyan: tw`bg-cyan-50 text-cyan-600`,
blue: tw`bg-blue-50 text-blue-600`,
}[this.variant],
this.pill ? tw`min-w-[1.125rem] rounded-full px-1` : tw`rounded px-2`,
this.pill
? [
tw`min-w-[1.125rem] rounded-full`,
this.size === "large" ? tw`px-1.5 py-0.5` : tw`px-1`,
]
: [tw`rounded`, this.size === "large" ? tw`px-2.5 py-1` : tw`px-2`],
)}
part="base"
>
Expand Down
7 changes: 7 additions & 0 deletions frontend/src/events/btrix-cancel.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
export type BtrixCancelEvent = CustomEvent<never>;

declare global {
interface GlobalEventHandlersEventMap {
"btrix-cancel": BtrixCancelEvent;
}
}
7 changes: 7 additions & 0 deletions frontend/src/events/btrix-confirm.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
export type BtrixConfirmEvent = CustomEvent<never>;

declare global {
interface GlobalEventHandlersEventMap {
"btrix-confirm": BtrixConfirmEvent;
}
}
4 changes: 2 additions & 2 deletions frontend/src/features/archived-items/crawl-status.ts
Original file line number Diff line number Diff line change
Expand Up @@ -308,9 +308,9 @@ export class CrawlStatus extends TailwindElement {
break;

case "canceled":
color = "var(--sl-color-orange-600)";
color = "var(--sl-color-neutral-600)";
icon = html`<sl-icon
name="x-octagon-fill"
name="x-octagon"
slot="prefix"
style="color: ${color}"
></sl-icon>`;
Expand Down
144 changes: 144 additions & 0 deletions frontend/src/features/archived-items/delete-item-dialog.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,144 @@
import { localized, msg, str } from "@lit/localize";
import { Task } from "@lit/task";
import { html } from "lit";
import { customElement, property, query } from "lit/decorators.js";
import { when } from "lit/directives/when.js";

import { BtrixElement } from "@/classes/BtrixElement";
import type { Dialog } from "@/components/ui/dialog";
import type { ArchivedItem } from "@/types/crawler";
import { isCrawl, renderName } from "@/utils/crawler";
import { pluralOf } from "@/utils/pluralize";

/**
* Confirm deletion of an archived item, crawl associated
* with an archived item, or crawl run.
*
* @slot name
*/
@customElement("btrix-delete-item-dialog")
@localized()
export class DeleteItemDialog extends BtrixElement {
@property({ type: Object })
item?: ArchivedItem;

@property({ type: Boolean })
open = false;

@query("btrix-dialog")
readonly dialog?: Dialog | null;

private readonly collectionsTask = new Task(this, {
task: async ([open, crawl], { signal }) => {
if (!crawl?.collectionIds) return;

if (!open) {
return crawl.collectionIds.map((id) => ({ id }));
}

return (await this.getCrawl(crawl.id, signal)).collections;
},
args: () => [this.open, this.item] as const,
});

render() {
return html`<btrix-dialog
.label=${this.item
? isCrawl(this.item)
? msg("Delete Crawl?")
: msg("Delete Archived Item?")
: msg("Delete")}
.open=${this.open}
>
${this.renderContent()}
</btrix-dialog>`;
}

private renderContent() {
const item = this.item;

if (!item) return;

const crawl = isCrawl(item);
const item_name = html`<slot name="name"
><strong class="font-semibold">${renderName(item)}</strong></slot
>`;

return html`
<p>
${msg(html`Are you sure you want to delete ${item_name}?`)}
${msg("All associated files and logs will be deleted.")}
</p>

${this.renderCollections()}
<div slot="footer" class="flex justify-between">
<sl-button
size="small"
.autofocus=${true}
@click=${() => {
void this.dialog?.hide();
this.dispatchEvent(new CustomEvent("btrix-cancel"));
}}
>${msg("Cancel")}</sl-button
>
<sl-button
size="small"
variant="danger"
@click=${() => {
this.dispatchEvent(new CustomEvent("btrix-confirm"));
}}
>${crawl
? msg("Delete Crawl")
: msg("Delete Archived Item")}</sl-button
>
</div>
`;
}

private renderCollections() {
if (!this.item?.collectionIds.length) return;

const { collectionIds } = this.item;
const count = collectionIds.length;

const number_of_collections = this.localize.number(count);
const plural_of_collections = pluralOf("collections", count);

return html`
<p class="my-2">
${msg(
str`The archived item will be removed from ${number_of_collections} ${plural_of_collections}:`,
)}
</p>
${this.collectionsTask.render({
pending: () =>
html`<btrix-linked-collections-list
.collections=${collectionIds.map((id) => ({ id }))}
baseUrl="${this.navigate.orgBasePath}/collections/view"
>
</btrix-linked-collections-list>`,
complete: (res) =>
when(
res,
(collections) =>
html`<btrix-linked-collections-list
.collections=${collections}
baseUrl="${this.navigate.orgBasePath}/collections/view"
>
</btrix-linked-collections-list>`,
),
})}
`;
}

private async getCrawl(id: string, signal: AbortSignal) {
const data: ArchivedItem = await this.api.fetch<ArchivedItem>(
`/orgs/${this.orgId}/crawls/${id}/replay.json`,
{
signal,
},
);

return data;
}
}
2 changes: 1 addition & 1 deletion frontend/src/features/archived-items/index.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import("./archived-item-list");
import("./archived-item-state-filter");
import("./archived-item-tag-filter");
import("./crawl-list");
import("./crawl-log-table");
import("./crawl-logs");
import("./delete-item-dialog");
import("./item-metadata-editor");
import("./crawl-pending-exclusions");
import("./crawl-queue");
Expand Down
1 change: 1 addition & 0 deletions frontend/src/features/crawl-workflows/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import("./workflow-action-menu/workflow-action-menu");
import("./workflow-editor");
import("./workflow-list");
import("./workflow-schedule-filter");
import("./workflow-search");
import("./workflow-tag-filter");
import("./workflow-profile-filter");
import("./workflow-last-crawl-state-filter");
7 changes: 6 additions & 1 deletion frontend/src/features/crawl-workflows/workflow-list.ts
Original file line number Diff line number Diff line change
Expand Up @@ -452,7 +452,12 @@ export class WorkflowListItem extends BtrixElement {
<sl-tooltip hoist placement="bottom">
<div>
<div class="detail truncate">
<span class="userName">${workflow.modifiedByName}</span>
${workflow.modifiedByName
? html`<btrix-user-chip
userId=${workflow.modifiedBy}
userName=${workflow.modifiedByName}
></btrix-user-chip>`
: notSpecified}
</div>
<div class="desc">${shortDate(workflow.modified)}</div>
</div>
Expand Down
26 changes: 26 additions & 0 deletions frontend/src/features/crawl-workflows/workflow-search.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import { localized, msg } from "@lit/localize";
import { customElement, property } from "lit/decorators.js";

import { SearchCombobox } from "@/components/ui/search-combobox";

export type SearchFields = "name" | "firstSeed";

@customElement("btrix-workflow-search")
@localized()
export class WorkflowSearch extends SearchCombobox<{ [x: string]: string }> {
static FieldLabels: Record<SearchFields, string> = {
name: msg("Name"),
firstSeed: msg("Crawl Start URL"),
};

@property({ type: Array })
searchOptions: { [x: string]: string }[] = [];

@property({ type: String })
selectedKey?: string;

readonly searchKeys = ["name", "firstSeed"];
readonly keyLabels = WorkflowSearch.FieldLabels;

placeholder = msg("Search by workflow name or crawl start URL");
}
Loading
Loading