export default function Selection()

in src/components/Selection/index.ts [18:90]


export default function Selection(props: {
    pings: AllPings,
    selectedPings: (selected: Ping[]) => void,
    filterInfo?: (filterInfo: FilterInfo) => void,
    children: FilterSpec[],
}) {
    const loaded = createMemo(() => {
        const specs = props.children;
        const pings = props.pings;
        const filters = specs.flatMap(spec => spec.build(pings));
        const filtersByField = new Map(filters.map(f => [f.field, f]));
        const components = filters.map(f => f.component(filtersByField));

        // Load settings
        untrack(() => {
            const filterSettings = settings.selection;
            if (filterSettings) {
                for (const filter of filters) {
                    if (filter.label in filterSettings) {
                        filter.settings = filterSettings[filter.label];
                    }
                }
            }
        });
        return { filters, components };
    });

    createEffect(() => {
        const filterFunctions = loaded().filters.map(filter => filter.filterFunction()).filter(x => x !== undefined);
        const pings = [];
        for (let i = 0; i < props.pings.crashid.length; i++) {
            if (filterFunctions.every(f => f(i))) {
                pings.push(i);
            }
        }
        props.selectedPings(pings);
    });

    // Store settings
    createEffect(() => {
        const filterSettings: { [key: string]: MultiselectSettings } = {};
        for (const filter of loaded().filters) {
            const settings = filter.settings;
            if (!settings) continue;
            filterSettings[filter.label] = settings;
        }
        modifyMutable(settings.selection, reconcile(filterSettings, { merge: true }));
    });

    // Set up filterInfo based on the filters
    createEffect(() => {
        if (props.filterInfo) {
            props.filterInfo({
                countFilterValues(pings: Ping[]) {
                    const ret = [];
                    for (const f of loaded().filters) {
                        const counts = f.countValues(pings)
                        if (counts.length == 0) continue;
                        ret.push({ filterLabel: f.label, counts });
                    }
                    return ret;
                }
            });
        }
    });

    // Add right padding so that, if a scrollbar is shown, it doesn't overlay
    // on the filter scrollbars or other elements. We don't know how large the
    // scrollbar will be, so we hope for the best. There doesn't seem to be a
    // way to force classic scrollbars (with pre-allocated space), which is
    // upsetting.
    return html`<${Layout} column style=${{ "padding-right": "12px" }}>${() => loaded().components}</div>`;
};