From 6ddba105f4e080d5e43449597fa84f0111642f16 Mon Sep 17 00:00:00 2001 From: sua yoo Date: Thu, 14 Sep 2023 15:21:01 -0700 Subject: [PATCH] Enable saving individual collection form sections (#1166) - Moves metadata tab to first position - Adds save button to each section, stays in edit view on saving - Validates name exists before moving to next section or saving - Changes save button text to "Create Collection without Items" if crawl/uploads aren't selected in new collection - Fix server error not showing in UI --- frontend/src/pages/org/collection-edit.ts | 14 +- frontend/src/pages/org/collection-editor.ts | 358 ++++++++++++-------- frontend/src/pages/org/collections-new.ts | 14 +- 3 files changed, 242 insertions(+), 144 deletions(-) diff --git a/frontend/src/pages/org/collection-edit.ts b/frontend/src/pages/org/collection-edit.ts index 18153320..1bba8fce 100644 --- a/frontend/src/pages/org/collection-edit.ts +++ b/frontend/src/pages/org/collection-edit.ts @@ -87,7 +87,7 @@ export class CollectionEdit extends LiteElement { e.detail.values; try { - if (oldCrawlIds && oldCrawlIds) { + if (crawlIds && oldCrawlIds) { await this.saveCrawlSelection({ crawlIds, oldCrawlIds, @@ -96,27 +96,29 @@ export class CollectionEdit extends LiteElement { await this.saveMetadata({ name, description, - isPublic: isPublic === "on", + isPublic, }); } - this.navTo(`/orgs/${this.orgId}/collections/view/${this.collectionId}`); this.notify({ message: msg( html`Successfully updated ${name} Collection.` ), variant: "success", icon: "check2-circle", - duration: 8000, }); } catch (e: any) { if (e?.isApiError) { - this.serverError = e?.message; + this.serverError = e?.message as string; } else { this.serverError = msg("Something unexpected went wrong"); } - console.log(this.serverError); + this.notify({ + message: this.serverError, + variant: "danger", + icon: "exclamation-octagon", + }); } this.isSubmitting = false; diff --git a/frontend/src/pages/org/collection-editor.ts b/frontend/src/pages/org/collection-editor.ts index c3902fbc..bdc0bd61 100644 --- a/frontend/src/pages/org/collection-editor.ts +++ b/frontend/src/pages/org/collection-editor.ts @@ -1,5 +1,5 @@ import type { TemplateResult } from "lit"; -import { state, property } from "lit/decorators.js"; +import { state, property, query } from "lit/decorators.js"; import { msg, localized, str } from "@lit/localize"; import { when } from "lit/directives/when.js"; import { guard } from "lit/directives/guard.js"; @@ -17,7 +17,7 @@ import uniqBy from "lodash/fp/uniqBy"; import Fuse from "fuse.js"; import queryString from "query-string"; import { serialize } from "@shoelace-style/shoelace/dist/utilities/form.js"; -import type { SlMenuItem } from "@shoelace-style/shoelace"; +import type { SlInput, SlMenuItem } from "@shoelace-style/shoelace"; import type { CheckboxChangeEvent, @@ -36,7 +36,7 @@ import type { Collection } from "../../types/collection"; import type { Crawl, CrawlState, Upload, Workflow } from "../../types/crawler"; import type { PageChangeEvent } from "../../components/pagination"; -const TABS = ["crawls", "uploads", "metadata"] as const; +const TABS = ["metadata", "crawls", "uploads"] as const; type Tab = (typeof TABS)[number]; type SearchFields = "name" | "firstSeed"; type SearchResult = { @@ -84,9 +84,14 @@ export type CollectionSubmitEvent = CustomEvent<{ description: string | null; crawlIds: string[]; oldCrawlIds?: string[]; - isPublic: string | null; + isPublic: boolean; }; }>; +type FormValues = { + name: string; + description: string; + isPublic?: string; +}; /** * @event on-submit @@ -114,9 +119,15 @@ export class CollectionEditor extends LiteElement { @state() private collectionCrawls?: Crawl[]; + @state() + private collectionUploads?: Upload[]; + // Store crawl IDs to compare later private savedCollectionCrawlIds: string[] = []; + // Store upload IDs to compare later + private savedCollectionUploadIds: string[] = []; + @state() private workflows?: APIPaginatedList & { items: Workflow[]; @@ -144,6 +155,10 @@ export class CollectionEditor extends LiteElement { [crawlId: string]: Crawl; } = {}; + @state() + private selectedUploads: { + [uploadId: string]: Upload; + } = {}; @state() private activeTab: Tab = TABS[0]; @@ -165,10 +180,20 @@ export class CollectionEditor extends LiteElement { @state() private searchResultsOpen = false; + @query("#collectionForm-name-input") + private nameInput?: SlInput; + private get hasSearchStr() { return this.searchByValue.length >= MIN_SEARCH_LENGTH; } + private get hasItemSelection() { + return Boolean( + Object.keys(this.selectedCrawls).length || + Object.keys(this.selectedUploads).length + ); + } + private get selectedSearchFilterKey() { return Object.keys(this.fieldLabels).find((key) => Boolean((this.filterWorkflowsBy as any)[key]) @@ -201,6 +226,16 @@ export class CollectionEditor extends LiteElement { }; protected async willUpdate(changedProperties: Map) { + if ( + changedProperties.has("activeTab") && + !changedProperties.get("activeTab") && + this.activeTab + ) { + // First tab load + if (this.activeTab !== "metadata" && !this.collectionId) { + this.goToTab("metadata"); + } + } if (changedProperties.has("orgId") && this.orgId) { this.fetchSearchValues(); } @@ -313,6 +348,7 @@ export class CollectionEditor extends LiteElement {
${guard( [ + this.activeTab === "crawls", this.isCrawler, this.collectionCrawls, this.selectedCrawls, @@ -375,31 +411,46 @@ export class CollectionEditor extends LiteElement {
${when( - this.collectionId, + !this.collectionId, () => html` isLoading === true - )} - ?loading=${this.isSubmitting} - @click=${this.submitCrawlSelectionChanges} + class="mr-auto" + @click=${() => this.goToTab("metadata")} > - ${msg("Save Crawl Selection")} + + ${msg("Previous Step")} - `, - () => html` - this.goToTab("uploads")}> + this.goToTab("uploads")} + > ${msg("Select Uploads")} ` )} + isLoading === true + )} + ?loading=${this.isSubmitting} + > + ${this.collectionId + ? msg("Save Crawls") + : this.hasItemSelection + ? msg("Create Collection") + : msg("Create Collection without Items")} +
`; @@ -414,7 +465,7 @@ export class CollectionEditor extends LiteElement {
${guard( - [this.collectionCrawls, this.selectedCrawls], + [this.collectionUploads, this.selectedUploads], this.renderCollectionUploadList )}
@@ -423,7 +474,7 @@ export class CollectionEditor extends LiteElement {

${msg("All Uploads")}

${guard( - [this.isCrawler, this.uploads, this.selectedCrawls], + [this.isCrawler, this.uploads, this.selectedUploads], this.renderUploadList )}
@@ -449,41 +500,38 @@ export class CollectionEditor extends LiteElement {
${when( !this.collectionId, - () => html` - this.goToTab("crawls")}> - - ${msg("Select Crawls")} - - ` - )} - ${when( - this.collectionId, () => html` isLoading === true - )} - ?loading=${this.isSubmitting} - @click=${this.submitCrawlSelectionChanges} + @click=${() => this.goToTab("crawls")} > - ${msg("Save Upload Selection")} - - `, - () => html` - this.goToTab("metadata")}> - - ${msg("Enter Metadata")} + + ${msg("Previous Step")} ` )} + isLoading === true + )} + ?loading=${this.isSubmitting} + > + ${this.collectionId + ? msg("Save Uploads") + : this.hasItemSelection + ? msg("Create Collection") + : msg("Create Collection without Items")} +
`; @@ -495,6 +543,7 @@ export class CollectionEditor extends LiteElement {
-