@principal-ade/code-quality-panels 0.1.0 → 0.1.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/components/QualityEmptyState.d.ts +22 -0
- package/dist/components/QualityEmptyState.d.ts.map +1 -0
- package/dist/components/QualityHexagon.d.ts +19 -1
- package/dist/components/QualityHexagon.d.ts.map +1 -1
- package/dist/components/QualityHexagon.stories.d.ts +1 -0
- package/dist/components/QualityHexagon.stories.d.ts.map +1 -1
- package/dist/components/RepositoryQualityGrid.d.ts +82 -0
- package/dist/components/RepositoryQualityGrid.d.ts.map +1 -0
- package/dist/components/RepositoryQualityGrid.stories.d.ts +45 -0
- package/dist/components/RepositoryQualityGrid.stories.d.ts.map +1 -0
- package/dist/components/index.d.ts +3 -1
- package/dist/components/index.d.ts.map +1 -1
- package/dist/index.d.ts +2 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/mocks/panelContext.d.ts.map +1 -1
- package/dist/panels/QualityHexagonPanel.d.ts.map +1 -1
- package/dist/panels/QualityHexagonPanel.stories.d.ts +10 -5
- package/dist/panels/QualityHexagonPanel.stories.d.ts.map +1 -1
- package/dist/panels/RepositoryQualityGridPanel.d.ts +8 -0
- package/dist/panels/RepositoryQualityGridPanel.d.ts.map +1 -0
- package/dist/panels/RepositoryQualityGridPanel.stories.d.ts +26 -0
- package/dist/panels/RepositoryQualityGridPanel.stories.d.ts.map +1 -0
- package/dist/panels.bundle.js +1308 -119
- package/dist/panels.bundle.js.map +1 -1
- package/package.json +1 -1
package/dist/panels.bundle.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { jsxs, jsx, Fragment } from "react/jsx-runtime";
|
|
2
|
-
import
|
|
2
|
+
import * as React2 from "react";
|
|
3
|
+
import React2__default, { forwardRef, createElement, createContext, useState, useEffect, useContext } from "react";
|
|
3
4
|
/**
|
|
4
5
|
* @license lucide-react v0.552.0 - ISC
|
|
5
6
|
*
|
|
@@ -105,7 +106,34 @@ const createLucideIcon = (iconName, iconNode) => {
|
|
|
105
106
|
* This source code is licensed under the ISC license.
|
|
106
107
|
* See the LICENSE file in the root directory of this source tree.
|
|
107
108
|
*/
|
|
108
|
-
const __iconNode = [
|
|
109
|
+
const __iconNode$4 = [["path", { d: "M20 6 9 17l-5-5", key: "1gmf2c" }]];
|
|
110
|
+
const Check = createLucideIcon("check", __iconNode$4);
|
|
111
|
+
/**
|
|
112
|
+
* @license lucide-react v0.552.0 - ISC
|
|
113
|
+
*
|
|
114
|
+
* This source code is licensed under the ISC license.
|
|
115
|
+
* See the LICENSE file in the root directory of this source tree.
|
|
116
|
+
*/
|
|
117
|
+
const __iconNode$3 = [["path", { d: "m9 18 6-6-6-6", key: "mthhwq" }]];
|
|
118
|
+
const ChevronRight = createLucideIcon("chevron-right", __iconNode$3);
|
|
119
|
+
/**
|
|
120
|
+
* @license lucide-react v0.552.0 - ISC
|
|
121
|
+
*
|
|
122
|
+
* This source code is licensed under the ISC license.
|
|
123
|
+
* See the LICENSE file in the root directory of this source tree.
|
|
124
|
+
*/
|
|
125
|
+
const __iconNode$2 = [
|
|
126
|
+
["rect", { width: "14", height: "14", x: "8", y: "8", rx: "2", ry: "2", key: "17jyea" }],
|
|
127
|
+
["path", { d: "M4 16c-1.1 0-2-.9-2-2V4c0-1.1.9-2 2-2h10c1.1 0 2 .9 2 2", key: "zix9uf" }]
|
|
128
|
+
];
|
|
129
|
+
const Copy = createLucideIcon("copy", __iconNode$2);
|
|
130
|
+
/**
|
|
131
|
+
* @license lucide-react v0.552.0 - ISC
|
|
132
|
+
*
|
|
133
|
+
* This source code is licensed under the ISC license.
|
|
134
|
+
* See the LICENSE file in the root directory of this source tree.
|
|
135
|
+
*/
|
|
136
|
+
const __iconNode$1 = [
|
|
109
137
|
[
|
|
110
138
|
"path",
|
|
111
139
|
{
|
|
@@ -114,7 +142,18 @@ const __iconNode = [
|
|
|
114
142
|
}
|
|
115
143
|
]
|
|
116
144
|
];
|
|
117
|
-
const Hexagon = createLucideIcon("hexagon", __iconNode);
|
|
145
|
+
const Hexagon = createLucideIcon("hexagon", __iconNode$1);
|
|
146
|
+
/**
|
|
147
|
+
* @license lucide-react v0.552.0 - ISC
|
|
148
|
+
*
|
|
149
|
+
* This source code is licensed under the ISC license.
|
|
150
|
+
* See the LICENSE file in the root directory of this source tree.
|
|
151
|
+
*/
|
|
152
|
+
const __iconNode = [
|
|
153
|
+
["path", { d: "M12 19h8", key: "baeox8" }],
|
|
154
|
+
["path", { d: "m4 17 6-6-6-6", key: "1yngyt" }]
|
|
155
|
+
];
|
|
156
|
+
const Terminal = createLucideIcon("terminal", __iconNode);
|
|
118
157
|
var terminalTheme = {
|
|
119
158
|
space: [0, 4, 8, 16, 32, 64, 128, 256, 512],
|
|
120
159
|
fonts: {
|
|
@@ -296,7 +335,7 @@ var ThemeProvider = ({
|
|
|
296
335
|
initialMode
|
|
297
336
|
}) => {
|
|
298
337
|
const [mode, setMode] = useState(initialMode);
|
|
299
|
-
const activeTheme =
|
|
338
|
+
const activeTheme = React2__default.useMemo(() => {
|
|
300
339
|
if (!mode || !customTheme.modes || !customTheme.modes[mode]) {
|
|
301
340
|
return customTheme;
|
|
302
341
|
}
|
|
@@ -325,7 +364,7 @@ var ThemeProvider = ({
|
|
|
325
364
|
mode,
|
|
326
365
|
setMode
|
|
327
366
|
};
|
|
328
|
-
return /* @__PURE__ */
|
|
367
|
+
return /* @__PURE__ */ React2__default.createElement(ThemeContextSingleton.Provider, {
|
|
329
368
|
value
|
|
330
369
|
}, children);
|
|
331
370
|
};
|
|
@@ -404,7 +443,10 @@ function QualityHexagon({
|
|
|
404
443
|
theme: theme2,
|
|
405
444
|
showLabels = false,
|
|
406
445
|
showValues = false,
|
|
407
|
-
className
|
|
446
|
+
className,
|
|
447
|
+
onVertexHover,
|
|
448
|
+
onVertexLeave,
|
|
449
|
+
onVertexClick
|
|
408
450
|
}) {
|
|
409
451
|
const themeColors = getThemeColors(theme2);
|
|
410
452
|
const colors = themeColors.tierColors[tier] ?? themeColors.tierColors.none;
|
|
@@ -484,38 +526,71 @@ function QualityHexagon({
|
|
|
484
526
|
style: { transition: "all 0.5s ease" }
|
|
485
527
|
}
|
|
486
528
|
),
|
|
487
|
-
metricConfig.map(({ key, angle }) => {
|
|
488
|
-
|
|
529
|
+
metricConfig.map(({ key, label, color, angle }) => {
|
|
530
|
+
const rawValue = metrics[key];
|
|
531
|
+
let value = rawValue;
|
|
489
532
|
if (key === "deadCode") {
|
|
490
533
|
value = 100 - value;
|
|
491
534
|
}
|
|
492
535
|
const point = calculateMetricPoint(center, radius, angle, 100);
|
|
493
536
|
const dataPoint = calculateMetricPoint(center, radius, angle, value);
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
)
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
537
|
+
const vertexInfo = {
|
|
538
|
+
key,
|
|
539
|
+
label,
|
|
540
|
+
value: rawValue,
|
|
541
|
+
color
|
|
542
|
+
};
|
|
543
|
+
const handleMouseEnter = () => {
|
|
544
|
+
onVertexHover == null ? void 0 : onVertexHover(vertexInfo);
|
|
545
|
+
};
|
|
546
|
+
const handleClick = (e) => {
|
|
547
|
+
e.stopPropagation();
|
|
548
|
+
onVertexClick == null ? void 0 : onVertexClick(vertexInfo);
|
|
549
|
+
};
|
|
550
|
+
return /* @__PURE__ */ jsxs(
|
|
551
|
+
"g",
|
|
552
|
+
{
|
|
553
|
+
onMouseEnter: handleMouseEnter,
|
|
554
|
+
onMouseLeave: onVertexLeave,
|
|
555
|
+
onClick: handleClick,
|
|
556
|
+
style: { cursor: onVertexHover || onVertexClick ? "pointer" : "default" },
|
|
557
|
+
children: [
|
|
558
|
+
/* @__PURE__ */ jsx(
|
|
559
|
+
"circle",
|
|
560
|
+
{
|
|
561
|
+
cx: point.x,
|
|
562
|
+
cy: point.y,
|
|
563
|
+
r: dotSize * 2.5,
|
|
564
|
+
fill: "transparent"
|
|
565
|
+
}
|
|
566
|
+
),
|
|
567
|
+
/* @__PURE__ */ jsx(
|
|
568
|
+
"circle",
|
|
569
|
+
{
|
|
570
|
+
cx: point.x,
|
|
571
|
+
cy: point.y,
|
|
572
|
+
r: dotSize,
|
|
573
|
+
fill: "white",
|
|
574
|
+
stroke: colors.stroke,
|
|
575
|
+
strokeWidth: 1.5
|
|
576
|
+
}
|
|
577
|
+
),
|
|
578
|
+
/* @__PURE__ */ jsx(
|
|
579
|
+
"circle",
|
|
580
|
+
{
|
|
581
|
+
cx: dataPoint.x,
|
|
582
|
+
cy: dataPoint.y,
|
|
583
|
+
r: dotSize * 0.7,
|
|
584
|
+
fill: colors.fill,
|
|
585
|
+
stroke: colors.stroke,
|
|
586
|
+
strokeWidth: 1,
|
|
587
|
+
style: { opacity: 0.9 }
|
|
588
|
+
}
|
|
589
|
+
)
|
|
590
|
+
]
|
|
591
|
+
},
|
|
592
|
+
key
|
|
593
|
+
);
|
|
519
594
|
}),
|
|
520
595
|
/* @__PURE__ */ jsx(
|
|
521
596
|
"text",
|
|
@@ -726,6 +801,202 @@ function QualityHexagonDetailed({
|
|
|
726
801
|
}
|
|
727
802
|
);
|
|
728
803
|
}
|
|
804
|
+
function QualityHexagonExpandable({
|
|
805
|
+
metrics,
|
|
806
|
+
tier,
|
|
807
|
+
theme: theme2,
|
|
808
|
+
className,
|
|
809
|
+
packageName,
|
|
810
|
+
packageVersion,
|
|
811
|
+
onRefresh,
|
|
812
|
+
isRefreshing = false,
|
|
813
|
+
defaultExpanded = false
|
|
814
|
+
}) {
|
|
815
|
+
const [expanded, setExpanded] = React2.useState(defaultExpanded);
|
|
816
|
+
const themeColors = getThemeColors(theme2);
|
|
817
|
+
const colors = themeColors.tierColors[tier] ?? themeColors.tierColors.none;
|
|
818
|
+
const metricConfig = getMetricConfig(themeColors);
|
|
819
|
+
const hasHeader = packageName || onRefresh;
|
|
820
|
+
return /* @__PURE__ */ jsxs(
|
|
821
|
+
"div",
|
|
822
|
+
{
|
|
823
|
+
className: cn(className),
|
|
824
|
+
style: {
|
|
825
|
+
display: "flex",
|
|
826
|
+
flexDirection: "column",
|
|
827
|
+
gap: 12,
|
|
828
|
+
padding: 16,
|
|
829
|
+
borderRadius: 8,
|
|
830
|
+
backgroundColor: colors.bg,
|
|
831
|
+
flex: "1 1 200px"
|
|
832
|
+
},
|
|
833
|
+
children: [
|
|
834
|
+
hasHeader && /* @__PURE__ */ jsxs("div", { style: {
|
|
835
|
+
display: "flex",
|
|
836
|
+
alignItems: "center",
|
|
837
|
+
justifyContent: "space-between",
|
|
838
|
+
gap: 12
|
|
839
|
+
}, children: [
|
|
840
|
+
packageName ? /* @__PURE__ */ jsxs("div", { style: { display: "flex", flexDirection: "column", gap: 2 }, children: [
|
|
841
|
+
packageName.startsWith("@") && packageName.includes("/") ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
842
|
+
/* @__PURE__ */ jsx("span", { style: {
|
|
843
|
+
fontSize: 12,
|
|
844
|
+
color: theme2.colors.textMuted
|
|
845
|
+
}, children: packageName.split("/")[0] }),
|
|
846
|
+
/* @__PURE__ */ jsx("span", { style: {
|
|
847
|
+
fontSize: 14,
|
|
848
|
+
fontWeight: 500,
|
|
849
|
+
color: colors.stroke
|
|
850
|
+
}, children: packageName.split("/")[1] })
|
|
851
|
+
] }) : /* @__PURE__ */ jsx("span", { style: {
|
|
852
|
+
fontSize: 14,
|
|
853
|
+
fontWeight: 500,
|
|
854
|
+
color: colors.stroke
|
|
855
|
+
}, children: packageName }),
|
|
856
|
+
packageVersion && /* @__PURE__ */ jsxs("span", { style: {
|
|
857
|
+
fontSize: 12,
|
|
858
|
+
color: theme2.colors.textMuted
|
|
859
|
+
}, children: [
|
|
860
|
+
"v",
|
|
861
|
+
packageVersion
|
|
862
|
+
] })
|
|
863
|
+
] }) : /* @__PURE__ */ jsx("span", {}),
|
|
864
|
+
onRefresh && /* @__PURE__ */ jsx(
|
|
865
|
+
"button",
|
|
866
|
+
{
|
|
867
|
+
onClick: onRefresh,
|
|
868
|
+
disabled: isRefreshing,
|
|
869
|
+
style: {
|
|
870
|
+
padding: 6,
|
|
871
|
+
display: "flex",
|
|
872
|
+
alignItems: "center",
|
|
873
|
+
justifyContent: "center",
|
|
874
|
+
border: `1px solid ${theme2.colors.border}`,
|
|
875
|
+
borderRadius: 4,
|
|
876
|
+
background: theme2.colors.surface,
|
|
877
|
+
color: theme2.colors.textMuted,
|
|
878
|
+
cursor: isRefreshing ? "not-allowed" : "pointer",
|
|
879
|
+
opacity: isRefreshing ? 0.6 : 1
|
|
880
|
+
},
|
|
881
|
+
title: "Refresh",
|
|
882
|
+
children: /* @__PURE__ */ jsxs(
|
|
883
|
+
"svg",
|
|
884
|
+
{
|
|
885
|
+
width: "14",
|
|
886
|
+
height: "14",
|
|
887
|
+
viewBox: "0 0 24 24",
|
|
888
|
+
fill: "none",
|
|
889
|
+
stroke: "currentColor",
|
|
890
|
+
strokeWidth: "2",
|
|
891
|
+
strokeLinecap: "round",
|
|
892
|
+
strokeLinejoin: "round",
|
|
893
|
+
style: {
|
|
894
|
+
animation: isRefreshing ? "spin 1s linear infinite" : "none"
|
|
895
|
+
},
|
|
896
|
+
children: [
|
|
897
|
+
/* @__PURE__ */ jsx("path", { d: "M21 12a9 9 0 0 0-9-9 9.75 9.75 0 0 0-6.74 2.74L3 8" }),
|
|
898
|
+
/* @__PURE__ */ jsx("path", { d: "M3 3v5h5" }),
|
|
899
|
+
/* @__PURE__ */ jsx("path", { d: "M3 12a9 9 0 0 0 9 9 9.75 9.75 0 0 0 6.74-2.74L21 16" }),
|
|
900
|
+
/* @__PURE__ */ jsx("path", { d: "M16 16h5v5" })
|
|
901
|
+
]
|
|
902
|
+
}
|
|
903
|
+
)
|
|
904
|
+
}
|
|
905
|
+
)
|
|
906
|
+
] }),
|
|
907
|
+
/* @__PURE__ */ jsx(
|
|
908
|
+
"div",
|
|
909
|
+
{
|
|
910
|
+
onClick: () => setExpanded(!expanded),
|
|
911
|
+
style: {
|
|
912
|
+
cursor: "pointer",
|
|
913
|
+
display: "flex",
|
|
914
|
+
justifyContent: "center",
|
|
915
|
+
alignItems: "center"
|
|
916
|
+
},
|
|
917
|
+
children: /* @__PURE__ */ jsx("div", { style: { width: 200, height: 200 }, children: /* @__PURE__ */ jsx(
|
|
918
|
+
QualityHexagon,
|
|
919
|
+
{
|
|
920
|
+
metrics,
|
|
921
|
+
tier,
|
|
922
|
+
theme: theme2,
|
|
923
|
+
showLabels: true,
|
|
924
|
+
showValues: false
|
|
925
|
+
}
|
|
926
|
+
) })
|
|
927
|
+
}
|
|
928
|
+
),
|
|
929
|
+
/* @__PURE__ */ jsx(
|
|
930
|
+
"div",
|
|
931
|
+
{
|
|
932
|
+
style: {
|
|
933
|
+
display: "grid",
|
|
934
|
+
gridTemplateRows: expanded ? "1fr" : "0fr",
|
|
935
|
+
transition: "grid-template-rows 0.3s ease"
|
|
936
|
+
},
|
|
937
|
+
children: /* @__PURE__ */ jsx("div", { style: { overflow: "hidden" }, children: /* @__PURE__ */ jsx("div", { style: {
|
|
938
|
+
display: "flex",
|
|
939
|
+
flexDirection: "column",
|
|
940
|
+
gap: 8,
|
|
941
|
+
padding: "8px 24px",
|
|
942
|
+
borderTop: `1px solid ${theme2.colors.border}`,
|
|
943
|
+
marginTop: 8
|
|
944
|
+
}, children: metricConfig.map(({ key, label, color }) => {
|
|
945
|
+
const value = metrics[key];
|
|
946
|
+
return /* @__PURE__ */ jsxs("div", { style: { display: "flex", alignItems: "center", justifyContent: "space-between", gap: 12 }, children: [
|
|
947
|
+
/* @__PURE__ */ jsxs("span", { style: {
|
|
948
|
+
fontSize: 14,
|
|
949
|
+
color: theme2.colors.textMuted
|
|
950
|
+
}, children: [
|
|
951
|
+
label,
|
|
952
|
+
key === "deadCode" ? " ↓" : ""
|
|
953
|
+
] }),
|
|
954
|
+
/* @__PURE__ */ jsxs("span", { style: {
|
|
955
|
+
fontSize: 14,
|
|
956
|
+
fontWeight: 500,
|
|
957
|
+
color
|
|
958
|
+
}, children: [
|
|
959
|
+
value,
|
|
960
|
+
"%"
|
|
961
|
+
] })
|
|
962
|
+
] }, key);
|
|
963
|
+
}) }) })
|
|
964
|
+
}
|
|
965
|
+
),
|
|
966
|
+
/* @__PURE__ */ jsx(
|
|
967
|
+
"div",
|
|
968
|
+
{
|
|
969
|
+
onClick: () => setExpanded(!expanded),
|
|
970
|
+
style: {
|
|
971
|
+
display: "flex",
|
|
972
|
+
justifyContent: "center",
|
|
973
|
+
cursor: "pointer",
|
|
974
|
+
padding: 4
|
|
975
|
+
},
|
|
976
|
+
children: /* @__PURE__ */ jsx(
|
|
977
|
+
"svg",
|
|
978
|
+
{
|
|
979
|
+
width: "16",
|
|
980
|
+
height: "16",
|
|
981
|
+
viewBox: "0 0 24 24",
|
|
982
|
+
fill: "none",
|
|
983
|
+
stroke: theme2.colors.textMuted,
|
|
984
|
+
strokeWidth: "2",
|
|
985
|
+
strokeLinecap: "round",
|
|
986
|
+
strokeLinejoin: "round",
|
|
987
|
+
style: {
|
|
988
|
+
transform: expanded ? "rotate(180deg)" : "rotate(0deg)",
|
|
989
|
+
transition: "transform 0.3s ease"
|
|
990
|
+
},
|
|
991
|
+
children: /* @__PURE__ */ jsx("path", { d: "m6 9 6 6 6-6" })
|
|
992
|
+
}
|
|
993
|
+
)
|
|
994
|
+
}
|
|
995
|
+
)
|
|
996
|
+
]
|
|
997
|
+
}
|
|
998
|
+
);
|
|
999
|
+
}
|
|
729
1000
|
function calculateQualityTier(metrics) {
|
|
730
1001
|
const metricsForAverage = { ...metrics };
|
|
731
1002
|
metricsForAverage.deadCode = 100 - metricsForAverage.deadCode;
|
|
@@ -736,6 +1007,322 @@ function calculateQualityTier(metrics) {
|
|
|
736
1007
|
if (average >= 40) return "bronze";
|
|
737
1008
|
return "none";
|
|
738
1009
|
}
|
|
1010
|
+
const WORKFLOW_FILE_PATH = ".github/workflows/quality-lens.yml";
|
|
1011
|
+
function checkFileExistsInTree(treeData, targetPath) {
|
|
1012
|
+
if (!(treeData == null ? void 0 : treeData.allFiles)) return false;
|
|
1013
|
+
const normalizedTarget = targetPath.replace(/^\//, "").toLowerCase();
|
|
1014
|
+
return treeData.allFiles.some((file) => {
|
|
1015
|
+
const filePath = (file.relativePath || file.path || "").toLowerCase();
|
|
1016
|
+
return filePath.endsWith(normalizedTarget) || filePath === normalizedTarget;
|
|
1017
|
+
});
|
|
1018
|
+
}
|
|
1019
|
+
const CommandLine = ({ command, theme: theme2 }) => {
|
|
1020
|
+
const [copied, setCopied] = React2__default.useState(false);
|
|
1021
|
+
const handleCopy = async () => {
|
|
1022
|
+
try {
|
|
1023
|
+
await navigator.clipboard.writeText(command);
|
|
1024
|
+
setCopied(true);
|
|
1025
|
+
setTimeout(() => setCopied(false), 2e3);
|
|
1026
|
+
} catch {
|
|
1027
|
+
console.log("Copy:", command);
|
|
1028
|
+
}
|
|
1029
|
+
};
|
|
1030
|
+
return /* @__PURE__ */ jsxs(
|
|
1031
|
+
"div",
|
|
1032
|
+
{
|
|
1033
|
+
style: {
|
|
1034
|
+
display: "flex",
|
|
1035
|
+
alignItems: "center",
|
|
1036
|
+
justifyContent: "space-between",
|
|
1037
|
+
gap: 12,
|
|
1038
|
+
padding: "10px 14px",
|
|
1039
|
+
borderRadius: 6,
|
|
1040
|
+
backgroundColor: theme2.colors.background,
|
|
1041
|
+
border: `1px solid ${theme2.colors.border}`,
|
|
1042
|
+
fontFamily: "monospace",
|
|
1043
|
+
fontSize: 13
|
|
1044
|
+
},
|
|
1045
|
+
children: [
|
|
1046
|
+
/* @__PURE__ */ jsx("code", { style: { color: theme2.colors.text }, children: command }),
|
|
1047
|
+
/* @__PURE__ */ jsx(
|
|
1048
|
+
"button",
|
|
1049
|
+
{
|
|
1050
|
+
onClick: handleCopy,
|
|
1051
|
+
style: {
|
|
1052
|
+
display: "flex",
|
|
1053
|
+
alignItems: "center",
|
|
1054
|
+
justifyContent: "center",
|
|
1055
|
+
padding: 4,
|
|
1056
|
+
border: "none",
|
|
1057
|
+
backgroundColor: "transparent",
|
|
1058
|
+
color: theme2.colors.textMuted,
|
|
1059
|
+
cursor: "pointer"
|
|
1060
|
+
},
|
|
1061
|
+
title: "Copy command",
|
|
1062
|
+
children: copied ? /* @__PURE__ */ jsx(Check, { size: 16, color: theme2.colors.success }) : /* @__PURE__ */ jsx(Copy, { size: 16 })
|
|
1063
|
+
}
|
|
1064
|
+
)
|
|
1065
|
+
]
|
|
1066
|
+
}
|
|
1067
|
+
);
|
|
1068
|
+
};
|
|
1069
|
+
const QualityEmptyState = ({
|
|
1070
|
+
theme: theme2,
|
|
1071
|
+
hasWorkflow
|
|
1072
|
+
}) => {
|
|
1073
|
+
if (hasWorkflow) {
|
|
1074
|
+
return /* @__PURE__ */ jsxs(
|
|
1075
|
+
"div",
|
|
1076
|
+
{
|
|
1077
|
+
style: {
|
|
1078
|
+
display: "flex",
|
|
1079
|
+
flexDirection: "column",
|
|
1080
|
+
padding: "16px 0",
|
|
1081
|
+
gap: 16,
|
|
1082
|
+
width: "100%"
|
|
1083
|
+
},
|
|
1084
|
+
children: [
|
|
1085
|
+
/* @__PURE__ */ jsx(
|
|
1086
|
+
"p",
|
|
1087
|
+
{
|
|
1088
|
+
style: {
|
|
1089
|
+
margin: 0,
|
|
1090
|
+
fontSize: 14,
|
|
1091
|
+
color: theme2.colors.textMuted,
|
|
1092
|
+
lineHeight: 1.5
|
|
1093
|
+
},
|
|
1094
|
+
children: "Quality metrics will appear here after your next CI run completes."
|
|
1095
|
+
}
|
|
1096
|
+
),
|
|
1097
|
+
/* @__PURE__ */ jsxs(
|
|
1098
|
+
"div",
|
|
1099
|
+
{
|
|
1100
|
+
style: {
|
|
1101
|
+
display: "flex",
|
|
1102
|
+
alignItems: "center",
|
|
1103
|
+
gap: 8,
|
|
1104
|
+
padding: "10px 14px",
|
|
1105
|
+
borderRadius: 6,
|
|
1106
|
+
backgroundColor: `${theme2.colors.success}15`,
|
|
1107
|
+
color: theme2.colors.success,
|
|
1108
|
+
fontSize: 13
|
|
1109
|
+
},
|
|
1110
|
+
children: [
|
|
1111
|
+
/* @__PURE__ */ jsx(Check, { size: 16 }),
|
|
1112
|
+
/* @__PURE__ */ jsxs("span", { children: [
|
|
1113
|
+
"Workflow detected at ",
|
|
1114
|
+
WORKFLOW_FILE_PATH
|
|
1115
|
+
] })
|
|
1116
|
+
]
|
|
1117
|
+
}
|
|
1118
|
+
)
|
|
1119
|
+
]
|
|
1120
|
+
}
|
|
1121
|
+
);
|
|
1122
|
+
}
|
|
1123
|
+
return /* @__PURE__ */ jsxs(
|
|
1124
|
+
"div",
|
|
1125
|
+
{
|
|
1126
|
+
style: {
|
|
1127
|
+
display: "flex",
|
|
1128
|
+
flexDirection: "column",
|
|
1129
|
+
padding: "16px 0",
|
|
1130
|
+
gap: 16,
|
|
1131
|
+
width: "100%"
|
|
1132
|
+
},
|
|
1133
|
+
children: [
|
|
1134
|
+
/* @__PURE__ */ jsx(
|
|
1135
|
+
"p",
|
|
1136
|
+
{
|
|
1137
|
+
style: {
|
|
1138
|
+
margin: 0,
|
|
1139
|
+
fontSize: 14,
|
|
1140
|
+
color: theme2.colors.textMuted,
|
|
1141
|
+
lineHeight: 1.5
|
|
1142
|
+
},
|
|
1143
|
+
children: "Track your code quality with automated analysis of tests, linting, types, formatting, dead code, and documentation."
|
|
1144
|
+
}
|
|
1145
|
+
),
|
|
1146
|
+
/* @__PURE__ */ jsxs(
|
|
1147
|
+
"div",
|
|
1148
|
+
{
|
|
1149
|
+
style: {
|
|
1150
|
+
display: "flex",
|
|
1151
|
+
flexDirection: "column",
|
|
1152
|
+
gap: 16,
|
|
1153
|
+
padding: 20,
|
|
1154
|
+
borderRadius: 8,
|
|
1155
|
+
backgroundColor: theme2.colors.surface,
|
|
1156
|
+
border: `1px solid ${theme2.colors.border}`
|
|
1157
|
+
},
|
|
1158
|
+
children: [
|
|
1159
|
+
/* @__PURE__ */ jsxs(
|
|
1160
|
+
"div",
|
|
1161
|
+
{
|
|
1162
|
+
style: {
|
|
1163
|
+
display: "flex",
|
|
1164
|
+
alignItems: "center",
|
|
1165
|
+
gap: 10,
|
|
1166
|
+
marginBottom: 4
|
|
1167
|
+
},
|
|
1168
|
+
children: [
|
|
1169
|
+
/* @__PURE__ */ jsx(Terminal, { size: 20, color: theme2.colors.text }),
|
|
1170
|
+
/* @__PURE__ */ jsx(
|
|
1171
|
+
"h4",
|
|
1172
|
+
{
|
|
1173
|
+
style: {
|
|
1174
|
+
margin: 0,
|
|
1175
|
+
fontSize: 15,
|
|
1176
|
+
fontWeight: 600,
|
|
1177
|
+
color: theme2.colors.text
|
|
1178
|
+
},
|
|
1179
|
+
children: "Get Started"
|
|
1180
|
+
}
|
|
1181
|
+
)
|
|
1182
|
+
]
|
|
1183
|
+
}
|
|
1184
|
+
),
|
|
1185
|
+
/* @__PURE__ */ jsxs("div", { children: [
|
|
1186
|
+
/* @__PURE__ */ jsxs(
|
|
1187
|
+
"div",
|
|
1188
|
+
{
|
|
1189
|
+
style: {
|
|
1190
|
+
display: "flex",
|
|
1191
|
+
alignItems: "center",
|
|
1192
|
+
gap: 8,
|
|
1193
|
+
marginBottom: 8,
|
|
1194
|
+
fontSize: 13,
|
|
1195
|
+
color: theme2.colors.textMuted
|
|
1196
|
+
},
|
|
1197
|
+
children: [
|
|
1198
|
+
/* @__PURE__ */ jsx(
|
|
1199
|
+
"span",
|
|
1200
|
+
{
|
|
1201
|
+
style: {
|
|
1202
|
+
display: "flex",
|
|
1203
|
+
alignItems: "center",
|
|
1204
|
+
justifyContent: "center",
|
|
1205
|
+
width: 20,
|
|
1206
|
+
height: 20,
|
|
1207
|
+
borderRadius: "50%",
|
|
1208
|
+
backgroundColor: theme2.colors.primary,
|
|
1209
|
+
color: theme2.colors.background,
|
|
1210
|
+
fontSize: 11,
|
|
1211
|
+
fontWeight: 600
|
|
1212
|
+
},
|
|
1213
|
+
children: "1"
|
|
1214
|
+
}
|
|
1215
|
+
),
|
|
1216
|
+
/* @__PURE__ */ jsx("span", { children: "Install the CLI" })
|
|
1217
|
+
]
|
|
1218
|
+
}
|
|
1219
|
+
),
|
|
1220
|
+
/* @__PURE__ */ jsx(
|
|
1221
|
+
CommandLine,
|
|
1222
|
+
{
|
|
1223
|
+
command: "npm install -g @principal-ai/quality-lens-cli",
|
|
1224
|
+
theme: theme2
|
|
1225
|
+
}
|
|
1226
|
+
)
|
|
1227
|
+
] }),
|
|
1228
|
+
/* @__PURE__ */ jsxs("div", { children: [
|
|
1229
|
+
/* @__PURE__ */ jsxs(
|
|
1230
|
+
"div",
|
|
1231
|
+
{
|
|
1232
|
+
style: {
|
|
1233
|
+
display: "flex",
|
|
1234
|
+
alignItems: "center",
|
|
1235
|
+
gap: 8,
|
|
1236
|
+
marginBottom: 8,
|
|
1237
|
+
fontSize: 13,
|
|
1238
|
+
color: theme2.colors.textMuted
|
|
1239
|
+
},
|
|
1240
|
+
children: [
|
|
1241
|
+
/* @__PURE__ */ jsx(
|
|
1242
|
+
"span",
|
|
1243
|
+
{
|
|
1244
|
+
style: {
|
|
1245
|
+
display: "flex",
|
|
1246
|
+
alignItems: "center",
|
|
1247
|
+
justifyContent: "center",
|
|
1248
|
+
width: 20,
|
|
1249
|
+
height: 20,
|
|
1250
|
+
borderRadius: "50%",
|
|
1251
|
+
backgroundColor: theme2.colors.primary,
|
|
1252
|
+
color: theme2.colors.background,
|
|
1253
|
+
fontSize: 11,
|
|
1254
|
+
fontWeight: 600
|
|
1255
|
+
},
|
|
1256
|
+
children: "2"
|
|
1257
|
+
}
|
|
1258
|
+
),
|
|
1259
|
+
/* @__PURE__ */ jsx("span", { children: "Check what quality tools are available" })
|
|
1260
|
+
]
|
|
1261
|
+
}
|
|
1262
|
+
),
|
|
1263
|
+
/* @__PURE__ */ jsx(CommandLine, { command: "quality-lens list", theme: theme2 })
|
|
1264
|
+
] }),
|
|
1265
|
+
/* @__PURE__ */ jsxs("div", { children: [
|
|
1266
|
+
/* @__PURE__ */ jsxs(
|
|
1267
|
+
"div",
|
|
1268
|
+
{
|
|
1269
|
+
style: {
|
|
1270
|
+
display: "flex",
|
|
1271
|
+
alignItems: "center",
|
|
1272
|
+
gap: 8,
|
|
1273
|
+
marginBottom: 8,
|
|
1274
|
+
fontSize: 13,
|
|
1275
|
+
color: theme2.colors.textMuted
|
|
1276
|
+
},
|
|
1277
|
+
children: [
|
|
1278
|
+
/* @__PURE__ */ jsx(
|
|
1279
|
+
"span",
|
|
1280
|
+
{
|
|
1281
|
+
style: {
|
|
1282
|
+
display: "flex",
|
|
1283
|
+
alignItems: "center",
|
|
1284
|
+
justifyContent: "center",
|
|
1285
|
+
width: 20,
|
|
1286
|
+
height: 20,
|
|
1287
|
+
borderRadius: "50%",
|
|
1288
|
+
backgroundColor: theme2.colors.primary,
|
|
1289
|
+
color: theme2.colors.background,
|
|
1290
|
+
fontSize: 11,
|
|
1291
|
+
fontWeight: 600
|
|
1292
|
+
},
|
|
1293
|
+
children: "3"
|
|
1294
|
+
}
|
|
1295
|
+
),
|
|
1296
|
+
/* @__PURE__ */ jsx("span", { children: "Set up the GitHub Action" })
|
|
1297
|
+
]
|
|
1298
|
+
}
|
|
1299
|
+
),
|
|
1300
|
+
/* @__PURE__ */ jsx(CommandLine, { command: "quality-lens init", theme: theme2 })
|
|
1301
|
+
] }),
|
|
1302
|
+
/* @__PURE__ */ jsxs(
|
|
1303
|
+
"div",
|
|
1304
|
+
{
|
|
1305
|
+
style: {
|
|
1306
|
+
display: "flex",
|
|
1307
|
+
alignItems: "center",
|
|
1308
|
+
gap: 6,
|
|
1309
|
+
paddingTop: 8,
|
|
1310
|
+
fontSize: 13,
|
|
1311
|
+
color: theme2.colors.textMuted
|
|
1312
|
+
},
|
|
1313
|
+
children: [
|
|
1314
|
+
/* @__PURE__ */ jsx(ChevronRight, { size: 14 }),
|
|
1315
|
+
/* @__PURE__ */ jsx("span", { children: "Then commit and push to start tracking quality" })
|
|
1316
|
+
]
|
|
1317
|
+
}
|
|
1318
|
+
)
|
|
1319
|
+
]
|
|
1320
|
+
}
|
|
1321
|
+
)
|
|
1322
|
+
]
|
|
1323
|
+
}
|
|
1324
|
+
);
|
|
1325
|
+
};
|
|
739
1326
|
const mockPackages = [
|
|
740
1327
|
{
|
|
741
1328
|
name: "@principal-ade/code-quality-panels",
|
|
@@ -756,11 +1343,15 @@ const QualityHexagonPanelContent = ({
|
|
|
756
1343
|
}) => {
|
|
757
1344
|
var _a;
|
|
758
1345
|
const { theme: theme2 } = useTheme();
|
|
759
|
-
const [refreshingPackages, setRefreshingPackages] =
|
|
1346
|
+
const [refreshingPackages, setRefreshingPackages] = React2__default.useState(/* @__PURE__ */ new Set());
|
|
760
1347
|
const qualitySlice = context.getSlice("quality");
|
|
761
1348
|
const hasQualitySlice = context.hasSlice("quality");
|
|
762
1349
|
const isLoading = (qualitySlice == null ? void 0 : qualitySlice.loading) ?? false;
|
|
763
|
-
const
|
|
1350
|
+
const fileTreeSlice = context.getSlice("fileTree");
|
|
1351
|
+
const hasWorkflow = React2__default.useMemo(() => {
|
|
1352
|
+
return checkFileExistsInTree((fileTreeSlice == null ? void 0 : fileTreeSlice.data) ?? void 0, WORKFLOW_FILE_PATH);
|
|
1353
|
+
}, [fileTreeSlice == null ? void 0 : fileTreeSlice.data]);
|
|
1354
|
+
const packages = React2__default.useMemo(() => {
|
|
764
1355
|
var _a2;
|
|
765
1356
|
if ((_a2 = qualitySlice == null ? void 0 : qualitySlice.data) == null ? void 0 : _a2.packages) {
|
|
766
1357
|
return qualitySlice.data.packages;
|
|
@@ -770,20 +1361,6 @@ const QualityHexagonPanelContent = ({
|
|
|
770
1361
|
}
|
|
771
1362
|
return mockPackages;
|
|
772
1363
|
}, [(_a = qualitySlice == null ? void 0 : qualitySlice.data) == null ? void 0 : _a.packages, hasQualitySlice]);
|
|
773
|
-
const handleRefreshPackage = async (packageName) => {
|
|
774
|
-
setRefreshingPackages((prev) => new Set(prev).add(packageName));
|
|
775
|
-
try {
|
|
776
|
-
if (context.hasSlice("quality")) {
|
|
777
|
-
await context.refresh("repository", "quality");
|
|
778
|
-
}
|
|
779
|
-
} finally {
|
|
780
|
-
setRefreshingPackages((prev) => {
|
|
781
|
-
const next = new Set(prev);
|
|
782
|
-
next.delete(packageName);
|
|
783
|
-
return next;
|
|
784
|
-
});
|
|
785
|
-
}
|
|
786
|
-
};
|
|
787
1364
|
const handleRefreshAll = async () => {
|
|
788
1365
|
const allNames = packages.map((p) => p.name);
|
|
789
1366
|
setRefreshingPackages(new Set(allNames));
|
|
@@ -795,7 +1372,7 @@ const QualityHexagonPanelContent = ({
|
|
|
795
1372
|
setRefreshingPackages(/* @__PURE__ */ new Set());
|
|
796
1373
|
}
|
|
797
1374
|
};
|
|
798
|
-
|
|
1375
|
+
React2__default.useEffect(() => {
|
|
799
1376
|
const unsubscribers = [
|
|
800
1377
|
events.on("principal-ade.quality-panel:refresh", async () => {
|
|
801
1378
|
await handleRefreshAll();
|
|
@@ -820,93 +1397,679 @@ const QualityHexagonPanelContent = ({
|
|
|
820
1397
|
documentation: acc.documentation + pkg.metrics.documentation / packages.length
|
|
821
1398
|
}), { tests: 0, deadCode: 0, linting: 0, formatting: 0, types: 0, documentation: 0 })
|
|
822
1399
|
) : "none";
|
|
823
|
-
return /* @__PURE__ */
|
|
1400
|
+
return /* @__PURE__ */ jsx(
|
|
824
1401
|
"div",
|
|
825
1402
|
{
|
|
826
1403
|
style: {
|
|
827
|
-
padding: 20,
|
|
828
1404
|
fontFamily: theme2.fonts.body,
|
|
829
1405
|
height: "100%",
|
|
830
|
-
|
|
831
|
-
flexDirection: "column",
|
|
832
|
-
gap: 16,
|
|
1406
|
+
minHeight: 0,
|
|
833
1407
|
backgroundColor: theme2.colors.background,
|
|
834
1408
|
color: theme2.colors.text,
|
|
835
1409
|
overflowY: "auto",
|
|
836
1410
|
boxSizing: "border-box"
|
|
837
1411
|
},
|
|
1412
|
+
children: /* @__PURE__ */ jsxs(
|
|
1413
|
+
"div",
|
|
1414
|
+
{
|
|
1415
|
+
style: {
|
|
1416
|
+
padding: 20,
|
|
1417
|
+
display: "flex",
|
|
1418
|
+
flexDirection: "column",
|
|
1419
|
+
gap: 16
|
|
1420
|
+
},
|
|
1421
|
+
children: [
|
|
1422
|
+
/* @__PURE__ */ jsxs("div", { style: { display: "flex", alignItems: "center", gap: 12 }, children: [
|
|
1423
|
+
/* @__PURE__ */ jsx(Hexagon, { size: 24, color: tierColors[overallTier] }),
|
|
1424
|
+
/* @__PURE__ */ jsx(
|
|
1425
|
+
"h2",
|
|
1426
|
+
{
|
|
1427
|
+
style: {
|
|
1428
|
+
margin: 0,
|
|
1429
|
+
fontSize: 20,
|
|
1430
|
+
fontWeight: 600,
|
|
1431
|
+
color: theme2.colors.text
|
|
1432
|
+
},
|
|
1433
|
+
children: "Code Quality"
|
|
1434
|
+
}
|
|
1435
|
+
),
|
|
1436
|
+
/* @__PURE__ */ jsx(
|
|
1437
|
+
"span",
|
|
1438
|
+
{
|
|
1439
|
+
title: "Platinum: 90%+ avg | Gold: 75%+ | Silver: 60%+ | Bronze: 40%+",
|
|
1440
|
+
style: {
|
|
1441
|
+
display: "inline-flex",
|
|
1442
|
+
alignItems: "center",
|
|
1443
|
+
justifyContent: "center",
|
|
1444
|
+
width: 18,
|
|
1445
|
+
height: 18,
|
|
1446
|
+
borderRadius: "50%",
|
|
1447
|
+
border: `1px solid ${theme2.colors.border}`,
|
|
1448
|
+
fontSize: 12,
|
|
1449
|
+
color: theme2.colors.textMuted,
|
|
1450
|
+
cursor: "help"
|
|
1451
|
+
},
|
|
1452
|
+
children: "?"
|
|
1453
|
+
}
|
|
1454
|
+
),
|
|
1455
|
+
packages.length > 1 && /* @__PURE__ */ jsxs("span", { style: {
|
|
1456
|
+
fontSize: 14,
|
|
1457
|
+
color: theme2.colors.textMuted
|
|
1458
|
+
}, children: [
|
|
1459
|
+
packages.length,
|
|
1460
|
+
" packages"
|
|
1461
|
+
] })
|
|
1462
|
+
] }),
|
|
1463
|
+
/* @__PURE__ */ jsx("div", { style: { display: "flex", flexWrap: "wrap", gap: 16, minHeight: 0 }, children: isLoading ? /* @__PURE__ */ jsx("div", { style: {
|
|
1464
|
+
padding: 40,
|
|
1465
|
+
textAlign: "center",
|
|
1466
|
+
color: theme2.colors.textMuted
|
|
1467
|
+
}, children: "Loading quality metrics..." }) : packages.length === 0 ? /* @__PURE__ */ jsx(
|
|
1468
|
+
QualityEmptyState,
|
|
1469
|
+
{
|
|
1470
|
+
theme: theme2,
|
|
1471
|
+
hasWorkflow
|
|
1472
|
+
}
|
|
1473
|
+
) : packages.map((pkg) => {
|
|
1474
|
+
const tier = calculateQualityTier(pkg.metrics);
|
|
1475
|
+
return /* @__PURE__ */ jsx(
|
|
1476
|
+
QualityHexagonExpandable,
|
|
1477
|
+
{
|
|
1478
|
+
metrics: pkg.metrics,
|
|
1479
|
+
tier,
|
|
1480
|
+
theme: theme2,
|
|
1481
|
+
packageName: pkg.name,
|
|
1482
|
+
packageVersion: pkg.version
|
|
1483
|
+
},
|
|
1484
|
+
pkg.name
|
|
1485
|
+
);
|
|
1486
|
+
}) })
|
|
1487
|
+
]
|
|
1488
|
+
}
|
|
1489
|
+
)
|
|
1490
|
+
}
|
|
1491
|
+
);
|
|
1492
|
+
};
|
|
1493
|
+
const QualityHexagonPanel = (props) => {
|
|
1494
|
+
return /* @__PURE__ */ jsx(ThemeProvider, { children: /* @__PURE__ */ jsx(QualityHexagonPanelContent, { ...props }) });
|
|
1495
|
+
};
|
|
1496
|
+
const METRIC_OPTIONS = [
|
|
1497
|
+
{ key: "types", label: "Types" },
|
|
1498
|
+
{ key: "documentation", label: "Docs" },
|
|
1499
|
+
{ key: "tests", label: "Tests" },
|
|
1500
|
+
{ key: "deadCode", label: "Dead Code" },
|
|
1501
|
+
{ key: "formatting", label: "Format" },
|
|
1502
|
+
{ key: "linting", label: "Linting" }
|
|
1503
|
+
];
|
|
1504
|
+
function flattenRepositories(repositories) {
|
|
1505
|
+
const items = [];
|
|
1506
|
+
for (const repo of repositories) {
|
|
1507
|
+
for (const pkg of repo.packages) {
|
|
1508
|
+
items.push({
|
|
1509
|
+
key: `${repo.id}:${pkg.name}`,
|
|
1510
|
+
repositoryId: repo.id,
|
|
1511
|
+
repositoryName: repo.name,
|
|
1512
|
+
packageName: pkg.name,
|
|
1513
|
+
version: pkg.version,
|
|
1514
|
+
metrics: pkg.metrics,
|
|
1515
|
+
tier: calculateQualityTier(pkg.metrics)
|
|
1516
|
+
});
|
|
1517
|
+
}
|
|
1518
|
+
}
|
|
1519
|
+
return items;
|
|
1520
|
+
}
|
|
1521
|
+
function calculateOverallTier(items) {
|
|
1522
|
+
if (items.length === 0) return "none";
|
|
1523
|
+
const avgMetrics = items.reduce(
|
|
1524
|
+
(acc, item) => ({
|
|
1525
|
+
tests: acc.tests + item.metrics.tests / items.length,
|
|
1526
|
+
deadCode: acc.deadCode + item.metrics.deadCode / items.length,
|
|
1527
|
+
linting: acc.linting + item.metrics.linting / items.length,
|
|
1528
|
+
formatting: acc.formatting + item.metrics.formatting / items.length,
|
|
1529
|
+
types: acc.types + item.metrics.types / items.length,
|
|
1530
|
+
documentation: acc.documentation + item.metrics.documentation / items.length
|
|
1531
|
+
}),
|
|
1532
|
+
{ tests: 0, deadCode: 0, linting: 0, formatting: 0, types: 0, documentation: 0 }
|
|
1533
|
+
);
|
|
1534
|
+
return calculateQualityTier(avgMetrics);
|
|
1535
|
+
}
|
|
1536
|
+
function formatLabel(item, showRepositoryName, isSameAsRepo) {
|
|
1537
|
+
if (!showRepositoryName || isSameAsRepo) {
|
|
1538
|
+
return item.packageName;
|
|
1539
|
+
}
|
|
1540
|
+
return `${item.repositoryName} / ${item.packageName}`;
|
|
1541
|
+
}
|
|
1542
|
+
function getValueColor(value, key, theme2) {
|
|
1543
|
+
const effectiveValue = key === "deadCode" ? 100 - value : value;
|
|
1544
|
+
if (effectiveValue >= 80) return theme2.colors.success;
|
|
1545
|
+
if (effectiveValue >= 60) return theme2.colors.warning;
|
|
1546
|
+
return theme2.colors.error;
|
|
1547
|
+
}
|
|
1548
|
+
function RepositoryQualityGridItem({
|
|
1549
|
+
item,
|
|
1550
|
+
theme: theme2,
|
|
1551
|
+
onClick,
|
|
1552
|
+
onVertexClick,
|
|
1553
|
+
showRepositoryName = true,
|
|
1554
|
+
selectedMetric,
|
|
1555
|
+
className
|
|
1556
|
+
}) {
|
|
1557
|
+
const [hoveredVertex, setHoveredVertex] = React2.useState(null);
|
|
1558
|
+
const isSameAsRepo = item.packageName === item.repositoryName;
|
|
1559
|
+
const label = formatLabel(item, showRepositoryName, isSameAsRepo);
|
|
1560
|
+
const tierColors = {
|
|
1561
|
+
none: theme2.colors.muted,
|
|
1562
|
+
bronze: theme2.colors.warning,
|
|
1563
|
+
silver: theme2.colors.secondary,
|
|
1564
|
+
gold: theme2.colors.accent,
|
|
1565
|
+
platinum: theme2.colors.primary
|
|
1566
|
+
};
|
|
1567
|
+
const displayInfo = React2.useMemo(() => {
|
|
1568
|
+
if (selectedMetric) {
|
|
1569
|
+
const option = METRIC_OPTIONS.find((o) => o.key === selectedMetric);
|
|
1570
|
+
if (option) {
|
|
1571
|
+
const value = item.metrics[selectedMetric];
|
|
1572
|
+
return {
|
|
1573
|
+
label: option.label,
|
|
1574
|
+
value,
|
|
1575
|
+
valueColor: getValueColor(value, selectedMetric, theme2)
|
|
1576
|
+
};
|
|
1577
|
+
}
|
|
1578
|
+
}
|
|
1579
|
+
if (hoveredVertex) {
|
|
1580
|
+
return {
|
|
1581
|
+
label: hoveredVertex.label,
|
|
1582
|
+
value: hoveredVertex.value,
|
|
1583
|
+
valueColor: getValueColor(hoveredVertex.value, hoveredVertex.key, theme2)
|
|
1584
|
+
};
|
|
1585
|
+
}
|
|
1586
|
+
return null;
|
|
1587
|
+
}, [selectedMetric, hoveredVertex, item.metrics, theme2]);
|
|
1588
|
+
return /* @__PURE__ */ jsxs(
|
|
1589
|
+
"div",
|
|
1590
|
+
{
|
|
1591
|
+
className: cn(className),
|
|
1592
|
+
onClick,
|
|
1593
|
+
style: {
|
|
1594
|
+
display: "flex",
|
|
1595
|
+
flexDirection: "column",
|
|
1596
|
+
alignItems: "center",
|
|
1597
|
+
gap: 8,
|
|
1598
|
+
padding: 12,
|
|
1599
|
+
borderRadius: 8,
|
|
1600
|
+
backgroundColor: theme2.colors.surface,
|
|
1601
|
+
border: `1px solid ${theme2.colors.border}`,
|
|
1602
|
+
cursor: onClick ? "pointer" : "default",
|
|
1603
|
+
transition: "all 0.2s ease"
|
|
1604
|
+
},
|
|
1605
|
+
onMouseEnter: (e) => {
|
|
1606
|
+
if (onClick) {
|
|
1607
|
+
e.currentTarget.style.borderColor = tierColors[item.tier];
|
|
1608
|
+
e.currentTarget.style.transform = "translateY(-2px)";
|
|
1609
|
+
}
|
|
1610
|
+
},
|
|
1611
|
+
onMouseLeave: (e) => {
|
|
1612
|
+
e.currentTarget.style.borderColor = theme2.colors.border;
|
|
1613
|
+
e.currentTarget.style.transform = "translateY(0)";
|
|
1614
|
+
setHoveredVertex(null);
|
|
1615
|
+
},
|
|
838
1616
|
children: [
|
|
839
|
-
/* @__PURE__ */
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
|
|
843
|
-
|
|
844
|
-
|
|
845
|
-
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
|
|
851
|
-
|
|
852
|
-
|
|
853
|
-
|
|
854
|
-
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
|
|
859
|
-
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
|
|
865
|
-
|
|
866
|
-
|
|
867
|
-
|
|
868
|
-
|
|
869
|
-
|
|
870
|
-
|
|
871
|
-
|
|
872
|
-
|
|
873
|
-
|
|
874
|
-
|
|
875
|
-
|
|
876
|
-
|
|
877
|
-
"
|
|
878
|
-
|
|
879
|
-
|
|
880
|
-
/* @__PURE__ */ jsx("div", { style: {
|
|
881
|
-
|
|
882
|
-
|
|
883
|
-
|
|
884
|
-
|
|
1617
|
+
/* @__PURE__ */ jsx(
|
|
1618
|
+
"div",
|
|
1619
|
+
{
|
|
1620
|
+
style: {
|
|
1621
|
+
height: 24,
|
|
1622
|
+
display: "flex",
|
|
1623
|
+
alignItems: "center",
|
|
1624
|
+
justifyContent: "center",
|
|
1625
|
+
gap: 8,
|
|
1626
|
+
width: "100%",
|
|
1627
|
+
minHeight: 24
|
|
1628
|
+
},
|
|
1629
|
+
children: displayInfo ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
1630
|
+
/* @__PURE__ */ jsx(
|
|
1631
|
+
"span",
|
|
1632
|
+
{
|
|
1633
|
+
style: {
|
|
1634
|
+
fontSize: 14,
|
|
1635
|
+
fontWeight: 500,
|
|
1636
|
+
color: theme2.colors.text
|
|
1637
|
+
},
|
|
1638
|
+
children: displayInfo.label
|
|
1639
|
+
}
|
|
1640
|
+
),
|
|
1641
|
+
/* @__PURE__ */ jsxs(
|
|
1642
|
+
"span",
|
|
1643
|
+
{
|
|
1644
|
+
style: {
|
|
1645
|
+
fontSize: 14,
|
|
1646
|
+
fontWeight: 600,
|
|
1647
|
+
color: displayInfo.valueColor
|
|
1648
|
+
},
|
|
1649
|
+
children: [
|
|
1650
|
+
displayInfo.value,
|
|
1651
|
+
"%"
|
|
1652
|
+
]
|
|
1653
|
+
}
|
|
1654
|
+
)
|
|
1655
|
+
] }) : /* @__PURE__ */ jsx("span", { style: { fontSize: 12, color: theme2.colors.textMuted }, children: "Hover a corner" })
|
|
1656
|
+
}
|
|
1657
|
+
),
|
|
1658
|
+
/* @__PURE__ */ jsx("div", { style: { width: 200, height: 200 }, children: /* @__PURE__ */ jsx(
|
|
1659
|
+
QualityHexagon,
|
|
1660
|
+
{
|
|
1661
|
+
metrics: item.metrics,
|
|
1662
|
+
tier: item.tier,
|
|
1663
|
+
theme: theme2,
|
|
1664
|
+
showLabels: false,
|
|
1665
|
+
showValues: false,
|
|
1666
|
+
onVertexHover: setHoveredVertex,
|
|
1667
|
+
onVertexLeave: () => setHoveredVertex(null),
|
|
1668
|
+
onVertexClick: onVertexClick ? (vertex) => onVertexClick(item, vertex) : void 0
|
|
1669
|
+
}
|
|
1670
|
+
) }),
|
|
1671
|
+
/* @__PURE__ */ jsxs(
|
|
1672
|
+
"div",
|
|
1673
|
+
{
|
|
1674
|
+
style: {
|
|
1675
|
+
display: "flex",
|
|
1676
|
+
flexDirection: "column",
|
|
1677
|
+
alignItems: "center",
|
|
1678
|
+
gap: 2
|
|
1679
|
+
},
|
|
1680
|
+
children: [
|
|
1681
|
+
/* @__PURE__ */ jsx(
|
|
1682
|
+
"span",
|
|
1683
|
+
{
|
|
1684
|
+
style: {
|
|
1685
|
+
fontSize: 12,
|
|
1686
|
+
fontWeight: 500,
|
|
1687
|
+
color: theme2.colors.text,
|
|
1688
|
+
textAlign: "center"
|
|
1689
|
+
},
|
|
1690
|
+
children: label
|
|
1691
|
+
}
|
|
1692
|
+
),
|
|
1693
|
+
item.version && /* @__PURE__ */ jsxs(
|
|
1694
|
+
"span",
|
|
1695
|
+
{
|
|
1696
|
+
style: {
|
|
1697
|
+
fontSize: 10,
|
|
1698
|
+
color: theme2.colors.textMuted
|
|
1699
|
+
},
|
|
1700
|
+
children: [
|
|
1701
|
+
"v",
|
|
1702
|
+
item.version
|
|
1703
|
+
]
|
|
1704
|
+
}
|
|
1705
|
+
)
|
|
1706
|
+
]
|
|
1707
|
+
}
|
|
1708
|
+
)
|
|
1709
|
+
]
|
|
1710
|
+
}
|
|
1711
|
+
);
|
|
1712
|
+
}
|
|
1713
|
+
function calculateAverageScore(metrics) {
|
|
1714
|
+
const adjusted = { ...metrics };
|
|
1715
|
+
adjusted.deadCode = 100 - adjusted.deadCode;
|
|
1716
|
+
return Object.values(adjusted).reduce((a, b) => a + b, 0) / 6;
|
|
1717
|
+
}
|
|
1718
|
+
function RepositoryQualityGrid({
|
|
1719
|
+
repositories,
|
|
1720
|
+
theme: theme2,
|
|
1721
|
+
onItemClick,
|
|
1722
|
+
onVertexClick,
|
|
1723
|
+
className,
|
|
1724
|
+
showRepositoryName = true,
|
|
1725
|
+
showSummary = true
|
|
1726
|
+
}) {
|
|
1727
|
+
const [selectedMetric, setSelectedMetric] = React2.useState(null);
|
|
1728
|
+
const items = React2.useMemo(() => flattenRepositories(repositories), [repositories]);
|
|
1729
|
+
const overallTier = React2.useMemo(() => calculateOverallTier(items), [items]);
|
|
1730
|
+
const sortedItems = React2.useMemo(() => {
|
|
1731
|
+
return [...items].sort((a, b) => {
|
|
1732
|
+
if (selectedMetric) {
|
|
1733
|
+
const aVal = selectedMetric === "deadCode" ? 100 - a.metrics[selectedMetric] : a.metrics[selectedMetric];
|
|
1734
|
+
const bVal = selectedMetric === "deadCode" ? 100 - b.metrics[selectedMetric] : b.metrics[selectedMetric];
|
|
1735
|
+
return bVal - aVal;
|
|
1736
|
+
} else {
|
|
1737
|
+
return calculateAverageScore(b.metrics) - calculateAverageScore(a.metrics);
|
|
1738
|
+
}
|
|
1739
|
+
});
|
|
1740
|
+
}, [items, selectedMetric]);
|
|
1741
|
+
const tierColors = {
|
|
1742
|
+
none: theme2.colors.muted,
|
|
1743
|
+
bronze: theme2.colors.warning,
|
|
1744
|
+
silver: theme2.colors.secondary,
|
|
1745
|
+
gold: theme2.colors.accent,
|
|
1746
|
+
platinum: theme2.colors.primary
|
|
1747
|
+
};
|
|
1748
|
+
const tierLabels = {
|
|
1749
|
+
none: "No Data",
|
|
1750
|
+
bronze: "Bronze",
|
|
1751
|
+
silver: "Silver",
|
|
1752
|
+
gold: "Gold",
|
|
1753
|
+
platinum: "Platinum"
|
|
1754
|
+
};
|
|
1755
|
+
if (items.length === 0) {
|
|
1756
|
+
return /* @__PURE__ */ jsx(
|
|
1757
|
+
"div",
|
|
1758
|
+
{
|
|
1759
|
+
className: cn(className),
|
|
1760
|
+
style: {
|
|
885
1761
|
padding: 40,
|
|
886
1762
|
textAlign: "center",
|
|
887
|
-
color: theme2.colors.textMuted
|
|
888
|
-
|
|
889
|
-
|
|
890
|
-
|
|
891
|
-
|
|
892
|
-
|
|
893
|
-
|
|
894
|
-
|
|
895
|
-
|
|
896
|
-
|
|
897
|
-
|
|
898
|
-
|
|
899
|
-
|
|
1763
|
+
color: theme2.colors.textMuted,
|
|
1764
|
+
backgroundColor: theme2.colors.background,
|
|
1765
|
+
borderRadius: 8
|
|
1766
|
+
},
|
|
1767
|
+
children: "No repositories to display"
|
|
1768
|
+
}
|
|
1769
|
+
);
|
|
1770
|
+
}
|
|
1771
|
+
return /* @__PURE__ */ jsxs(
|
|
1772
|
+
"div",
|
|
1773
|
+
{
|
|
1774
|
+
className: cn(className),
|
|
1775
|
+
style: {
|
|
1776
|
+
display: "flex",
|
|
1777
|
+
flexDirection: "column",
|
|
1778
|
+
gap: 16,
|
|
1779
|
+
backgroundColor: theme2.colors.background,
|
|
1780
|
+
fontFamily: theme2.fonts.body
|
|
1781
|
+
},
|
|
1782
|
+
children: [
|
|
1783
|
+
showSummary && /* @__PURE__ */ jsxs(
|
|
1784
|
+
"div",
|
|
1785
|
+
{
|
|
1786
|
+
style: {
|
|
1787
|
+
display: "flex",
|
|
1788
|
+
alignItems: "center",
|
|
1789
|
+
justifyContent: "space-between",
|
|
1790
|
+
flexWrap: "wrap",
|
|
1791
|
+
gap: 12,
|
|
1792
|
+
padding: "12px 16px",
|
|
1793
|
+
backgroundColor: theme2.colors.surface,
|
|
1794
|
+
border: `1px solid ${theme2.colors.border}`
|
|
900
1795
|
},
|
|
901
|
-
|
|
902
|
-
|
|
903
|
-
|
|
1796
|
+
children: [
|
|
1797
|
+
/* @__PURE__ */ jsxs("div", { style: { display: "flex", alignItems: "center", gap: 12 }, children: [
|
|
1798
|
+
/* @__PURE__ */ jsxs(
|
|
1799
|
+
"span",
|
|
1800
|
+
{
|
|
1801
|
+
style: {
|
|
1802
|
+
fontSize: 14,
|
|
1803
|
+
fontWeight: 500,
|
|
1804
|
+
color: theme2.colors.text
|
|
1805
|
+
},
|
|
1806
|
+
children: [
|
|
1807
|
+
items.length,
|
|
1808
|
+
" ",
|
|
1809
|
+
items.length === 1 ? "package" : "packages"
|
|
1810
|
+
]
|
|
1811
|
+
}
|
|
1812
|
+
),
|
|
1813
|
+
/* @__PURE__ */ jsx("span", { style: { color: theme2.colors.textMuted }, children: "•" }),
|
|
1814
|
+
/* @__PURE__ */ jsxs(
|
|
1815
|
+
"span",
|
|
1816
|
+
{
|
|
1817
|
+
style: {
|
|
1818
|
+
fontSize: 14,
|
|
1819
|
+
color: theme2.colors.textMuted
|
|
1820
|
+
},
|
|
1821
|
+
children: [
|
|
1822
|
+
repositories.length,
|
|
1823
|
+
" ",
|
|
1824
|
+
repositories.length === 1 ? "repository" : "repositories"
|
|
1825
|
+
]
|
|
1826
|
+
}
|
|
1827
|
+
)
|
|
1828
|
+
] }),
|
|
1829
|
+
/* @__PURE__ */ jsxs("div", { style: { display: "flex", alignItems: "center", gap: 12 }, children: [
|
|
1830
|
+
/* @__PURE__ */ jsxs(
|
|
1831
|
+
"select",
|
|
1832
|
+
{
|
|
1833
|
+
value: selectedMetric ?? "",
|
|
1834
|
+
onChange: (e) => setSelectedMetric(e.target.value ? e.target.value : null),
|
|
1835
|
+
style: {
|
|
1836
|
+
padding: "4px 8px",
|
|
1837
|
+
fontSize: 13,
|
|
1838
|
+
backgroundColor: theme2.colors.background,
|
|
1839
|
+
color: theme2.colors.text,
|
|
1840
|
+
border: `1px solid ${theme2.colors.border}`,
|
|
1841
|
+
borderRadius: 4,
|
|
1842
|
+
cursor: "pointer",
|
|
1843
|
+
outline: "none"
|
|
1844
|
+
},
|
|
1845
|
+
children: [
|
|
1846
|
+
/* @__PURE__ */ jsx("option", { value: "", children: "Select metric..." }),
|
|
1847
|
+
METRIC_OPTIONS.map((option) => /* @__PURE__ */ jsx("option", { value: option.key, children: option.label }, option.key))
|
|
1848
|
+
]
|
|
1849
|
+
}
|
|
1850
|
+
),
|
|
1851
|
+
/* @__PURE__ */ jsxs(
|
|
1852
|
+
"div",
|
|
1853
|
+
{
|
|
1854
|
+
style: {
|
|
1855
|
+
display: "flex",
|
|
1856
|
+
alignItems: "center",
|
|
1857
|
+
gap: 8,
|
|
1858
|
+
padding: "4px 12px",
|
|
1859
|
+
backgroundColor: theme2.colors.backgroundLight,
|
|
1860
|
+
borderRadius: 16,
|
|
1861
|
+
border: `1px solid ${tierColors[overallTier]}`
|
|
1862
|
+
},
|
|
1863
|
+
children: [
|
|
1864
|
+
/* @__PURE__ */ jsx(
|
|
1865
|
+
"span",
|
|
1866
|
+
{
|
|
1867
|
+
style: {
|
|
1868
|
+
width: 8,
|
|
1869
|
+
height: 8,
|
|
1870
|
+
borderRadius: "50%",
|
|
1871
|
+
backgroundColor: tierColors[overallTier]
|
|
1872
|
+
}
|
|
1873
|
+
}
|
|
1874
|
+
),
|
|
1875
|
+
/* @__PURE__ */ jsx(
|
|
1876
|
+
"span",
|
|
1877
|
+
{
|
|
1878
|
+
style: {
|
|
1879
|
+
fontSize: 13,
|
|
1880
|
+
fontWeight: 500,
|
|
1881
|
+
color: tierColors[overallTier]
|
|
1882
|
+
},
|
|
1883
|
+
children: tierLabels[overallTier]
|
|
1884
|
+
}
|
|
1885
|
+
)
|
|
1886
|
+
]
|
|
1887
|
+
}
|
|
1888
|
+
)
|
|
1889
|
+
] })
|
|
1890
|
+
]
|
|
1891
|
+
}
|
|
1892
|
+
),
|
|
1893
|
+
/* @__PURE__ */ jsx(
|
|
1894
|
+
"div",
|
|
1895
|
+
{
|
|
1896
|
+
style: {
|
|
1897
|
+
display: "grid",
|
|
1898
|
+
gridTemplateColumns: "repeat(auto-fill, minmax(220px, 1fr))",
|
|
1899
|
+
gap: 12,
|
|
1900
|
+
padding: 16
|
|
1901
|
+
},
|
|
1902
|
+
children: sortedItems.map((item) => /* @__PURE__ */ jsx(
|
|
1903
|
+
RepositoryQualityGridItem,
|
|
1904
|
+
{
|
|
1905
|
+
item,
|
|
1906
|
+
theme: theme2,
|
|
1907
|
+
onClick: onItemClick ? () => onItemClick(item) : void 0,
|
|
1908
|
+
onVertexClick,
|
|
1909
|
+
showRepositoryName,
|
|
1910
|
+
selectedMetric
|
|
1911
|
+
},
|
|
1912
|
+
item.key
|
|
1913
|
+
))
|
|
1914
|
+
}
|
|
1915
|
+
)
|
|
904
1916
|
]
|
|
905
1917
|
}
|
|
906
1918
|
);
|
|
1919
|
+
}
|
|
1920
|
+
const mockRepositories = [
|
|
1921
|
+
{
|
|
1922
|
+
id: "platform",
|
|
1923
|
+
name: "platform",
|
|
1924
|
+
packages: [
|
|
1925
|
+
{
|
|
1926
|
+
name: "@org/core",
|
|
1927
|
+
version: "2.0.0",
|
|
1928
|
+
metrics: { tests: 94, deadCode: 4, linting: 98, formatting: 100, types: 97, documentation: 90 }
|
|
1929
|
+
},
|
|
1930
|
+
{
|
|
1931
|
+
name: "@org/ui-components",
|
|
1932
|
+
version: "2.0.0",
|
|
1933
|
+
metrics: { tests: 85, deadCode: 8, linting: 95, formatting: 98, types: 92, documentation: 80 }
|
|
1934
|
+
},
|
|
1935
|
+
{
|
|
1936
|
+
name: "@org/hooks",
|
|
1937
|
+
version: "2.0.0",
|
|
1938
|
+
metrics: { tests: 88, deadCode: 6, linting: 96, formatting: 100, types: 94, documentation: 85 }
|
|
1939
|
+
}
|
|
1940
|
+
]
|
|
1941
|
+
},
|
|
1942
|
+
{
|
|
1943
|
+
id: "backend",
|
|
1944
|
+
name: "backend-services",
|
|
1945
|
+
packages: [
|
|
1946
|
+
{
|
|
1947
|
+
name: "backend-services",
|
|
1948
|
+
version: "1.5.0",
|
|
1949
|
+
metrics: { tests: 80, deadCode: 15, linting: 90, formatting: 95, types: 85, documentation: 72 }
|
|
1950
|
+
}
|
|
1951
|
+
]
|
|
1952
|
+
},
|
|
1953
|
+
{
|
|
1954
|
+
id: "docs",
|
|
1955
|
+
name: "documentation-site",
|
|
1956
|
+
packages: [
|
|
1957
|
+
{
|
|
1958
|
+
name: "documentation-site",
|
|
1959
|
+
version: "1.0.0",
|
|
1960
|
+
metrics: { tests: 45, deadCode: 25, linting: 75, formatting: 85, types: 60, documentation: 95 }
|
|
1961
|
+
}
|
|
1962
|
+
]
|
|
1963
|
+
}
|
|
1964
|
+
];
|
|
1965
|
+
const RepositoryQualityGridPanelContent = ({
|
|
1966
|
+
context,
|
|
1967
|
+
events
|
|
1968
|
+
}) => {
|
|
1969
|
+
var _a;
|
|
1970
|
+
const { theme: theme2 } = useTheme();
|
|
1971
|
+
const qualitySlice = context.getSlice("repositoriesQuality");
|
|
1972
|
+
const hasQualitySlice = context.hasSlice("repositoriesQuality");
|
|
1973
|
+
const isLoading = (qualitySlice == null ? void 0 : qualitySlice.loading) ?? false;
|
|
1974
|
+
const repositories = React2__default.useMemo(() => {
|
|
1975
|
+
var _a2;
|
|
1976
|
+
if ((_a2 = qualitySlice == null ? void 0 : qualitySlice.data) == null ? void 0 : _a2.repositories) {
|
|
1977
|
+
return qualitySlice.data.repositories;
|
|
1978
|
+
}
|
|
1979
|
+
if (hasQualitySlice) {
|
|
1980
|
+
return [];
|
|
1981
|
+
}
|
|
1982
|
+
return mockRepositories;
|
|
1983
|
+
}, [(_a = qualitySlice == null ? void 0 : qualitySlice.data) == null ? void 0 : _a.repositories, hasQualitySlice]);
|
|
1984
|
+
const handleItemClick = (item) => {
|
|
1985
|
+
events.emit({
|
|
1986
|
+
type: "principal-ade.repository-quality-grid:item:click",
|
|
1987
|
+
source: "principal-ade.repository-quality-grid-panel",
|
|
1988
|
+
timestamp: Date.now(),
|
|
1989
|
+
payload: {
|
|
1990
|
+
repositoryId: item.repositoryId,
|
|
1991
|
+
repositoryName: item.repositoryName,
|
|
1992
|
+
packageName: item.packageName,
|
|
1993
|
+
tier: item.tier
|
|
1994
|
+
}
|
|
1995
|
+
});
|
|
1996
|
+
};
|
|
1997
|
+
const handleVertexClick = (item, vertex) => {
|
|
1998
|
+
events.emit({
|
|
1999
|
+
type: "principal-ade.repository-quality-grid:vertex:click",
|
|
2000
|
+
source: "principal-ade.repository-quality-grid-panel",
|
|
2001
|
+
timestamp: Date.now(),
|
|
2002
|
+
payload: {
|
|
2003
|
+
repositoryId: item.repositoryId,
|
|
2004
|
+
repositoryName: item.repositoryName,
|
|
2005
|
+
packageName: item.packageName,
|
|
2006
|
+
metric: vertex.key,
|
|
2007
|
+
label: vertex.label,
|
|
2008
|
+
value: vertex.value
|
|
2009
|
+
}
|
|
2010
|
+
});
|
|
2011
|
+
};
|
|
2012
|
+
const handleRefresh = async () => {
|
|
2013
|
+
if (context.hasSlice("repositoriesQuality")) {
|
|
2014
|
+
await context.refresh("workspace", "repositoriesQuality");
|
|
2015
|
+
}
|
|
2016
|
+
};
|
|
2017
|
+
React2__default.useEffect(() => {
|
|
2018
|
+
const unsubscribers = [
|
|
2019
|
+
events.on("principal-ade.repository-quality-grid:refresh", async () => {
|
|
2020
|
+
await handleRefresh();
|
|
2021
|
+
})
|
|
2022
|
+
];
|
|
2023
|
+
return () => unsubscribers.forEach((unsub) => unsub());
|
|
2024
|
+
}, [events, context]);
|
|
2025
|
+
return /* @__PURE__ */ jsx(
|
|
2026
|
+
"div",
|
|
2027
|
+
{
|
|
2028
|
+
style: {
|
|
2029
|
+
fontFamily: theme2.fonts.body,
|
|
2030
|
+
height: "100%",
|
|
2031
|
+
minHeight: 0,
|
|
2032
|
+
backgroundColor: theme2.colors.background,
|
|
2033
|
+
color: theme2.colors.text,
|
|
2034
|
+
overflowY: "auto",
|
|
2035
|
+
boxSizing: "border-box"
|
|
2036
|
+
},
|
|
2037
|
+
children: isLoading ? /* @__PURE__ */ jsx(
|
|
2038
|
+
"div",
|
|
2039
|
+
{
|
|
2040
|
+
style: {
|
|
2041
|
+
padding: 40,
|
|
2042
|
+
textAlign: "center",
|
|
2043
|
+
color: theme2.colors.textMuted
|
|
2044
|
+
},
|
|
2045
|
+
children: "Loading repository quality metrics..."
|
|
2046
|
+
}
|
|
2047
|
+
) : repositories.length === 0 ? /* @__PURE__ */ jsx(
|
|
2048
|
+
"div",
|
|
2049
|
+
{
|
|
2050
|
+
style: {
|
|
2051
|
+
padding: 40,
|
|
2052
|
+
textAlign: "center",
|
|
2053
|
+
color: theme2.colors.textMuted
|
|
2054
|
+
},
|
|
2055
|
+
children: "No repositories with quality metrics found."
|
|
2056
|
+
}
|
|
2057
|
+
) : /* @__PURE__ */ jsx(
|
|
2058
|
+
RepositoryQualityGrid,
|
|
2059
|
+
{
|
|
2060
|
+
repositories,
|
|
2061
|
+
theme: theme2,
|
|
2062
|
+
onItemClick: handleItemClick,
|
|
2063
|
+
onVertexClick: handleVertexClick,
|
|
2064
|
+
showRepositoryName: true,
|
|
2065
|
+
showSummary: true
|
|
2066
|
+
}
|
|
2067
|
+
)
|
|
2068
|
+
}
|
|
2069
|
+
);
|
|
907
2070
|
};
|
|
908
|
-
const
|
|
909
|
-
return /* @__PURE__ */ jsx(ThemeProvider, { children: /* @__PURE__ */ jsx(
|
|
2071
|
+
const RepositoryQualityGridPanel = (props) => {
|
|
2072
|
+
return /* @__PURE__ */ jsx(ThemeProvider, { children: /* @__PURE__ */ jsx(RepositoryQualityGridPanelContent, { ...props }) });
|
|
910
2073
|
};
|
|
911
2074
|
const panels = [
|
|
912
2075
|
{
|
|
@@ -934,6 +2097,28 @@ const panels = [
|
|
|
934
2097
|
onUnmount: async (_context) => {
|
|
935
2098
|
console.log("Quality Hexagon Panel unmounting");
|
|
936
2099
|
}
|
|
2100
|
+
},
|
|
2101
|
+
{
|
|
2102
|
+
metadata: {
|
|
2103
|
+
id: "principal-ade.repository-quality-grid-panel",
|
|
2104
|
+
name: "Repository Quality Grid",
|
|
2105
|
+
icon: "⬡",
|
|
2106
|
+
version: "0.1.0",
|
|
2107
|
+
author: "Principal ADE",
|
|
2108
|
+
description: "Display quality metrics for multiple repositories in a flat grid layout. Supports filtering by metric type, sorting, and comparing quality across projects.",
|
|
2109
|
+
slices: ["repositoriesQuality"],
|
|
2110
|
+
tools: []
|
|
2111
|
+
},
|
|
2112
|
+
component: RepositoryQualityGridPanel,
|
|
2113
|
+
onMount: async (context) => {
|
|
2114
|
+
console.log("Repository Quality Grid Panel mounted");
|
|
2115
|
+
if (context.hasSlice("repositoriesQuality") && !context.isSliceLoading("repositoriesQuality")) {
|
|
2116
|
+
await context.refresh("workspace", "repositoriesQuality");
|
|
2117
|
+
}
|
|
2118
|
+
},
|
|
2119
|
+
onUnmount: async (_context) => {
|
|
2120
|
+
console.log("Repository Quality Grid Panel unmounting");
|
|
2121
|
+
}
|
|
937
2122
|
}
|
|
938
2123
|
];
|
|
939
2124
|
const onPackageLoad = async () => {
|
|
@@ -946,7 +2131,11 @@ export {
|
|
|
946
2131
|
QualityHexagon,
|
|
947
2132
|
QualityHexagonCompact,
|
|
948
2133
|
QualityHexagonDetailed,
|
|
2134
|
+
QualityHexagonExpandable,
|
|
949
2135
|
QualityHexagonPanel,
|
|
2136
|
+
RepositoryQualityGrid,
|
|
2137
|
+
RepositoryQualityGridItem,
|
|
2138
|
+
RepositoryQualityGridPanel,
|
|
950
2139
|
calculateQualityTier,
|
|
951
2140
|
onPackageLoad,
|
|
952
2141
|
onPackageUnload,
|