ToolJet/frontend/src/Editor/Components/Multiselect.jsx

181 lines
5.4 KiB
React
Raw Normal View History

import _ from 'lodash';
import React, { useState, useEffect } from 'react';
import { MultiSelect } from 'react-multi-select-component';
const ItemRenderer = ({ checked, option, onClick, disabled }) => (
<div className={`item-renderer ${disabled && 'disabled'}`}>
<input type="checkbox" onClick={onClick} checked={checked} tabIndex={-1} disabled={disabled} />
<span>{option.label}</span>
</div>
);
2021-04-14 17:01:34 +00:00
2021-04-30 06:31:32 +00:00
export const Multiselect = function Multiselect({
id,
component,
2021-04-30 06:31:32 +00:00
height,
properties,
styles,
exposedVariables,
setExposedVariable,
setExposedVariables,
onComponentClick,
darkMode,
fireEvent,
dataCy,
}) {
const { label, value, values, display_values, showAllOption } = properties;
const { borderRadius, visibility, disabledState, boxShadow } = styles;
const [selected, setSelected] = useState([]);
const [searched, setSearched] = useState('');
let selectOptions = [];
try {
selectOptions = [
...values.map((value, index) => {
return { label: display_values[index], value: value };
}),
];
} catch (err) {
console.log(err);
}
2021-04-30 06:31:32 +00:00
useEffect(() => {
let newValues = [];
2021-04-30 06:31:32 +00:00
if (_.intersection(values, value)?.length === value?.length) newValues = value;
2021-04-30 06:31:32 +00:00
setExposedVariable('values', newValues);
setSelected(selectOptions.filter((option) => newValues.includes(option.value)));
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [JSON.stringify(values), JSON.stringify(display_values)]);
2021-04-30 06:31:32 +00:00
useEffect(() => {
setExposedVariable('values', value);
setSelected(selectOptions.filter((option) => value.includes(option.value)));
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [JSON.stringify(value), JSON.stringify(display_values)]);
2021-04-30 06:31:32 +00:00
useEffect(() => {
if (value && !selected) {
setSelected(selectOptions.filter((option) => properties.value.includes(option.value)));
}
if (JSON.stringify(exposedVariables.values) === '{}') {
setSelected(selectOptions.filter((option) => properties.value.includes(option.value)));
}
// eslint-disable-next-line react-hooks/exhaustive-deps
2022-03-03 15:06:49 +00:00
}, []);
const onChangeHandler = (items) => {
setSelected(items);
setExposedVariable(
'values',
items.map((item) => item.value)
Feature :: Exposing CSA for child widgets of form and listview (#7142) * feat :: exposing child widget of form and listview , removing register action * feat :: exposing only components and not child items * fix :: removing value of funcation info * lint fixes * reverted * test commit :: lint fix * fix :: initial render showing all components * fix :: data and children values are same * kanban breaking fix * fix for exposed variable not being accessible in initial render * comments * fix :: all components showing up in inspector during initial render for form and listview widget * reduce rerenders in button due to exposed vars * combining useeffects for lesser rerenders * fix showing of child widgets of list and form in inspector during intial render * fix :: ui break * combining useeffects in form * test commit :: reducing rerenders fromsetexposed variable called multipole time * fix :: reduce rerenders by combining multiple setExosedvariable calls * Revert "fix :: reduce rerenders by combining multiple setExosedvariable calls" This reverts commit 78c9e469444843fbbb7b0632632d54f30254c4ee. * bugfix * bugfix :: events not firing * fixes and revertions * fix :: perf checking for parent in box in case of form and listview * fix :: initial render bug * fix :: removed csa functions from listview data key * fix bugs , actions not working * fix :: dependencies * fix :: testing bugs * tabs:: event firing bug * fix :: multiselect not firing event * bugfix :: multiselect csa not triggering * fix :: kanban csa * fix :: table csa , kanban move card * fix :: bug filepicker csa
2023-09-01 08:25:03 +00:00
);
fireEvent('onSelect');
};
2021-04-30 06:31:32 +00:00
Feature :: Exposing CSA for child widgets of form and listview (#7142) * feat :: exposing child widget of form and listview , removing register action * feat :: exposing only components and not child items * fix :: removing value of funcation info * lint fixes * reverted * test commit :: lint fix * fix :: initial render showing all components * fix :: data and children values are same * kanban breaking fix * fix for exposed variable not being accessible in initial render * comments * fix :: all components showing up in inspector during initial render for form and listview widget * reduce rerenders in button due to exposed vars * combining useeffects for lesser rerenders * fix showing of child widgets of list and form in inspector during intial render * fix :: ui break * combining useeffects in form * test commit :: reducing rerenders fromsetexposed variable called multipole time * fix :: reduce rerenders by combining multiple setExosedvariable calls * Revert "fix :: reduce rerenders by combining multiple setExosedvariable calls" This reverts commit 78c9e469444843fbbb7b0632632d54f30254c4ee. * bugfix * bugfix :: events not firing * fixes and revertions * fix :: perf checking for parent in box in case of form and listview * fix :: initial render bug * fix :: removed csa functions from listview data key * fix bugs , actions not working * fix :: dependencies * fix :: testing bugs * tabs:: event firing bug * fix :: multiselect not firing event * bugfix :: multiselect csa not triggering * fix :: kanban csa * fix :: table csa , kanban move card * fix :: bug filepicker csa
2023-09-01 08:25:03 +00:00
useEffect(() => {
const exposedVariables = {
selectOption: async function (value) {
if (
selectOptions.some((option) => option.value === value) &&
!selected.some((option) => option.value === value)
) {
const newSelected = [
...selected,
...selectOptions.filter(
(option) =>
option.value === value && !selected.map((selectedOption) => selectedOption.value).includes(value)
),
];
setSelected(newSelected);
setExposedVariable(
'values',
newSelected.map((item) => item.value)
);
fireEvent('onSelect');
}
},
deselectOption: async function (value) {
if (
selectOptions.some((option) => option.value === value) &&
selected.some((option) => option.value === value)
) {
const newSelected = [
...selected.filter(function (item) {
return item.value !== value;
}),
];
setSelected(newSelected);
setExposedVariable(
'values',
newSelected.map((item) => item.value)
);
fireEvent('onSelect');
}
},
clearSelections: async function () {
if (selected.length >= 1) {
setSelected([]);
setExposedVariable('values', []);
fireEvent('onSelect');
}
},
};
setExposedVariables(exposedVariables);
Feature :: Exposing CSA for child widgets of form and listview (#7142) * feat :: exposing child widget of form and listview , removing register action * feat :: exposing only components and not child items * fix :: removing value of funcation info * lint fixes * reverted * test commit :: lint fix * fix :: initial render showing all components * fix :: data and children values are same * kanban breaking fix * fix for exposed variable not being accessible in initial render * comments * fix :: all components showing up in inspector during initial render for form and listview widget * reduce rerenders in button due to exposed vars * combining useeffects for lesser rerenders * fix showing of child widgets of list and form in inspector during intial render * fix :: ui break * combining useeffects in form * test commit :: reducing rerenders fromsetexposed variable called multipole time * fix :: reduce rerenders by combining multiple setExosedvariable calls * Revert "fix :: reduce rerenders by combining multiple setExosedvariable calls" This reverts commit 78c9e469444843fbbb7b0632632d54f30254c4ee. * bugfix * bugfix :: events not firing * fixes and revertions * fix :: perf checking for parent in box in case of form and listview * fix :: initial render bug * fix :: removed csa functions from listview data key * fix bugs , actions not working * fix :: dependencies * fix :: testing bugs * tabs:: event firing bug * fix :: multiselect not firing event * bugfix :: multiselect csa not triggering * fix :: kanban csa * fix :: table csa , kanban move card * fix :: bug filepicker csa
2023-09-01 08:25:03 +00:00
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [selected, setSelected]);
const filterOptions = (options, filter) => {
setSearched(filter);
if (searched !== filter) {
setExposedVariable('searchText', filter);
fireEvent('onSearchTextChanged');
}
if (!filter) return options;
return options.filter(
({ label, value }) => label != null && value != null && label.toLowerCase().includes(filter.toLowerCase())
);
};
2021-04-30 06:31:32 +00:00
return (
<div
className="multiselect-widget row g-0"
data-cy={dataCy}
style={{ height, display: visibility ? '' : 'none' }}
onFocus={() => {
onComponentClick(this, id, component);
}}
>
<div className="col-auto my-auto d-flex align-items-center">
<label
style={{ marginRight: label ? '1rem' : '', marginBottom: 0 }}
className={`form-label py-1 ${darkMode ? 'text-light' : 'text-secondary'}`}
data-cy={`multiselect-label-${component.name.toLowerCase()}`}
>
{label}
</label>
2021-04-30 06:31:32 +00:00
</div>
<div className="col px-0 h-100" style={{ borderRadius: parseInt(borderRadius), boxShadow }}>
<MultiSelect
hasSelectAll={showAllOption ?? false}
2021-04-30 06:31:32 +00:00
options={selectOptions}
value={selected}
onChange={onChangeHandler}
labelledBy={'Select'}
disabled={disabledState}
className={`multiselect-box${darkMode ? ' dark dark-multiselectinput' : ''}`}
ItemRenderer={ItemRenderer}
filterOptions={filterOptions}
debounceDuration={0}
2021-04-30 06:31:32 +00:00
/>
</div>
</div>
);
2021-04-14 17:01:34 +00:00
};