@smartnet360/svelte-components 0.0.33 → 0.0.35

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.
Files changed (43) hide show
  1. package/dist/apps/site-check/SiteCheck.svelte +96 -0
  2. package/dist/apps/site-check/SiteCheck.svelte.d.ts +12 -0
  3. package/dist/apps/site-check/data-loader.d.ts +29 -0
  4. package/dist/apps/site-check/data-loader.js +105 -0
  5. package/dist/apps/site-check/helper.d.ts +19 -0
  6. package/dist/apps/site-check/helper.js +103 -0
  7. package/dist/apps/site-check/index.d.ts +8 -0
  8. package/dist/apps/site-check/index.js +12 -0
  9. package/dist/apps/site-check/transforms.d.ts +24 -0
  10. package/dist/apps/site-check/transforms.js +142 -0
  11. package/dist/core/Charts/ChartCard.svelte +7 -6
  12. package/dist/core/Charts/ChartCard.svelte.d.ts +1 -2
  13. package/dist/core/Charts/ChartComponent.svelte +0 -2
  14. package/dist/core/Charts/adapt.d.ts +1 -2
  15. package/dist/core/Charts/adapt.js +7 -30
  16. package/dist/core/Charts/charts.model.d.ts +3 -2
  17. package/dist/core/Charts/data-utils.d.ts +4 -2
  18. package/dist/core/Charts/data-utils.js +71 -18
  19. package/dist/core/Charts/index.d.ts +1 -1
  20. package/dist/core/TreeView/TreeView.svelte +2 -2
  21. package/dist/core/index.d.ts +0 -1
  22. package/dist/core/index.js +0 -2
  23. package/dist/index.d.ts +0 -1
  24. package/dist/index.js +0 -2
  25. package/package.json +1 -1
  26. package/dist/cellular/CellularChartsView.svelte +0 -293
  27. package/dist/cellular/CellularChartsView.svelte.d.ts +0 -7
  28. package/dist/cellular/HierarchicalTree.svelte +0 -469
  29. package/dist/cellular/HierarchicalTree.svelte.d.ts +0 -9
  30. package/dist/cellular/SiteTree.svelte +0 -286
  31. package/dist/cellular/SiteTree.svelte.d.ts +0 -11
  32. package/dist/cellular/cellular-transforms.d.ts +0 -25
  33. package/dist/cellular/cellular-transforms.js +0 -129
  34. package/dist/cellular/cellular.model.d.ts +0 -63
  35. package/dist/cellular/cellular.model.js +0 -6
  36. package/dist/cellular/index.d.ts +0 -11
  37. package/dist/cellular/index.js +0 -11
  38. package/dist/cellular/mock-cellular-data.d.ts +0 -13
  39. package/dist/cellular/mock-cellular-data.js +0 -241
  40. package/dist/core/TreeChartView/TreeChartView.svelte +0 -208
  41. package/dist/core/TreeChartView/TreeChartView.svelte.d.ts +0 -42
  42. package/dist/core/TreeChartView/index.d.ts +0 -7
  43. package/dist/core/TreeChartView/index.js +0 -7
@@ -5,42 +5,22 @@
5
5
  /**
6
6
  * Adapts hover behavior based on container size and series count
7
7
  * Optimizes tooltip display and performance for different chart sizes
8
- * Respects configured hover mode, with exception for tiny charts (always 'closest' for performance)
9
8
  */
