@smartnet360/svelte-components 0.0.136 → 0.0.139

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.
@@ -5,5 +5,6 @@
5
5
  * Uses CellTableV2 for the underlying table functionality
6
6
  */
7
7
  export { default as CellHistoryPanel } from './CellHistoryPanel.svelte';
8
- export type { HistoryTableRow, CellHistoryPanelProps } from './types';
8
+ export type { CellHistoryData, HistoryTableRow, CellHistoryPanelProps } from './types';
9
9
  export { transformHistoryData, EXAMPLE_HISTORY_DATA } from './transformers';
10
+ export { getHistoryColumns, createHistoryChangeFormatter, historyDateFormatter, HISTORY_COLUMN_FIELDS, } from './column-config';
@@ -8,3 +8,5 @@
8
8
  export { default as CellHistoryPanel } from './CellHistoryPanel.svelte';
9
9
  // Utilities
10
10
  export { transformHistoryData, EXAMPLE_HISTORY_DATA } from './transformers';
11
+ // Column configuration
12
+ export { getHistoryColumns, createHistoryChangeFormatter, historyDateFormatter, HISTORY_COLUMN_FIELDS, } from './column-config';
@@ -363,12 +363,28 @@
363
363
  }
364
364
  }
365
365
 
366
+ /** Get set of all column fields in current table (for silent existence checks) */
367
+ function getColumnFields(): Set<string> {
368
+ if (!table) return new Set();
369
+ return new Set(
370
+ table.getColumns()
371
+ .map(col => col.getField())
372
+ .filter((field): field is string => !!field)
373
+ );
374
+ }
375
+
366
376
  export function showColumn(field: string): void {
367
- table?.showColumn(field);
377
+ // Only show if column exists in current table (silent check)
378
+ if (getColumnFields().has(field)) {
379
+ table?.showColumn(field);
380
+ }
368
381
  }
369
382
 
370
383
  export function hideColumn(field: string): void {
371
- table?.hideColumn(field);
384
+ // Only hide if column exists in current table (silent check)
385
+ if (getColumnFields().has(field)) {
386
+ table?.hideColumn(field);
387
+ }
372
388
  }
373
389
 
