Skip to content

Commit b3d9d14

Browse files
committed
chore: ESLint fixes and touchups
1 parent 0b3289f commit b3d9d14

3 files changed

Lines changed: 132 additions & 24 deletions

File tree

Website/components/insightsview/overview/InsightsOverviewView.tsx

Lines changed: 5 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import { InfoCard } from "@/components/shared/elements/InfoCard";
22
import { useDatamodelData } from "@/contexts/DatamodelDataContext";
33
import { ComponentIcon, InfoIcon, ProcessesIcon, SolutionIcon, WarningIcon } from "@/lib/icons";
4-
import { generateThemedSVG } from "@/lib/svgart";
4+
import { generateLiquidCheeseSVG } from "@/lib/svgart";
55
import { Box, Grid, Paper, Stack, Tooltip, Typography, useTheme } from "@mui/material";
66
import { ResponsiveBar } from "@nivo/bar";
77
import { useMemo } from "react";
@@ -71,15 +71,12 @@ const InsightsOverviewView = ({ }: InsightsOverviewViewProps) => {
7171
<Grid size={{ xs: 12, md: 7 }}>
7272
<Box className="px-6 py-8 mb-8 rounded-2xl relative flex items-center h-full" sx={{
7373
backgroundColor: "background.default",
74-
backgroundImage: generateThemedSVG(
74+
backgroundImage: generateLiquidCheeseSVG(
7575
theme.palette.primary.main,
76-
theme.palette.primary.light,
77-
theme.palette.primary.dark
7876
),
79-
backgroundAttachment: "fixed",
8077
backgroundSize: "cover",
8178
color: 'primary.contrastText',
82-
}}>
79+
}}>
8380
<Stack direction="column" spacing={2} justifyContent="center">
8481
<Typography
8582
variant="h3"
@@ -100,7 +97,7 @@ const InsightsOverviewView = ({ }: InsightsOverviewViewProps) => {
10097
: 'none'
10198
}}
10299
>
103-
All your insights in one place. Keep track of your data model's health and status.<br />Stay informed about any potential issues or areas for improvement.
100+
All your insights in one place. Keep track of your data model&apos;s health and status.<br />Stay informed about any potential issues or areas for improvement.
104101
</Typography>
105102
</Stack>
106103
</Box>
@@ -166,11 +163,6 @@ const InsightsOverviewView = ({ }: InsightsOverviewViewProps) => {
166163
/>
167164
</Grid>
168165

169-
170-
{/* // TODO:
171-
// Barchart notes enabled and other details
172-
// Tables with no rules */}
173-
174166
<Grid size={12}>
175167
<Paper elevation={2} className="p-6 rounded-2xl">
176168
<Typography variant="h6" className="mb-4" sx={{ color: 'text.primary' }}>
@@ -197,7 +189,7 @@ const InsightsOverviewView = ({ }: InsightsOverviewViewProps) => {
197189
enableLabel={true}
198190
labelSkipWidth={12}
199191
labelSkipHeight={12}
200-
labelTextColor={{ from: 'color', modifiers: [['darker', 1.6]] }}
192+
labelTextColor={{ from: 'color', modifiers: [['brighter', 3]] }}
201193
legends={[
202194
{
203195
dataFrom: 'keys',

Website/components/insightsview/solutions/InsightsSolutionView.tsx

Lines changed: 28 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,17 @@
11
import { useDatamodelData } from '@/contexts/DatamodelDataContext'
2-
import { Paper, Typography, Box, Divider, Grid } from '@mui/material'
2+
import { Paper, Typography, Box, Grid, useTheme } from '@mui/material'
33
import React, { useMemo, useState } from 'react'
44
import { ResponsiveChord, RibbonDatum } from '@nivo/chord'
55
import { SolutionComponentType, SolutionComponentTypeEnum } from '@/lib/Types'
6+
import { generateEnvelopeSVG } from '@/lib/svgart'
67

78
interface InsightsSolutionViewProps {
89

910
}
1011

1112
const InsightsSolutionView = ({ }: InsightsSolutionViewProps) => {
1213
const { solutions } = useDatamodelData();
14+
const theme = useTheme();
1315

1416
const [selectedSolution, setSelectedSolution] = useState<{ sourceSolution: { name: string; color: string }; targetSolution: { name: string; color: string }; sharedComponents: SolutionComponentType[] } | undefined>(undefined);
1517

@@ -165,6 +167,25 @@ const InsightsSolutionView = ({ }: InsightsSolutionViewProps) => {
165167

166168
return (
167169
<Grid container spacing={2}>
170+
<Grid size={12}>
171+
<Box className="px-6 py-8 mb-8 rounded-2xl relative flex justify-center h-full flex-col" sx={{
172+
backgroundColor: "background.default",
173+
backgroundImage: generateEnvelopeSVG(
174+
theme.palette.primary.main,
175+
),
176+
backgroundPosition: "center",
177+
backgroundSize: "cover",
178+
color: 'primary.contrastText',
179+
}}>
180+
<Typography variant="h4" className="font-semibold">
181+
Solution Insights
182+
</Typography>
183+
<Typography variant="body1" sx={{ color: 'primary.contrastText', mt: 1, maxWidth: 600 }}>
184+
Explore relationships between solutions in your data model.
185+
The chord diagram below visualizes shared components between different solutions, helping you identify overlaps and dependencies.
186+
</Typography>
187+
</Box>
188+
</Grid>
168189
<Grid size={{ xs: 12, md: 8 }}>
169190
<Paper className="p-6 rounded-2xl" elevation={2}>
170191
<Typography variant="h4" className="mb-6 font-semibold">
@@ -187,7 +208,7 @@ const InsightsSolutionView = ({ }: InsightsSolutionViewProps) => {
187208
arcOpacity={1}
188209
arcBorderWidth={1}
189210
arcBorderColor={{ from: 'color', modifiers: [['darker', 0.3]] }}
190-
arcTooltip={_ => <></>}
211+
arcTooltip={undefined}
191212
ribbonOpacity={0.5}
192213
ribbonBorderWidth={1}
193214
ribbonBorderColor={{ from: 'color', modifiers: [['darker', 0.3]] }}
@@ -226,7 +247,7 @@ const InsightsSolutionView = ({ }: InsightsSolutionViewProps) => {
226247
<Typography variant="h6" className="mb-2">
227248
Solution Summary
228249
</Typography>
229-
{selectedSolution && (
250+
{selectedSolution ? (
230251
<Box className="rounded-lg p-4 flex-grow" sx={{ backgroundColor: "background.default" }}>
231252
<Typography variant="subtitle1" sx={{ fontWeight: 'bold', mb: 1 }}>
232253
<Box className="p-1 w-4 h-4 rounded-md inline-block mr-1" sx={{ backgroundColor: selectedSolution.sourceSolution.color }} />{selectedSolution.sourceSolution.name} -and- <Box className="p-1 w-4 h-4 rounded-md inline-block mr-1" sx={{ backgroundColor: selectedSolution.targetSolution.color }} />{selectedSolution.targetSolution.name}
@@ -262,6 +283,10 @@ const InsightsSolutionView = ({ }: InsightsSolutionViewProps) => {
262283
)}
263284
</Box>
264285
</Box>
286+
) : (
287+
<Typography variant="body2" sx={{ color: 'text.secondary' }}>
288+
Select a connection in the chord diagram to see details about shared components between solutions.
289+
</Typography>
265290
)}
266291
</Paper>
267292
</Grid>

Website/lib/svgart.ts

Lines changed: 99 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,101 @@
1-
import { useTheme } from '@mui/material/styles';
1+
// Helper function to convert hex to HSL
2+
const hexToHsl = (hex: string): [number, number, number] => {
3+
const r = parseInt(hex.slice(1, 3), 16) / 255;
4+
const g = parseInt(hex.slice(3, 5), 16) / 255;
5+
const b = parseInt(hex.slice(5, 7), 16) / 255;
26

3-
export const generateThemedSVG = (primaryMain: string, primaryLight: string, primaryDark: string) => {
4-
// URL encode the colors properly
5-
const primary = encodeURIComponent(primaryMain);
6-
const primaryLightEncoded = encodeURIComponent(primaryLight);
7-
const primaryDarkEncoded = encodeURIComponent(primaryDark);
7+
const max = Math.max(r, g, b);
8+
const min = Math.min(r, g, b);
9+
let h = 0, s = 0;
10+
const l = (max + min) / 2;
811

9-
return `url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='100%25' height='100%25' viewBox='0 0 1600 800'%3E%3Cg %3E%3Cpath fill='${primaryLightEncoded}' d='M486 705.8c-109.3-21.8-223.4-32.2-335.3-19.4C99.5 692.1 49 703 0 719.8V800h843.8c-115.9-33.2-230.8-68.1-347.6-92.2C492.8 707.1 489.4 706.5 486 705.8z'/%3E%3Cpath fill='${primaryDarkEncoded}' d='M1600 0H0v719.8c49-16.8 99.5-27.8 150.7-33.5c111.9-12.7 226-2.4 335.3 19.4c3.4 0.7 6.8 1.4 10.2 2c116.8 24 231.7 59 347.6 92.2H1600V0z'/%3E%3Cpath fill='${primaryDarkEncoded}' d='M478.4 581c3.2 0.8 6.4 1.7 9.5 2.5c196.2 52.5 388.7 133.5 593.5 176.6c174.2 36.6 349.5 29.2 518.6-10.2V0H0v574.9c52.3-17.6 106.5-27.7 161.1-30.9C268.4 537.4 375.7 554.2 478.4 581z'/%3E%3Cpath fill='${primary}' d='M0 0v429.4c55.6-18.4 113.5-27.3 171.4-27.7c102.8-0.8 203.2 22.7 299.3 54.5c3 1 5.9 2 8.9 3c183.6 62 365.7 146.1 562.4 192.1c186.7 43.7 376.3 34.4 557.9-12.6V0H0z'/%3E%3Cpath fill='${primaryLightEncoded}' d='M181.8 259.4c98.2 6 191.9 35.2 281.3 72.1c2.8 1.1 5.5 2.3 8.3 3.4c171 71.6 342.7 158.5 531.3 207.7c198.8 51.8 403.4 40.8 597.3-14.8V0H0v283.2C59 263.6 120.6 255.7 181.8 259.4z'/%3E%3Cpath fill='${primary}' d='M1600 0H0v136.3c62.3-20.9 127.7-27.5 192.2-19.2c93.6 12.1 180.5 47.7 263.3 89.6c2.6 1.3 5.1 2.6 7.7 3.9c158.4 81.1 319.7 170.9 500.3 223.2c210.5 61 430.8 49 636.6-16.6V0z'/%3E%3Cpath fill='${primaryLightEncoded}' d='M454.9 86.3C600.7 177 751.6 269.3 924.1 325c208.6 67.4 431.3 60.8 637.9-5.3c12.8-4.1 25.4-8.4 38.1-12.9V0H288.1c56 21.3 108.7 50.6 159.7 82C450.2 83.4 452.5 84.9 454.9 86.3z'/%3E%3Cpath fill='${primaryDarkEncoded}' d='M1600 0H498c118.1 85.8 243.5 164.5 386.8 216.2c191.8 69.2 400 74.7 595 21.1c40.8-11.2 81.1-25.2 120.3-41.7V0z'/%3E%3Cpath fill='${primary}' d='M1397.5 154.8c47.2-10.6 93.6-25.3 138.6-43.8c21.7-8.9 43-18.8 63.9-29.5V0H643.4c62.9 41.7 129.7 78.2 202.1 107.4C1020.4 178.1 1214.2 196.1 1397.5 154.8z'/%3E%3Cpath fill='${primaryLightEncoded}' d='M1315.3 72.4c75.3-12.6 148.9-37.1 216.8-72.4h-723C966.8 71 1144.7 101 1315.3 72.4z'/%3E%3C/g%3E%3C/svg%3E")`;
10-
};
12+
if (max !== min) {
13+
const d = max - min;
14+
s = l > 0.5 ? d / (2 - max - min) : d / (max + min);
15+
switch (max) {
16+
case r: h = (g - b) / d + (g < b ? 6 : 0); break;
17+
case g: h = (b - r) / d + 2; break;
18+
case b: h = (r - g) / d + 4; break;
19+
}
20+
h /= 6;
21+
}
22+
23+
return [h * 360, s * 100, l * 100];
24+
};
25+
26+
// Helper function to convert HSL to hex
27+
const hslToHex = (h: number, s: number, l: number): string => {
28+
h /= 360;
29+
s /= 100;
30+
l /= 100;
31+
32+
const c = (1 - Math.abs(2 * l - 1)) * s;
33+
const x = c * (1 - Math.abs((h * 6) % 2 - 1));
34+
const m = l - c / 2;
35+
let r = 0, g = 0, b = 0;
36+
37+
if (0 <= h && h < 1/6) {
38+
r = c; g = x; b = 0;
39+
} else if (1/6 <= h && h < 2/6) {
40+
r = x; g = c; b = 0;
41+
} else if (2/6 <= h && h < 3/6) {
42+
r = 0; g = c; b = x;
43+
} else if (3/6 <= h && h < 4/6) {
44+
r = 0; g = x; b = c;
45+
} else if (4/6 <= h && h < 5/6) {
46+
r = x; g = 0; b = c;
47+
} else if (5/6 <= h && h < 1) {
48+
r = c; g = 0; b = x;
49+
}
50+
51+
r = Math.round((r + m) * 255);
52+
g = Math.round((g + m) * 255);
53+
b = Math.round((b + m) * 255);
54+
55+
return `#${r.toString(16).padStart(2, '0')}${g.toString(16).padStart(2, '0')}${b.toString(16).padStart(2, '0')}`;
56+
};
57+
58+
// Generate lighter and darker variants of a color
59+
const generateColorVariants = (baseColor: string) => {
60+
// Ensure hex format
61+
const hex = baseColor.startsWith('#') ? baseColor : `#${baseColor}`;
62+
63+
const [h, s, l] = hexToHsl(hex);
64+
65+
// Generate lighter variant (increase lightness by 20%)
66+
const lightL = Math.min(100, l + 20);
67+
const lightColor = hslToHex(h, s, lightL);
68+
69+
// Generate darker variant (decrease lightness by 20%)
70+
const darkL = Math.max(0, l - 20);
71+
const darkColor = hslToHex(h, s, darkL);
72+
73+
return {
74+
main: hex,
75+
light: lightColor,
76+
dark: darkColor
77+
};
78+
};
79+
80+
export const generateLiquidCheeseSVG = (primaryColor: string) => {
81+
const hex = primaryColor.startsWith('#') ? primaryColor : `#${primaryColor}`;
82+
const [h, s, l] = hexToHsl(hex);
83+
84+
// Generate 10 color variants from darkest to lightest
85+
const colorSteps = [];
86+
for (let i = 0; i < 10; i++) {
87+
const lightness = Math.max(0, Math.min(100, l + (-30 + (i * 7)))); // Steps of 7% lightness
88+
const color = hslToHex(h, s, lightness);
89+
colorSteps.push(encodeURIComponent(color));
90+
}
91+
92+
return `url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='100%25' height='100%25' viewBox='0 0 1600 800'%3E%3Cg %3E%3Cpath fill='${colorSteps[0]}' d='M486 705.8c-109.3-21.8-223.4-32.2-335.3-19.4C99.5 692.1 49 703 0 719.8V800h843.8c-115.9-33.2-230.8-68.1-347.6-92.2C492.8 707.1 489.4 706.5 486 705.8z'/%3E%3Cpath fill='${colorSteps[1]}' d='M1600 0H0v719.8c49-16.8 99.5-27.8 150.7-33.5c111.9-12.7 226-2.4 335.3 19.4c3.4 0.7 6.8 1.4 10.2 2c116.8 24 231.7 59 347.6 92.2H1600V0z'/%3E%3Cpath fill='${colorSteps[2]}' d='M478.4 581c3.2 0.8 6.4 1.7 9.5 2.5c196.2 52.5 388.7 133.5 593.5 176.6c174.2 36.6 349.5 29.2 518.6-10.2V0H0v574.9c52.3-17.6 106.5-27.7 161.1-30.9C268.4 537.4 375.7 554.2 478.4 581z'/%3E%3Cpath fill='${colorSteps[3]}' d='M0 0v429.4c55.6-18.4 113.5-27.3 171.4-27.7c102.8-0.8 203.2 22.7 299.3 54.5c3 1 5.9 2 8.9 3c183.6 62 365.7 146.1 562.4 192.1c186.7 43.7 376.3 34.4 557.9-12.6V0H0z'/%3E%3Cpath fill='${colorSteps[4]}' d='M181.8 259.4c98.2 6 191.9 35.2 281.3 72.1c2.8 1.1 5.5 2.3 8.3 3.4c171 71.6 342.7 158.5 531.3 207.7c198.8 51.8 403.4 40.8 597.3-14.8V0H0v283.2C59 263.6 120.6 255.7 181.8 259.4z'/%3E%3Cpath fill='${colorSteps[5]}' d='M1600 0H0v136.3c62.3-20.9 127.7-27.5 192.2-19.2c93.6 12.1 180.5 47.7 263.3 89.6c2.6 1.3 5.1 2.6 7.7 3.9c158.4 81.1 319.7 170.9 500.3 223.2c210.5 61 430.8 49 636.6-16.6V0z'/%3E%3Cpath fill='${colorSteps[6]}' d='M454.9 86.3C600.7 177 751.6 269.3 924.1 325c208.6 67.4 431.3 60.8 637.9-5.3c12.8-4.1 25.4-8.4 38.1-12.9V0H288.1c56 21.3 108.7 50.6 159.7 82C450.2 83.4 452.5 84.9 454.9 86.3z'/%3E%3Cpath fill='${colorSteps[7]}' d='M1600 0H498c118.1 85.8 243.5 164.5 386.8 216.2c191.8 69.2 400 74.7 595 21.1c40.8-11.2 81.1-25.2 120.3-41.7V0z'/%3E%3Cpath fill='${colorSteps[8]}' d='M1397.5 154.8c47.2-10.6 93.6-25.3 138.6-43.8c21.7-8.9 43-18.8 63.9-29.5V0H643.4c62.9 41.7 129.7 78.2 202.1 107.4C1020.4 178.1 1214.2 196.1 1397.5 154.8z'/%3E%3Cpath fill='${colorSteps[9]}' d='M1315.3 72.4c75.3-12.6 148.9-37.1 216.8-72.4h-723C966.8 71 1144.7 101 1315.3 72.4z'/%3E%3C/g%3E%3C/svg%3E")`;
93+
};
94+
95+
export const generateEnvelopeSVG = (primaryColor: string) => {
96+
const colors = generateColorVariants(primaryColor);
97+
const primaryLightEncoded = encodeURIComponent(colors.light);
98+
const primaryDarkEncoded = encodeURIComponent(colors.dark);
99+
100+
return `url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='100%25' height='100%25' viewBox='0 0 2 1'%3E%3Cdefs%3E%3ClinearGradient id='a' gradientUnits='userSpaceOnUse' x1='0' x2='0' y1='0' y2='1'%3E%3Cstop offset='0' stop-color='${primaryLightEncoded}'/%3E%3Cstop offset='1' stop-color='${primaryDarkEncoded}'/%3E%3C/linearGradient%3E%3ClinearGradient id='b' gradientUnits='userSpaceOnUse' x1='0' y1='0' x2='0' y2='1'%3E%3Cstop offset='0' stop-color='${primaryLightEncoded}' stop-opacity='0'/%3E%3Cstop offset='1' stop-color='${primaryLightEncoded}' stop-opacity='1'/%3E%3C/linearGradient%3E%3ClinearGradient id='c' gradientUnits='userSpaceOnUse' x1='0' y1='0' x2='2' y2='2'%3E%3Cstop offset='0' stop-color='${primaryLightEncoded}' stop-opacity='0'/%3E%3Cstop offset='1' stop-color='${primaryLightEncoded}' stop-opacity='1'/%3E%3C/linearGradient%3E%3C/defs%3E%3Crect x='0' y='0' fill='url(%23a)' width='2' height='1'/%3E%3Cg fill-opacity='0.5'%3E%3Cpolygon fill='url(%23b)' points='0 1 0 0 2 0'/%3E%3Cpolygon fill='url(%23c)' points='2 1 2 0 0 0'/%3E%3C/g%3E%3C/svg%3E")`;
101+
}

0 commit comments

Comments
 (0)