Skip to content

Commit

Permalink
fix: add displayName on top of name rather than replace (#1055)
Browse files Browse the repository at this point in the history
  • Loading branch information
ckbedwell authored Feb 3, 2025
1 parent 0253f91 commit b8264af
Show file tree
Hide file tree
Showing 26 changed files with 152 additions and 93 deletions.
8 changes: 4 additions & 4 deletions src/components/CheckEditor/CheckProbes/CheckProbes.tsx
Original file line number Diff line number Diff line change
@@ -1,30 +1,30 @@
import React, { useMemo, useState } from 'react';
import { Field, Stack } from '@grafana/ui';

import { Probe } from 'types';
import { ProbeWithMetadata } from 'types';

import { PrivateProbesAlert } from './PrivateProbesAlert';
import { PROBES_FILTER_ID, ProbesFilter } from './ProbesFilter';
import { ProbesList } from './ProbesList';

interface CheckProbesProps {
probes: number[];
availableProbes: Probe[];
availableProbes: ProbeWithMetadata[];
disabled?: boolean;
onChange: (probes: number[]) => void;
onBlur?: () => void;
invalid?: boolean;
error?: string;
}
export function CheckProbes({ probes, availableProbes, onChange, error }: CheckProbesProps) {
const [filteredProbes, setFilteredProbes] = useState<Probe[]>(availableProbes);
const [filteredProbes, setFilteredProbes] = useState<ProbeWithMetadata[]>(availableProbes);

const publicProbes = useMemo(() => filteredProbes.filter((probe) => probe.public), [filteredProbes]);
const privateProbes = useMemo(() => filteredProbes.filter((probe) => !probe.public), [filteredProbes]);

const groupedByRegion = useMemo(
() =>
publicProbes.reduce((acc: Record<string, Probe[]>, curr: Probe) => {
publicProbes.reduce((acc: Record<string, ProbeWithMetadata[]>, curr: ProbeWithMetadata) => {
const region = curr.region;
if (!acc[region]) {
acc[region] = [];
Expand Down
20 changes: 13 additions & 7 deletions src/components/CheckEditor/CheckProbes/ProbesFilter.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,17 @@
import React, { useState } from 'react';

import { Probe } from 'types';
import { ProbeWithMetadata } from 'types';
import { SearchFilter } from 'components/SearchFilter';

export const PROBES_FILTER_ID = 'check-probes-filter';

export const ProbesFilter = ({ probes, onSearch }: { probes: Probe[]; onSearch: (probes: Probe[]) => void }) => {
export const ProbesFilter = ({
probes,
onSearch,
}: {
probes: ProbeWithMetadata[];
onSearch: (probes: ProbeWithMetadata[]) => void;
}) => {
const [showEmptyState, setShowEmptyState] = useState(false);
const [filterText, setFilterText] = useState('');

Expand All @@ -15,11 +21,11 @@ export const ProbesFilter = ({ probes, onSearch }: { probes: Probe[]; onSearch:
(probe) =>
probe.region.toLowerCase().includes(searchValue) ||
probe.name.toLowerCase().includes(searchValue) ||
probe.longRegion?.toLowerCase().includes(searchValue) ||
probe.city?.toLowerCase().includes(searchValue) ||
probe.provider?.toLowerCase().includes(searchValue) ||
probe.country?.toLowerCase().includes(searchValue) ||
probe.countryCode?.toLowerCase().includes(searchValue)
probe.displayName.toLowerCase().includes(searchValue) ||
probe.longRegion.toLowerCase().includes(searchValue) ||
probe.provider.toLowerCase().includes(searchValue) ||
probe.country.toLowerCase().includes(searchValue) ||
probe.countryCode.toLowerCase().includes(searchValue)
);

onSearch(filteredProbes);
Expand Down
10 changes: 5 additions & 5 deletions src/components/CheckEditor/CheckProbes/ProbesList.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { GrafanaTheme2 } from '@grafana/data';
import { Checkbox, Label, Stack, Text, TextLink, useStyles2 } from '@grafana/ui';
import { css } from '@emotion/css';

import { Probe } from 'types';
import { ProbeWithMetadata } from 'types';
import { DeprecationNotice } from 'components/DeprecationNotice/DeprecationNotice';
import { ProbeStatus } from 'components/ProbeCard/ProbeStatus';

Expand All @@ -14,7 +14,7 @@ export const ProbesList = ({
onSelectionChange,
}: {
title: string;
probes: Probe[];
probes: ProbeWithMetadata[];
selectedProbes: number[];
onSelectionChange: (probes: number[]) => void;
}) => {
Expand All @@ -29,7 +29,7 @@ export const ProbesList = ({
onSelectionChange([...selected]);
};

const handleToggleProbe = (probe: Probe) => {
const handleToggleProbe = (probe: ProbeWithMetadata) => {
if (!probe.id) {
return;
}
Expand Down Expand Up @@ -73,7 +73,7 @@ export const ProbesList = ({
</Label>
</div>
<div className={styles.probesList}>
{probes.map((probe: Probe) => (
{probes.map((probe: ProbeWithMetadata) => (
<div key={probe.id} className={styles.item}>
<Checkbox
id={`probe-${probe.id}`}
Expand All @@ -83,7 +83,7 @@ export const ProbesList = ({
<Label htmlFor={`probe-${probe.id}`}>
<div className={styles.columnLabel}>
<ProbeStatus probe={probe} />{' '}
{`${probe.name}${probe.countryCode ? `, ${probe.countryCode}` : ''} ${
{`${probe.displayName}${probe.countryCode ? `, ${probe.countryCode}` : ''} ${
probe.provider ? `(${probe.provider})` : ''
}`}
{probe.deprecated && (
Expand Down
4 changes: 2 additions & 2 deletions src/components/CheckEditor/ProbeOptions.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import React from 'react';
import { Controller, useFormContext } from 'react-hook-form';
import { Field } from '@grafana/ui';

import { CheckFormValues, CheckType, Probe } from 'types';
import { CheckFormValues, CheckType, ProbeWithMetadata } from 'types';
import { useProbesWithMetadata } from 'data/useProbes';
import { SliderInput } from 'components/SliderInput';

Expand Down Expand Up @@ -73,7 +73,7 @@ function getFrequencyBounds(checkType: CheckType) {
};
}

function getAvailableProbes(probes: Probe[], checkType: CheckType) {
function getAvailableProbes(probes: ProbeWithMetadata[], checkType: CheckType) {
if (checkType === CheckType.Scripted) {
return probes.filter((probe) => probe.capabilities.disableScriptedChecks === false);
}
Expand Down
4 changes: 2 additions & 2 deletions src/components/CheckEditor/ProbesMetadata.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { ProbeProvider } from 'types';
import { ProbeMetadata, ProbeProvider } from 'types';

const REGION_APAC = { code: 'APAC', long: 'Asia-Pacific' };
const REGION_AMER = { code: 'AMER', long: 'The Americas' };
Expand All @@ -23,7 +23,7 @@ const COUNTRY_AE = { code: 'AE', long: 'United Arab Emirates' };
const COUNTRY_ES = { code: 'ES', long: 'Spain' };
const COUNTRY_ID = { code: 'ID', long: 'Indonesia' };

export const PROBES_METADATA = [
export const PROBES_METADATA: ProbeMetadata[] = [
{
name: 'Bangalore',
region: REGION_APAC.code,
Expand Down
2 changes: 1 addition & 1 deletion src/components/DeleteProbeButton/DeleteProbeButton.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ export function DeleteProbeButton({ probe, onDeleteSuccess: _onDeleteSuccess }:
<>
You do not have sufficient permissions
<br />
to delete the probe <span className={styles.probeName}>&apos;{probe.name}&apos;</span>.
to delete the probe <span className={styles.probeName}>&apos;{probe.displayName}&apos;</span>.
</>
);

Expand Down
6 changes: 3 additions & 3 deletions src/components/DeleteProbeButton/DeleteProbeButton.utils.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
import type { BackendError } from './DeleteProbeButton.types';
import { Probe } from 'types';
import { ProbeWithMetadata } from 'types';

export function getPrettyError(error: Error | BackendError, probe: Probe) {
export function getPrettyError(error: Error | BackendError, probe: ProbeWithMetadata) {
if (!error) {
return undefined;
}

if ('data' in error && 'err' in error.data && 'msg' in error.data && typeof error.data.msg === 'string') {
return { name: error.data.err, message: error.data.msg.replace(String(probe.id), `'${probe.name}'`) };
return { name: error.data.err, message: error.data.msg.replace(String(probe.id), `'${probe.displayName}'`) };
}

return { name: 'Unknown error', message: 'An unknown error occurred' };
Expand Down
32 changes: 16 additions & 16 deletions src/components/ProbeCard/ProbeCard.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,9 @@ it(`Displays the correct information`, async () => {
const probe = probeToExtendedProbe(ONLINE_PROBE);
render(<ProbeCard probe={probe} />);

await screen.findByText(probe.name);
await screen.findByText(probe.displayName);

expect(screen.getByText((content) => content.startsWith(probe.name))).toBeInTheDocument();
expect(screen.getByText((content) => content.startsWith(probe.displayName))).toBeInTheDocument();
expect(screen.getByText(/Version:/)).toBeInTheDocument();
expect(screen.getByText(probe.version, { exact: false })).toBeInTheDocument();

Expand All @@ -36,7 +36,7 @@ it(`Displays the correct information for an online probe`, async () => {
const probe = probeToExtendedProbe(ONLINE_PROBE);

render(<ProbeCard probe={probe} />);
await screen.findByText(probe.name);
await screen.findByText(probe.displayName);

// Check status circle
const status = screen.getByTestId('probe-online-status');
Expand All @@ -47,15 +47,15 @@ it(`Displays the correct information for an online probe`, async () => {
await userEvent.hover(status);
const tooltip = await screen.findByTestId('probe-online-status-tooltip');
expect(tooltip).toBeInTheDocument();
expect(tooltip).toHaveTextContent(`Probe ${probe.name} is online`);
expect(tooltip).toHaveTextContent(`Probe ${probe.displayName} is online`);
});

it(`Displays the correct information for an offline probe`, async () => {
const { result } = renderHook<GrafanaTheme2, undefined>(useTheme2);
const probe = probeToExtendedProbe(OFFLINE_PROBE);

render(<ProbeCard probe={probe} />);
await screen.findByText(probe.name);
await screen.findByText(probe.displayName);

// Check status circle
const status = screen.getByTestId('probe-online-status');
Expand All @@ -66,14 +66,14 @@ it(`Displays the correct information for an offline probe`, async () => {
await userEvent.hover(status);
const tooltip = await screen.findByTestId('probe-online-status-tooltip');
expect(tooltip).toBeInTheDocument();
expect(tooltip).toHaveTextContent(`Probe ${probe.name} is offline`);
expect(tooltip).toHaveTextContent(`Probe ${probe.displayName} is offline`);
});

it(`Displays the correct information for a private probe`, async () => {
const probe = probeToExtendedProbe(PRIVATE_PROBE);

render(<ProbeCard probe={probe} />);
await screen.findByText(probe.name, { exact: false });
await screen.findByText(probe.displayName, { exact: false });

const button = screen.getByTestId('probe-card-action-button');
expect(button).toBeInTheDocument();
Expand All @@ -85,7 +85,7 @@ it(`Displays the correct information for a private probe as a viewer`, async ()
const probe = probeToExtendedProbe(PRIVATE_PROBE);

render(<ProbeCard probe={probe} />);
await screen.findByText(probe.name, { exact: false });
await screen.findByText(probe.displayName, { exact: false });

const button = screen.getByTestId('probe-card-action-button');
expect(button).toBeInTheDocument();
Expand All @@ -97,7 +97,7 @@ it(`Displays the correct information for a private probe as a RBAC viewer`, asyn
const probe = probeToExtendedProbe(PRIVATE_PROBE);

render(<ProbeCard probe={probe} />);
await screen.findByText(probe.name, { exact: false });
await screen.findByText(probe.displayName, { exact: false });

const button = screen.getByTestId('probe-card-action-button');
expect(button).toBeInTheDocument();
Expand All @@ -108,7 +108,7 @@ it(`Displays the correct information for a public probe`, async () => {
const probe = probeToExtendedProbe(PUBLIC_PROBE);

render(<ProbeCard probe={probe} />);
await screen.findByText(probe.name, { exact: false });
await screen.findByText(probe.displayName, { exact: false });

const button = screen.getByTestId('probe-card-action-button');
expect(button).toBeInTheDocument();
Expand All @@ -118,8 +118,8 @@ it(`Displays the correct information for a public probe`, async () => {
it('handles public probe click', async () => {
const probe = probeToExtendedProbe(PUBLIC_PROBE);
const { user } = render(<ProbeCard probe={probe} />);
await screen.findByText(probe.name);
await user.click(screen.getByText(probe.name));
await screen.findByText(probe.displayName);
await user.click(screen.getByText(probe.displayName));

expect(screen.getByTestId(DataTestIds.TEST_ROUTER_INFO_PATHNAME)).toHaveTextContent(
generateRoutePath(ROUTES.ViewProbe, { id: probe.id! })
Expand All @@ -129,8 +129,8 @@ it('handles public probe click', async () => {
it('handles private probe click', async () => {
const probe = probeToExtendedProbe(PRIVATE_PROBE);
const { user } = render(<ProbeCard probe={probe} />);
await screen.findByText(probe.name);
await user.click(screen.getByText(probe.name));
await screen.findByText(probe.displayName);
await user.click(screen.getByText(probe.displayName));

expect(screen.getByTestId(DataTestIds.TEST_ROUTER_INFO_PATHNAME)).toHaveTextContent(
generateRoutePath(ROUTES.EditProbe, { id: probe.id! })
Expand All @@ -146,7 +146,7 @@ it.each<[ExtendedProbe, string]>([
async (probe: ExtendedProbe, expectedText: string) => {
const { user } = render(<ProbeCard probe={probe} />);

await screen.findByText(probe.name);
await screen.findByText(probe.displayName);

const usageLink = screen.getByTestId(DataTestIds.PROBE_USAGE_LINK);
expect(usageLink).toBeInTheDocument();
Expand All @@ -163,7 +163,7 @@ it('Displays the correct information for a probe that is NOT in use', async () =
const probe = probeToExtendedProbe(PUBLIC_PROBE);

render(<ProbeCard probe={probe} />);
await screen.findByText(probe.name);
await screen.findByText(probe.displayName);

const usageLink = screen.queryByTestId(DataTestIds.PROBE_USAGE_LINK);
expect(usageLink).not.toBeInTheDocument();
Expand Down
6 changes: 3 additions & 3 deletions src/components/ProbeCard/ProbeCard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ export const ProbeCard = ({ probe }: { probe: ExtendedProbe }) => {
<Stack alignItems="center" gap={0}>
<ProbeStatus probe={probe} />
<Link href={probeEditHref}>
<span>{probe.name}</span>
<span>{probe.displayName}</span>
{probe.region && <span>&nbsp;{`(${probe.region})`}</span>}
</Link>
{probe.deprecated && (
Expand Down Expand Up @@ -80,7 +80,7 @@ export const ProbeCard = ({ probe }: { probe: ExtendedProbe }) => {
fill="outline"
variant="secondary"
href={probeEditHref}
aria-label={`Edit probe ${probe.name}`}
aria-label={`Edit probe ${probe.displayName}`}
tooltip="Edit probe"
>
Edit
Expand All @@ -94,7 +94,7 @@ export const ProbeCard = ({ probe }: { probe: ExtendedProbe }) => {
variant="secondary"
icon="eye"
tooltip="View probe"
aria-label={`View probe ${probe.name}`}
aria-label={`View probe ${probe.displayName}`}
>
View
</LinkButton>
Expand Down
8 changes: 4 additions & 4 deletions src/components/ProbeCard/ProbeStatus.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,16 +3,16 @@ import { GrafanaTheme2 } from '@grafana/data';
import { Tooltip, useStyles2 } from '@grafana/ui';
import { css } from '@emotion/css';

import { Probe } from 'types';
import { ProbeWithMetadata } from 'types';

export function ProbeStatus({ probe }: { probe: Probe }) {
export function ProbeStatus({ probe }: { probe: ProbeWithMetadata }) {
const styles = useStyles2((theme) => getStyles(theme, probe));

return (
<Tooltip
content={
<div data-testid="probe-online-status-tooltip">
Probe {probe.name} is <span className={styles.statusText}>{probe.online ? 'online' : 'offline'}</span>
Probe {probe.displayName} is <span className={styles.statusText}>{probe.online ? 'online' : 'offline'}</span>
</div>
}
>
Expand All @@ -21,7 +21,7 @@ export function ProbeStatus({ probe }: { probe: Probe }) {
);
}

function getStyles(theme: GrafanaTheme2, probe: Probe) {
function getStyles(theme: GrafanaTheme2, probe: ProbeWithMetadata) {
return {
container: css({
display: 'inline-block',
Expand Down
11 changes: 6 additions & 5 deletions src/data/useProbes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,14 @@ import { type QueryKey, useMutation, UseMutationResult, useQuery, useSuspenseQue
import { isFetchError } from '@grafana/runtime';

import { type MutationProps } from 'data/types';
import { ExtendedProbe, type Probe } from 'types';
import { ExtendedProbe, type Probe, ProbeMetadata, ProbeWithMetadata } from 'types';
import { FaroEvent } from 'faro';
import { camelCaseToSentence } from 'utils';
import { SMDataSource } from 'datasource/DataSource';
import type {
AddProbeResult,
DeleteProbeError,
DeleteProbeResult,
ListProbeResult,
ResetProbeTokenResult,
UpdateProbeResult,
} from 'datasource/responses.types';
Expand Down Expand Up @@ -41,21 +40,23 @@ export function useProbes() {
export function useProbesWithMetadata() {
const { data: probes = [], isLoading } = useProbes();

const probesWithMetadata = useMemo<ListProbeResult>(() => {
const probesWithMetadata = useMemo<ProbeWithMetadata[]>(() => {
if (isLoading) {
return [];
}

return probes
.sort((a, b) => a.name.localeCompare(b.name))
.map((probe) => {
const metadata = PROBES_METADATA.find((info) => info.name === probe.name && info.region === probe.region);
const metadata = PROBES_METADATA.find(
(info) => info.name === probe.name && info.region === probe.region
) as ProbeMetadata;
const displayName = camelCaseToSentence(probe.name);

return {
...probe,
...metadata,
name: displayName,
displayName,
};
});
}, [probes, isLoading]);
Expand Down
Loading

0 comments on commit b8264af

Please sign in to comment.