374
390
  export function getVisibleColumns(): string[] {
@@ -176,13 +176,16 @@
176
176
 
177
177
  // ========== Effects ==========
178
178
 
179
- // Track preset changes to apply column visibility
179
+ // Track preset changes to apply column visibility (only when not using customColumns)
180
180
  let prevPreset: ColumnPreset | null = columnVis.columnPreset;
181
181
 
182
182
  $effect(() => {
183
183
  if (columnVis.columnPreset !== prevPreset) {
184
184
  prevPreset = columnVis.columnPreset;
185
- columnVis.applyToTable(cellTable);
185
+ // Skip column visibility management when using custom columns
186
+ if (!customColumns) {
187
+ columnVis.applyToTable(cellTable);
188
+ }
186
189
  }
187
190
  });
188
191
 
@@ -193,8 +196,10 @@
193
196
  tableRef = {
194
197
  redraw: () => cellTable?.redraw()
195
198
  };
196
- // Apply persisted column visibility after table is ready
197
- setTimeout(() => columnVis.applyToTable(cellTable), 100);
199
+ // Apply persisted column visibility after table is ready (only when not using customColumns)
200
+ if (!customColumns) {
201
+ setTimeout(() => columnVis.applyToTable(cellTable), 100);
202
+ }
198
203
  // Apply persisted filter visibility after table is ready
199
204
  if (!filtersVisible) {
200
205
  setTimeout(() => cellTable?.toggleHeaderFilters(false), 100);
@@ -489,73 +494,124 @@
489
494
  {#if detailsContent}
490
495
  {@render detailsContent({ cell: clickedCell, closeSidebar })}
491
496
  {:else if clickedCell}
492
- <!-- Default details view -->
497
+ {@const entries = Object.entries(clickedCell)}
498
+ {@const identityFields = ['id', 'cellName', 'siteId', 'sector']}
499
+ {@const techFields = ['tech', 'fband', 'frq', 'status']}
500
+ {@const physicalFields = ['azimuth', 'height', 'beamwidth', 'electricalTilt', 'mechanicalTilt', 'antenna']}
501
+ {@const locationFields = ['latitude', 'longitude']}
502
+ {@const networkFields = ['nwET', 'nwPW', 'nwRS', 'nwBW', 'atollET', 'atollPW', 'atollRS', 'atollBW', 'atollMT']}
503
+ {@const planningFields = ['planner', 'onAirDate', 'comment']}
504
+ {@const knownFields = [...identityFields, ...techFields, ...physicalFields, ...locationFields, ...networkFields, ...planningFields]}
505
+ {@const otherFields = entries.filter(([k]) => !knownFields.includes(k)).map(([k]) => k)}
506
+
493
507
  <dl class="row mb-0 small">
494
- <dt class="col-5 text-muted">ID</dt>
495
- <dd class="col-7"><code class="text-primary">{clickedCell.id}</code></dd>
496
-
497
- <dt class="col-5 text-muted">Cell Name</dt>
498
- <dd class="col-7 fw-medium">{clickedCell.cellName}</dd>
499
-
500
- <dt class="col-5 text-muted">Site</dt>
501
- <dd class="col-7">{clickedCell.siteId}</dd>
502
-
503
- <dt class="col-5 text-muted">Technology</dt>
504
- <dd class="col-7">
505
- <span class="badge" style="background-color: {techColors?.[clickedCell.tech] ?? DEFAULT_TECH_COLORS[clickedCell.tech] ?? '#6c757d'}; color: white;">{clickedCell.tech}</span>
506
- </dd>
507
-
508
- <dt class="col-5 text-muted">Band</dt>
509
- <dd class="col-7">
510
- <span class="badge" style="background-color: {FBAND_COLORS[clickedCell.fband] ?? '#6c757d'}; color: white;">{clickedCell.fband}</span>
511
- </dd>
512
-
513
- <dt class="col-5 text-muted">Frequency</dt>
514
- <dd class="col-7">{clickedCell.frq} MHz</dd>
515
-
516
- <dt class="col-5 text-muted">Status</dt>
517
- <dd class="col-7">
518
- <span class="badge" style="background-color: {statusColors?.[clickedCell.status] ?? DEFAULT_STATUS_COLORS[clickedCell.status] ?? '#6c757d'}; color: white;">{clickedCell.status.replace(/_/g, ' ')}</span>
519
- </dd>
520
-
521
- <dt class="col-12 text-muted mt-2 mb-1 border-top pt-2">Physical</dt>
522
-
523
- <dt class="col-5 text-muted">Azimuth</dt>
524
- <dd class="col-7">{clickedCell.azimuth}°</dd>
525
-
526
- <dt class="col-5 text-muted">Height</dt>
527
- <dd class="col-7">{clickedCell.height}m</dd>
528
-
529
- <dt class="col-5 text-muted">Beamwidth</dt>
530
- <dd class="col-7">{clickedCell.beamwidth}°</dd>
531
-
532
- <dt class="col-5 text-muted">E-Tilt</dt>
533
- <dd class="col-7">{clickedCell.electricalTilt}°</dd>
534
-
535
- <dt class="col-5 text-muted">Antenna</dt>
536
- <dd class="col-7 text-truncate" title={clickedCell.antenna}>
537
- {clickedCell.antenna}
538
- </dd>
539
-
540
- <dt class="col-12 text-muted mt-2 mb-1 border-top pt-2">Location</dt>
541
-
542
- <dt class="col-5 text-muted">Latitude</dt>
543
- <dd class="col-7">{clickedCell.latitude.toFixed(6)}</dd>
544
-
545
- <dt class="col-5 text-muted">Longitude</dt>
546
- <dd class="col-7">{clickedCell.longitude.toFixed(6)}</dd>
547
-
548
- <dt class="col-12 text-muted mt-2 mb-1 border-top pt-2">Planning</dt>
508
+ <!-- Identity -->
509
+ <dt class="col-12 text-muted border-bottom pb-1 mb-2">Identity</dt>
510
+ {#each identityFields as field}
511
+ {@const value = clickedCell[field as keyof typeof clickedCell]}
512
+ {#if value !== undefined}
513
+ <dt class="col-5 text-muted">{field}</dt>
514
+ <dd class="col-7">
515
+ {#if field === 'id'}
516
+ <code class="text-primary">{value}</code>
517
+ {:else}
518
+ <span class="fw-medium">{value}</span>
519
+ {/if}
520
+ </dd>
521
+ {/if}
522
+ {/each}
523
+
524
+ <!-- Technology -->
525
+ <dt class="col-12 text-muted border-bottom pb-1 mb-2 mt-2">Technology</dt>
526
+ {#each techFields as field}
527
+ {@const value = clickedCell[field as keyof typeof clickedCell]}
528
+ {#if value !== undefined}
529
+ <dt class="col-5 text-muted">{field}</dt>
530
+ <dd class="col-7">
531
+ {#if field === 'tech'}
532
+ <span class="badge" style="background-color: {techColors?.[value as string] ?? DEFAULT_TECH_COLORS[value as string] ?? '#6c757d'}; color: white;">{value}</span>
533
+ {:else if field === 'fband'}
534
+ <span class="badge" style="background-color: {FBAND_COLORS[value as string] ?? '#6c757d'}; color: white;">{value}</span>
535
+ {:else if field === 'status'}
536
+ <span class="badge" style="background-color: {statusColors?.[value as string] ?? DEFAULT_STATUS_COLORS[value as string] ?? '#6c757d'}; color: white;">{String(value).replace(/_/g, ' ')}</span>
537
+ {:else if field === 'frq'}
538
+ {value} MHz
539
+ {:else}
540
+ {value}
541
+ {/if}
542
+ </dd>
543
+ {/if}
544
+ {/each}
545
+
546
+ <!-- Physical -->
547
+ <dt class="col-12 text-muted border-bottom pb-1 mb-2 mt-2">Physical</dt>
548
+ {#each physicalFields as field}
549
+ {@const value = clickedCell[field as keyof typeof clickedCell]}
550
+ {#if value !== undefined}
551
+ <dt class="col-5 text-muted">{field}</dt>
552
+ <dd class="col-7 text-truncate" title={String(value)}>
553
+ {#if field === 'azimuth' || field === 'beamwidth' || field === 'electricalTilt' || field === 'mechanicalTilt'}
554
+ {value}°
555
+ {:else if field === 'height'}
556
+ {value}m
557
+ {:else}
558
+ {value}
559
+ {/if}
560
+ </dd>
561
+ {/if}
562
+ {/each}
563
+
564
+ <!-- Location -->
565
+ {#if locationFields.some(f => clickedCell[f as keyof typeof clickedCell] !== undefined)}
566
+ <dt class="col-12 text-muted border-bottom pb-1 mb-2 mt-2">Location</dt>
567
+ {#each locationFields as field}
568
+ {@const value = clickedCell[field as keyof typeof clickedCell]}
569
+ {#if value !== undefined}
570
+ <dt class="col-5 text-muted">{field}</dt>
571
+ <dd class="col-7 font-monospace">{typeof value === 'number' ? value.toFixed(6) : value}</dd>
572
+ {/if}
573
+ {/each}
574
+ {/if}
549
575
 
550
- <dt class="col-5 text-muted">Planner</dt>
551
- <dd class="col-7">{clickedCell.planner}</dd>
576
+ <!-- Network -->
577
+ {#if networkFields.some(f => clickedCell[f as keyof typeof clickedCell] !== undefined)}
578
+ <dt class="col-12 text-muted border-bottom pb-1 mb-2 mt-2">Network</dt>
579
+ {#each networkFields as field}
580
+ {@const value = clickedCell[field as keyof typeof clickedCell]}
581
+ {#if value !== undefined}
582
+ <dt class="col-5 text-muted">{field}</dt>
583
+ <dd class="col-7">{typeof value === 'number' ? (Number.isInteger(value) ? value : value.toFixed(2)) : value}</dd>
584
+ {/if}
585
+ {/each}
586
+ {/if}
552
587
 
553
- <dt class="col-5 text-muted">On Air</dt>
554
- <dd class="col-7">{clickedCell.onAirDate}</dd>
588
+ <!-- Planning -->
589
+ {#if planningFields.some(f => clickedCell[f as keyof typeof clickedCell] !== undefined)}
590
+ <dt class="col-12 text-muted border-bottom pb-1 mb-2 mt-2">Planning</dt>
591
+ {#each planningFields as field}
592
+ {@const value = clickedCell[field as keyof typeof clickedCell]}
593
+ {#if value !== undefined && value !== ''}
594
+ <dt class="col-5 text-muted">{field}</dt>
595
+ <dd class="col-7 {field === 'comment' ? 'fst-italic' : ''}">{value}</dd>
596
+ {/if}
597
+ {/each}
598
+ {/if}
555
599
 
556
- {#if clickedCell.comment}
557
- <dt class="col-5 text-muted">Comment</dt>
558
- <dd class="col-7 fst-italic">{clickedCell.comment}</dd>
600
+ <!-- Other -->
601
+ {#if otherFields.length > 0}
602
+ <dt class="col-12 text-muted border-bottom pb-1 mb-2 mt-2">Other</dt>
603
+ {#each otherFields as field}
604
+ {@const value = clickedCell[field as keyof typeof clickedCell]}
605
+ {@const displayValue = value === null || value === undefined ? '' :
606
+ typeof value === 'number' ? (Number.isInteger(value) ? value : value.toFixed(4)) :
607
+ typeof value === 'boolean' ? (value ? 'Yes' : 'No') :
608
+ typeof value === 'object' ? JSON.stringify(value) :
609
+ String(value)}
610
+ {#if displayValue !== ''}
611
+ <dt class="col-5 text-muted text-truncate" title={field}>{field}</dt>
612
+ <dd class="col-7 text-truncate" title={String(displayValue)}>{displayValue}</dd>
613
+ {/if}
614
+ {/each}
559
615
  {/if}
560
616
  </dl>
561
617
  {:else}
@@ -9,4 +9,5 @@ export { default as CellTableToolbar } from './CellTableToolbar.svelte';
9
9
  export { default as ColumnPicker } from './ColumnPicker.svelte';
10
10
  export * from './composables';
11
11
  export { DEFAULT_TECH_COLORS, DEFAULT_STATUS_COLORS, FBAND_COLORS, COLUMN_GROUPS, getColumnMetadata, getColumnsForPreset, getPresetVisibleFields, getAllColumns, } from './column-config';
12
- export type { CellData, CellTableColumn, CellTableGroupField, CellTableProps, ColumnPreset, GroupOption, RowSelectionEvent, RowClickEvent, RowDblClickEvent, RowContextMenuEvent, DataChangeEvent, TechColorMap, StatusColorMap, } from './types';
12
+ export type { ColumnMeta, ColumnMetadataOptions, } from './column-config';
13
+ export type { CellData, CellHistoryData, CellTableColumn, CellTableGroupField, CellTableProps, ColumnPreset, GroupOption, RowSelectionEvent, RowClickEvent, RowDblClickEvent, RowContextMenuEvent, DataChangeEvent, TechColorMap, StatusColorMap, } from './types';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@smartnet360/svelte-components",
3
- "version": "0.0.136",
3
+ "version": "0.0.139",
4
4
  "scripts": {
5
5
  "dev": "vite dev",
6
6
  "build": "vite build && npm run prepack",