diff --git a/src/frontend/app-common/app-menu.tsx b/src/frontend/app-common/app-menu.tsx index b417ff82..c634db1f 100644 --- a/src/frontend/app-common/app-menu.tsx +++ b/src/frontend/app-common/app-menu.tsx @@ -1,5 +1,7 @@ -import { ReactNode } from "react"; -import { FloatingPosition, Menu } from "@mantine/core"; +import { PropsWithChildren, ReactNode } from "react"; +import { FloatingPosition, Menu, ActionIcon } from "@mantine/core"; +import { IconDots } from "@tabler/icons-react"; +import { IconSize } from "../common/style-constants"; interface AppContextMenuProps { menuItems: ReactNode; @@ -56,3 +58,22 @@ export function AppContextMenu(props: AppContextMenuProps): ReactNode { ); } + +/** + * An explicit button which opens a menu with the given items. Used alongside + * the right-click context menu so the menu is reachable without a right-click. + */ +export function MenuButton(props: PropsWithChildren): ReactNode { + return ( + + e.stopPropagation()} + > + + + + ); +} diff --git a/src/frontend/cards/card-components.tsx b/src/frontend/cards/card-components.tsx index e045fc5b..a773b484 100644 --- a/src/frontend/cards/card-components.tsx +++ b/src/frontend/cards/card-components.tsx @@ -1,6 +1,5 @@ -import { ActionIcon, Group, Menu, Table, Text } from "@mantine/core"; +import { Group, Menu, Table, Text } from "@mantine/core"; import { - IconDots, IconExternalLink, IconEyeOff, IconLink, @@ -11,11 +10,11 @@ import { import { IconColor, IconSize } from "../common/style-constants"; import { copyUrlToClipboard, makeUrl, openUrlInNewTab } from "../common/url"; import { PropsWithChildren, ReactNode, useCallback } from "react"; -import { AppContextMenu } from "../app-common/app-menu"; +import { AppContextMenu, MenuButton } from "../app-common/app-menu"; import { SearchHit } from "../search/search"; import { SearchHitTitle } from "../search/search-results"; import { CardThumbnail } from "../insert/thumbnail"; -import { DocumentPath } from "../../shared/onshape-path"; +import { ConfigurablePath, InstancePath } from "../../shared/onshape-path"; import { openCannotDeriveAssemblyAlert } from "../app/alerts"; import { useInsertMutation, @@ -30,9 +29,8 @@ import { RequireAccessLevel } from "../api-utils/access-level"; import { useReloadThumbnailMutation } from "./card-hooks"; interface OpenDocumentItemsProps { - path: DocumentPath; + path: InstancePath | ConfigurablePath; } - /** * Menu items which can be used to open or copy a link to a document. */ @@ -224,25 +222,6 @@ export function ItemRow(props: ItemRowProps): ReactNode { ); } -/** - * An explicit button which opens a menu with the given items. Used alongside - * the right-click context menu so the menu is reachable without a right-click. - */ -export function MenuButton(props: PropsWithChildren): ReactNode { - return ( - - e.stopPropagation()} - > - - - - ); -} - /** * Wraps one or more admin-only menu items into an Admin submenu. */ diff --git a/src/frontend/cards/insertable-card.tsx b/src/frontend/cards/insertable-card.tsx index 45ae3d5b..c05bde4d 100644 --- a/src/frontend/cards/insertable-card.tsx +++ b/src/frontend/cards/insertable-card.tsx @@ -14,6 +14,7 @@ import { getFavoriteForInsertable, InsertableOut } from "../../shared/api-models"; +import { Configuration } from "../../shared/configuration-models"; import { ElementType } from "../../shared/types"; import { SearchHit } from "../search/search"; import { @@ -114,26 +115,32 @@ export function InsertableCard(props: InsertableCardProps): ReactNode { interface InsertableMenuItemsProps { favorite: Favorite | undefined; insertable: InsertableOut; + inInsertMenu?: boolean; + configuration?: Configuration; } export function InsertableMenuItems( props: InsertableMenuItemsProps ): ReactNode { - const { favorite, insertable } = props; + const { favorite, insertable, inInsertMenu, configuration } = props; return ( <> - - + {!inInsertMenu && ( + <> + + + + )} - + -): string; -export function makeUrl( - path: DocumentPath, - configuration?: Record -): string { +export function makeUrl(path: InstancePath): string; +export function makeUrl(path: DocumentPath): string { let url = `https://cad.onshape.com/documents/${path.documentId}`; if (isInstancePath(path)) { url += `/${path.instanceType}/${path.instanceId}`; @@ -29,35 +24,29 @@ export function makeUrl( if (isElementPath(path)) { url += `/e/${path.elementId}`; } - if (configuration) { - url += "?configuration=" + encodeConfigurationForQuery(configuration); + if (isConfigurablePath(path)) { + url += + "?configuration=" + encodeConfigurationForQuery(path.configuration); } return url; } -export interface ConfigurationPath { - configuration?: string; -} - /** * Parses an Onshape document URL into an ElementPath. * Returns `undefined` if the URL could not be parsed successfully. */ -export function parseUrl( - urlString: string -): (ElementPath & ConfigurationPath) | undefined { +export function parseUrl(urlString: string): ElementPath | undefined { try { // Example pathname: /documents/769b556baf61d32b18813fd0/w/e6d6c2b3a472b97a7e352949/e/8a0c13d3b2b68a99502dc436 const url = new URL(urlString); const parts = url.pathname.split("/"); - const configuration = - url.searchParams.get("configuration") ?? undefined; + // const configuration = + // url.searchParams.get("configuration") ?? undefined; return { documentId: parts[2], instanceId: parts[4], instanceType: parts[3] as InstanceType, - elementId: parts[6], - configuration + elementId: parts[6] }; } catch { return undefined; diff --git a/src/frontend/insert/insert-menu.tsx b/src/frontend/insert/insert-menu.tsx index 8b10bbc3..58254ab3 100644 --- a/src/frontend/insert/insert-menu.tsx +++ b/src/frontend/insert/insert-menu.tsx @@ -16,6 +16,8 @@ import { NotificationAction, renderNotification } from "../common/notifications"; +import { MenuButton } from "../app-common/app-menu"; +import { InsertableMenuItems } from "../cards/insertable-card"; import { ConfigurationWrapper } from "./configurations"; import { useInsertMutation } from "./insert-hooks"; import { Configuration } from "../../shared/configuration-models"; @@ -94,6 +96,14 @@ function InsertMenuContent(props: InsertMenuContentProps): ReactNode { {parameters} + + +