@smartnet360/svelte-components 0.0.84 → 0.0.86

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 (122) hide show
  1. package/dist/apps/antenna-pattern/components/AntennaControls.svelte +1 -106
  2. package/dist/apps/antenna-pattern/components/AntennaDiagrams.svelte +0 -36
  3. package/dist/apps/antenna-pattern/components/AntennaSettingsModal.svelte +0 -2
  4. package/dist/apps/antenna-pattern/components/PlotlyRadarChart.svelte +0 -22
  5. package/dist/apps/antenna-pattern/components/chart-engines/PolarAreaChart.svelte +0 -2
  6. package/dist/apps/antenna-pattern/components/chart-engines/PolarBarChart.svelte +0 -2
  7. package/dist/apps/antenna-pattern/components/chart-engines/PolarLineChart.svelte +0 -2
  8. package/dist/apps/site-check/SiteCheck.svelte +60 -80
  9. package/dist/apps/site-check/data-loader.d.ts +9 -6
  10. package/dist/apps/site-check/data-loader.js +2 -11
  11. package/dist/apps/site-check/helper.d.ts +3 -2
  12. package/dist/apps/site-check/helper.js +7 -5
  13. package/dist/apps/site-check/index.d.ts +1 -1
  14. package/dist/apps/site-check/transforms.d.ts +4 -2
  15. package/dist/apps/site-check/transforms.js +49 -10
  16. package/dist/core/Charts/GlobalControls.svelte +0 -4
  17. package/dist/core/Desktop/Grid/ResizeHandle.svelte +0 -7
  18. package/dist/core/Desktop/Grid/resizeStore.js +0 -1
  19. package/dist/index.d.ts +1 -0
  20. package/dist/index.js +2 -0
  21. package/dist/map-v2/demo/DemoMap.svelte +0 -2
  22. package/dist/map-v2/demo/demo-cells.js +0 -1
  23. package/dist/map-v2/features/cells/layers/CellsLayer.svelte +7 -26
  24. package/dist/map-v2/features/cells/utils/cellTree.js +0 -29
  25. package/dist/map-v2/features/repeaters/layers/RepeaterLabelsLayer.svelte +3 -27
  26. package/dist/map-v2/features/repeaters/layers/RepeatersLayer.svelte +8 -25
  27. package/dist/map-v2/features/repeaters/utils/repeaterTree.js +0 -6
  28. package/dist/map-v2/features/sites/controls/SiteFilterControl.svelte +0 -8
  29. package/dist/map-v2/features/sites/utils/siteTreeUtils.js +0 -6
  30. package/dist/map-v3/core/components/Map.svelte +89 -0
  31. package/dist/map-v3/core/components/Map.svelte.d.ts +13 -0
  32. package/dist/map-v3/core/controls/FeatureSettingsControl.svelte +103 -0
  33. package/dist/map-v3/core/controls/FeatureSettingsControl.svelte.d.ts +15 -0
  34. package/dist/map-v3/core/controls/MapStyleControl.svelte +271 -0
  35. package/dist/map-v3/core/controls/MapStyleControl.svelte.d.ts +28 -0
  36. package/dist/map-v3/core/index.d.ts +3 -0
  37. package/dist/map-v3/core/index.js +3 -0
  38. package/dist/map-v3/core/stores/map.store.svelte.d.ts +8 -0
  39. package/dist/map-v3/core/stores/map.store.svelte.js +29 -0
  40. package/dist/map-v3/core/stores/viewport.store.svelte.d.ts +38 -0
  41. package/dist/map-v3/core/stores/viewport.store.svelte.js +107 -0
  42. package/dist/map-v3/demo/DemoMap.svelte +104 -0
  43. package/dist/map-v3/demo/DemoMap.svelte.d.ts +6 -0
  44. package/dist/map-v3/demo/demo-cells.d.ts +13 -0
  45. package/dist/map-v3/demo/demo-cells.js +130 -0
  46. package/dist/map-v3/demo/demo-data.d.ts +8 -0
  47. package/dist/map-v3/demo/demo-data.js +104 -0
  48. package/dist/map-v3/demo/demo-repeaters.d.ts +13 -0
  49. package/dist/map-v3/demo/demo-repeaters.js +73 -0
  50. package/dist/map-v3/features/cells/components/CellFilterControl.svelte +208 -0
  51. package/dist/map-v3/features/cells/components/CellFilterControl.svelte.d.ts +12 -0
  52. package/dist/map-v3/features/cells/components/CellSettingsPanel.svelte +229 -0
  53. package/dist/map-v3/features/cells/components/CellSettingsPanel.svelte.d.ts +7 -0
  54. package/dist/map-v3/features/cells/constants.d.ts +18 -0
  55. package/dist/map-v3/features/cells/constants.js +37 -0
  56. package/dist/map-v3/features/cells/layers/CellLabelsLayer.svelte +230 -0
  57. package/dist/map-v3/features/cells/layers/CellLabelsLayer.svelte.d.ts +11 -0
  58. package/dist/map-v3/features/cells/layers/CellsLayer.svelte +194 -0
  59. package/dist/map-v3/features/cells/layers/CellsLayer.svelte.d.ts +11 -0
  60. package/dist/map-v3/features/cells/layers/index.d.ts +2 -0
  61. package/dist/map-v3/features/cells/layers/index.js +2 -0
  62. package/dist/map-v3/features/cells/logic/geometry.d.ts +12 -0
  63. package/dist/map-v3/features/cells/logic/geometry.js +35 -0
  64. package/dist/map-v3/features/cells/logic/grouping.d.ts +18 -0
  65. package/dist/map-v3/features/cells/logic/grouping.js +30 -0
  66. package/dist/map-v3/features/cells/logic/tree-adapter.d.ts +11 -0
  67. package/dist/map-v3/features/cells/logic/tree-adapter.js +53 -0
  68. package/dist/map-v3/features/cells/stores/cell.data.svelte.d.ts +9 -0
  69. package/dist/map-v3/features/cells/stores/cell.data.svelte.js +16 -0
  70. package/dist/map-v3/features/cells/stores/cell.display.svelte.d.ts +25 -0
  71. package/dist/map-v3/features/cells/stores/cell.display.svelte.js +67 -0
  72. package/dist/map-v3/features/cells/stores/cell.registry.svelte.d.ts +23 -0
  73. package/dist/map-v3/features/cells/stores/cell.registry.svelte.js +68 -0
  74. package/dist/map-v3/features/cells/types.d.ts +62 -0
  75. package/dist/map-v3/features/cells/types.js +6 -0
  76. package/dist/map-v3/features/repeaters/components/RepeaterFilterControl.svelte +148 -0
  77. package/dist/map-v3/features/repeaters/components/RepeaterFilterControl.svelte.d.ts +12 -0
  78. package/dist/map-v3/features/repeaters/components/RepeaterSettingsPanel.svelte +209 -0
  79. package/dist/map-v3/features/repeaters/components/RepeaterSettingsPanel.svelte.d.ts +7 -0
  80. package/dist/map-v3/features/repeaters/layers/RepeaterLabelsLayer.svelte +177 -0
  81. package/dist/map-v3/features/repeaters/layers/RepeaterLabelsLayer.svelte.d.ts +11 -0
  82. package/dist/map-v3/features/repeaters/layers/RepeatersLayer.svelte +163 -0
  83. package/dist/map-v3/features/repeaters/layers/RepeatersLayer.svelte.d.ts +11 -0
  84. package/dist/map-v3/features/repeaters/logic/geometry.d.ts +3 -0
  85. package/dist/map-v3/features/repeaters/logic/geometry.js +23 -0
  86. package/dist/map-v3/features/repeaters/logic/grouping.d.ts +8 -0
  87. package/dist/map-v3/features/repeaters/logic/grouping.js +20 -0
  88. package/dist/map-v3/features/repeaters/logic/tree-adapter.d.ts +8 -0
  89. package/dist/map-v3/features/repeaters/logic/tree-adapter.js +43 -0
  90. package/dist/map-v3/features/repeaters/stores/repeater.data.svelte.d.ts +8 -0
  91. package/dist/map-v3/features/repeaters/stores/repeater.data.svelte.js +13 -0
  92. package/dist/map-v3/features/repeaters/stores/repeater.display.svelte.d.ts +21 -0
  93. package/dist/map-v3/features/repeaters/stores/repeater.display.svelte.js +64 -0
  94. package/dist/map-v3/features/repeaters/stores/repeater.registry.svelte.d.ts +23 -0
  95. package/dist/map-v3/features/repeaters/stores/repeater.registry.svelte.js +68 -0
  96. package/dist/map-v3/features/repeaters/types.d.ts +18 -0
  97. package/dist/map-v3/features/repeaters/types.js +1 -0
  98. package/dist/map-v3/features/sites/components/SiteFilterControl.svelte +119 -0
  99. package/dist/map-v3/features/sites/components/SiteFilterControl.svelte.d.ts +12 -0
  100. package/dist/map-v3/features/sites/components/SiteSettingsPanel.svelte +241 -0
  101. package/dist/map-v3/features/sites/components/SiteSettingsPanel.svelte.d.ts +7 -0
  102. package/dist/map-v3/features/sites/layers/SiteLabelsLayer.svelte +152 -0
  103. package/dist/map-v3/features/sites/layers/SiteLabelsLayer.svelte.d.ts +11 -0
  104. package/dist/map-v3/features/sites/layers/SitesLayer.svelte +132 -0
  105. package/dist/map-v3/features/sites/layers/SitesLayer.svelte.d.ts +11 -0
  106. package/dist/map-v3/features/sites/logic/tree-adapter.d.ts +9 -0
  107. package/dist/map-v3/features/sites/logic/tree-adapter.js +75 -0
  108. package/dist/map-v3/features/sites/stores/site.data.svelte.d.ts +8 -0
  109. package/dist/map-v3/features/sites/stores/site.data.svelte.js +40 -0
  110. package/dist/map-v3/features/sites/stores/site.display.svelte.d.ts +20 -0
  111. package/dist/map-v3/features/sites/stores/site.display.svelte.js +63 -0
  112. package/dist/map-v3/features/sites/stores/site.registry.svelte.d.ts +13 -0
  113. package/dist/map-v3/features/sites/stores/site.registry.svelte.js +83 -0
  114. package/dist/map-v3/features/sites/types.d.ts +12 -0
  115. package/dist/map-v3/features/sites/types.js +1 -0
  116. package/dist/map-v3/index.d.ts +26 -0
  117. package/dist/map-v3/index.js +31 -0
  118. package/dist/map-v3/shared/controls/MapControl.svelte +242 -0
  119. package/dist/map-v3/shared/controls/MapControl.svelte.d.ts +27 -0
  120. package/dist/map-v3/shared/index.d.ts +1 -0
  121. package/dist/map-v3/shared/index.js +1 -0
  122. package/package.json +1 -1
