Skip to content

Commit 71361cf

Browse files
committed
feat: filter button + tinted nodes
1 parent 50559a8 commit 71361cf

File tree

3 files changed

+95
-41
lines changed

3 files changed

+95
-41
lines changed

src/components/Graphs/Graph.module.css

Lines changed: 34 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,39 @@
33
height: 600px;
44
overflow: hidden;
55
font-family: var(--sapFontFamily);
6+
position: relative;
67
}
78

89
.graphColumn {
910
flex: 1;
1011
display: flex;
1112
flex-direction: column;
13+
background-color: #ffffff;
14+
}
15+
16+
.topLegendContainer {
17+
position: absolute;
18+
top: 1rem;
19+
right: 1rem;
20+
display: flex;
21+
align-items: center;
22+
z-index: 2;
23+
}
24+
25+
.filterIcon {
26+
display: flex;
27+
align-items: center;
28+
cursor: pointer;
29+
padding: 4px;
30+
border-radius: 8px;
31+
transition: background-color 0.2s ease;
32+
background-color: rgba(255, 255, 255, 0.9);
33+
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
34+
margin-left: 0.5rem;
35+
}
36+
37+
.filterIcon:hover {
38+
background-color: var(--sapButton_Hover_Background, #f0f0f0);
1239
}
1340

1441
.graphHeader {
@@ -45,15 +72,20 @@
4572
color: var(--sapTextColor, #222);
4673
}
4774

48-
/* Remove the default fieldset frame when used for grouping only */
4975
.fieldsetReset {
5076
border: 0;
5177
margin: 0;
5278
padding: 0;
5379
min-inline-size: 0;
5480
}
5581

56-
/* React Flow Controls dark mode */
82+
.popoverButtonContainer {
83+
display: flex;
84+
flex-direction: column;
85+
gap: 0.5rem;
86+
padding: 0.5rem;
87+
}
88+
5789
:global([data-theme='dark'] .react-flow__controls) {
5890
background-color: rgba(28, 28, 28, 0.9);
5991
border: 1px solid rgba(255, 255, 255, 0.15);

src/components/Graphs/Graph.tsx

Lines changed: 53 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import React, { useState, useCallback, useMemo } from 'react';
2-
import { ReactFlow, Background, Controls, MarkerType, Node, Panel } from '@xyflow/react';
2+
import { ReactFlow, Background, Controls, MarkerType, Node } from '@xyflow/react';
3+
import { Button, Popover } from '@ui5/webcomponents-react';
34
import type { NodeProps } from '@xyflow/react';
4-
import { RadioButton, FlexBox, FlexBoxAlignItems } from '@ui5/webcomponents-react';
55
import styles from './Graph.module.css';
66
import '@xyflow/react/dist/style.css';
77
import { NodeData, ColorBy } from './types';
@@ -32,7 +32,8 @@ const Graph: React.FC = () => {
3232
const { t } = useTranslation();
3333
const { openInAside } = useSplitter();
3434
const { isDarkTheme } = useTheme();
35-
const [colorBy, setColorBy] = useState<ColorBy>('provider');
35+
const [colorBy, setColorBy] = useState<ColorBy>('source');
36+
const [filterPopoverOpen, setFilterPopoverOpen] = useState(false);
3637

3738
const handleYamlClick = useCallback(
3839
(item: ManagedResourceItem) => {
@@ -92,37 +93,56 @@ const Graph: React.FC = () => {
9293
>
9394
<Controls showInteractive={false} />
9495
<Background />
95-
<Panel position="top-left">
96-
<FlexBox alignItems={FlexBoxAlignItems.Center} role="radiogroup">
97-
<fieldset className={styles.fieldsetReset}>
98-
<div className={styles.graphHeader}>
99-
<span className={styles.colorizedTitle}>{t('Graphs.colorizedTitle')}</span>
100-
<RadioButton
101-
name="colorBy"
102-
text={t('Graphs.colorsProviderConfig')}
103-
checked={colorBy === 'provider'}
104-
onChange={() => setColorBy('provider')}
105-
/>
106-
<RadioButton
107-
name="colorBy"
108-
text={t('Graphs.colorsProvider')}
109-
checked={colorBy === 'source'}
110-
onChange={() => setColorBy('source')}
111-
/>
112-
<RadioButton
113-
name="colorBy"
114-
text={t('Graphs.colorsFlux')}
115-
checked={colorBy === 'flux'}
116-
onChange={() => setColorBy('flux')}
117-
/>
118-
</div>
119-
</fieldset>
120-
</FlexBox>
121-
</Panel>
122-
<Panel position="top-right">
123-
<Legend legendItems={legendItems} />
124-
</Panel>
12596
</ReactFlow>
97+
98+
<div className={styles.topLegendContainer}>
99+
<Legend legendItems={legendItems}/>
100+
<Popover
101+
opener="filter-button"
102+
open={filterPopoverOpen}
103+
onClose={() => setFilterPopoverOpen(false)}
104+
placement="Top"
105+
>
106+
<div className={styles.popoverButtonContainer}>
107+
<Button
108+
design={colorBy === 'source' ? 'Emphasized' : 'Default'}
109+
onClick={() => {
110+
setColorBy('source');
111+
setFilterPopoverOpen(false);
112+
}}
113+
>
114+
{t('Graphs.colorsProvider')}
115+
</Button>
116+
<Button
117+
design={colorBy === 'provider' ? 'Emphasized' : 'Default'}
118+
onClick={() => {
119+
setColorBy('provider');
120+
setFilterPopoverOpen(false);
121+
}}
122+
>
123+
{t('Graphs.colorsProviderConfig')}
124+
</Button>
125+
<Button
126+
design={colorBy === 'flux' ? 'Emphasized' : 'Default'}
127+
onClick={() => {
128+
setColorBy('flux');
129+
setFilterPopoverOpen(false);
130+
}}
131+
>
132+
{t('Graphs.colorsFlux')}
133+
</Button>
134+
</div>
135+
</Popover>
136+
<div className={styles.filterIcon}>
137+
<Button
138+
id="filter-button"
139+
design="Transparent"
140+
icon="filter"
141+
tooltip={t('Graphs.colorizedTitle')}
142+
onClick={() => setFilterPopoverOpen(!filterPopoverOpen)}
143+
/>
144+
</div>
145+
</div>
126146
</div>
127147
</div>
128148
);

src/components/Graphs/useGraph.ts

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -24,14 +24,17 @@ function buildGraph(
2424
treeData.forEach((n) => {
2525
const colorKey: string =
2626
colorBy === 'source' ? n.providerType : colorBy === 'flux' ? (n.fluxName ?? 'default') : n.providerConfigName;
27-
const node: Node<NodeData> = {
27+
const borderColor = colorMap[colorKey] || '#ccc';
28+
const backgroundColor = `${borderColor}08`;
29+
30+
const node: Node<NodeData> = {
2831
id: n.id,
2932
type: 'custom',
3033
data: { ...n },
3134
style: {
32-
border: `2px solid ${colorMap[colorKey] || '#ccc'}`,
35+
border: `2px solid ${borderColor}`,
3336
borderRadius: 8,
34-
backgroundColor: 'var(--sapTile_Background, #fff)',
37+
backgroundColor,
3538
width: nodeWidth,
3639
height: nodeHeight,
3740
},
@@ -53,8 +56,7 @@ function buildGraph(
5356
id: `e-${n.parentId}-${n.id}`,
5457
source: n.parentId,
5558
target: n.id,
56-
markerEnd: { type: MarkerType.ArrowClosed },
57-
});
59+
style: { strokeWidth: 2, stroke: '#888' }, });
5860
}
5961
n.extraRefs?.forEach((refId) => {
6062
if (nodeMap.has(refId)) {
@@ -63,7 +65,7 @@ function buildGraph(
6365
id: `e-${refId}-${n.id}`,
6466
source: refId,
6567
target: n.id,
66-
markerEnd: { type: MarkerType.ArrowClosed },
68+
style: { strokeWidth: 2, stroke: '#888' },
6769
});
6870
}
6971
});

0 commit comments

Comments
 (0)