Skip to content
Merged
Show file tree
Hide file tree
Changes from 6 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 25 additions & 10 deletions shesha-reactjs/src/components/dropdown/dropdown.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import { IncomeValueFunc, ISelectOption, OutcomeValueFunc } from '@/components/r
import { ReferenceListItemDto } from '@/apis/referenceList';
import { useStyles } from './style';
import { getTagStyle } from '@/utils/style';
import ReflistTag from '../refListDropDown/reflistTag';


export const Dropdown: FC<IDropdownProps> = ({
Expand Down Expand Up @@ -37,7 +38,7 @@ export const Dropdown: FC<IDropdownProps> = ({
tagStyle
}) => {

const { styles } = useStyles({ style, tagStyle });
const { styles } = useStyles({ style });

const selectedMode = mode === 'multiple' || mode === 'tags' ? mode : undefined;

Expand Down Expand Up @@ -79,6 +80,7 @@ export const Dropdown: FC<IDropdownProps> = ({
color: item?.color,
icon: item?.icon,
data: item?.data,
description: item?.description,
};
}, [incomeValueFunc]);

Expand All @@ -104,6 +106,7 @@ export const Dropdown: FC<IDropdownProps> = ({
data: outcomeValueFunc(fetchedItem, args),
color: fetchedItem?.color,
icon: fetchedItem?.icon,
description: fetchedItem?.description,
};
}, [labelCustomJs, outcomeValueFunc, incomeValueFunc]);

Expand Down Expand Up @@ -176,23 +179,29 @@ export const Dropdown: FC<IDropdownProps> = ({
if (displayStyle === 'tags' && mode !== 'multiple') {
return <Select
{...commonSelectProps}
className={styles.dropdown}
showSearch
style={{ ...style, width: 'max-content' }}
popupMatchSelectWidth={false}
style={{ width: 'max-content' }}
placeholder={<Tag
style={{ ...getTagStyle(tagStyle, true), background: '#d9d9d9' }}
>
{placeholder ?? <span style={{ whiteSpace: 'pre' }}>{' '}</span>}
</Tag>}
labelRender={(props) => {
const option = options.find((o) => o.value === props.value);
return <Tag
return <ReflistTag
key={props.value}
color={option?.color}
icon={((option?.icon && showIcon)) && <Icon type={option?.icon} />}
style={getTagStyle(tagStyle, !!option?.color && solidColor)}
>
{showItemName && option?.label}
</Tag>;
tagStyle={tagStyle}
showIcon={showIcon}
solidColor={solidColor}
showItemName={showItemName}
label={option?.label}
value={props.value}
tooltip={"Single"}
/>;
Comment thread
coderabbitai[bot] marked this conversation as resolved.
}}
>
{
Expand All @@ -214,12 +223,18 @@ export const Dropdown: FC<IDropdownProps> = ({
{...(displayStyle === 'tags' ? {
labelRender: (props) => {
const option = options.find((o) => o.value === props.value);
return <Tag
return <ReflistTag
showIcon={showIcon}
showItemName={showItemName}
tagStyle={tagStyle}
solidColor={solidColor}
label={option?.label}
value={props.value}
key={props.value}
tooltip={"multiple"}
color={option?.color}
icon={option?.icon && showIcon && <Icon type={option?.icon} />}
style={getTagStyle(tagStyle, !!option?.color && solidColor)}
>{showItemName && option?.label}</Tag>;
></ReflistTag>;
Comment on lines +226 to +237
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Fix hardcoded tooltip and inconsistent Icon handling.

Two issues:

  1. The hardcoded tooltip "multiple" doesn't provide useful information
  2. Icon is being wrapped in Icon component here, but ReflistTag already handles this internally
                     return <ReflistTag
                         showIcon={showIcon}
                         showItemName={showItemName}
                         tagStyle={tagStyle}
                         solidColor={solidColor}
                         label={option?.label}
                         value={props.value}
                         key={props.value}
-                        tooltip={"multiple"}
+                        tooltip={option?.description}
                         color={option?.color}
-                        icon={option?.icon && showIcon && <Icon type={option?.icon} />}
+                        icon={option?.icon}
                     ></ReflistTag>;
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
return <ReflistTag
showIcon={showIcon}
showItemName={showItemName}
tagStyle={tagStyle}
solidColor={solidColor}
label={option?.label}
value={props.value}
key={props.value}
tooltip={"multiple"}
color={option?.color}
icon={option?.icon && showIcon && <Icon type={option?.icon} />}
style={getTagStyle(tagStyle, !!option?.color && solidColor)}
>{showItemName && option?.label}</Tag>;
></ReflistTag>;
return <ReflistTag
showIcon={showIcon}
showItemName={showItemName}
tagStyle={tagStyle}
solidColor={solidColor}
label={option?.label}
value={props.value}
key={props.value}
tooltip={option?.description}
color={option?.color}
icon={option?.icon}
></ReflistTag>;
🤖 Prompt for AI Agents
In shesha-reactjs/src/components/dropdown/dropdown.tsx around lines 226 to 237,
the tooltip prop is hardcoded to "multiple" which is not informative; replace it
with a dynamic or contextually relevant value. Also, remove the wrapping of
option?.icon inside the Icon component since ReflistTag already manages icon
rendering internally, so just pass the icon data directly without wrapping.

}
} : {})}
>
Expand Down
7 changes: 2 additions & 5 deletions shesha-reactjs/src/components/dropdown/style.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,13 @@
import { createStyles } from '@/styles';
import { CSSProperties } from 'react';

export const useStyles = createStyles(({ css, cx, token }, { style, tagStyle }: { style: CSSProperties; tagStyle: CSSProperties }) => {
export const useStyles = createStyles(({ css, cx, token }, { style }: { style: CSSProperties }) => {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Mismatch between CSS variable names – font weight will not apply

You set
--ant-font-weight-strong: ${style.fontWeight};

Later, .ant-select-selection-item uses font-weight: var(--ant-font-weight); – note the missing “-strong”. This leaves the weight uncontrolled.

-      --ant-font-weight-strong: ${style.fontWeight} !important;
+      --ant-font-weight: ${style.fontWeight} !important;

Apply the same rename (or update the consumer) to restore the intended styling.

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
export const useStyles = createStyles(({ css, cx, token }, { style }: { style: CSSProperties }) => {
export const useStyles = createStyles(
({ css, cx, token }, { style }: { style: CSSProperties }) => ({
dropdown: css`
- --ant-font-weight-strong: ${style.fontWeight} !important;
+ --ant-font-weight: ${style.fontWeight} !important;
/* …other rules… */
`,
})
);
🤖 Prompt for AI Agents
In shesha-reactjs/src/components/dropdown/style.ts at line 4, the CSS variable
for font weight is defined as --ant-font-weight-strong but the style uses
--ant-font-weight, causing the font weight not to apply. To fix this, rename the
CSS variable to --ant-font-weight to match the usage in
.ant-select-selection-item or update the consumer to use
--ant-font-weight-strong consistently, ensuring the font weight is correctly
applied.


const dropdown = cx("sha-dropdown", css`
--ant-color-text: ${style.color} !important;
--ant-font-size: ${style.fontSize} !important;
--ant-font-weight-strong: ${style.fontWeight} !important;
--ant-select-multiple-item-bg: transparent !important;
--ant-select-multiple-item-height: ${tagStyle.height} !important;

.ant-select-selector{
overflow: auto;
Expand All @@ -31,16 +30,14 @@ export const useStyles = createStyles(({ css, cx, token }, { style, tagStyle }:

:hover {
border: none !important;
.ant-tag {
.ant-tag {
align-content: center;
cursor: default !important;
pointer-events: none !important;
}
}
Comment on lines +33 to 38
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Hover disables pointer events on all nested tags – may break close icon

pointer-events:none on .ant-tag during hover prevents the built-in close (‘x’) button from receiving clicks in multi-select mode. If read-only behaviour is desired, guard it with a prop instead of unconditional CSS.

Consider:

  .ant-tag[disabled] { pointer-events:none; }
🤖 Prompt for AI Agents
In shesha-reactjs/src/components/dropdown/style.ts around lines 33 to 38, the
CSS rule unconditionally sets pointer-events:none on .ant-tag during hover,
which disables interaction with the close icon in multi-select mode. To fix
this, remove the unconditional pointer-events:none and instead apply it
conditionally using a prop or attribute, such as .ant-tag[disabled] {
pointer-events:none; }, so that pointer events are only disabled when explicitly
desired.

}



&.ant-select-open, &:hover {
border-color: ${token.colorPrimary} !important;
}
Expand Down
42 changes: 25 additions & 17 deletions shesha-reactjs/src/components/readOnlyDisplayFormItem/index.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Space, Switch, Tag } from 'antd';
import { Space, Switch } from 'antd';
import Checkbox from 'antd/lib/checkbox/Checkbox';
import { ValueRenderer } from '@/components/valueRenderer/index';
import React, { FC, useMemo } from 'react';
Expand All @@ -7,7 +7,7 @@ import { ISelectOption } from '@/components/autocomplete';
import QuickView, { GenericQuickView } from '@/components/quickView';
import { IReadOnlyDisplayFormItemProps } from './models';
import { useStyles } from './styles/styles';
import { getTagStyle } from '@/utils/style';
import ReflistTag from '../refListDropDown/reflistTag';

type AutocompleteType = ISelectOption;

Expand Down Expand Up @@ -78,13 +78,18 @@ export const ReadOnlyDisplayFormItem: FC<IReadOnlyDisplayFormItemProps> = (props
/>
);
} else {
return dropdownDisplayMode === 'tags' ? <Tag
color={value?.color}
icon={((value?.icon && showIcon)) && <Icon type={value?.icon} />}
style={getTagStyle(style, !!value?.color && solidColor)}
>
{showItemName && displayName}
</Tag> : displayName || value;
return dropdownDisplayMode === 'tags' ?
<ReflistTag
value={value}
color={value?.color}
icon={value?.icon}
showIcon={showIcon}
tagStyle={style}
tooltip={value?.description}
solidColor={solidColor}
showItemName={showItemName}
label={displayName}
/> : displayName ?? value;
}
}

Expand All @@ -97,16 +102,19 @@ export const ReadOnlyDisplayFormItem: FC<IReadOnlyDisplayFormItemProps> = (props
return dropdownDisplayMode === 'raw'
? values?.join(', ')
: <Space size={8}>
{value?.map(({ label, color, icon, value }) => {

return <Tag
{value?.map(({ label, color, icon, value, description }) => {
return <ReflistTag
key={value}
value={value}
color={color}
icon={((icon && showIcon)) && <Icon type={icon} />}
style={getTagStyle(style, !!color && solidColor)}
>
{showItemName && label}
</Tag>;
icon={icon}
tooltip={description}
showIcon={showIcon}
tagStyle={style}
solidColor={solidColor}
showItemName={showItemName}
label={label}
/>;
})}
</Space>;
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
import { Empty, Select, Spin, Tag } from 'antd';
import { Empty, Select, Spin } from 'antd';
import { ValidationErrors } from '@/components';
import { useReferenceList } from '@/providers/referenceListDispatcher';
import React, { useMemo } from 'react';
import { ReferenceListItemDto } from '@/apis/referenceList';
import ReadOnlyDisplayFormItem, { Icon } from '@/components/readOnlyDisplayFormItem';
import ReadOnlyDisplayFormItem from '@/components/readOnlyDisplayFormItem';
import { CustomLabeledValue, IGenericRefListDropDownProps, ISelectOption } from './models';
import { getTagStyle } from '@/utils/style';
import ReflistTag from './reflistTag';

// tslint:disable-next-line:whitespace
export const GenericRefListDropDown = <TValue,>(props: IGenericRefListDropDownProps<TValue>) => {
Expand Down Expand Up @@ -35,6 +35,7 @@ export const GenericRefListDropDown = <TValue,>(props: IGenericRefListDropDownPr
...rest
} = props;
const { data: refList, loading: refListLoading, error: refListError } = useReferenceList(referenceListId);

const filter = ({ itemValue }: ReferenceListItemDto) => {
if (!filters?.length) {
return true;
Expand Down Expand Up @@ -122,6 +123,7 @@ export const GenericRefListDropDown = <TValue,>(props: IGenericRefListDropDownPr
value={wrapValue(value, options)}
disabled={disabled}
showIcon={showIcon}
showItemName={showItemName}
solidColor={solidColor}
style={displayStyle === 'tags' ? tagStyle : style}
dropdownDisplayMode={displayStyle === 'tags' ? 'tags' : 'raw'}
Expand Down Expand Up @@ -164,12 +166,18 @@ export const GenericRefListDropDown = <TValue,>(props: IGenericRefListDropDownPr
style={{ width: 'max-content' }}
labelRender={(props) => {
const option = options.find((o) => o.value === props.value);
return <Tag
return <ReflistTag
key={props.value}
value={props.value}
tooltip={value}
color={option?.color}
icon={option?.icon && showIcon && <Icon type={option?.icon} />}
style={getTagStyle(tagStyle, !!option?.color && solidColor)}
>{showItemName && option?.label}</Tag>;
icon={option?.icon}
showIcon={showIcon}
tagStyle={tagStyle}
solidColor={solidColor}
showItemName={showItemName}
label={option?.label}
/>;
}}
Comment thread
coderabbitai[bot] marked this conversation as resolved.
Outdated
>
{options?.map(({ value: localValue, label, data, disabled }) => (
Expand All @@ -189,12 +197,17 @@ export const GenericRefListDropDown = <TValue,>(props: IGenericRefListDropDownPr
{...(displayStyle === 'tags' ? {
labelRender: (props) => {
const option = options.find((o) => o.value === props.value);
return <Tag
key={props.value}
return <ReflistTag
value={option?.value}
tooltip={value}
color={option?.color}
icon={(option?.icon && showIcon) && <Icon type={option?.icon} />}
style={getTagStyle(tagStyle, !!option?.color && solidColor)}
>{showItemName && option?.label}</Tag>;
icon={option?.icon}
showIcon={showIcon}
tagStyle={tagStyle}
solidColor={solidColor}
showItemName={showItemName}
label={option?.label}
/>;
}
Comment thread
coderabbitai[bot] marked this conversation as resolved.
} : {})}
>
Expand Down
1 change: 1 addition & 0 deletions shesha-reactjs/src/components/refListDropDown/models.ts
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ export interface ISelectOption<TValue = any> {
disabled?: boolean;
color?: string;
icon?: string;
description?: string;
}

export type CustomLabeledValue<TValue = any> = LabeledValue & { data: TValue };
24 changes: 24 additions & 0 deletions shesha-reactjs/src/components/refListDropDown/reflistTag.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import { getTagStyle } from '@/utils/style';
import convertCssColorNameToHex from 'convert-css-color-name-to-hex';
import { Tag, Tooltip, TooltipProps } from 'antd';
import React from 'react';
import { Icon } from '../readOnlyDisplayFormItem';
function ReflistTag({ value, tooltip, color, icon, showIcon, tagStyle, solidColor, showItemName, label, placement = 'right' }) {

const memoizedColor = solidColor
? convertCssColorNameToHex(color ?? '')
: color?.toLowerCase();

return (
<Tooltip title={tooltip} placement={placement as TooltipProps['placement']} style={{ cursor: 'pointer' }}>
<Tag
key={value}
color={memoizedColor}
icon={(icon && showIcon) && <Icon type={icon} />}
style={getTagStyle(tagStyle, !!color)}
>{showItemName && label}</Tag>
</Tooltip>
);
};

export default ReflistTag;
Comment on lines +1 to +24
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Add TypeScript interface for component props to improve type safety.

The component lacks TypeScript typing, which reduces type safety and IDE support. As this is a reusable component used across multiple files, proper typing is essential.

Add TypeScript interface and type the component:

 import { getTagStyle } from '@/utils/style';
 import convertCssColorNameToHex from 'convert-css-color-name-to-hex';
 import { Tag, Tooltip, TooltipProps } from 'antd';
-import React from 'react';
+import React, { FC, ReactNode } from 'react';
 import { Icon } from '../readOnlyDisplayFormItem';
+
+interface IReflistTagProps {
+  value: string | number;
+  tooltip?: string;
+  color?: string;
+  icon?: string;
+  showIcon?: boolean;
+  tagStyle?: React.CSSProperties;
+  solidColor?: boolean;
+  showItemName?: boolean;
+  label?: ReactNode;
+  placement?: TooltipProps['placement'];
+}
+
-function ReflistTag({ value, tooltip, color, icon, showIcon, tagStyle, solidColor, showItemName, label, placement = 'right' }) {
+const ReflistTag: FC<IReflistTagProps> = ({ 
+  value, 
+  tooltip, 
+  color, 
+  icon, 
+  showIcon, 
+  tagStyle, 
+  solidColor, 
+  showItemName, 
+  label, 
+  placement = 'right' 
+}) => {
 
     const memoizedColor = solidColor
         ? convertCssColorNameToHex(color ?? '')
         : color?.toLowerCase();

     return (
         <Tooltip title={tooltip} placement={placement as TooltipProps['placement']} style={{ cursor: 'pointer' }}>
             <Tag
                 key={value}
                 color={memoizedColor}
                 icon={(icon && showIcon) && <Icon type={icon} />}
                 style={getTagStyle(tagStyle, !!color)}
             >{showItemName && label}</Tag>
         </Tooltip>
     );
 };

 export default ReflistTag;
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
import { getTagStyle } from '@/utils/style';
import convertCssColorNameToHex from 'convert-css-color-name-to-hex';
import { Tag, Tooltip, TooltipProps } from 'antd';
import React from 'react';
import { Icon } from '../readOnlyDisplayFormItem';
function ReflistTag({ value, tooltip, color, icon, showIcon, tagStyle, solidColor, showItemName, label, placement = 'right' }) {
const memoizedColor = solidColor
? convertCssColorNameToHex(color ?? '')
: color?.toLowerCase();
return (
<Tooltip title={tooltip} placement={placement as TooltipProps['placement']} style={{ cursor: 'pointer' }}>
<Tag
key={value}
color={memoizedColor}
icon={(icon && showIcon) && <Icon type={icon} />}
style={getTagStyle(tagStyle, !!color)}
>{showItemName && label}</Tag>
</Tooltip>
);
};
export default ReflistTag;
import { getTagStyle } from '@/utils/style';
import convertCssColorNameToHex from 'convert-css-color-name-to-hex';
import { Tag, Tooltip, TooltipProps } from 'antd';
import React, { FC, ReactNode } from 'react';
import { Icon } from '../readOnlyDisplayFormItem';
interface IReflistTagProps {
value: string | number;
tooltip?: string;
color?: string;
icon?: string;
showIcon?: boolean;
tagStyle?: React.CSSProperties;
solidColor?: boolean;
showItemName?: boolean;
label?: ReactNode;
placement?: TooltipProps['placement'];
}
const ReflistTag: FC<IReflistTagProps> = ({
value,
tooltip,
color,
icon,
showIcon,
tagStyle,
solidColor,
showItemName,
label,
placement = 'right',
}) => {
const memoizedColor = solidColor
? convertCssColorNameToHex(color ?? '')
: color?.toLowerCase();
return (
<Tooltip title={tooltip} placement={placement as TooltipProps['placement']} style={{ cursor: 'pointer' }}>
<Tag
key={value}
color={memoizedColor}
icon={(icon && showIcon) && <Icon type={icon} />}
style={getTagStyle(tagStyle, !!color)}
>
{showItemName && label}
</Tag>
</Tooltip>
);
};
export default ReflistTag;
🤖 Prompt for AI Agents
In shesha-reactjs/src/components/refListDropDown/reflistTag.tsx lines 1 to 24,
the ReflistTag component lacks TypeScript typings for its props, reducing type
safety and IDE support. Define a TypeScript interface describing all expected
props with their types, including optional and defaulted ones, then update the
component function signature to use this interface for its props parameter.

Loading
Loading