Add "Copy <item type> ID" to a bunch of menus (#2426)

Addresses feedback from here
https://discord.com/channels/895426029194207262/910966759165657161/1344367205004873819
by @tw4l.

Add "Copy <item type> ID" to a bunch of menus, including all list and
detail pages, as well as all other item/crawl/page lists.

| Screenshots |
|--------|
| <img width="323" alt="Screenshot 2025-02-26 at 3 56 48 PM"
src="https://github.com/user-attachments/assets/32044c47-65f3-4e80-8f39-df5fd2101324"
/> |
| <img width="246" alt="Screenshot 2025-02-26 at 4 02 06 PM"
src="https://github.com/user-attachments/assets/8f2d6272-f450-4923-b5c9-751a2eea9a26"
/> |
| <img width="419" alt="Screenshot 2025-02-26 at 4 02 55 PM"
src="https://github.com/user-attachments/assets/0c005a33-055d-4fb7-a79e-9bedae57b785"
/> |
| <img width="1104" alt="Screenshot 2025-02-26 at 1 57 01 PM"
src="https://github.com/user-attachments/assets/7ee43400-1b30-4c78-89a0-3ddb89ef90ca"
/> |
| <img width="292" alt="Screenshot 2025-02-26 at 4 01 10 PM"
src="https://github.com/user-attachments/assets/929f7870-aa83-4f3c-947a-efad377e0b49"
/> |
| <img width="240" alt="Screenshot 2025-02-26 at 4 03 19 PM"
src="https://github.com/user-attachments/assets/45bff838-f741-45ce-b1a7-a8cfefa9656b"
/> |

---------

Co-authored-by: Henry Wilkinson <henry@wilkinson.graphics>
This commit is contained in:
Emma Segal-Grossman 2025-02-26 16:58:00 -05:00 committed by GitHub
parent e67708bd4f
commit 00e85c3e94
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
10 changed files with 176 additions and 60 deletions

View File

@ -47,7 +47,10 @@ export class MenuItemLink extends TailwindElement {
download=${this.download}
aria-disabled=${this.disabled}
@click=${(e: MouseEvent) => {
if (this.disabled || this.loading) return;
if (this.disabled || this.loading) {
e.preventDefault();
return;
}
if (this.download) {
const dropdown = this.shadowRoot!.host.closest<

View File

@ -630,6 +630,26 @@ export class ArchivedItemDetail extends BtrixElement {
<sl-divider></sl-divider>
`,
)}
${when(
isSuccessfullyFinished(this.item),
() => html`
<btrix-menu-item-link
href=${`/api/orgs/${this.orgId}/all-crawls/${this.itemId}/download?auth_bearer=${authToken}`}
download
>
<sl-icon name="cloud-download" slot="prefix"></sl-icon>
${msg("Download Item")}
${this.item?.fileSize
? html` <btrix-badge
slot="suffix"
class="font-monostyle text-xs text-neutral-500"
>${this.localize.bytes(this.item.fileSize)}</btrix-badge
>`
: nothing}
</btrix-menu-item-link>
<sl-divider></sl-divider>
`,
)}
${when(
this.itemType === "crawl",
() => html`
@ -659,19 +679,15 @@ export class ArchivedItemDetail extends BtrixElement {
<sl-icon name="tags" slot="prefix"></sl-icon>
${msg("Copy Tags")}
</sl-menu-item>
${when(
isSuccessfullyFinished(this.item),
() => html`
<sl-divider></sl-divider>
<btrix-menu-item-link
href=${`/api/orgs/${this.orgId}/all-crawls/${this.itemId}/download?auth_bearer=${authToken}`}
download
>
<sl-icon name="cloud-download" slot="prefix"></sl-icon>
${msg("Download Item")}
</btrix-menu-item-link>
`,
)}
<sl-menu-item
@click=${() =>
ClipboardController.copyToClipboard(
this.item?.id ?? this.itemId ?? "",
)}
>
<sl-icon name="copy" slot="prefix"></sl-icon>
${msg("Copy Item ID")}
</sl-menu-item>
${when(
this.isCrawler,
() => html`

View File

@ -16,6 +16,7 @@ import queryString from "query-string";
import { BtrixElement } from "@/classes/BtrixElement";
import { type Dialog } from "@/components/ui/dialog";
import type { PageChangeEvent } from "@/components/ui/pagination";
import { ClipboardController } from "@/controllers/clipboard";
import { iconFor as iconForPageReview } from "@/features/qa/page-list/helpers";
import * as pageApproval from "@/features/qa/page-list/helpers/approval";
import type { SelectDetail } from "@/features/qa/qa-run-dropdown";
@ -392,6 +393,13 @@ export class ArchivedItemDetailQA extends BtrixElement {
</btrix-menu-item-link>
<sl-divider></sl-divider>
`}
<sl-menu-item
@click=${() => ClipboardController.copyToClipboard(run.id)}
>
<sl-icon name="copy" slot="prefix"></sl-icon>
${msg("Copy Run ID")}
</sl-menu-item>
<sl-divider></sl-divider>
<sl-menu-item
@click=${() => {
this.deleting = run.id;
@ -750,12 +758,16 @@ export class ArchivedItemDetailQA extends BtrixElement {
"[clickable-start] minmax(12rem, auto)",
"minmax(min-content, 12rem)",
"minmax(min-content, 12rem) [clickable-end]",
"min-content",
].join(" ")}"
>
<btrix-table-head>
<btrix-table-header-cell>${msg("Page")}</btrix-table-header-cell>
<btrix-table-header-cell>${msg("Approval")}</btrix-table-header-cell>
<btrix-table-header-cell>${msg("Comments")}</btrix-table-header-cell>
<btrix-table-header-cell class="px-0">
<span class="sr-only">${msg("Row actions")}</span>
</btrix-table-header-cell>
</btrix-table-head>
<btrix-table-body class="rounded border">
${this.pages?.items.map(
@ -809,6 +821,21 @@ export class ArchivedItemDetailQA extends BtrixElement {
${msg("None")}
</span>`}
</btrix-table-cell>
<btrix-table-cell class="p-0">
<div class="col action">
<btrix-overflow-dropdown>
<sl-menu>
<sl-menu-item
@click=${() =>
ClipboardController.copyToClipboard(page.id)}
>
<sl-icon name="copy" slot="prefix"></sl-icon>
${msg("Copy Page ID")}
</sl-menu-item>
</sl-menu>
</btrix-overflow-dropdown>
</div>
</btrix-table-cell>
</btrix-table-row>
`,
)}

View File

@ -598,6 +598,26 @@ export class CrawlsList extends BtrixElement {
<sl-divider></sl-divider>
`,
)}
${when(
isSuccessfullyFinished(item),
() => html`
<btrix-menu-item-link
href=${`/api/orgs/${this.orgId}/all-crawls/${item.id}/download?auth_bearer=${authToken}`}
download
>
<sl-icon name="cloud-download" slot="prefix"></sl-icon>
${msg("Download Item")}
${item.fileSize
? html` <btrix-badge
slot="suffix"
class="font-monostyle text-xs text-neutral-500"
>${this.localize.bytes(item.fileSize)}</btrix-badge
>`
: nothing}
</btrix-menu-item-link>
<sl-divider></sl-divider>
`,
)}
${item.type === "crawl"
? html`
<sl-menu-item
@ -615,14 +635,9 @@ export class CrawlsList extends BtrixElement {
<sl-icon name="copy" slot="prefix"></sl-icon>
${msg("Copy Workflow ID")}
</sl-menu-item>
<sl-menu-item
@click=${() => ClipboardController.copyToClipboard(item.id)}
>
<sl-icon name="copy" slot="prefix"></sl-icon>
${msg("Copy Archived Item ID")}
</sl-menu-item>
`
: nothing}
<sl-menu-item
@click=${() =>
ClipboardController.copyToClipboard(item.tags.join(", "))}
@ -631,19 +646,12 @@ export class CrawlsList extends BtrixElement {
<sl-icon name="tags" slot="prefix"></sl-icon>
${msg("Copy Tags")}
</sl-menu-item>
${when(
isSuccessfullyFinished(item),
() => html`
<sl-divider></sl-divider>
<btrix-menu-item-link
href=${`/api/orgs/${this.orgId}/all-crawls/${item.id}/download?auth_bearer=${authToken}`}
download
>
<sl-icon name="cloud-download" slot="prefix"></sl-icon>
${msg("Download Item")}
</btrix-menu-item-link>
`,
)}
<sl-menu-item
@click=${() => ClipboardController.copyToClipboard(item.id)}
>
<sl-icon name="copy" slot="prefix"></sl-icon>
${msg("Copy Item ID")}
</sl-menu-item>
${when(
this.isCrawler && (item.type !== "crawl" || !isActive(item)),
() => html`

View File

@ -10,6 +10,7 @@ import type { Profile, ProfileWorkflow } from "./types";
import { BtrixElement } from "@/classes/BtrixElement";
import type { Dialog } from "@/components/ui/dialog";
import { ClipboardController } from "@/controllers/clipboard";
import type { BrowserConnectionChange } from "@/features/browser-profiles/profile-browser";
import { pageNav } from "@/layouts/pageHeader";
import { isApiError } from "@/utils/api";
@ -432,12 +433,19 @@ export class BrowserProfilesDetail extends BtrixElement {
${msg("Duplicate Profile")}
</sl-menu-item>
<sl-divider></sl-divider>
<sl-menu-item
@click=${() => ClipboardController.copyToClipboard(this.profileId)}
>
<sl-icon name="copy" slot="prefix"></sl-icon>
${msg("Copy Profile ID")}
</sl-menu-item>
<sl-divider></sl-divider>
<sl-menu-item
style="--sl-color-neutral-700: var(--danger)"
@click=${() => void this.deleteProfile()}
>
<sl-icon slot="prefix" name="trash3"></sl-icon>
${msg("Delete")}
${msg("Delete Profile")}
</sl-menu-item>
</sl-menu>
</sl-dropdown>

View File

@ -15,6 +15,7 @@ import {
SortDirection,
type SortValues,
} from "@/components/ui/table/table-header-cell";
import { ClipboardController } from "@/controllers/clipboard";
import { pageHeader } from "@/layouts/pageHeader";
import type {
APIPaginatedList,
@ -325,6 +326,14 @@ export class BrowserProfilesList extends BtrixElement {
<sl-icon slot="prefix" name="files"></sl-icon>
${msg("Duplicate Profile")}
</sl-menu-item>
<sl-divider></sl-divider>
<sl-menu-item
@click=${() => ClipboardController.copyToClipboard(data.id)}
>
<sl-icon name="copy" slot="prefix"></sl-icon>
${msg("Copy Profile ID")}
</sl-menu-item>
<sl-divider></sl-divider>
<sl-menu-item
style="--sl-color-neutral-700: var(--danger)"
@click=${() => {
@ -332,7 +341,7 @@ export class BrowserProfilesList extends BtrixElement {
}}
>
<sl-icon slot="prefix" name="trash3"></sl-icon>
${msg("Delete")}
${msg("Delete Profile")}
</sl-menu-item>
</sl-menu>
</btrix-overflow-dropdown>

View File

@ -14,6 +14,7 @@ import { BtrixElement } from "@/classes/BtrixElement";
import type { MarkdownEditor } from "@/components/ui/markdown-editor";
import type { PageChangeEvent } from "@/components/ui/pagination";
import { viewStateContext, type ViewStateContext } from "@/context/view-state";
import { ClipboardController } from "@/controllers/clipboard";
import type { EditDialogTab } from "@/features/collections/collection-edit-dialog";
import { collectionShareLink } from "@/features/collections/helpers/share-link";
import { SelectCollectionAccess } from "@/features/collections/select-collection-access";
@ -563,6 +564,16 @@ export class CollectionDetail extends BtrixElement {
)}
</btrix-menu-item-link>
<sl-divider></sl-divider>
<sl-menu-item
@click=${() =>
ClipboardController.copyToClipboard(
this.collection?.id ?? this.collectionId,
)}
>
<sl-icon name="copy" slot="prefix"></sl-icon>
${msg("Copy Collection ID")}
</sl-menu-item>
<sl-divider></sl-divider>
<sl-menu-item
style="--sl-color-neutral-700: var(--danger)"
@click=${this.confirmDelete}
@ -868,6 +879,13 @@ export class CollectionDetail extends BtrixElement {
<sl-icon name="folder-minus" slot="prefix"></sl-icon>
${msg("Remove from Collection")}
</sl-menu-item>
<sl-divider></sl-divider>
<sl-menu-item
@click=${() => ClipboardController.copyToClipboard(item.id)}
>
<sl-icon name="copy" slot="prefix"></sl-icon>
${msg("Copy Item ID")}
</sl-menu-item>
</sl-menu>
</btrix-overflow-dropdown>
</btrix-table-cell>

View File

@ -585,12 +585,10 @@ export class CollectionsList extends BtrixElement {
<sl-icon name="gear" slot="prefix"></sl-icon>
${msg("Edit Collection Settings")}
</sl-menu-item>
<sl-divider></sl-divider>
${col.access === CollectionAccess.Public ||
col.access === CollectionAccess.Unlisted
? html`
<sl-menu-item
style="--sl-color-neutral-700: var(--success)"
@click=${() => {
ClipboardController.copyToClipboard(this.getShareLink(col));
this.notify.toast({
@ -605,14 +603,14 @@ export class CollectionsList extends BtrixElement {
</sl-menu-item>
`
: nothing}
<sl-divider></sl-divider>
<btrix-menu-item-link
href=${`/api/orgs/${this.orgId}/collections/${col.id}/download?auth_bearer=${authToken}`}
download
?disabled=${!col.totalSize}
>
<sl-icon name="cloud-download" slot="prefix"></sl-icon>
${msg("Download")}
${msg("Download Collection")}
<btrix-badge
slot="suffix"
class="font-monostyle text-xs text-neutral-500"
@ -620,6 +618,13 @@ export class CollectionsList extends BtrixElement {
>
</btrix-menu-item-link>
<sl-divider></sl-divider>
<sl-menu-item
@click=${() => ClipboardController.copyToClipboard(col.id)}
>
<sl-icon name="copy" slot="prefix"></sl-icon>
${msg("Copy Collection ID")}
</sl-menu-item>
<sl-divider></sl-divider>
<sl-menu-item
style="--sl-color-neutral-700: var(--danger)"
@click=${() => void this.manageCollection(col, "delete")}

View File

@ -744,6 +744,14 @@ export class WorkflowDetail extends BtrixElement {
<sl-icon name="gear" slot="prefix"></sl-icon>
${msg("Edit Workflow Settings")}
</sl-menu-item>
<sl-menu-item
?disabled=${archivingDisabled}
@click=${() => void this.duplicateConfig()}
>
<sl-icon name="files" slot="prefix"></sl-icon>
${msg("Duplicate Workflow")}
</sl-menu-item>
<sl-divider></sl-divider>
<sl-menu-item
@click=${() =>
ClipboardController.copyToClipboard(workflow.tags.join(", "))}
@ -753,11 +761,10 @@ export class WorkflowDetail extends BtrixElement {
${msg("Copy Tags")}
</sl-menu-item>
<sl-menu-item
?disabled=${archivingDisabled}
@click=${() => void this.duplicateConfig()}
@click=${() => ClipboardController.copyToClipboard(workflow.id)}
>
<sl-icon name="files" slot="prefix"></sl-icon>
${msg("Duplicate Workflow")}
<sl-icon name="copy" slot="prefix"></sl-icon>
${msg("Copy Workflow ID")}
</sl-menu-item>
${when(
!workflow.crawlCount,
@ -925,10 +932,18 @@ export class WorkflowDetail extends BtrixElement {
)}
.crawl=${crawl}
>
${when(
this.isCrawler,
() =>
html` <sl-menu slot="menu">
<sl-menu slot="menu">
<sl-menu-item
@click=${() =>
ClipboardController.copyToClipboard(crawl.id)}
>
<sl-icon name="copy" slot="prefix"></sl-icon>
${msg("Copy Crawl ID")}
</sl-menu-item>
${when(
this.isCrawler,
() => html`
<sl-divider></sl-divider>
<sl-menu-item
style="--sl-color-neutral-700: var(--danger)"
@click=${() => this.confirmDeleteCrawl(crawl)}
@ -936,9 +951,10 @@ export class WorkflowDetail extends BtrixElement {
<sl-icon name="trash3" slot="prefix"></sl-icon>
${msg("Delete Crawl")}
</sl-menu-item>
</sl-menu>`,
)}</btrix-crawl-list-item
>`,
`,
)}
</sl-menu>
</btrix-crawl-list-item>`,
),
)}
</btrix-crawl-list>

View File

@ -613,16 +613,15 @@ export class WorkflowsList extends BtrixElement {
${when(
this.appState.isCrawler,
() =>
html` <sl-divider></sl-divider>
<sl-menu-item
@click=${() =>
this.navigate.to(
`${this.navigate.orgBasePath}/workflows/${workflow.id}?edit`,
)}
>
<sl-icon name="gear" slot="prefix"></sl-icon>
${msg("Edit Workflow Settings")}
</sl-menu-item>`,
html`<sl-menu-item
@click=${() =>
this.navigate.to(
`${this.navigate.orgBasePath}/workflows/${workflow.id}?edit`,
)}
>
<sl-icon name="gear" slot="prefix"></sl-icon>
${msg("Edit Workflow Settings")}
</sl-menu-item>`,
)}
<sl-menu-item
@click=${() =>
@ -642,6 +641,13 @@ export class WorkflowsList extends BtrixElement {
<sl-icon name="files" slot="prefix"></sl-icon>
${msg("Duplicate Workflow")}
</sl-menu-item>
<sl-divider></sl-divider>
<sl-menu-item
@click=${() => ClipboardController.copyToClipboard(workflow.id)}
>
<sl-icon name="copy" slot="prefix"></sl-icon>
${msg("Copy Workflow ID")}
</sl-menu-item>
${when(
!workflow.crawlCount,
() => html`