+
+
-
setIsFocused(true)} onBlur={() => setIsFocused(false)}>
- {probe.name}
-
-
-
-
-
-
-
-
- {labelsString &&
Labels: {labelsString}
}
-
Version: {probe.version}
+
+
+
{probe.name}
+ {probe.region &&
{`(${probe.region})`}}
+
+
+
+
+
+ Version: {probe.version}
+
+
+
+
+ )}
+
+
-
-
-
-
+
+
+
+ {canEdit ? (
+ <>
+
+ Edit
+
+ >
+ ) : (
+
+ View
+
+ )}
+
);
};
-const getStyles = (theme: GrafanaTheme2) => {
+const getStyles2 = (theme: GrafanaTheme2) => {
const containerName = `probeCard`;
- const breakpoint = theme.breakpoints.values.sm;
- const containerQuery = `@container ${containerName} (max-width: ${breakpoint}px)`;
- const mediaQuery = `@supports not (container-type: inline-size) @media (max-width: ${breakpoint}px)`;
return {
card: css({
containerName,
- containerType: `inline-size`,
- marginBottom: theme.spacing(1),
-
- '&:hover button': {
- opacity: 1,
- },
- }),
- cardContent: css({
- display: `grid`,
- gridTemplateColumns: `auto 1fr auto`,
- gridTemplateAreas: `"info gauge action"`,
-
- [containerQuery]: {
- gridTemplateAreas: `
- "info action"
- "gauge action"
- `,
- gridTemplateColumns: `1fr auto`,
- },
-
- [mediaQuery]: {
- gridTemplateAreas: `
- "info action"
- "gauge action"
- `,
- gridTemplateColumns: `1fr auto`,
- },
- }),
- info: css({
- display: `flex`,
- gap: theme.spacing(0.5),
- flexDirection: `column`,
- gridArea: `info`,
}),
- badges: css({
- display: `flex`,
+ badgeContainer: css({
+ display: `inline-flex`,
gap: theme.spacing(0.5),
- }),
- meta: css({
- color: theme.colors.text.secondary,
+ flexWrap: `wrap`,
}),
gaugeContainer: css({
display: 'flex',
justifyContent: 'flex-end',
alignItems: 'center',
gridArea: `gauge`,
-
- [containerQuery]: {
- justifyContent: 'flex-start',
- marginLeft: theme.spacing(-1),
- marginTop: theme.spacing(1),
- },
-
- [mediaQuery]: {
- justifyContent: 'flex-start',
- marginLeft: theme.spacing(-1),
- marginTop: theme.spacing(1),
- },
}),
- link: css({
- marginBottom: theme.spacing(1),
+ extendedTags: css({
+ gridRowEnd: 'span 2',
}),
- buttonWrapper: css({
- alignItems: 'center',
+ extendedDescription: css({
+ gridColumn: '1 / span 3',
display: 'flex',
- gap: theme.spacing(2),
- gridArea: `action`,
+ justifyContent: 'space-between',
}),
- button: css({
- opacity: 0,
-
- [containerQuery]: {
- opacity: 1,
- },
-
- [mediaQuery]: {
- opacity: 1,
- },
- }),
- focussed: css({
- opacity: 1,
+ labelContainer: css({
+ display: 'inline-flex',
+ flexWrap: 'wrap',
+ gap: theme.spacing(0.5),
}),
};
};
function labelsToString(labels: Label[]) {
- return labels.map(({ name, value }) => `${name}:${value}`).join(', ');
+ return labels.map(({ name, value }) => `label_${name}: ${value}`).join(', ');
}
diff --git a/src/components/ProbeCard/ProbeDisabledCapabilities.tsx b/src/components/ProbeCard/ProbeDisabledCapabilities.tsx
new file mode 100644
index 000000000..75ff86a83
--- /dev/null
+++ b/src/components/ProbeCard/ProbeDisabledCapabilities.tsx
@@ -0,0 +1,42 @@
+import React, { useMemo } from 'react';
+import { Text } from '@grafana/ui';
+
+import { type ExtendedProbe, FeatureName } from 'types';
+import { useFeatureFlag } from 'hooks/useFeatureFlag';
+
+interface ProbeDisabledCapabilitiesProps {
+ probe: ExtendedProbe;
+}
+export function ProbeDisabledCapabilities({ probe }: ProbeDisabledCapabilitiesProps) {
+ // as we only want to show that a feature is disabled if the user can use the feature to start with
+ const scriptedFeature = useFeatureFlag(FeatureName.ScriptedChecks);
+ const browserFeature = useFeatureFlag(FeatureName.BrowserChecks);
+
+ const browserChecksDisabled = probe.capabilities.disableBrowserChecks;
+ const scriptedChecksDisabled = probe.capabilities.disableScriptedChecks;
+ const noun = browserChecksDisabled && scriptedChecksDisabled ? 'types' : 'type';
+
+ const disabledChecks = useMemo(() => {
+ const disabledChecks = [];
+ if (scriptedFeature.isEnabled && scriptedChecksDisabled) {
+ disabledChecks.push('Scripted');
+ }
+
+ if (browserFeature.isEnabled && browserChecksDisabled) {
+ disabledChecks.push('Browser');
+ }
+
+ return disabledChecks.join(', ');
+ }, [browserChecksDisabled, browserFeature.isEnabled, scriptedChecksDisabled, scriptedFeature.isEnabled]);
+
+ if (!disabledChecks) {
+ return
;
+ }
+
+ return (
+
+ Unsupported check {noun}:
+ {disabledChecks}
+
+ );
+}
diff --git a/src/components/ProbeCard/ProbeLabels.tsx b/src/components/ProbeCard/ProbeLabels.tsx
new file mode 100644
index 000000000..48c2eb691
--- /dev/null
+++ b/src/components/ProbeCard/ProbeLabels.tsx
@@ -0,0 +1,27 @@
+import React, { Fragment } from 'react';
+import { Text } from '@grafana/ui';
+
+import { Probe } from 'types';
+
+const LABEL_PREFIX = 'label_';
+
+interface ProbeLabelsProps {
+ labels: Probe['labels'];
+}
+
+export function ProbeLabels({ labels }: ProbeLabelsProps) {
+ if (labels.length === 0) {
+ return null;
+ }
+
+ return labels.map(({ name, value }, index) => {
+ return (
+
+
+ {`${LABEL_PREFIX}${name}`}: {value}
+ {labels[index + 1] && ', '}
+
+
+ );
+ });
+}
diff --git a/src/components/ProbeCard/ProbeStatus.tsx b/src/components/ProbeCard/ProbeStatus.tsx
new file mode 100644
index 000000000..2418de287
--- /dev/null
+++ b/src/components/ProbeCard/ProbeStatus.tsx
@@ -0,0 +1,38 @@
+import React from 'react';
+import { GrafanaTheme2 } from '@grafana/data';
+import { Tooltip, useStyles2 } from '@grafana/ui';
+import { css } from '@emotion/css';
+
+import { Probe } from 'types';
+
+export function ProbeStatus({ probe }: { probe: Probe }) {
+ const styles = useStyles2((theme) => getStyles(theme, probe));
+
+ return (
+
+ Probe {probe.name} is {probe.online ? 'online' : 'offline'}
+
+ }
+ >
+