@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
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@quicdata/analytics",
3
- "version": "0.0.12",
3
+ "version": "0.0.13",
4
4
  "type": "module",
5
5
  "main": "index.js",
6
6
  "module": "index.js",
@@ -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;AAO9E;;;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,gBAAgB,CAAU;IACnD,QAAyB,gBAAgB,CAAS;IAElD,OAAO,CAAC,eAAe,CAAK;IAC5B,OAAO,CAAC,cAAc,CAAS;IAC/B,OAAO,CAAC,YAAY,CAAmC;IACvD,OAAO,CAAC,kBAAkB,CAA6B;IACvD,OAAO,CAAC,iBAAiB,CAAS;IAClC,OAAO,CAAC,uBAAuB,CAAS;IACxC,OAAO,CAAC,kBAAkB,CAAS;;IAsBnC,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;IA2B5C,YAAY,IAAI,IAAI;IAkB7B,OAAO,CAAC,gBAAgB;IASxB,OAAO,CAAC,gBAAgB;IASxB,OAAO,CAAC,oBAAoB;IAO5B,OAAO,CAAC,mBAAmB;IAQ3B,OAAO,KAAK,eAAe,GAE1B;IAED,OAAO,CAAC,MAAM;YAQA,SAAS;IA+DvB,OAAO,CAAC,UAAU;IAKlB,+EAA+E;IAC/E,OAAO,CAAC,YAAY;IAsBX,MAAM;CAqFhB"}
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"}
@@ -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
- if (changed.has('dataUrl') ||
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
- const out = { ...(this.dataParams ?? {}) };
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 && !this._definitionTitle) {
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
- params = { ...(this.dataParams ?? {}) };
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);