@smartnet360/svelte-components 0.0.10 → 0.0.12

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.
Files changed (88) hide show
  1. package/dist/apps/antenna-pattern/components/AntennaControls.svelte +424 -0
  2. package/dist/apps/antenna-pattern/components/AntennaControls.svelte.d.ts +16 -0
  3. package/dist/apps/antenna-pattern/components/AntennaDataDropdown.svelte +62 -0
  4. package/dist/apps/antenna-pattern/components/AntennaDataDropdown.svelte.d.ts +18 -0
  5. package/dist/apps/antenna-pattern/components/AntennaDiagrams.svelte +339 -0
  6. package/dist/apps/antenna-pattern/components/AntennaDiagrams.svelte.d.ts +3 -0
  7. package/dist/apps/antenna-pattern/components/AntennaSettingsModal.svelte +299 -0
  8. package/dist/apps/antenna-pattern/components/AntennaSettingsModal.svelte.d.ts +24 -0
  9. package/dist/apps/antenna-pattern/components/DbNotification.svelte +67 -0
  10. package/dist/apps/antenna-pattern/components/DbNotification.svelte.d.ts +18 -0
  11. package/dist/apps/antenna-pattern/components/JsonImporter.svelte +116 -0
  12. package/dist/apps/antenna-pattern/components/JsonImporter.svelte.d.ts +18 -0
  13. package/dist/apps/antenna-pattern/components/MSIConverter.svelte +209 -0
  14. package/dist/apps/antenna-pattern/components/MSIConverter.svelte.d.ts +18 -0
  15. package/dist/apps/antenna-pattern/components/PlotlyRadarChart.svelte +252 -0
  16. package/dist/apps/antenna-pattern/components/PlotlyRadarChart.svelte.d.ts +22 -0
  17. package/dist/apps/antenna-pattern/db.d.ts +24 -0
  18. package/dist/apps/antenna-pattern/db.js +15 -0
  19. package/dist/apps/antenna-pattern/helpers/plotly-utils.d.ts +54 -0
  20. package/dist/apps/antenna-pattern/helpers/plotly-utils.js +324 -0
  21. package/dist/apps/antenna-pattern/index.d.ts +15 -0
  22. package/dist/apps/antenna-pattern/index.js +19 -0
  23. package/dist/apps/antenna-pattern/stores/antennas.d.ts +5 -0
  24. package/dist/apps/antenna-pattern/stores/antennas.js +14 -0
  25. package/dist/apps/antenna-pattern/stores/db-status.d.ts +28 -0
  26. package/dist/apps/antenna-pattern/stores/db-status.js +34 -0
  27. package/dist/apps/antenna-pattern/utils/db-utils.d.ts +9 -0
  28. package/dist/apps/antenna-pattern/utils/db-utils.js +180 -0
  29. package/dist/apps/antenna-pattern/utils/init-db.d.ts +2 -0
  30. package/dist/apps/antenna-pattern/utils/init-db.js +95 -0
  31. package/dist/apps/antenna-pattern/utils/msi-parser.d.ts +3 -0
  32. package/dist/apps/antenna-pattern/utils/msi-parser.js +197 -0
  33. package/dist/apps/antenna-pattern/utils/plotly-chart-utils.d.ts +101 -0
  34. package/dist/apps/antenna-pattern/utils/plotly-chart-utils.js +152 -0
  35. package/dist/apps/index.d.ts +1 -0
  36. package/dist/apps/index.js +6 -0
  37. package/dist/{Charts → core/Charts}/ChartComponent.svelte +131 -39
  38. package/dist/{Charts → core/Charts}/charts.model.d.ts +1 -1
  39. package/dist/{Charts → core/Charts}/data-utils.js +0 -4
  40. package/dist/{Desktop → core/Desktop}/GridRenderer.svelte +1 -1
  41. package/dist/core/index.d.ts +2 -0
  42. package/dist/core/index.js +6 -0
  43. package/dist/index.d.ts +2 -2
  44. package/dist/index.js +6 -2
  45. package/package.json +6 -2
  46. /package/dist/{Charts → core/Charts}/ChartCard.svelte +0 -0
  47. /package/dist/{Charts → core/Charts}/ChartCard.svelte.d.ts +0 -0
  48. /package/dist/{Charts → core/Charts}/ChartComponent.svelte.d.ts +0 -0
  49. /package/dist/{Charts → core/Charts}/adapt.d.ts +0 -0
  50. /package/dist/{Charts → core/Charts}/adapt.js +0 -0
  51. /package/dist/{Charts → core/Charts}/charts.model.js +0 -0
  52. /package/dist/{Charts → core/Charts}/data-utils.d.ts +0 -0
  53. /package/dist/{Charts → core/Charts}/index.d.ts +0 -0
  54. /package/dist/{Charts → core/Charts}/index.js +0 -0
  55. /package/dist/{Charts → core/Charts}/plotly.d.ts +0 -0
  56. /package/dist/{Desktop → core/Desktop}/Desktop.svelte +0 -0
  57. /package/dist/{Desktop → core/Desktop}/Desktop.svelte.d.ts +0 -0
  58. /package/dist/{Desktop → core/Desktop}/Grid/Half.svelte +0 -0
  59. /package/dist/{Desktop → core/Desktop}/Grid/Half.svelte.d.ts +0 -0
  60. /package/dist/{Desktop → core/Desktop}/Grid/Quarter.svelte +0 -0
  61. /package/dist/{Desktop → core/Desktop}/Grid/Quarter.svelte.d.ts +0 -0
  62. /package/dist/{Desktop → core/Desktop}/Grid/ResizeHandle.svelte +0 -0
  63. /package/dist/{Desktop → core/Desktop}/Grid/ResizeHandle.svelte.d.ts +0 -0
  64. /package/dist/{Desktop → core/Desktop}/Grid/index.d.ts +0 -0
  65. /package/dist/{Desktop → core/Desktop}/Grid/index.js +0 -0
  66. /package/dist/{Desktop → core/Desktop}/Grid/resizeStore.d.ts +0 -0
  67. /package/dist/{Desktop → core/Desktop}/Grid/resizeStore.js +0 -0
  68. /package/dist/{Desktop → core/Desktop}/GridRenderer.svelte.d.ts +0 -0
  69. /package/dist/{Desktop → core/Desktop}/GridSelector/ComponentPalette.svelte +0 -0
  70. /package/dist/{Desktop → core/Desktop}/GridSelector/ComponentPalette.svelte.d.ts +0 -0
  71. /package/dist/{Desktop → core/Desktop}/GridSelector/ConfigurationPanel.svelte +0 -0
  72. /package/dist/{Desktop → core/Desktop}/GridSelector/ConfigurationPanel.svelte.d.ts +0 -0
  73. /package/dist/{Desktop → core/Desktop}/GridSelector/GridSelector.svelte +0 -0
  74. /package/dist/{Desktop → core/Desktop}/GridSelector/GridSelector.svelte.d.ts +0 -0
  75. /package/dist/{Desktop → core/Desktop}/GridSelector/LayoutPicker.svelte +0 -0
  76. /package/dist/{Desktop → core/Desktop}/GridSelector/LayoutPicker.svelte.d.ts +0 -0
  77. /package/dist/{Desktop → core/Desktop}/GridSelector/LayoutPreview.svelte +0 -0
  78. /package/dist/{Desktop → core/Desktop}/GridSelector/LayoutPreview.svelte.d.ts +0 -0
  79. /package/dist/{Desktop → core/Desktop}/GridSelector/index.d.ts +0 -0
  80. /package/dist/{Desktop → core/Desktop}/GridSelector/index.js +0 -0
  81. /package/dist/{Desktop → core/Desktop}/GridViewer.svelte +0 -0
  82. /package/dist/{Desktop → core/Desktop}/GridViewer.svelte.d.ts +0 -0
  83. /package/dist/{Desktop → core/Desktop}/gridLayouts.d.ts +0 -0
  84. /package/dist/{Desktop → core/Desktop}/gridLayouts.js +0 -0
  85. /package/dist/{Desktop → core/Desktop}/index.d.ts +0 -0
  86. /package/dist/{Desktop → core/Desktop}/index.js +0 -0
  87. /package/dist/{Desktop → core/Desktop}/launchHelpers.d.ts +0 -0
  88. /package/dist/{Desktop → core/Desktop}/launchHelpers.js +0 -0
