Skip to content

Commit 6aa0787

Browse files
authored
feat: Move collection settings to own section (#2847)
Resolves #2840 ## Changes - Adds new "Collections" setting to workflow form, workflow settings, and archived item overview - Consistently displays collections list in workflow and archived item settings - Renames archived item "Edit Metadata" dialog - Fixes collection typing to account for collections without `created`
1 parent 40c7b6b commit 6aa0787

File tree

20 files changed

+379
-184
lines changed

20 files changed

+379
-184
lines changed

frontend/docs/docs/user-guide/workflow-setup.md

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -392,6 +392,12 @@ You can use a tool like [crontab.guru](https://crontab.guru/) to check Cron synt
392392

393393
Cron schedules are always in [UTC](https://en.wikipedia.org/wiki/Coordinated_Universal_Time).
394394

395+
## Collections
396+
397+
### Auto-Add to Collection
398+
399+
Search for and specify [collections](collection.md) that this crawl workflow should automatically add archived items to as soon as crawling finishes. Canceled and Failed crawls will not be added to collections.
400+
395401
## Metadata
396402

397403
Describe and organize your crawl workflow and the resulting archived items.
@@ -407,7 +413,3 @@ Leave optional notes about the workflow's configuration.
407413
### Tags
408414

409415
Apply tags to the workflow. Tags applied to the workflow will propagate to every crawl created with it at the time of crawl creation.
410-
411-
### Collection Auto-Add
412-
413-
Search for and specify [collections](collection.md) that this crawl workflow should automatically add archived items to as soon as crawling finishes. Canceled and Failed crawls will not be added to collections.

frontend/src/components/ui/config-details.ts

Lines changed: 18 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -16,9 +16,7 @@ import {
1616
import { labelFor } from "@/strings/crawl-workflows/labels";
1717
import scopeTypeLabel from "@/strings/crawl-workflows/scopeType";
1818
import sectionStrings from "@/strings/crawl-workflows/section";
19-
import type { Collection } from "@/types/collection";
2019
import { WorkflowScopeType, type StorageSeedFile } from "@/types/workflow";
21-
import { isApiError } from "@/utils/api";
2220
import { unescapeCustomPrefix } from "@/utils/crawl-workflows/unescapeCustomPrefix";
2321
import { DEPTH_SUPPORTED_SCOPES, isPageScopeType } from "@/utils/crawler";
2422
import { humanizeSchedule } from "@/utils/cron";
@@ -60,13 +58,9 @@ export class ConfigDetails extends BtrixElement {
6058
maxPagesPerCrawl?: number;
6159
};
6260

63-
@state()
64-
private collections: Collection[] = [];
65-
6661
async connectedCallback() {
6762
super.connectedCallback();
6863
void this.fetchOrgDefaults();
69-
await this.fetchCollections();
7064
}
7165

7266
render() {
@@ -313,6 +307,24 @@ export class ConfigDetails extends BtrixElement {
313307
)}
314308
`,
315309
})}
310+
${when(!this.hideMetadata, () =>
311+
this.renderSection({
312+
id: "collection",
313+
heading: sectionStrings.collections,
314+
renderDescItems: () => html`
315+
${this.renderSetting(
316+
html`<span class="mb-1 inline-block"
317+
>${msg("Auto-Add to Collection")}</span
318+
>`,
319+
crawlConfig?.autoAddCollections.length
320+
? html`<btrix-linked-collections
321+
.collectionIds=${crawlConfig.autoAddCollections}
322+
></btrix-linked-collections>`
323+
: undefined,
324+
)}
325+
`,
326+
}),
327+
)}
316328
${when(!this.hideMetadata, () =>
317329
this.renderSection({
318330
id: "crawl-metadata",
@@ -338,21 +350,6 @@ export class ConfigDetails extends BtrixElement {
338350
)
339351
: [],
340352
)}
341-
${this.renderSetting(
342-
msg("Collections"),
343-
this.collections.length
344-
? this.collections.map(
345-
(coll) =>
346-
html`<sl-tag class="mr-2 mt-1" variant="neutral">
347-
${coll.name}
348-
<span class="font-monostyle pl-1 text-xs">
349-
(${this.localize.number(coll.crawlCount)}
350-
${pluralOf("items", coll.crawlCount)})
351-
</span>
352-
</sl-tag>`,
353-
)
354-
: undefined,
355-
)}
356353
`,
357354
}),
358355
)}
@@ -633,44 +630,6 @@ export class ConfigDetails extends BtrixElement {
633630
`;
634631
}
635632

636-
private async fetchCollections() {
637-
if (this.crawlConfig?.autoAddCollections) {
638-
try {
639-
await this.getCollections();
640-
} catch (e) {
641-
this.notify.toast({
642-
message:
643-
isApiError(e) && e.statusCode === 404
644-
? msg("Collections not found.")
645-
: msg(
646-
"Sorry, couldn't retrieve Collection details at this time.",
647-
),
648-
variant: "danger",
649-
icon: "exclamation-octagon",
650-
id: "collection-fetch-status",
651-
});
652-
}
653-
}
654-
}
655-
656-
private async getCollections() {
657-
const collections: Collection[] = [];
658-
const orgId = this.crawlConfig?.oid;
659-
660-
if (this.crawlConfig?.autoAddCollections && orgId) {
661-
for (const collectionId of this.crawlConfig.autoAddCollections) {
662-
const data = await this.api.fetch<Collection | undefined>(
663-
`/orgs/${orgId}/collections/${collectionId}`,
664-
);
665-
if (data) {
666-
collections.push(data);
667-
}
668-
}
669-
}
670-
this.collections = collections;
671-
this.requestUpdate();
672-
}
673-
674633
// TODO Consolidate with workflow-editor
675634
private async fetchOrgDefaults() {
676635
try {

frontend/src/features/archived-items/item-metadata-editor.ts

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
11
import { localized, msg } from "@lit/localize";
22
import { serialize } from "@shoelace-style/shoelace/dist/utilities/form.js";
33
import Fuse from "fuse.js";
4+
import { html } from "lit";
45
import { customElement, property, state } from "lit/decorators.js";
56

7+
import { BtrixElement } from "@/classes/BtrixElement";
68
import type {
79
TagInputEvent,
810
Tags,
@@ -12,7 +14,6 @@ import { type CollectionsChangeEvent } from "@/features/collections/collections-
1214
import type { ArchivedItem } from "@/types/crawler";
1315
import { type WorkflowTag, type WorkflowTags } from "@/types/workflow";
1416
import { maxLengthValidator } from "@/utils/form";
15-
import LiteElement, { html } from "@/utils/LiteElement";
1617

1718
/**
1819
* Usage:
@@ -30,7 +31,7 @@ import LiteElement, { html } from "@/utils/LiteElement";
3031
*/
3132
@customElement("btrix-item-metadata-editor")
3233
@localized()
33-
export class CrawlMetadataEditor extends LiteElement {
34+
export class CrawlMetadataEditor extends BtrixElement {
3435
@property({ type: Object })
3536
crawl?: ArchivedItem;
3637

@@ -78,7 +79,7 @@ export class CrawlMetadataEditor extends LiteElement {
7879
render() {
7980
return html`
8081
<btrix-dialog
81-
.label=${msg("Edit Metadata")}
82+
.label=${msg("Edit Archived Item")}
8283
.open=${this.open}
8384
@sl-show=${() => (this.isDialogVisible = true)}
8485
@sl-after-hide=${() => (this.isDialogVisible = false)}
@@ -125,11 +126,11 @@ export class CrawlMetadataEditor extends LiteElement {
125126
@tags-change=${(e: TagsChangeEvent) =>
126127
(this.tagsToSave = e.detail.tags)}
127128
></btrix-tag-input>
128-
<div class="mt-4">
129+
<div class="mt-7">
129130
<btrix-collections-add
130131
.initialCollections=${this.crawl.collectionIds}
131132
.configId=${"temp"}
132-
label=${msg("Add to Collection")}
133+
label=${msg("Include in Collection")}
133134
@collections-change=${(e: CollectionsChangeEvent) =>
134135
(this.collectionsToSave = e.detail.collections)}
135136
>
@@ -166,7 +167,7 @@ export class CrawlMetadataEditor extends LiteElement {
166167
private async fetchTags() {
167168
if (!this.crawl) return;
168169
try {
169-
const { tags } = await this.apiFetch<WorkflowTags>(
170+
const { tags } = await this.api.fetch<WorkflowTags>(
170171
`/orgs/${this.crawl.oid}/crawlconfigs/tagCounts`,
171172
);
172173

@@ -220,7 +221,7 @@ export class CrawlMetadataEditor extends LiteElement {
220221
this.isSubmittingUpdate = true;
221222

222223
try {
223-
const data = await this.apiFetch<{ updated: boolean }>(
224+
const data = await this.api.fetch<{ updated: boolean }>(
224225
`/orgs/${this.crawl.oid}/all-crawls/${this.crawl.id}`,
225226
{
226227
method: "PATCH",
@@ -233,15 +234,15 @@ export class CrawlMetadataEditor extends LiteElement {
233234
}
234235

235236
this.dispatchEvent(new CustomEvent("updated"));
236-
this.notify({
237+
this.notify.toast({
237238
message: msg("Successfully saved crawl details."),
238239
variant: "success",
239240
icon: "check2-circle",
240241
id: "crawl-details-update-status",
241242
});
242243
this.requestClose();
243244
} catch (e) {
244-
this.notify({
245+
this.notify.toast({
245246
message: msg("Sorry, couldn't save crawl details at this time."),
246247
variant: "danger",
247248
icon: "exclamation-octagon",

frontend/src/features/collections/collections-add.ts

Lines changed: 12 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import queryString from "query-string";
99

1010
import { BtrixElement } from "@/classes/BtrixElement";
1111
import type { Combobox } from "@/components/ui/combobox";
12+
import type { BtrixRemoveLinkedCollectionEvent } from "@/features/collections/linked-collections/types";
1213
import type {
1314
APIPaginatedList,
1415
APIPaginationQuery,
@@ -51,9 +52,6 @@ export class CollectionsAdd extends BtrixElement {
5152
@property({ type: String })
5253
emptyText?: string;
5354

54-
@state()
55-
private collectionsData: { [id: string]: Collection } = {};
56-
5755
@state()
5856
private collectionIds: string[] = [];
5957

@@ -89,7 +87,6 @@ export class CollectionsAdd extends BtrixElement {
8987
this.collectionIds = this.initialCollections;
9088
}
9189
super.connectedCallback();
92-
void this.initializeCollectionsFromIds();
9390
}
9491

9592
disconnectedCallback() {
@@ -99,7 +96,7 @@ export class CollectionsAdd extends BtrixElement {
9996
render() {
10097
return html`<div>
10198
<label class="form-label">
102-
${this.label || msg("Collection Auto-Add")}
99+
${this.label || msg("Add to Collection")}
103100
</label>
104101
<div class="mb-2 rounded-lg border bg-neutral-50 p-2">
105102
${this.renderSearch()}
@@ -109,9 +106,15 @@ export class CollectionsAdd extends BtrixElement {
109106
this.collectionIds.length
110107
? html`
111108
<div class="mb-2">
112-
<ul class="contents">
113-
${this.collectionIds.map(this.renderCollectionItem, this)}
114-
</ul>
109+
<btrix-linked-collections
110+
.collectionIds=${this.collectionIds}
111+
removable
112+
@btrix-remove=${(e: BtrixRemoveLinkedCollectionEvent) => {
113+
const { id } = e.detail.item;
114+
115+
this.removeCollection(id);
116+
}}
117+
></btrix-linked-collections>
115118
</div>
116119
`
117120
: this.emptyText
@@ -142,12 +145,6 @@ export class CollectionsAdd extends BtrixElement {
142145
);
143146
if (coll) {
144147
const { id } = coll;
145-
if (!(this.collectionsData[id] as Collection | undefined)) {
146-
this.collectionsData = {
147-
...this.collectionsData,
148-
[id]: (await this.getCollection(id))!,
149-
};
150-
}
151148
this.collectionIds = [...this.collectionIds, id];
152149
void this.dispatchChange();
153150
}
@@ -225,35 +222,7 @@ export class CollectionsAdd extends BtrixElement {
225222
});
226223
}
227224

228-
private renderCollectionItem(id: string) {
229-
const collection = this.collectionsData[id] as Collection | undefined;
230-
return html`<li class="mt-1 rounded-sm border p-1 pl-3">
231-
<div
232-
class="${collection
233-
? "opacity-100"
234-
: "opacity-0"} flex flex-row items-center justify-between gap-2 transition-opacity delay-75"
235-
>
236-
<div class="grow justify-self-stretch truncate">
237-
${collection?.name}
238-
</div>
239-
<div class="font-monostyle text-right text-xs text-neutral-500">
240-
${msg(str`${collection?.crawlCount || 0} items`)}
241-
</div>
242-
<sl-icon-button
243-
name="x-lg"
244-
label=${msg("Remove from auto-add")}
245-
data-key=${id}
246-
?disabled=${!collection}
247-
@click=${this.removeCollection}
248-
>
249-
</sl-icon-button>
250-
</div>
251-
</li>`;
252-
}
253-
254-
private removeCollection(event: Event) {
255-
const target = event.currentTarget as HTMLElement;
256-
const collectionId = target.getAttribute("data-key");
225+
private removeCollection(collectionId: string) {
257226
if (collectionId) {
258227
const collIdIndex = this.collectionIds.indexOf(collectionId);
259228
if (collIdIndex > -1) {
@@ -325,24 +294,6 @@ export class CollectionsAdd extends BtrixElement {
325294
return data;
326295
}
327296

328-
private async initializeCollectionsFromIds() {
329-
this.collectionIds.forEach(async (id) => {
330-
const data = await this.getCollection(id);
331-
if (data) {
332-
this.collectionsData = {
333-
...this.collectionsData,
334-
[id]: data,
335-
};
336-
}
337-
});
338-
}
339-
340-
private readonly getCollection = async (
341-
collId: string,
342-
): Promise<Collection | undefined> => {
343-
return this.api.fetch(`/orgs/${this.orgId}/collections/${collId}`);
344-
};
345-
346297
private async dispatchChange() {
347298
await this.updateComplete;
348299
this.dispatchEvent(

frontend/src/features/collections/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import("./collection-edit-dialog");
66
import("./collection-create-dialog");
77
import("./collection-initial-view-dialog");
88
import("./collection-workflow-list");
9+
import("./linked-collections");
910
import("./select-collection-access");
1011
import("./select-collection-page");
1112
import("./share-collection");
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
import "./linked-collections";

0 commit comments

Comments
 (0)