From 06d802d364d8bbce12135aca73c31f938437de17 Mon Sep 17 00:00:00 2001 From: Ben Elferink Date: Wed, 20 Nov 2024 17:15:23 +0200 Subject: [PATCH 1/7] [GEN-1754]: namespace "select all" -> close the accordion (#1797) Co-authored-by: Alon Braymok <138359965+alonkeyval@users.noreply.github.com> Co-authored-by: Tamir David Co-authored-by: Tamir David Co-authored-by: Amir Blum Co-authored-by: Ron Federman <73110295+RonFed@users.noreply.github.com> Co-authored-by: yodigos Co-authored-by: Mike Dame Co-authored-by: alonbraymok Co-authored-by: Daria Dovzhikova Co-authored-by: David <65228999+david336362@users.noreply.github.com> Co-authored-by: David Co-authored-by: Eden Federman --- .../sources-list/index.tsx | 8 ++- .../webapp/hooks/sources/useSourceFormData.ts | 50 +++++++++++-------- 2 files changed, 32 insertions(+), 26 deletions(-) diff --git a/frontend/webapp/containers/main/sources/choose-sources/choose-sources-body/choose-sources-body-fast/sources-list/index.tsx b/frontend/webapp/containers/main/sources/choose-sources/choose-sources-body/choose-sources-body-fast/sources-list/index.tsx index 044df3800..7834d918d 100644 --- a/frontend/webapp/containers/main/sources/choose-sources/choose-sources-body/choose-sources-body-fast/sources-list/index.tsx +++ b/frontend/webapp/containers/main/sources/choose-sources/choose-sources-body/choose-sources-body-fast/sources-list/index.tsx @@ -100,6 +100,7 @@ export const SourcesList: React.FC = ({ onSelectFutureApps, searchText, + selectAllForNamespace, onSelectAll, showSelectedOnly, @@ -127,7 +128,7 @@ export const SourcesList: React.FC = ({ const namespacePassesFilters = (!searchText || namespace.toLowerCase().includes(searchText)) && (!showSelectedOnly || !!selected.length); if (!namespacePassesFilters) return null; - const isNamespaceSelected = selectedNamespace === namespace; + const isNamespaceSelected = selectedNamespace === namespace && !selectAllForNamespace; const isNamespaceCanSelect = namespaceLoaded && !!available.length; const isNamespaceAllSourcesSelected = isNamespaceCanSelect && selected.length === sources.length; @@ -141,10 +142,7 @@ export const SourcesList: React.FC = ({ { - if (bool) onSelectNamespace(namespace); - onSelectAll(bool, namespace); - }} + onChange={(bool) => onSelectAll(bool, namespace)} /> {namespace} diff --git a/frontend/webapp/hooks/sources/useSourceFormData.ts b/frontend/webapp/hooks/sources/useSourceFormData.ts index fc637267e..b6ef9c2cd 100644 --- a/frontend/webapp/hooks/sources/useSourceFormData.ts +++ b/frontend/webapp/hooks/sources/useSourceFormData.ts @@ -1,4 +1,4 @@ -import { Dispatch, SetStateAction, useEffect, useState } from 'react'; +import { Dispatch, SetStateAction, useCallback, useEffect, useState } from 'react'; import { useAppStore } from '@/store'; import type { K8sActualSource } from '@/types'; import { useNamespace } from '../compute-platform'; @@ -28,6 +28,7 @@ export interface UseSourceFormDataResponse { searchText: string; selectAll: boolean; + selectAllForNamespace: string; showSelectedOnly: boolean; setSearchText: Dispatch>; onSelectAll: (bool: boolean, namespace?: string) => void; @@ -107,35 +108,41 @@ export const useSourceFormData = (params?: UseSourceFormDataParams): UseSourceFo }); }; - const onSelectAll: UseSourceFormDataResponse['onSelectAll'] = (bool, namespace) => { - if (!!namespace) { - const nsAvailableSources = availableSources[namespace]; - const nsSelectedSources = selectedSources[namespace]; - - if (!nsAvailableSources.length && !nsSelectedSources && bool) { - setSelectAllForNamespace(namespace); + const onSelectAll: UseSourceFormDataResponse['onSelectAll'] = useCallback( + (bool, namespace) => { + if (!!namespace) { + const nsAvailableSources = availableSources[namespace]; + const nsSelectedSources = selectedSources[namespace]; + + if (!nsSelectedSources && bool) { + onSelectNamespace(namespace); + setSelectAllForNamespace(namespace); + } else { + setSelectedSources((prev) => ({ ...prev, [namespace]: bool ? nsAvailableSources : [] })); + setSelectAllForNamespace(''); + setSelectedNamespace(''); + } } else { - setSelectedSources((prev) => ({ ...prev, [namespace]: bool ? nsAvailableSources : [] })); - } - } else { - setSelectAll(bool); + setSelectAll(bool); - if (bool) { - doSelectAll(); - } else { - doUnselectAll(); + if (bool) { + doSelectAll(); + } else { + doUnselectAll(); + } } - } - }; + }, + [availableSources, selectedSources], + ); // this is to keep trying "select all" per namespace until the sources are loaded (allows for 1-click, better UX). // if selectedSources returns an emtpy array, it will stop to prevent inifnite loop where no availableSources ever exist for that namespace useEffect(() => { if (!!selectAllForNamespace) { - setSelectAllForNamespace(''); - setTimeout(() => onSelectAll(true, selectAllForNamespace), 100); + const interval = setInterval(() => onSelectAll(true, selectAllForNamespace), 100); + return () => clearInterval(interval); } - }, [selectAllForNamespace]); + }, [selectAllForNamespace, onSelectAll]); const onSelectNamespace: UseSourceFormDataResponse['onSelectNamespace'] = (namespace) => { const alreadySelected = selectedNamespace === namespace; @@ -194,6 +201,7 @@ export const useSourceFormData = (params?: UseSourceFormDataParams): UseSourceFo searchText, selectAll, + selectAllForNamespace, showSelectedOnly, setSearchText, onSelectAll, From f1dbca54c5e66bf9d8b559744a0aa065f505f5f7 Mon Sep 17 00:00:00 2001 From: Ben Elferink Date: Wed, 20 Nov 2024 17:17:58 +0200 Subject: [PATCH 2/7] [GEN-1755]: disable "select all" for empty namespaces (#1798) Co-authored-by: Alon Braymok <138359965+alonkeyval@users.noreply.github.com> Co-authored-by: Tamir David Co-authored-by: Tamir David Co-authored-by: Amir Blum Co-authored-by: Ron Federman <73110295+RonFed@users.noreply.github.com> Co-authored-by: yodigos Co-authored-by: Mike Dame Co-authored-by: alonbraymok Co-authored-by: Daria Dovzhikova Co-authored-by: David <65228999+david336362@users.noreply.github.com> Co-authored-by: David Co-authored-by: Eden Federman --- .../choose-sources-body-fast/sources-list/index.tsx | 6 +----- frontend/webapp/hooks/sources/useSourceFormData.ts | 2 +- frontend/webapp/reuseable-components/checkbox/index.tsx | 5 ++++- 3 files changed, 6 insertions(+), 7 deletions(-) diff --git a/frontend/webapp/containers/main/sources/choose-sources/choose-sources-body/choose-sources-body-fast/sources-list/index.tsx b/frontend/webapp/containers/main/sources/choose-sources/choose-sources-body/choose-sources-body-fast/sources-list/index.tsx index 7834d918d..32a00866b 100644 --- a/frontend/webapp/containers/main/sources/choose-sources/choose-sources-body/choose-sources-body-fast/sources-list/index.tsx +++ b/frontend/webapp/containers/main/sources/choose-sources/choose-sources-body/choose-sources-body-fast/sources-list/index.tsx @@ -139,11 +139,7 @@ export const SourcesList: React.FC = ({ onSelectNamespace(namespace)}> - onSelectAll(bool, namespace)} - /> + onSelectAll(bool, namespace)} /> {namespace} diff --git a/frontend/webapp/hooks/sources/useSourceFormData.ts b/frontend/webapp/hooks/sources/useSourceFormData.ts index b6ef9c2cd..9987d25e4 100644 --- a/frontend/webapp/hooks/sources/useSourceFormData.ts +++ b/frontend/webapp/hooks/sources/useSourceFormData.ts @@ -120,7 +120,7 @@ export const useSourceFormData = (params?: UseSourceFormDataParams): UseSourceFo } else { setSelectedSources((prev) => ({ ...prev, [namespace]: bool ? nsAvailableSources : [] })); setSelectAllForNamespace(''); - setSelectedNamespace(''); + if (!!nsAvailableSources.length) setSelectedNamespace(''); } } else { setSelectAll(bool); diff --git a/frontend/webapp/reuseable-components/checkbox/index.tsx b/frontend/webapp/reuseable-components/checkbox/index.tsx index fdaf9c402..874a52599 100644 --- a/frontend/webapp/reuseable-components/checkbox/index.tsx +++ b/frontend/webapp/reuseable-components/checkbox/index.tsx @@ -38,7 +38,10 @@ const CheckboxWrapper = styled.div<{ $isChecked: boolean; $disabled?: CheckboxPr const Checkbox: React.FC = ({ title, titleColor, tooltip, initialValue = false, onChange, disabled, style }) => { const [isChecked, setIsChecked] = useState(initialValue); - useEffect(() => setIsChecked(initialValue), [initialValue]); + + useEffect(() => { + if (isChecked !== initialValue) setIsChecked(initialValue); + }, [isChecked, initialValue]); const handleToggle: React.MouseEventHandler = (e) => { if (disabled) return; From e48b1ca3967b6a80fa879351d2a560303320c109 Mon Sep 17 00:00:00 2001 From: Ben Elferink Date: Wed, 20 Nov 2024 17:20:41 +0200 Subject: [PATCH 3/7] [GEN-1753]: proper English for "running instance(s)" (#1800) Co-authored-by: Alon Braymok <138359965+alonkeyval@users.noreply.github.com> Co-authored-by: Tamir David Co-authored-by: Tamir David Co-authored-by: Amir Blum Co-authored-by: Ron Federman <73110295+RonFed@users.noreply.github.com> Co-authored-by: yodigos Co-authored-by: Mike Dame Co-authored-by: alonbraymok Co-authored-by: Daria Dovzhikova Co-authored-by: David <65228999+david336362@users.noreply.github.com> Co-authored-by: David Co-authored-by: Eden Federman --- .../choose-sources-body-fast/sources-list/index.tsx | 4 ++-- .../choose-sources-body-simple/sources-list/index.tsx | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/frontend/webapp/containers/main/sources/choose-sources/choose-sources-body/choose-sources-body-fast/sources-list/index.tsx b/frontend/webapp/containers/main/sources/choose-sources/choose-sources-body/choose-sources-body-fast/sources-list/index.tsx index 32a00866b..a28c2427f 100644 --- a/frontend/webapp/containers/main/sources/choose-sources/choose-sources-body/choose-sources-body-fast/sources-list/index.tsx +++ b/frontend/webapp/containers/main/sources/choose-sources/choose-sources-body/choose-sources-body-fast/sources-list/index.tsx @@ -125,7 +125,7 @@ export const SourcesList: React.FC = ({ const selected = selectedSources[namespace] || []; const futureApps = selectedFutureApps[namespace] || false; - const namespacePassesFilters = (!searchText || namespace.toLowerCase().includes(searchText)) && (!showSelectedOnly || !!selected.length); + const namespacePassesFilters = !searchText || namespace.toLowerCase().includes(searchText); if (!namespacePassesFilters) return null; const isNamespaceSelected = selectedNamespace === namespace && !selectAllForNamespace; @@ -169,7 +169,7 @@ export const SourcesList: React.FC = ({ onSelectSource(source, namespace)} /> {source.name} - {source.numberOfInstances} running instances · {source.kind} + {source.numberOfInstances} running instance{source.numberOfInstances !== 1 && 's'} · {source.kind} diff --git a/frontend/webapp/containers/main/sources/choose-sources/choose-sources-body/choose-sources-body-simple/sources-list/index.tsx b/frontend/webapp/containers/main/sources/choose-sources/choose-sources-body/choose-sources-body-simple/sources-list/index.tsx index 7bdc2fe65..9553cbfd7 100644 --- a/frontend/webapp/containers/main/sources/choose-sources/choose-sources-body/choose-sources-body-simple/sources-list/index.tsx +++ b/frontend/webapp/containers/main/sources/choose-sources/choose-sources-body/choose-sources-body-simple/sources-list/index.tsx @@ -108,7 +108,7 @@ export const SourcesList: React.FC = ({ {source.name} - {source.numberOfInstances} running instances · {source.kind} + {source.numberOfInstances} running instance{source.numberOfInstances !== 1 && 's'} · {source.kind} From c01fbabc5580de4f071f38322e9d7a796841a5cf Mon Sep 17 00:00:00 2001 From: Ben Elferink Date: Wed, 20 Nov 2024 17:20:58 +0200 Subject: [PATCH 4/7] [GEN-1756]: show all namespaces even with the "select all" filter on (#1799) Co-authored-by: Alon Braymok <138359965+alonkeyval@users.noreply.github.com> Co-authored-by: Tamir David Co-authored-by: Tamir David Co-authored-by: Amir Blum Co-authored-by: Ron Federman <73110295+RonFed@users.noreply.github.com> Co-authored-by: yodigos Co-authored-by: Mike Dame Co-authored-by: alonbraymok Co-authored-by: Daria Dovzhikova Co-authored-by: David <65228999+david336362@users.noreply.github.com> Co-authored-by: David Co-authored-by: Eden Federman From 57ebfe6015b4b1516fb1d203d60b826eeccca2bf Mon Sep 17 00:00:00 2001 From: Ben Elferink Date: Wed, 20 Nov 2024 17:23:59 +0200 Subject: [PATCH 5/7] [GEN-1783]: do not apply edges if there are no sources/destinations (#1802) Co-authored-by: Alon Braymok <138359965+alonkeyval@users.noreply.github.com> Co-authored-by: Tamir David Co-authored-by: Tamir David Co-authored-by: Amir Blum Co-authored-by: Ron Federman <73110295+RonFed@users.noreply.github.com> Co-authored-by: Mike Dame Co-authored-by: alonbraymok Co-authored-by: Daria Dovzhikova Co-authored-by: David <65228999+david336362@users.noreply.github.com> Co-authored-by: David Co-authored-by: Eden Federman --- .../button/docs-button/index.tsx | 12 +++++- .../reuseable-components/button/index.tsx | 8 ++-- .../nodes-data-flow/builder.ts | 8 +--- .../nodes-data-flow/edges/labeled-edge.tsx | 31 +++++++------- .../nodes-data-flow/nodes/add-node.tsx | 42 +++++++------------ .../nodes-data-flow/nodes/base-node.tsx | 39 ++++++++--------- .../nodes-data-flow/nodes/group-node.tsx | 6 ++- .../nodes-data-flow/nodes/header-node.tsx | 24 ++++++----- 8 files changed, 85 insertions(+), 85 deletions(-) diff --git a/frontend/webapp/reuseable-components/button/docs-button/index.tsx b/frontend/webapp/reuseable-components/button/docs-button/index.tsx index 601bd5069..26814a522 100644 --- a/frontend/webapp/reuseable-components/button/docs-button/index.tsx +++ b/frontend/webapp/reuseable-components/button/docs-button/index.tsx @@ -2,6 +2,7 @@ import Image from 'next/image'; import { DOCS_LINK } from '@/utils'; import styled from 'styled-components'; import { Button, ButtonProps } from '..'; +import { useRef } from 'react'; const StyledButton = styled(Button)` display: flex; @@ -13,8 +14,17 @@ const StyledButton = styled(Button)` `; export const DocsButton = ({ endpoint = '/', variant = 'secondary' }: { endpoint?: string; variant?: ButtonProps['variant'] }) => { + const ref = useRef(null); + return ( - window.open(`${DOCS_LINK}${endpoint}`, '_blank', 'noopener noreferrer')}> + { + window.open(`${DOCS_LINK}${endpoint}`, '_blank', 'noopener noreferrer'); + ref.current?.blur(); + }} + > Docs Docs diff --git a/frontend/webapp/reuseable-components/button/index.tsx b/frontend/webapp/reuseable-components/button/index.tsx index cb45d7514..237b9b94c 100644 --- a/frontend/webapp/reuseable-components/button/index.tsx +++ b/frontend/webapp/reuseable-components/button/index.tsx @@ -1,4 +1,4 @@ -import React, { ButtonHTMLAttributes } from 'react'; +import React, { ButtonHTMLAttributes, forwardRef, LegacyRef } from 'react'; import styled, { css } from 'styled-components'; export interface ButtonProps extends ButtonHTMLAttributes { @@ -117,12 +117,12 @@ const ButtonContainer = styled.div<{ $variant: ButtonProps['variant'] }>` } `; -export const Button: React.FC = ({ children, variant = 'primary', isDisabled = false, ...props }) => { +export const Button = forwardRef(({ children, variant = 'primary', isDisabled = false, ...props }, ref) => { return ( - + {children} ); -}; +}); diff --git a/frontend/webapp/reuseable-components/nodes-data-flow/builder.ts b/frontend/webapp/reuseable-components/nodes-data-flow/builder.ts index 6e219053e..c910d85fd 100644 --- a/frontend/webapp/reuseable-components/nodes-data-flow/builder.ts +++ b/frontend/webapp/reuseable-components/nodes-data-flow/builder.ts @@ -281,9 +281,7 @@ export const buildNodesAndEdges = ({ } // Connect sources to actions - if (!sources.length) { - edges.push(createEdge(`source-0-to-action-${actions.length ? 'group' : 0}`)); - } else { + if (!!sources.length) { tempNodes['sources'].forEach((node, idx) => { if (idx > 0) { const sourceIndex = idx - 1; @@ -312,9 +310,7 @@ export const buildNodesAndEdges = ({ } // Connect actions to destinations - if (!destinations.length) { - edges.push(createEdge(`action-${actions.length ? 'group' : 0}-to-destination-0`)); - } else { + if (!!destinations.length) { tempNodes['destinations'].forEach((node, idx) => { if (idx > 0) { const destinationIndex = idx - 1; diff --git a/frontend/webapp/reuseable-components/nodes-data-flow/edges/labeled-edge.tsx b/frontend/webapp/reuseable-components/nodes-data-flow/edges/labeled-edge.tsx index 1cc4b1840..c6f2452f8 100644 --- a/frontend/webapp/reuseable-components/nodes-data-flow/edges/labeled-edge.tsx +++ b/frontend/webapp/reuseable-components/nodes-data-flow/edges/labeled-edge.tsx @@ -2,6 +2,18 @@ import React from 'react'; import styled from 'styled-components'; import { EdgeLabelRenderer, BaseEdge, type EdgeProps, type Edge, getSmoothStepPath } from '@xyflow/react'; +interface Props + extends EdgeProps< + Edge< + { + label: string; + isMultiTarget?: boolean; + isError?: boolean; + }, + 'labeled' + > + > {} + const Label = styled.div<{ $labelX: number; $labelY: number; $isError?: boolean }>` position: absolute; transform: ${({ $labelX, $labelY }) => `translate(-50%, -50%) translate(${$labelX}px, ${$labelY}px)`}; @@ -20,17 +32,7 @@ const Label = styled.div<{ $labelX: number; $labelY: number; $isError?: boolean justify-content: center; `; -const LabeledEdge: React.FC>> = ({ - id, - sourceX, - sourceY, - targetX, - targetY, - sourcePosition, - targetPosition, - data, - style, -}) => { +const LabeledEdge: React.FC = ({ id, sourceX, sourceY, targetX, targetY, sourcePosition, targetPosition, data, style }) => { const [edgePath] = getSmoothStepPath({ sourceX, sourceY, @@ -44,12 +46,7 @@ const LabeledEdge: React.FC - diff --git a/frontend/webapp/reuseable-components/nodes-data-flow/nodes/add-node.tsx b/frontend/webapp/reuseable-components/nodes-data-flow/nodes/add-node.tsx index e49dea2bd..17bb5df6d 100644 --- a/frontend/webapp/reuseable-components/nodes-data-flow/nodes/add-node.tsx +++ b/frontend/webapp/reuseable-components/nodes-data-flow/nodes/add-node.tsx @@ -2,35 +2,25 @@ import React from 'react'; import Image from 'next/image'; import styled from 'styled-components'; import { Text } from '@/reuseable-components'; -import { Handle, Position } from '@xyflow/react'; - -interface BaseNodeProps { - data: Record; - - id: string; - parentId?: any; - type: string; - - isConnectable: boolean; - selectable: boolean; - selected?: any; - deletable: boolean; - draggable: boolean; - dragging: boolean; - dragHandle?: any; - - width: number; - height: number; - zIndex: number; - positionAbsoluteX: number; - positionAbsoluteY: number; - sourcePosition?: any; - targetPosition?: any; +import { OVERVIEW_NODE_TYPES, STATUSES } from '@/types'; +import { Handle, type Node, type NodeProps, Position } from '@xyflow/react'; +interface Props + extends NodeProps< + Node< + { + type: OVERVIEW_NODE_TYPES; + status: STATUSES; + title: string; + subTitle: string; + }, + 'add' + > + > { nodeWidth: number; } -const BaseNodeContainer = styled.div<{ $nodeWidth: BaseNodeProps['nodeWidth'] }>` +const BaseNodeContainer = styled.div<{ $nodeWidth: Props['nodeWidth'] }>` width: ${({ $nodeWidth }) => `${$nodeWidth}px`}; padding: 16px 24px 16px 16px; display: flex; @@ -68,7 +58,7 @@ const SubTitle = styled(Text)` text-align: center; `; -const AddNode = ({ id, isConnectable, data, nodeWidth }: BaseNodeProps) => { +const AddNode: React.FC = ({ nodeWidth, data, id, isConnectable }) => { return ( diff --git a/frontend/webapp/reuseable-components/nodes-data-flow/nodes/base-node.tsx b/frontend/webapp/reuseable-components/nodes-data-flow/nodes/base-node.tsx index 73720bc07..6cc839db4 100644 --- a/frontend/webapp/reuseable-components/nodes-data-flow/nodes/base-node.tsx +++ b/frontend/webapp/reuseable-components/nodes-data-flow/nodes/base-node.tsx @@ -3,30 +3,31 @@ import Image from 'next/image'; import { useAppStore } from '@/store'; import styled from 'styled-components'; import { getStatusIcon } from '@/utils'; -import { Handle, Position } from '@xyflow/react'; import { Checkbox, Status, Text } from '@/reuseable-components'; +import { Handle, type Node, type NodeProps, Position } from '@xyflow/react'; import { type ActionDataParsed, type ActualDestination, type InstrumentationRuleSpec, type K8sActualSource, STATUSES } from '@/types'; -export interface NodeDataProps { - id: string; - type: 'source' | 'action' | 'destination'; - status: STATUSES; - title: string; - subTitle: string; - imageUri: string; - monitors?: string[]; - isActive?: boolean; - raw: InstrumentationRuleSpec | K8sActualSource | ActionDataParsed | ActualDestination; -} - -interface BaseNodeProps { - id: string; +interface Props + extends NodeProps< + Node< + { + id: string; + type: 'source' | 'action' | 'destination'; + status: STATUSES; + title: string; + subTitle: string; + imageUri: string; + monitors?: string[]; + isActive?: boolean; + raw: InstrumentationRuleSpec | K8sActualSource | ActionDataParsed | ActualDestination; + }, + 'base' + > + > { nodeWidth: number; - isConnectable: boolean; - data: NodeDataProps; } -const Container = styled.div<{ $nodeWidth: number; $isError?: boolean }>` +const Container = styled.div<{ $nodeWidth: Props['nodeWidth']; $isError?: boolean }>` display: flex; align-items: center; align-self: stretch; @@ -85,7 +86,7 @@ const ActionsWrapper = styled.div` margin-left: auto; `; -const BaseNode = ({ nodeWidth, isConnectable, data }: BaseNodeProps) => { +const BaseNode: React.FC = ({ nodeWidth, data, isConnectable }) => { const { type, status, title, subTitle, imageUri, monitors, isActive, raw } = data; const isError = status === STATUSES.UNHEALTHY; diff --git a/frontend/webapp/reuseable-components/nodes-data-flow/nodes/group-node.tsx b/frontend/webapp/reuseable-components/nodes-data-flow/nodes/group-node.tsx index f2203074f..54f990a8d 100644 --- a/frontend/webapp/reuseable-components/nodes-data-flow/nodes/group-node.tsx +++ b/frontend/webapp/reuseable-components/nodes-data-flow/nodes/group-node.tsx @@ -1,7 +1,9 @@ import React from 'react'; -import { Handle, Position } from '@xyflow/react'; +import { Handle, type Node, type NodeProps, Position } from '@xyflow/react'; -const GroupNode = () => { +interface Props extends NodeProps> {} + +const GroupNode: React.FC = () => { return ( <> diff --git a/frontend/webapp/reuseable-components/nodes-data-flow/nodes/header-node.tsx b/frontend/webapp/reuseable-components/nodes-data-flow/nodes/header-node.tsx index 449995aad..802b701bb 100644 --- a/frontend/webapp/reuseable-components/nodes-data-flow/nodes/header-node.tsx +++ b/frontend/webapp/reuseable-components/nodes-data-flow/nodes/header-node.tsx @@ -3,20 +3,24 @@ import Image from 'next/image'; import { useAppStore } from '@/store'; import styled from 'styled-components'; import { useSourceCRUD } from '@/hooks'; +import type { Node, NodeProps } from '@xyflow/react'; import { Badge, Checkbox, Text } from '@/reuseable-components'; -interface Column { - icon: string; - title: string; - tagValue: number; -} - -interface HeaderNodeProps { +interface Props + extends NodeProps< + Node< + { + icon: string; + title: string; + tagValue: number; + }, + 'header' + > + > { nodeWidth: number; - data: Column; } -const Container = styled.div<{ $nodeWidth: HeaderNodeProps['nodeWidth'] }>` +const Container = styled.div<{ $nodeWidth: Props['nodeWidth'] }>` width: ${({ $nodeWidth }) => `${$nodeWidth}px`}; padding: 12px 0px 16px 0px; gap: 8px; @@ -34,7 +38,7 @@ const ActionsWrapper = styled.div` margin-right: 24px; `; -const HeaderNode = ({ data, nodeWidth }: HeaderNodeProps) => { +const HeaderNode: React.FC = ({ nodeWidth, data }) => { const { title, icon, tagValue } = data; const isSources = title === 'Sources'; const isActions = title === 'Actions'; From 141db03678ec37521b244377e38ecf2acf3343fc Mon Sep 17 00:00:00 2001 From: Ben Elferink Date: Wed, 20 Nov 2024 17:24:22 +0200 Subject: [PATCH 6/7] [GEN-1791]: unfocus/blur docs button after window.open() (#1801) Co-authored-by: Alon Braymok <138359965+alonkeyval@users.noreply.github.com> Co-authored-by: Tamir David Co-authored-by: Tamir David Co-authored-by: Amir Blum Co-authored-by: Ron Federman <73110295+RonFed@users.noreply.github.com> Co-authored-by: Mike Dame Co-authored-by: alonbraymok Co-authored-by: Daria Dovzhikova Co-authored-by: David <65228999+david336362@users.noreply.github.com> Co-authored-by: David Co-authored-by: Eden Federman From 572d4779102988d4e317426d413917d45a076a35 Mon Sep 17 00:00:00 2001 From: Ben Elferink Date: Wed, 20 Nov 2024 17:27:08 +0200 Subject: [PATCH 7/7] [GEN-1768]: fix value and label for "bytes" (#1803) Co-authored-by: Alon Braymok <138359965+alonkeyval@users.noreply.github.com> Co-authored-by: Tamir David Co-authored-by: Tamir David Co-authored-by: Amir Blum Co-authored-by: Ron Federman <73110295+RonFed@users.noreply.github.com> Co-authored-by: Mike Dame Co-authored-by: alonbraymok Co-authored-by: Daria Dovzhikova Co-authored-by: David <65228999+david336362@users.noreply.github.com> Co-authored-by: David Co-authored-by: Eden Federman --- frontend/webapp/utils/functions/formatters.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/frontend/webapp/utils/functions/formatters.ts b/frontend/webapp/utils/functions/formatters.ts index ed7c86f81..39cf58e7f 100644 --- a/frontend/webapp/utils/functions/formatters.ts +++ b/frontend/webapp/utils/functions/formatters.ts @@ -3,11 +3,11 @@ import { ExportedSignals, OVERVIEW_ENTITY_TYPES, WorkloadId } from '@/types'; export const formatBytes = (bytes?: number) => { if (!bytes) return '0 KB/s'; - const sizes = ['Bytes', 'KB/s', 'MB/s', 'GB/s', 'TB/s']; + const sizes = ['Bytes/s', 'KB/s', 'MB/s', 'GB/s', 'TB/s']; const i = Math.floor(Math.log(bytes) / Math.log(1024)); const value = bytes / Math.pow(1024, i); - return `${value.toFixed(1)} ${sizes[i]}`; + return `${value.toFixed(i === 0 ? 0 : 1)} ${sizes[i]}`; }; export const extractMonitors = (exportedSignals: ExportedSignals) => {