@smartnet360/svelte-components 0.0.134 → 0.0.136
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 → CellTableV2}/CellTable.svelte +7 -3
- package/dist/core/{CellTable → CellTableV2}/CellTable.svelte.d.ts +3 -0
- package/dist/core/{CellTable → CellTableV2}/CellTablePanel.svelte +87 -235
- package/dist/core/{CellTable → CellTableV2}/CellTablePanel.svelte.d.ts +16 -2
- package/dist/core/{CellTable → CellTableV2}/CellTableToolbar.svelte +0 -1
- package/dist/core/{CellTable → CellTableV2}/column-config.d.ts +11 -30
- package/dist/core/{CellTable → CellTableV2}/column-config.js +21 -220
- 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/{CellTable → CellTableV2}/types.d.ts +3 -3
- package/dist/core/index.d.ts +2 -1
- package/dist/core/index.js +3 -1
- package/package.json +1 -1
- package/dist/core/CellTable/CellHistoryDemo.svelte +0 -240
- package/dist/core/CellTable/CellHistoryDemo.svelte.d.ts +0 -3
- package/dist/core/CellTable/CellTableDemo.svelte +0 -336
- package/dist/core/CellTable/CellTableDemo.svelte.d.ts +0 -3
- package/dist/core/CellTable/history-api-helper.d.ts +0 -79
- package/dist/core/CellTable/history-api-helper.js +0 -83
- package/dist/core/CellTable/index.d.ts +0 -15
- package/dist/core/CellTable/index.js +0 -20
- /package/dist/core/{CellTable → CellTableV2}/CellTableToolbar.svelte.d.ts +0 -0
- /package/dist/core/{CellTable → CellTableV2}/ColumnPicker.svelte +0 -0
- /package/dist/core/{CellTable → CellTableV2}/ColumnPicker.svelte.d.ts +0 -0
- /package/dist/core/{CellTable → CellTableV2}/types.js +0 -0
|
@@ -0,0 +1,178 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import CellTablePanel from '../CellTableV2/CellTablePanel.svelte';
|
|
3
|
+
import type { RowSelectionEvent, CellData } from '../CellTableV2/types';
|
|
4
|
+
import type { HistoryTableRow, CellHistoryPanelProps } from './types';
|
|
5
|
+
import type { CellHistoryData } from '../CellTableV2/types';
|
|
6
|
+
import { transformHistoryData, EXAMPLE_HISTORY_DATA } from './transformers';
|
|
7
|
+
import { getHistoryColumns } from './column-config';
|
|
8
|
+
|
|
9
|
+
let {
|
|
10
|
+
cellName = $bindable('1001141'),
|
|
11
|
+
historyData: externalData,
|
|
12
|
+
storageKey = 'cell-history-table',
|
|
13
|
+
showToolbar = true,
|
|
14
|
+
showExport = true,
|
|
15
|
+
headerFilters = true,
|
|
16
|
+
title = 'Cell Configuration History',
|
|
17
|
+
onselectionchange,
|
|
18
|
+
oncompare,
|
|
19
|
+
}: CellHistoryPanelProps = $props();
|
|
20
|
+
|
|
21
|
+
// Get history-specific columns
|
|
22
|
+
const historyColumns = getHistoryColumns(headerFilters);
|
|
23
|
+
|
|
24
|
+
// Internal state for API data
|
|
25
|
+
let rawHistoryData = $state<CellHistoryData[]>(EXAMPLE_HISTORY_DATA);
|
|
26
|
+
|
|
27
|
+
// Use external data if provided, otherwise transform internal data
|
|
28
|
+
let historyData = $derived(externalData ?? transformHistoryData(rawHistoryData));
|
|
29
|
+
|
|
30
|
+
function loadHistory() {
|
|
31
|
+
// TODO: Replace with actual API call
|
|
32
|
+
console.log(`Loading history for cell: ${cellName}`);
|
|
33
|
+
rawHistoryData = EXAMPLE_HISTORY_DATA.filter(r => r.CELLNAME === cellName);
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
function handleSelectionChange(event: RowSelectionEvent) {
|
|
37
|
+
console.log('Selection changed:', event.ids);
|
|
38
|
+
onselectionchange?.({
|
|
39
|
+
ids: event.ids,
|
|
40
|
+
rows: event.rows as unknown as HistoryTableRow[]
|
|
41
|
+
});
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* Compare two selected history records - opens antenna compare tool
|
|
46
|
+
*/
|
|
47
|
+
function handleCompareTwoRecords(record1: HistoryTableRow, record2: HistoryTableRow) {
|
|
48
|
+
// Allow external handler to override
|
|
49
|
+
if (oncompare) {
|
|
50
|
+
oncompare(record1, record2);
|
|
51
|
+
return;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
// Default behavior: open antenna compare page
|
|
55
|
+
const params = new URLSearchParams();
|
|
56
|
+
|
|
57
|
+
// Use antenna from both records
|
|
58
|
+
if (record1.antenna) params.set('ant1', record1.antenna);
|
|
59
|
+
if (record2.antenna) params.set('ant2', record2.antenna);
|
|
60
|
+
|
|
61
|
+
// Use frequency (same for both records typically)
|
|
62
|
+
params.set('freq1', String(record1.frequency || 1800));
|
|
63
|
+
params.set('freq2', String(record2.frequency || 1800));
|
|
64
|
+
|
|
65
|
+
// Use electrical tilt values
|
|
66
|
+
params.set('etilt1', String(record1.electricalTilt || 0));
|
|
67
|
+
params.set('etilt2', String(record2.electricalTilt || 0));
|
|
68
|
+
|
|
69
|
+
// Use mechanical tilt values
|
|
70
|
+
params.set('mtilt1', String(record1.mechanicalTilt || 0));
|
|
71
|
+
params.set('mtilt2', String(record2.mechanicalTilt || 0));
|
|
72
|
+
|
|
73
|
+
// Add config date as labels
|
|
74
|
+
params.set('label1', `${record1.cellName} (${record1.configDate})`);
|
|
75
|
+
params.set('label2', `${record2.cellName} (${record2.configDate})`);
|
|
76
|
+
|
|
77
|
+
const url = `/apps/antenna-compare?${params.toString()}`;
|
|
78
|
+
window.open(url, '_blank');
|
|
79
|
+
}
|
|
80
|
+
</script>
|
|
81
|
+
|
|
82
|
+
<div class="cell-history-panel vh-100 d-flex flex-column">
|
|
83
|
+
<!-- Header -->
|
|
84
|
+
<div class="history-controls bg-light border-bottom px-3 py-2 d-flex align-items-center gap-3 flex-wrap">
|
|
85
|
+
<div class="input-group input-group-sm" style="width: auto;">
|
|
86
|
+
<span class="input-group-text">Cell Name</span>
|
|
87
|
+
<input
|
|
88
|
+
type="text"
|
|
89
|
+
class="form-control"
|
|
90
|
+
bind:value={cellName}
|
|
91
|
+
style="width: 120px;"
|
|
92
|
+
/>
|
|
93
|
+
<button class="btn btn-outline-primary" onclick={loadHistory}>
|
|
94
|
+
<i class="bi bi-arrow-clockwise"></i> Load History
|
|
95
|
+
</button>
|
|
96
|
+
</div>
|
|
97
|
+
<span class="badge bg-info">
|
|
98
|
+
{historyData.length} records
|
|
99
|
+
</span>
|
|
100
|
+
<span class="text-muted small">
|
|
101
|
+
Select 2 rows to compare antenna configurations
|
|
102
|
+
</span>
|
|
103
|
+
</div>
|
|
104
|
+
|
|
105
|
+
<!-- CellTablePanel with custom history columns -->
|
|
106
|
+
<div class="flex-grow-1 overflow-hidden">
|
|
107
|
+
<CellTablePanel
|
|
108
|
+
cells={historyData as unknown as CellData[]}
|
|
109
|
+
groupBy="none"
|
|
110
|
+
{storageKey}
|
|
111
|
+
groupOptions={[
|
|
112
|
+
{ value: 'none', label: 'No Grouping' },
|
|
113
|
+
{ value: 'antenna', label: 'Antenna Type' },
|
|
114
|
+
{ value: 'cellname', label: 'Cell Name' },
|
|
115
|
+
]}
|
|
116
|
+
customColumns={historyColumns}
|
|
117
|
+
showColumnPresets={false}
|
|
118
|
+
selectable={true}
|
|
119
|
+
multiSelect={true}
|
|
120
|
+
{showToolbar}
|
|
121
|
+
{showExport}
|
|
122
|
+
{headerFilters}
|
|
123
|
+
showDetailsSidebar={false}
|
|
124
|
+
showScrollSpy={false}
|
|
125
|
+
{title}
|
|
126
|
+
onselectionchange={handleSelectionChange}
|
|
127
|
+
>
|
|
128
|
+
{#snippet footer({ selectedRows, selectedCount })}
|
|
129
|
+
<div class="d-flex align-items-center justify-content-between">
|
|
130
|
+
<span class="text-muted small">
|
|
131
|
+
{#if selectedCount > 0}
|
|
132
|
+
{selectedCount} record(s) selected
|
|
133
|
+
{:else}
|
|
134
|
+
Select rows to compare configurations
|
|
135
|
+
{/if}
|
|
136
|
+
</span>
|
|
137
|
+
<div class="btn-group">
|
|
138
|
+
<button
|
|
139
|
+
type="button"
|
|
140
|
+
class="btn btn-sm btn-outline-success"
|
|
141
|
+
disabled={selectedCount !== 2}
|
|
142
|
+
title={selectedCount === 2
|
|
143
|
+
? 'Compare antenna patterns for selected dates'
|
|
144
|
+
: 'Select exactly 2 records to compare'}
|
|
145
|
+
onclick={() =>
|
|
146
|
+
handleCompareTwoRecords(
|
|
147
|
+
selectedRows[0] as unknown as HistoryTableRow,
|
|
148
|
+
selectedRows[1] as unknown as HistoryTableRow
|
|
149
|
+
)}
|
|
150
|
+
>
|
|
151
|
+
<i class="bi bi-broadcast-pin"></i>
|
|
152
|
+
<span class="d-none d-sm-inline ms-1">Compare Antennas</span>
|
|
153
|
+
</button>
|
|
154
|
+
<button
|
|
155
|
+
type="button"
|
|
156
|
+
class="btn btn-sm btn-outline-secondary"
|
|
157
|
+
disabled={selectedCount === 0}
|
|
158
|
+
onclick={() => console.log('Export:', selectedRows.map((r) => r.configDate))}
|
|
159
|
+
>
|
|
160
|
+
<i class="bi bi-download"></i>
|
|
161
|
+
<span class="d-none d-sm-inline ms-1">Export</span>
|
|
162
|
+
</button>
|
|
163
|
+
</div>
|
|
164
|
+
</div>
|
|
165
|
+
{/snippet}
|
|
166
|
+
</CellTablePanel>
|
|
167
|
+
</div>
|
|
168
|
+
</div>
|
|
169
|
+
|
|
170
|
+
<style>
|
|
171
|
+
.cell-history-panel {
|
|
172
|
+
background: var(--bs-body-bg, #f8f9fa);
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
.history-controls {
|
|
176
|
+
flex-shrink: 0;
|
|
177
|
+
}
|
|
178
|
+
</style>
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* CellHistory - Column Configuration
|
|
3
|
+
*
|
|
4
|
+
* History-specific column definitions and formatters
|
|
5
|
+
*/
|
|
6
|
+
import type { ColumnDefinition, CellComponent } from 'tabulator-tables';
|
|
7
|
+
/**
|
|
8
|
+
* Create a history change formatter for showing current vs previous values
|
|
9
|
+
* Highlights changes in yellow/amber, unchanged values in muted style
|
|
10
|
+
*
|
|
11
|
+
* @param currentField - Field name for current value
|
|
12
|
+
* @param prevField - Field name for previous value
|
|
13
|
+
*/
|
|
14
|
+
export declare function createHistoryChangeFormatter(currentField: string, prevField: string): (cell: CellComponent) => string;
|
|
15
|
+
/**
|
|
16
|
+
* Format ISO date string to YYYY-MM-DD format for history display
|
|
17
|
+
*/
|
|
18
|
+
export declare function historyDateFormatter(cell: CellComponent): string;
|
|
19
|
+
/**
|
|
20
|
+
* Get history-specific column definitions
|
|
21
|
+
*/
|
|
22
|
+
export declare function getHistoryColumns(headerFilters?: boolean): ColumnDefinition[];
|
|
23
|
+
/**
|
|
24
|
+
* History column fields for visibility tracking
|
|
25
|
+
*/
|
|
26
|
+
export declare const HISTORY_COLUMN_FIELDS: string[];
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* CellHistory - Column Configuration
|
|
3
|
+
*
|
|
4
|
+
* History-specific column definitions and formatters
|
|
5
|
+
*/
|
|
6
|
+
/**
|
|
7
|
+
* Create a history change formatter for showing current vs previous values
|
|
8
|
+
* Highlights changes in yellow/amber, unchanged values in muted style
|
|
9
|
+
*
|
|
10
|
+
* @param currentField - Field name for current value
|
|
11
|
+
* @param prevField - Field name for previous value
|
|
12
|
+
*/
|
|
13
|
+
export function createHistoryChangeFormatter(currentField, prevField) {
|
|
14
|
+
return (cell) => {
|
|
15
|
+
const row = cell.getRow().getData();
|
|
16
|
+
const currentVal = row[currentField];
|
|
17
|
+
const prevVal = row[prevField];
|
|
18
|
+
const currentStr = currentVal !== null && currentVal !== undefined ? String(currentVal) : '-';
|
|
19
|
+
const prevStr = prevVal !== null && prevVal !== undefined ? String(prevVal) : '-';
|
|
20
|
+
const hasChanged = currentVal !== prevVal;
|
|
21
|
+
if (hasChanged) {
|
|
22
|
+
// Value changed - highlight with amber/warning color
|
|
23
|
+
return `<span class="badge bg-warning text-dark" style="font-size: 0.75rem; font-weight: 500;" title="Changed from: ${prevStr}">${currentStr}</span>`;
|
|
24
|
+
}
|
|
25
|
+
else {
|
|
26
|
+
// No change - muted style
|
|
27
|
+
return `<span class="text-muted">${currentStr}</span>`;
|
|
28
|
+
}
|
|
29
|
+
};
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Format ISO date string to YYYY-MM-DD format for history display
|
|
33
|
+
*/
|
|
34
|
+
export function historyDateFormatter(cell) {
|
|
35
|
+
const value = cell.getValue();
|
|
36
|
+
if (!value)
|
|
37
|
+
return '-';
|
|
38
|
+
try {
|
|
39
|
+
const date = new Date(value);
|
|
40
|
+
const year = date.getFullYear();
|
|
41
|
+
const month = String(date.getMonth() + 1).padStart(2, '0');
|
|
42
|
+
const day = String(date.getDate()).padStart(2, '0');
|
|
43
|
+
return `${year}-${month}-${day}`;
|
|
44
|
+
}
|
|
45
|
+
catch {
|
|
46
|
+
return value;
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Get history-specific column definitions
|
|
51
|
+
*/
|
|
52
|
+
export function getHistoryColumns(headerFilters = true) {
|
|
53
|
+
const headerFilterParams = headerFilters ? { headerFilter: 'input' } : {};
|
|
54
|
+
return [
|
|
55
|
+
// Core identifier
|
|
56
|
+
{
|
|
57
|
+
title: 'Cell Name',
|
|
58
|
+
field: 'cellName',
|
|
59
|
+
width: 120,
|
|
60
|
+
frozen: true,
|
|
61
|
+
...headerFilterParams,
|
|
62
|
+
},
|
|
63
|
+
// History-specific columns
|
|
64
|
+
{
|
|
65
|
+
title: 'Config Date',
|
|
66
|
+
field: 'configDate',
|
|
67
|
+
width: 120,
|
|
68
|
+
formatter: historyDateFormatter,
|
|
69
|
+
...headerFilterParams,
|
|
70
|
+
},
|
|
71
|
+
{
|
|
72
|
+
title: 'Freq (MHz)',
|
|
73
|
+
field: 'frequency',
|
|
74
|
+
width: 100,
|
|
75
|
+
hozAlign: 'right',
|
|
76
|
+
...headerFilterParams,
|
|
77
|
+
},
|
|
78
|
+
// Change columns (current vs previous, highlights differences)
|
|
79
|
+
{
|
|
80
|
+
title: 'Antenna',
|
|
81
|
+
field: 'antennaChange',
|
|
82
|
+
width: 160,
|
|
83
|
+
formatter: createHistoryChangeFormatter('antenna', 'prevAntenna'),
|
|
84
|
+
...headerFilterParams,
|
|
85
|
+
},
|
|
86
|
+
{
|
|
87
|
+
title: 'E-Tilt',
|
|
88
|
+
field: 'etiltChange',
|
|
89
|
+
width: 80,
|
|
90
|
+
hozAlign: 'center',
|
|
91
|
+
formatter: createHistoryChangeFormatter('electricalTilt', 'prevElectricalTilt'),
|
|
92
|
+
},
|
|
93
|
+
{
|
|
94
|
+
title: 'M-Tilt',
|
|
95
|
+
field: 'mtiltChange',
|
|
96
|
+
width: 80,
|
|
97
|
+
hozAlign: 'center',
|
|
98
|
+
formatter: createHistoryChangeFormatter('mechanicalTilt', 'prevMechanicalTilt'),
|
|
99
|
+
},
|
|
100
|
+
{
|
|
101
|
+
title: 'Power',
|
|
102
|
+
field: 'powerChange',
|
|
103
|
+
width: 80,
|
|
104
|
+
hozAlign: 'center',
|
|
105
|
+
formatter: createHistoryChangeFormatter('power', 'prevPower'),
|
|
106
|
+
},
|
|
107
|
+
];
|
|
108
|
+
}
|
|
109
|
+
/**
|
|
110
|
+
* History column fields for visibility tracking
|
|
111
|
+
*/
|
|
112
|
+
export const HISTORY_COLUMN_FIELDS = [
|
|
113
|
+
'cellName',
|
|
114
|
+
'configDate',
|
|
115
|
+
'frequency',
|
|
116
|
+
'antennaChange',
|
|
117
|
+
'etiltChange',
|
|
118
|
+
'mtiltChange',
|
|
119
|
+
'powerChange'
|
|
120
|
+
];
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Cell History Feature
|
|
3
|
+
*
|
|
4
|
+
* Cell configuration history tracking and comparison
|
|
5
|
+
* Uses CellTableV2 for the underlying table functionality
|
|
6
|
+
*/
|
|
7
|
+
export { default as CellHistoryPanel } from './CellHistoryPanel.svelte';
|
|
8
|
+
export type { HistoryTableRow, CellHistoryPanelProps } from './types';
|
|
9
|
+
export { transformHistoryData, EXAMPLE_HISTORY_DATA } from './transformers';
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Cell History Feature
|
|
3
|
+
*
|
|
4
|
+
* Cell configuration history tracking and comparison
|
|
5
|
+
* Uses CellTableV2 for the underlying table functionality
|
|
6
|
+
*/
|
|
7
|
+
// Main component
|
|
8
|
+
export { default as CellHistoryPanel } from './CellHistoryPanel.svelte';
|
|
9
|
+
// Utilities
|
|
10
|
+
export { transformHistoryData, EXAMPLE_HISTORY_DATA } from './transformers';
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Cell History Transformers
|
|
3
|
+
*
|
|
4
|
+
* Functions to transform API data to table-ready format
|
|
5
|
+
*/
|
|
6
|
+
import type { CellHistoryData } from '../CellTableV2/types';
|
|
7
|
+
import type { HistoryTableRow } from './types';
|
|
8
|
+
/**
|
|
9
|
+
* Transform API history data to table-friendly format
|
|
10
|
+
* Maps UPPER_CASE API fields to camelCase and adds virtual fields for change detection
|
|
11
|
+
*/
|
|
12
|
+
export declare function transformHistoryData(apiData: CellHistoryData[]): HistoryTableRow[];
|
|
13
|
+
/**
|
|
14
|
+
* Example API data for cell configuration history (for demos/testing)
|
|
15
|
+
*/
|
|
16
|
+
export declare const EXAMPLE_HISTORY_DATA: CellHistoryData[];
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Cell History Transformers
|
|
3
|
+
*
|
|
4
|
+
* Functions to transform API data to table-ready format
|
|
5
|
+
*/
|
|
6
|
+
/**
|
|
7
|
+
* Transform API history data to table-friendly format
|
|
8
|
+
* Maps UPPER_CASE API fields to camelCase and adds virtual fields for change detection
|
|
9
|
+
*/
|
|
10
|
+
export function transformHistoryData(apiData) {
|
|
11
|
+
return apiData.map((record, index) => ({
|
|
12
|
+
id: `hist-${index}`,
|
|
13
|
+
cellName: record.CELLNAME,
|
|
14
|
+
frequency: record.FREQUENCY,
|
|
15
|
+
configDate: record.CONFIG_DATE,
|
|
16
|
+
// Current values
|
|
17
|
+
antenna: record.ANTENNA_TYPE,
|
|
18
|
+
electricalTilt: record.ELECTRONIC_TILT,
|
|
19
|
+
mechanicalTilt: record.MECHANIC_TILT,
|
|
20
|
+
power: record.ANTOUTPUTPWR,
|
|
21
|
+
// Previous values for change comparison
|
|
22
|
+
prevAntenna: record.PREV_ANTENNA_TYPE,
|
|
23
|
+
prevElectricalTilt: record.PREV_ELECTRONIC_TILT,
|
|
24
|
+
prevMechanicalTilt: record.PREV_MECHANIC_TILT,
|
|
25
|
+
prevPower: record.PREV_ANTOUTPUTPWR,
|
|
26
|
+
// Virtual fields for the change columns (needed for column filtering)
|
|
27
|
+
antennaChange: record.ANTENNA_TYPE,
|
|
28
|
+
etiltChange: record.ELECTRONIC_TILT,
|
|
29
|
+
mtiltChange: record.MECHANIC_TILT,
|
|
30
|
+
powerChange: record.ANTOUTPUTPWR,
|
|
31
|
+
}));
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Example API data for cell configuration history (for demos/testing)
|
|
35
|
+
*/
|
|
36
|
+
export const EXAMPLE_HISTORY_DATA = [
|
|
37
|
+
{
|
|
38
|
+
CELLNAME: '1001141',
|
|
39
|
+
FREQUENCY: 1800,
|
|
40
|
+
CONFIG_DATE: '2025-12-03T23:00:00.000Z',
|
|
41
|
+
ANTENNA_TYPE: 'AQU4521R01v06',
|
|
42
|
+
PREV_ANTENNA_TYPE: 'AQU4521R01v06',
|
|
43
|
+
ANTOUTPUTPWR: 20,
|
|
44
|
+
PREV_ANTOUTPUTPWR: 20,
|
|
45
|
+
MECHANIC_TILT: 1,
|
|
46
|
+
PREV_MECHANIC_TILT: 1,
|
|
47
|
+
ELECTRONIC_TILT: 10,
|
|
48
|
+
PREV_ELECTRONIC_TILT: 9
|
|
49
|
+
},
|
|
50
|
+
{
|
|
51
|
+
CELLNAME: '1001141',
|
|
52
|
+
FREQUENCY: 1800,
|
|
53
|
+
CONFIG_DATE: '2025-09-11T22:00:00.000Z',
|
|
54
|
+
ANTENNA_TYPE: 'AQU4521R01v06',
|
|
55
|
+
PREV_ANTENNA_TYPE: 'ADU451602v01',
|
|
56
|
+
ANTOUTPUTPWR: 20,
|
|
57
|
+
PREV_ANTOUTPUTPWR: 20,
|
|
58
|
+
MECHANIC_TILT: 1,
|
|
59
|
+
PREV_MECHANIC_TILT: 0,
|
|
60
|
+
ELECTRONIC_TILT: 9,
|
|
61
|
+
PREV_ELECTRONIC_TILT: 10
|
|
62
|
+
},
|
|
63
|
+
{
|
|
64
|
+
CELLNAME: '1001141',
|
|
65
|
+
FREQUENCY: 1800,
|
|
66
|
+
CONFIG_DATE: '2021-02-15T23:00:00.000Z',
|
|
67
|
+
ANTENNA_TYPE: 'ADU451602v01',
|
|
68
|
+
PREV_ANTENNA_TYPE: 'ADU451602v01',
|
|
69
|
+
ANTOUTPUTPWR: 20,
|
|
70
|
+
PREV_ANTOUTPUTPWR: 20,
|
|
71
|
+
MECHANIC_TILT: 0,
|
|
72
|
+
PREV_MECHANIC_TILT: 2,
|
|
73
|
+
ELECTRONIC_TILT: 10,
|
|
74
|
+
PREV_ELECTRONIC_TILT: 10
|
|
75
|
+
}
|
|
76
|
+
];
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Cell History Types
|
|
3
|
+
*
|
|
4
|
+
* Type definitions for cell configuration history feature
|
|
5
|
+
*/
|
|
6
|
+
export type { CellHistoryData } from '../CellTableV2/types';
|
|
7
|
+
/**
|
|
8
|
+
* Table-ready history record after transformation from API data
|
|
9
|
+
* Maps UPPER_CASE API fields to camelCase for table columns
|
|
10
|
+
*/
|
|
11
|
+
export interface HistoryTableRow {
|
|
12
|
+
id: string;
|
|
13
|
+
cellName: string;
|
|
14
|
+
frequency: number;
|
|
15
|
+
configDate: string;
|
|
16
|
+
antenna: string;
|
|
17
|
+
electricalTilt: number;
|
|
18
|
+
mechanicalTilt: number;
|
|
19
|
+
power: number;
|
|
20
|
+
prevAntenna: string;
|
|
21
|
+
prevElectricalTilt: number;
|
|
22
|
+
prevMechanicalTilt: number;
|
|
23
|
+
prevPower: number;
|
|
24
|
+
antennaChange: string;
|
|
25
|
+
etiltChange: number;
|
|
26
|
+
mtiltChange: number;
|
|
27
|
+
powerChange: number;
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Props for CellHistoryPanel component
|
|
31
|
+
*/
|
|
32
|
+
export interface CellHistoryPanelProps {
|
|
33
|
+
/** Cell name to load history for */
|
|
34
|
+
cellName?: string;
|
|
35
|
+
/** Pre-loaded history data (optional, for external data sources) */
|
|
36
|
+
historyData?: HistoryTableRow[];
|
|
37
|
+
/** Storage key prefix for persistence */
|
|
38
|
+
storageKey?: string;
|
|
39
|
+
/** Show toolbar controls */
|
|
40
|
+
showToolbar?: boolean;
|
|
41
|
+
/** Show export button */
|
|
42
|
+
showExport?: boolean;
|
|
43
|
+
/** Enable header filters */
|
|
44
|
+
headerFilters?: boolean;
|
|
45
|
+
/** Panel title */
|
|
46
|
+
title?: string;
|
|
47
|
+
/** Callback when selection changes */
|
|
48
|
+
onselectionchange?: (event: {
|
|
49
|
+
ids: string[];
|
|
50
|
+
rows: HistoryTableRow[];
|
|
51
|
+
}) => void;
|
|
52
|
+
/** Callback when compare is requested */
|
|
53
|
+
oncompare?: (record1: HistoryTableRow, record2: HistoryTableRow) => void;
|
|
54
|
+
}
|
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
// Import Bootstrap 5 theme for proper styling
|
|
5
5
|
import 'tabulator-tables/dist/css/tabulator_bootstrap5.min.css';
|
|
6
6
|
import type { Options, RowComponent } from 'tabulator-tables';
|
|
7
|
+
import type { ColumnDefinition } from 'tabulator-tables';
|
|
7
8
|
import type {
|
|
8
9
|
CellTableProps,
|
|
9
10
|
CellData,
|
|
@@ -29,6 +30,8 @@
|
|
|
29
30
|
}
|
|
30
31
|
|
|
31
32
|
interface Props extends CellTableProps {
|
|
33
|
+
/** Custom column definitions (overrides columnPreset when provided) */
|
|
34
|
+
customColumns?: ColumnDefinition[];
|
|
32
35
|
/** Row selection change event */
|
|
33
36
|
onselectionchange?: (event: RowSelectionEvent) => void;
|
|
34
37
|
/** Row click event */
|
|
@@ -45,6 +48,7 @@
|
|
|
45
48
|
cells = [],
|
|
46
49
|
groupBy = 'none',
|
|
47
50
|
columnPreset = 'default',
|
|
51
|
+
customColumns,
|
|
48
52
|
columnVisibility,
|
|
49
53
|
selectable = false,
|
|
50
54
|
multiSelect = true,
|
|
@@ -69,10 +73,10 @@
|
|
|
69
73
|
let table: Tabulator | null = null;
|
|
70
74
|
let isInitialized = $state(false);
|
|
71
75
|
|
|
72
|
-
// Reactive column configuration -
|
|
76
|
+
// Reactive column configuration - uses customColumns if provided, otherwise preset
|
|
73
77
|
let columns = $derived.by(() => {
|
|
74
|
-
//
|
|
75
|
-
const baseColumns = getColumnsForPreset(columnPreset, techColors, statusColors, headerFilters);
|
|
78
|
+
// Use custom columns if provided, otherwise get from preset
|
|
79
|
+
const baseColumns = customColumns ?? getColumnsForPreset(columnPreset, techColors, statusColors, headerFilters);
|
|
76
80
|
|
|
77
81
|
// Add row selection checkbox column if selectable
|
|
78
82
|
if (selectable) {
|
|
@@ -1,7 +1,10 @@
|
|
|
1
1
|
import { TabulatorFull as Tabulator } from 'tabulator-tables';
|
|
2
2
|
import 'tabulator-tables/dist/css/tabulator_bootstrap5.min.css';
|
|
3
|
+
import type { ColumnDefinition } from 'tabulator-tables';
|
|
3
4
|
import type { CellTableProps, CellData, RowSelectionEvent, RowClickEvent, RowDblClickEvent, RowContextMenuEvent, DataChangeEvent } from './types';
|
|
4
5
|
interface Props extends CellTableProps {
|
|
6
|
+
/** Custom column definitions (overrides columnPreset when provided) */
|
|
7
|
+
customColumns?: ColumnDefinition[];
|
|
5
8
|
/** Row selection change event */
|
|
6
9
|
onselectionchange?: (event: RowSelectionEvent) => void;
|
|
7
10
|
/** Row click event */
|