@@ -56,29 +56,15 @@
56
56
  // Get available electrical tilts from antennas with the selected name and frequency
57
57
  let availableElectricalTilts = $state<string[]>(['0']);
58
58
  $effect(() => {
59
- console.log('🔄 [TILTS] Effect triggered - updating available tilts:', {
60
- antenna: internalSelectedAntenna?.name,
61
- frequency: selectedFrequency,
62
- currentTilts: availableElectricalTilts,
63
- timestamp: new Date().toISOString()
64
- });
65
-
66
59
  let newTilts: string[] = ['0'];
67
60
 
68
61
  if (internalSelectedAntenna) {
69
62
  // Find ALL antennas with the same name and frequency to collect all electrical tilts
70
63
  let sameName = antennas.filter(a => a.name === internalSelectedAntenna!.name);
71
- console.log('🔍 [TILTS] Found antennas with same name:', sameName.length);
72
64
 
73
65
  // If frequency is selected, filter by it
74
66
  if (selectedFrequency) {
75
- const beforeFilter = sameName.length;
76
67
  sameName = sameName.filter(a => a.frequency === selectedFrequency);
77
- console.log('🔍 [TILTS] After frequency filter:', {
78
- before: beforeFilter,
79
- after: sameName.length,
80
- frequency: selectedFrequency
81
- });
82
68
  }
83
69
 
84
70
  const allTilts = new Set<string>();
@@ -96,14 +82,6 @@
96
82
 
97
83
  // Convert to sorted array
98
84
  newTilts = Array.from(allTilts).sort((a, b) => parseFloat(a) - parseFloat(b));
99
-
100
- console.log('✅ [TILTS] Available tilts calculated:', {
101
- from: availableElectricalTilts,
102
- to: newTilts,
103
- changed: JSON.stringify(availableElectricalTilts) !== JSON.stringify(newTilts)
104
- });
105
- } else {
106
- console.log('ℹ️ [TILTS] No antenna selected, using default tilts');
107
85
  }
108
86
 
109
87
  // Only update if actually changed to prevent infinite loops
@@ -141,34 +119,12 @@
141
119
 
142
120
  // Handle frequency selection
143
121
  function handleFrequencyChange(frequency: number) {
144
- console.log('🔄 [FREQ] handleFrequencyChange called:', {
145
- requestedFrequency: frequency,
146
- currentSelectedFrequency: selectedFrequency,
147
- currentAntenna: internalSelectedAntenna?.name,
148
- currentTiltIndex: internalElectricalTiltIndex,
149
- availableTilts: availableElectricalTilts,
150
- timestamp: new Date().toISOString()
151
- });
152
-
153
- const previousFrequency = selectedFrequency;
154
122
  selectedFrequency = frequency;
155
123
 
156
- console.log('📝 [FREQ] Frequency state updated:', {
157
- from: previousFrequency,
158
- to: selectedFrequency,
159
- changed: previousFrequency !== selectedFrequency
160
- });
161
-
162
124
  if (internalSelectedAntenna) {
163
125
  // STEP 1: Calculate available tilts for the new frequency
164
126
  let sameName = antennas.filter(a => a.name === internalSelectedAntenna!.name && a.frequency === frequency);
165
127
 
166
- console.log('🔍 [FREQ] Found antennas with same name and new frequency:', {
167
- antennaName: internalSelectedAntenna.name,
168
- frequency: frequency,
169
- count: sameName.length
170
- });
171
-
172
128
  const allTilts = new Set<string>();
173
129
  sameName.forEach(antenna => {
174
130
  if (antenna.tilt) {
@@ -183,11 +139,6 @@
183
139
 
184
140
  const newAvailableTilts = Array.from(allTilts).sort((a, b) => parseFloat(a) - parseFloat(b));
185
141
 
186
- console.log('🔧 [FREQ] Calculated tilts for new frequency:', {
187
- availableTilts: newAvailableTilts,
188
- hasZeroTilt: newAvailableTilts.includes('0')
189
- });
190
-
191
142
  // STEP 2: Determine the best tilt index to use
192
143
  let bestTiltIndex = 0;
193
144
  let bestTiltValue = '0';
@@ -203,12 +154,6 @@
203
154
  }
204
155
  }
205
156
 
206
- console.log('🎯 [FREQ] Selected best tilt:', {
207
- index: bestTiltIndex,
208
- value: bestTiltValue,
209
- reason: newAvailableTilts.includes('0') ? 'preferred 0 tilt' : 'first available tilt'
210
- });
211
-
212
157
  // STEP 3: Find antenna with the new frequency and best tilt
213
158
  const antennaWithNewFreq = antennas.find(antenna => {
214
159
  if (antenna.name !== internalSelectedAntenna!.name) return false;
@@ -224,60 +169,19 @@
224
169
  }
225
170
  return bestTiltValue === '0';
226
171
  });
227
-
228
- console.log('🎯 [FREQ] Antenna search result:', {
229
- found: !!antennaWithNewFreq,
230
- searchCriteria: {
231
- name: internalSelectedAntenna.name,
232
- frequency: frequency,
233
- tiltValue: bestTiltValue
234
- },
235
- antenna: antennaWithNewFreq ? {
236
- name: antennaWithNewFreq.name,
237
- frequency: antennaWithNewFreq.frequency,
238
- tilt: antennaWithNewFreq.tilt
239
- } : null
240
- });
241
172
 
242
173
  if (antennaWithNewFreq) {
243
- const previousAntenna = internalSelectedAntenna;
244
- const previousTiltIndex = internalElectricalTiltIndex;
245
-
246
174
  internalSelectedAntenna = antennaWithNewFreq;
247
175
  internalElectricalTiltIndex = bestTiltIndex;
248
176
 
249
- console.log('✅ [FREQ] Antenna and tilt updated:', {
250
- antenna: {
251
- from: {
252
- name: previousAntenna.name,
253
- frequency: previousAntenna.frequency,
254
- tilt: previousAntenna.tilt
255
- },
256
- to: {
257
- name: antennaWithNewFreq.name,
258
- frequency: antennaWithNewFreq.frequency,
259
- tilt: antennaWithNewFreq.tilt
260
- }
261
- },
262
- tiltIndex: {
263
- from: previousTiltIndex,
264
- to: bestTiltIndex
265
- }
266
- });
267
-
268
- console.log('📞 [FREQ] Calling onAntennaChange callback');
269
177
  onAntennaChange?.(antennaWithNewFreq);
270
-
271
- console.log('📞 [FREQ] Calling onElectricalTiltChange callback with index', bestTiltIndex);
272
178
  onElectricalTiltChange?.(bestTiltIndex);
273
179
  } else {
274
- console.warn('⚠️ [FREQ] No antenna found for frequency, keeping current antenna');
275
180
  // Reset tilt to 0 as fallback
276
181
  internalElectricalTiltIndex = 0;
277
182
  onElectricalTiltChange?.(0);
278
183
  }
279
184
  } else {
280
- console.log('ℹ️ [FREQ] No current antenna selected');
281
185
  internalElectricalTiltIndex = 0;
282
186
  onElectricalTiltChange?.(0);
283
187
  }
@@ -498,16 +402,7 @@
498
402
  <button
499
403
  type="button"
500
404
  class="btn btn-sm {selectedFrequency === freq ? 'btn-primary' : 'btn-outline-secondary'}"
501
- onclick={(e) => {
502
- console.log('🖱️ [FREQ] Button clicked:', {
503
- frequency: freq,
504
- currentSelectedFrequency: selectedFrequency,
505
- isAlreadySelected: selectedFrequency === freq,
506
- clickEvent: e.type,
507
- timestamp: new Date().toISOString()
508
- });
509
- handleFrequencyChange(freq);
510
- }}
405
+ onclick={() => handleFrequencyChange(freq)}
511
406
  >
512
407
  {freq} MHz
513
408
  </button>
@@ -39,34 +39,12 @@
39
39
 
40
40
  // Handle antenna selection from controls
41
41
  function handleAntenna1Change(antenna: Antenna | null) {
42
- console.log('📥 [PARENT] handleAntenna1Change called:', {
43
- antenna: antenna ? {
44
- name: antenna.name,
45
- frequency: antenna.frequency,
46
- tilt: antenna.tilt
47
- } : null,
48
- previousAntenna: selectedAntenna ? {
49
- name: selectedAntenna.name,
50
- frequency: selectedAntenna.frequency,
51
- tilt: selectedAntenna.tilt
52
- } : null,
53
- timestamp: new Date().toISOString()
54
- });
55
-
56
42
  selectedAntenna = antenna;
57
43
  if (antenna) {
58
44
  // Update available electrical tilts based on selected antenna
59
- const previousTilts = [...availableElectricalTilts];
60
45
  availableElectricalTilts = antenna.tilt ?
61
46
  antenna.tilt.split(',').map(t => t.trim()) :
62
47
  ['0', '2', '4', '6', '8'];
63
-
64
- console.log('🔧 [PARENT] Updated available tilts and reset positions:', {
65
- from: previousTilts,
66
- to: availableElectricalTilts,
67
- electricalTiltReset: ant1ElectricalTilt,
68
- mechanicalTiltReset: ant1MechanicalTilt
69
- });
70
48
 
71
49
  ant1ElectricalTilt = 0;
72
50
  ant1MechanicalTilt = 0;
@@ -83,22 +61,10 @@
83
61
 
84
62
  // Handle electrical tilt changes from controls
85
63
  function handleTilt1Change(tilt: number) {
86
- console.log('📥 [PARENT] handleTilt1Change called:', {
87
- tilt,
88
- previousTilt: ant1ElectricalTilt,
89
- changed: tilt !== ant1ElectricalTilt,
90
- timestamp: new Date().toISOString()
91
- });
92
64
  ant1ElectricalTilt = tilt;
93
65
  }
94
66
 
95
67
  function handleTilt2Change(tilt: number) {
96
- console.log('📥 [PARENT] handleTilt2Change called:', {
97
- tilt,
98
- previousTilt: ant2ElectricalTilt,
99
- changed: tilt !== ant2ElectricalTilt,
100
- timestamp: new Date().toISOString()
101
- });
102
68
  ant2ElectricalTilt = tilt;
103
69
  }
104
70
 
@@ -140,8 +106,6 @@
140
106
  ant2ElectricalTilt = 0;
141
107
  ant2MechanicalTilt = 0;
142
108
  }
143
-
144
- console.log('Data refreshed from settings modal');
145
109
  } catch (error) {
146
110
  console.error('Failed to refresh data:', error);
147
111
  }
@@ -29,7 +29,6 @@
29
29
  async function handleExport() {
30
30
  try {
31
31
  await exportAntennas();
32
- console.log('Data exported successfully');
33
32
  } catch (error) {
34
33
  console.error('Export failed:', error);
35
34
  }
@@ -46,7 +45,6 @@
46
45
  await clearAllAntennas();
47
46
  showClearConfirm = false;
48
47
  handleDataRefresh();
49
- console.log('All data cleared successfully');
50
48
  } catch (error) {
51
49
  console.error('Clear data failed:', error);
52
50
  }
@@ -63,21 +63,9 @@
63
63
 
64
64
  async function initializeChart() {
65
65
  if (!Plotly || !chartDiv || !data.length) {
66
- console.log('PlotlyRadarChart - Cannot initialize:', {
67
- hasPlotly: !!Plotly,
68
- hasChartDiv: !!chartDiv,
69
- dataLength: data.length
70
- });
71
66
  return;
72
67
  }
73
68
 
74
- console.log('PlotlyRadarChart - Initializing with data:', {
75
- dataCount: data.length,
76
- sampleData: data[0],
77
- title,
78
- showSliders
79
- });
80
-
81
69
  const { data: plotData, layout, config } = createPlotlyRadarConfig(
82
70
  data,
83
71
  title,
@@ -89,7 +77,6 @@
89
77
  const sliders = createSliders();
90
78
  if (sliders.length > 0) {
91
79
  layout.sliders = sliders;
92
- console.log('Added sliders:', sliders.length);
93
80
  }
94
81
 
95
82
  // Add pattern toggle if requested
@@ -97,13 +84,9 @@
97
84
  layout.updatemenus = [createPatternToggleMenu()];
98
85
  }
99
86
 
100
- console.log('PlotlyRadarChart - Final layout:', layout);
101
- console.log('PlotlyRadarChart - Plot data:', plotData);
102
-
103
87
  try {
104
88
  await Plotly.newPlot(chartDiv, plotData, layout, config);
105
89
  chartInitialized = true;
106
- console.log('PlotlyRadarChart - Successfully initialized');
107
90
 
108
91
  // Set up event listeners using Plotly's event system
109
92
  if (chartDiv) {
@@ -172,16 +155,12 @@
172
155
  }
173
156
 
174
157
  function handleSliderChange(eventData: any) {
175
- console.log('Slider change event:', eventData);
176
-
177
158
  // Handle slider changes and notify parent
178
159
  if (onTiltChange && eventData && eventData.detail) {
179
160
  const step = eventData.detail.step;
180
161
  const sliderIndex = eventData.detail.slider.active;
181
162
  const slider = eventData.detail.slider;
182
163
 
183
- console.log('Slider details:', { step, sliderIndex, slider });
184
-
185
164
  // Determine which antenna slider was changed based on position or other identifier
186
165
  const antennaIndex = slider.x < 0.3 ? 1 : 2;
187
166
  onTiltChange(antennaIndex, sliderIndex);
@@ -190,7 +169,6 @@
190
169
 
191
170
  function handleButtonClick(eventData: any) {
192
171
  // Handle button clicks (pattern toggle)
193
- console.log('Button clicked:', eventData);
194
172
  }
195
173
 
196
174
  // Export methods for parent components
@@ -45,7 +45,6 @@
45
45
  if (browser) {
46
46
  try {
47
47
  Plotly = await import('plotly.js-dist-min');
48
- console.log('Plotly loaded for polar area chart');
49
48
  await initializeChart();
50
49
  } catch (error) {
51
50
  console.error('Failed to load Plotly:', error);
@@ -91,7 +90,6 @@
91
90
  try {
92
91
  await Plotly.newPlot(chartDiv, data, layout, config);
93
92
  chartInitialized = true;
94
- console.log('Polar area chart initialized');
95
93
  } catch (error) {
96
94
  console.error('Failed to create polar area chart:', error);
97
95
  }
@@ -45,7 +45,6 @@
45
45
  if (browser) {
46
46
  try {
47
47
  Plotly = await import('plotly.js-dist-min');
48
- console.log('Plotly loaded for polar bar chart');
49
48
  await initializeChart();
50
49
  } catch (error) {
51
50
  console.error('Failed to load Plotly:', error);
@@ -90,7 +89,6 @@
90
89
  try {
91
90
  await Plotly.newPlot(chartDiv, data, layout, config);
92
91
  chartInitialized = true;
93
- console.log('Polar bar chart initialized');
94
92
  } catch (error) {
95
93
  console.error('Failed to create polar bar chart:', error);
96
94
  }
@@ -45,7 +45,6 @@
45
45
  if (browser) {
46
46
  try {
47
47
  Plotly = await import('plotly.js-dist-min');
48
- console.log('Plotly loaded for polar line chart');
49
48
  await initializeChart();
50
49
  } catch (error) {
51
50
  console.error('Failed to load Plotly:', error);
@@ -91,7 +90,6 @@
91
90
  try {
92
91
  await Plotly.newPlot(chartDiv, data, layout, config);
93
92
  chartInitialized = true;
94
- console.log('Polar line chart initialized');
95
93
  } catch (error) {
96
94
  console.error('Failed to create polar line chart:', error);
97
95
  }
@@ -3,7 +3,7 @@
3
3
  <script lang="ts">
4
4
  import { TreeView, createTreeStore } from '../../core/TreeView';
5
5
  import { ChartComponent, type Layout, type CellStylingConfig } from '../../core/Charts';
6
- import { buildTreeNodes, filterChartData, transformChartData, type CellTrafficRecord, defaultCellStyling, type TreeGroupingConfig, type TreeGroupField, defaultTreeGrouping } from './index';
6
+ import { buildTreeNodes, filterChartData, transformChartData, type CellTrafficRecord, defaultCellStyling, type TreeGroupingConfig, type TreeGroupField, type ColorDimension, defaultTreeGrouping } from './index';
7
7
  import { expandLayoutForCells } from './helper';
8
8
  import { log } from '../../core/logger';
9
9
  import type {ChartMarker, Mode } from '../../index.js';
@@ -58,55 +58,38 @@
58
58
  // Internal state for current grouping
59
59
  let treeGrouping = $state<TreeGroupingConfig>(initialGrouping);
60
60
 
61
+ // Color dimension state (defaults to 'band' for semantic RF characteristics)
62
+ let colorDimension = $state<ColorDimension>('band');
63
+
61
64
  // Available field options for grouping levels
62
65
  const fieldOptions: { value: TreeGroupField; label: string }[] = [
63
66
  { value: 'site', label: 'Site' },
64
67
  { value: 'band', label: 'Band' },
65
68
  { value: 'azimuth', label: 'Azimuth' },
66
- { value: 'cell', label: 'Cell' }
69
+ { value: 'sector', label: 'Sector' }
67
70
  ];
68
71
 
69
72
  // Handlers for level changes
70
73
  function handleLevel0Change(value: TreeGroupField) {
71
74
  // Clear level1 if it conflicts with new level0
72
75
  const newLevel1 = treeGrouping.level1 === value ? null : treeGrouping.level1;
73
- // Clear level2 if it conflicts with new level0
74
- let newLevel2 = treeGrouping.level2;
75
- if (newLevel2 !== null && newLevel2 !== 'cell' && newLevel2 === value) {
76
- newLevel2 = null;
77
- }
78
76
  treeGrouping = {
79
77
  level0: value,
80
- level1: newLevel1,
81
- level2: newLevel2
78
+ level1: newLevel1
82
79
  };
83
80
  }
84
81
 
85
82
  function handleLevel1Change(value: TreeGroupField | 'none') {
86
83
  const newLevel1 = value === 'none' ? null : value;
87
- // Clear level2 if it conflicts with new level1
88
- let newLevel2 = treeGrouping.level2;
89
- if (newLevel2 !== null && newLevel2 !== 'cell' && newLevel2 === newLevel1) {
90
- newLevel2 = null;
91
- }
92
84
  treeGrouping = {
93
85
  level0: treeGrouping.level0,
94
- level1: newLevel1,
95
- level2: newLevel2
86
+ level1: newLevel1
96
87
  };
97
88
  }
98
89
 
99
90
  // Get available options for level1 (exclude level0)
100
91
  let availableLevel1Options = $derived.by(() => {
101
92
  return fieldOptions.filter(opt => opt.value !== treeGrouping.level0);
102
- });
103
-
104
- // Get available options for level2 (exclude level0 and level1)
105
- let availableLevel2Options = $derived.by(() => {
106
- return fieldOptions.filter(opt =>
107
- opt.value !== treeGrouping.level0 &&
108
- opt.value !== treeGrouping.level1
109
- );
110
93
  }); let treeStore = $state<ReturnType<typeof createTreeStore> | null>(null);
111
94
 
112
95
  // Rebuild tree whenever treeGrouping changes
@@ -174,16 +157,17 @@
174
157
 
175
158
  // Expand layout based on selected cells and chosen base layout
176
159
  let chartLayout = $derived.by(() => {
177
- // Pass cellStyling and treeGrouping - helper will decide per-section whether to use styling,
178
- // and generate appropriate labels based on grouping
179
- const expanded = expandLayoutForCells(selectedBaseLayout, filteredData, treeGrouping, cellStyling);
160
+ // Pass cellStyling, treeGrouping, and colorDimension - helper will decide per-section whether to use styling,
161
+ // and generate appropriate labels based on grouping and colors based on colorDimension
162
+ const expanded = expandLayoutForCells(selectedBaseLayout, filteredData, treeGrouping, colorDimension, cellStyling);
180
163
  log('📐 Chart Layout:', {
181
164
  layoutName: selectedBaseLayout.layoutName,
182
165
  layoutDefaultColors: selectedBaseLayout.useDefaultChartColors ?? false,
183
166
  sectionsCount: expanded.sections.length,
184
167
  totalCharts: expanded.sections.reduce((sum, s) => sum + s.charts.length, 0),
185
168
  firstSection: expanded.sections[0],
186
- grouping: treeGrouping
169
+ grouping: treeGrouping,
170
+ colorDimension
187
171
  });
188
172
  return expanded;
189
173
  });
@@ -325,60 +309,56 @@
325
309
  <div class="p-3 border-bottom flex-shrink-0">
326
310
  <div class="small fw-semibold mb-2">Tree Grouping</div>
327
311
 
328
- <!-- Level 0 (Mandatory) -->
329
- <div class="mb-2">
330
- <label for="level0Select" class="form-label small mb-1">Level 0 (Root)</label>
331
- <select
332
- id="level0Select"
333
- class="form-select form-select-sm"
334
- value={treeGrouping.level0}
335
- onchange={(e) => handleLevel0Change(e.currentTarget.value as TreeGroupField)}
336
- >
337
- {#each fieldOptions as option}
338
- <option value={option.value}>{option.label}</option>
339
- {/each}
340
- </select>
341
- </div>
342
-
343
- <!-- Level 1 (Optional) -->
344
- <div class="mb-2">
345
- <label for="level1Select" class="form-label small mb-1">Level 1 (Optional)</label>
346
- <select
347
- id="level1Select"
348
- class="form-select form-select-sm"
349
- value={treeGrouping.level1 ?? 'none'}
350
- onchange={(e) => handleLevel1Change(e.currentTarget.value as TreeGroupField | 'none')}
351
- >
352
- <option value="none">None</option>
353
- {#each availableLevel1Options as option}
354
- <option value={option.value}>{option.label}</option>
355
- {/each}
356
- </select>
312
+ <div class="row g-2 mb-2">
313
+ <!-- Level 0 (Mandatory) -->
314
+ <div class="col-4">
315
+ <label for="level0Select" class="form-label small mb-1">Level 0</label>
316
+ <select
317
+ id="level0Select"
318
+ class="form-select form-select-sm"
319
+ value={treeGrouping.level0}
320
+ onchange={(e) => handleLevel0Change(e.currentTarget.value as TreeGroupField)}
321
+ >
322
+ {#each fieldOptions as option}
323
+ <option value={option.value}>{option.label}</option>
324
+ {/each}
325
+ </select>
326
+ </div>
327
+
328
+ <!-- Level 1 (Optional) -->
329
+ <div class="col-4">
330
+ <label for="level1Select" class="form-label small mb-1">Level 1</label>
331
+ <select
332
+ id="level1Select"
333
+ class="form-select form-select-sm"
334
+ value={treeGrouping.level1 ?? 'none'}
335
+ onchange={(e) => handleLevel1Change(e.currentTarget.value as TreeGroupField | 'none')}
336
+ >
337
+ <option value="none">None</option>
338
+ {#each availableLevel1Options as option}
339
+ <option value={option.value}>{option.label}</option>
340
+ {/each}
341
+ </select>
342
+ </div>
343
+
344
+ <!-- Color By -->
345
+ <div class="col-4">
346
+ <label for="colorDimensionSelect" class="form-label small mb-1">Color By</label>
347
+ <select
348
+ id="colorDimensionSelect"
349
+ class="form-select form-select-sm"
350
+ value={colorDimension}
351
+ onchange={(e) => {
352
+ colorDimension = e.currentTarget.value as ColorDimension;
353
+ log('🎨 Color dimension changed:', colorDimension);
354
+ }}
355
+ >
356
+ <option value="band">Band</option>
357
+ <option value="site">Site</option>
358
+ </select>
359
+ </div>
357
360
  </div>
358
361
 
359
- <!-- Level 2 (Optional) -->
360
- <div class="mb-0">
361
- <label for="level2Select" class="form-label small mb-1">Level 2 (Optional)</label>
362
- <select
363
- id="level2Select"
364
- class="form-select form-select-sm"
365
- value={treeGrouping.level2 ?? 'none'}
366
- onchange={(e) => {
367
- const value = e.currentTarget.value;
368
- treeGrouping = {
369
- level0: treeGrouping.level0,
370
- level1: treeGrouping.level1,
371
- level2: value === 'none' ? null : (value as 'cell')
372
- };
373
- }}
374
- >
375
- <option value="none">None</option>
376
- <option value="cell">Cell</option>
377
- {#each availableLevel2Options as option}
378
- <option value={option.value}>{option.label}</option>
379
- {/each}
380
- </select>
381
- </div>
382
362
  </div>
383
363
  {/if}
384
364
  {/if} <!-- Tree View -->
@@ -14,21 +14,24 @@ export interface CellTrafficRecord {
14
14
  /**
15
15
  * Tree grouping field types
16
16
  */
17
- export type TreeGroupField = 'site' | 'azimuth' | 'band' | 'cell';
17
+ export type TreeGroupField = 'site' | 'azimuth' | 'band' | 'sector';
18
+ /**
19
+ * Color dimension types - determines which field is used for chart coloring
20
+ */
21
+ export type ColorDimension = 'site' | 'band';
18
22
  /**
19
23
  * Configuration for tree hierarchy grouping
20
24
  * Defines which fields appear at each level of the tree
21
- * - For 3-level tree: level0 level1 level2
22
- * - For 2-level tree: level0 → level1 (set level2 to null)
23
- * - For 1-level tree: level0 only (set level1 and level2 to null)
25
+ * Cells are always the leaf nodes (implicit, not configured)
26
+ * - For 2-level tree: level0 → cell (set level1 to null)
27
+ * - For 3-level tree: level0 level1 cell
24
28
  */
25
29
  export interface TreeGroupingConfig {
26
30
  level0: TreeGroupField;
27
31
  level1: TreeGroupField | null;
28
- level2: TreeGroupField | 'cell' | null;
29
32
  }
30
33
  /**
31
- * Default tree grouping: Site → Azimuth → Cell (3-level)
34
+ * Default tree grouping: Site → Band → Cell (3-level)
32
35
  */
33
36
  export declare const defaultTreeGrouping: TreeGroupingConfig;
34
37
  /**
@@ -3,12 +3,11 @@
3
3
  * Loads and parses cell_traffic_with_band.csv
4
4
  */
5
5
  /**
6
- * Default tree grouping: Site → Azimuth → Cell (3-level)
6
+ * Default tree grouping: Site → Band → Cell (3-level)
7
7
  */
8
8
  export const defaultTreeGrouping = {
9
9
  level0: 'site',
10
- level1: 'azimuth',
11
- level2: 'cell'
10
+ level1: 'band'
12
11
  };
13
12
  /**
14
13
  * Load cell traffic data from CSV file
@@ -20,14 +19,6 @@ export async function loadCellTrafficData() {
20
19
  }
21
20
  const text = await response.text();
22
21
  const records = parseCsvData(text);
23
- // Log sample of converted dates for debugging
24
- if (records.length > 0) {
25
- console.log('📅 Sample date conversions:', {
26
- first: records[0].date,
27
- last: records[records.length - 1].date,
28
- totalRecords: records.length
29
- });
30
- }
31
22
  return records;
32
23
  }
33
24
  /**
@@ -1,5 +1,5 @@
1
1
  import type { Layout, CellStylingConfig } from '../../core/Charts';
2
- import type { CellTrafficRecord, TreeGroupingConfig } from './';
2
+ import type { CellTrafficRecord, TreeGroupingConfig, ColorDimension } from './';
3
3
  import { type StackGroupMode } from './transforms.js';
4
4
  /**
5
5
  * Expand base layout configuration with dynamic KPIs based on selected cells
@@ -8,11 +8,12 @@ import { type StackGroupMode } from './transforms.js';
8
8
  * @param baseLayout - The base layout configuration from JSON
9
9
  * @param data - Filtered cell traffic records for selected cells
10
10
  * @param grouping - Current tree grouping configuration (determines label format)
11
+ * @param colorDimension - Which field to use for coloring (site or band)
11
12
  * @param stylingConfig - Optional cell styling configuration (band colors, sector line styles)
12
13
  * @param stackGroupMode - Optional stackgroup strategy for stacked charts (default: 'none' = single stack)
13
14
  * @returns Expanded layout with cell-specific KPIs
14
15
  */
15
- export declare function expandLayoutForCells(baseLayout: Layout, data: CellTrafficRecord[], grouping: TreeGroupingConfig, stylingConfig?: CellStylingConfig, stackGroupMode?: StackGroupMode): Layout;
16
+ export declare function expandLayoutForCells(baseLayout: Layout, data: CellTrafficRecord[], grouping: TreeGroupingConfig, colorDimension: ColorDimension, stylingConfig?: CellStylingConfig, stackGroupMode?: StackGroupMode): Layout;
16
17
  /**
17
18
  * Extract base metric names from a layout configuration
18
19
  * Returns unique metric rawNames that need to be pivoted