diff --git a/app/components/CopyCode.tsx b/app/components/CopyCode.tsx
index 930be0665..d4caa535a 100644
--- a/app/components/CopyCode.tsx
+++ b/app/components/CopyCode.tsx
@@ -5,6 +5,7 @@
*
* Copyright Oxide Computer Company
*/
+import * as m from 'motion/react-m'
import { useState, type ReactNode } from 'react'
import { Success12Icon } from '@oxide/design-system/icons/react'
@@ -13,31 +14,27 @@ import { Button } from '~/ui/lib/Button'
import { Modal } from '~/ui/lib/Modal'
import { useTimeout } from '~/ui/lib/use-timeout'
-type CopyCodeProps = {
+type CopyCodeModalProps = {
code: string
- modalButtonText: string
copyButtonText: string
modalTitle: string
footer?: ReactNode
/** rendered code */
children?: ReactNode
+ isOpen: boolean
+ onDismiss: () => void
}
-export function CopyCode({
+export function CopyCodeModal({
+ isOpen,
+ onDismiss,
code,
- modalButtonText,
copyButtonText,
modalTitle,
children,
footer,
-}: CopyCodeProps) {
- const [isOpen, setIsOpen] = useState(false)
+}: CopyCodeModalProps) {
const [hasCopied, setHasCopied] = useState(false)
-
- function handleDismiss() {
- setIsOpen(false)
- }
-
useTimeout(() => setHasCopied(false), hasCopied ? 2000 : null)
const handleCopy = () => {
@@ -47,37 +44,44 @@ export function CopyCode({
}
return (
- <>
-
-
-
-
- {children}
-
-
-
- {copyButtonText}
-
+
+
+ {children}
+
+
+
+
+ {copyButtonText}
+
+
+ {hasCopied && (
+
-
- Copied
-
- >
- }
- >
- {footer}
-
-
- >
+
+
+ )}
+ >
+ }
+ >
+ {footer}
+
+
)
}
@@ -90,15 +94,23 @@ export function EquivalentCliCommand({ project, instance }: EquivProps) {
`--instance ${instance}`,
]
+ const [isOpen, setIsOpen] = useState(false)
+
return (
-
- $
- {cmdParts.join(' \\\n ')}
-
+ <>
+
+ setIsOpen(false)}
+ >
+ $
+ {cmdParts.join(' \\\n ')}
+
+ >
)
}
diff --git a/app/pages/project/instances/instance/tabs/MetricsTab/OxqlMetric.tsx b/app/pages/project/instances/instance/tabs/MetricsTab/OxqlMetric.tsx
index 225f229ee..80d44f5a9 100644
--- a/app/pages/project/instances/instance/tabs/MetricsTab/OxqlMetric.tsx
+++ b/app/pages/project/instances/instance/tabs/MetricsTab/OxqlMetric.tsx
@@ -11,11 +11,12 @@
* https://github.com/oxidecomputer/omicron/tree/main/oximeter/oximeter/schema
*/
-import React, { Fragment, Suspense, useEffect, useMemo } from 'react'
+import React, { Fragment, Suspense, useEffect, useMemo, useState } from 'react'
import { useApiQuery, type ChartDatum, type OxqlQueryResult } from '@oxide/api'
-import { CopyCode } from '~/components/CopyCode'
+import { CopyCodeModal } from '~/components/CopyCode'
+import { MoreActionsMenu } from '~/components/MoreActionsMenu'
import { LearnMore } from '~/ui/lib/SettingsGroup'
import { intersperse } from '~/util/array'
import { classed } from '~/util/classed'
@@ -320,6 +321,8 @@ export function OxqlMetric({ title, description, ...queryObj }: OxqlMetricProps)
return getPercentChartProps(chartData, startTime, endTime)
}, [unit, chartData, startTime, endTime])
+ const [modalOpen, setModalOpen] = useState(false)
+
return (
@@ -330,15 +333,35 @@ export function OxqlMetric({ title, description, ...queryObj }: OxqlMetricProps)
{description}
-
{
+ // Turn into a real link when this is fixed
+ // https://github.com/oxidecomputer/console/issues/1855
+ const url = links.oxqlSchemaDocs(queryObj.metricName)
+ window.open(url, '_blank', 'noopener,noreferrer')
+ },
+ },
+ {
+ label: 'OxQL query',
+ onActivate: () => setModalOpen(true),
+ },
+ ]}
+ isSmall
+ />
+ setModalOpen(false)}
code={query}
- modalButtonText="OxQL"
copyButtonText="Copy query"
modalTitle="OxQL query"
footer={}
>
-
+
}>
diff --git a/app/util/links.ts b/app/util/links.ts
index e03ed3e9e..a5f0d043c 100644
--- a/app/util/links.ts
+++ b/app/util/links.ts
@@ -33,6 +33,9 @@ export const links = {
keyConceptsProjectsDocs:
'https://docs.oxide.computer/guides/key-entities-and-concepts#_projects',
oxqlDocs: 'https://docs.oxide.computer/guides/operator/system-metrics#_oxql_quickstart',
+ // TODO: update URL once https://github.com/oxidecomputer/docs/pull/426 is merged
+ oxqlSchemaDocs: (metric: string) =>
+ `https://docs-git-timeseries-guide-oxidecomputer.vercel.app/guides/operator/available-metric-data#_${metric.replace(':', '')}`,
projectsDocs: 'https://docs.oxide.computer/guides/onboarding-projects',
quickStart: 'https://docs.oxide.computer/guides/quickstart',
routersDocs: