-
Notifications
You must be signed in to change notification settings - Fork 19
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
Feat: Re-design probe selection when creating / editing checks #973
Merged
Merged
Changes from all commits
Commits
Show all changes
21 commits
Select commit
Hold shift + click to select a range
d610556
feat: display probes as checklists in columns
VikaCep 7e7d72c
feat: add private probe alert
VikaCep f631448
feat: implement probe search
VikaCep ec9a959
fix: styling and tests
VikaCep 5a575fc
fix: prevent showing alert when filtering probes
VikaCep bc523b9
fix: remove unneeded code
VikaCep 3e9e387
fix: set size constraints and enable scrolling for long probe lists
VikaCep c4a5d42
feat: add probe metadata on the frontend
VikaCep 32e4775
feat: display probe metadata and allow to filter by it
VikaCep 2b3da73
fix: update private probes description
VikaCep 2109637
fix: move check usage component back to the bottom
VikaCep 56b8f34
feat: add useLocalStorage hook and store dismissed private probe alert
VikaCep e5398c6
fix: display number of selected probes in section header
VikaCep 18c0762
fix: search for special inputs on probe filter
VikaCep 53c4f63
feat: display region description on header
VikaCep 26d9388
fix: address review comments
VikaCep 7fcec54
fix: checkbox and probe alignment
VikaCep cb0db55
fix: bring back test to make sure probes filter focuses on error
VikaCep 0b2609f
fix: lint
VikaCep cc1413a
fix: improve probes filter
VikaCep 9e4c6de
feat: create generic SearchFilter component
VikaCep File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,78 @@ | ||
import React, { forwardRef, useMemo, useState } from 'react'; | ||
import { Field, Stack } from '@grafana/ui'; | ||
|
||
import { Probe } from 'types'; | ||
|
||
import { PrivateProbesAlert } from './PrivateProbesAlert'; | ||
import { PROBES_FILTER_ID, ProbesFilter } from './ProbesFilter'; | ||
import { ProbesList } from './ProbesList'; | ||
|
||
interface CheckProbesProps { | ||
probes: number[]; | ||
availableProbes: Probe[]; | ||
disabled?: boolean; | ||
onChange: (probes: number[]) => void; | ||
onBlur?: () => void; | ||
invalid?: boolean; | ||
error?: string; | ||
} | ||
export const CheckProbes = forwardRef(({ probes, availableProbes, onChange, error }: CheckProbesProps) => { | ||
const [filteredProbes, setFilteredProbes] = useState<Probe[]>(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) => { | ||
const region = curr.region; | ||
if (!acc[region]) { | ||
acc[region] = []; | ||
} | ||
acc[region].push(curr); | ||
return acc; | ||
}, {}), | ||
[publicProbes] | ||
); | ||
|
||
const showPrivateProbesDiscovery = privateProbes.length === 0 && filteredProbes.length === availableProbes.length; | ||
|
||
return ( | ||
<div> | ||
<Field | ||
label="Probe locations" | ||
description="Select one, multiple, or all probes where this target will be checked from. Deprecated probes can be removed, but they cannot be added." | ||
invalid={!!error} | ||
error={error} | ||
htmlFor={PROBES_FILTER_ID} | ||
> | ||
<div> | ||
<ProbesFilter probes={availableProbes} onSearch={setFilteredProbes} /> | ||
<Stack wrap="wrap"> | ||
{privateProbes.length > 0 && ( | ||
<ProbesList | ||
title="Private probes" | ||
probes={privateProbes} | ||
selectedProbes={probes} | ||
onSelectionChange={onChange} | ||
/> | ||
)} | ||
|
||
{Object.entries(groupedByRegion).map(([region, allProbes]) => ( | ||
<ProbesList | ||
key={region} | ||
title={region} | ||
probes={allProbes} | ||
selectedProbes={probes} | ||
onSelectionChange={onChange} | ||
/> | ||
))} | ||
</Stack> | ||
</div> | ||
</Field> | ||
{showPrivateProbesDiscovery && <PrivateProbesAlert />} | ||
</div> | ||
); | ||
}); | ||
|
||
CheckProbes.displayName = 'CheckProbes'; |
40 changes: 40 additions & 0 deletions
40
src/components/CheckEditor/CheckProbes/PrivateProbesAlert.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,40 @@ | ||
import React from 'react'; | ||
import { Alert, LinkButton, Stack, TextLink } from '@grafana/ui'; | ||
import { useLocalStorage } from 'usehooks-ts'; | ||
|
||
import { ROUTES } from 'types'; | ||
import { getRoute } from 'components/Routing.utils'; | ||
|
||
export const PrivateProbesAlert = () => { | ||
const [dismissed, setDismissed] = useLocalStorage<boolean>('dismissedPrivateProbesAlert', false); | ||
|
||
if (dismissed) { | ||
return null; | ||
} | ||
|
||
return ( | ||
<Alert | ||
title="You haven't set up any private probes yet." | ||
severity="info" | ||
onRemove={() => { | ||
setDismissed(true); | ||
}} | ||
> | ||
<Stack gap={1} direction="column" alignItems="flex-start"> | ||
<p> | ||
Private probes are instances of the open source Grafana{' '} | ||
<TextLink | ||
href="https://grafana.com/docs/grafana-cloud/testing/synthetic-monitoring/set-up/set-up-private-probes/" | ||
external={true} | ||
> | ||
Synthetic Monitoring Agent | ||
</TextLink>{' '} | ||
and are only accessible to you. | ||
</p> | ||
<LinkButton size="sm" href={`${getRoute(ROUTES.NewProbe)}`}> | ||
Set up a Private Probe | ||
</LinkButton> | ||
</Stack> | ||
</Alert> | ||
); | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,41 @@ | ||
import React, { useState } from 'react'; | ||
|
||
import { Probe } 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 }) => { | ||
const [showEmptyState, setShowEmptyState] = useState(false); | ||
const [filterText, setFilterText] = useState(''); | ||
|
||
const handleSearch = (searchValue: string) => { | ||
setFilterText(searchValue); | ||
const filteredProbes = probes.filter( | ||
(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) | ||
); | ||
|
||
onSearch(filteredProbes); | ||
setShowEmptyState(filteredProbes.length === 0); | ||
}; | ||
|
||
return ( | ||
<> | ||
<SearchFilter | ||
onSearch={handleSearch} | ||
id={PROBES_FILTER_ID} | ||
value={filterText} | ||
showEmptyState={showEmptyState} | ||
emptyText="There are no probes matching your criteria." | ||
placeholder="Find a probe by city, country, region or provider" | ||
/> | ||
</> | ||
); | ||
}; |
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
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.
The original design used a different color and icon for this message, but with the intention of reusing and not modifying the elements we get from
grafana/ui
for consistency with other parts of the app, I've used theAlert
component withinfo
severity which displays in light blue. Happy to adapt it to the original design if you think that's better though.(edit: changed content text after Chris comments)