10
- function adaptHoverBehavior(layout, containerSize, chartInfo, configuredHoverMode) {
9
+ function adaptHoverBehavior(layout, containerSize, chartInfo) {
11
10
  const { width, height } = containerSize;
12
11
  const isTiny = width < 250 || height < 200;
13
12
  const isSmall = width < 400 || height < 300;
14
13
  const isMedium = width < 600 || height < 400;
15
14
  const totalSeries = chartInfo.leftSeriesCount + chartInfo.rightSeriesCount;
16
- // EXCEPTION: Always use 'closest' in tiny charts for performance (override user setting)
15
+ // Priority 1: Disable hover in tiny charts (performance + UX)
17
16
  if (isTiny) {
18
- layout.hovermode = 'closest';
17
+ layout.hovermode = 'closest'; // Single point instead of unified
19
18
  if (layout.hoverlabel) {
20
19
  layout.hoverlabel.font = layout.hoverlabel.font || {};
21
20
  layout.hoverlabel.font.size = 9; // Smaller font
22
21
  }
23
22
  return layout;
24
23
  }
25
- // If user configured a specific hover mode, respect it (except tiny override above)
26
- if (configuredHoverMode !== undefined) {
27
- layout.hovermode = configuredHoverMode;
28
- // Still apply adaptive font sizing based on container size
29
- if (layout.hoverlabel) {
30
- layout.hoverlabel.font = layout.hoverlabel.font || {};
31
- if (isSmall) {
32
- layout.hoverlabel.font.size = 9;
33
- }
34
- else if (isMedium) {
35
- layout.hoverlabel.font.size = 10;
36
- }
37
- else {
38
- layout.hoverlabel.font.size = 11;
39
- }
40
- }
41
- return layout;
42
- }
43
- // No configured mode - apply full adaptive logic (default: 'x')
44
24
  // Priority 2: Simplify hover in small charts
45
25
  if (isSmall) {
46
26
  layout.hovermode = 'x'; // Single point instead of unified
@@ -52,17 +32,14 @@ function adaptHoverBehavior(layout, containerSize, chartInfo, configuredHoverMod
52
32
  }
53
33
  // Priority 3: Adaptive hover mode based on series count
54
34
  if (totalSeries > 4 && isMedium) {
55
- // Too many series in medium chart - switch to x
35
+ // Too many series in medium chart - switch to closest
56
36
  layout.hovermode = 'x';
57
37
  }
58
38
  else if (totalSeries > 8) {
59
39
  // Very many series - even in large charts, use x
60
40
  layout.hovermode = 'x';
61
41
  }
62
- else {
63
- // Default for large charts with reasonable series count
64
- layout.hovermode = 'x';
65
- }
42
+ // Otherwise keep default 'x unified' from base layout
66
43
  // Priority 4: Adaptive hover label font size
67
44
  if (layout.hoverlabel) {
68
45
  layout.hoverlabel.font = layout.hoverlabel.font || {};
@@ -80,7 +57,7 @@ function adaptHoverBehavior(layout, containerSize, chartInfo, configuredHoverMod
80
57
  * Preserves external styling while optimizing functional properties
81
58
  */
82
59
  export function adaptPlotlyLayout(baseLayout, containerSize, chartInfo, config = {}) {
83
- const { enableAdaptation = true, configuredHoverMode } = config;
60
+ const { enableAdaptation = true } = config;
84
61
  if (!enableAdaptation)
85
62
  return baseLayout;
86
63
  const { width, height } = containerSize;
@@ -170,7 +147,7 @@ export function adaptPlotlyLayout(baseLayout, containerSize, chartInfo, config =
170
147
  }
171
148
  }
172
149
  // Apply adaptive hover behavior (disable in tiny, simplify in small, optimize for series count)
173
- adaptHoverBehavior(adaptedLayout, containerSize, chartInfo, configuredHoverMode);
150
+ adaptHoverBehavior(adaptedLayout, containerSize, chartInfo);
174
151
  return adaptedLayout;
175
152
  }
176
153
  /**
@@ -15,12 +15,15 @@ export interface KPI {
15
15
  }
16
16
  export type ChartPosition = 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9;
17
17
  export type ChartGrid = "2x2" | "3x3" | "4x4" | "1x2" | "1x4" | "1x8";
18
+ export type ChartType = "line" | "stacked-area" | "stacked-percentage" | "bar" | "scatter";
18
19
  export interface Chart {
19
20
  pos?: ChartPosition;
20
21
  title: string;
22
+ type?: ChartType;
21
23
  yLeft: KPI[];
22
24
  yRight: KPI[];
23
25
  movingAverage?: MovingAverageConfig;
26
+ stackGroup?: string;
24
27
  }
25
28
  export interface Section {
26
29
  id: string;
@@ -30,12 +33,10 @@ export interface Section {
30
33
  movingAverage?: MovingAverageConfig;
31
34
  }
32
35
  export type Mode = "tabs" | "scrollspy";
33
- export type HoverMode = 'x' | 'y' | 'closest' | 'x unified' | 'y unified' | false;
34
36
  export interface Layout {
35
37
  layoutName: string;
36
38
  sections: Section[];
37
39
  movingAverage?: MovingAverageConfig;
38
- hoverMode?: HoverMode;
39
40
  }
40
41
  export interface ChartMarker {
41
42
  date: string | Date;
@@ -1,7 +1,7 @@
1
1
  import type { KPI } from './charts.model.js';
2
2
  export declare function processKPIData(data: any[], kpi: KPI): number[];
3
3
  export declare function calculateMovingAverage(values: number[], window: number): number[];
4
- export declare function createTimeSeriesTrace(values: number[], timestamps: any[], kpi: KPI, yaxis?: 'y1' | 'y2', colorIndex?: number): any;
4
+ export declare function createTimeSeriesTrace(values: number[], timestamps: any[], kpi: KPI, yaxis?: 'y1' | 'y2', colorIndex?: number, chartType?: string, stackGroup?: string): any;
5
5
  /**
6
6
  * Create time series trace(s) with optional moving average
7
7
  * @param values - Pre-processed numeric values array for the KPI
@@ -9,9 +9,11 @@ export declare function createTimeSeriesTrace(values: number[], timestamps: any[
9
9
  * @param kpi - KPI configuration (may include movingAverage config)
10
10
  * @param yaxis - Which Y-axis to use ('y1' or 'y2')
11
11
  * @param colorIndex - Index for color selection
12
+ * @param chartType - Type of chart (line, stacked-area, etc.)
13
+ * @param stackGroup - Optional stack group identifier
12
14
  * @returns Array of traces (original + MA if configured)
13
15
  */
14
- export declare function createTimeSeriesTraceWithMA(values: number[], timestamps: any[], kpi: KPI, yaxis?: 'y1' | 'y2', colorIndex?: number): any[];
16
+ export declare function createTimeSeriesTraceWithMA(values: number[], timestamps: any[], kpi: KPI, yaxis?: 'y1' | 'y2', colorIndex?: number, chartType?: string, stackGroup?: string): any[];
15
17
  export declare function getYAxisTitle(kpis: KPI[]): string;
16
18
  export declare function formatValue(value: number, scale: 'percent' | 'absolute', unit: string): string;
17
19
  export declare function createDefaultPlotlyLayout(title?: string): any;
@@ -72,27 +72,76 @@ export function calculateMovingAverage(values, window) {
72
72
  maCache.set(cacheKey, result);
73
73
  return result;
74
74
  }
75
- export function createTimeSeriesTrace(values, timestamps, kpi, yaxis = 'y1', colorIndex = 0) {
75
+ export function createTimeSeriesTrace(values, timestamps, kpi, yaxis = 'y1', colorIndex = 0, chartType = 'line', stackGroup) {
76
76
  // Use KPI color if provided, otherwise cycle through modern colors
77
77
  const traceColor = kpi.color || modernColors[colorIndex % modernColors.length];
78
- return {
78
+ // Base trace configuration
79
+ const baseTrace = {
79
80
  x: timestamps,
80
81
  y: values,
81
- type: 'scatter',
82
- mode: 'lines', // Only lines, no markers
83
82
  name: kpi.name,
84
83
  yaxis: yaxis,
85
- line: {
86
- color: traceColor,
87
- width: 3,
88
- shape: 'spline',
89
- smoothing: 0.3,
90
- dash: yaxis === 'y1' ? 'solid' : 'dot' // Y1 = solid, Y2 = dotted
91
- },
92
84
  hovertemplate: `<b>${kpi.name}</b><br>` +
93
- `Value: %{y:} ${kpi.unit}<br>` +
85
+ `Value: %{y:,.2f} ${kpi.unit}<br>` +
94
86
  '<extra></extra>'
95
87
  };
88
+ // Configure based on chart type
89
+ switch (chartType) {
90
+ case 'stacked-area':
91
+ return {
92
+ ...baseTrace,
93
+ type: 'scatter',
94
+ mode: 'lines',
95
+ fill: 'tonexty',
96
+ stackgroup: stackGroup || 'one',
97
+ line: { width: 0.5, color: traceColor },
98
+ fillcolor: traceColor
99
+ };
100
+ case 'stacked-percentage':
101
+ return {
102
+ ...baseTrace,
103
+ type: 'scatter',
104
+ mode: 'lines',
105
+ fill: 'tonexty',
106
+ stackgroup: stackGroup || 'one',
107
+ groupnorm: 'percent',
108
+ line: { width: 0.5, color: traceColor },
109
+ fillcolor: traceColor,
110
+ hovertemplate: `<b>${kpi.name}</b><br>` +
111
+ `Percentage: %{y:.1f}%<br>` +
112
+ '<extra></extra>'
113
+ };
114
+ case 'bar':
115
+ return {
116
+ ...baseTrace,
117
+ type: 'bar',
118
+ marker: { color: traceColor }
119
+ };
120
+ case 'scatter':
121
+ return {
122
+ ...baseTrace,
123
+ type: 'scatter',
124
+ mode: 'markers',
125
+ marker: {
126
+ color: traceColor,
127
+ size: 8
128
+ }
129
+ };
130
+ case 'line':
131
+ default:
132
+ return {
133
+ ...baseTrace,
134
+ type: 'scatter',
135
+ mode: 'lines',
136
+ line: {
137
+ color: traceColor,
138
+ width: 3,
139
+ shape: 'spline',
140
+ smoothing: 0.3,
141
+ dash: yaxis === 'y1' ? 'solid' : 'dot'
142
+ }
143
+ };
144
+ }
96
145
  }
97
146
  /**
98
147
  * Create time series trace(s) with optional moving average
@@ -101,23 +150,27 @@ export function createTimeSeriesTrace(values, timestamps, kpi, yaxis = 'y1', col
101
150
  * @param kpi - KPI configuration (may include movingAverage config)
102
151
  * @param yaxis - Which Y-axis to use ('y1' or 'y2')
103
152
  * @param colorIndex - Index for color selection
153
+ * @param chartType - Type of chart (line, stacked-area, etc.)
154
+ * @param stackGroup - Optional stack group identifier
104
155
  * @returns Array of traces (original + MA if configured)
105
156
  */
106
- export function createTimeSeriesTraceWithMA(values, timestamps, kpi, yaxis = 'y1', colorIndex = 0) {
157
+ export function createTimeSeriesTraceWithMA(values, timestamps, kpi, yaxis = 'y1', colorIndex = 0, chartType = 'line', stackGroup) {
107
158
  const traces = [];
108
159
  const traceColor = kpi.color || modernColors[colorIndex % modernColors.length];
109
160
  // Add original trace (unless explicitly disabled)
110
161
  if (!kpi.movingAverage || kpi.movingAverage.showOriginal !== false) {
111
- const originalTrace = createTimeSeriesTrace(values, timestamps, kpi, yaxis, colorIndex);
162
+ const originalTrace = createTimeSeriesTrace(values, timestamps, kpi, yaxis, colorIndex, chartType, stackGroup);
112
163
  // If MA is enabled, make the original line slightly transparent
113
164
  if (kpi.movingAverage?.enabled) {
114
165
  originalTrace.opacity = 0.4;
115
- originalTrace.line.width = 2;
166
+ if (originalTrace.line) {
167
+ originalTrace.line.width = 2;
168
+ }
116
169
  }
117
170
  traces.push(originalTrace);
118
171
  }
119
- // Add moving average trace if configured
120
- if (kpi.movingAverage?.enabled) {
172
+ // Add moving average trace if configured (only for line charts)
173
+ if (kpi.movingAverage?.enabled && (chartType === 'line' || !chartType)) {
121
174
  const maValues = calculateMovingAverage(values, kpi.movingAverage.window);
122
175
  const maLabel = kpi.movingAverage.label ||
123
176
  `${kpi.name} (MA${kpi.movingAverage.window})`;
@@ -201,7 +254,7 @@ export function createDefaultPlotlyLayout(title) {
201
254
  paper_bgcolor: 'rgba(0,0,0,0)',
202
255
  plot_bgcolor: 'rgba(0,0,0,0)',
203
256
  font: { family: 'Inter, -apple-system, BlinkMacSystemFont, sans-serif' },
204
- hovermode: 'x', // Default hover mode (can be overridden by layout.hoverMode or adaptive behavior)
257
+ hovermode: 'x',
205
258
  hoverlabel: {
206
259
  font: {
207
260
  family: 'Inter, Segoe UI, Tahoma, Geneva, Verdana, sans-serif',
@@ -1,6 +1,6 @@
1
1
  export { default as ChartComponent } from './ChartComponent.svelte';
2
2
  export { default as ChartCard } from './ChartCard.svelte';
3
- export type { Layout, Section, Chart, KPI, Mode, Scale, ChartMarker, ChartGrid, ChartPosition, HoverMode } from './charts.model.js';
3
+ export type { Layout, Section, Chart, KPI, Mode, Scale, ChartMarker, ChartGrid, ChartPosition } from './charts.model.js';
4
4
  export { createTimeSeriesTrace, getYAxisTitle, formatValue, processKPIData, createDefaultPlotlyLayout } from './data-utils.js';
5
5
  export { adaptPlotlyLayout, getSizeCategory, createMarkerShapes, createMarkerAnnotations, addMarkersToLayout } from './adapt.js';
6
6
  export type { ContainerSize, ChartInfo, AdaptationConfig } from './adapt.js';
@@ -81,12 +81,12 @@
81
81
  {/if}
82
82
 
83
83
  <div class="tree-content">
84
- <div class="tree-help-text">
84
+ <!-- <div class="tree-help-text">
85
85
  <small class="text-muted">
86
86
  <i class="bi bi-info-circle"></i>
87
87
  Click checkboxes to select/deselect. Click arrows to expand/collapse.
88
88
  </small>
89
- </div>
89
+ </div> -->
90
90
 
91
91
  <div class="tree-nodes">
92
92
  {#each rootNodes as rootNode (rootNode.path)}
@@ -1,4 +1,3 @@
1
1
  export * from './Desktop/index.js';
2
2
  export * from './Charts/index.js';
3
3
  export * from './TreeView/index.js';
4
- export * from './TreeChartView/index.js';
@@ -6,5 +6,3 @@ export * from './Desktop/index.js';
6
6
  export * from './Charts/index.js';
7
7
  // TreeView generic hierarchical component
8
8
  export * from './TreeView/index.js';
9
- // TreeChartView combined layout component
10
- export * from './TreeChartView/index.js';
package/dist/index.d.ts CHANGED
@@ -1,3 +1,2 @@
1
1
  export * from './core/index.js';
2
2
  export * from './apps/index.js';
3
- export * from './cellular/index.js';
package/dist/index.js CHANGED
@@ -4,5 +4,3 @@
4
4
  export * from './core/index.js';
5
5
  // Complete applications
6
6
  export * from './apps/index.js';
7
- // Cellular network components
8
- export * from './cellular/index.js';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@smartnet360/svelte-components",
3
- "version": "0.0.33",
3
+ "version": "0.0.35",
4
4
  "scripts": {
5
5
  "dev": "vite dev",
6
6
  "build": "vite build && npm run prepack",
@@ -1,293 +0,0 @@
1
- <svelte:options runes={true} />
2
-
3
- <script lang="ts">
4
- import type { CellularSite, CellLine } from './cellular.model.js';
5
- import type { Layout } from '../core/Charts/charts.model.js';
6
- import type { TreeNode } from '../core/TreeView/tree.model.js';
7
- import ChartComponent from '../core/Charts/ChartComponent.svelte';
8
- import { TreeView, createTreeStore } from '../core/TreeView';
9
- import { getBandColor, getBandLabel } from './mock-cellular-data.js';
10
-
11
- interface Props {
12
- sites: CellularSite[];
13
- }
14
-
15
- let { sites }: Props = $props();
16
-
17
- // Transform cellular sites to TreeNode structure
18
- let treeNodes = $derived.by((): TreeNode[] => {
19
- return sites.map(site => ({
20
- id: site.siteId,
21
- label: site.siteName,
22
- icon: '📡',
23
- defaultExpanded: false,
24
- defaultChecked: true, // Explicitly set
25
- children: site.sectors.map(sector => ({
26
- id: sector.sectorId, // Just the sector ID, not full path
27
- label: sector.sectorName,
28
- icon: '📶',
29
- defaultExpanded: false,
30
- defaultChecked: true, // Explicitly set
31
- children: sector.cells.map(cell => ({
32
- id: String(cell.band), // Just the band number
33
- label: getBandLabel(cell.band),
34
- icon: '📻',
35
- defaultChecked: true, // Explicitly set
36
- metadata: {
37
- band: cell.band,
38
- color: getBandColor(cell.band)
39
- }
40
- }))
41
- }))
42
- }));
43
- });
44
-
45
- // Create tree store with persistence
46
- let treeStore = $derived(
47
- createTreeStore({
48
- nodes: treeNodes,
49
- namespace: 'cellular-sites',
50
- persistState: true, // Re-enabled - state will be saved/restored
51
- defaultExpandAll: false,
52
- showIndeterminate: true
53
- })
54
- );
55
-
56
- // Flatten sites into cell lines
57
- let cellLines = $derived.by((): CellLine[] => {
58
- const lines: CellLine[] = [];
59
-
60
- sites.forEach(site => {
61
- site.sectors.forEach(sector => {
62
- sector.cells.forEach(cell => {
63
- // Path construction matches tree-utils.ts flattenTree logic
64
- // Root: "siteId"
65
- // Level 1: "siteId:sectorId"
66
- // Level 2: "siteId:sectorId:band"
67
- const cellKey = `${site.siteId}:${sector.sectorId}:${cell.band}`;
68
-
69
- // Check visibility from tree store
70
- const isVisible = $treeStore.state.checkedPaths.has(cellKey);
71
-
72
- lines.push({
73
- siteId: site.siteId,
74
- siteName: site.siteName,
75
- sectorId: sector.sectorId,
76
- sectorName: sector.sectorName,
77
- cellId: cell.cellId,
78
- band: cell.band,
79
- label: `${site.siteName} - ${sector.sectorName} - ${getBandLabel(cell.band)}`,
80
- color: getBandColor(cell.band),
81
- kpis: cell.kpis,
82
- visible: isVisible
83
- });
84
- });
85
- });
86
- });
87
-
88
- return lines;
89
- });
90
-
91
- // Filter visible cell lines for chart display
92
- let visibleCellLines = $derived(cellLines.filter(line => line.visible));
93
-
94
- // Transform cell lines into chart data format
95
- let chartData = $derived.by(() => {
96
- const data: any[] = [];
97
-
98
- visibleCellLines.forEach(line => {
99
- // Create one row per timestamp with all KPI values
100
- const timestamps = new Set(line.kpis.throughput.map(kpi => kpi.timestamp));
101
-
102
- timestamps.forEach(timestamp => {
103
- const throughputPoint = line.kpis.throughput.find(kpi => kpi.timestamp === timestamp);
104
- const taPoint = line.kpis.timingAdvance.find(kpi => kpi.timestamp === timestamp);
105
-
106
- if (throughputPoint && taPoint) {
107
- data.push({
108
- TIMESTAMP: timestamp,
109
- [`DL_THROUGHPUT_${line.cellId}`]: throughputPoint.value,
110
- [`AVG_TA_${line.cellId}`]: taPoint.value,
111
- _cellId: line.cellId,
112
- _label: line.label,
113
- _color: line.color
114
- });
115
- }
116
- });
117
- });
118
-
119
- return data;
120
- });
121
-
122
- // Chart layout configuration - dynamically build KPIs from visible cells
123
- let chartLayout = $derived.by((): Layout => {
124
- const throughputKPIs = visibleCellLines.map(line => ({
125
- rawName: `DL_THROUGHPUT_${line.cellId}`,
126
- name: line.label,
127
- scale: 'absolute' as const,
128
- unit: 'Mbps',
129
- color: line.color
130
- }));
131
-
132
- const taKPIs = visibleCellLines.map(line => ({
133
- rawName: `AVG_TA_${line.cellId}`,
134
- name: line.label,
135
- scale: 'absolute' as const,
136
- unit: 'μs',
137
- color: line.color
138
- }));
139
-
140
- return {
141
- layoutName: 'Cellular KPIs',
142
- sections: [
143
- {
144
- id: 'kpis',
145
- title: 'KPIs',
146
- grid: '2x2',
147
- charts: [
148
- {
149
- title: 'Downlink Throughput',
150
- yLeft: throughputKPIs,
151
- yRight: []
152
- },
153
- {
154
- title: 'Average Timing Advance',
155
- yLeft: taKPIs,
156
- yRight: []
157
- }
158
- ]
159
- }
160
- ]
161
- };
162
- });
163
- </script>
164
-
165
- <div class="cellular-charts-view">
166
- <!-- Left: Site Tree -->
167
- <aside class="site-selector">
168
- <TreeView store={$treeStore} showControls={true} height="100%" />
169
- </aside>
170
-
171
- <!-- Right: Charts -->
172
- <main class="charts-area">
173
- <div class="charts-header">
174
- <h5 class="mb-0">Cellular Network KPIs</h5>
175
- <div class="stats">
176
- <span class="badge bg-primary">
177
- {visibleCellLines.length} of {cellLines.length} cells visible
178
- </span>
179
- </div>
180
- </div>
181
- <div class="charts-container">
182
- {#if visibleCellLines.length === 0}
183
- <div class="empty-state">
184
- <div class="empty-state-content">
185
- <i class="bi bi-info-circle" style="font-size: 3rem; color: #6c757d;"></i>
186
- <h4 class="mt-3">No Cells Selected</h4>
187
- <p class="text-muted">
188
- Select one or more cells from the tree on the left to display KPI charts.
189
- </p>
190
- </div>
191
- </div>
192
- {:else}
193
- <ChartComponent
194
- layout={chartLayout}
195
- data={chartData}
196
- mode="tabs"
197
- showGlobalControls={true}
198
- enableAdaptation={true}
199
- />
200
- {/if}
201
- </div>
202
- </main>
203
- </div>
204
-
205
- <style>
206
- .cellular-charts-view {
207
- width: 100%;
208
- height: 100%;
209
- display: flex;
210
- gap: 0;
211
- background-color: #fff;
212
- }
213
-
214
- .site-selector {
215
- width: 300px;
216
- flex-shrink: 0;
217
- height: 100%;
218
- overflow: hidden;
219
- }
220
-
221
- .charts-area {
222
- flex: 1;
223
- display: flex;
224
- flex-direction: column;
225
- min-width: 0;
226
- height: 100%;
227
- }
228
-
229
- .charts-header {
230
- padding: 1rem;
231
- border-bottom: 1px solid #dee2e6;
232
- background-color: #f8f9fa;
233
- display: flex;
234
- justify-content: space-between;
235
- align-items: center;
236
- flex-shrink: 0;
237
- }
238
-
239
- .charts-header h5 {
240
- margin: 0;
241
- color: #495057;
242
- }
243
-
244
- .stats {
245
- display: flex;
246
- gap: 0.5rem;
247
- }
248
-
249
- .charts-container {
250
- flex: 1;
251
- min-height: 0;
252
- overflow: hidden;
253
- }
254
-
255
- .empty-state {
256
- display: flex;
257
- align-items: center;
258
- justify-content: center;
259
- height: 100%;
260
- width: 100%;
261
- }
262
-
263
- .empty-state-content {
264
- text-align: center;
265
- max-width: 400px;
266
- padding: 2rem;
267
- }
268
-
269
- .empty-state-content h4 {
270
- color: #495057;
271
- margin-bottom: 0.5rem;
272
- }
273
-
274
- /* Responsive layout */
275
- @media (max-width: 992px) {
276
- .site-selector {
277
- width: 250px;
278
- }
279
- }
280
-
281
- @media (max-width: 768px) {
282
- .cellular-charts-view {
283
- flex-direction: column;
284
- }
285
-
286
- .site-selector {
287
- width: 100%;
288
- height: 300px;
289
- border-right: none;
290
- border-bottom: 1px solid #dee2e6;
291
- }
292
- }
293
- </style>
@@ -1,7 +0,0 @@
1
- import type { CellularSite } from './cellular.model.js';
2
- interface Props {
3
- sites: CellularSite[];
4
- }
5
- declare const CellularChartsView: import("svelte").Component<Props, {}, "">;
6
- type CellularChartsView = ReturnType<typeof CellularChartsView>;
7
- export default CellularChartsView;