@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.
- package/dist/apps/antenna-pattern/components/AntennaControls.svelte +1 -106
- package/dist/apps/antenna-pattern/components/AntennaDiagrams.svelte +0 -36
- package/dist/apps/antenna-pattern/components/AntennaSettingsModal.svelte +0 -2
- package/dist/apps/antenna-pattern/components/PlotlyRadarChart.svelte +0 -22
- package/dist/apps/antenna-pattern/components/chart-engines/PolarAreaChart.svelte +0 -2
- package/dist/apps/antenna-pattern/components/chart-engines/PolarBarChart.svelte +0 -2
- package/dist/apps/antenna-pattern/components/chart-engines/PolarLineChart.svelte +0 -2
- package/dist/apps/site-check/SiteCheck.svelte +60 -80
- package/dist/apps/site-check/data-loader.d.ts +9 -6
- package/dist/apps/site-check/data-loader.js +2 -11
- package/dist/apps/site-check/helper.d.ts +3 -2
- package/dist/apps/site-check/helper.js +7 -5
- package/dist/apps/site-check/index.d.ts +1 -1
- package/dist/apps/site-check/transforms.d.ts +4 -2
- package/dist/apps/site-check/transforms.js +49 -10
- package/dist/core/Charts/GlobalControls.svelte +0 -4
- package/dist/core/Desktop/Grid/ResizeHandle.svelte +0 -7
- package/dist/core/Desktop/Grid/resizeStore.js +0 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.js +2 -0
- package/dist/map-v2/demo/DemoMap.svelte +0 -2
- package/dist/map-v2/demo/demo-cells.js +0 -1
- package/dist/map-v2/features/cells/layers/CellsLayer.svelte +7 -26
- package/dist/map-v2/features/cells/utils/cellTree.js +0 -29
- package/dist/map-v2/features/repeaters/layers/RepeaterLabelsLayer.svelte +3 -27
- package/dist/map-v2/features/repeaters/layers/RepeatersLayer.svelte +8 -25
- package/dist/map-v2/features/repeaters/utils/repeaterTree.js +0 -6
- package/dist/map-v2/features/sites/controls/SiteFilterControl.svelte +0 -8
- package/dist/map-v2/features/sites/utils/siteTreeUtils.js +0 -6
- package/dist/map-v3/core/components/Map.svelte +89 -0
- package/dist/map-v3/core/components/Map.svelte.d.ts +13 -0
- package/dist/map-v3/core/controls/FeatureSettingsControl.svelte +103 -0
- package/dist/map-v3/core/controls/FeatureSettingsControl.svelte.d.ts +15 -0
- package/dist/map-v3/core/controls/MapStyleControl.svelte +271 -0
- package/dist/map-v3/core/controls/MapStyleControl.svelte.d.ts +28 -0
- package/dist/map-v3/core/index.d.ts +3 -0
- package/dist/map-v3/core/index.js +3 -0
- package/dist/map-v3/core/stores/map.store.svelte.d.ts +8 -0
- package/dist/map-v3/core/stores/map.store.svelte.js +29 -0
- package/dist/map-v3/core/stores/viewport.store.svelte.d.ts +38 -0
- package/dist/map-v3/core/stores/viewport.store.svelte.js +107 -0
- package/dist/map-v3/demo/DemoMap.svelte +104 -0
- package/dist/map-v3/demo/DemoMap.svelte.d.ts +6 -0
- package/dist/map-v3/demo/demo-cells.d.ts +13 -0
- package/dist/map-v3/demo/demo-cells.js +130 -0
- package/dist/map-v3/demo/demo-data.d.ts +8 -0
- package/dist/map-v3/demo/demo-data.js +104 -0
- package/dist/map-v3/demo/demo-repeaters.d.ts +13 -0
- package/dist/map-v3/demo/demo-repeaters.js +73 -0
- package/dist/map-v3/features/cells/components/CellFilterControl.svelte +208 -0
- package/dist/map-v3/features/cells/components/CellFilterControl.svelte.d.ts +12 -0
- package/dist/map-v3/features/cells/components/CellSettingsPanel.svelte +229 -0
- package/dist/map-v3/features/cells/components/CellSettingsPanel.svelte.d.ts +7 -0
- package/dist/map-v3/features/cells/constants.d.ts +18 -0
- package/dist/map-v3/features/cells/constants.js +37 -0
- package/dist/map-v3/features/cells/layers/CellLabelsLayer.svelte +230 -0
- package/dist/map-v3/features/cells/layers/CellLabelsLayer.svelte.d.ts +11 -0
- package/dist/map-v3/features/cells/layers/CellsLayer.svelte +194 -0
- package/dist/map-v3/features/cells/layers/CellsLayer.svelte.d.ts +11 -0
- package/dist/map-v3/features/cells/layers/index.d.ts +2 -0
- package/dist/map-v3/features/cells/layers/index.js +2 -0
- package/dist/map-v3/features/cells/logic/geometry.d.ts +12 -0
- package/dist/map-v3/features/cells/logic/geometry.js +35 -0
- package/dist/map-v3/features/cells/logic/grouping.d.ts +18 -0
- package/dist/map-v3/features/cells/logic/grouping.js +30 -0
- package/dist/map-v3/features/cells/logic/tree-adapter.d.ts +11 -0
- package/dist/map-v3/features/cells/logic/tree-adapter.js +53 -0
- package/dist/map-v3/features/cells/stores/cell.data.svelte.d.ts +9 -0
- package/dist/map-v3/features/cells/stores/cell.data.svelte.js +16 -0
- package/dist/map-v3/features/cells/stores/cell.display.svelte.d.ts +25 -0
- package/dist/map-v3/features/cells/stores/cell.display.svelte.js +67 -0
- package/dist/map-v3/features/cells/stores/cell.registry.svelte.d.ts +23 -0
- package/dist/map-v3/features/cells/stores/cell.registry.svelte.js +68 -0
- package/dist/map-v3/features/cells/types.d.ts +62 -0
- package/dist/map-v3/features/cells/types.js +6 -0
- package/dist/map-v3/features/repeaters/components/RepeaterFilterControl.svelte +148 -0
- package/dist/map-v3/features/repeaters/components/RepeaterFilterControl.svelte.d.ts +12 -0
- package/dist/map-v3/features/repeaters/components/RepeaterSettingsPanel.svelte +209 -0
- package/dist/map-v3/features/repeaters/components/RepeaterSettingsPanel.svelte.d.ts +7 -0
- package/dist/map-v3/features/repeaters/layers/RepeaterLabelsLayer.svelte +177 -0
- package/dist/map-v3/features/repeaters/layers/RepeaterLabelsLayer.svelte.d.ts +11 -0
- package/dist/map-v3/features/repeaters/layers/RepeatersLayer.svelte +163 -0
- package/dist/map-v3/features/repeaters/layers/RepeatersLayer.svelte.d.ts +11 -0
- package/dist/map-v3/features/repeaters/logic/geometry.d.ts +3 -0
- package/dist/map-v3/features/repeaters/logic/geometry.js +23 -0
- package/dist/map-v3/features/repeaters/logic/grouping.d.ts +8 -0
- package/dist/map-v3/features/repeaters/logic/grouping.js +20 -0
- package/dist/map-v3/features/repeaters/logic/tree-adapter.d.ts +8 -0
- package/dist/map-v3/features/repeaters/logic/tree-adapter.js +43 -0
- package/dist/map-v3/features/repeaters/stores/repeater.data.svelte.d.ts +8 -0
- package/dist/map-v3/features/repeaters/stores/repeater.data.svelte.js +13 -0
- package/dist/map-v3/features/repeaters/stores/repeater.display.svelte.d.ts +21 -0
- package/dist/map-v3/features/repeaters/stores/repeater.display.svelte.js +64 -0
- package/dist/map-v3/features/repeaters/stores/repeater.registry.svelte.d.ts +23 -0
- package/dist/map-v3/features/repeaters/stores/repeater.registry.svelte.js +68 -0
- package/dist/map-v3/features/repeaters/types.d.ts +18 -0
- package/dist/map-v3/features/repeaters/types.js +1 -0
- package/dist/map-v3/features/sites/components/SiteFilterControl.svelte +119 -0
- package/dist/map-v3/features/sites/components/SiteFilterControl.svelte.d.ts +12 -0
- package/dist/map-v3/features/sites/components/SiteSettingsPanel.svelte +241 -0
- package/dist/map-v3/features/sites/components/SiteSettingsPanel.svelte.d.ts +7 -0
- package/dist/map-v3/features/sites/layers/SiteLabelsLayer.svelte +152 -0
- package/dist/map-v3/features/sites/layers/SiteLabelsLayer.svelte.d.ts +11 -0
- package/dist/map-v3/features/sites/layers/SitesLayer.svelte +132 -0
- package/dist/map-v3/features/sites/layers/SitesLayer.svelte.d.ts +11 -0
- package/dist/map-v3/features/sites/logic/tree-adapter.d.ts +9 -0
- package/dist/map-v3/features/sites/logic/tree-adapter.js +75 -0
- package/dist/map-v3/features/sites/stores/site.data.svelte.d.ts +8 -0
- package/dist/map-v3/features/sites/stores/site.data.svelte.js +40 -0
- package/dist/map-v3/features/sites/stores/site.display.svelte.d.ts +20 -0
- package/dist/map-v3/features/sites/stores/site.display.svelte.js +63 -0
- package/dist/map-v3/features/sites/stores/site.registry.svelte.d.ts +13 -0
- package/dist/map-v3/features/sites/stores/site.registry.svelte.js +83 -0
- package/dist/map-v3/features/sites/types.d.ts +12 -0
- package/dist/map-v3/features/sites/types.js +1 -0
- package/dist/map-v3/index.d.ts +26 -0
- package/dist/map-v3/index.js +31 -0
- package/dist/map-v3/shared/controls/MapControl.svelte +242 -0
- package/dist/map-v3/shared/controls/MapControl.svelte.d.ts +27 -0
- package/dist/map-v3/shared/index.d.ts +1 -0
- package/dist/map-v3/shared/index.js +1 -0
- 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={(
|
|
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: '
|
|
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
|
|
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
|
-
|
|
329
|
-
|
|
330
|
-
<
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
<
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
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' | '
|
|
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
|
-
*
|
|
22
|
-
* - For 2-level tree: level0 →
|
|
23
|
-
* - For
|
|
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 →
|
|
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 →
|
|
6
|
+
* Default tree grouping: Site → Band → Cell (3-level)
|
|
7
7
|
*/
|
|
8
8
|
export const defaultTreeGrouping = {
|
|
9
9
|
level0: 'site',
|
|
10
|
-
level1: '
|
|
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
|