Skip to content

Commit

Permalink
chore: Group URLs in Select component (#443)
Browse files Browse the repository at this point in the history
  • Loading branch information
cristianoventura authored Jan 31, 2025
1 parent c01750a commit 14f94da
Show file tree
Hide file tree
Showing 3 changed files with 104 additions and 19 deletions.
46 changes: 34 additions & 12 deletions src/components/Form/ControlledSelect.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,17 +3,24 @@ import { ReactNode } from 'react'
import { Control, Controller, FieldValues, Path } from 'react-hook-form'

type Option = { label: ReactNode; value: string; disabled?: boolean }
type GroupedOption = { label: string; options: Option[] }

interface ControlledSelectProps<T extends FieldValues, O extends Option> {
interface ControlledSelectProps<
T extends FieldValues,
O extends Option | GroupedOption,
> {
name: Path<T>
control: Control<T>
options: O[]
selectProps?: Select.RootProps
contentProps?: Select.ContentProps
onChange?: (value: O['value']) => void
onChange?: (value: O extends Option ? O['value'] : string) => void
}

export function ControlledSelect<T extends FieldValues, O extends Option>({
export function ControlledSelect<
T extends FieldValues,
O extends Option | GroupedOption,
>({
name,
control,
options,
Expand All @@ -37,15 +44,30 @@ export function ControlledSelect<T extends FieldValues, O extends Option>({
css={{ width: '100%' }}
/>
<Select.Content {...contentProps}>
{options.map((option) => (
<Select.Item
key={option.value}
value={option.value}
disabled={option.disabled}
>
{option.label}
</Select.Item>
))}
{options.map((option) =>
'options' in option ? (
<Select.Group key={option.label}>
<Select.Label>{option.label}</Select.Label>
{option.options.map((subOption) => (
<Select.Item
key={subOption.value}
value={subOption.value}
disabled={subOption.disabled}
>
{subOption.label}
</Select.Item>
))}
</Select.Group>
) : (
<Select.Item
key={option.value}
value={option.value}
disabled={option.disabled}
>
{option.label}
</Select.Item>
)
)}
</Select.Content>
</Select.Root>
)}
Expand Down
28 changes: 21 additions & 7 deletions src/views/Generator/TestOptions/Thresholds/ThresholdRow.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,24 +14,27 @@ import {
THRESHOLD_CONDITIONS_OPTIONS,
getMetricUnit,
} from './Thresholds.utils'
import { useThresholdURLOptions } from './Thresholds.hooks'
import { css } from '@emotion/react'
import { useTheme } from '@/hooks/useTheme'

export function ThresholdRow({
field,
index,
remove,
}: {
type ThresholdRowProps = {
index: number
field: FieldArrayWithId<ThresholdData, 'thresholds', 'id'>
remove: UseFieldArrayRemove
}) {
}

export function ThresholdRow({ field, index, remove }: ThresholdRowProps) {
const {
register,
formState: { errors },
control,
watch,
} = useFormContext<ThresholdData>()

const urlOptions = useThresholdURLOptions()
const threshold = watch('thresholds')[index]
const theme = useTheme()

return (
<Table.Row key={field.id}>
Expand All @@ -47,9 +50,20 @@ export function ThresholdRow({
<Table.Cell>
<FieldGroup errors={errors} name={`thresholds.${index}.url`} mb="0">
<ControlledSelect
options={[]}
options={urlOptions}
control={control}
name={`thresholds.${index}.url`}
contentProps={{
css: css`
.rt-SelectLabel {
background-color: ${theme === 'dark'
? 'var(--gray-6)'
: 'var(--gray-3)'};
color: var(--sand-12);
padding: 0 var(--space-2);
}
`,
}}
/>
</FieldGroup>
</Table.Cell>
Expand Down
49 changes: 49 additions & 0 deletions src/views/Generator/TestOptions/Thresholds/Thresholds.hooks.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
import { selectFilteredRequests, useGeneratorStore } from '@/store/generator'

type GroupItem = { path: string; protocol: string }

export const useThresholdURLOptions = () => {
const requests = useGeneratorStore(selectFilteredRequests)

// Group requests by host
const groupedRequests = requests.reduce<Record<string, GroupItem[]>>(
(acc, { request }) => {
const { host, path, url } = request
const { protocol } = new URL(url)
if (!acc[host]) {
acc[host] = []
}
acc[host].push({ path, protocol })

return acc
},
{}
)

// Flatten the results so it can be used in the Select component
const urlOptionsMap = Object.keys(groupedRequests).map((host) => {
const addedPaths = new Set<string>()
const options: { label: string; value: string }[] = []

// Add the requests for each host
groupedRequests[host]?.forEach((request) => {
const { protocol, path } = request
const fullPath = new URL(`${protocol}//${host}${path}`).href

if (!addedPaths.has(fullPath)) {
options.push({
label: path,
value: fullPath,
})
addedPaths.add(fullPath)
}
})

return {
label: host,
options,
}
})

return [{ label: 'Across all URLs', value: '*' }, ...urlOptionsMap]
}

0 comments on commit 14f94da

Please sign in to comment.