@smartnet360/svelte-components 0.0.133 → 0.0.134

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.
@@ -174,6 +174,7 @@
174
174
  <CellTablePanel
175
175
  cells={historyData as unknown as import('./types').CellData[]}
176
176
  groupBy="none"
177
+ storageKey="cell-history-table"
177
178
  groupOptions={[
178
179
  { value: 'none', label: 'No Grouping' },
179
180
  { value: 'antenna', label: 'Antenna Type' },
@@ -56,7 +56,7 @@
56
56
  headerFilters = true,
57
57
  resizableColumns = true,
58
58
  movableColumns = true,
59
- persistLayout = false,
59
+ persistLayout = true,
60
60
  storageKey = 'cell-table-layout',
61
61
  onselectionchange,
62
62
  onrowclick,
@@ -119,11 +119,12 @@
119
119
  selectable: selectable ? (multiSelect ? true : 1) : false,
120
120
  selectableRangeMode: 'click',
121
121
 
122
- // Persistence - disable sort persistence to preserve pre-sorted order
122
+ // Persistence - save column widths, order, visibility and group settings
123
123
  persistence: persistLayout ? {
124
- filter: true,
125
- columns: ['width', 'visible'],
124
+ columns: ['width', 'visible', 'order'],
125
+ group: true,
126
126
  } : false,
127
+ persistenceMode: persistLayout ? 'local' : undefined,
127
128
  persistenceID: persistLayout ? storageKey : undefined,
128
129
 
129
130
  // Grouping
@@ -230,7 +231,8 @@
230
231
  // Track previous values to avoid unnecessary updates
231
232
  let prevCellsRef: unknown[] | null = null;
232
233
  let prevGroupBy: string | null = null;
233
- let prevColumnPreset: string | null = null;
234
+ // Initialize with current preset to prevent setColumns on first load (which would override persisted layout)
235
+ let prevColumnPreset: string | null = columnPreset;
234
236
 
235
237
  // Update table data when cells change (reference comparison)
236
238
  $effect(() => {
@@ -56,6 +56,8 @@
56
56
  persistSettings?: boolean;
57
57
  /** Storage key prefix for persisted settings */
58
58
  storageKey?: string;
59
+ /** Enable Tabulator persistence for column widths, order, visibility */
60
+ persistLayout?: boolean;
59
61
  /** Show scrollspy navigation bar for quick group navigation */
60
62
  showScrollSpy?: boolean;
61
63
  /** Bindable reference to table methods */
@@ -98,6 +100,7 @@
98
100
  sidebarWidth = 320,
99
101
  persistSettings = true,
100
102
  storageKey = 'cell-table',
103
+ persistLayout = true,
101
104
  showScrollSpy = false,
102
105
  tableRef = $bindable(null),
103
106
  onselectionchange,
@@ -117,17 +120,22 @@
117
120
 
118
121
  // Storage keys
119
122
  const STORAGE_KEY_GROUP = `${storageKey}-groupBy`;
120
- const STORAGE_KEY_COLUMNS = `${storageKey}-visibleColumns`;
121
123
  const STORAGE_KEY_FILTERS = `${storageKey}-filtersVisible`;
122
124
  const STORAGE_KEY_SCROLLSPY = `${storageKey}-scrollSpyEnabled`;
125
+ const STORAGE_KEY_PRESET = `${storageKey}-columnPreset`;
126
+
127
+ // Per-preset column visibility storage key
128
+ function getColumnsStorageKey(preset: ColumnPreset): string {
129
+ return `${storageKey}-visibleColumns-${preset}`;
130
+ }
123
131
 
124
132
  // Load persisted settings
125
133
  function loadPersistedSettings() {
126
- if (!persistSettings || typeof localStorage === 'undefined') return { columns: null, filtersVisible: true, scrollSpyEnabled: showScrollSpy };
134
+ if (!persistSettings || typeof localStorage === 'undefined') return { filtersVisible: true, scrollSpyEnabled: showScrollSpy, preset: null };
127
135
 
128
- let columns: string[] | null = null;
129
136
  let filters = true;
130
137
  let scrollSpy = showScrollSpy;
138
+ let preset: ColumnPreset | null = null;
131
139
 
132
140
  try {
133
141
  const savedGroup = localStorage.getItem(STORAGE_KEY_GROUP);
@@ -135,9 +143,9 @@
135
143
  groupBy = savedGroup as CellTableGroupField;
136
144
  }
137
145
 
138
- const savedColumns = localStorage.getItem(STORAGE_KEY_COLUMNS);
139
- if (savedColumns) {
140
- columns = JSON.parse(savedColumns) as string[];
146
+ const savedPreset = localStorage.getItem(STORAGE_KEY_PRESET);
147
+ if (savedPreset) {
148
+ preset = savedPreset as ColumnPreset;
141
149
  }
142
150
 
143
151
  const savedFilters = localStorage.getItem(STORAGE_KEY_FILTERS);
@@ -152,7 +160,23 @@
152
160
  } catch (e) {
153
161
  console.warn('Failed to load CellTable settings:', e);
154
162
  }
155
- return { columns, filtersVisible: filters, scrollSpyEnabled: scrollSpy };
163
+ return { filtersVisible: filters, scrollSpyEnabled: scrollSpy, preset };
164
+ }
165
+
166
+ // Load columns for a specific preset
167
+ function loadColumnsForPreset(preset: ColumnPreset): string[] {
168
+ if (!persistSettings || typeof localStorage === 'undefined') {
169
+ return getPresetVisibleFields(preset);
170
+ }
171
+ try {
172
+ const saved = localStorage.getItem(getColumnsStorageKey(preset));
173
+ if (saved) {
174
+ return JSON.parse(saved) as string[];
175
+ }
176
+ } catch (e) {
177
+ console.warn('Failed to load columns for preset:', e);
178
+ }
179
+ return getPresetVisibleFields(preset);
156
180
  }
157
181
 
158
182
  // Save group setting
@@ -165,11 +189,11 @@
165
189
  }
166
190
  }
167
191
 
168
- // Save column visibility
192
+ // Save column visibility for current preset
169
193
  function saveColumnVisibility(columns: string[]) {
170
194
  if (!persistSettings || typeof localStorage === 'undefined') return;
171
195
  try {
172
- localStorage.setItem(STORAGE_KEY_COLUMNS, JSON.stringify(columns));
196
+ localStorage.setItem(getColumnsStorageKey(columnPreset), JSON.stringify(columns));
173
197
  } catch (e) {
174
198
  console.warn('Failed to save column visibility:', e);
175
199
  }
@@ -195,6 +219,16 @@
195
219
  }
196
220
  }
197
221
 
222
+ // Save column preset
223
+ function savePreset(preset: ColumnPreset) {
224
+ if (!persistSettings || typeof localStorage === 'undefined') return;
225
+ try {
226
+ localStorage.setItem(STORAGE_KEY_PRESET, preset);
227
+ } catch (e) {
228
+ console.warn('Failed to save preset:', e);
229
+ }
230
+ }
231
+
198
232
  let cellTable: CellTable;
199
233
  let selectedCount = $state(0);
200
234
  let selectedRows = $state<CellData[]>([]);
@@ -209,15 +243,44 @@
209
243
  // Initialize from storage or defaults
210
244
  const persistedSettings = loadPersistedSettings();
211
245
  let filtersVisible = $state(persistedSettings.filtersVisible);
212
- let visibleColumns = $state<string[]>(persistedSettings.columns ?? getPresetVisibleFields(columnPreset));
246
+
247
+ // Apply persisted preset if available
248
+ if (persistedSettings.preset) {
249
+ columnPreset = persistedSettings.preset;
250
+ }
251
+
252
+ // Load columns for the current preset (with any saved customizations)
253
+ let visibleColumns = $state<string[]>(loadColumnsForPreset(columnPreset));
213
254
 
214
255
  // ScrollSpy state - initialize from persisted settings
215
256
  let scrollSpyGroups = $state<{ key: string; count: number }[]>([]);
216
257
  let scrollSpyEnabled = $state(persistedSettings.scrollSpyEnabled);
217
258
 
218
- // Update visible columns when preset changes (but not from storage load)
259
+ // Track preset changes to load per-preset columns
260
+ let prevPreset: ColumnPreset | null = columnPreset;
261
+
262
+ // Apply column visibility to Tabulator
263
+ function applyColumnVisibility(columns: string[]) {
264
+ if (!cellTable) return;
265
+ columnMeta.forEach(col => {
266
+ if (columns.includes(col.field)) {
267
+ cellTable.showColumn(col.field);
268
+ } else {
269
+ cellTable.hideColumn(col.field);
270
+ }
271
+ });
272
+ }
273
+
274
+ // Update visible columns when preset changes - load saved customizations for that preset
219
275
  $effect(() => {
220
- visibleColumns = getPresetVisibleFields(columnPreset);
276
+ if (columnPreset !== prevPreset) {
277
+ prevPreset = columnPreset;
278
+ // Load saved columns for this preset (or preset defaults if none saved)
279
+ const newColumns = loadColumnsForPreset(columnPreset);
280
+ visibleColumns = newColumns;
281
+ // Apply to Tabulator
282
+ applyColumnVisibility(newColumns);
283
+ }
221
284
  });
222
285
 
223
286
  // Expose table methods via tableRef - only set once
@@ -227,6 +290,8 @@
227
290
  tableRef = {
228
291
  redraw: () => cellTable?.redraw()
229
292
  };
293
+ // Apply persisted column visibility after table is ready
294
+ setTimeout(() => applyColumnVisibility(visibleColumns), 100);
230
295
  // Apply persisted filter visibility after table is ready
231
296
  if (!filtersVisible) {
232
297
  setTimeout(() => cellTable?.toggleHeaderFilters(false), 100);
@@ -311,6 +376,7 @@
311
376
 
312
377
  function handlePresetChange(preset: ColumnPreset) {
313
378
  columnPreset = preset;
379
+ savePreset(preset);
314
380
  }
315
381
 
316
382
  function handleExportCSV() {
@@ -363,10 +429,10 @@
363
429
  cellTable?.hideColumn(col.field);
364
430
  }
365
431
  });
