diff --git a/mocks/loki/flow_records.json b/mocks/loki/flow_records.json index ffecf6661..35282e0ff 100644 --- a/mocks/loki/flow_records.json +++ b/mocks/loki/flow_records.json @@ -16,7 +16,7 @@ "values": [ [ "1708011867120999936", - "{\"SrcK8S_Name\":\"ip-10-0-1-7.ec2.internal\",\"Bytes\":66,\"TimeFlowRttNs\":10000,\"Packets\":1,\"Interfaces\":[\"br-ex\",\"test\"],\"SrcMac\":\"02:27:A1:A8:84:B9\",\"Proto\":1,\"SrcK8S_HostIP\":\"10.0.1.7\",\"SrcK8S_HostName\":\"ip-10-0-1-7.ec2.internal\",\"Flags\":16,\"DnsErrno\":0,\"TimeFlowStartMs\":1708011867121,\"TimeReceived\":1708011867,\"DstAddr\":\"10.0.1.140\",\"Etype\":2048,\"SrcPort\":50104,\"AgentIP\":\"10.0.1.7\",\"SrcK8S_OwnerType\":\"Node\",\"Dscp\":0,\"TimeFlowEndMs\":1708011867121,\"IfDirections\":[\"1\",\"0\"],\"SrcAddr\":\"10.0.1.7\",\"DstMac\":\"02:7B:32:68:BE:65\",\"DstPort\":443,\"IcmpType\":3,\"IcmpCode\":0}" + "{\"SrcK8S_Name\":\"ip-10-0-1-7.ec2.internal\",\"Bytes\":66,\"TimeFlowRttNs\":10000,\"Packets\":1,\"Interfaces\":[\"br-ex\",\"test1\",\"test2\",\"test3\",\"test4\",\"test5\"],\"SrcMac\":\"02:27:A1:A8:84:B9\",\"Proto\":1,\"SrcK8S_HostIP\":\"10.0.1.7\",\"SrcK8S_HostName\":\"ip-10-0-1-7.ec2.internal\",\"Flags\":16,\"DnsErrno\":0,\"TimeFlowStartMs\":1708011867121,\"TimeReceived\":1708011867,\"DstAddr\":\"10.0.1.140\",\"Etype\":2048,\"SrcPort\":50104,\"AgentIP\":\"10.0.1.7\",\"SrcK8S_OwnerType\":\"Node\",\"Dscp\":0,\"TimeFlowEndMs\":1708011867121,\"IfDirections\":[\"1\",\"0\",\"0\",\"0\",\"0\",\"0\"],\"SrcAddr\":\"10.0.1.7\",\"DstMac\":\"02:7B:32:68:BE:65\",\"DstPort\":443,\"IcmpType\":3,\"IcmpCode\":0}" ], [ "1708011867120999936", diff --git a/web/locales/en/plugin__netobserv-plugin.json b/web/locales/en/plugin__netobserv-plugin.json index e47ebb839..d410b1976 100644 --- a/web/locales/en/plugin__netobserv-plugin.json +++ b/web/locales/en/plugin__netobserv-plugin.json @@ -36,6 +36,7 @@ "Add Namespace, Owner or Resource filters (which use indexed fields), or decrease limit / range, to improve the query performance": "Add Namespace, Owner or Resource filters (which use indexed fields), or decrease limit / range, to improve the query performance", "Add more filters or decrease limit / range to improve the query performance": "Add more filters or decrease limit / range to improve the query performance", "Unable to get {{item}}": "Unable to get {{item}}", + "more": "more", "DNS Error": "DNS Error", "Namespace": "Namespace", "Show related documentation": "Show related documentation", diff --git a/web/src/components/drawer/record/record-field.css b/web/src/components/drawer/record/record-field.css index 440d87c5e..d5ca9d92f 100644 --- a/web/src/components/drawer/record/record-field.css +++ b/web/src/components/drawer/record/record-field.css @@ -33,6 +33,19 @@ gap: .3rem; } +.record-field-flex-container .flowdirints { + flex-direction: column !important; +} + +.record-field-flex-container .flowdirints > div { + width: 100%; +} + +.side-by-side { + padding: 0 !important; + margin: 0 !important; +} + .record-field-flex { align-self: center; } @@ -59,7 +72,6 @@ .record-field-flex-container.s, .record-field-flex-container.m, .record-field-flex-container.l { - flex-direction: column; } .record-field-flex-container.s { diff --git a/web/src/components/drawer/record/record-field.tsx b/web/src/components/drawer/record/record-field.tsx index 980a32568..f78dfd6a9 100644 --- a/web/src/components/drawer/record/record-field.tsx +++ b/web/src/components/drawer/record/record-field.tsx @@ -24,6 +24,8 @@ export type RecordFieldFilter = { isDelete: boolean; }; +export const MAX_ARRAY_INDEX = 2; + export type FlexValue = 'flexDefault' | 'flexNone' | 'flex_1' | 'flex_2' | 'flex_3' | 'flex_4'; export type FlexWrapValue = 'wrap' | 'wrapReverse' | 'nowrap'; @@ -80,6 +82,10 @@ export const RecordField: React.FC = ({ return {t('n/a')}; }; + const moreText = (count: number) => { + return {`${count} ${t('more')}...`}; + }; + const emptyDnsErrorText = () => { return emptyText( flow.fields.DnsErrno @@ -215,21 +221,31 @@ export const RecordField: React.FC = ({ ); }; - const nthContainer = (children: (JSX.Element | undefined)[], asChild = true, childIcon = true, forcedSize?: Size) => { + const nthContainer = ( + children: (JSX.Element | undefined)[], + asChild = true, + childIcon = true, + truncate?: boolean, + forcedSize?: Size, + className = '' + ) => { return ( - + {children.length > 0 ? ( - children.map((c, i) => { - const child = c ? c : emptyText(); - if (i > 0 && asChild && childIcon) { - const arrow = {'↪'}; - return sideBySideContainer(arrow, child, 'flexNone', 'flex_1', 'nowrap'); - } - return child; - }) + children + .filter((_c, i) => !truncate || i < MAX_ARRAY_INDEX) + .map((c, i) => { + const child = c ? c : emptyText(); + if (i > 0 && asChild && childIcon) { + const arrow = {'↪'}; + return sideBySideContainer(arrow, child, 'flexNone', 'flex_1', 'nowrap'); + } + return child; + }) ) : ( {t('n/a')} )} + {truncate && children.length > MAX_ARRAY_INDEX && moreText(children.length - MAX_ARRAY_INDEX)} ); }; @@ -241,7 +257,7 @@ export const RecordField: React.FC = ({ childIcon = true, forcedSize?: Size ) => { - return nthContainer([child1, child2], asChild, childIcon, forcedSize); + return nthContainer([child1, child2], asChild, childIcon, false, forcedSize); }; const sideBySideContainer = ( @@ -253,8 +269,12 @@ export const RecordField: React.FC = ({ ) => { return ( - {leftElement || emptyText()} - {rightElement || emptyText()} + + {leftElement || emptyText()} + + + {rightElement || emptyText()} + ); }; @@ -288,7 +308,7 @@ export const RecordField: React.FC = ({ ); }; - const content = (c: Column) => { + const content = (c: Column, isTable: boolean) => { if (!c.value) { // Value function not configured return emptyText(); @@ -420,6 +440,7 @@ export const RecordField: React.FC = ({ value.map(dir => simpleTextWithTooltip(getDirectionDisplayString(String(dir) as FlowDirection, t))), true, false, + isTable, multiLineSize ); } @@ -431,6 +452,7 @@ export const RecordField: React.FC = ({ value.map(iName => simpleTextWithTooltip(String(iName))), true, false, + isTable, multiLineSize ); } @@ -444,7 +466,8 @@ export const RecordField: React.FC = ({ .filter(iName => iName !== '') .map(iName => simpleTextWithTooltip(iName)), true, - false + false, + isTable ); } return singleContainer(simpleTextWithTooltip(String(value))); @@ -470,7 +493,10 @@ export const RecordField: React.FC = ({ ) ), true, - false + false, + isTable, + undefined, + 'flowdirints' ); } else { return singleContainer(emptyText(t('Invalid data provided. Check JSON for details.'))); @@ -594,7 +620,7 @@ export const RecordField: React.FC = ({ return filter ? ( - {content(column)} + {content(column, false)} = ({ ) : ( - content(column) + content(column, true) ); };