mirror of
https://github.com/ToolJet/ToolJet
synced 2026-05-24 09:28:31 +00:00
Implemented sorting for dropdown and multiselect in component and properties panel.
This commit is contained in:
parent
1082190e98
commit
26ac5ffdce
3 changed files with 75 additions and 24 deletions
|
|
@ -1,4 +1,4 @@
|
|||
import React, { useState, useEffect } from 'react';
|
||||
import React, { useState, useEffect, useRef } from 'react';
|
||||
import Accordion from '@/_ui/Accordion';
|
||||
import { EventManager } from '../EventManager';
|
||||
import { renderElement } from '../Utils';
|
||||
|
|
@ -27,12 +27,13 @@ export function Select({ componentMeta, darkMode, ...restProps }) {
|
|||
allComponents,
|
||||
pages,
|
||||
} = restProps;
|
||||
|
||||
const isInitialRender = useRef(true);
|
||||
const getResolvedValue = useStore((state) => state.getResolvedValue, shallow);
|
||||
const isMultiSelect = component?.component?.component === 'MultiselectV2';
|
||||
|
||||
const isDynamicOptionsEnabled = getResolvedValue(component?.component?.definition?.properties?.advanced?.value);
|
||||
|
||||
const isSortingEnabled = componentMeta?.properties['sort'] ?? false;
|
||||
const sort = component?.component?.definition?.properties?.sort?.value;
|
||||
|
||||
const constructOptions = () => {
|
||||
let optionsValue = component?.component?.definition?.properties?.options?.value;
|
||||
|
|
@ -83,6 +84,15 @@ export function Select({ componentMeta, darkMode, ...restProps }) {
|
|||
}
|
||||
}
|
||||
|
||||
const sortArray = (arr) => {
|
||||
if (sort === 'asc') {
|
||||
return arr.sort((a, b) => a.label?.localeCompare(b.label));
|
||||
} else if (sort === 'desc') {
|
||||
return arr.sort((a, b) => b.label?.localeCompare(a.label));
|
||||
}
|
||||
return arr;
|
||||
};
|
||||
|
||||
const getItemStyle = (isDragging, draggableStyle) => ({
|
||||
userSelect: 'none',
|
||||
...draggableStyle,
|
||||
|
|
@ -92,6 +102,15 @@ export function Select({ componentMeta, darkMode, ...restProps }) {
|
|||
paramUpdated({ name: 'options' }, 'value', options, 'properties', false, props);
|
||||
};
|
||||
|
||||
const updateSortParam = (value) => {
|
||||
paramUpdated({ name: 'sort' }, 'value', value, 'properties');
|
||||
};
|
||||
|
||||
const updateOptions = (options) => {
|
||||
setOptions(options);
|
||||
updateAllOptionsParams(options);
|
||||
};
|
||||
|
||||
const generateNewOptions = () => {
|
||||
let found = false;
|
||||
let label = '';
|
||||
|
|
@ -117,8 +136,8 @@ export function Select({ componentMeta, darkMode, ...restProps }) {
|
|||
const handleAddOption = () => {
|
||||
let _option = generateNewOptions();
|
||||
const _items = [...options, _option];
|
||||
setOptions(_items);
|
||||
updateAllOptionsParams(_items);
|
||||
const sortedItems = sortArray(_items);
|
||||
updateOptions(sortedItems);
|
||||
};
|
||||
|
||||
const handleDeleteOption = (index) => {
|
||||
|
|
@ -137,8 +156,7 @@ export function Select({ componentMeta, darkMode, ...restProps }) {
|
|||
}
|
||||
return option;
|
||||
});
|
||||
setOptions(_options);
|
||||
updateAllOptionsParams(_options);
|
||||
updateOptions(_options);
|
||||
};
|
||||
|
||||
const handleValueChange = (value, index) => {
|
||||
|
|
@ -151,16 +169,17 @@ export function Select({ componentMeta, darkMode, ...restProps }) {
|
|||
}
|
||||
return option;
|
||||
});
|
||||
setOptions(_options);
|
||||
updateAllOptionsParams(_options);
|
||||
updateOptions(_options);
|
||||
};
|
||||
|
||||
const reorderOptions = async (startIndex, endIndex) => {
|
||||
const result = [...options];
|
||||
const [removed] = result.splice(startIndex, 1);
|
||||
result.splice(endIndex, 0, removed);
|
||||
setOptions(result);
|
||||
updateAllOptionsParams(result);
|
||||
updateOptions(result);
|
||||
if (isSortingEnabled && sort !== 'none') {
|
||||
updateSortParam('none');
|
||||
}
|
||||
};
|
||||
|
||||
const onDragEnd = ({ source, destination }) => {
|
||||
|
|
@ -203,8 +222,7 @@ export function Select({ componentMeta, darkMode, ...restProps }) {
|
|||
};
|
||||
}
|
||||
});
|
||||
setOptions(_options);
|
||||
updateAllOptionsParams(_options);
|
||||
updateOptions(_options);
|
||||
setMarkedAsDefault(_value);
|
||||
paramUpdated({ name: 'value' }, 'value', _value, 'properties');
|
||||
}
|
||||
|
|
@ -223,8 +241,7 @@ export function Select({ componentMeta, darkMode, ...restProps }) {
|
|||
}
|
||||
return option;
|
||||
});
|
||||
setOptions(_options);
|
||||
updateAllOptionsParams(_options);
|
||||
updateOptions(_options);
|
||||
};
|
||||
|
||||
const handleDisableChange = (value, index) => {
|
||||
|
|
@ -240,8 +257,7 @@ export function Select({ componentMeta, darkMode, ...restProps }) {
|
|||
}
|
||||
return option;
|
||||
});
|
||||
setOptions(_options);
|
||||
updateAllOptionsParams(_options);
|
||||
updateOptions(_options);
|
||||
};
|
||||
|
||||
const handleOnFxPress = (active, index, key) => {
|
||||
|
|
@ -257,12 +273,20 @@ export function Select({ componentMeta, darkMode, ...restProps }) {
|
|||
}
|
||||
return option;
|
||||
});
|
||||
setOptions(_options);
|
||||
updateAllOptionsParams(_options);
|
||||
updateOptions(_options);
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
setOptions(constructOptions());
|
||||
if (!isInitialRender.current && isSortingEnabled) {
|
||||
const sortedOptions = sortArray([...options]);
|
||||
updateOptions(sortedOptions);
|
||||
}
|
||||
}, [sort]);
|
||||
|
||||
useEffect(() => {
|
||||
const sortedOptions = sortArray(constructOptions());
|
||||
updateOptions(sortedOptions);
|
||||
isInitialRender.current = false;
|
||||
}, [isMultiSelect, component?.id]);
|
||||
|
||||
const _renderOverlay = (item, index) => {
|
||||
|
|
@ -389,6 +413,12 @@ export function Select({ componentMeta, darkMode, ...restProps }) {
|
|||
trigger="click"
|
||||
placement="left"
|
||||
rootClose
|
||||
onExited={() => {
|
||||
if (isSortingEnabled && sort !== 'none') {
|
||||
const sortedOptions = sortArray([...options]);
|
||||
updateOptions(sortedOptions);
|
||||
}
|
||||
}}
|
||||
overlay={_renderOverlay(item, index)}
|
||||
>
|
||||
<div key={item.value}>
|
||||
|
|
|
|||
|
|
@ -68,6 +68,7 @@ export const DropdownV2 = ({
|
|||
loadingState: dropdownLoadingState,
|
||||
disabledState,
|
||||
optionsLoadingState,
|
||||
sort,
|
||||
} = properties;
|
||||
const {
|
||||
selectedTextColor,
|
||||
|
|
@ -112,6 +113,16 @@ export const DropdownV2 = ({
|
|||
const foundItem = _schema?.find((item) => item?.default === true);
|
||||
return !hasVisibleFalse(foundItem?.value) ? foundItem?.value : undefined;
|
||||
}
|
||||
|
||||
const sortArray = (arr) => {
|
||||
if (sort === 'asc') {
|
||||
return arr.sort((a, b) => a.label?.localeCompare(b.label));
|
||||
} else if (sort === 'desc') {
|
||||
return arr.sort((a, b) => b.label?.localeCompare(a.label));
|
||||
}
|
||||
return arr;
|
||||
};
|
||||
|
||||
const selectOptions = useMemo(() => {
|
||||
let _options = advanced ? schema : options;
|
||||
if (Array.isArray(_options)) {
|
||||
|
|
@ -124,11 +135,11 @@ export const DropdownV2 = ({
|
|||
isDisabled: data?.disable ?? false,
|
||||
}));
|
||||
|
||||
return _selectOptions;
|
||||
return sortArray(_selectOptions);
|
||||
} else {
|
||||
return [];
|
||||
}
|
||||
}, [advanced, schema, options]);
|
||||
}, [advanced, schema, options, sort]);
|
||||
|
||||
function selectOption(value) {
|
||||
const val = selectOptions.filter((option) => !option.isDisabled)?.find((option) => option.value === value);
|
||||
|
|
|
|||
|
|
@ -36,6 +36,7 @@ export const MultiselectV2 = ({
|
|||
placeholder,
|
||||
loadingState: multiSelectLoadingState,
|
||||
optionsLoadingState,
|
||||
sort,
|
||||
} = properties;
|
||||
const {
|
||||
selectedTextColor,
|
||||
|
|
@ -84,6 +85,15 @@ export const MultiselectV2 = ({
|
|||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [properties.visibility, multiSelectLoadingState, disabledState]);
|
||||
|
||||
const sortArray = (arr) => {
|
||||
if (sort === 'asc') {
|
||||
return arr.sort((a, b) => a.label?.localeCompare(b.label));
|
||||
} else if (sort === 'desc') {
|
||||
return arr.sort((a, b) => b.label?.localeCompare(a.label));
|
||||
}
|
||||
return arr;
|
||||
};
|
||||
|
||||
const selectOptions = useMemo(() => {
|
||||
const _options = advanced ? schema : options;
|
||||
let _selectOptions = Array.isArray(_options)
|
||||
|
|
@ -96,9 +106,9 @@ export const MultiselectV2 = ({
|
|||
isDisabled: data?.disable ?? false,
|
||||
}))
|
||||
: [];
|
||||
return _selectOptions;
|
||||
return sortArray(_selectOptions);
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [advanced, JSON.stringify(schema), JSON.stringify(options)]);
|
||||
}, [advanced, JSON.stringify(schema), JSON.stringify(options), sort]);
|
||||
|
||||
function findDefaultItem(value, isAdvanced, isDefault) {
|
||||
if (isAdvanced) {
|
||||
|
|
|
|||
Loading…
Reference in a new issue