-
Notifications
You must be signed in to change notification settings - Fork 18
Allow links in row actions and more actions dropdowns #2751
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,18 @@ | ||
| /* | ||
| * This Source Code Form is subject to the terms of the Mozilla Public | ||
| * License, v. 2.0. If a copy of the MPL was not distributed with this | ||
| * file, you can obtain one at https://mozilla.org/MPL/2.0/. | ||
| * | ||
| * Copyright Oxide Computer Company | ||
| */ | ||
|
|
||
| import * as DropdownMenu from '~/ui/lib/DropdownMenu' | ||
|
|
||
| export function CopyIdItem({ id, label = 'Copy ID' }: { id: string; label?: string }) { | ||
| return ( | ||
| <DropdownMenu.Item | ||
| onSelect={() => window.navigator.clipboard.writeText(id)} | ||
| label={label} | ||
| /> | ||
| ) | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -6,14 +6,14 @@ | |
| * Copyright Oxide Computer Company | ||
| */ | ||
| import { useCallback } from 'react' | ||
| import { useNavigate } from 'react-router' | ||
|
|
||
| import { instanceCan, useApiMutation, type Instance } from '@oxide/api' | ||
|
|
||
| import { HL } from '~/components/HL' | ||
| import { confirmAction } from '~/stores/confirm-action' | ||
| import { confirmDelete } from '~/stores/confirm-delete' | ||
| import { addToast } from '~/stores/toast' | ||
| import type { MenuAction, MenuActionItem } from '~/table/columns/action-col' | ||
| import { pb } from '~/util/path-builder' | ||
|
|
||
| import { fancifyStates } from './common' | ||
|
|
@@ -50,7 +50,8 @@ export const useMakeInstanceActions = ( | |
| const { onResizeClick } = options | ||
|
|
||
| const makeButtonActions = useCallback( | ||
| (instance: Instance) => { | ||
| // restrict to items for now so we don't have to handle links in the calling code | ||
| (instance: Instance): MenuActionItem[] => { | ||
| const instanceParams = { path: { instance: instance.name }, query: { project } } | ||
| return [ | ||
| { | ||
|
|
@@ -116,9 +117,8 @@ export const useMakeInstanceActions = ( | |
| [project, startInstanceAsync, stopInstanceAsync] | ||
| ) | ||
|
|
||
| const navigate = useNavigate() | ||
| const makeMenuActions = useCallback( | ||
| (instance: Instance) => { | ||
| (instance: Instance): MenuAction[] => { | ||
| const instanceParams = { path: { instance: instance.name }, query: { project } } | ||
| return [ | ||
| { | ||
|
|
@@ -153,9 +153,7 @@ export const useMakeInstanceActions = ( | |
| }, | ||
| { | ||
| label: 'View serial console', | ||
| onActivate() { | ||
| navigate(pb.serialConsole({ project, instance: instance.name })) | ||
| }, | ||
| to: pb.serialConsole({ project, instance: instance.name }), | ||
|
Collaborator
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is the narrow change asked for on behalf of an external user in #1855. This allows serial console to be opened in a new tab from both instance list row actions and instance detail "more actions". |
||
| }, | ||
| { | ||
| label: 'Delete', | ||
|
|
@@ -179,7 +177,7 @@ export const useMakeInstanceActions = ( | |
| // Do not put `options` in here, refer to the property. options is not ref | ||
| // stable. Extra renders here cause the row actions menu to close when it | ||
| // shouldn't, like during polling on instance list. | ||
| [project, deleteInstanceAsync, rebootInstanceAsync, onResizeClick, navigate] | ||
| [project, deleteInstanceAsync, rebootInstanceAsync, onResizeClick] | ||
| ) | ||
|
|
||
| return { makeButtonActions, makeMenuActions } | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -7,7 +7,7 @@ | |
| */ | ||
|
|
||
| import { createColumnHelper } from '@tanstack/react-table' | ||
| import { useCallback, useMemo } from 'react' | ||
| import { useCallback } from 'react' | ||
| import { Outlet, useNavigate, type LoaderFunctionArgs } from 'react-router' | ||
|
|
||
| import { Networking16Icon, Networking24Icon } from '@oxide/design-system/icons/react' | ||
|
|
@@ -23,6 +23,7 @@ import { | |
| type RouterRoute, | ||
| type RouteTarget, | ||
| } from '~/api' | ||
| import { CopyIdItem } from '~/components/CopyIdItem' | ||
| import { DocsPopover } from '~/components/DocsPopover' | ||
| import { HL } from '~/components/HL' | ||
| import { MoreActionsMenu } from '~/components/MoreActionsMenu' | ||
|
|
@@ -97,18 +98,6 @@ export default function RouterPage() { | |
| }, | ||
| }) | ||
|
|
||
| const actions = useMemo( | ||
| () => [ | ||
| { | ||
| label: 'Copy ID', | ||
| onActivate() { | ||
| window.navigator.clipboard.writeText(routerData.id || '') | ||
| }, | ||
| }, | ||
| ], | ||
| [routerData] | ||
| ) | ||
|
|
||
| const emptyState = ( | ||
| <EmptyMessage | ||
| icon={<Networking24Icon />} | ||
|
|
@@ -197,7 +186,9 @@ export default function RouterPage() { | |
| summary="Routers are collections of routes that direct traffic between VPCs and their subnets." | ||
| links={[docLinks.routers]} | ||
| /> | ||
| <MoreActionsMenu label="Router actions" actions={actions} /> | ||
| <MoreActionsMenu label="Router actions"> | ||
| <CopyIdItem id={routerData.id} /> | ||
| </MoreActionsMenu> | ||
|
Collaborator
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. net negative lines speak for themselves I think |
||
| </div> | ||
| </PageHeader> | ||
| <PropertiesTable columns={2} className="-mt-8 mb-8"> | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -5,7 +5,6 @@ | |
| * | ||
| * Copyright Oxide Computer Company | ||
| */ | ||
| import { useMemo } from 'react' | ||
| import { useNavigate, type LoaderFunctionArgs } from 'react-router' | ||
|
|
||
| import { apiq, queryClient, useApiMutation, usePrefetchedQuery } from '@oxide/api' | ||
|
|
@@ -17,6 +16,7 @@ import { RouteTabs, Tab } from '~/components/RouteTabs' | |
| import { getVpcSelector, useVpcSelector } from '~/hooks/use-params' | ||
| import { confirmDelete } from '~/stores/confirm-delete' | ||
| import { addToast } from '~/stores/toast' | ||
| import * as DropdownMenu from '~/ui/lib/DropdownMenu' | ||
| import { PageHeader, PageTitle } from '~/ui/lib/PageHeader' | ||
| import { PropertiesTable } from '~/ui/lib/PropertiesTable' | ||
| import { pb } from '~/util/path-builder' | ||
|
|
@@ -46,33 +46,23 @@ export default function VpcPage() { | |
| }, | ||
| }) | ||
|
|
||
| const actions = useMemo( | ||
| () => [ | ||
| { | ||
| label: 'Edit', | ||
| onActivate() { | ||
| navigate(pb.vpcEdit(vpcSelector)) | ||
| }, | ||
| }, | ||
| { | ||
| label: 'Delete', | ||
| onActivate: confirmDelete({ | ||
| doDelete: () => deleteVpc({ path: { vpc: vpcName }, query: { project } }), | ||
| label: vpcName, | ||
| }), | ||
| className: 'destructive', | ||
| }, | ||
| ], | ||
| [deleteVpc, navigate, project, vpcName, vpcSelector] | ||
| ) | ||
|
|
||
| return ( | ||
| <> | ||
| <PageHeader> | ||
| <PageTitle icon={<Networking24Icon />}>{vpc.name}</PageTitle> | ||
| <div className="inline-flex gap-2"> | ||
| <VpcDocsPopover /> | ||
| <MoreActionsMenu label="VPC actions" actions={actions} /> | ||
| <MoreActionsMenu label="VPC actions"> | ||
| <DropdownMenu.LinkItem to={pb.vpcEdit(vpcSelector)}>Edit</DropdownMenu.LinkItem> | ||
| <DropdownMenu.Item | ||
| label="Delete" | ||
| onSelect={confirmDelete({ | ||
| doDelete: () => deleteVpc({ path: { vpc: vpcName }, query: { project } }), | ||
| label: vpcName, | ||
| })} | ||
| className="destructive" | ||
| /> | ||
| </MoreActionsMenu> | ||
|
Collaborator
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This shows why the children approach is nice. There's no config object where you then elsewhere have to decide what it renders. You just render those things directly. |
||
| </div> | ||
| </PageHeader> | ||
| <PropertiesTable columns={2} className="-mt-8 mb-8"> | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is the one spot where we are adding some noise, because this is the one spot where we were passing the same set of action config objects to
RowActionsin one place (instance list) andMoreActionsMenuin another (here, instance detail). BecauseMoreActionsMenuhas been converted to take children directly, we have to do the conversion to elements here. Maybe this should be extracted since it's the same as what RowActions does internally....