export function PropertyPlaceholderDropdown()

in karavan-app/src/main/webui/src/designer/property/property/PropertyPlaceholderDropdown.tsx [60:198]


export function PropertyPlaceholderDropdown(props: Props) {

    const [propertyPlaceholders, setPropertyPlaceholders, parameterPlaceholders] = useDesignerStore((s) =>
        [s.propertyPlaceholders, s.setPropertyPlaceholders, s.parameterPlaceholders], shallow)
    const [isOpenPlaceholdersDropdown, setOpenPlaceholdersDropdown] = useState<boolean>(false);
    const [propValue, setPropValue] = useState<string>('');
    const [isVisible, setIsVisible] = React.useState(false);

    function removeBrackets(val: string) {
        return val.replace('{{', '').replace('}}', '');
    }

    const {property, value} = props;
    const valueIsPlaceholder: boolean = value && value.toString().startsWith('{{') && value.toString().endsWith('}}');
    const placeholderValue = valueIsPlaceholder ? value.toString().replace('{{', '').replace('}}', '') : undefined;
    const isRouteTemplateParameter = parameterPlaceholders.map(p => p[0]).includes(placeholderValue);
    const showAddButton = valueIsPlaceholder
        && !isRouteTemplateParameter
        && !propertyPlaceholders.includes(placeholderValue)
        && !SYNTAX_EXAMPLES.map(se => se.value).includes(removeBrackets(placeholderValue))
        && SYNTAX_EXAMPLES.findIndex(se => removeBrackets(placeholderValue).startsWith(se.key)) === -1;
    const popoverId = "popover-selector-" + property.hasOwnProperty('name') ? (property as any).name : (property as any).id;

    const hasPlaceholders = (propertyPlaceholders && propertyPlaceholders.length > 0);

    function parametersChanged(value: string | number | boolean | any) {
        if (property instanceof ComponentProperty) {
            props.onComponentPropertyChange?.(property.name, `{{${value}}}`, property.kind === 'path');
        } else if (property instanceof PropertyMeta) {
            props.onDslPropertyChange?.(property.name, `{{${value}}}`);
        } else {
            props.onDslPropertyChange?.((property as Property).id, `{{${value}}}`);
        }
    }

    function onMenuToggleClick() {
        if (!showAddButton) {
            setOpenPlaceholdersDropdown(!isOpenPlaceholdersDropdown)
        }
    }

    function saveProperty() {
        InfrastructureAPI.onSavePropertyPlaceholder(placeholderValue, propValue);
        setIsVisible(false);
        const p = [...propertyPlaceholders]
        p.push(placeholderValue);
        setPropertyPlaceholders(p);
    }

    function getPopover() {
        return (
            <Popover
                isVisible={isVisible}
                shouldOpen={(_event, _fn) => setIsVisible(true)}
                shouldClose={(_event, _fn) => setIsVisible(false)}
                aria-label="Add property"
                headerContent={"Add property"}
                bodyContent={
                    <Form isHorizontal className="property-placeholder-toggle-form" autoComplete="off">
                        <FormGroup isInline label="Property" isRequired fieldId="property">
                            <TextInput id="property" readOnly value={placeholderValue}/>
                        </FormGroup>
                        <FormGroup isInline label="Value" isRequired fieldId="value">
                            <TextInput id="value" isRequired value={propValue}
                                       onChange={(_, value) => setPropValue(value)}/>
                        </FormGroup>
                    </Form>
                }
                footerContent={
                    <Flex>
                        <FlexItem align={{default: "alignRight"}}>
                            <Button
                                onClick={() => saveProperty()}>
                                Save
                            </Button>
                        </FlexItem>
                    </Flex>
                }
                triggerRef={() => document.getElementById(popoverId) as HTMLButtonElement}
            />
        )
    }

    function getToggle(toggleRef: React.Ref<MenuToggleElement>) {
        return (
            <MenuToggle className="property-placeholder-toggle"
                        id={popoverId}
                        ref={toggleRef}
                        aria-label="placeholder menu"
                        variant="default"
                        onClick={() => onMenuToggleClick()}
                        isExpanded={isOpenPlaceholdersDropdown}
            >
                {showAddButton ? <AddIcon/> : <EllipsisVIcon/>}
                {showAddButton && getPopover()}
            </MenuToggle>
        )
    }

    return (
        <Dropdown
            popperProps={{position: "end"}}
            isOpen={isOpenPlaceholdersDropdown}
            onSelect={(_, value) => {
                parametersChanged(value);
                setOpenPlaceholdersDropdown(false);
            }}
            onOpenChange={(isOpen: boolean) => setOpenPlaceholdersDropdown(isOpen)}
            toggle={(toggleRef: React.Ref<MenuToggleElement>) => getToggle(toggleRef)}
            shouldFocusToggleOnSelect
        >
            <DropdownList>
                {parameterPlaceholders &&
                    <DropdownGroup label="Template Parameters" className='property-placeholder-dropdown'>
                        {parameterPlaceholders.map((pp, index) =>
                            <DropdownItem value={pp[0]} key={index} description={pp[1]}>{pp[0]}</DropdownItem>
                        )}
                    </DropdownGroup>
                }
                {parameterPlaceholders && <Divider component="li"/>}
                {hasPlaceholders &&
                    <DropdownGroup label="Application Properties" className='property-placeholder-dropdown'>
                        {propertyPlaceholders.map((pp, index) =>
                            <DropdownItem value={pp[0]} key={index}>{pp[0]}</DropdownItem>
                        )}
                    </DropdownGroup>
                }
                {hasPlaceholders && <Divider component="li"/>}
                <DropdownGroup label="Syntax examples" className='property-placeholder-dropdown'>
                    {SYNTAX_EXAMPLES.map(se =>
                        <DropdownItem value={se.value} key={se.key} description={se.description}>
                            {se.value}
                        </DropdownItem>)
                    }
                </DropdownGroup>
            </DropdownList>
        </Dropdown>
    )
}