@smartnet360/svelte-components 0.0.133 → 0.0.135
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/core/CellHistory/CellHistoryPanel.svelte +178 -0
- package/dist/core/CellHistory/CellHistoryPanel.svelte.d.ts +4 -0
- package/dist/core/CellHistory/column-config.d.ts +26 -0
- package/dist/core/CellHistory/column-config.js +120 -0
- package/dist/core/CellHistory/index.d.ts +9 -0
- package/dist/core/CellHistory/index.js +10 -0
- package/dist/core/CellHistory/transformers.d.ts +16 -0
- package/dist/core/CellHistory/transformers.js +76 -0
- package/dist/core/CellHistory/types.d.ts +54 -0
- package/dist/core/CellHistory/types.js +6 -0
- package/dist/core/CellTable/CellHistoryDemo.svelte +1 -0
- package/dist/core/CellTable/CellTable.svelte +7 -5
- package/dist/core/CellTable/CellTablePanel.svelte +82 -14
- package/dist/core/CellTable/CellTablePanel.svelte.d.ts +2 -0
- package/dist/core/CellTable/column-config.js +46 -58
- package/dist/core/CellTableV2/CellTable.svelte +601 -0
- package/dist/core/CellTableV2/CellTable.svelte.d.ts +43 -0
- package/dist/core/CellTableV2/CellTablePanel.svelte +685 -0
- package/dist/core/CellTableV2/CellTablePanel.svelte.d.ts +98 -0
- package/dist/core/CellTableV2/CellTableToolbar.svelte +322 -0
- package/dist/core/CellTableV2/CellTableToolbar.svelte.d.ts +59 -0
- package/dist/core/CellTableV2/ColumnPicker.svelte +214 -0
- package/dist/core/CellTableV2/ColumnPicker.svelte.d.ts +26 -0
- package/dist/core/CellTableV2/column-config.d.ts +120 -0
- package/dist/core/CellTableV2/column-config.js +671 -0
- package/dist/core/CellTableV2/composables/index.d.ts +12 -0
- package/dist/core/CellTableV2/composables/index.js +9 -0
- package/dist/core/CellTableV2/composables/useColumnVisibility.svelte.d.ts +45 -0
- package/dist/core/CellTableV2/composables/useColumnVisibility.svelte.js +98 -0
- package/dist/core/CellTableV2/composables/usePersistence.svelte.d.ts +28 -0
- package/dist/core/CellTableV2/composables/usePersistence.svelte.js +101 -0
- package/dist/core/CellTableV2/composables/useScrollSpy.svelte.d.ts +44 -0
- package/dist/core/CellTableV2/composables/useScrollSpy.svelte.js +91 -0
- package/dist/core/CellTableV2/index.d.ts +12 -0
- package/dist/core/CellTableV2/index.js +14 -0
- package/dist/core/CellTableV2/types.d.ts +172 -0
- package/dist/core/CellTableV2/types.js +6 -0
- package/dist/core/index.d.ts +2 -0
- package/dist/core/index.js +5 -0
- package/package.json +1 -1
|
@@ -0,0 +1,671 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* CellTable - Column Configuration
|
|
3
|
+
*
|
|
4
|
+
* Defines column definitions, presets, and formatters for the cell table
|
|
5
|
+
*/
|
|
6
|
+
/**
|
|
7
|
+
* Default technology colors (Bootstrap-aligned)
|
|
8
|
+
* 2G: Yellow, 4G: Purple, 5G: Green
|
|
9
|
+
*/
|
|
10
|
+
export const DEFAULT_TECH_COLORS = {
|
|
11
|
+
'2G': '#ffc107', // Yellow
|
|
12
|
+
'3G': '#0d6efd', // primary blue
|
|
13
|
+
'4G': '#9333ea', // Purple
|
|
14
|
+
'5G': '#22c55e', // Green
|
|
15
|
+
'LTE': '#9333ea', // Purple (same as 4G)
|
|
16
|
+
'NR': '#22c55e', // Green (same as 5G)
|
|
17
|
+
};
|
|
18
|
+
/**
|
|
19
|
+
* Default status colors (Bootstrap-aligned)
|
|
20
|
+
*/
|
|
21
|
+
export const DEFAULT_STATUS_COLORS = {
|
|
22
|
+
'On_Air': '#198754', // success green
|
|
23
|
+
'On_Air_UNDER_CONSTRUCTION': '#4ce207ff', // warning yellow
|
|
24
|
+
'On_Air_Locked': '#e04001ff', // info cyan
|
|
25
|
+
'RF_Plan_Ready': '#e69603ff', // primary blue
|
|
26
|
+
'Re-Planned_RF_Plan_Ready': '#c1a342ff', // purple
|
|
27
|
+
'Tavlati_RF_Plan_Ready': '#25ddfdff', // orange
|
|
28
|
+
};
|
|
29
|
+
/**
|
|
30
|
+
* Frequency band colors
|
|
31
|
+
* GSM: Yellow shades (darker = higher freq)
|
|
32
|
+
* LTE: Purple shades (darker = higher freq)
|
|
33
|
+
* 5G: Green shades (stronger = higher freq)
|
|
34
|
+
*/
|
|
35
|
+
export const FBAND_COLORS = {
|
|
36
|
+
// GSM - Yellow shades (900 lighter, 1800 darker)
|
|
37
|
+
'GSM900': '#ffc107', // Light yellow
|
|
38
|
+
'GSM1800': '#cc9a06', // Darker yellow/gold
|
|
39
|
+
// LTE - Purple shades (700 lightest → 2600 darkest)
|
|
40
|
+
'LTE700': '#d8b4fe', // Light purple
|
|
41
|
+
'LTE800': '#c084fc', //
|
|
42
|
+
'LTE900': '#a855f7', //
|
|
43
|
+
'LTE1800': '#9333ea', //
|
|
44
|
+
'LTE2100': '#7e22ce', //
|
|
45
|
+
'LTE2600': '#6b21a8', // Dark purple
|
|
46
|
+
// 5G - Green shades (700 lighter → 3500 stronger)
|
|
47
|
+
'5G-700': '#86efac', // Light green
|
|
48
|
+
'5G-2100': '#22c55e', // Medium green
|
|
49
|
+
'5G-3500': '#15803d', // Strong/dark green
|
|
50
|
+
'NR3500': '#15803d', // Same as 5G-3500
|
|
51
|
+
};
|
|
52
|
+
/**
|
|
53
|
+
* Column groups for different presets
|
|
54
|
+
*/
|
|
55
|
+
export const COLUMN_GROUPS = {
|
|
56
|
+
core: ['siteId', 'txId', 'cellName', 'tech', 'fband', 'status'],
|
|
57
|
+
physical: ['antenna', 'azimuth', 'height', 'beamwidth'],
|
|
58
|
+
network: ['nwET', 'nwPW', 'nwRS', 'nwBW', 'dlEarfn', 'bcch', 'pci', 'rru', 'cellID', 'cellId2G', 'ctrlid'],
|
|
59
|
+
planning: ['planner', 'comment', 'onAirDate'],
|
|
60
|
+
atoll: ['atollET', 'atollMT', 'atollPW', 'atollRS', 'atollBW'],
|
|
61
|
+
position: ['latitude', 'longitude', 'siteLatitude', 'siteLongitude', 'dx', 'dy'],
|
|
62
|
+
compare: ['compareET', 'comparePW', 'compareRS', 'compareBW'],
|
|
63
|
+
};
|
|
64
|
+
/**
|
|
65
|
+
* Create a technology badge formatter
|
|
66
|
+
*/
|
|
67
|
+
export function createTechFormatter(colors = DEFAULT_TECH_COLORS) {
|
|
68
|
+
return (cell) => {
|
|
69
|
+
const value = cell.getValue();
|
|
70
|
+
const color = colors[value] || '#6c757d';
|
|
71
|
+
return `<span class="badge" style="background-color: ${color}; color: white;">${value}</span>`;
|
|
72
|
+
};
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* Create a status badge formatter
|
|
76
|
+
*/
|
|
77
|
+
export function createStatusFormatter(colors = DEFAULT_STATUS_COLORS) {
|
|
78
|
+
return (cell) => {
|
|
79
|
+
const value = cell.getValue();
|
|
80
|
+
const color = colors[value] || '#6c757d';
|
|
81
|
+
const displayValue = value.replace(/_/g, ' ');
|
|
82
|
+
return `<span class="badge" style="background-color: ${color}; color: white; font-size: 0.7rem;">${displayValue}</span>`;
|
|
83
|
+
};
|
|
84
|
+
}
|
|
85
|
+
/**
|
|
86
|
+
* Create an fband badge formatter
|
|
87
|
+
*/
|
|
88
|
+
export function createFbandFormatter() {
|
|
89
|
+
return (cell) => {
|
|
90
|
+
const value = cell.getValue();
|
|
91
|
+
const color = FBAND_COLORS[value] || '#6c757d';
|
|
92
|
+
return `<span class="badge" style="background-color: ${color}; color: white;">${value}</span>`;
|
|
93
|
+
};
|
|
94
|
+
}
|
|
95
|
+
/**
|
|
96
|
+
* Number formatter with fixed decimals
|
|
97
|
+
*/
|
|
98
|
+
export function numberFormatter(decimals = 2) {
|
|
99
|
+
return (cell) => {
|
|
100
|
+
const value = cell.getValue();
|
|
101
|
+
if (value === null || value === undefined || value === '')
|
|
102
|
+
return '';
|
|
103
|
+
const num = Number(value);
|
|
104
|
+
return isNaN(num) ? String(value) : num.toFixed(decimals);
|
|
105
|
+
};
|
|
106
|
+
}
|
|
107
|
+
/**
|
|
108
|
+
* Coordinate formatter (lat/lng)
|
|
109
|
+
*/
|
|
110
|
+
export function coordinateFormatter(cell) {
|
|
111
|
+
const value = cell.getValue();
|
|
112
|
+
if (value === null || value === undefined || value === '')
|
|
113
|
+
return '';
|
|
114
|
+
const num = Number(value);
|
|
115
|
+
return isNaN(num) ? String(value) : num.toFixed(6);
|
|
116
|
+
}
|
|
117
|
+
/**
|
|
118
|
+
* Azimuth formatter with degree symbol
|
|
119
|
+
*/
|
|
120
|
+
export function azimuthFormatter(cell) {
|
|
121
|
+
const value = cell.getValue();
|
|
122
|
+
if (value === null || value === undefined || value === '')
|
|
123
|
+
return '';
|
|
124
|
+
return `${value}°`;
|
|
125
|
+
}
|
|
126
|
+
/**
|
|
127
|
+
* Height formatter with meter unit
|
|
128
|
+
*/
|
|
129
|
+
export function heightFormatter(cell) {
|
|
130
|
+
const value = cell.getValue();
|
|
131
|
+
if (value === null || value === undefined || value === '')
|
|
132
|
+
return '';
|
|
133
|
+
return `${value}m`;
|
|
134
|
+
}
|
|
135
|
+
/**
|
|
136
|
+
* Comparison formatter for Atoll vs Network values
|
|
137
|
+
* Shows both values side by side with color coding:
|
|
138
|
+
* - Green: values match exactly
|
|
139
|
+
* - Red: values don't match
|
|
140
|
+
* - Gray: one or both values missing
|
|
141
|
+
*/
|
|
142
|
+
export function createCompareFormatter(atollField, nwtField) {
|
|
143
|
+
return (cell) => {
|
|
144
|
+
const row = cell.getRow().getData();
|
|
145
|
+
const atollVal = row[atollField];
|
|
146
|
+
const nwtVal = row[nwtField];
|
|
147
|
+
const atollStr = atollVal !== null && atollVal !== undefined ? String(atollVal) : '-';
|
|
148
|
+
const nwtStr = nwtVal !== null && nwtVal !== undefined ? String(nwtVal) : '-';
|
|
149
|
+
// Determine match status
|
|
150
|
+
const atollMissing = atollVal === null || atollVal === undefined;
|
|
151
|
+
const nwtMissing = nwtVal === null || nwtVal === undefined;
|
|
152
|
+
let bgColor;
|
|
153
|
+
let textColor = 'white';
|
|
154
|
+
if (atollMissing || nwtMissing) {
|
|
155
|
+
// One or both missing - gray
|
|
156
|
+
bgColor = '#6c757d';
|
|
157
|
+
}
|
|
158
|
+
else if (atollVal === nwtVal) {
|
|
159
|
+
// Exact match - green
|
|
160
|
+
bgColor = '#198754';
|
|
161
|
+
}
|
|
162
|
+
else {
|
|
163
|
+
// Mismatch - red
|
|
164
|
+
bgColor = '#dc3545';
|
|
165
|
+
}
|
|
166
|
+
return `<span class="badge" style="background-color: ${bgColor}; color: ${textColor}; font-size: 0.75rem; font-weight: normal;">${atollStr} | ${nwtStr}</span>`;
|
|
167
|
+
};
|
|
168
|
+
}
|
|
169
|
+
/**
|
|
170
|
+
* Custom sorter for fband - extracts numeric portion and sorts numerically
|
|
171
|
+
* Examples: LTE700 → 700, GSM900 → 900, LTE1800 → 1800, 5G-3500 → 3500
|
|
172
|
+
*/
|
|
173
|
+
export function fbandSorter(a, b) {
|
|
174
|
+
const numA = parseInt(a.replace(/\D/g, ''), 10) || 0;
|
|
175
|
+
const numB = parseInt(b.replace(/\D/g, ''), 10) || 0;
|
|
176
|
+
return numA - numB;
|
|
177
|
+
}
|
|
178
|
+
/**
|
|
179
|
+
* Custom sorter for cellName - sorts by the 5th character (sector digit)
|
|
180
|
+
* Example: 10001 → '1', 10002 → '2', 10003 → '3'
|
|
181
|
+
*/
|
|
182
|
+
export function cellNameSectorSorter(a, b) {
|
|
183
|
+
const charA = a.charAt(4) || '0';
|
|
184
|
+
const charB = b.charAt(4) || '0';
|
|
185
|
+
return charA.localeCompare(charB);
|
|
186
|
+
}
|
|
187
|
+
/**
|
|
188
|
+
* Combined multi-level sorter for cell data
|
|
189
|
+
* Sort order: tech (asc) → fband by numeric value (asc) → cellName by 5th digit (asc)
|
|
190
|
+
*/
|
|
191
|
+
export function cellDataSorter(a, b) {
|
|
192
|
+
// 1. Sort by tech (string comparison)
|
|
193
|
+
const techA = String(a.tech || '');
|
|
194
|
+
const techB = String(b.tech || '');
|
|
195
|
+
const techCompare = techA.localeCompare(techB);
|
|
196
|
+
if (techCompare !== 0)
|
|
197
|
+
return techCompare;
|
|
198
|
+
// 2. Sort by fband (numeric extraction)
|
|
199
|
+
const fbandA = String(a.fband || '');
|
|
200
|
+
const fbandB = String(b.fband || '');
|
|
201
|
+
const fbandCompare = fbandSorter(fbandA, fbandB);
|
|
202
|
+
if (fbandCompare !== 0)
|
|
203
|
+
return fbandCompare;
|
|
204
|
+
// 3. Sort by cellName 5th character (sector)
|
|
205
|
+
const cellNameA = String(a.cellName || '');
|
|
206
|
+
const cellNameB = String(b.cellName || '');
|
|
207
|
+
return cellNameSectorSorter(cellNameA, cellNameB);
|
|
208
|
+
}
|
|
209
|
+
/**
|
|
210
|
+
* Get all column definitions
|
|
211
|
+
*/
|
|
212
|
+
export function getAllColumns(techColors = DEFAULT_TECH_COLORS, statusColors = DEFAULT_STATUS_COLORS, headerFilters = true) {
|
|
213
|
+
const headerFilterParams = headerFilters ? { headerFilter: 'input' } : {};
|
|
214
|
+
const selectHeaderFilter = headerFilters ? { headerFilter: 'list', headerFilterParams: { valuesLookup: true } } : {};
|
|
215
|
+
return [
|
|
216
|
+
// Core columns - siteId, txId, cellName first (frozen)
|
|
217
|
+
{
|
|
218
|
+
title: 'Site ID',
|
|
219
|
+
field: 'siteId',
|
|
220
|
+
width: 120,
|
|
221
|
+
frozen: true,
|
|
222
|
+
...headerFilterParams,
|
|
223
|
+
},
|
|
224
|
+
{
|
|
225
|
+
title: 'TX ID',
|
|
226
|
+
field: 'txId',
|
|
227
|
+
width: 100,
|
|
228
|
+
frozen: true,
|
|
229
|
+
...headerFilterParams,
|
|
230
|
+
},
|
|
231
|
+
{
|
|
232
|
+
title: 'Cell Name',
|
|
233
|
+
field: 'cellName',
|
|
234
|
+
width: 150,
|
|
235
|
+
frozen: true,
|
|
236
|
+
...headerFilterParams,
|
|
237
|
+
},
|
|
238
|
+
{
|
|
239
|
+
title: 'Tech',
|
|
240
|
+
field: 'tech',
|
|
241
|
+
width: 80,
|
|
242
|
+
hozAlign: 'center',
|
|
243
|
+
formatter: createTechFormatter(techColors),
|
|
244
|
+
...selectHeaderFilter,
|
|
245
|
+
},
|
|
246
|
+
{
|
|
247
|
+
title: 'Band',
|
|
248
|
+
field: 'fband',
|
|
249
|
+
width: 100,
|
|
250
|
+
hozAlign: 'center',
|
|
251
|
+
formatter: createFbandFormatter(),
|
|
252
|
+
...selectHeaderFilter,
|
|
253
|
+
},
|
|
254
|
+
{
|
|
255
|
+
title: 'Freq',
|
|
256
|
+
field: 'frq',
|
|
257
|
+
width: 80,
|
|
258
|
+
hozAlign: 'center',
|
|
259
|
+
...selectHeaderFilter,
|
|
260
|
+
},
|
|
261
|
+
{
|
|
262
|
+
title: 'Status',
|
|
263
|
+
field: 'status',
|
|
264
|
+
width: 180,
|
|
265
|
+
formatter: createStatusFormatter(statusColors),
|
|
266
|
+
...selectHeaderFilter,
|
|
267
|
+
},
|
|
268
|
+
{
|
|
269
|
+
title: 'On Air Date',
|
|
270
|
+
field: 'onAirDate',
|
|
271
|
+
width: 120,
|
|
272
|
+
...headerFilterParams,
|
|
273
|
+
},
|
|
274
|
+
// Physical columns
|
|
275
|
+
{
|
|
276
|
+
title: 'Antenna',
|
|
277
|
+
field: 'antenna',
|
|
278
|
+
width: 150,
|
|
279
|
+
...headerFilterParams,
|
|
280
|
+
},
|
|
281
|
+
{
|
|
282
|
+
title: 'Azimuth',
|
|
283
|
+
field: 'azimuth',
|
|
284
|
+
width: 90,
|
|
285
|
+
hozAlign: 'right',
|
|
286
|
+
formatter: azimuthFormatter,
|
|
287
|
+
...headerFilterParams,
|
|
288
|
+
},
|
|
289
|
+
{
|
|
290
|
+
title: 'Height',
|
|
291
|
+
field: 'height',
|
|
292
|
+
width: 80,
|
|
293
|
+
hozAlign: 'right',
|
|
294
|
+
formatter: heightFormatter,
|
|
295
|
+
...headerFilterParams,
|
|
296
|
+
},
|
|
297
|
+
{
|
|
298
|
+
title: 'Beamwidth',
|
|
299
|
+
field: 'beamwidth',
|
|
300
|
+
width: 100,
|
|
301
|
+
hozAlign: 'right',
|
|
302
|
+
formatter: azimuthFormatter,
|
|
303
|
+
...headerFilterParams,
|
|
304
|
+
},
|
|
305
|
+
// Network columns
|
|
306
|
+
{
|
|
307
|
+
title: 'DL EARFCN',
|
|
308
|
+
field: 'dlEarfn',
|
|
309
|
+
width: 100,
|
|
310
|
+
hozAlign: 'right',
|
|
311
|
+
...headerFilterParams,
|
|
312
|
+
},
|
|
313
|
+
{
|
|
314
|
+
title: 'BCCH',
|
|
315
|
+
field: 'bcch',
|
|
316
|
+
width: 80,
|
|
317
|
+
hozAlign: 'right',
|
|
318
|
+
...headerFilterParams,
|
|
319
|
+
},
|
|
320
|
+
{
|
|
321
|
+
title: 'PCI',
|
|
322
|
+
field: 'pci',
|
|
323
|
+
width: 80,
|
|
324
|
+
hozAlign: 'right',
|
|
325
|
+
...headerFilterParams,
|
|
326
|
+
},
|
|
327
|
+
{
|
|
328
|
+
title: 'Cell ID',
|
|
329
|
+
field: 'cellID',
|
|
330
|
+
width: 100,
|
|
331
|
+
...headerFilterParams,
|
|
332
|
+
},
|
|
333
|
+
{
|
|
334
|
+
title: 'Cell ID 2G',
|
|
335
|
+
field: 'cellID2G',
|
|
336
|
+
width: 100,
|
|
337
|
+
...headerFilterParams,
|
|
338
|
+
},
|
|
339
|
+
{
|
|
340
|
+
title: 'Ctrl ID',
|
|
341
|
+
field: 'ctrlid',
|
|
342
|
+
width: 100,
|
|
343
|
+
...headerFilterParams,
|
|
344
|
+
},
|
|
345
|
+
{
|
|
346
|
+
title: 'RRU',
|
|
347
|
+
field: 'rru',
|
|
348
|
+
width: 100,
|
|
349
|
+
...headerFilterParams,
|
|
350
|
+
},
|
|
351
|
+
{
|
|
352
|
+
title: 'NW ET',
|
|
353
|
+
field: 'nwET',
|
|
354
|
+
width: 80,
|
|
355
|
+
hozAlign: 'right',
|
|
356
|
+
formatter: numberFormatter(1),
|
|
357
|
+
...headerFilterParams,
|
|
358
|
+
},
|
|
359
|
+
{
|
|
360
|
+
title: 'NW PW',
|
|
361
|
+
field: 'nwPW',
|
|
362
|
+
width: 80,
|
|
363
|
+
hozAlign: 'right',
|
|
364
|
+
formatter: numberFormatter(1),
|
|
365
|
+
...headerFilterParams,
|
|
366
|
+
},
|
|
367
|
+
{
|
|
368
|
+
title: 'NW RS',
|
|
369
|
+
field: 'nwRS',
|
|
370
|
+
width: 80,
|
|
371
|
+
hozAlign: 'right',
|
|
372
|
+
...headerFilterParams,
|
|
373
|
+
},
|
|
374
|
+
{
|
|
375
|
+
title: 'NW BW',
|
|
376
|
+
field: 'nwBW',
|
|
377
|
+
width: 80,
|
|
378
|
+
hozAlign: 'right',
|
|
379
|
+
...headerFilterParams,
|
|
380
|
+
},
|
|
381
|
+
// Atoll columns
|
|
382
|
+
{
|
|
383
|
+
title: 'Atoll ET',
|
|
384
|
+
field: 'atollET',
|
|
385
|
+
width: 90,
|
|
386
|
+
hozAlign: 'right',
|
|
387
|
+
formatter: numberFormatter(1),
|
|
388
|
+
...headerFilterParams,
|
|
389
|
+
},
|
|
390
|
+
{
|
|
391
|
+
title: 'Atoll MT',
|
|
392
|
+
field: 'atollMT',
|
|
393
|
+
width: 90,
|
|
394
|
+
hozAlign: 'right',
|
|
395
|
+
formatter: numberFormatter(1),
|
|
396
|
+
...headerFilterParams,
|
|
397
|
+
},
|
|
398
|
+
{
|
|
399
|
+
title: 'Atoll PW',
|
|
400
|
+
field: 'atollPW',
|
|
401
|
+
width: 90,
|
|
402
|
+
hozAlign: 'right',
|
|
403
|
+
formatter: numberFormatter(1),
|
|
404
|
+
...headerFilterParams,
|
|
405
|
+
},
|
|
406
|
+
{
|
|
407
|
+
title: 'Atoll RS',
|
|
408
|
+
field: 'atollRS',
|
|
409
|
+
width: 90,
|
|
410
|
+
hozAlign: 'right',
|
|
411
|
+
formatter: numberFormatter(1),
|
|
412
|
+
...headerFilterParams,
|
|
413
|
+
},
|
|
414
|
+
{
|
|
415
|
+
title: 'Atoll BW',
|
|
416
|
+
field: 'atollBW',
|
|
417
|
+
width: 90,
|
|
418
|
+
hozAlign: 'right',
|
|
419
|
+
formatter: numberFormatter(1),
|
|
420
|
+
...headerFilterParams,
|
|
421
|
+
},
|
|
422
|
+
// Compare columns (Atoll vs Network)
|
|
423
|
+
{
|
|
424
|
+
title: 'Δ ET',
|
|
425
|
+
field: 'compareET',
|
|
426
|
+
width: 110,
|
|
427
|
+
hozAlign: 'center',
|
|
428
|
+
formatter: createCompareFormatter('atollET', 'nwET'),
|
|
429
|
+
headerTooltip: 'Atoll ET | Network ET',
|
|
430
|
+
},
|
|
431
|
+
{
|
|
432
|
+
title: 'Δ PW',
|
|
433
|
+
field: 'comparePW',
|
|
434
|
+
width: 110,
|
|
435
|
+
hozAlign: 'center',
|
|
436
|
+
formatter: createCompareFormatter('atollPW', 'nwPW'),
|
|
437
|
+
headerTooltip: 'Atoll PW | Network PW',
|
|
438
|
+
},
|
|
439
|
+
{
|
|
440
|
+
title: 'Δ RS',
|
|
441
|
+
field: 'compareRS',
|
|
442
|
+
width: 110,
|
|
443
|
+
hozAlign: 'center',
|
|
444
|
+
formatter: createCompareFormatter('atollRS', 'nwRS'),
|
|
445
|
+
headerTooltip: 'Atoll RS | Network RS',
|
|
446
|
+
},
|
|
447
|
+
{
|
|
448
|
+
title: 'Δ BW',
|
|
449
|
+
field: 'compareBW',
|
|
450
|
+
width: 110,
|
|
451
|
+
hozAlign: 'center',
|
|
452
|
+
formatter: createCompareFormatter('atollBW', 'nwBW'),
|
|
453
|
+
headerTooltip: 'Atoll BW | Network BW',
|
|
454
|
+
},
|
|
455
|
+
// Position columns
|
|
456
|
+
{
|
|
457
|
+
title: 'Latitude',
|
|
458
|
+
field: 'latitude',
|
|
459
|
+
width: 120,
|
|
460
|
+
hozAlign: 'right',
|
|
461
|
+
formatter: coordinateFormatter,
|
|
462
|
+
...headerFilterParams,
|
|
463
|
+
},
|
|
464
|
+
{
|
|
465
|
+
title: 'Longitude',
|
|
466
|
+
field: 'longitude',
|
|
467
|
+
width: 120,
|
|
468
|
+
hozAlign: 'right',
|
|
469
|
+
formatter: coordinateFormatter,
|
|
470
|
+
...headerFilterParams,
|
|
471
|
+
},
|
|
472
|
+
{
|
|
473
|
+
title: 'Site Lat',
|
|
474
|
+
field: 'siteLatitude',
|
|
475
|
+
width: 120,
|
|
476
|
+
hozAlign: 'right',
|
|
477
|
+
formatter: coordinateFormatter,
|
|
478
|
+
...headerFilterParams,
|
|
479
|
+
},
|
|
480
|
+
{
|
|
481
|
+
title: 'Site Lng',
|
|
482
|
+
field: 'siteLongitude',
|
|
483
|
+
width: 120,
|
|
484
|
+
hozAlign: 'right',
|
|
485
|
+
formatter: coordinateFormatter,
|
|
486
|
+
...headerFilterParams,
|
|
487
|
+
},
|
|
488
|
+
{
|
|
489
|
+
title: 'DX',
|
|
490
|
+
field: 'dx',
|
|
491
|
+
width: 80,
|
|
492
|
+
hozAlign: 'right',
|
|
493
|
+
formatter: numberFormatter(2),
|
|
494
|
+
...headerFilterParams,
|
|
495
|
+
},
|
|
496
|
+
{
|
|
497
|
+
title: 'DY',
|
|
498
|
+
field: 'dy',
|
|
499
|
+
width: 80,
|
|
500
|
+
hozAlign: 'right',
|
|
501
|
+
formatter: numberFormatter(2),
|
|
502
|
+
...headerFilterParams,
|
|
503
|
+
},
|
|
504
|
+
// Planning columns
|
|
505
|
+
{
|
|
506
|
+
title: 'Planner',
|
|
507
|
+
field: 'planner',
|
|
508
|
+
width: 120,
|
|
509
|
+
...headerFilterParams,
|
|
510
|
+
},
|
|
511
|
+
{
|
|
512
|
+
title: 'Comment',
|
|
513
|
+
field: 'comment',
|
|
514
|
+
width: 200,
|
|
515
|
+
...headerFilterParams,
|
|
516
|
+
},
|
|
517
|
+
{
|
|
518
|
+
title: 'Subgroup',
|
|
519
|
+
field: 'customSubgroup',
|
|
520
|
+
width: 120,
|
|
521
|
+
...headerFilterParams,
|
|
522
|
+
},
|
|
523
|
+
];
|
|
524
|
+
}
|
|
525
|
+
/**
|
|
526
|
+
* Get columns for a specific preset
|
|
527
|
+
*/
|
|
528
|
+
export function getColumnsForPreset(preset, techColors = DEFAULT_TECH_COLORS, statusColors = DEFAULT_STATUS_COLORS, headerFilters = true) {
|
|
529
|
+
const allColumns = getAllColumns(techColors, statusColors, headerFilters);
|
|
530
|
+
let visibleFields;
|
|
531
|
+
switch (preset) {
|
|
532
|
+
case 'compact':
|
|
533
|
+
visibleFields = ['siteId', 'txId', 'cellName', 'tech', 'fband', 'status'];
|
|
534
|
+
break;
|
|
535
|
+
case 'full':
|
|
536
|
+
return allColumns;
|
|
537
|
+
case 'physical':
|
|
538
|
+
visibleFields = [...COLUMN_GROUPS.core, ...COLUMN_GROUPS.physical];
|
|
539
|
+
break;
|
|
540
|
+
case 'network':
|
|
541
|
+
visibleFields = [...COLUMN_GROUPS.core, ...COLUMN_GROUPS.network];
|
|
542
|
+
break;
|
|
543
|
+
case 'planning':
|
|
544
|
+
visibleFields = [...COLUMN_GROUPS.core, ...COLUMN_GROUPS.planning];
|
|
545
|
+
break;
|
|
546
|
+
case 'compare':
|
|
547
|
+
visibleFields = [...COLUMN_GROUPS.core, ...COLUMN_GROUPS.compare];
|
|
548
|
+
break;
|
|
549
|
+
case 'default':
|
|
550
|
+
default:
|
|
551
|
+
visibleFields = [
|
|
552
|
+
'siteId', 'txId', 'cellName', 'tech', 'fband', 'frq', 'status',
|
|
553
|
+
'azimuth', 'height', 'antenna'
|
|
554
|
+
];
|
|
555
|
+
}
|
|
556
|
+
return allColumns.filter(col => visibleFields.includes(col.field));
|
|
557
|
+
}
|
|
558
|
+
/**
|
|
559
|
+
* Get group header formatter for a specific field
|
|
560
|
+
*/
|
|
561
|
+
export function getGroupHeaderFormatter(groupField) {
|
|
562
|
+
return (value, count) => {
|
|
563
|
+
const displayValue = String(value).replace(/_/g, ' ');
|
|
564
|
+
let color = '#6c757d';
|
|
565
|
+
if (groupField === 'tech') {
|
|
566
|
+
color = DEFAULT_TECH_COLORS[String(value)] || color;
|
|
567
|
+
}
|
|
568
|
+
else if (groupField === 'fband') {
|
|
569
|
+
color = FBAND_COLORS[String(value)] || color;
|
|
570
|
+
}
|
|
571
|
+
else if (groupField === 'status') {
|
|
572
|
+
color = DEFAULT_STATUS_COLORS[String(value)] || color;
|
|
573
|
+
}
|
|
574
|
+
return `<span class="badge me-2" style="background-color: ${color}; color: white;">${displayValue}</span>
|
|
575
|
+
<span class="text-muted">(${count} cell${count !== 1 ? 's' : ''})</span>`;
|
|
576
|
+
};
|
|
577
|
+
}
|
|
578
|
+
/**
|
|
579
|
+
* Get column metadata for the column picker UI
|
|
580
|
+
* @param options Filter options for including/excluding column groups
|
|
581
|
+
*/
|
|
582
|
+
export function getColumnMetadata(options) {
|
|
583
|
+
const allColumns = [
|
|
584
|
+
// Core
|
|
585
|
+
{ field: 'siteId', title: 'Site ID', group: 'Core' },
|
|
586
|
+
{ field: 'txId', title: 'TX ID', group: 'Core' },
|
|
587
|
+
{ field: 'cellName', title: 'Cell Name', group: 'Core' },
|
|
588
|
+
{ field: 'tech', title: 'Technology', group: 'Core' },
|
|
589
|
+
{ field: 'fband', title: 'Band', group: 'Core' },
|
|
590
|
+
{ field: 'frq', title: 'Frequency', group: 'Core' },
|
|
591
|
+
{ field: 'status', title: 'Status', group: 'Core' },
|
|
592
|
+
{ field: 'onAirDate', title: 'On Air Date', group: 'Core' },
|
|
593
|
+
// Antenna Physical
|
|
594
|
+
{ field: 'antenna', title: 'Antenna', group: 'Antenna Physical' },
|
|
595
|
+
{ field: 'azimuth', title: 'Azimuth', group: 'Antenna Physical' },
|
|
596
|
+
{ field: 'height', title: 'Height', group: 'Antenna Physical' },
|
|
597
|
+
{ field: 'beamwidth', title: 'Beamwidth', group: 'Antenna Physical' },
|
|
598
|
+
{ field: 'atollMT', title: 'Atoll MT', group: 'Atoll' },
|
|
599
|
+
// Atoll antenna settings
|
|
600
|
+
{ field: 'atollET', title: 'Atoll ET', group: 'Atoll' },
|
|
601
|
+
{ field: 'atollPW', title: 'Atoll PW', group: 'Atoll' },
|
|
602
|
+
{ field: 'atollRS', title: 'Atoll RS', group: 'Atoll' },
|
|
603
|
+
{ field: 'atollBW', title: 'Atoll BW', group: 'Atoll' },
|
|
604
|
+
// Network antena settings
|
|
605
|
+
{ field: 'nwET', title: 'NW ET', group: 'Network' },
|
|
606
|
+
{ field: 'nwPW', title: 'NW PW', group: 'Network' },
|
|
607
|
+
{ field: 'nwRS', title: 'NW RS', group: 'Network' },
|
|
608
|
+
{ field: 'nwBW', title: 'NW BW', group: 'Network' },
|
|
609
|
+
// Compare (Atoll vs Network)
|
|
610
|
+
{ field: 'compareET', title: 'Δ ET', group: 'Compare' },
|
|
611
|
+
{ field: 'comparePW', title: 'Δ PW', group: 'Compare' },
|
|
612
|
+
{ field: 'compareRS', title: 'Δ RS', group: 'Compare' },
|
|
613
|
+
{ field: 'compareBW', title: 'Δ BW', group: 'Compare' },
|
|
614
|
+
// Network settings
|
|
615
|
+
{ field: 'dlEarfn', title: 'DL EARFCN', group: 'Network' },
|
|
616
|
+
{ field: 'bcch', title: 'BCCH', group: 'Network' },
|
|
617
|
+
{ field: 'pci', title: 'PCI', group: 'Network' },
|
|
618
|
+
{ field: 'rru', title: 'RRU', group: 'Network' },
|
|
619
|
+
{ field: 'cellID', title: 'Cell ID', group: 'Network' },
|
|
620
|
+
{ field: 'cellId2G', title: 'Cell ID 2G', group: 'Network' },
|
|
621
|
+
{ field: 'ctrlid', title: 'Ctrl ID', group: 'Network' },
|
|
622
|
+
// Position
|
|
623
|
+
// { field: 'latitude', title: 'Latitude', group: 'Position' },
|
|
624
|
+
// { field: 'longitude', title: 'Longitude', group: 'Position' },
|
|
625
|
+
// { field: 'siteLatitude', title: 'Site Latitude', group: 'Position' },
|
|
626
|
+
// { field: 'siteLongitude', title: 'Site Longitude', group: 'Position' },
|
|
627
|
+
// { field: 'dx', title: 'DX', group: 'Position' },
|
|
628
|
+
// { field: 'dy', title: 'DY', group: 'Position' },
|
|
629
|
+
// Planning
|
|
630
|
+
{ field: 'planner', title: 'Planner', group: 'Planning' },
|
|
631
|
+
{ field: 'comment', title: 'Comment', group: 'Planning' },
|
|
632
|
+
// { field: 'customSubgroup', title: 'Subgroup', group: 'Planning' },
|
|
633
|
+
];
|
|
634
|
+
// Apply filtering if options provided
|
|
635
|
+
const { include, exclude } = options ?? {};
|
|
636
|
+
return allColumns.filter(col => {
|
|
637
|
+
// If include is specified, only include those groups
|
|
638
|
+
if (include && include.length > 0) {
|
|
639
|
+
if (!include.includes(col.group)) {
|
|
640
|
+
return false;
|
|
641
|
+
}
|
|
642
|
+
}
|
|
643
|
+
// Apply exclude filter
|
|
644
|
+
if (exclude && exclude.includes(col.group)) {
|
|
645
|
+
return false;
|
|
646
|
+
}
|
|
647
|
+
return true;
|
|
648
|
+
});
|
|
649
|
+
}
|
|
650
|
+
/**
|
|
651
|
+
* Get default visible columns for a preset
|
|
652
|
+
*/
|
|
653
|
+
export function getPresetVisibleFields(preset) {
|
|
654
|
+
switch (preset) {
|
|
655
|
+
case 'compact':
|
|
656
|
+
return ['siteId', 'txId', 'cellName', 'tech', 'fband', 'status'];
|
|
657
|
+
case 'full':
|
|
658
|
+
return getColumnMetadata().map(c => c.field);
|
|
659
|
+
case 'physical':
|
|
660
|
+
return [...COLUMN_GROUPS.core, ...COLUMN_GROUPS.physical];
|
|
661
|
+
case 'network':
|
|
662
|
+
return [...COLUMN_GROUPS.core, ...COLUMN_GROUPS.network];
|
|
663
|
+
case 'planning':
|
|
664
|
+
return [...COLUMN_GROUPS.core, ...COLUMN_GROUPS.planning];
|
|
665
|
+
case 'compare':
|
|
666
|
+
return [...COLUMN_GROUPS.core, ...COLUMN_GROUPS.compare];
|
|
667
|
+
case 'default':
|
|
668
|
+
default:
|
|
669
|
+
return ['siteId', 'txId', 'cellName', 'tech', 'fband', 'frq', 'status', 'azimuth', 'height', 'antenna'];
|
|
670
|
+
}
|
|
671
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* CellTableV2 Composables
|
|
3
|
+
*
|
|
4
|
+
* Reusable logic hooks for cell table functionality.
|
|
5
|
+
* These composables use Svelte 5 runes and can be shared across different panel types.
|
|
6
|
+
*/
|
|
7
|
+
export { usePersistence } from './usePersistence.svelte';
|
|
8
|
+
export type { UsePersistenceOptions, UsePersistenceReturn } from './usePersistence.svelte';
|
|
9
|
+
export { useColumnVisibility } from './useColumnVisibility.svelte';
|
|
10
|
+
export type { UseColumnVisibilityOptions, UseColumnVisibilityReturn } from './useColumnVisibility.svelte';
|
|
11
|
+
export { useScrollSpy } from './useScrollSpy.svelte';
|
|
12
|
+
export type { UseScrollSpyOptions, UseScrollSpyReturn, ScrollSpyGroup, CellTableRef } from './useScrollSpy.svelte';
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* CellTableV2 Composables
|
|
3
|
+
*
|
|
4
|
+
* Reusable logic hooks for cell table functionality.
|
|
5
|
+
* These composables use Svelte 5 runes and can be shared across different panel types.
|
|
6
|
+
*/
|
|
7
|
+
export { usePersistence } from './usePersistence.svelte';
|
|
8
|
+
export { useColumnVisibility } from './useColumnVisibility.svelte';
|
|
9
|
+
export { useScrollSpy } from './useScrollSpy.svelte';
|