@smartnet360/svelte-components 0.0.48 → 0.0.49
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/apps/site-check/helper.d.ts +3 -1
- package/dist/apps/site-check/helper.js +11 -7
- package/dist/apps/site-check/index.d.ts +1 -1
- package/dist/apps/site-check/index.js +1 -1
- package/dist/apps/site-check/transforms.d.ts +26 -0
- package/dist/apps/site-check/transforms.js +87 -0
- package/dist/core/Charts/charts.model.d.ts +1 -0
- package/dist/core/Charts/data-utils.js +5 -2
- package/package.json +1 -1
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type { Layout, CellStylingConfig } from '../../core/Charts';
|
|
2
2
|
import type { CellTrafficRecord } from './';
|
|
3
|
+
import { type StackGroupMode } from './transforms.js';
|
|
3
4
|
/**
|
|
4
5
|
* Expand base layout configuration with dynamic KPIs based on selected cells
|
|
5
6
|
* Takes a base layout (with one KPI per metric) and expands it to include one KPI per cell
|
|
@@ -7,9 +8,10 @@ import type { CellTrafficRecord } from './';
|
|
|
7
8
|
* @param baseLayout - The base layout configuration from JSON
|
|
8
9
|
* @param data - Filtered cell traffic records for selected cells
|
|
9
10
|
* @param stylingConfig - Optional cell styling configuration (band colors, sector line styles)
|
|
11
|
+
* @param stackGroupMode - Optional stackgroup strategy for stacked charts (default: 'none' = single stack)
|
|
10
12
|
* @returns Expanded layout with cell-specific KPIs
|
|
11
13
|
*/
|
|
12
|
-
export declare function expandLayoutForCells(baseLayout: Layout, data: CellTrafficRecord[], stylingConfig?: CellStylingConfig): Layout;
|
|
14
|
+
export declare function expandLayoutForCells(baseLayout: Layout, data: CellTrafficRecord[], stylingConfig?: CellStylingConfig, stackGroupMode?: StackGroupMode): Layout;
|
|
13
15
|
/**
|
|
14
16
|
* Extract base metric names from a layout configuration
|
|
15
17
|
* Returns unique metric rawNames that need to be pivoted
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { createStyledKPI, sortCellsByBandFrequency } from './transforms.js';
|
|
1
|
+
import { createStyledKPI, sortCellsByBandFrequency, assignStackGroups } from './transforms.js';
|
|
2
2
|
/**
|
|
3
3
|
* Expand base layout configuration with dynamic KPIs based on selected cells
|
|
4
4
|
* Takes a base layout (with one KPI per metric) and expands it to include one KPI per cell
|
|
@@ -6,9 +6,10 @@ import { createStyledKPI, sortCellsByBandFrequency } from './transforms.js';
|
|
|
6
6
|
* @param baseLayout - The base layout configuration from JSON
|
|
7
7
|
* @param data - Filtered cell traffic records for selected cells
|
|
8
8
|
* @param stylingConfig - Optional cell styling configuration (band colors, sector line styles)
|
|
9
|
+
* @param stackGroupMode - Optional stackgroup strategy for stacked charts (default: 'none' = single stack)
|
|
9
10
|
* @returns Expanded layout with cell-specific KPIs
|
|
10
11
|
*/
|
|
11
|
-
export function expandLayoutForCells(baseLayout, data, stylingConfig) {
|
|
12
|
+
export function expandLayoutForCells(baseLayout, data, stylingConfig, stackGroupMode = 'none') {
|
|
12
13
|
// Get unique cells and their metadata, sorted by band frequency
|
|
13
14
|
const cellMap = new Map();
|
|
14
15
|
data.forEach((record) => {
|
|
@@ -36,8 +37,8 @@ export function expandLayoutForCells(baseLayout, data, stylingConfig) {
|
|
|
36
37
|
...section,
|
|
37
38
|
charts: section.charts.map((chart) => ({
|
|
38
39
|
...chart,
|
|
39
|
-
yLeft: expandKPIs(chart.yLeft, cells, effectiveStyling),
|
|
40
|
-
yRight: expandKPIs(chart.yRight, cells, effectiveStyling)
|
|
40
|
+
yLeft: expandKPIs(chart.yLeft, cells, effectiveStyling, stackGroupMode),
|
|
41
|
+
yRight: expandKPIs(chart.yRight, cells, effectiveStyling, stackGroupMode)
|
|
41
42
|
}))
|
|
42
43
|
};
|
|
43
44
|
})
|
|
@@ -52,10 +53,11 @@ export function expandLayoutForCells(baseLayout, data, stylingConfig) {
|
|
|
52
53
|
* @param baseKPIs - Array of base KPIs from layout
|
|
53
54
|
* @param cells - Array of [cellName, record] tuples
|
|
54
55
|
* @param stylingConfig - Optional cell styling configuration
|
|
55
|
-
* @
|
|
56
|
+
* @param stackGroupMode - Stackgroup strategy for this set of KPIs
|
|
57
|
+
* @returns Expanded array of KPIs (styled or default, with stackgroups assigned)
|
|
56
58
|
*/
|
|
57
|
-
function expandKPIs(baseKPIs, cells, stylingConfig) {
|
|
58
|
-
|
|
59
|
+
function expandKPIs(baseKPIs, cells, stylingConfig, stackGroupMode = 'none') {
|
|
60
|
+
let expandedKPIs = [];
|
|
59
61
|
baseKPIs.forEach((baseKPI) => {
|
|
60
62
|
cells.forEach(([cellName, record]) => {
|
|
61
63
|
if (stylingConfig) {
|
|
@@ -73,6 +75,8 @@ function expandKPIs(baseKPIs, cells, stylingConfig) {
|
|
|
73
75
|
}
|
|
74
76
|
});
|
|
75
77
|
});
|
|
78
|
+
// Apply stackgroups to all expanded KPIs
|
|
79
|
+
expandedKPIs = assignStackGroups(expandedKPIs, cells, stackGroupMode);
|
|
76
80
|
return expandedKPIs;
|
|
77
81
|
}
|
|
78
82
|
/**
|
|
@@ -4,6 +4,6 @@
|
|
|
4
4
|
*/
|
|
5
5
|
export { default as SiteCheck } from './SiteCheck.svelte';
|
|
6
6
|
export { loadCellTrafficData, getUniqueSites, getUniqueCells, groupDataByCell, defaultTreeGrouping, type CellTrafficRecord, type TreeGroupingConfig, type TreeGroupField } from './data-loader.js';
|
|
7
|
-
export { buildTreeNodes, filterChartData, transformChartData, createStyledKPI, extractBandFromCell, getBandFrequency, sortCellsByBandFrequency } from './transforms.js';
|
|
7
|
+
export { buildTreeNodes, filterChartData, transformChartData, createStyledKPI, extractBandFromCell, getBandFrequency, sortCellsByBandFrequency, assignStackGroups, createStackGroupId, type StackGroupMode } from './transforms.js';
|
|
8
8
|
export { expandLayoutForCells, extractBaseMetrics } from './helper.js';
|
|
9
9
|
export { defaultCellStyling } from './default-cell-styling.js';
|
|
@@ -7,7 +7,7 @@ export { default as SiteCheck } from './SiteCheck.svelte';
|
|
|
7
7
|
// Data loading
|
|
8
8
|
export { loadCellTrafficData, getUniqueSites, getUniqueCells, groupDataByCell, defaultTreeGrouping } from './data-loader.js';
|
|
9
9
|
// Data transforms
|
|
10
|
-
export { buildTreeNodes, filterChartData, transformChartData, createStyledKPI, extractBandFromCell, getBandFrequency, sortCellsByBandFrequency } from './transforms.js';
|
|
10
|
+
export { buildTreeNodes, filterChartData, transformChartData, createStyledKPI, extractBandFromCell, getBandFrequency, sortCellsByBandFrequency, assignStackGroups, createStackGroupId } from './transforms.js';
|
|
11
11
|
// Helper functions
|
|
12
12
|
export { expandLayoutForCells, extractBaseMetrics } from './helper.js';
|
|
13
13
|
// Default cell styling configuration
|
|
@@ -5,6 +5,32 @@
|
|
|
5
5
|
import type { TreeNode } from '../../core/TreeView';
|
|
6
6
|
import type { KPI, CellStylingConfig } from '../../core/Charts';
|
|
7
7
|
import type { CellTrafficRecord, TreeGroupingConfig } from './data-loader';
|
|
8
|
+
/**
|
|
9
|
+
* Stackgroup mode types for dynamic stacking strategies
|
|
10
|
+
*/
|
|
11
|
+
export type StackGroupMode = 'band' | 'site' | 'azimuth' | 'sector' | 'cell' | 'none';
|
|
12
|
+
/**
|
|
13
|
+
* Generate a deterministic, production-safe stackgroup ID
|
|
14
|
+
* This function ensures stackgroups are:
|
|
15
|
+
* - Consistent across dev and prod builds
|
|
16
|
+
* - Never undefined, null, or empty
|
|
17
|
+
* - Properly stringified and sanitized
|
|
18
|
+
*
|
|
19
|
+
* @param value - The grouping value (band, site, etc.)
|
|
20
|
+
* @param mode - The grouping mode/strategy
|
|
21
|
+
* @returns Normalized stackgroup string
|
|
22
|
+
*/
|
|
23
|
+
export declare function createStackGroupId(value: string | number | null | undefined, mode: StackGroupMode): string;
|
|
24
|
+
/**
|
|
25
|
+
* Assign stackgroups to KPIs based on cell metadata and grouping mode
|
|
26
|
+
* This is production-safe and works identically in dev and build modes
|
|
27
|
+
*
|
|
28
|
+
* @param kpis - Array of KPIs to assign stackgroups to
|
|
29
|
+
* @param cells - Array of [cellName, record] tuples with metadata
|
|
30
|
+
* @param mode - Grouping strategy (band, site, azimuth, etc.)
|
|
31
|
+
* @returns KPIs with stackGroup field populated
|
|
32
|
+
*/
|
|
33
|
+
export declare function assignStackGroups(kpis: KPI[], cells: [string, CellTrafficRecord][], mode: StackGroupMode): KPI[];
|
|
8
34
|
/**
|
|
9
35
|
* Extract band from cell name using regex pattern matching
|
|
10
36
|
* @param cellName - Cell name like "LTE700_1", "NR3500_2", etc.
|
|
@@ -3,6 +3,93 @@
|
|
|
3
3
|
* Converts raw CSV data to TreeView nodes and Chart configurations
|
|
4
4
|
*/
|
|
5
5
|
import { log } from '../../core/logger';
|
|
6
|
+
/**
|
|
7
|
+
* Generate a deterministic, production-safe stackgroup ID
|
|
8
|
+
* This function ensures stackgroups are:
|
|
9
|
+
* - Consistent across dev and prod builds
|
|
10
|
+
* - Never undefined, null, or empty
|
|
11
|
+
* - Properly stringified and sanitized
|
|
12
|
+
*
|
|
13
|
+
* @param value - The grouping value (band, site, etc.)
|
|
14
|
+
* @param mode - The grouping mode/strategy
|
|
15
|
+
* @returns Normalized stackgroup string
|
|
16
|
+
*/
|
|
17
|
+
export function createStackGroupId(value, mode) {
|
|
18
|
+
// Sanitize the value - convert to string and handle nullish values
|
|
19
|
+
const sanitizedValue = value != null ? String(value).trim() : 'default';
|
|
20
|
+
// If mode is 'none', return a single stackgroup for all traces
|
|
21
|
+
if (mode === 'none') {
|
|
22
|
+
return 'stack_all';
|
|
23
|
+
}
|
|
24
|
+
// Build deterministic ID: stack_{mode}_{value}
|
|
25
|
+
// This ensures all traces with same mode+value get identical stackgroup
|
|
26
|
+
return `stack_${mode}_${sanitizedValue}`;
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Assign stackgroups to KPIs based on cell metadata and grouping mode
|
|
30
|
+
* This is production-safe and works identically in dev and build modes
|
|
31
|
+
*
|
|
32
|
+
* @param kpis - Array of KPIs to assign stackgroups to
|
|
33
|
+
* @param cells - Array of [cellName, record] tuples with metadata
|
|
34
|
+
* @param mode - Grouping strategy (band, site, azimuth, etc.)
|
|
35
|
+
* @returns KPIs with stackGroup field populated
|
|
36
|
+
*/
|
|
37
|
+
export function assignStackGroups(kpis, cells, mode) {
|
|
38
|
+
// Create a mapping of cellName → metadata for quick lookup
|
|
39
|
+
const cellMetadata = new Map(cells);
|
|
40
|
+
return kpis.map(kpi => {
|
|
41
|
+
// Extract cellName from the rawName (format: "METRIC_CELLNAME")
|
|
42
|
+
const cellName = kpi.rawName.split('_').slice(1).join('_');
|
|
43
|
+
const record = cellMetadata.get(cellName);
|
|
44
|
+
if (!record) {
|
|
45
|
+
// Fallback if cell not found - use default stackgroup
|
|
46
|
+
log('⚠️ Cell not found for KPI, using default stackgroup', {
|
|
47
|
+
kpiRawName: kpi.rawName,
|
|
48
|
+
cellName
|
|
49
|
+
});
|
|
50
|
+
return {
|
|
51
|
+
...kpi,
|
|
52
|
+
stackGroup: createStackGroupId(null, mode)
|
|
53
|
+
};
|
|
54
|
+
}
|
|
55
|
+
// Get the grouping value based on mode
|
|
56
|
+
let groupValue;
|
|
57
|
+
switch (mode) {
|
|
58
|
+
case 'band':
|
|
59
|
+
groupValue = record.band;
|
|
60
|
+
break;
|
|
61
|
+
case 'site':
|
|
62
|
+
groupValue = record.siteName;
|
|
63
|
+
break;
|
|
64
|
+
case 'azimuth':
|
|
65
|
+
groupValue = record.azimuth;
|
|
66
|
+
break;
|
|
67
|
+
case 'sector':
|
|
68
|
+
groupValue = record.sector;
|
|
69
|
+
break;
|
|
70
|
+
case 'cell':
|
|
71
|
+
groupValue = record.cellName;
|
|
72
|
+
break;
|
|
73
|
+
case 'none':
|
|
74
|
+
default:
|
|
75
|
+
groupValue = null;
|
|
76
|
+
break;
|
|
77
|
+
}
|
|
78
|
+
// Create deterministic stackgroup ID
|
|
79
|
+
const stackGroup = createStackGroupId(groupValue, mode);
|
|
80
|
+
log('📊 Assigned stackgroup', {
|
|
81
|
+
kpiName: kpi.name,
|
|
82
|
+
cellName,
|
|
83
|
+
mode,
|
|
84
|
+
groupValue,
|
|
85
|
+
stackGroup
|
|
86
|
+
});
|
|
87
|
+
return {
|
|
88
|
+
...kpi,
|
|
89
|
+
stackGroup
|
|
90
|
+
};
|
|
91
|
+
});
|
|
92
|
+
}
|
|
6
93
|
/**
|
|
7
94
|
* Band frequency mapping for consistent ordering
|
|
8
95
|
* Maps band strings to their actual frequencies in MHz
|
|
@@ -14,6 +14,7 @@ export interface KPI {
|
|
|
14
14
|
color?: string;
|
|
15
15
|
lineStyle?: LineStyle;
|
|
16
16
|
movingAverage?: MovingAverageConfig;
|
|
17
|
+
stackGroup?: string;
|
|
17
18
|
}
|
|
18
19
|
export type ChartPosition = 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9;
|
|
19
20
|
export type ChartGrid = "2x2" | "3x3" | "4x4" | "1x2" | "1x4" | "1x8";
|
|
@@ -96,6 +96,9 @@ export function calculateMovingAverage(values, window) {
|
|
|
96
96
|
export function createTimeSeriesTrace(values, timestamps, kpi, yaxis = 'y1', colorIndex = 0, chartType = 'line', stackGroup, coloredHover = true) {
|
|
97
97
|
// Use KPI color if provided, otherwise cycle through modern colors
|
|
98
98
|
const traceColor = kpi.color || modernColors[colorIndex % modernColors.length];
|
|
99
|
+
// Use KPI-level stackgroup if available, otherwise fall back to chart-level stackgroup
|
|
100
|
+
// This allows per-KPI stackgroup assignment (production-safe for dynamic grouping)
|
|
101
|
+
const effectiveStackGroup = kpi.stackGroup || stackGroup;
|
|
99
102
|
// Base trace configuration
|
|
100
103
|
const baseTrace = {
|
|
101
104
|
x: timestamps,
|
|
@@ -126,7 +129,7 @@ export function createTimeSeriesTrace(values, timestamps, kpi, yaxis = 'y1', col
|
|
|
126
129
|
type: 'scatter',
|
|
127
130
|
mode: 'lines',
|
|
128
131
|
fill: 'tonexty',
|
|
129
|
-
stackgroup:
|
|
132
|
+
stackgroup: effectiveStackGroup || 'one',
|
|
130
133
|
line: {
|
|
131
134
|
width: 1.5, // Visible border width
|
|
132
135
|
color: darkenColor(traceColor, 0.25) // 25% darker border for better separation
|
|
@@ -139,7 +142,7 @@ export function createTimeSeriesTrace(values, timestamps, kpi, yaxis = 'y1', col
|
|
|
139
142
|
type: 'scatter',
|
|
140
143
|
mode: 'lines',
|
|
141
144
|
fill: 'tonexty',
|
|
142
|
-
stackgroup:
|
|
145
|
+
stackgroup: effectiveStackGroup || 'one',
|
|
143
146
|
groupnorm: 'percent',
|
|
144
147
|
line: {
|
|
145
148
|
width: 1.5, // Visible border width
|