@@ -0,0 +1,339 @@
1
+ <svelte:options runes={true} />
2
+
3
+ <script lang="ts">
4
+ import { onMount } from 'svelte';
5
+ import { browser } from '$app/environment';
6
+ import { loadAntennas } from '../utils/db-utils';
7
+ import type { Antenna } from '../db';
8
+ import AntennaControls from './AntennaControls.svelte';
9
+ import AntennaSettingsModal from './AntennaSettingsModal.svelte';
10
+ import {
11
+ createAntennaChartData,
12
+ createChartLayout,
13
+ createChartConfig,
14
+ generateChartTitle,
15
+ type PlotlyTraceData
16
+ } from '../utils/plotly-chart-utils';
17
+
18
+ let Plotly: any;
19
+ let chartDiv = $state<HTMLDivElement>();
20
+ let antennas = $state<Antenna[]>([]);
21
+ let selectedAntenna = $state<Antenna | null>(null);
22
+ let selectedAntenna2 = $state<Antenna | null>(null);
23
+ let chartInitialized = $state(false);
24
+
25
+ // External Bootstrap slider values
26
+ let ant1ElectricalTilt = $state(0);
27
+ let ant2ElectricalTilt = $state(0);
28
+ let ant1MechanicalTilt = $state(0);
29
+ let ant2MechanicalTilt = $state(0);
30
+
31
+ // Viewing mode and pattern visibility
32
+ let viewMode = $state<'single' | 'compare'>('single');
33
+ let patternType = $state<'horizontal' | 'vertical'>('vertical');
34
+
35
+ // Settings modal state
36
+ let showSettingsModal = $state(false);
37
+
38
+ // Available tilt options (will be set from antenna data)
39
+ let availableElectricalTilts = $state<string[]>(['0', '2', '4', '6', '8']);
40
+
41
+ // Handle antenna selection from controls
42
+ function handleAntenna1Change(antenna: Antenna | null) {
43
+ selectedAntenna = antenna;
44
+ if (antenna) {
45
+ // Update available electrical tilts based on selected antenna
46
+ availableElectricalTilts = antenna.tilt ?
47
+ antenna.tilt.split(',').map(t => t.trim()) :
48
+ ['0', '2', '4', '6', '8'];
49
+ ant1ElectricalTilt = 0;
50
+ ant1MechanicalTilt = 0;
51
+ }
52
+ }
53
+
54
+ function handleAntenna2Change(antenna: Antenna | null) {
55
+ selectedAntenna2 = antenna;
56
+ if (antenna) {
57
+ ant2ElectricalTilt = 0;
58
+ ant2MechanicalTilt = 0;
59
+ }
60
+ }
61
+
62
+ // Handle electrical tilt changes from controls
63
+ function handleTilt1Change(tilt: number) {
64
+ ant1ElectricalTilt = tilt;
65
+ }
66
+
67
+ function handleTilt2Change(tilt: number) {
68
+ ant2ElectricalTilt = tilt;
69
+ }
70
+
71
+ // Handle mechanical tilt changes from controls
72
+ function handleMechTilt1Change(tilt: number) {
73
+ ant1MechanicalTilt = tilt;
74
+ }
75
+
76
+ function handleMechTilt2Change(tilt: number) {
77
+ ant2MechanicalTilt = tilt;
78
+ }
79
+
80
+ // Handle settings modal
81
+ function openSettings() {
82
+ showSettingsModal = true;
83
+ }
84
+
85
+ function closeSettings() {
86
+ showSettingsModal = false;
87
+ }
88
+
89
+ // Handle data refresh from settings modal
90
+ async function handleDataRefresh() {
91
+ try {
92
+ antennas = await loadAntennas();
93
+
94
+ // Reinitialize antenna selections after data refresh
95
+ if (antennas.length > 0) {
96
+ selectedAntenna = antennas[0];
97
+ if (antennas.length > 1) {
98
+ selectedAntenna2 = antennas[1];
99
+ } else {
100
+ selectedAntenna2 = antennas[0];
101
+ }
102
+
103
+ // Reset tilt values
104
+ ant1ElectricalTilt = 0;
105
+ ant1MechanicalTilt = 0;
106
+ ant2ElectricalTilt = 0;
107
+ ant2MechanicalTilt = 0;
108
+
109
+ // Update chart if initialized
110
+ if (chartInitialized) {
111
+ await updateChart();
112
+ }
113
+ }
114
+
115
+ console.log('Data refreshed from settings modal');
116
+ } catch (error) {
117
+ console.error('Failed to refresh data:', error);
118
+ }
119
+ }
120
+
121
+ // Watch for slider changes and update chart
122
+ $effect(() => {
123
+ if (chartInitialized) {
124
+ updateChart();
125
+ }
126
+ });
127
+
128
+ onMount(async () => {
129
+ if (browser) {
130
+ try {
131
+ // Load Plotly and antenna data
132
+ Plotly = await import('plotly.js-dist-min');
133
+ antennas = await loadAntennas();
134
+
135
+ if (antennas.length > 0) {
136
+ // Set default antenna selection for antenna 1
137
+ selectedAntenna = antennas[0];
138
+ if (selectedAntenna.tilt) {
139
+ availableElectricalTilts = selectedAntenna.tilt.split(',').map(t => t.trim());
140
+ }
141
+
142
+ // Set default antenna selection for antenna 2 (for compare mode)
143
+ if (antennas.length > 1) {
144
+ selectedAntenna2 = antennas[1];
145
+ } else {
146
+ selectedAntenna2 = antennas[0]; // Use same antenna if only one available
147
+ }
148
+
149
+ await initializeChart();
150
+ }
151
+ } catch (error) {
152
+ console.error('Failed to initialize:', error);
153
+ }
154
+ }
155
+ });
156
+
157
+ async function initializeChart() {
158
+ if (!Plotly || !chartDiv) return;
159
+
160
+ const data = createAntennaChartData(
161
+ selectedAntenna,
162
+ selectedAntenna2,
163
+ viewMode,
164
+ patternType === 'horizontal',
165
+ patternType === 'vertical',
166
+ ant1ElectricalTilt,
167
+ ant1MechanicalTilt,
168
+ ant2ElectricalTilt,
169
+ ant2MechanicalTilt
170
+ );
171
+ const title = generateChartTitle(viewMode, selectedAntenna, selectedAntenna2);
172
+ const layout = createChartLayout(title);
173
+ const config = createChartConfig();
174
+
175
+ try {
176
+ await Plotly.newPlot(chartDiv, data, layout, config);
177
+ chartInitialized = true;
178
+ console.log('Chart initialized with antenna controls');
179
+ } catch (error) {
180
+ console.error('Failed to create chart:', error);
181
+ }
182
+ }
183
+
184
+ async function updateChart() {
185
+ if (!Plotly || !chartDiv || !chartInitialized) return;
186
+
187
+ try {
188
+ const data = createAntennaChartData(
189
+ selectedAntenna,
190
+ selectedAntenna2,
191
+ viewMode,
192
+ patternType === 'horizontal',
193
+ patternType === 'vertical',
194
+ ant1ElectricalTilt,
195
+ ant1MechanicalTilt,
196
+ ant2ElectricalTilt,
197
+ ant2MechanicalTilt
198
+ );
199
+ const title = generateChartTitle(viewMode, selectedAntenna, selectedAntenna2);
200
+ await Plotly.react(chartDiv, data, createChartLayout(title));
201
+ } catch (error) {
202
+ console.error('Failed to update chart:', error);
203
+ }
204
+ }
205
+ </script>
206
+
207
+ <div class="container-fluid mt-4">
208
+
209
+
210
+ <!-- Viewing Mode and Pattern Visibility Controls -->
211
+ <div class="row mb-4">
212
+ <div class="col-md-4">
213
+ <div class="form-label">Viewing Mode:</div>
214
+ <div class="btn-group w-100" role="group" aria-label="Viewing mode selection">
215
+ <input
216
+ type="radio"
217
+ class="btn-check"
218
+ id="singleMode"
219
+ bind:group={viewMode}
220
+ value="single"
221
+ >
222
+ <label class="btn btn-outline-primary" for="singleMode">Single Antenna</label>
223
+
224
+ <input
225
+ type="radio"
226
+ class="btn-check"
227
+ id="compareMode"
228
+ bind:group={viewMode}
229
+ value="compare"
230
+ >
231
+ <label class="btn btn-outline-primary" for="compareMode">Compare</label>
232
+ </div>
233
+ </div>
234
+
235
+ <div class="col-md-4">
236
+ <div class="form-label">Pattern Type:</div>
237
+ <div class="btn-group w-100" role="group" aria-label="Pattern type selection">
238
+ <input
239
+ type="radio"
240
+ class="btn-check"
241
+ id="horizontalPattern"
242
+ bind:group={patternType}
243
+ value="horizontal"
244
+ >
245
+ <label class="btn btn-outline-primary" for="horizontalPattern">Horizontal</label>
246
+
247
+ <input
248
+ type="radio"
249
+ class="btn-check"
250
+ id="verticalPattern"
251
+ bind:group={patternType}
252
+ value="vertical"
253
+ >
254
+ <label class="btn btn-outline-primary" for="verticalPattern">Vertical</label>
255
+ </div>
256
+ </div>
257
+
258
+ <div class="col-md-4">
259
+ <div class="form-label">Actions:</div>
260
+ <button
261
+ type="button"
262
+ class="btn btn-outline-secondary w-100"
263
+ onclick={openSettings}
264
+ title="Settings"
265
+ >
266
+ <i class="bi bi-gear"></i> Settings
267
+ </button>
268
+ </div>
269
+ </div>
270
+
271
+ <div class="row">
272
+ <!-- Left Column - Antenna 1 Controls -->
273
+ <div class="col-md-3">
274
+ <AntennaControls
275
+ antennas={antennas}
276
+ selectedAntenna={selectedAntenna}
277
+ antennaNumber={1}
278
+ electricalTiltIndex={ant1ElectricalTilt}
279
+ mechanicalTilt={ant1MechanicalTilt}
280
+ colorTheme="primary"
281
+ onAntennaChange={handleAntenna1Change}
282
+ onElectricalTiltChange={handleTilt1Change}
283
+ onMechanicalTiltChange={handleMechTilt1Change}
284
+ />
285
+ </div>
286
+
287
+ <!-- Center Column - Chart (always centered) -->
288
+ <div class="col-md-6">
289
+ <div class="card">
290
+ <div class="card-body p-1">
291
+ <div bind:this={chartDiv} style="height: 700px;"></div>
292
+ </div>
293
+ </div>
294
+ </div>
295
+
296
+ <!-- Right Column - Antenna 2 Controls (only in compare mode) -->
297
+ <div class="col-md-3">
298
+ {#if viewMode === 'compare'}
299
+ <AntennaControls
300
+ antennas={antennas}
301
+ selectedAntenna={selectedAntenna2}
302
+ antennaNumber={2}
303
+ electricalTiltIndex={ant2ElectricalTilt}
304
+ mechanicalTilt={ant2MechanicalTilt}
305
+ colorTheme="warning"
306
+ onAntennaChange={handleAntenna2Change}
307
+ onElectricalTiltChange={handleTilt2Change}
308
+ onMechanicalTiltChange={handleMechTilt2Change}
309
+ />
310
+ {:else}
311
+ <!-- Empty space to keep chart centered in single mode -->
312
+ <div></div>
313
+ {/if}
314
+ </div>
315
+ </div>
316
+
317
+
318
+ </div>
319
+
320
+ <!-- Settings Modal -->
321
+ <AntennaSettingsModal
322
+ show={showSettingsModal}
323
+ onClose={closeSettings}
324
+ on:dataRefresh={handleDataRefresh}
325
+ />
326
+
327
+ <style>
328
+ /* Chart container */
329
+ :global(.plotly .plot-container) {
330
+ border-radius: 8px !important;
331
+ }
332
+
333
+ /* Main chart card styling */
334
+ .card {
335
+ border: none;
336
+ box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
337
+ border-radius: 12px;
338
+ }
339
+ </style>
@@ -0,0 +1,3 @@
1
+ declare const AntennaDiagrams: import("svelte").Component<Record<string, never>, {}, "">;
2
+ type AntennaDiagrams = ReturnType<typeof AntennaDiagrams>;
3
+ export default AntennaDiagrams;
@@ -0,0 +1,299 @@
1
+ <svelte:options runes={true} />
2
+
3
+ <script lang="ts">
4
+ import { createEventDispatcher } from 'svelte';
5
+ import JsonImporter from './JsonImporter.svelte';
6
+ import MSIConverter from './MSIConverter.svelte';
7
+ import DbNotification from './DbNotification.svelte';
8
+ import { exportAntennas, clearAllAntennas } from '../utils/db-utils';
9
+ import { dbStatus } from '../stores/db-status';
10
+
11
+ interface Props {
12
+ show: boolean;
13
+ onClose: () => void;
14
+ }
15
+
16
+ let { show, onClose }: Props = $props();
17
+
18
+ const dispatch = createEventDispatcher();
19
+
20
+ let activeTab = $state<'import' | 'export' | 'manage' | 'msi'>('import');
21
+ let showClearConfirm = $state(false);
22
+
23
+ // Handle data refresh after import operations
24
+ function handleDataRefresh() {
25
+ dispatch('dataRefresh');
26
+ }
27
+
28
+ // Export data as JSON
29
+ async function handleExport() {
30
+ try {
31
+ await exportAntennas();
32
+ console.log('Data exported successfully');
33
+ } catch (error) {
34
+ console.error('Export failed:', error);
35
+ }
36
+ }
37
+
38
+ // Clear all data with confirmation
39
+ async function handleClearData() {
40
+ if (!showClearConfirm) {
41
+ showClearConfirm = true;
42
+ return;
43
+ }
44
+
45
+ try {
46
+ await clearAllAntennas();
47
+ showClearConfirm = false;
48
+ handleDataRefresh();
49
+ console.log('All data cleared successfully');
50
+ } catch (error) {
51
+ console.error('Clear data failed:', error);
52
+ }
53
+ }
54
+
55
+ function cancelClear() {
56
+ showClearConfirm = false;
57
+ }
58
+ </script>
59
+
60
+ <!-- Modal -->
61
+ {#if show}
62
+ <!-- Modal backdrop -->
63
+ <div class="modal-backdrop fade show"></div>
64
+
65
+ <!-- Modal dialog -->
66
+ <div class="modal fade show d-block" tabindex="-1" role="dialog">
67
+ <div class="modal-dialog modal-xl modal-dialog-centered modal-dialog-scrollable" role="document">
68
+ <div class="modal-content">
69
+ <!-- Modal Header -->
70
+ <div class="modal-header border-bottom">
71
+ <h4 class="modal-title">
72
+ <i class="bi bi-gear me-2"></i>
73
+ Antenna Data Management
74
+ </h4>
75
+ <button
76
+ type="button"
77
+ class="btn-close"
78
+ onclick={onClose}
79
+ aria-label="Close"
80
+ ></button>
81
+ </div>
82
+
83
+ <!-- Modal Body -->
84
+ <div class="modal-body p-0">
85
+ <!-- Tab Navigation -->
86
+ <div class="border-bottom">
87
+ <div class="nav nav-tabs">
88
+ <button
89
+ class="nav-link {activeTab === 'import' ? 'active' : ''}"
90
+ type="button"
91
+ onclick={() => activeTab = 'import'}
92
+ >
93
+ <i class="bi bi-upload me-2"></i>Import JSON
94
+ </button>
95
+ <button
96
+ class="nav-link {activeTab === 'msi' ? 'active' : ''}"
97
+ type="button"
98
+ onclick={() => activeTab = 'msi'}
99
+ >
100
+ <i class="bi bi-file-earmark-text me-2"></i>Import MSI
101
+ </button>
102
+ <button
103
+ class="nav-link {activeTab === 'export' ? 'active' : ''}"
104
+ type="button"
105
+ onclick={() => activeTab = 'export'}
106
+ >
107
+ <i class="bi bi-download me-2"></i>Export Data
108
+ </button>
109
+ <button
110
+ class="nav-link {activeTab === 'manage' ? 'active' : ''}"
111
+ type="button"
112
+ onclick={() => activeTab = 'manage'}
113
+ >
114
+ <i class="bi bi-trash me-2"></i>Manage Data
115
+ </button>
116
+ </div>
117
+ </div>
118
+
119
+ <!-- Tab Content -->
120
+ <div class="tab-content p-4">
121
+
122
+ <!-- Import JSON Tab -->
123
+ {#if activeTab === 'import'}
124
+ <div class="tab-pane fade show active">
125
+ <div class="row">
126
+ <div class="col-12">
127
+ <h5 class="mb-3">Import Antenna Data from JSON</h5>
128
+ <JsonImporter on:dataRefresh={handleDataRefresh} />
129
+ </div>
130
+ </div>
131
+ </div>
132
+ {/if}
133
+
134
+ <!-- Import MSI Tab -->
135
+ {#if activeTab === 'msi'}
136
+ <div class="tab-pane fade show active">
137
+ <div class="row">
138
+ <div class="col-12">
139
+ <h5 class="mb-3">Import MSI Pattern Files</h5>
140
+
141
+ <MSIConverter on:dataRefresh={handleDataRefresh} />
142
+ </div>
143
+ </div>
144
+ </div>
145
+ {/if}
146
+
147
+ <!-- Export Data Tab -->
148
+ {#if activeTab === 'export'}
149
+ <div class="tab-pane fade show active">
150
+ <div class="row">
151
+ <div class="col-12">
152
+ <h5 class="mb-3">Export Antenna Data</h5>
153
+
154
+ <div class="card border-success">
155
+ <div class="card-body text-center">
156
+ <i class="bi bi-download text-success" style="font-size: 3rem;"></i>
157
+ <h6 class="mt-3 mb-3">Download Data Backup</h6>
158
+ <p class="text-muted mb-4">
159
+ Export all antenna patterns and metadata as a JSON file.
160
+ </p>
161
+ <button
162
+ type="button"
163
+ class="btn btn-success btn-lg"
164
+ onclick={handleExport}
165
+ >
166
+ <i class="bi bi-download me-2"></i>
167
+ Export JSON File
168
+ </button>
169
+ </div>
170
+ </div>
171
+ </div>
172
+ </div>
173
+ </div>
174
+ {/if}
175
+
176
+ <!-- Manage Data Tab -->
177
+ {#if activeTab === 'manage'}
178
+ <div class="tab-pane fade show active">
179
+ <div class="row">
180
+ <div class="col-12">
181
+ <h5 class="mb-3">Manage Database</h5>
182
+
183
+
184
+ <!-- Database Status -->
185
+ <div class="card border-info mb-4">
186
+ <div class="card-body">
187
+ <h6 class="card-title">
188
+ <i class="bi bi-info-circle me-2"></i>Database Status
189
+ </h6>
190
+ <DbNotification />
191
+ </div>
192
+ </div>
193
+
194
+ <!-- Clear Data Section -->
195
+ <div class="card border-danger">
196
+ <div class="card-body">
197
+ <h6 class="card-title text-danger">
198
+ <i class="bi bi-exclamation-triangle me-2"></i>Danger Zone
199
+ </h6>
200
+ <p class="text-muted mb-3">
201
+ Permanently delete all antenna data from the database. This action cannot be undone.
202
+ </p>
203
+
204
+ {#if !showClearConfirm}
205
+ <button
206
+ type="button"
207
+ class="btn btn-outline-danger"
208
+ onclick={handleClearData}
209
+ >
210
+ <i class="bi bi-trash me-2"></i>
211
+ Clear All Data
212
+ </button>
213
+ {:else}
214
+ <div class="alert alert-danger" role="alert">
215
+ <strong>Are you sure?</strong> This will permanently delete all antenna data.
216
+ </div>
217
+ <div class="d-flex gap-2">
218
+ <button
219
+ type="button"
220
+ class="btn btn-danger"
221
+ onclick={handleClearData}
222
+ >
223
+ <i class="bi bi-trash me-2"></i>
224
+ Yes, Delete All Data
225
+ </button>
226
+ <button
227
+ type="button"
228
+ class="btn btn-secondary"
229
+ onclick={cancelClear}
230
+ >
231
+ Cancel
232
+ </button>
233
+ </div>
234
+ {/if}
235
+ </div>
236
+ </div>
237
+ </div>
238
+ </div>
239
+ </div>
240
+ {/if}
241
+
242
+ </div>
243
+ </div>
244
+
245
+ <!-- Modal Footer -->
246
+ <div class="modal-footer border-top">
247
+ <button
248
+ type="button"
249
+ class="btn btn-secondary"
250
+ onclick={onClose}
251
+ >
252
+ Close
253
+ </button>
254
+ </div>
255
+ </div>
256
+ </div>
257
+ </div>
258
+ {/if}
259
+
260
+ <style>
261
+ .modal {
262
+ background-color: rgba(0, 0, 0, 0.5);
263
+ }
264
+
265
+ .modal-xl {
266
+ max-width: 1140px;
267
+ }
268
+
269
+ .nav-tabs {
270
+ border-bottom: 1px solid #dee2e6;
271
+ }
272
+
273
+ .nav-tabs .nav-link {
274
+ border: none;
275
+ border-bottom: 3px solid transparent;
276
+ background: none;
277
+ color: #6c757d;
278
+ padding: 1rem 1.5rem;
279
+ }
280
+
281
+ .nav-tabs .nav-link:hover {
282
+ border-bottom-color: #e9ecef;
283
+ color: #495057;
284
+ }
285
+
286
+ .nav-tabs .nav-link.active {
287
+ color: #0d6efd;
288
+ border-bottom-color: #0d6efd;
289
+ background: none;
290
+ }
291
+
292
+ .card {
293
+ transition: box-shadow 0.15s ease-in-out;
294
+ }
295
+
296
+ .card:hover {
297
+ box-shadow: 0 0.5rem 1rem rgba(0, 0, 0, 0.15);
298
+ }
299
+ </style>
@@ -0,0 +1,24 @@
1
+ interface Props {
2
+ show: boolean;
3
+ onClose: () => void;
4
+ }
5
+ interface $$__sveltets_2_IsomorphicComponent<Props extends Record<string, any> = any, Events extends Record<string, any> = any, Slots extends Record<string, any> = any, Exports = {}, Bindings = string> {
6
+ new (options: import('svelte').ComponentConstructorOptions<Props>): import('svelte').SvelteComponent<Props, Events, Slots> & {
7
+ $$bindings?: Bindings;
8
+ } & Exports;
9
+ (internal: unknown, props: Props & {
10
+ $$events?: Events;
11
+ $$slots?: Slots;
12
+ }): Exports & {
13
+ $set?: any;
14
+ $on?: any;
15
+ };
16
+ z_$$bindings?: Bindings;
17
+ }
18
+ declare const AntennaSettingsModal: $$__sveltets_2_IsomorphicComponent<Props, {
19
+ dataRefresh: CustomEvent<any>;
20
+ } & {
21
+ [evt: string]: CustomEvent<any>;
22
+ }, {}, {}, "">;
23
+ type AntennaSettingsModal = InstanceType<typeof AntennaSettingsModal>;
24
+ export default AntennaSettingsModal;