All files / blong-browser/src/widgets MultiSelectTreeTableWidget.tsx

47.14% Statements 33/70
100% Branches 1/1
0% Functions 0/1
47.14% Lines 33/70

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 711x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x                                                                            
import type {IWidgetProps} from '@feasibleone/blong';
import {useEffect, useState} from 'react';
import {useBlong} from '../context/BlongContext.js';
import {dropdownRegistry} from '../model/dropdownRegistry.js';
import {Column, TreeTable, type TreeNode} from '../primereact/index.js';
 
export function MultiSelectTreeTableWidget({
    id,
    name,
    schema,
    value,
    onChange,
    error,
    readOnly,
    disabled,
}: IWidgetProps) {
    const {fetch: fetchAction, options: staticOptions, dropdown: dropdownKey} = schema.widget ?? {};
    const {handler} = useBlong();
    const [options, setOptions] = useState<unknown[]>(staticOptions ?? []);
 
    useEffect(() => {
        if (staticOptions) return;
        let cancelled = false;
 
        if (dropdownKey) {
            const loader = (key: string) =>
                (
                    handler.portalDropdownList({names: [key]}, {}) as Promise<
                        Record<string, unknown>
                    >
                ).then(result => result[key] as unknown[]);
            dropdownRegistry
                .get(dropdownKey, loader as Parameters<typeof dropdownRegistry.get>[1])
                .then(data => {
                    if (!cancelled) setOptions(data as unknown[]);
                })
                .catch(() => {});
            return () => {
                cancelled = true;
            };
        }

        if (!fetchAction) return;
        (handler[fetchAction]({}, {}) as Promise<unknown[]>)
            .then(data => {
                if (!cancelled) setOptions(Array.isArray(data) ? data : []);
            })
            .catch(() => {});
        return () => {
            cancelled = true;
        };
    }, [fetchAction, dropdownKey, handler, staticOptions]);

    return (
        <TreeTable
            data-testid={id ?? name}
            value={options as TreeNode[]}
            selectionKeys={value as Record<string, {checked?: boolean; partialChecked?: boolean}>}
            onSelectionChange={e => onChange(e.value ?? null)}
            selectionMode="checkbox"
            disabled={disabled || readOnly}
            className={`blong-multiselect-tree-table w-full ${error ? 'p-invalid' : ''}`}
        >
            <Column
                expander
                body={(node: TreeNode) => (node as Record<string, unknown>).label as string}
            />
        </TreeTable>
    );
}