♻️ refactor(models-table): extract reusable renderLimitedItems for list popovers
Introduce a generic `renderLimitedItems` helper within `ModelsColumnDefs.js` to eliminate duplicated logic for list-style columns. Key changes • Added `renderLimitedItems` to handle item limiting, “+N” indicator, and popover display. • Migrated `renderTags`, `renderEndpoints`, and `renderBoundChannels` to use the new helper. • Removed redundant inline implementations, reducing complexity and improving readability. • Preserved previous UX: first 3 items shown, overflow accessible via popover. This refactor streamlines code maintenance and ensures consistent behavior across related columns.
This commit is contained in:
@@ -39,6 +39,34 @@ function renderTimestamp(timestamp) {
|
|||||||
return <>{timestamp2string(timestamp)}</>;
|
return <>{timestamp2string(timestamp)}</>;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Generic renderer for list-style tags with limit and popover
|
||||||
|
function renderLimitedItems({ items, renderItem, maxDisplay = 3 }) {
|
||||||
|
if (!items || items.length === 0) return '-';
|
||||||
|
const displayItems = items.slice(0, maxDisplay);
|
||||||
|
const remainingItems = items.slice(maxDisplay);
|
||||||
|
return (
|
||||||
|
<Space spacing={1} wrap>
|
||||||
|
{displayItems.map((item, idx) => renderItem(item, idx))}
|
||||||
|
{remainingItems.length > 0 && (
|
||||||
|
<Popover
|
||||||
|
content={
|
||||||
|
<div className='p-2'>
|
||||||
|
<Space spacing={1} wrap>
|
||||||
|
{remainingItems.map((item, idx) => renderItem(item, idx))}
|
||||||
|
</Space>
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
position='top'
|
||||||
|
>
|
||||||
|
<Tag size='small' shape='circle' color='grey'>
|
||||||
|
+{remainingItems.length}
|
||||||
|
</Tag>
|
||||||
|
</Popover>
|
||||||
|
)}
|
||||||
|
</Space>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
// Render vendor column with icon
|
// Render vendor column with icon
|
||||||
const renderVendorTag = (vendorId, vendorMap, t) => {
|
const renderVendorTag = (vendorId, vendorMap, t) => {
|
||||||
if (!vendorId || !vendorMap[vendorId]) return '-';
|
if (!vendorId || !vendorMap[vendorId]) return '-';
|
||||||
@@ -67,72 +95,44 @@ const renderDescription = (text) => {
|
|||||||
const renderTags = (text) => {
|
const renderTags = (text) => {
|
||||||
if (!text) return '-';
|
if (!text) return '-';
|
||||||
const tagsArr = text.split(',').filter(Boolean);
|
const tagsArr = text.split(',').filter(Boolean);
|
||||||
const maxDisplayTags = 3;
|
return renderLimitedItems({
|
||||||
const displayTags = tagsArr.slice(0, maxDisplayTags);
|
items: tagsArr,
|
||||||
const remainingTags = tagsArr.slice(maxDisplayTags);
|
renderItem: (tag, idx) => (
|
||||||
|
<Tag key={idx} size="small" shape='circle' color={stringToColor(tag)}>
|
||||||
return (
|
{tag}
|
||||||
<Space spacing={1} wrap>
|
</Tag>
|
||||||
{displayTags.map((tag, index) => (
|
),
|
||||||
<Tag key={index} size="small" shape='circle' color={stringToColor(tag)}>
|
});
|
||||||
{tag}
|
|
||||||
</Tag>
|
|
||||||
))}
|
|
||||||
{remainingTags.length > 0 && (
|
|
||||||
<Popover
|
|
||||||
content={
|
|
||||||
<div className='p-2'>
|
|
||||||
<Space spacing={1} wrap>
|
|
||||||
{remainingTags.map((tag, index) => (
|
|
||||||
<Tag key={index} size="small" shape='circle' color={stringToColor(tag)}>
|
|
||||||
{tag}
|
|
||||||
</Tag>
|
|
||||||
))}
|
|
||||||
</Space>
|
|
||||||
</div>
|
|
||||||
}
|
|
||||||
position="top"
|
|
||||||
>
|
|
||||||
<Tag size="small" shape='circle' color="grey">
|
|
||||||
+{remainingTags.length}
|
|
||||||
</Tag>
|
|
||||||
</Popover>
|
|
||||||
)}
|
|
||||||
</Space>
|
|
||||||
);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// Render endpoints
|
// Render endpoints
|
||||||
const renderEndpoints = (text) => {
|
const renderEndpoints = (text) => {
|
||||||
|
let arr;
|
||||||
try {
|
try {
|
||||||
const arr = JSON.parse(text);
|
arr = JSON.parse(text);
|
||||||
if (Array.isArray(arr)) {
|
|
||||||
return (
|
|
||||||
<Space spacing={1} wrap>
|
|
||||||
{arr.map((ep) => (
|
|
||||||
<Tag key={ep} color="blue" size="small" shape='circle'>
|
|
||||||
{ep}
|
|
||||||
</Tag>
|
|
||||||
))}
|
|
||||||
</Space>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
} catch (_) { }
|
} catch (_) { }
|
||||||
return text || '-';
|
if (!Array.isArray(arr)) return text || '-';
|
||||||
|
return renderLimitedItems({
|
||||||
|
items: arr,
|
||||||
|
renderItem: (ep, idx) => (
|
||||||
|
<Tag key={idx} color="blue" size="small" shape='circle'>
|
||||||
|
{ep}
|
||||||
|
</Tag>
|
||||||
|
),
|
||||||
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
// Render bound channels
|
// Render bound channels
|
||||||
const renderBoundChannels = (channels) => {
|
const renderBoundChannels = (channels) => {
|
||||||
if (!channels || channels.length === 0) return '-';
|
if (!channels || channels.length === 0) return '-';
|
||||||
return (
|
return renderLimitedItems({
|
||||||
<Space spacing={1} wrap>
|
items: channels,
|
||||||
{channels.map((c, idx) => (
|
renderItem: (c, idx) => (
|
||||||
<Tag key={idx} color="purple" size="small" shape='circle'>
|
<Tag key={idx} color="purple" size="small" shape='circle'>
|
||||||
{c.name}({c.type})
|
{c.name}({c.type})
|
||||||
</Tag>
|
</Tag>
|
||||||
))}
|
),
|
||||||
</Space>
|
});
|
||||||
);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// Render operations column
|
// Render operations column
|
||||||
|
|||||||
Reference in New Issue
Block a user