Implement governed distribution lists
This commit is contained in:
@@ -0,0 +1,74 @@
|
||||
import { useCallback, useMemo, useRef } from "react";
|
||||
import {
|
||||
FormField,
|
||||
SearchableSelect,
|
||||
type ApiSettings,
|
||||
type SearchableSelectOption
|
||||
} from "@govoplan/core-webui";
|
||||
import {
|
||||
listDistributionLists,
|
||||
type DistributionList
|
||||
} from "../api/distLists";
|
||||
|
||||
export type DistributionListPickerProps = {
|
||||
settings: ApiSettings;
|
||||
value: string;
|
||||
onChange: (listId: string, item: DistributionList | null) => void;
|
||||
label?: string;
|
||||
placeholder?: string;
|
||||
disabled?: boolean;
|
||||
required?: boolean;
|
||||
selected?: DistributionList | null;
|
||||
};
|
||||
|
||||
export default function DistributionListPicker({
|
||||
settings,
|
||||
value,
|
||||
onChange,
|
||||
label = "Distribution list",
|
||||
placeholder = "Search distribution lists",
|
||||
disabled = false,
|
||||
required = false,
|
||||
selected = null
|
||||
}: DistributionListPickerProps) {
|
||||
const cache = useRef(new Map<string, DistributionList>());
|
||||
if (selected) cache.current.set(selected.id, selected);
|
||||
|
||||
const selectedOption = useMemo<SearchableSelectOption | null>(() => {
|
||||
const item = selected ?? cache.current.get(value);
|
||||
if (!item) return value ? { value, label: value } : null;
|
||||
return optionFor(item);
|
||||
}, [selected, value]);
|
||||
|
||||
const loadOptions = useCallback(async (query: string) => {
|
||||
const items = await listDistributionLists(settings, query);
|
||||
for (const item of items) cache.current.set(item.id, item);
|
||||
return items.map(optionFor);
|
||||
}, [settings]);
|
||||
|
||||
return (
|
||||
<FormField label={label}>
|
||||
<SearchableSelect
|
||||
value={value}
|
||||
selectedOption={selectedOption}
|
||||
loadOptions={loadOptions}
|
||||
onChange={(nextValue) =>
|
||||
onChange(nextValue, cache.current.get(nextValue) ?? null)}
|
||||
placeholder={placeholder}
|
||||
searchPlaceholder="Search by list name"
|
||||
emptyText="No matching distribution lists."
|
||||
disabled={disabled}
|
||||
required={required}
|
||||
/>
|
||||
</FormField>
|
||||
);
|
||||
}
|
||||
|
||||
function optionFor(item: DistributionList): SearchableSelectOption {
|
||||
return {
|
||||
value: item.id,
|
||||
label: item.name,
|
||||
description: `${item.revision.entries.length} entries · revision ${item.current_revision}`,
|
||||
searchText: `${item.description ?? ""} ${item.scope_type}`
|
||||
};
|
||||
}
|
||||
Reference in New Issue
Block a user