From 984c8ee47790c91d0cffa5d1f3c3e7cef180d232 Mon Sep 17 00:00:00 2001 From: t0ng7u Date: Sun, 3 Aug 2025 19:31:29 +0800 Subject: [PATCH] =?UTF-8?q?=E2=99=BB=EF=B8=8F=20refactor(models-table):=20?= =?UTF-8?q?extract=20reusable=20`renderLimitedItems`=20for=20list=20popove?= =?UTF-8?q?rs?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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. --- .../table/models/ModelsColumnDefs.js | 110 +++++++++--------- 1 file changed, 55 insertions(+), 55 deletions(-) diff --git a/web/src/components/table/models/ModelsColumnDefs.js b/web/src/components/table/models/ModelsColumnDefs.js index ef404958..db4dae88 100644 --- a/web/src/components/table/models/ModelsColumnDefs.js +++ b/web/src/components/table/models/ModelsColumnDefs.js @@ -39,6 +39,34 @@ function renderTimestamp(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 ( + + {displayItems.map((item, idx) => renderItem(item, idx))} + {remainingItems.length > 0 && ( + + + {remainingItems.map((item, idx) => renderItem(item, idx))} + + + } + position='top' + > + + +{remainingItems.length} + + + )} + + ); +} + // Render vendor column with icon const renderVendorTag = (vendorId, vendorMap, t) => { if (!vendorId || !vendorMap[vendorId]) return '-'; @@ -67,72 +95,44 @@ const renderDescription = (text) => { const renderTags = (text) => { if (!text) return '-'; const tagsArr = text.split(',').filter(Boolean); - const maxDisplayTags = 3; - const displayTags = tagsArr.slice(0, maxDisplayTags); - const remainingTags = tagsArr.slice(maxDisplayTags); - - return ( - - {displayTags.map((tag, index) => ( - - {tag} - - ))} - {remainingTags.length > 0 && ( - - - {remainingTags.map((tag, index) => ( - - {tag} - - ))} - - - } - position="top" - > - - +{remainingTags.length} - - - )} - - ); + return renderLimitedItems({ + items: tagsArr, + renderItem: (tag, idx) => ( + + {tag} + + ), + }); }; // Render endpoints const renderEndpoints = (text) => { + let arr; try { - const arr = JSON.parse(text); - if (Array.isArray(arr)) { - return ( - - {arr.map((ep) => ( - - {ep} - - ))} - - ); - } + arr = JSON.parse(text); } catch (_) { } - return text || '-'; + if (!Array.isArray(arr)) return text || '-'; + return renderLimitedItems({ + items: arr, + renderItem: (ep, idx) => ( + + {ep} + + ), + }); }; // Render bound channels const renderBoundChannels = (channels) => { if (!channels || channels.length === 0) return '-'; - return ( - - {channels.map((c, idx) => ( - - {c.name}({c.type}) - - ))} - - ); + return renderLimitedItems({ + items: channels, + renderItem: (c, idx) => ( + + {c.name}({c.type}) + + ), + }); }; // Render operations column