Skip to content

Commit

Permalink
✨ [#4524] VariableSelection grouped by source
Browse files Browse the repository at this point in the history
  • Loading branch information
robinmolen committed Sep 25, 2024
1 parent ba87f95 commit 0747766
Show file tree
Hide file tree
Showing 4 changed files with 108 additions and 13 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,12 @@ const VARIABLE_SOURCES = {
userDefined: 'user_defined',
};

const VARIABLE_SOURCES_GROUP_LABELS = {
userDefined: 'user variables',
component: 'component variables',
static: 'static variables',
};

const EMPTY_VARIABLE = {
name: '',
key: '',
Expand Down Expand Up @@ -113,6 +119,7 @@ const IDENTIFIER_ROLE_CHOICES = {
export {
COMPONENT_DATATYPES,
VARIABLE_SOURCES,
VARIABLE_SOURCES_GROUP_LABELS,
DATATYPES_CHOICES,
EMPTY_VARIABLE,
IDENTIFIER_ROLE_CHOICES,
Expand Down
41 changes: 34 additions & 7 deletions src/openforms/js/components/admin/forms/ReactSelect.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import {getReactSelectStyles} from '@open-formulieren/formio-builder/esm/components/formio/select';
import classNames from 'classnames';
import {useField} from 'formik';
import PropTypes from 'prop-types';
import ReactSelect from 'react-select';
import classNames from 'classnames';

const initialStyles = getReactSelectStyles();
const styles = {
Expand Down Expand Up @@ -32,6 +32,32 @@ const styles = {
}),
};

const getValueRecursively = (options, value) => {
if (!value) {
return null;
}

const option = options.find(opt => opt.value === value);
if (option) {
return option;
}

// Search for the option recursively
for (let i = 0; i < options.length; i++) {
const opt = options[i];
if (!opt.options) {
continue;
}

const option = getValueRecursively(opt.options, value);
if (option) {
return option;
}
}

return null;
};

/**
* A select dropdown backed by react-select for legacy usage.
*
Expand All @@ -41,8 +67,8 @@ const styles = {
* variant.
*/
const SelectWithoutFormik = ({name, options, value, className, onChange, ...props}) => {
const classes = classNames("admin-react-select", {
[`${className}`]: className
const classes = classNames('admin-react-select', {
[`${className}`]: className,
});
return (
<ReactSelect
Expand All @@ -53,7 +79,7 @@ const SelectWithoutFormik = ({name, options, value, className, onChange, ...prop
styles={styles}
menuPlacement="auto"
options={options}
value={options.find(opt => opt.value === value) || null}
value={getValueRecursively(options, value)}
onChange={selectedOption => {
onChange(selectedOption === null ? undefined : selectedOption.value);
}}
Expand All @@ -71,8 +97,8 @@ const SelectWithFormik = ({name, options, className, ...props}) => {
const [fieldProps, , fieldHelpers] = useField(name);
const {value} = fieldProps;
const {setValue} = fieldHelpers;
const classes = classNames("admin-react-select", {
[`${className}`]: className
const classes = classNames('admin-react-select', {
[`${className}`]: className,
});
return (
<ReactSelect
Expand All @@ -83,7 +109,7 @@ const SelectWithFormik = ({name, options, className, ...props}) => {
menuPlacement="auto"
options={options}
{...fieldProps}
value={options.find(opt => opt.value === value) || null}
value={getValueRecursively(options, value)}
onChange={selectedOption => {
// clear the value
if (selectedOption == null) {
Expand All @@ -99,6 +125,7 @@ const SelectWithFormik = ({name, options, className, ...props}) => {

SelectWithoutFormik.propTypes = {
name: PropTypes.string.isRequired,
onChange: PropTypes.func.isRequired,
options: PropTypes.arrayOf(PropTypes.object),
};

Expand Down
42 changes: 36 additions & 6 deletions src/openforms/js/components/admin/forms/VariableSelection.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import React, {useContext} from 'react';

import {FormContext} from 'components/admin/form_design/Context';

import {VARIABLE_SOURCES, VARIABLE_SOURCES_GROUP_LABELS} from '../form_design/variables/constants';
import {SelectWithoutFormik} from './ReactSelect';

const allowAny = () => true;
Expand All @@ -24,14 +25,37 @@ const VariableSelection = ({
});

const allFormVariables = (includeStaticVariables ? staticVariables : []).concat(formVariables);

const getVariableSource = variable => {
if (variable.source === VARIABLE_SOURCES.userDefined) {
return VARIABLE_SOURCES_GROUP_LABELS.userDefined;
}
if (variable.source === VARIABLE_SOURCES.component) {
return VARIABLE_SOURCES_GROUP_LABELS.component;
}
return VARIABLE_SOURCES_GROUP_LABELS.static;
};

const choices = allFormVariables
.filter(variable => filter(variable))
.map(variable => {
const label = formDefinitionsNames[variable.formDefinition]
? `${formDefinitionsNames[variable.formDefinition]}: ${variable.name} (${variable.key})`
: `${variable.name} (${variable.key})`;
return {value: variable.key, label};
});
.reduce(
(variableGroups, variable) => {
let label = `<span class="form-variable-dropdown__option__label">${variable.name} <code class="form-variable-dropdown__option__key">(${variable.key})</code></span>`;
if (formDefinitionsNames[variable.formDefinition]) {
label += `<span class="form-variable-dropdown__option__form-definition">${formDefinitionsNames[variable.formDefinition]}</span>`;
}

variableGroups
.find(group => group.label === getVariableSource(variable))
.options.push({value: variable.key, label});
return variableGroups;
},
[
{label: VARIABLE_SOURCES_GROUP_LABELS.userDefined, options: []},
{label: VARIABLE_SOURCES_GROUP_LABELS.component, options: []},
{label: VARIABLE_SOURCES_GROUP_LABELS.static, options: []},
]
);

return (
<SelectWithoutFormik
Expand All @@ -40,6 +64,12 @@ const VariableSelection = ({
name={name}
options={choices}
onChange={newValue => onChange({target: {name, value: newValue}})}
formatOptionLabel={data => (
<span
className="form-variable-dropdown__option"
dangerouslySetInnerHTML={{__html: data.label}}
/>
)}
value={value}
{...props}
/>
Expand Down
31 changes: 31 additions & 0 deletions src/openforms/scss/components/admin/_select.scss
Original file line number Diff line number Diff line change
@@ -1,4 +1,35 @@
.form-variable-dropdown {
--of-admin-select-min-inline-size: 300px;
min-inline-size: var(--of-admin-select-min-inline-size);
max-inline-size: var(--of-admin-select-max-inline-size);

&__option {
display: flex;
flex-direction: column;
flex-wrap: wrap;
row-gap: 4px;

&__label {
display: flex;
flex-wrap: wrap;
justify-content: space-between;
row-gap: 4px;
}

&__form-definition {
width: 100%;
font-size: 12px;
color: var(--body-quiet-color);
}
}

// The selected option only shows the label
.admin-react-select__value-container & {
&__option {
&__key,
&__form-definition {
display: none;
}
}
}
}

0 comments on commit 0747766

Please sign in to comment.