diff --git a/app/components/MoreActionsMenu.tsx b/app/components/MoreActionsMenu.tsx
index 67a6955dd0..9c7ed5a06f 100644
--- a/app/components/MoreActionsMenu.tsx
+++ b/app/components/MoreActionsMenu.tsx
@@ -29,13 +29,19 @@ export const MoreActionsMenu = ({ actions, label }: MoreActionsMenuProps) => {
{actions.map((a) => (
}>
-
- {a.label}
-
+ {typeof a.onActivate === 'string' ? (
+
+ {a.label}
+
+ ) : (
+
+ {a.label}
+
+ )}
))}
diff --git a/app/components/TopBarPicker.tsx b/app/components/TopBarPicker.tsx
index 48ecfa4073..a6470c0e8d 100644
--- a/app/components/TopBarPicker.tsx
+++ b/app/components/TopBarPicker.tsx
@@ -115,14 +115,17 @@ const TopBarPicker = (props: TopBarPickerProps) => {
props.items.map(({ label, to }) => {
const isSelected = props.current === label
return (
-
-
-
- {label}
- {isSelected && }
-
-
-
+
+
+ {label}
+ {isSelected && }
+
+
)
})
) : (
diff --git a/app/pages/project/instances/actions.tsx b/app/pages/project/instances/actions.tsx
index f0c91316fd..25a73d36b4 100644
--- a/app/pages/project/instances/actions.tsx
+++ b/app/pages/project/instances/actions.tsx
@@ -6,7 +6,6 @@
* Copyright Oxide Computer Company
*/
import { useCallback } from 'react'
-import { useNavigate } from 'react-router-dom'
import { instanceCan, useApiMutation, type Instance } from '@oxide/api'
@@ -32,8 +31,6 @@ export const useMakeInstanceActions = (
projectSelector: { project: string },
options: Options = {}
): MakeActions => {
- const navigate = useNavigate()
-
// if you also pass onSuccess to mutate(), this one is not overridden — this
// one runs first, then the one passed to mutate()
const opts = { onSuccess: options.onSuccess }
@@ -109,9 +106,7 @@ export const useMakeInstanceActions = (
},
{
label: 'View serial console',
- onActivate() {
- navigate(pb.serialConsole(instanceSelector))
- },
+ onActivate: pb.serialConsole(instanceSelector),
},
{
label: 'Delete',
@@ -132,6 +127,6 @@ export const useMakeInstanceActions = (
},
]
},
- [projectSelector, deleteInstance, navigate, rebootInstance, startInstance, stopInstance]
+ [projectSelector, deleteInstance, rebootInstance, startInstance, stopInstance]
)
}
diff --git a/app/pages/project/vpcs/VpcPage/tabs/VpcFirewallRulesTab.tsx b/app/pages/project/vpcs/VpcPage/tabs/VpcFirewallRulesTab.tsx
index e4fab8bc61..ca4f18d6e4 100644
--- a/app/pages/project/vpcs/VpcPage/tabs/VpcFirewallRulesTab.tsx
+++ b/app/pages/project/vpcs/VpcPage/tabs/VpcFirewallRulesTab.tsx
@@ -7,7 +7,7 @@
*/
import { createColumnHelper, getCoreRowModel, useReactTable } from '@tanstack/react-table'
import { useMemo } from 'react'
-import { Outlet, useNavigate, type LoaderFunctionArgs } from 'react-router-dom'
+import { Outlet, type LoaderFunctionArgs } from 'react-router-dom'
import * as R from 'remeda'
import {
@@ -112,8 +112,6 @@ export function VpcFirewallRulesTab() {
})
const rules = useMemo(() => R.sortBy(data.rules, (r) => r.priority), [data])
- const navigate = useNavigate()
-
const updateRules = useApiMutation('vpcFirewallRulesUpdate', {
onSuccess() {
queryClient.invalidateQueries('vpcFirewallRulesView')
@@ -135,15 +133,11 @@ export function VpcFirewallRulesTab() {
getActionsCol((rule: VpcFirewallRule) => [
{
label: 'Edit',
- onActivate() {
- navigate(pb.vpcFirewallRuleEdit({ ...vpcSelector, rule: rule.name }))
- },
+ onActivate: pb.vpcFirewallRuleEdit({ ...vpcSelector, rule: rule.name }),
},
{
label: 'Clone',
- onActivate() {
- navigate(pb.vpcFirewallRuleClone({ ...vpcSelector, rule: rule.name }))
- },
+ onActivate: pb.vpcFirewallRuleClone({ ...vpcSelector, rule: rule.name }),
},
{
label: 'Delete',
@@ -160,7 +154,7 @@ export function VpcFirewallRulesTab() {
},
]),
]
- }, [navigate, rules, updateRules, vpcSelector])
+ }, [rules, updateRules, vpcSelector])
const table = useReactTable({ columns, data: rules, getCoreRowModel: getCoreRowModel() })
diff --git a/app/pages/project/vpcs/VpcPage/tabs/VpcSubnetsTab.tsx b/app/pages/project/vpcs/VpcPage/tabs/VpcSubnetsTab.tsx
index 8c0a56dd51..ae2010f60f 100644
--- a/app/pages/project/vpcs/VpcPage/tabs/VpcSubnetsTab.tsx
+++ b/app/pages/project/vpcs/VpcPage/tabs/VpcSubnetsTab.tsx
@@ -7,7 +7,7 @@
*/
import { createColumnHelper } from '@tanstack/react-table'
import { useCallback, useMemo } from 'react'
-import { Outlet, useNavigate, type LoaderFunctionArgs } from 'react-router-dom'
+import { Outlet, type LoaderFunctionArgs } from 'react-router-dom'
import {
apiQueryClient,
@@ -49,14 +49,11 @@ export function VpcSubnetsTab() {
},
})
- const navigate = useNavigate()
-
const makeActions = useCallback(
(subnet: VpcSubnet): MenuAction[] => [
{
label: 'Edit',
- onActivate: () =>
- navigate(pb.vpcSubnetsEdit({ ...vpcSelector, subnet: subnet.name })),
+ onActivate: pb.vpcSubnetsEdit({ ...vpcSelector, subnet: subnet.name }),
},
// TODO: only show if you have permission to do this
{
@@ -67,7 +64,7 @@ export function VpcSubnetsTab() {
}),
},
],
- [navigate, deleteSubnet, vpcSelector]
+ [deleteSubnet, vpcSelector]
)
const columns = useMemo(
diff --git a/app/table/columns/action-col.tsx b/app/table/columns/action-col.tsx
index a130f15fdf..9b81f390ec 100644
--- a/app/table/columns/action-col.tsx
+++ b/app/table/columns/action-col.tsx
@@ -20,7 +20,8 @@ export type MakeActions- = (item: Item) => Array
export type MenuAction = {
label: string
- onActivate: () => void
+ /** If it's a string, it's a URL and we should make it a LinkItem */
+ onActivate: string | (() => void)
disabled?: false | React.ReactNode
className?: string
}
@@ -81,16 +82,28 @@ export const getActionsCol = >(
with={}
key={kebabCase(`action-${action.label}`)}
>
-
- {action.label}
-
+ {typeof action.onActivate === 'string' ? (
+
+ {action.label}
+
+ ) : (
+
+ {action.label}
+
+ )}
)
})}