@quicdata/analytics 0.0.12 → 0.0.13
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/package.json
CHANGED
package/widgets/number-kpi.d.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { LitElement } from 'lit';
|
|
2
2
|
import type { WidgetDefinitionSubset } from '../core/fetch-data.js';
|
|
3
3
|
import type { DashboardContainer } from '../dashboard/dashboard-container.js';
|
|
4
|
+
import '../filters/index.js';
|
|
4
5
|
/**
|
|
5
6
|
* Number KPI widget. Displays one or more large formatted numbers with labels.
|
|
6
7
|
* Data shape from backend transformNumber(): { chartType: 'Number', values, labels, options }.
|
|
@@ -21,10 +22,14 @@ export declare class NumberKpiWidget extends LitElement {
|
|
|
21
22
|
private _loading;
|
|
22
23
|
private _error;
|
|
23
24
|
private _dashboardParams;
|
|
25
|
+
private _widgetFilters;
|
|
26
|
+
private _widgetFilterParams;
|
|
27
|
+
private _hideFilter;
|
|
24
28
|
private _viewportVisible;
|
|
25
29
|
private _definitionTitle;
|
|
26
30
|
private _loadGeneration;
|
|
27
31
|
private _hasLoadedOnce;
|
|
32
|
+
private _ignoreNextFilterChange;
|
|
28
33
|
private _dashboardEl;
|
|
29
34
|
private _viewportUnobserve;
|
|
30
35
|
private _loadDataInFlight;
|
|
@@ -45,6 +50,7 @@ export declare class NumberKpiWidget extends LitElement {
|
|
|
45
50
|
private _defer;
|
|
46
51
|
private _loadData;
|
|
47
52
|
private _onRefresh;
|
|
53
|
+
private _onWidgetFilterChange;
|
|
48
54
|
/** Format a number: apply decimal places, optionally shorten (1234 → 1.2K). */
|
|
49
55
|
private _formatValue;
|
|
50
56
|
render(): import("lit-html").TemplateResult<1>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"number-kpi.d.ts","sourceRoot":"","sources":["../../../../libs/analytics/src/widgets/number-kpi.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAsB,MAAM,KAAK,CAAC;AAGrD,OAAO,KAAK,EAA0B,sBAAsB,EAAE,MAAM,uBAAuB,CAAC;AAM5F,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,qCAAqC,CAAC;
|
|
1
|
+
{"version":3,"file":"number-kpi.d.ts","sourceRoot":"","sources":["../../../../libs/analytics/src/widgets/number-kpi.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAsB,MAAM,KAAK,CAAC;AAGrD,OAAO,KAAK,EAA0B,sBAAsB,EAAE,MAAM,uBAAuB,CAAC;AAM5F,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,qCAAqC,CAAC;AAM9E,OAAO,qBAAqB,CAAC;AAE7B;;;GAGG;AACH,qBACa,eAAgB,SAAQ,UAAU;IAC7C,OAAgB,MAAM,0BAsMpB;IAEkC,KAAK,EAAE,MAAM,CAAC;IACqB,iBAAiB,EAAE,OAAO,CAAC;IACvC,OAAO,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,GAAG,MAAM,CAAC;IAC5B,MAAM,EAAE,MAAM,CAAC;IACrC,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,CAAC,CAAC;IACtD,SAAS,EAAE,kBAAkB,GAAG,IAAI,CAAC;IACpC,IAAI,EAAE,OAAO,CAAC;IACe,cAAc,EAAE,MAAM,CAAC;IACrD,iBAAiB,EAAE,sBAAsB,GAAG,SAAS,CAAC;IAE1F,QAAyB,QAAQ,CAA6B;IAC9D,QAAyB,QAAQ,CAAU;IAC3C,QAAyB,MAAM,CAAgB;IAC/C,QAAyB,gBAAgB,CAA4C;IACrF,QAAyB,cAAc,CAAqB;IAC5D,QAAyB,mBAAmB,CAA4C;IACxF,QAAyB,WAAW,CAAU;IAC9C,QAAyB,gBAAgB,CAAU;IACnD,QAAyB,gBAAgB,CAAS;IAElD,OAAO,CAAC,eAAe,CAAK;IAC5B,OAAO,CAAC,cAAc,CAAS;IAC/B,OAAO,CAAC,uBAAuB,CAAS;IACxC,OAAO,CAAC,YAAY,CAAmC;IACvD,OAAO,CAAC,kBAAkB,CAA6B;IACvD,OAAO,CAAC,iBAAiB,CAAS;IAClC,OAAO,CAAC,uBAAuB,CAAS;IACxC,OAAO,CAAC,kBAAkB,CAAS;;IAyBnC,OAAO,CAAC,6BAA6B,CAInC;IAEF,OAAO,CAAC,wBAAwB,CAG9B;IAEO,iBAAiB,IAAI,IAAI;IAKzB,oBAAoB,IAAI,IAAI;IAO5B,OAAO,CAAC,OAAO,EAAE,GAAG,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI;IAuC5C,YAAY,IAAI,IAAI;IAkB7B,OAAO,CAAC,gBAAgB;IASxB,OAAO,CAAC,gBAAgB;IASxB,OAAO,CAAC,oBAAoB;IAO5B,OAAO,CAAC,mBAAmB;IAyB3B,OAAO,KAAK,eAAe,GAE1B;IAED,OAAO,CAAC,MAAM;YAQA,SAAS;IA6EvB,OAAO,CAAC,UAAU;IAKlB,OAAO,CAAC,qBAAqB;IAI7B,+EAA+E;IAC/E,OAAO,CAAC,YAAY;IAsBX,MAAM;CAmGhB"}
|
package/widgets/number-kpi.js
CHANGED
|
@@ -4,6 +4,7 @@ import { customElement, property, state } from 'lit/decorators.js';
|
|
|
4
4
|
import { buildWidgetDataUrl, fetchWidgetData, fetchWidgetDefinition, } from '../core/fetch-data.js';
|
|
5
5
|
import { EVENT_DASHBOARD_FILTER_CHANGE, EVENT_DASHBOARD_REFRESH, } from '../dashboard/index.js';
|
|
6
6
|
import { observeViewport } from '../core/viewport-observer.js';
|
|
7
|
+
import '../filters/index.js';
|
|
7
8
|
/**
|
|
8
9
|
* Number KPI widget. Displays one or more large formatted numbers with labels.
|
|
9
10
|
* Data shape from backend transformNumber(): { chartType: 'Number', values, labels, options }.
|
|
@@ -212,6 +213,7 @@ let NumberKpiWidget = class NumberKpiWidget extends LitElement {
|
|
|
212
213
|
super();
|
|
213
214
|
this._loadGeneration = 0;
|
|
214
215
|
this._hasLoadedOnce = false;
|
|
216
|
+
this._ignoreNextFilterChange = false;
|
|
215
217
|
this._dashboardEl = null;
|
|
216
218
|
this._viewportUnobserve = null;
|
|
217
219
|
this._loadDataInFlight = false;
|
|
@@ -241,6 +243,9 @@ let NumberKpiWidget = class NumberKpiWidget extends LitElement {
|
|
|
241
243
|
this._loading = false;
|
|
242
244
|
this._error = null;
|
|
243
245
|
this._dashboardParams = {};
|
|
246
|
+
this._widgetFilters = [];
|
|
247
|
+
this._widgetFilterParams = {};
|
|
248
|
+
this._hideFilter = false;
|
|
244
249
|
this._viewportVisible = true;
|
|
245
250
|
this._definitionTitle = '';
|
|
246
251
|
}
|
|
@@ -261,11 +266,23 @@ let NumberKpiWidget = class NumberKpiWidget extends LitElement {
|
|
|
261
266
|
}
|
|
262
267
|
if (changed.has('widgetId') || changed.has('apiUrl')) {
|
|
263
268
|
this._definitionTitle = '';
|
|
269
|
+
this._widgetFilters = [];
|
|
270
|
+
this._widgetFilterParams = {};
|
|
271
|
+
this._ignoreNextFilterChange = true;
|
|
264
272
|
}
|
|
265
|
-
|
|
273
|
+
const onlyFilterState = (changed.has('_widgetFilterParams') || changed.has('_widgetFilters')) &&
|
|
274
|
+
!changed.has('dataUrl') &&
|
|
275
|
+
!changed.has('dataParams') &&
|
|
276
|
+
!changed.has('widgetId') &&
|
|
277
|
+
!changed.has('apiUrl');
|
|
278
|
+
if (onlyFilterState && this._ignoreNextFilterChange) {
|
|
279
|
+
this._ignoreNextFilterChange = false;
|
|
280
|
+
}
|
|
281
|
+
else if (changed.has('dataUrl') ||
|
|
266
282
|
changed.has('dataParams') ||
|
|
267
283
|
changed.has('widgetId') ||
|
|
268
|
-
changed.has('apiUrl')
|
|
284
|
+
changed.has('apiUrl') ||
|
|
285
|
+
changed.has('_widgetFilterParams')) {
|
|
269
286
|
if (this._getEffectiveDataUrl() && !this._loadDataScheduled) {
|
|
270
287
|
this._loadDataScheduled = true;
|
|
271
288
|
queueMicrotask(() => {
|
|
@@ -321,7 +338,26 @@ let NumberKpiWidget = class NumberKpiWidget extends LitElement {
|
|
|
321
338
|
return this.dataUrl;
|
|
322
339
|
}
|
|
323
340
|
_getEffectiveParams() {
|
|
324
|
-
|
|
341
|
+
let widgetFilterParams = {};
|
|
342
|
+
if (this._hideFilter) {
|
|
343
|
+
for (const f of this._widgetFilters) {
|
|
344
|
+
if (f.default_value !== undefined && f.default_value !== null) {
|
|
345
|
+
widgetFilterParams[f.param_name] = f.default_value;
|
|
346
|
+
}
|
|
347
|
+
}
|
|
348
|
+
}
|
|
349
|
+
else if (this._widgetFilters.length > 0) {
|
|
350
|
+
for (const f of this._widgetFilters) {
|
|
351
|
+
const setByUser = f.param_name in this._widgetFilterParams;
|
|
352
|
+
widgetFilterParams[f.param_name] = setByUser
|
|
353
|
+
? (this._widgetFilterParams[f.param_name] ?? '')
|
|
354
|
+
: (f.default_value ?? '');
|
|
355
|
+
}
|
|
356
|
+
}
|
|
357
|
+
else {
|
|
358
|
+
widgetFilterParams = { ...this._widgetFilterParams };
|
|
359
|
+
}
|
|
360
|
+
const out = { ...widgetFilterParams, ...(this.dataParams ?? {}) };
|
|
325
361
|
if (Object.keys(this._dashboardParams).length > 0) {
|
|
326
362
|
out.dashboard_params = this._dashboardParams;
|
|
327
363
|
}
|
|
@@ -358,17 +394,27 @@ let NumberKpiWidget = class NumberKpiWidget extends LitElement {
|
|
|
358
394
|
try {
|
|
359
395
|
const useWidgetApi = Boolean(this.apiUrl && this.widgetId);
|
|
360
396
|
let params;
|
|
361
|
-
if (useWidgetApi &&
|
|
397
|
+
if (useWidgetApi && this._widgetFilters.length === 0) {
|
|
362
398
|
const def = this.initialDefinition ?? (await fetchWidgetDefinition(this.apiUrl, this.widgetId));
|
|
363
399
|
this._definitionTitle = def.title ?? '';
|
|
364
|
-
|
|
400
|
+
this._widgetFilters = def.filters ?? [];
|
|
401
|
+
this._hideFilter = def.hide_filter ?? false;
|
|
402
|
+
const defaultParams = {};
|
|
403
|
+
for (const f of (def.filters ?? [])) {
|
|
404
|
+
if (f.default_value !== undefined && f.default_value !== null) {
|
|
405
|
+
defaultParams[f.param_name] = f.default_value;
|
|
406
|
+
}
|
|
407
|
+
}
|
|
408
|
+
this._widgetFilterParams = { ...defaultParams, ...this._widgetFilterParams };
|
|
409
|
+
this._ignoreNextFilterChange = true;
|
|
410
|
+
params = { ...defaultParams, ...(this.dataParams ?? {}) };
|
|
411
|
+
if (Object.keys(this._dashboardParams).length > 0) {
|
|
412
|
+
params.dashboard_params = this._dashboardParams;
|
|
413
|
+
}
|
|
365
414
|
}
|
|
366
415
|
else {
|
|
367
416
|
params = this._getEffectiveParams();
|
|
368
417
|
}
|
|
369
|
-
if (Object.keys(this._dashboardParams).length > 0) {
|
|
370
|
-
params.dashboard_params = this._dashboardParams;
|
|
371
|
-
}
|
|
372
418
|
const res = await fetchWidgetData(dataUrl, params);
|
|
373
419
|
if (gen !== this._loadGeneration)
|
|
374
420
|
return;
|
|
@@ -376,11 +422,17 @@ let NumberKpiWidget = class NumberKpiWidget extends LitElement {
|
|
|
376
422
|
const kpiData = wd && wd.chartType === 'Number'
|
|
377
423
|
? { chartType: 'Number', values: wd.values ?? [], labels: wd.labels ?? [], options: wd.options, shorten_numbers: wd.shorten_numbers }
|
|
378
424
|
: null;
|
|
425
|
+
const filters = res.filters;
|
|
426
|
+
const hideFilter = res.hide_filter;
|
|
379
427
|
this._defer(() => {
|
|
380
428
|
if (gen !== this._loadGeneration)
|
|
381
429
|
return;
|
|
382
430
|
this._loadDataInFlight = false;
|
|
383
431
|
this._kpiData = kpiData;
|
|
432
|
+
if (filters?.length)
|
|
433
|
+
this._widgetFilters = filters;
|
|
434
|
+
if (hideFilter !== undefined)
|
|
435
|
+
this._hideFilter = hideFilter;
|
|
384
436
|
this._hasLoadedOnce = true;
|
|
385
437
|
this._loading = false;
|
|
386
438
|
if (this._loadDataPendingRefresh) {
|
|
@@ -410,6 +462,9 @@ let NumberKpiWidget = class NumberKpiWidget extends LitElement {
|
|
|
410
462
|
return;
|
|
411
463
|
this._loadData();
|
|
412
464
|
}
|
|
465
|
+
_onWidgetFilterChange(e) {
|
|
466
|
+
this._widgetFilterParams = { ...(e.detail?.params ?? {}) };
|
|
467
|
+
}
|
|
413
468
|
/** Format a number: apply decimal places, optionally shorten (1234 → 1.2K). */
|
|
414
469
|
_formatValue(value, decimal, shorten) {
|
|
415
470
|
const dec = decimal != null && decimal !== '' ? parseInt(decimal, 10) : undefined;
|
|
@@ -436,6 +491,8 @@ let NumberKpiWidget = class NumberKpiWidget extends LitElement {
|
|
|
436
491
|
}
|
|
437
492
|
render() {
|
|
438
493
|
const canRefresh = Boolean(this._getEffectiveDataUrl()) && !this.hideRefreshButton;
|
|
494
|
+
const hasWidgetFilters = this._widgetFilters.length > 0 && !this._hideFilter;
|
|
495
|
+
const widgetActiveCount = Object.keys(this._widgetFilterParams).filter((k) => this._widgetFilterParams[k] !== '' && this._widgetFilterParams[k] != null).length;
|
|
439
496
|
const showSkeleton = this._loading && !this._hasLoadedOnce;
|
|
440
497
|
const showSpinnerOverlay = this._loading && this._hasLoadedOnce;
|
|
441
498
|
const showTitlePlaceholder = !this._effectiveTitle && !this.hideRefreshButton;
|
|
@@ -512,6 +569,16 @@ let NumberKpiWidget = class NumberKpiWidget extends LitElement {
|
|
|
512
569
|
<div class="loading-spinner" aria-hidden="true"></div>
|
|
513
570
|
</div>`
|
|
514
571
|
: nothing}
|
|
572
|
+
${hasWidgetFilters
|
|
573
|
+
? html `
|
|
574
|
+
<analytics-widget-toolbar
|
|
575
|
+
.filters=${this._widgetFilters}
|
|
576
|
+
.values=${this._widgetFilterParams}
|
|
577
|
+
.activeCount=${widgetActiveCount}
|
|
578
|
+
@analytics-filter-change=${this._onWidgetFilterChange}
|
|
579
|
+
></analytics-widget-toolbar>
|
|
580
|
+
`
|
|
581
|
+
: ''}
|
|
515
582
|
</div>
|
|
516
583
|
`;
|
|
517
584
|
}
|
|
@@ -558,6 +625,15 @@ __decorate([
|
|
|
558
625
|
__decorate([
|
|
559
626
|
state()
|
|
560
627
|
], NumberKpiWidget.prototype, "_dashboardParams", void 0);
|
|
628
|
+
__decorate([
|
|
629
|
+
state()
|
|
630
|
+
], NumberKpiWidget.prototype, "_widgetFilters", void 0);
|
|
631
|
+
__decorate([
|
|
632
|
+
state()
|
|
633
|
+
], NumberKpiWidget.prototype, "_widgetFilterParams", void 0);
|
|
634
|
+
__decorate([
|
|
635
|
+
state()
|
|
636
|
+
], NumberKpiWidget.prototype, "_hideFilter", void 0);
|
|
561
637
|
__decorate([
|
|
562
638
|
state()
|
|
563
639
|
], NumberKpiWidget.prototype, "_viewportVisible", void 0);
|