366
- // Clear persisted column visibility (use preset defaults)
432
+ // Clear persisted column visibility for this preset (use preset defaults)
367
433
  if (persistSettings && typeof localStorage !== 'undefined') {
368
434
  try {
369
- localStorage.removeItem(STORAGE_KEY_COLUMNS);
435
+ localStorage.removeItem(getColumnsStorageKey(columnPreset));
370
436
  } catch (e) {
371
437
  console.warn('Failed to clear column visibility:', e);
372
438
  }
@@ -512,6 +578,8 @@
512
578
  {techColors}
513
579
  {statusColors}
514
580
  {headerFilters}
581
+ {persistLayout}
582
+ storageKey="{storageKey}-tabulator"
515
583
  onselectionchange={handleSelectionChange}
516
584
  ondatachange={handleDataChange}
517
585
  onrowclick={handleRowClick}
@@ -39,6 +39,8 @@ interface Props {
39
39
  persistSettings?: boolean;
40
40
  /** Storage key prefix for persisted settings */
41
41
  storageKey?: string;
42
+ /** Enable Tabulator persistence for column widths, order, visibility */
43
+ persistLayout?: boolean;
42
44
  /** Show scrollspy navigation bar for quick group navigation */
43
45
  showScrollSpy?: boolean;
44
46
  /** Bindable reference to table methods */
@@ -54,10 +54,10 @@ export const FBAND_COLORS = {
54
54
  */
55
55
  export const COLUMN_GROUPS = {
56
56
  core: ['siteId', 'txId', 'cellName', 'tech', 'fband', 'status'],
57
- physical: ['antenna', 'azimuth', 'height', 'electricalTilt', 'beamwidth'],
58
- network: ['dlEarfn', 'bcch', 'pci1', 'cellId3', 'nwET', 'nwPW', 'nwRS', 'nwBW'],
59
- planning: ['planner', 'comment', 'onAirDate', 'type'],
60
- atoll: ['atollET', 'atollPW', 'atollRS', 'atollBW'],
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
61
  position: ['latitude', 'longitude', 'siteLatitude', 'siteLongitude', 'dx', 'dy'],
62
62
  compare: ['compareET', 'comparePW', 'compareRS', 'compareBW'],
63
63
  kpi: ['kpiTraffic', 'kpiThroughput', 'kpiAvailability', 'kpiSuccessRate'],
@@ -359,12 +359,6 @@ export function getAllColumns(techColors = DEFAULT_TECH_COLORS, statusColors = D
359
359
  formatter: createStatusFormatter(statusColors),
360
360
  ...selectHeaderFilter,
361
361
  },
362
- {
363
- title: 'Type',
364
- field: 'type',
365
- width: 100,
366
- ...selectHeaderFilter,
367
- },
368
362
  {
369
363
  title: 'On Air Date',
370
364
  field: 'onAirDate',
@@ -437,13 +431,6 @@ export function getAllColumns(techColors = DEFAULT_TECH_COLORS, statusColors = D
437
431
  formatter: heightFormatter,
438
432
  ...headerFilterParams,
439
433
  },
440
- {
441
- title: 'E-Tilt',
442
- field: 'electricalTilt',
443
- width: 80,
444
- hozAlign: 'right',
445
- ...headerFilterParams,
446
- },
447
434
  {
448
435
  title: 'Beamwidth',
449
436
  field: 'beamwidth',
@@ -469,17 +456,11 @@ export function getAllColumns(techColors = DEFAULT_TECH_COLORS, statusColors = D
469
456
  },
470
457
  {
471
458
  title: 'PCI',
472
- field: 'pci1',
459
+ field: 'pci',
473
460
  width: 80,
474
461
  hozAlign: 'right',
475
462
  ...headerFilterParams,
476
463
  },
477
- {
478
- title: 'Cell ID 3',
479
- field: 'cellId3',
480
- width: 100,
481
- ...headerFilterParams,
482
- },
483
464
  {
484
465
  title: 'Cell ID',
485
466
  field: 'cellID',
@@ -499,17 +480,25 @@ export function getAllColumns(techColors = DEFAULT_TECH_COLORS, statusColors = D
499
480
  ...headerFilterParams,
500
481
  },
501
482
  {
502
- title: 'NWT P1',
503
- field: 'nwP1',
483
+ title: 'RRU',
484
+ field: 'rru',
485
+ width: 100,
486
+ ...headerFilterParams,
487
+ },
488
+ {
489
+ title: 'NW ET',
490
+ field: 'nwET',
504
491
  width: 80,
505
492
  hozAlign: 'right',
493
+ formatter: numberFormatter(1),
506
494
  ...headerFilterParams,
507
495
  },
508
496
  {
509
- title: 'NWT P2',
510
- field: 'nwP2',
497
+ title: 'NW PW',
498
+ field: 'nwPW',
511
499
  width: 80,
512
500
  hozAlign: 'right',
501
+ formatter: numberFormatter(1),
513
502
  ...headerFilterParams,
514
503
  },
515
504
  {
@@ -798,34 +787,36 @@ export function getColumnMetadata() {
798
787
  { field: 'cellName', title: 'Cell Name', group: 'Core' },
799
788
  { field: 'tech', title: 'Technology', group: 'Core' },
800
789
  { field: 'fband', title: 'Band', group: 'Core' },
790
+ { field: 'rru', title: 'RRU', group: 'Core' },
801
791
  { field: 'frq', title: 'Frequency', group: 'Core' },
802
792
  { field: 'status', title: 'Status', group: 'Core' },
803
- { field: 'type', title: 'Type', group: 'Core' },
804
793
  { field: 'onAirDate', title: 'On Air Date', group: 'Core' },
805
- // Physical
806
- { field: 'antenna', title: 'Antenna', group: 'Physical' },
807
- { field: 'azimuth', title: 'Azimuth', group: 'Physical' },
808
- { field: 'height', title: 'Height', group: 'Physical' },
809
- { field: 'electricalTilt', title: 'E-Tilt', group: 'Physical' },
810
- { field: 'beamwidth', title: 'Beamwidth', group: 'Physical' },
811
- // Network
812
- { field: 'dlEarfn', title: 'DL EARFCN', group: 'Network' },
813
- { field: 'bcch', title: 'BCCH', group: 'Network' },
814
- { field: 'pci', title: 'PCI', group: 'Network' },
815
- { field: 'rru', title: 'RRU', group: 'Network' },
816
- { field: 'cellID', title: 'Cell ID', group: 'Network' },
817
- { field: 'cellId2G', title: 'Cell ID 2G', group: 'Network' },
818
- { field: 'ctrlid', title: 'Ctrl ID', group: 'Network' },
819
- { field: 'nwET', title: 'NW ET', group: 'Network' },
820
- { field: 'nwPW', title: 'NW PW', group: 'Network' },
821
- { field: 'nwRS', title: 'NW RS', group: 'Network' },
822
- { field: 'nwBW', title: 'NW BW', group: 'Network' },
823
- // Atoll
824
- { field: 'atollET', title: 'Atoll ET', group: 'Atoll' },
794
+ // Antenna Physical
795
+ { field: 'antenna', title: 'Antenna', group: 'Antenna Physical' },
796
+ { field: 'azimuth', title: 'Azimuth', group: 'Antenna Physical' },
797
+ { field: 'height', title: 'Height', group: 'Antenna Physical' },
798
+ { field: 'beamwidth', title: 'Beamwidth', group: 'Antenna Physical' },
825
799
  { field: 'atollMT', title: 'Atoll MT', group: 'Atoll' },
800
+ // Atoll antenna settings
801
+ { field: 'atollET', title: 'Atoll ET', group: 'Atoll' },
826
802
  { field: 'atollPW', title: 'Atoll PW', group: 'Atoll' },
827
803
  { field: 'atollRS', title: 'Atoll RS', group: 'Atoll' },
828
804
  { field: 'atollBW', title: 'Atoll BW', group: 'Atoll' },
805
+ // Network antena settings
806
+ { field: 'nwET', title: 'NW ET', group: 'Network' },
807
+ { field: 'nwPW', title: 'NW PW', group: 'Network' },
808
+ { field: 'nwRS', title: 'NW RS', group: 'Network' },
809
+ { field: 'nwBW', title: 'NW BW', group: 'Network' },
810
+ // Compare (Atoll vs Network)
811
+ { field: 'compareET', title: 'Δ ET', group: 'Compare' },
812
+ { field: 'comparePW', title: 'Δ PW', group: 'Compare' },
813
+ { field: 'compareRS', title: 'Δ RS', group: 'Compare' },
814
+ { field: 'compareBW', title: 'Δ BW', group: 'Compare' },
815
+ // Network settings
816
+ { field: 'dlEarfn', title: 'DL EARFCN', group: 'Network' },
817
+ { field: 'bcch', title: 'BCCH', group: 'Network' },
818
+ { field: 'pci', title: 'PCI', group: 'Network' },
819
+ { field: 'ctrlid', title: 'Ctrl ID', group: 'Network' },
829
820
  // History
830
821
  { field: 'configDate', title: 'Config Date', group: 'History' },
831
822
  { field: 'frequency', title: 'Freq (MHz)', group: 'History' },
@@ -833,27 +824,22 @@ export function getColumnMetadata() {
833
824
  { field: 'etiltChange', title: 'E-Tilt (Δ)', group: 'History' },
834
825
  { field: 'mtiltChange', title: 'M-Tilt (Δ)', group: 'History' },
835
826
  { field: 'powerChange', title: 'Power (Δ)', group: 'History' },
836
- // Compare (Atoll vs Network)
837
- { field: 'compareET', title: 'Δ ET', group: 'Compare' },
838
- { field: 'comparePW', title: 'Δ PW', group: 'Compare' },
839
- { field: 'compareRS', title: 'Δ RS', group: 'Compare' },
840
- { field: 'compareBW', title: 'Δ BW', group: 'Compare' },
841
827
  // KPI Trends
842
828
  { field: 'kpiTraffic', title: 'Traffic', group: 'KPI' },
843
829
  { field: 'kpiThroughput', title: 'Throughput', group: 'KPI' },
844
830
  { field: 'kpiAvailability', title: 'Availability', group: 'KPI' },
845
831
  { field: 'kpiSuccessRate', title: 'Success Rate', group: 'KPI' },
846
832
  // Position
847
- { field: 'latitude', title: 'Latitude', group: 'Position' },
848
- { field: 'longitude', title: 'Longitude', group: 'Position' },
849
- { field: 'siteLatitude', title: 'Site Latitude', group: 'Position' },
850
- { field: 'siteLongitude', title: 'Site Longitude', group: 'Position' },
851
- { field: 'dx', title: 'DX', group: 'Position' },
852
- { field: 'dy', title: 'DY', group: 'Position' },
833
+ // { field: 'latitude', title: 'Latitude', group: 'Position' },
834
+ // { field: 'longitude', title: 'Longitude', group: 'Position' },
835
+ // { field: 'siteLatitude', title: 'Site Latitude', group: 'Position' },
836
+ // { field: 'siteLongitude', title: 'Site Longitude', group: 'Position' },
837
+ // { field: 'dx', title: 'DX', group: 'Position' },
838
+ // { field: 'dy', title: 'DY', group: 'Position' },
853
839
  // Planning
854
840
  { field: 'planner', title: 'Planner', group: 'Planning' },
855
841
  { field: 'comment', title: 'Comment', group: 'Planning' },
856
- { field: 'customSubgroup', title: 'Subgroup', group: 'Planning' },
842
+ // { field: 'customSubgroup', title: 'Subgroup', group: 'Planning' },
857
843
  ];
858
844
  }
859
845
  /**
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@smartnet360/svelte-components",
3
- "version": "0.0.133",
3
+ "version": "0.0.134",
4
4
  "scripts": {
5
5
  "dev": "vite dev",
6
6
  "build": "vite build && npm run prepack",