From 08ddb4556ffb13a4a52fdf5699ea65ca1f9a33b9 Mon Sep 17 00:00:00 2001 From: Madmat8 <119794838+Madmat8@users.noreply.github.com> Date: Wed, 4 Sep 2024 15:43:24 +0200 Subject: [PATCH] JNG-5905 Fix tags component (#454) * fix tags component * fix template * fix template --- .../actor/src/components/widgets/Tags.tsx.hbs | 96 +++++++++---------- 1 file changed, 48 insertions(+), 48 deletions(-) diff --git a/judo-ui-react/src/main/resources/actor/src/components/widgets/Tags.tsx.hbs b/judo-ui-react/src/main/resources/actor/src/components/widgets/Tags.tsx.hbs index 04452822..954fbcd2 100644 --- a/judo-ui-react/src/main/resources/actor/src/components/widgets/Tags.tsx.hbs +++ b/judo-ui-react/src/main/resources/actor/src/components/widgets/Tags.tsx.hbs @@ -1,19 +1,19 @@ {{> fragment.header.hbs }} -import { type MouseEvent, type SyntheticEvent, useCallback, useMemo, useState, useRef, useEffect } from 'react'; -import clsx from 'clsx'; -import InputAdornment from '@mui/material/InputAdornment'; +import Autocomplete from '@mui/material/Autocomplete'; import ButtonGroup from '@mui/material/ButtonGroup'; import CircularProgress from '@mui/material/CircularProgress'; import IconButton from '@mui/material/IconButton'; -import Autocomplete from '@mui/material/Autocomplete'; +import InputAdornment from '@mui/material/InputAdornment'; import TextField from '@mui/material/TextField'; -import { MdiIcon } from '~/components/MdiIcon'; import { debounce } from '@mui/material/utils'; +import clsx from 'clsx'; +import { type MouseEvent, type SyntheticEvent, useCallback, useEffect, useMemo, useRef, useState } from 'react'; +import { MdiIcon } from '~/components/MdiIcon'; import { debounceInputs } from '~/config/general'; import { QueryCustomizer } from '~/services/data-api/common/QueryCustomizer'; -import { FilterByTypesString } from '~/services/data-api/rest/FilterByTypesString'; import { StringOperation } from '~/services/data-api/model/StringOperation'; +import { FilterByTypesString } from '~/services/data-api/rest/FilterByTypesString'; export interface TagsProps
{ id: string; @@ -26,6 +26,7 @@ export interface TagsProps
{
helperText?: string;
editMode?: boolean;
autoCompleteAttribute: keyof T;
+ identifierAttribute: string | keyof T;
onAutoCompleteSearch: (searchText: string, preparedQueryCustomizer: QueryCustomizer {
/**
* Experimental Tags component to serve as an alternative to aggregation->association collections.
-*/
-export function Tags (props: TagsProps ) {
+ */
+export function Tags (props: TagsProps ) {
const {
id,
label,
@@ -67,10 +68,11 @@ export function Tags (props: TagsProps ) {
createDialogTitle,
createDialogIcon = 'file-document-plus',
onClearDialogsClick,
- clearTitle= 'Clear',
+ clearTitle = 'Clear',
clearIcon = 'close',
additionalMaskAttributes = [],
limitOptions = 10,
+ identifierAttribute,
} = props;
const [options, setOptions] = useState (props: TagsProps ) {
const handleSearch = async (searchText: string) => {
try {
setLoading(true);
- const filter: FilterByTypesString[] = (ownerData[name] as T[] ?? []).map((c: any) => ({
- value: c[autoCompleteAttribute]!,
- operator: StringOperation.notEqual,
- }));
+ const filter: FilterByTypesString[] = [];
if (searchText) {
filter.push({
value: `%${searchText}%`,
@@ -90,13 +89,13 @@ export function Tags (props: TagsProps ) {
});
}
const queryCustomizer: QueryCustomizer (props: TagsProps ) {
[ownerData],
);
- const onChange = useCallback((event: SyntheticEvent, value: (string | any)[]) => {
- // prevent useEffect below from triggering recursion
- prevValues.current = value;
- onValueChange(value as any);
- }, [ownerData, onValueChange]);
+ const onChange = useCallback(
+ (event: SyntheticEvent, value: (string | any)[]) => {
+ // prevent useEffect below from triggering recursion
+ prevValues.current = value;
+ onValueChange(value as any);
+ },
+ [ownerData, onValueChange],
+ );
- const onChipClicked = useCallback((event: MouseEvent) => {
- const label = (event.target as HTMLSpanElement).textContent;
- if (label) {
- const data = (ownerData[name] as T[] ?? []).find((c: any) => c[autoCompleteAttribute] === label);
- if (data && onItemClick) {
- onItemClick(data);
+ const onChipClicked = useCallback(
+ (event: MouseEvent) => {
+ const label = (event.target as HTMLSpanElement).textContent;
+ if (label) {
+ const data = ((ownerData[name] as T[]) ?? []).find((c: any) => c[autoCompleteAttribute] === label);
+ if (data && onItemClick) {
+ onItemClick(data);
+ }
}
- }
- }, [ownerData, onItemClick]);
+ },
+ [ownerData, onItemClick],
+ );
useEffect(() => {
// prevent recursion
@@ -156,10 +161,11 @@ export function Tags (props: TagsProps ) {
readOnly={readOnly}
options={options}
loading={loading}
- value={ownerData[name] as T[] ?? []}
+ value={(ownerData[name] as T[]) ?? []}
disableClearable={true}
+ getOptionKey={(option) => option[identifierAttribute]}
getOptionLabel={(option) => option[autoCompleteAttribute] ?? ''}
- isOptionEqualToValue={(option, value) => option[autoCompleteAttribute] === value[autoCompleteAttribute]}
+ isOptionEqualToValue={(option, value) => option[identifierAttribute] === value[identifierAttribute]}
onOpen={ () => {
setOptions([]); // always start with a clean slate
handleSearch('');
@@ -187,28 +193,22 @@ export function Tags (props: TagsProps ) {
'TagsButtonGroup': true,
})}
>
- {loading ? (
- (props: TagsProps ) {
} }
/>
);
-};
+}