Skip to content

Commit feb6b88

Browse files
authored
Merge pull request #152 from jpinsonneau/dark_mode
Dark theme support
2 parents 9943b3b + 7619456 commit feb6b88

File tree

14 files changed

+316
-133
lines changed

14 files changed

+316
-133
lines changed

web/package-lock.json

Lines changed: 158 additions & 95 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

web/package.json

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -23,12 +23,12 @@
2323
"fix-imports": "eslint --no-eslintrc --no-inline-config --parser '@typescript-eslint/parser' --plugin 'unused-imports' --plugin 'react-hooks' --rule 'unused-imports/no-unused-imports:error' --fix \"./src/**/*.{ts,tsx}\""
2424
},
2525
"devDependencies": {
26-
"@openshift-console/dynamic-plugin-sdk": "0.0.6",
26+
"@openshift-console/dynamic-plugin-sdk": "0.0.10",
2727
"@openshift-console/dynamic-plugin-sdk-webpack": "0.0.6",
28-
"@patternfly/react-charts": "^6.51.19",
29-
"@patternfly/react-core": "^4.202.5",
30-
"@patternfly/react-table": "4.44.4",
31-
"@patternfly/react-topology": "4.49.5",
28+
"@patternfly/react-charts": "^6.67.1",
29+
"@patternfly/react-core": "^4.214.1",
30+
"@patternfly/react-table": "4.83.1",
31+
"@patternfly/react-topology": "4.61.1",
3232
"@testing-library/react": "^12.1.2",
3333
"@types/copy-webpack-plugin": "8.0.1",
3434
"@types/enzyme": "3.10.x",

web/setup-tests.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,9 @@ jest.mock('react-i18next', () => {
4949
jest.mock('@openshift-console/dynamic-plugin-sdk', () => {
5050
return {
5151
useResolvedExtensions: jest.fn(),
52+
useK8sModels: () => {
53+
return [{}, false];
54+
},
5255
ResourceLink: () => {
5356
return null;
5457
}
@@ -70,7 +73,7 @@ jest.mock('@patternfly/react-core', () => ({
7073
DatePicker: () => {
7174
return null;
7275
},
73-
OverflowMenuControl: ()=> {
76+
OverflowMenuControl: () => {
7477
return null;
7578
}
7679
}));
Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,17 @@
11
/* table stripping from pf-color-black-150 value */
2-
tbody>tr:nth-child(even) {
2+
.light-stripped:nth-child(even) {
33
background-color: #f5f5f5;
44
}
55

6+
.dark-stripped:nth-child(even) {
7+
background-color: #050505;
8+
}
9+
610
.newflow-appear {
7-
background-color: #73bcf755;
11+
background-color: #73bcf755;
812
}
913

1014
.newflow-appear-done {
11-
background-color: transparent;
12-
transition: background-color 5s;
13-
}
15+
background-color: transparent;
16+
transition: background-color 5s;
17+
}

web/src/components/netflow-table/netflow-table-row.tsx

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import { Size } from '../dropdowns/display-dropdown';
66
import { RecordField } from '../netflow-record/record-field';
77
import './netflow-table-row.css';
88
import CSSTransition from 'react-transition-group/CSSTransition';
9+
import { isDark } from '../../utils/theme';
910

1011
const NetflowTableRow: React.FC<{
1112
flow: Record;
@@ -24,7 +25,11 @@ const NetflowTableRow: React.FC<{
2425
const shouldHighlight = React.useRef(highlight);
2526

2627
return (
27-
<Tr isRowSelected={flow.key === selectedRecord?.key} onRowClick={onRowClick}>
28+
<Tr
29+
isRowSelected={flow.key === selectedRecord?.key}
30+
onRowClick={onRowClick}
31+
className={`${isDark() ? 'dark' : 'light'}-stripped`}
32+
>
2833
{columns.map(c => (
2934
<CSSTransition
3035
key={c.id}

web/src/components/netflow-topology/__tests__/netflow-topology.spec.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ describe('<NetflowTopology />', () => {
1111
const mocks = {
1212
error: undefined as string | undefined,
1313
loading: false,
14+
k8sModels: {},
1415
range: defaultTimeRange,
1516
metricFunction: 'sum' as MetricFunction,
1617
metricType: 'bytes' as MetricType,

web/src/components/netflow-topology/components/node.tsx

Lines changed: 20 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,8 @@ const getStatusIcon = (status: NodeStatus) => {
5454
};
5555

5656
type BaseNodeProps = {
57+
children?: React.ReactNode;
58+
className?: string;
5759
element: Node;
5860
droppable?: boolean;
5961
hover?: boolean;
@@ -66,9 +68,10 @@ type BaseNodeProps = {
6668
label?: string; // Defaults to element.getLabel()
6769
secondaryLabel?: string;
6870
showLabel?: boolean; // Defaults to true
69-
labelPosition?: LabelPosition; // Defaults to bottom
71+
labelPosition?: LabelPosition; // Defaults to element.getLabelPosition()
7072
truncateLength?: number; // Defaults to 13
7173
labelIconClass?: string; // Icon to show in label
74+
labelIcon?: React.ReactNode;
7275
labelIconPadding?: number;
7376
badge?: string;
7477
badgeColor?: string;
@@ -82,7 +85,7 @@ type BaseNodeProps = {
8285
statusDecoratorTooltip?: React.ReactNode;
8386
onStatusDecoratorClick?: (event: React.MouseEvent<SVGGElement, MouseEvent>, element: GraphElement) => void;
8487
getCustomShape?: (node: Node) => React.FC<ShapeProps>;
85-
getShapeDecoratorCenter?: (quadrant: TopologyQuadrant, node: Node, radius?: number) => { x: number; y: number };
88+
getShapeDecoratorCenter?: (quadrant: TopologyQuadrant, node: Node) => { x: number; y: number };
8689
} & Partial<
8790
WithSelectionProps &
8891
WithDragNodeProps &
@@ -96,6 +99,7 @@ type BaseNodeProps = {
9699
// to support shadow / hover behaviors
97100

98101
const BaseNode: React.FC<BaseNodeProps> = ({
102+
className,
99103
element,
100104
selected,
101105
hover,
@@ -104,9 +108,11 @@ const BaseNode: React.FC<BaseNodeProps> = ({
104108
shadowed,
105109
highlighted,
106110
secondaryLabel,
107-
labelPosition = LabelPosition.bottom,
111+
labelPosition,
108112
truncateLength,
109113
labelIconClass,
114+
labelIcon,
115+
labelIconPadding,
110116
showStatusBackground,
111117
showStatusDecorator = false,
112118
statusDecoratorTooltip,
@@ -149,8 +155,8 @@ const BaseNode: React.FC<BaseNodeProps> = ({
149155
}
150156

151157
const { x, y } = getShapeDecoratorCenter
152-
? getShapeDecoratorCenter(StatusQuadrant, element, DEFAULT_DECORATOR_RADIUS)
153-
: getDefaultShapeDecoratorCenter(StatusQuadrant, element, DEFAULT_DECORATOR_RADIUS);
158+
? getShapeDecoratorCenter(StatusQuadrant, element)
159+
: getDefaultShapeDecoratorCenter(StatusQuadrant, element);
154160

155161
const decorator = (
156162
<Decorator
@@ -191,8 +197,10 @@ const BaseNode: React.FC<BaseNodeProps> = ({
191197

192198
const groupClassName = css(
193199
styles.topologyNode,
200+
className,
194201
isHover && 'pf-m-hover',
195202
(dragging || edgeDragging) && 'pf-m-dragging',
203+
canDrop && 'pf-m-highlight',
196204
canDrop && dropTarget && 'pf-m-drop-target',
197205
selected && 'pf-m-selected',
198206
StatusModifier[status],
@@ -214,6 +222,8 @@ const BaseNode: React.FC<BaseNodeProps> = ({
214222
filter = createSvgIdUrl(NODE_SHADOW_FILTER_ID_HOVER);
215223
}
216224

225+
const nodeLabelPosition = labelPosition || element.getLabelPosition();
226+
217227
return (
218228
<Layer id={dragging || isHover || highlighted ? TOP_LAYER : undefined}>
219229
<g ref={hoverRef as React.LegacyRef<SVGGElement> | undefined} className={groupClassName}>
@@ -232,9 +242,9 @@ const BaseNode: React.FC<BaseNodeProps> = ({
232242
{showLabel && (label || element.getLabel()) && (
233243
<NodeLabel
234244
className={css(styles.topologyNodeLabel)}
235-
x={labelPosition === LabelPosition.right ? width + 8 : width / 2}
236-
y={labelPosition === LabelPosition.right ? height / 2 : height + 6}
237-
position={labelPosition}
245+
x={nodeLabelPosition === LabelPosition.right ? width + 8 : width / 2}
246+
y={nodeLabelPosition === LabelPosition.right ? height / 2 : height + 6}
247+
position={nodeLabelPosition}
238248
paddingX={8}
239249
paddingY={4}
240250
secondaryLabel={secondaryLabel}
@@ -250,6 +260,8 @@ const BaseNode: React.FC<BaseNodeProps> = ({
250260
contextMenuOpen={contextMenuOpen ? true : false}
251261
hover={isHover}
252262
labelIconClass={labelIconClass}
263+
labelIcon={labelIcon}
264+
labelIconPadding={labelIconPadding}
253265
>
254266
{label || element.getLabel()}
255267
</NodeLabel>

web/src/components/netflow-topology/netflow-topology.css

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,4 +53,12 @@ g.topology.node-highlighted>g>ellipse {
5353
g.topology.edge-highlighted>.pf-topology__edge__link,
5454
g.topology.edge-highlighted>.pf-topology-connector-arrow {
5555
stroke: #0066CC;
56+
}
57+
58+
.topology-icon {
59+
border: none;
60+
}
61+
62+
.topology-icon > text {
63+
fill: white;
5664
}

web/src/components/netflow-topology/netflow-topology.tsx

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@ import stylesComponentFactory from './componentFactories/stylesComponentFactory'
5252
import layoutFactory from './layouts/layoutFactory';
5353
import './netflow-topology.css';
5454
import { STEP_INTO_EVENT, FILTER_EVENT } from './styles/styleNode';
55+
import { K8sModel } from '@openshift-console/dynamic-plugin-sdk';
5556

5657
export const HOVER_EVENT = 'hover';
5758

@@ -64,6 +65,7 @@ const ZOOM_OUT = 3 / 4;
6465
const FIT_PADDING = 80;
6566

6667
const TopologyContent: React.FC<{
68+
k8sModels: { [key: string]: K8sModel };
6769
range: number | TimeRange;
6870
metricFunction?: MetricFunction;
6971
metricType?: MetricType;
@@ -76,6 +78,7 @@ const TopologyContent: React.FC<{
7678
selected: GraphElement | undefined;
7779
onSelect: (e: GraphElement | undefined) => void;
7880
}> = ({
81+
k8sModels,
7982
range,
8083
metricFunction,
8184
metricType,
@@ -326,7 +329,7 @@ const TopologyContent: React.FC<{
326329
highlightedId = selectedIds[0];
327330
}
328331

329-
const updatedModel = generateDataModel(metrics, getOptions(), searchValue, highlightedId, filters, t);
332+
const updatedModel = generateDataModel(metrics, getOptions(), searchValue, highlightedId, filters, t, k8sModels);
330333
const allIds = [...(updatedModel.nodes || []), ...(updatedModel.edges || [])].map(item => item.id);
331334
controller.getElements().forEach(e => {
332335
if (e.getType() !== 'graph') {
@@ -352,7 +355,7 @@ const TopologyContent: React.FC<{
352355
}
353356
});
354357
controller.fromModel(updatedModel);
355-
}, [controller, prevMetrics, metrics, hoveredId, selectedIds, getOptions, searchValue, filters, t]);
358+
}, [controller, prevMetrics, metrics, hoveredId, selectedIds, getOptions, searchValue, filters, t, k8sModels]);
356359

357360
//update model on layout / metrics / filters change
358361
React.useEffect(() => {
@@ -523,6 +526,7 @@ const TopologyContent: React.FC<{
523526

524527
const NetflowTopology: React.FC<{
525528
loading?: boolean;
529+
k8sModels: { [key: string]: K8sModel };
526530
error?: string;
527531
range: number | TimeRange;
528532
metricFunction?: MetricFunction;
@@ -537,6 +541,7 @@ const NetflowTopology: React.FC<{
537541
onSelect: (e: GraphElement | undefined) => void;
538542
}> = ({
539543
loading,
544+
k8sModels,
540545
error,
541546
range,
542547
metricFunction,
@@ -582,6 +587,7 @@ const NetflowTopology: React.FC<{
582587
return (
583588
<VisualizationProvider controller={controller}>
584589
<TopologyContent
590+
k8sModels={k8sModels}
585591
range={range}
586592
metricFunction={metricFunction}
587593
metricType={metricType}

web/src/components/netflow-traffic.tsx

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ import {
3939
MetricFunction,
4040
MetricType
4141
} from '../model/flow-query';
42+
import { useK8sModelsWithColors } from '../utils/k8s-models-hook';
4243
import { Stats, TopologyMetrics } from '../api/loki';
4344
import { DefaultOptions, TopologyGroupTypes, TopologyOptions } from '../model/topology';
4445
import { Column, getDefaultColumns } from '../utils/columns';
@@ -105,6 +106,7 @@ export const NetflowTraffic: React.FC<{
105106
const { push } = useHistory();
106107
const { t } = useTranslation('plugin__network-observability-plugin');
107108
const [extensions] = useResolvedExtensions<ModelFeatureFlag>(isModelFeatureFlag);
109+
const k8sModels = useK8sModelsWithColors();
108110
const [queryParams, setQueryParams] = useLocalStorage<string>(LOCAL_STORAGE_QUERY_PARAMS_KEY);
109111
// set url params from local storage saved items at startup if empty
110112
if (hasEmptyParams() && queryParams) {
@@ -566,6 +568,7 @@ export const NetflowTraffic: React.FC<{
566568
return (
567569
<NetflowTopology
568570
loading={loading}
571+
k8sModels={k8sModels}
569572
error={error}
570573
range={range}
571574
metricFunction={metricFunction}

0 commit comments

Comments
 (0)