adminator-admin-dashboard 2.7.1 → 2.8.0
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/CHANGELOG.md +50 -0
- package/README.md +40 -12
- package/dist/main.js +1771 -2565
- package/dist/main.js.map +1 -1
- package/package.json +22 -34
- package/src/assets/scripts/app.js +3 -3
- package/src/assets/scripts/utils/theme.js +4 -2
- package/src/assets/scripts/vectorMaps/index.js +5 -5
- package/dist/55b07f26c86c8e3d3754.svg +0 -1
- package/dist/9fad440d8ee7a949a9a9.svg +0 -1
- package/dist/test.html +0 -91
- package/src/assets/scripts/app.ts +0 -757
- package/src/assets/scripts/components/Chart.ts +0 -1350
- package/src/assets/scripts/components/Sidebar.ts +0 -388
- package/src/assets/scripts/datatable/index.ts +0 -707
- package/src/assets/scripts/datepicker/index.ts +0 -699
- package/src/assets/scripts/ui/index.ts +0 -740
- package/src/assets/scripts/utils/date.ts +0 -363
- package/src/assets/scripts/utils/dom.ts +0 -513
- package/src/assets/scripts/utils/theme.ts +0 -313
- package/src/assets/scripts/vectorMaps/index.ts +0 -542
- package/src/test.html +0 -96
- package/src/types/index.ts +0 -236
- /package/dist/assets/{c1e38fd9e0e74ba58f7a2b77ef29fdd3.svg → fontawesome-webfont.svg} +0 -0
- /package/dist/assets/{f0fc8c798eac5636249c4ea287832422.svg → themify.svg} +0 -0
|
@@ -1,1350 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Modern Chart Component with TypeScript
|
|
3
|
-
* Replaces jQuery Sparkline with Chart.js
|
|
4
|
-
*/
|
|
5
|
-
|
|
6
|
-
import { Chart, ChartConfiguration, registerables, ChartType as ChartJSType } from 'chart.js';
|
|
7
|
-
import type { ComponentInterface } from '../../../types';
|
|
8
|
-
import { COLORS } from '../constants/colors';
|
|
9
|
-
|
|
10
|
-
// Register Chart.js components
|
|
11
|
-
Chart.register(...registerables);
|
|
12
|
-
|
|
13
|
-
export interface SparklineConfig {
|
|
14
|
-
id: string;
|
|
15
|
-
data: number[];
|
|
16
|
-
color: string;
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
export interface ChartComponentOptions {
|
|
20
|
-
enableResize?: boolean;
|
|
21
|
-
resizeDebounceMs?: number;
|
|
22
|
-
enableAnimation?: boolean;
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
export interface ChartDimensions {
|
|
26
|
-
width: number;
|
|
27
|
-
height: number;
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
export type ChartElementType = 'sparkline' | 'sparkbar' | 'sparktri' | 'sparkdisc' | 'sparkbull' | 'sparkbox' | 'easypie';
|
|
31
|
-
|
|
32
|
-
export class ChartComponent implements ComponentInterface {
|
|
33
|
-
public name: string = 'ChartComponent';
|
|
34
|
-
public element: HTMLElement;
|
|
35
|
-
public options: ChartComponentOptions;
|
|
36
|
-
public isInitialized: boolean = false;
|
|
37
|
-
|
|
38
|
-
private charts: Map<string, Chart> = new Map();
|
|
39
|
-
private debounceTimer: number | null = null;
|
|
40
|
-
|
|
41
|
-
constructor(element?: HTMLElement, options: ChartComponentOptions = {}) {
|
|
42
|
-
this.element = element || document.body;
|
|
43
|
-
this.options = {
|
|
44
|
-
enableResize: true,
|
|
45
|
-
resizeDebounceMs: 150,
|
|
46
|
-
enableAnimation: true,
|
|
47
|
-
...options,
|
|
48
|
-
};
|
|
49
|
-
|
|
50
|
-
this.init();
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
/**
|
|
54
|
-
* Initialize the chart component
|
|
55
|
-
*/
|
|
56
|
-
public init(): void {
|
|
57
|
-
// Only disable resizing for small sparkline charts
|
|
58
|
-
this.createSparklines();
|
|
59
|
-
this.createOtherCharts();
|
|
60
|
-
|
|
61
|
-
if (this.options.enableResize) {
|
|
62
|
-
this.setupResizeHandler();
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
this.isInitialized = true;
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
/**
|
|
69
|
-
* Destroy the chart component
|
|
70
|
-
*/
|
|
71
|
-
public destroy(): void {
|
|
72
|
-
this.charts.forEach(chart => {
|
|
73
|
-
chart.destroy();
|
|
74
|
-
});
|
|
75
|
-
this.charts.clear();
|
|
76
|
-
|
|
77
|
-
if (this.debounceTimer) {
|
|
78
|
-
clearTimeout(this.debounceTimer);
|
|
79
|
-
this.debounceTimer = null;
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
this.isInitialized = false;
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
/**
|
|
86
|
-
* Create sparklines (only for dashboard page)
|
|
87
|
-
*/
|
|
88
|
-
private createSparklines(): void {
|
|
89
|
-
// Only create sparklines if we're on a page that has them
|
|
90
|
-
const sparklineExists = document.getElementById('sparklinedash');
|
|
91
|
-
if (!sparklineExists) {
|
|
92
|
-
return;
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
const sparklineConfigs: SparklineConfig[] = [
|
|
96
|
-
{
|
|
97
|
-
id: 'sparklinedash',
|
|
98
|
-
data: [0, 5, 6, 10, 9, 12, 4, 9],
|
|
99
|
-
color: '#4caf50',
|
|
100
|
-
},
|
|
101
|
-
{
|
|
102
|
-
id: 'sparklinedash2',
|
|
103
|
-
data: [0, 5, 6, 10, 9, 12, 4, 9],
|
|
104
|
-
color: '#9675ce',
|
|
105
|
-
},
|
|
106
|
-
{
|
|
107
|
-
id: 'sparklinedash3',
|
|
108
|
-
data: [0, 5, 6, 10, 9, 12, 4, 9],
|
|
109
|
-
color: '#03a9f3',
|
|
110
|
-
},
|
|
111
|
-
{
|
|
112
|
-
id: 'sparklinedash4',
|
|
113
|
-
data: [0, 5, 6, 10, 9, 12, 4, 9],
|
|
114
|
-
color: '#f96262',
|
|
115
|
-
},
|
|
116
|
-
];
|
|
117
|
-
|
|
118
|
-
sparklineConfigs.forEach(config => {
|
|
119
|
-
// Only create if the target element exists
|
|
120
|
-
if (document.getElementById(config.id)) {
|
|
121
|
-
this.createSparklineChart(config);
|
|
122
|
-
}
|
|
123
|
-
});
|
|
124
|
-
}
|
|
125
|
-
|
|
126
|
-
/**
|
|
127
|
-
* Create sparkline chart from configuration
|
|
128
|
-
*/
|
|
129
|
-
private createSparklineChart(config: SparklineConfig): void {
|
|
130
|
-
let canvas = document.getElementById(config.id) as HTMLCanvasElement;
|
|
131
|
-
|
|
132
|
-
// Only proceed if we have a valid target element
|
|
133
|
-
if (!canvas) {
|
|
134
|
-
return;
|
|
135
|
-
}
|
|
136
|
-
|
|
137
|
-
// If element exists but isn't a canvas, replace it with canvas
|
|
138
|
-
if (canvas.tagName !== 'CANVAS') {
|
|
139
|
-
const parent = canvas.parentNode;
|
|
140
|
-
if (!parent) {
|
|
141
|
-
return;
|
|
142
|
-
}
|
|
143
|
-
|
|
144
|
-
// Create new canvas element
|
|
145
|
-
const newCanvas = document.createElement('canvas');
|
|
146
|
-
newCanvas.id = config.id;
|
|
147
|
-
this.setCanvasDimensions(newCanvas, { width: 100, height: 20 });
|
|
148
|
-
|
|
149
|
-
// Replace the span with canvas
|
|
150
|
-
parent.replaceChild(newCanvas, canvas);
|
|
151
|
-
canvas = newCanvas;
|
|
152
|
-
} else {
|
|
153
|
-
// Set canvas dimensions to match original sparkline
|
|
154
|
-
this.setCanvasDimensions(canvas, { width: 100, height: 20 });
|
|
155
|
-
}
|
|
156
|
-
|
|
157
|
-
const ctx = canvas.getContext('2d');
|
|
158
|
-
if (!ctx) return;
|
|
159
|
-
|
|
160
|
-
const chartConfig: ChartConfiguration = {
|
|
161
|
-
type: 'bar',
|
|
162
|
-
data: {
|
|
163
|
-
labels: config.data.map((_, i) => i.toString()),
|
|
164
|
-
datasets: [{
|
|
165
|
-
data: config.data,
|
|
166
|
-
backgroundColor: config.color,
|
|
167
|
-
borderColor: config.color,
|
|
168
|
-
borderWidth: 0,
|
|
169
|
-
barPercentage: 0.6,
|
|
170
|
-
categoryPercentage: 0.8,
|
|
171
|
-
}],
|
|
172
|
-
},
|
|
173
|
-
options: {
|
|
174
|
-
responsive: false,
|
|
175
|
-
maintainAspectRatio: false,
|
|
176
|
-
animation: this.options.enableAnimation ? {} : false,
|
|
177
|
-
events: [],
|
|
178
|
-
scales: {
|
|
179
|
-
x: {
|
|
180
|
-
display: false,
|
|
181
|
-
},
|
|
182
|
-
y: {
|
|
183
|
-
display: false,
|
|
184
|
-
},
|
|
185
|
-
},
|
|
186
|
-
plugins: {
|
|
187
|
-
legend: {
|
|
188
|
-
display: false,
|
|
189
|
-
},
|
|
190
|
-
tooltip: {
|
|
191
|
-
enabled: false,
|
|
192
|
-
},
|
|
193
|
-
},
|
|
194
|
-
elements: {
|
|
195
|
-
bar: {
|
|
196
|
-
borderRadius: 1,
|
|
197
|
-
},
|
|
198
|
-
},
|
|
199
|
-
},
|
|
200
|
-
};
|
|
201
|
-
|
|
202
|
-
const chart = new Chart(ctx, chartConfig);
|
|
203
|
-
this.charts.set(config.id, chart);
|
|
204
|
-
}
|
|
205
|
-
|
|
206
|
-
/**
|
|
207
|
-
* Set canvas dimensions
|
|
208
|
-
*/
|
|
209
|
-
private setCanvasDimensions(canvas: HTMLCanvasElement, dimensions: ChartDimensions): void {
|
|
210
|
-
canvas.width = dimensions.width;
|
|
211
|
-
canvas.height = dimensions.height;
|
|
212
|
-
canvas.style.width = `${dimensions.width}px`;
|
|
213
|
-
canvas.style.height = `${dimensions.height}px`;
|
|
214
|
-
}
|
|
215
|
-
|
|
216
|
-
/**
|
|
217
|
-
* Create other chart types (only if they exist on the page)
|
|
218
|
-
*/
|
|
219
|
-
private createOtherCharts(): void {
|
|
220
|
-
// Determine if we're on the dashboard or charts page
|
|
221
|
-
const isChartsPage = document.getElementById('area-chart') !== null;
|
|
222
|
-
const isDashboard = !isChartsPage && document.getElementById('line-chart') !== null;
|
|
223
|
-
|
|
224
|
-
// Create Monthly Stats chart with enhanced dual-line data (dashboard only)
|
|
225
|
-
if (isDashboard) {
|
|
226
|
-
this.createMonthlyStatsChart();
|
|
227
|
-
}
|
|
228
|
-
|
|
229
|
-
// Charts page specific charts (only on charts page)
|
|
230
|
-
if (isChartsPage) {
|
|
231
|
-
this.createChartsPageCharts();
|
|
232
|
-
}
|
|
233
|
-
|
|
234
|
-
// Only create charts if their target elements exist
|
|
235
|
-
if (document.getElementById('sparkline')) {
|
|
236
|
-
this.createLineChart('sparkline', [5, 6, 7, 9, 9, 5, 3, 2, 2, 4, 6, 7]);
|
|
237
|
-
}
|
|
238
|
-
|
|
239
|
-
if (document.getElementById('compositebar')) {
|
|
240
|
-
this.createCompositeChart('compositebar', [4, 1, 5, 7, 9, 9, 8, 7, 6, 6, 4, 7, 8, 4, 3, 2, 2, 5, 6, 7]);
|
|
241
|
-
}
|
|
242
|
-
|
|
243
|
-
// Regular sparklines with custom colors (only on pages that have them)
|
|
244
|
-
this.createCustomSparklines();
|
|
245
|
-
|
|
246
|
-
// Easy Pie Charts (only if they exist)
|
|
247
|
-
this.createEasyPieCharts();
|
|
248
|
-
}
|
|
249
|
-
|
|
250
|
-
/**
|
|
251
|
-
* Create enhanced Monthly Stats chart with dual lines and more data
|
|
252
|
-
*/
|
|
253
|
-
private createMonthlyStatsChart(): void {
|
|
254
|
-
const canvas = document.getElementById('line-chart') as HTMLCanvasElement;
|
|
255
|
-
if (!canvas) return;
|
|
256
|
-
|
|
257
|
-
const ctx = canvas.getContext('2d');
|
|
258
|
-
if (!ctx) return;
|
|
259
|
-
|
|
260
|
-
// Enhanced data for monthly stats
|
|
261
|
-
const months = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'];
|
|
262
|
-
const salesData = [120, 135, 145, 165, 180, 195, 210, 225, 240, 220, 200, 185];
|
|
263
|
-
const profitData = [45, 52, 58, 62, 68, 75, 82, 88, 92, 85, 78, 72];
|
|
264
|
-
|
|
265
|
-
const chartConfig: ChartConfiguration = {
|
|
266
|
-
type: 'line',
|
|
267
|
-
data: {
|
|
268
|
-
labels: months,
|
|
269
|
-
datasets: [
|
|
270
|
-
{
|
|
271
|
-
label: 'Sales ($K)',
|
|
272
|
-
data: salesData,
|
|
273
|
-
borderColor: '#4caf50',
|
|
274
|
-
backgroundColor: 'rgba(76, 175, 80, 0.1)',
|
|
275
|
-
borderWidth: 3,
|
|
276
|
-
pointRadius: 5,
|
|
277
|
-
pointHoverRadius: 7,
|
|
278
|
-
pointBackgroundColor: '#4caf50',
|
|
279
|
-
pointBorderColor: '#ffffff',
|
|
280
|
-
pointBorderWidth: 2,
|
|
281
|
-
tension: 0.4,
|
|
282
|
-
fill: false,
|
|
283
|
-
},
|
|
284
|
-
{
|
|
285
|
-
label: 'Profit ($K)',
|
|
286
|
-
data: profitData,
|
|
287
|
-
borderColor: '#2196f3',
|
|
288
|
-
backgroundColor: 'rgba(33, 150, 243, 0.1)',
|
|
289
|
-
borderWidth: 3,
|
|
290
|
-
pointRadius: 5,
|
|
291
|
-
pointHoverRadius: 7,
|
|
292
|
-
pointBackgroundColor: '#2196f3',
|
|
293
|
-
pointBorderColor: '#ffffff',
|
|
294
|
-
pointBorderWidth: 2,
|
|
295
|
-
tension: 0.4,
|
|
296
|
-
fill: false,
|
|
297
|
-
},
|
|
298
|
-
],
|
|
299
|
-
},
|
|
300
|
-
options: {
|
|
301
|
-
responsive: true,
|
|
302
|
-
maintainAspectRatio: false,
|
|
303
|
-
plugins: {
|
|
304
|
-
legend: {
|
|
305
|
-
display: true,
|
|
306
|
-
position: 'top',
|
|
307
|
-
labels: {
|
|
308
|
-
padding: 20,
|
|
309
|
-
font: {
|
|
310
|
-
size: 12,
|
|
311
|
-
weight: 600,
|
|
312
|
-
},
|
|
313
|
-
},
|
|
314
|
-
},
|
|
315
|
-
tooltip: {
|
|
316
|
-
enabled: true,
|
|
317
|
-
cornerRadius: 8,
|
|
318
|
-
displayColors: true,
|
|
319
|
-
intersect: false,
|
|
320
|
-
mode: 'index',
|
|
321
|
-
callbacks: {
|
|
322
|
-
label(context) {
|
|
323
|
-
return `${context.dataset.label}: $${context.parsed.y}K`;
|
|
324
|
-
},
|
|
325
|
-
},
|
|
326
|
-
},
|
|
327
|
-
},
|
|
328
|
-
scales: {
|
|
329
|
-
x: {
|
|
330
|
-
grid: {
|
|
331
|
-
display: false,
|
|
332
|
-
},
|
|
333
|
-
ticks: {
|
|
334
|
-
font: {
|
|
335
|
-
size: 11,
|
|
336
|
-
},
|
|
337
|
-
},
|
|
338
|
-
},
|
|
339
|
-
y: {
|
|
340
|
-
beginAtZero: true,
|
|
341
|
-
grid: {
|
|
342
|
-
borderDash: [5, 5] as [number, number],
|
|
343
|
-
},
|
|
344
|
-
ticks: {
|
|
345
|
-
font: {
|
|
346
|
-
size: 11,
|
|
347
|
-
},
|
|
348
|
-
callback(value) {
|
|
349
|
-
return `$${value}K`;
|
|
350
|
-
},
|
|
351
|
-
},
|
|
352
|
-
},
|
|
353
|
-
},
|
|
354
|
-
interaction: {
|
|
355
|
-
intersect: false,
|
|
356
|
-
mode: 'index',
|
|
357
|
-
},
|
|
358
|
-
},
|
|
359
|
-
};
|
|
360
|
-
|
|
361
|
-
const chart = new Chart(ctx, chartConfig);
|
|
362
|
-
this.charts.set('line-chart', chart);
|
|
363
|
-
}
|
|
364
|
-
|
|
365
|
-
/**
|
|
366
|
-
* Create line chart (only if target exists)
|
|
367
|
-
*/
|
|
368
|
-
private createLineChart(id: string, data: number[]): void {
|
|
369
|
-
let canvas = document.getElementById(id) as HTMLCanvasElement;
|
|
370
|
-
|
|
371
|
-
// Only proceed if target element exists
|
|
372
|
-
if (!canvas) {
|
|
373
|
-
return;
|
|
374
|
-
}
|
|
375
|
-
|
|
376
|
-
// If element exists but isn't a canvas, replace it with canvas
|
|
377
|
-
if (canvas.tagName !== 'CANVAS') {
|
|
378
|
-
const parent = canvas.parentNode;
|
|
379
|
-
if (!parent) {
|
|
380
|
-
return;
|
|
381
|
-
}
|
|
382
|
-
|
|
383
|
-
// Create new canvas element
|
|
384
|
-
const newCanvas = document.createElement('canvas');
|
|
385
|
-
newCanvas.id = id;
|
|
386
|
-
this.setCanvasDimensions(newCanvas, { width: 100, height: 20 });
|
|
387
|
-
|
|
388
|
-
// Replace element with canvas
|
|
389
|
-
parent.replaceChild(newCanvas, canvas);
|
|
390
|
-
canvas = newCanvas;
|
|
391
|
-
} else {
|
|
392
|
-
this.setCanvasDimensions(canvas, { width: 100, height: 20 });
|
|
393
|
-
}
|
|
394
|
-
|
|
395
|
-
const ctx = canvas.getContext('2d');
|
|
396
|
-
if (!ctx) return;
|
|
397
|
-
|
|
398
|
-
const chartConfig: ChartConfiguration = {
|
|
399
|
-
type: 'line',
|
|
400
|
-
data: {
|
|
401
|
-
labels: data.map((_, i) => i.toString()),
|
|
402
|
-
datasets: [{
|
|
403
|
-
data,
|
|
404
|
-
borderColor: COLORS['blue-500'],
|
|
405
|
-
backgroundColor: 'transparent',
|
|
406
|
-
borderWidth: 1,
|
|
407
|
-
pointRadius: 0,
|
|
408
|
-
tension: 0.4,
|
|
409
|
-
}],
|
|
410
|
-
},
|
|
411
|
-
options: {
|
|
412
|
-
responsive: false,
|
|
413
|
-
maintainAspectRatio: false,
|
|
414
|
-
animation: false,
|
|
415
|
-
events: [],
|
|
416
|
-
scales: {
|
|
417
|
-
x: { display: false },
|
|
418
|
-
y: { display: false },
|
|
419
|
-
},
|
|
420
|
-
plugins: {
|
|
421
|
-
legend: { display: false },
|
|
422
|
-
tooltip: { enabled: false },
|
|
423
|
-
},
|
|
424
|
-
},
|
|
425
|
-
};
|
|
426
|
-
|
|
427
|
-
const chart = new Chart(ctx, chartConfig);
|
|
428
|
-
this.charts.set(id, chart);
|
|
429
|
-
}
|
|
430
|
-
|
|
431
|
-
/**
|
|
432
|
-
* Create composite chart (only if target exists)
|
|
433
|
-
*/
|
|
434
|
-
private createCompositeChart(id: string, data: number[]): void {
|
|
435
|
-
let canvas = document.getElementById(id) as HTMLCanvasElement;
|
|
436
|
-
|
|
437
|
-
// Only proceed if target element exists
|
|
438
|
-
if (!canvas) {
|
|
439
|
-
return;
|
|
440
|
-
}
|
|
441
|
-
|
|
442
|
-
// If element exists but isn't a canvas, replace it with canvas
|
|
443
|
-
if (canvas.tagName !== 'CANVAS') {
|
|
444
|
-
const parent = canvas.parentNode;
|
|
445
|
-
if (!parent) {
|
|
446
|
-
return;
|
|
447
|
-
}
|
|
448
|
-
|
|
449
|
-
// Create new canvas element
|
|
450
|
-
const newCanvas = document.createElement('canvas');
|
|
451
|
-
newCanvas.id = id;
|
|
452
|
-
this.setCanvasDimensions(newCanvas, { width: 100, height: 20 });
|
|
453
|
-
|
|
454
|
-
// Replace element with canvas
|
|
455
|
-
parent.replaceChild(newCanvas, canvas);
|
|
456
|
-
canvas = newCanvas;
|
|
457
|
-
} else {
|
|
458
|
-
this.setCanvasDimensions(canvas, { width: 100, height: 20 });
|
|
459
|
-
}
|
|
460
|
-
|
|
461
|
-
const ctx = canvas.getContext('2d');
|
|
462
|
-
if (!ctx) return;
|
|
463
|
-
|
|
464
|
-
const chartConfig: ChartConfiguration = {
|
|
465
|
-
type: 'bar',
|
|
466
|
-
data: {
|
|
467
|
-
labels: data.map((_, i) => i.toString()),
|
|
468
|
-
datasets: [
|
|
469
|
-
{
|
|
470
|
-
type: 'bar',
|
|
471
|
-
data,
|
|
472
|
-
backgroundColor: '#aaf',
|
|
473
|
-
borderColor: '#aaf',
|
|
474
|
-
borderWidth: 0,
|
|
475
|
-
},
|
|
476
|
-
{
|
|
477
|
-
type: 'line',
|
|
478
|
-
data,
|
|
479
|
-
borderColor: 'red',
|
|
480
|
-
backgroundColor: 'transparent',
|
|
481
|
-
borderWidth: 1,
|
|
482
|
-
pointRadius: 0,
|
|
483
|
-
tension: 0.4,
|
|
484
|
-
} as any, // Type assertion needed for mixed chart types
|
|
485
|
-
],
|
|
486
|
-
},
|
|
487
|
-
options: {
|
|
488
|
-
responsive: false,
|
|
489
|
-
maintainAspectRatio: false,
|
|
490
|
-
animation: false,
|
|
491
|
-
events: [],
|
|
492
|
-
scales: {
|
|
493
|
-
x: { display: false },
|
|
494
|
-
y: { display: false },
|
|
495
|
-
},
|
|
496
|
-
plugins: {
|
|
497
|
-
legend: { display: false },
|
|
498
|
-
tooltip: { enabled: false },
|
|
499
|
-
},
|
|
500
|
-
},
|
|
501
|
-
};
|
|
502
|
-
|
|
503
|
-
const chart = new Chart(ctx, chartConfig);
|
|
504
|
-
this.charts.set(id, chart);
|
|
505
|
-
}
|
|
506
|
-
|
|
507
|
-
/**
|
|
508
|
-
* Create custom sparklines for different elements (only if they exist)
|
|
509
|
-
*/
|
|
510
|
-
private createCustomSparklines(): void {
|
|
511
|
-
const sparklineElements = document.querySelectorAll('.sparkline');
|
|
512
|
-
const sparkbarElements = document.querySelectorAll('.sparkbar');
|
|
513
|
-
const sparktriElements = document.querySelectorAll('.sparktri');
|
|
514
|
-
const sparkdiscElements = document.querySelectorAll('.sparkdisc');
|
|
515
|
-
const sparkbullElements = document.querySelectorAll('.sparkbull');
|
|
516
|
-
const sparkboxElements = document.querySelectorAll('.sparkbox');
|
|
517
|
-
|
|
518
|
-
// Only create if we have elements
|
|
519
|
-
if (sparklineElements.length === 0 && sparkbarElements.length === 0 &&
|
|
520
|
-
sparktriElements.length === 0 && sparkdiscElements.length === 0 &&
|
|
521
|
-
sparkbullElements.length === 0 && sparkboxElements.length === 0) {
|
|
522
|
-
return;
|
|
523
|
-
}
|
|
524
|
-
|
|
525
|
-
const values = [5, 4, 5, -2, 0, 3, -5, 6, 7, 9, 9, 5, -3, -2, 2, -4];
|
|
526
|
-
const valuesAlt = [1, 1, 0, 1, -1, -1, 1, -1, 0, 0, 1, 1];
|
|
527
|
-
|
|
528
|
-
sparklineElements.forEach((element, index) => {
|
|
529
|
-
this.createCustomLineChart(element as HTMLElement, values, `sparkline-${index}`);
|
|
530
|
-
});
|
|
531
|
-
|
|
532
|
-
sparkbarElements.forEach((element, index) => {
|
|
533
|
-
this.createCustomBarChart(element as HTMLElement, values, `sparkbar-${index}`);
|
|
534
|
-
});
|
|
535
|
-
|
|
536
|
-
sparktriElements.forEach((element, index) => {
|
|
537
|
-
this.createTristateChart(element as HTMLElement, valuesAlt, `sparktri-${index}`);
|
|
538
|
-
});
|
|
539
|
-
|
|
540
|
-
sparkdiscElements.forEach((element, index) => {
|
|
541
|
-
this.createDiscreteChart(element as HTMLElement, values, `sparkdisc-${index}`);
|
|
542
|
-
});
|
|
543
|
-
|
|
544
|
-
sparkbullElements.forEach((element, index) => {
|
|
545
|
-
this.createBulletChart(element as HTMLElement, values, `sparkbull-${index}`);
|
|
546
|
-
});
|
|
547
|
-
|
|
548
|
-
sparkboxElements.forEach((element, index) => {
|
|
549
|
-
this.createBoxChart(element as HTMLElement, values, `sparkbox-${index}`);
|
|
550
|
-
});
|
|
551
|
-
}
|
|
552
|
-
|
|
553
|
-
/**
|
|
554
|
-
* Create custom line chart for sparkline elements
|
|
555
|
-
*/
|
|
556
|
-
private createCustomLineChart(element: HTMLElement, data: number[], id: string): void {
|
|
557
|
-
// Create canvas if it doesn't exist
|
|
558
|
-
let canvas = element.querySelector('canvas') as HTMLCanvasElement;
|
|
559
|
-
if (!canvas) {
|
|
560
|
-
canvas = document.createElement('canvas');
|
|
561
|
-
this.setCanvasDimensions(canvas, { width: 100, height: 20 });
|
|
562
|
-
element.appendChild(canvas);
|
|
563
|
-
}
|
|
564
|
-
|
|
565
|
-
const ctx = canvas.getContext('2d');
|
|
566
|
-
if (!ctx) return;
|
|
567
|
-
|
|
568
|
-
const chartConfig: ChartConfiguration = {
|
|
569
|
-
type: 'line',
|
|
570
|
-
data: {
|
|
571
|
-
labels: data.map((_, i) => i.toString()),
|
|
572
|
-
datasets: [{
|
|
573
|
-
data,
|
|
574
|
-
borderColor: COLORS['red-500'],
|
|
575
|
-
backgroundColor: 'transparent',
|
|
576
|
-
borderWidth: 2,
|
|
577
|
-
pointRadius: 3,
|
|
578
|
-
pointBackgroundColor: COLORS['red-500'],
|
|
579
|
-
tension: 0.4,
|
|
580
|
-
}],
|
|
581
|
-
},
|
|
582
|
-
options: {
|
|
583
|
-
responsive: false,
|
|
584
|
-
maintainAspectRatio: false,
|
|
585
|
-
animation: false, // Disable animations to prevent resize triggers
|
|
586
|
-
events: [], // Disable all events to prevent resize
|
|
587
|
-
scales: {
|
|
588
|
-
x: { display: false },
|
|
589
|
-
y: { display: false },
|
|
590
|
-
},
|
|
591
|
-
plugins: {
|
|
592
|
-
legend: { display: false },
|
|
593
|
-
tooltip: { enabled: false }, // Disable tooltip to prevent events
|
|
594
|
-
},
|
|
595
|
-
},
|
|
596
|
-
};
|
|
597
|
-
|
|
598
|
-
const chart = new Chart(ctx, chartConfig);
|
|
599
|
-
this.charts.set(id, chart);
|
|
600
|
-
}
|
|
601
|
-
|
|
602
|
-
/**
|
|
603
|
-
* Create custom bar chart for sparkbar elements
|
|
604
|
-
*/
|
|
605
|
-
private createCustomBarChart(element: HTMLElement, data: number[], id: string): void {
|
|
606
|
-
// Create canvas if it doesn't exist
|
|
607
|
-
let canvas = element.querySelector('canvas') as HTMLCanvasElement;
|
|
608
|
-
if (!canvas) {
|
|
609
|
-
canvas = document.createElement('canvas');
|
|
610
|
-
this.setCanvasDimensions(canvas, { width: 100, height: 20 });
|
|
611
|
-
element.appendChild(canvas);
|
|
612
|
-
}
|
|
613
|
-
|
|
614
|
-
const ctx = canvas.getContext('2d');
|
|
615
|
-
if (!ctx) return;
|
|
616
|
-
|
|
617
|
-
const chartConfig: ChartConfiguration = {
|
|
618
|
-
type: 'bar',
|
|
619
|
-
data: {
|
|
620
|
-
labels: data.map((_, i) => i.toString()),
|
|
621
|
-
datasets: [{
|
|
622
|
-
data,
|
|
623
|
-
backgroundColor: data.map(val => val < 0 ? COLORS['deep-purple-500'] : '#39f'),
|
|
624
|
-
borderColor: data.map(val => val < 0 ? COLORS['deep-purple-500'] : '#39f'),
|
|
625
|
-
borderWidth: 1,
|
|
626
|
-
barPercentage: 0.8,
|
|
627
|
-
}],
|
|
628
|
-
},
|
|
629
|
-
options: {
|
|
630
|
-
responsive: false,
|
|
631
|
-
maintainAspectRatio: false,
|
|
632
|
-
scales: {
|
|
633
|
-
x: { display: false },
|
|
634
|
-
y: { display: false },
|
|
635
|
-
},
|
|
636
|
-
plugins: {
|
|
637
|
-
legend: { display: false },
|
|
638
|
-
tooltip: {
|
|
639
|
-
enabled: true,
|
|
640
|
-
callbacks: {
|
|
641
|
-
label: (context) => `${context.parsed.y}°Celsius`,
|
|
642
|
-
},
|
|
643
|
-
},
|
|
644
|
-
},
|
|
645
|
-
},
|
|
646
|
-
};
|
|
647
|
-
|
|
648
|
-
const chart = new Chart(ctx, chartConfig);
|
|
649
|
-
this.charts.set(id, chart);
|
|
650
|
-
}
|
|
651
|
-
|
|
652
|
-
/**
|
|
653
|
-
* Setup resize handler for charts
|
|
654
|
-
*/
|
|
655
|
-
private setupResizeHandler(): void {
|
|
656
|
-
// Setup responsive resize for large charts only
|
|
657
|
-
window.addEventListener('resize', () => {
|
|
658
|
-
this.debounceResize();
|
|
659
|
-
});
|
|
660
|
-
|
|
661
|
-
// Listen for sidebar toggle events
|
|
662
|
-
window.addEventListener('sidebar:toggle', () => {
|
|
663
|
-
this.debounceResize();
|
|
664
|
-
});
|
|
665
|
-
}
|
|
666
|
-
|
|
667
|
-
/**
|
|
668
|
-
* Debounced resize handler
|
|
669
|
-
*/
|
|
670
|
-
private debounceResize(): void {
|
|
671
|
-
if (this.debounceTimer) {
|
|
672
|
-
clearTimeout(this.debounceTimer);
|
|
673
|
-
}
|
|
674
|
-
this.debounceTimer = window.setTimeout(() => {
|
|
675
|
-
this.redrawLargeChartsOnly();
|
|
676
|
-
}, this.options.resizeDebounceMs || 150);
|
|
677
|
-
}
|
|
678
|
-
|
|
679
|
-
/**
|
|
680
|
-
* Redraw only large charts, not sparklines
|
|
681
|
-
*/
|
|
682
|
-
private redrawLargeChartsOnly(): void {
|
|
683
|
-
const largeChartIds = [
|
|
684
|
-
'line-chart', 'area-chart', 'scatter-chart', 'bar-chart',
|
|
685
|
-
'doughnut-chart', 'polar-chart', 'radar-chart', 'mixed-chart', 'bubble-chart',
|
|
686
|
-
];
|
|
687
|
-
|
|
688
|
-
largeChartIds.forEach(id => {
|
|
689
|
-
const chart = this.charts.get(id);
|
|
690
|
-
if (chart && chart.options.responsive) {
|
|
691
|
-
chart.resize();
|
|
692
|
-
}
|
|
693
|
-
});
|
|
694
|
-
}
|
|
695
|
-
|
|
696
|
-
/**
|
|
697
|
-
* Redraw all charts (used sparingly)
|
|
698
|
-
*/
|
|
699
|
-
public redrawCharts(): void {
|
|
700
|
-
this.charts.forEach((chart) => {
|
|
701
|
-
if (chart.options.responsive) {
|
|
702
|
-
chart.resize();
|
|
703
|
-
}
|
|
704
|
-
});
|
|
705
|
-
}
|
|
706
|
-
|
|
707
|
-
/**
|
|
708
|
-
* Update chart data
|
|
709
|
-
*/
|
|
710
|
-
public updateChart(id: string, newData: number[]): void {
|
|
711
|
-
const chart = this.charts.get(id);
|
|
712
|
-
if (chart && chart.data.datasets[0]) {
|
|
713
|
-
chart.data.datasets[0].data = newData;
|
|
714
|
-
chart.update();
|
|
715
|
-
}
|
|
716
|
-
}
|
|
717
|
-
|
|
718
|
-
/**
|
|
719
|
-
* Get chart instance by id
|
|
720
|
-
*/
|
|
721
|
-
public getChart(id: string): Chart | undefined {
|
|
722
|
-
return this.charts.get(id);
|
|
723
|
-
}
|
|
724
|
-
|
|
725
|
-
/**
|
|
726
|
-
* Get all chart instances
|
|
727
|
-
*/
|
|
728
|
-
public getAllCharts(): Map<string, Chart> {
|
|
729
|
-
return new Map(this.charts);
|
|
730
|
-
}
|
|
731
|
-
|
|
732
|
-
/**
|
|
733
|
-
* Create charts for the charts.html page
|
|
734
|
-
*/
|
|
735
|
-
private createChartsPageCharts(): void {
|
|
736
|
-
// Line Chart
|
|
737
|
-
this.createLargeChart('line-chart', 'line', {
|
|
738
|
-
labels: ['January', 'February', 'March', 'April', 'May', 'June', 'July'],
|
|
739
|
-
datasets: [{
|
|
740
|
-
label: 'Dataset 1',
|
|
741
|
-
data: [65, 59, 80, 81, 56, 55, 40],
|
|
742
|
-
borderColor: 'rgb(75, 192, 192)',
|
|
743
|
-
backgroundColor: 'rgba(75, 192, 192, 0.2)',
|
|
744
|
-
tension: 0.4,
|
|
745
|
-
}],
|
|
746
|
-
});
|
|
747
|
-
|
|
748
|
-
// Area Chart
|
|
749
|
-
this.createLargeChart('area-chart', 'line', {
|
|
750
|
-
labels: ['January', 'February', 'March', 'April', 'May', 'June', 'July'],
|
|
751
|
-
datasets: [{
|
|
752
|
-
label: 'Dataset 1',
|
|
753
|
-
data: [65, 59, 80, 81, 56, 55, 40],
|
|
754
|
-
borderColor: 'rgb(54, 162, 235)',
|
|
755
|
-
backgroundColor: 'rgba(54, 162, 235, 0.4)',
|
|
756
|
-
fill: true,
|
|
757
|
-
tension: 0.4,
|
|
758
|
-
}],
|
|
759
|
-
});
|
|
760
|
-
|
|
761
|
-
// Scatter Chart with more data points
|
|
762
|
-
this.createLargeChart('scatter-chart', 'scatter', {
|
|
763
|
-
datasets: [{
|
|
764
|
-
label: 'Dataset 1',
|
|
765
|
-
data: [
|
|
766
|
-
{x: -15, y: 8}, {x: -12, y: 12}, {x: -8, y: 3}, {x: -5, y: 15},
|
|
767
|
-
{x: -2, y: 7}, {x: 0, y: 10}, {x: 3, y: 18}, {x: 6, y: 5},
|
|
768
|
-
{x: 9, y: 22}, {x: 12, y: 8}, {x: 15, y: 14}, {x: 18, y: 19},
|
|
769
|
-
{x: -10, y: 0}, {x: 10, y: 5}, {x: 0.5, y: 5.5}, {x: 7, y: 12},
|
|
770
|
-
{x: -7, y: 17}, {x: 4, y: 9}, {x: 11, y: 16}, {x: -3, y: 11},
|
|
771
|
-
],
|
|
772
|
-
backgroundColor: 'rgba(255, 99, 132, 0.7)',
|
|
773
|
-
borderColor: 'rgb(255, 99, 132)',
|
|
774
|
-
borderWidth: 1,
|
|
775
|
-
}],
|
|
776
|
-
});
|
|
777
|
-
|
|
778
|
-
// Continue with other chart types...
|
|
779
|
-
this.createBarChart();
|
|
780
|
-
this.createDoughnutChart();
|
|
781
|
-
this.createPolarChart();
|
|
782
|
-
this.createRadarChart();
|
|
783
|
-
this.createMixedChart();
|
|
784
|
-
this.createBubbleChart();
|
|
785
|
-
}
|
|
786
|
-
|
|
787
|
-
/**
|
|
788
|
-
* Create large chart for charts page
|
|
789
|
-
*/
|
|
790
|
-
private createLargeChart(id: string, type: ChartJSType, data: any): void {
|
|
791
|
-
const canvas = document.getElementById(id) as HTMLCanvasElement;
|
|
792
|
-
if (!canvas) return;
|
|
793
|
-
|
|
794
|
-
const ctx = canvas.getContext('2d');
|
|
795
|
-
if (!ctx) return;
|
|
796
|
-
|
|
797
|
-
// Define chart-specific options
|
|
798
|
-
const chartOptions = this.getChartOptions(type);
|
|
799
|
-
|
|
800
|
-
const chartConfig: ChartConfiguration = {
|
|
801
|
-
type,
|
|
802
|
-
data,
|
|
803
|
-
options: chartOptions,
|
|
804
|
-
};
|
|
805
|
-
|
|
806
|
-
const chart = new Chart(ctx, chartConfig);
|
|
807
|
-
this.charts.set(id, chart);
|
|
808
|
-
}
|
|
809
|
-
|
|
810
|
-
/**
|
|
811
|
-
* Get chart-specific options based on chart type
|
|
812
|
-
*/
|
|
813
|
-
private getChartOptions(type: ChartJSType): any {
|
|
814
|
-
const baseOptions = {
|
|
815
|
-
responsive: true,
|
|
816
|
-
maintainAspectRatio: false,
|
|
817
|
-
plugins: {
|
|
818
|
-
legend: {
|
|
819
|
-
display: true,
|
|
820
|
-
position: 'top' as const,
|
|
821
|
-
labels: {
|
|
822
|
-
padding: 20,
|
|
823
|
-
font: {
|
|
824
|
-
size: 12,
|
|
825
|
-
weight: '600' as const,
|
|
826
|
-
},
|
|
827
|
-
},
|
|
828
|
-
},
|
|
829
|
-
tooltip: {
|
|
830
|
-
enabled: true,
|
|
831
|
-
cornerRadius: 8,
|
|
832
|
-
displayColors: true,
|
|
833
|
-
},
|
|
834
|
-
},
|
|
835
|
-
};
|
|
836
|
-
|
|
837
|
-
// Chart type specific configurations
|
|
838
|
-
switch (type) {
|
|
839
|
-
case 'doughnut':
|
|
840
|
-
case 'pie':
|
|
841
|
-
return {
|
|
842
|
-
...baseOptions,
|
|
843
|
-
plugins: {
|
|
844
|
-
...baseOptions.plugins,
|
|
845
|
-
legend: {
|
|
846
|
-
...baseOptions.plugins.legend,
|
|
847
|
-
position: 'right' as const,
|
|
848
|
-
},
|
|
849
|
-
},
|
|
850
|
-
interaction: {
|
|
851
|
-
intersect: false,
|
|
852
|
-
},
|
|
853
|
-
};
|
|
854
|
-
|
|
855
|
-
case 'polarArea':
|
|
856
|
-
return {
|
|
857
|
-
...baseOptions,
|
|
858
|
-
scales: {
|
|
859
|
-
r: {
|
|
860
|
-
pointLabels: {
|
|
861
|
-
display: true,
|
|
862
|
-
centerPointLabels: true,
|
|
863
|
-
font: {
|
|
864
|
-
size: 10,
|
|
865
|
-
},
|
|
866
|
-
},
|
|
867
|
-
grid: {},
|
|
868
|
-
},
|
|
869
|
-
},
|
|
870
|
-
};
|
|
871
|
-
|
|
872
|
-
case 'radar':
|
|
873
|
-
return {
|
|
874
|
-
...baseOptions,
|
|
875
|
-
scales: {
|
|
876
|
-
r: {
|
|
877
|
-
angleLines: {
|
|
878
|
-
display: true,
|
|
879
|
-
},
|
|
880
|
-
grid: {},
|
|
881
|
-
pointLabels: {
|
|
882
|
-
font: {
|
|
883
|
-
size: 11,
|
|
884
|
-
},
|
|
885
|
-
},
|
|
886
|
-
ticks: {
|
|
887
|
-
display: true,
|
|
888
|
-
font: {
|
|
889
|
-
size: 10,
|
|
890
|
-
},
|
|
891
|
-
},
|
|
892
|
-
},
|
|
893
|
-
},
|
|
894
|
-
};
|
|
895
|
-
|
|
896
|
-
case 'bubble':
|
|
897
|
-
return {
|
|
898
|
-
...baseOptions,
|
|
899
|
-
scales: {
|
|
900
|
-
x: {
|
|
901
|
-
type: 'linear' as const,
|
|
902
|
-
position: 'bottom' as const,
|
|
903
|
-
grid: {
|
|
904
|
-
borderDash: [5, 5] as [number, number],
|
|
905
|
-
},
|
|
906
|
-
ticks: {
|
|
907
|
-
font: {
|
|
908
|
-
size: 11,
|
|
909
|
-
},
|
|
910
|
-
},
|
|
911
|
-
},
|
|
912
|
-
y: {
|
|
913
|
-
beginAtZero: true,
|
|
914
|
-
grid: {
|
|
915
|
-
borderDash: [5, 5] as [number, number],
|
|
916
|
-
},
|
|
917
|
-
ticks: {
|
|
918
|
-
font: {
|
|
919
|
-
size: 11,
|
|
920
|
-
},
|
|
921
|
-
},
|
|
922
|
-
},
|
|
923
|
-
},
|
|
924
|
-
};
|
|
925
|
-
|
|
926
|
-
case 'scatter':
|
|
927
|
-
return {
|
|
928
|
-
...baseOptions,
|
|
929
|
-
scales: {
|
|
930
|
-
x: {
|
|
931
|
-
type: 'linear' as const,
|
|
932
|
-
position: 'bottom' as const,
|
|
933
|
-
grid: {
|
|
934
|
-
borderDash: [5, 5] as [number, number],
|
|
935
|
-
},
|
|
936
|
-
ticks: {
|
|
937
|
-
font: {
|
|
938
|
-
size: 11,
|
|
939
|
-
},
|
|
940
|
-
},
|
|
941
|
-
},
|
|
942
|
-
y: {
|
|
943
|
-
grid: {
|
|
944
|
-
borderDash: [5, 5] as [number, number],
|
|
945
|
-
},
|
|
946
|
-
ticks: {
|
|
947
|
-
font: {
|
|
948
|
-
size: 11,
|
|
949
|
-
},
|
|
950
|
-
},
|
|
951
|
-
},
|
|
952
|
-
},
|
|
953
|
-
};
|
|
954
|
-
|
|
955
|
-
default:
|
|
956
|
-
// For line, bar, area, mixed charts
|
|
957
|
-
return {
|
|
958
|
-
...baseOptions,
|
|
959
|
-
scales: {
|
|
960
|
-
x: {
|
|
961
|
-
grid: {
|
|
962
|
-
borderDash: [5, 5] as [number, number],
|
|
963
|
-
},
|
|
964
|
-
ticks: {
|
|
965
|
-
font: {
|
|
966
|
-
size: 11,
|
|
967
|
-
},
|
|
968
|
-
},
|
|
969
|
-
},
|
|
970
|
-
y: {
|
|
971
|
-
beginAtZero: true,
|
|
972
|
-
grid: {
|
|
973
|
-
borderDash: [5, 5] as [number, number],
|
|
974
|
-
},
|
|
975
|
-
ticks: {
|
|
976
|
-
font: {
|
|
977
|
-
size: 11,
|
|
978
|
-
},
|
|
979
|
-
},
|
|
980
|
-
},
|
|
981
|
-
},
|
|
982
|
-
};
|
|
983
|
-
}
|
|
984
|
-
}
|
|
985
|
-
|
|
986
|
-
// Additional chart creation methods...
|
|
987
|
-
private createBarChart(): void {
|
|
988
|
-
this.createLargeChart('bar-chart', 'bar', {
|
|
989
|
-
labels: ['Red', 'Blue', 'Yellow', 'Green', 'Purple', 'Orange'],
|
|
990
|
-
datasets: [{
|
|
991
|
-
label: '# of Votes',
|
|
992
|
-
data: [12, 19, 3, 5, 2, 3],
|
|
993
|
-
backgroundColor: [
|
|
994
|
-
'rgba(255, 99, 132, 0.6)',
|
|
995
|
-
'rgba(54, 162, 235, 0.6)',
|
|
996
|
-
'rgba(255, 205, 86, 0.6)',
|
|
997
|
-
'rgba(75, 192, 192, 0.6)',
|
|
998
|
-
'rgba(153, 102, 255, 0.6)',
|
|
999
|
-
'rgba(255, 159, 64, 0.6)',
|
|
1000
|
-
],
|
|
1001
|
-
borderColor: [
|
|
1002
|
-
'rgba(255, 99, 132, 1)',
|
|
1003
|
-
'rgba(54, 162, 235, 1)',
|
|
1004
|
-
'rgba(255, 205, 86, 1)',
|
|
1005
|
-
'rgba(75, 192, 192, 1)',
|
|
1006
|
-
'rgba(153, 102, 255, 1)',
|
|
1007
|
-
'rgba(255, 159, 64, 1)',
|
|
1008
|
-
],
|
|
1009
|
-
borderWidth: 1,
|
|
1010
|
-
}],
|
|
1011
|
-
});
|
|
1012
|
-
}
|
|
1013
|
-
|
|
1014
|
-
private createDoughnutChart(): void {
|
|
1015
|
-
this.createLargeChart('doughnut-chart', 'doughnut', {
|
|
1016
|
-
labels: ['Red', 'Blue', 'Yellow', 'Green', 'Purple', 'Orange'],
|
|
1017
|
-
datasets: [{
|
|
1018
|
-
label: 'My First Dataset',
|
|
1019
|
-
data: [300, 50, 100, 75, 120, 60],
|
|
1020
|
-
backgroundColor: [
|
|
1021
|
-
'rgba(255, 99, 132, 0.8)',
|
|
1022
|
-
'rgba(54, 162, 235, 0.8)',
|
|
1023
|
-
'rgba(255, 205, 86, 0.8)',
|
|
1024
|
-
'rgba(75, 192, 192, 0.8)',
|
|
1025
|
-
'rgba(153, 102, 255, 0.8)',
|
|
1026
|
-
'rgba(255, 159, 64, 0.8)',
|
|
1027
|
-
],
|
|
1028
|
-
borderWidth: 2,
|
|
1029
|
-
hoverOffset: 10,
|
|
1030
|
-
}],
|
|
1031
|
-
});
|
|
1032
|
-
}
|
|
1033
|
-
|
|
1034
|
-
private createPolarChart(): void {
|
|
1035
|
-
this.createLargeChart('polar-chart', 'polarArea', {
|
|
1036
|
-
labels: ['Red', 'Green', 'Yellow', 'Grey', 'Blue'],
|
|
1037
|
-
datasets: [{
|
|
1038
|
-
label: 'My First Dataset',
|
|
1039
|
-
data: [11, 16, 7, 3, 14],
|
|
1040
|
-
backgroundColor: [
|
|
1041
|
-
'rgba(255, 99, 132, 0.7)',
|
|
1042
|
-
'rgba(75, 192, 192, 0.7)',
|
|
1043
|
-
'rgba(255, 205, 86, 0.7)',
|
|
1044
|
-
'rgba(201, 203, 207, 0.7)',
|
|
1045
|
-
'rgba(54, 162, 235, 0.7)',
|
|
1046
|
-
],
|
|
1047
|
-
borderWidth: 2,
|
|
1048
|
-
}],
|
|
1049
|
-
});
|
|
1050
|
-
}
|
|
1051
|
-
|
|
1052
|
-
private createRadarChart(): void {
|
|
1053
|
-
this.createLargeChart('radar-chart', 'radar', {
|
|
1054
|
-
labels: ['Speed', 'Reliability', 'Comfort', 'Safety', 'Efficiency', 'Innovation'],
|
|
1055
|
-
datasets: [{
|
|
1056
|
-
label: 'Product A',
|
|
1057
|
-
data: [65, 59, 90, 81, 56, 55],
|
|
1058
|
-
fill: true,
|
|
1059
|
-
backgroundColor: 'rgba(54, 162, 235, 0.2)',
|
|
1060
|
-
borderColor: 'rgb(54, 162, 235)',
|
|
1061
|
-
borderWidth: 2,
|
|
1062
|
-
}],
|
|
1063
|
-
});
|
|
1064
|
-
}
|
|
1065
|
-
|
|
1066
|
-
private createMixedChart(): void {
|
|
1067
|
-
this.createLargeChart('mixed-chart', 'bar', {
|
|
1068
|
-
labels: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun'],
|
|
1069
|
-
datasets: [{
|
|
1070
|
-
type: 'bar',
|
|
1071
|
-
label: 'Sales',
|
|
1072
|
-
data: [12, 19, 3, 5, 2, 3],
|
|
1073
|
-
backgroundColor: 'rgba(54, 162, 235, 0.7)',
|
|
1074
|
-
}, {
|
|
1075
|
-
type: 'line',
|
|
1076
|
-
label: 'Revenue',
|
|
1077
|
-
data: [18, 25, 8, 15, 12, 18],
|
|
1078
|
-
borderColor: 'rgb(255, 99, 132)',
|
|
1079
|
-
tension: 0.4,
|
|
1080
|
-
}],
|
|
1081
|
-
});
|
|
1082
|
-
}
|
|
1083
|
-
|
|
1084
|
-
private createBubbleChart(): void {
|
|
1085
|
-
this.createLargeChart('bubble-chart', 'bubble', {
|
|
1086
|
-
datasets: [{
|
|
1087
|
-
label: 'First Dataset',
|
|
1088
|
-
data: [
|
|
1089
|
-
{x: 20, y: 30, r: 15},
|
|
1090
|
-
{x: 40, y: 10, r: 10},
|
|
1091
|
-
{x: 30, y: 40, r: 20},
|
|
1092
|
-
],
|
|
1093
|
-
backgroundColor: 'rgba(54, 162, 235, 0.6)',
|
|
1094
|
-
borderColor: 'rgb(54, 162, 235)',
|
|
1095
|
-
borderWidth: 2,
|
|
1096
|
-
}],
|
|
1097
|
-
});
|
|
1098
|
-
}
|
|
1099
|
-
|
|
1100
|
-
/**
|
|
1101
|
-
* Create tristate chart (for .sparktri elements)
|
|
1102
|
-
*/
|
|
1103
|
-
private createTristateChart(element: HTMLElement, data: number[], id: string): void {
|
|
1104
|
-
let canvas = element.querySelector('canvas') as HTMLCanvasElement;
|
|
1105
|
-
if (!canvas) {
|
|
1106
|
-
canvas = document.createElement('canvas');
|
|
1107
|
-
this.setCanvasDimensions(canvas, { width: 100, height: 20 });
|
|
1108
|
-
element.appendChild(canvas);
|
|
1109
|
-
}
|
|
1110
|
-
|
|
1111
|
-
const ctx = canvas.getContext('2d');
|
|
1112
|
-
if (!ctx) return;
|
|
1113
|
-
|
|
1114
|
-
const chartConfig: ChartConfiguration = {
|
|
1115
|
-
type: 'bar',
|
|
1116
|
-
data: {
|
|
1117
|
-
labels: data.map((_, i) => i.toString()),
|
|
1118
|
-
datasets: [{
|
|
1119
|
-
data: data.map(val => Math.abs(val)),
|
|
1120
|
-
backgroundColor: data.map(val => {
|
|
1121
|
-
if (val > 0) return COLORS['light-blue-500'];
|
|
1122
|
-
if (val < 0) return '#f90';
|
|
1123
|
-
return '#000';
|
|
1124
|
-
}),
|
|
1125
|
-
borderWidth: 1,
|
|
1126
|
-
barPercentage: 0.8,
|
|
1127
|
-
}],
|
|
1128
|
-
},
|
|
1129
|
-
options: {
|
|
1130
|
-
responsive: false,
|
|
1131
|
-
maintainAspectRatio: false,
|
|
1132
|
-
scales: {
|
|
1133
|
-
x: { display: false },
|
|
1134
|
-
y: { display: false },
|
|
1135
|
-
},
|
|
1136
|
-
plugins: {
|
|
1137
|
-
legend: { display: false },
|
|
1138
|
-
tooltip: { enabled: false },
|
|
1139
|
-
},
|
|
1140
|
-
},
|
|
1141
|
-
};
|
|
1142
|
-
|
|
1143
|
-
const chart = new Chart(ctx, chartConfig);
|
|
1144
|
-
this.charts.set(id, chart);
|
|
1145
|
-
}
|
|
1146
|
-
|
|
1147
|
-
/**
|
|
1148
|
-
* Create discrete chart (for .sparkdisc elements)
|
|
1149
|
-
*/
|
|
1150
|
-
private createDiscreteChart(element: HTMLElement, data: number[], id: string): void {
|
|
1151
|
-
let canvas = element.querySelector('canvas') as HTMLCanvasElement;
|
|
1152
|
-
if (!canvas) {
|
|
1153
|
-
canvas = document.createElement('canvas');
|
|
1154
|
-
this.setCanvasDimensions(canvas, { width: 100, height: 20 });
|
|
1155
|
-
element.appendChild(canvas);
|
|
1156
|
-
}
|
|
1157
|
-
|
|
1158
|
-
const ctx = canvas.getContext('2d');
|
|
1159
|
-
if (!ctx) return;
|
|
1160
|
-
|
|
1161
|
-
const chartConfig: ChartConfiguration = {
|
|
1162
|
-
type: 'scatter',
|
|
1163
|
-
data: {
|
|
1164
|
-
datasets: [{
|
|
1165
|
-
data: data.map((val, index) => ({x: index, y: val})),
|
|
1166
|
-
backgroundColor: '#9f0',
|
|
1167
|
-
borderColor: '#9f0',
|
|
1168
|
-
pointRadius: 2,
|
|
1169
|
-
showLine: false,
|
|
1170
|
-
}],
|
|
1171
|
-
},
|
|
1172
|
-
options: {
|
|
1173
|
-
responsive: false,
|
|
1174
|
-
maintainAspectRatio: false,
|
|
1175
|
-
scales: {
|
|
1176
|
-
x: { display: false },
|
|
1177
|
-
y: { display: false },
|
|
1178
|
-
},
|
|
1179
|
-
plugins: {
|
|
1180
|
-
legend: { display: false },
|
|
1181
|
-
tooltip: { enabled: false },
|
|
1182
|
-
},
|
|
1183
|
-
},
|
|
1184
|
-
};
|
|
1185
|
-
|
|
1186
|
-
const chart = new Chart(ctx, chartConfig);
|
|
1187
|
-
this.charts.set(id, chart);
|
|
1188
|
-
}
|
|
1189
|
-
|
|
1190
|
-
/**
|
|
1191
|
-
* Create bullet chart (for .sparkbull elements)
|
|
1192
|
-
*/
|
|
1193
|
-
private createBulletChart(element: HTMLElement, data: number[], id: string): void {
|
|
1194
|
-
let canvas = element.querySelector('canvas') as HTMLCanvasElement;
|
|
1195
|
-
if (!canvas) {
|
|
1196
|
-
canvas = document.createElement('canvas');
|
|
1197
|
-
this.setCanvasDimensions(canvas, { width: 100, height: 20 });
|
|
1198
|
-
element.appendChild(canvas);
|
|
1199
|
-
}
|
|
1200
|
-
|
|
1201
|
-
const ctx = canvas.getContext('2d');
|
|
1202
|
-
if (!ctx) return;
|
|
1203
|
-
|
|
1204
|
-
const chartConfig: ChartConfiguration = {
|
|
1205
|
-
type: 'bar',
|
|
1206
|
-
data: {
|
|
1207
|
-
labels: [''],
|
|
1208
|
-
datasets: [{
|
|
1209
|
-
data: [Math.max(...data)],
|
|
1210
|
-
backgroundColor: COLORS['amber-500'],
|
|
1211
|
-
borderColor: COLORS['amber-500'],
|
|
1212
|
-
borderWidth: 1,
|
|
1213
|
-
barPercentage: 0.6,
|
|
1214
|
-
}],
|
|
1215
|
-
},
|
|
1216
|
-
options: {
|
|
1217
|
-
responsive: false,
|
|
1218
|
-
maintainAspectRatio: false,
|
|
1219
|
-
indexAxis: 'y',
|
|
1220
|
-
scales: {
|
|
1221
|
-
x: { display: false },
|
|
1222
|
-
y: { display: false },
|
|
1223
|
-
},
|
|
1224
|
-
plugins: {
|
|
1225
|
-
legend: { display: false },
|
|
1226
|
-
tooltip: { enabled: false },
|
|
1227
|
-
},
|
|
1228
|
-
},
|
|
1229
|
-
};
|
|
1230
|
-
|
|
1231
|
-
const chart = new Chart(ctx, chartConfig);
|
|
1232
|
-
this.charts.set(id, chart);
|
|
1233
|
-
}
|
|
1234
|
-
|
|
1235
|
-
/**
|
|
1236
|
-
* Create box chart (for .sparkbox elements)
|
|
1237
|
-
*/
|
|
1238
|
-
private createBoxChart(element: HTMLElement, data: number[], id: string): void {
|
|
1239
|
-
let canvas = element.querySelector('canvas') as HTMLCanvasElement;
|
|
1240
|
-
if (!canvas) {
|
|
1241
|
-
canvas = document.createElement('canvas');
|
|
1242
|
-
this.setCanvasDimensions(canvas, { width: 100, height: 20 });
|
|
1243
|
-
element.appendChild(canvas);
|
|
1244
|
-
}
|
|
1245
|
-
|
|
1246
|
-
const ctx = canvas.getContext('2d');
|
|
1247
|
-
if (!ctx) return;
|
|
1248
|
-
|
|
1249
|
-
// Box plot simplified as bar chart showing quartiles
|
|
1250
|
-
const sortedData = [...data].sort((a, b) => a - b);
|
|
1251
|
-
const q1 = sortedData[Math.floor(sortedData.length * 0.25)];
|
|
1252
|
-
const median = sortedData[Math.floor(sortedData.length * 0.5)];
|
|
1253
|
-
const q3 = sortedData[Math.floor(sortedData.length * 0.75)];
|
|
1254
|
-
|
|
1255
|
-
const chartConfig: ChartConfiguration = {
|
|
1256
|
-
type: 'bar',
|
|
1257
|
-
data: {
|
|
1258
|
-
labels: ['Q1', 'Med', 'Q3'],
|
|
1259
|
-
datasets: [{
|
|
1260
|
-
data: [q1, median, q3],
|
|
1261
|
-
backgroundColor: '#9f0',
|
|
1262
|
-
borderColor: '#9f0',
|
|
1263
|
-
borderWidth: 1,
|
|
1264
|
-
barPercentage: 0.8,
|
|
1265
|
-
}],
|
|
1266
|
-
},
|
|
1267
|
-
options: {
|
|
1268
|
-
responsive: false,
|
|
1269
|
-
maintainAspectRatio: false,
|
|
1270
|
-
scales: {
|
|
1271
|
-
x: { display: false },
|
|
1272
|
-
y: { display: false },
|
|
1273
|
-
},
|
|
1274
|
-
plugins: {
|
|
1275
|
-
legend: { display: false },
|
|
1276
|
-
tooltip: { enabled: false },
|
|
1277
|
-
},
|
|
1278
|
-
},
|
|
1279
|
-
};
|
|
1280
|
-
|
|
1281
|
-
const chart = new Chart(ctx, chartConfig);
|
|
1282
|
-
this.charts.set(id, chart);
|
|
1283
|
-
}
|
|
1284
|
-
|
|
1285
|
-
/**
|
|
1286
|
-
* Create Easy Pie Charts (replaces jQuery Easy Pie Chart)
|
|
1287
|
-
*/
|
|
1288
|
-
private createEasyPieCharts(): void {
|
|
1289
|
-
const easyPieElements = document.querySelectorAll('.easy-pie-chart');
|
|
1290
|
-
|
|
1291
|
-
easyPieElements.forEach((element, index) => {
|
|
1292
|
-
const htmlElement = element as HTMLElement;
|
|
1293
|
-
const size = parseInt(htmlElement.dataset.size || '80');
|
|
1294
|
-
const percent = parseInt(htmlElement.dataset.percent || '0');
|
|
1295
|
-
const barColor = htmlElement.dataset.barColor || '#f44336';
|
|
1296
|
-
|
|
1297
|
-
// Create canvas for the pie chart
|
|
1298
|
-
let canvas = element.querySelector('canvas') as HTMLCanvasElement;
|
|
1299
|
-
if (!canvas) {
|
|
1300
|
-
canvas = document.createElement('canvas');
|
|
1301
|
-
this.setCanvasDimensions(canvas, { width: size, height: size });
|
|
1302
|
-
element.appendChild(canvas);
|
|
1303
|
-
}
|
|
1304
|
-
|
|
1305
|
-
// Create percentage display
|
|
1306
|
-
const percentDisplay = element.querySelector('span') as HTMLSpanElement;
|
|
1307
|
-
if (percentDisplay) {
|
|
1308
|
-
percentDisplay.textContent = `${percent}%`;
|
|
1309
|
-
percentDisplay.style.position = 'absolute';
|
|
1310
|
-
percentDisplay.style.top = '50%';
|
|
1311
|
-
percentDisplay.style.left = '50%';
|
|
1312
|
-
percentDisplay.style.transform = 'translate(-50%, -50%)';
|
|
1313
|
-
percentDisplay.style.fontSize = '14px';
|
|
1314
|
-
percentDisplay.style.fontWeight = 'bold';
|
|
1315
|
-
}
|
|
1316
|
-
|
|
1317
|
-
// Set element position to relative for absolute positioning of text
|
|
1318
|
-
htmlElement.style.position = 'relative';
|
|
1319
|
-
htmlElement.style.display = 'inline-block';
|
|
1320
|
-
|
|
1321
|
-
const ctx = canvas.getContext('2d');
|
|
1322
|
-
if (!ctx) return;
|
|
1323
|
-
|
|
1324
|
-
const chartConfig: ChartConfiguration = {
|
|
1325
|
-
type: 'doughnut',
|
|
1326
|
-
data: {
|
|
1327
|
-
datasets: [{
|
|
1328
|
-
data: [percent, 100 - percent],
|
|
1329
|
-
backgroundColor: [barColor, '#f0f0f0'],
|
|
1330
|
-
borderWidth: 0,
|
|
1331
|
-
}],
|
|
1332
|
-
},
|
|
1333
|
-
options: {
|
|
1334
|
-
responsive: false,
|
|
1335
|
-
maintainAspectRatio: false,
|
|
1336
|
-
cutout: '70%',
|
|
1337
|
-
plugins: {
|
|
1338
|
-
legend: { display: false },
|
|
1339
|
-
tooltip: { enabled: false },
|
|
1340
|
-
},
|
|
1341
|
-
},
|
|
1342
|
-
};
|
|
1343
|
-
|
|
1344
|
-
const chart = new Chart(ctx, chartConfig);
|
|
1345
|
-
this.charts.set(`easy-pie-${index}`, chart);
|
|
1346
|
-
});
|
|
1347
|
-
}
|
|
1348
|
-
}
|
|
1349
|
-
|
|
1350
|
-
export default ChartComponent;
|