@quicdata/analytics 0.0.6 → 0.0.8

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.
@@ -11,10 +11,13 @@ export declare class AnalyticsWidgetToolbar extends LitElement {
11
11
  activeCount: number;
12
12
  private _dialogOpen;
13
13
  private _portalRoot;
14
+ private _inFilterChange;
15
+ private _onEscapeKey;
14
16
  updated(changed: Map<string, unknown>): void;
15
17
  disconnectedCallback(): void;
16
18
  private _renderOverlayPortal;
17
19
  private _onFilterIconClick;
20
+ private _onOverlayClick;
18
21
  private _onDialogClose;
19
22
  private _onFilterChange;
20
23
  private _onFilterBarClose;
@@ -1 +1 @@
1
- {"version":3,"file":"widget-toolbar.d.ts","sourceRoot":"","sources":["../../../../libs/analytics/src/filters/widget-toolbar.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAa,MAAM,KAAK,CAAC;AAG5C,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAC;AAiEzD;;;GAGG;AACH,qBACa,sBAAuB,SAAQ,UAAU;IACpD,OAAgB,MAAM,0BA8DpB;IAEyB,OAAO,EAAE,gBAAgB,EAAE,CAAM;IAChC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,CAAC,CAAM;IACvD,WAAW,SAAK;IAEnC,OAAO,CAAC,WAAW,CAAS;IACrC,OAAO,CAAC,WAAW,CAA4B;IAEtC,OAAO,CAAC,OAAO,EAAE,GAAG,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI;IAc5C,oBAAoB,IAAI,IAAI;IAQrC,OAAO,CAAC,oBAAoB;IA+B5B,OAAO,CAAC,kBAAkB;IAI1B,OAAO,CAAC,cAAc;IAOtB,OAAO,CAAC,eAAe;IAWvB,OAAO,CAAC,iBAAiB;IAIhB,MAAM;CAsBhB;AAED,OAAO,CAAC,MAAM,CAAC;IACb,UAAU,qBAAqB;QAC7B,0BAA0B,EAAE,sBAAsB,CAAC;KACpD;CACF"}
1
+ {"version":3,"file":"widget-toolbar.d.ts","sourceRoot":"","sources":["../../../../libs/analytics/src/filters/widget-toolbar.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAa,MAAM,KAAK,CAAC;AAG5C,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAC;AAiEzD;;;GAGG;AACH,qBACa,sBAAuB,SAAQ,UAAU;IACpD,OAAgB,MAAM,0BA8DpB;IAEyB,OAAO,EAAE,gBAAgB,EAAE,CAAM;IAChC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,CAAC,CAAM;IACvD,WAAW,SAAK;IAEnC,OAAO,CAAC,WAAW,CAAS;IACrC,OAAO,CAAC,WAAW,CAA4B;IAC/C,OAAO,CAAC,eAAe,CAAS;IAChC,OAAO,CAAC,YAAY,CAMlB;IAEO,OAAO,CAAC,OAAO,EAAE,GAAG,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI;IAgB5C,oBAAoB,IAAI,IAAI;IASrC,OAAO,CAAC,oBAAoB;IA+B5B,OAAO,CAAC,kBAAkB,CAExB;IAEF,OAAO,CAAC,eAAe,CAGrB;IAEF,OAAO,CAAC,cAAc,CAKpB;IAEF,OAAO,CAAC,eAAe,CAgBrB;IAEF,OAAO,CAAC,iBAAiB,CAEvB;IAEO,MAAM;CAsBhB;AAED,OAAO,CAAC,MAAM,CAAC;IACb,UAAU,qBAAqB;QAC7B,0BAA0B,EAAE,sBAAsB,CAAC;KACpD;CACF"}
@@ -76,11 +76,53 @@ let AnalyticsWidgetToolbar = class AnalyticsWidgetToolbar extends LitElement {
76
76
  this.activeCount = 0;
77
77
  this._dialogOpen = false;
78
78
  this._portalRoot = null;
79
+ this._inFilterChange = false;
80
+ this._onEscapeKey = (e) => {
81
+ if (!this._dialogOpen)
82
+ return;
83
+ if (e.key === 'Escape') {
84
+ e.preventDefault();
85
+ this._onDialogClose();
86
+ }
87
+ };
88
+ this._onFilterIconClick = () => {
89
+ this._dialogOpen = true;
90
+ };
91
+ this._onOverlayClick = (e) => {
92
+ if (e.target !== e.currentTarget)
93
+ return; // only close when clicking mask, not dialog
94
+ this._onDialogClose();
95
+ };
96
+ this._onDialogClose = () => {
97
+ this._dialogOpen = false;
98
+ this.dispatchEvent(new CustomEvent(EVENT_FILTER_CLOSE, { bubbles: true, composed: true }));
99
+ };
100
+ this._onFilterChange = (e) => {
101
+ if (this._inFilterChange)
102
+ return;
103
+ if (e.target === this)
104
+ return;
105
+ e.stopPropagation();
106
+ this._inFilterChange = true;
107
+ try {
108
+ this.dispatchEvent(new CustomEvent(EVENT_FILTER_CHANGE, {
109
+ bubbles: true,
110
+ composed: true,
111
+ detail: e.detail,
112
+ }));
113
+ }
114
+ finally {
115
+ this._inFilterChange = false;
116
+ }
117
+ };
118
+ this._onFilterBarClose = () => {
119
+ this._dialogOpen = false;
120
+ };
79
121
  }
80
122
  static { this.styles = css `
81
123
  :host {
82
124
  position: absolute;
83
- top: 0.5rem;
125
+ top: var(--analytics-widget-toolbar-top, 0.5rem);
84
126
  right: 0.5rem;
85
127
  z-index: var(--analytics-widget-toolbar-z-index, 20);
86
128
  opacity: 0;
@@ -148,10 +190,12 @@ let AnalyticsWidgetToolbar = class AnalyticsWidgetToolbar extends LitElement {
148
190
  document.body.appendChild(this._portalRoot);
149
191
  }
150
192
  render(this._renderOverlayPortal(), this._portalRoot);
193
+ window.addEventListener('keydown', this._onEscapeKey);
151
194
  }
152
195
  else if (this._portalRoot) {
153
196
  this._portalRoot.remove();
154
197
  this._portalRoot = null;
198
+ window.removeEventListener('keydown', this._onEscapeKey);
155
199
  }
156
200
  }
157
201
  disconnectedCallback() {
@@ -159,6 +203,7 @@ let AnalyticsWidgetToolbar = class AnalyticsWidgetToolbar extends LitElement {
159
203
  this._portalRoot.remove();
160
204
  this._portalRoot = null;
161
205
  }
206
+ window.removeEventListener('keydown', this._onEscapeKey);
162
207
  super.disconnectedCallback();
163
208
  }
164
209
  _renderOverlayPortal() {
@@ -169,7 +214,7 @@ let AnalyticsWidgetToolbar = class AnalyticsWidgetToolbar extends LitElement {
169
214
  role="dialog"
170
215
  aria-modal="true"
171
216
  aria-label="Filters"
172
- @click=${this._onDialogClose}
217
+ @click=${this._onOverlayClick}
173
218
  >
174
219
  <div class="dialog" @click=${(e) => e.stopPropagation()}>
175
220
  <button type="button" class="dialog-close" aria-label="Close" @click=${this._onDialogClose}>
@@ -191,24 +236,6 @@ let AnalyticsWidgetToolbar = class AnalyticsWidgetToolbar extends LitElement {
191
236
  </div>
192
237
  `;
193
238
  }
194
- _onFilterIconClick() {
195
- this._dialogOpen = true;
196
- }
197
- _onDialogClose() {
198
- this._dialogOpen = false;
199
- this.dispatchEvent(new CustomEvent(EVENT_FILTER_CLOSE, { bubbles: true, composed: true }));
200
- }
201
- _onFilterChange(e) {
202
- e.stopPropagation();
203
- this.dispatchEvent(new CustomEvent(EVENT_FILTER_CHANGE, {
204
- bubbles: true,
205
- composed: true,
206
- detail: e.detail,
207
- }));
208
- }
209
- _onFilterBarClose() {
210
- this._dialogOpen = false;
211
- }
212
239
  render() {
213
240
  const hasFilters = this.filters.length > 0;
214
241
  if (!hasFilters)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@quicdata/analytics",
3
- "version": "0.0.6",
3
+ "version": "0.0.8",
4
4
  "type": "module",
5
5
  "main": "index.js",
6
6
  "module": "index.js",
@@ -26,6 +26,7 @@ export declare class AnalyticsReport extends LitElement {
26
26
  private _excelUrlBase;
27
27
  private _loading;
28
28
  private _error;
29
+ private _refreshKey;
29
30
  constructor();
30
31
  connectedCallback(): void;
31
32
  disconnectedCallback(): void;
@@ -39,6 +40,7 @@ export declare class AnalyticsReport extends LitElement {
39
40
  private get _pdfUrl();
40
41
  private get _excelUrl();
41
42
  private _print;
43
+ private _onRefresh;
42
44
  render(): import("lit-html").TemplateResult<1> | typeof nothing;
43
45
  }
44
46
  declare global {
@@ -1 +1 @@
1
- {"version":3,"file":"analytics-report.d.ts","sourceRoot":"","sources":["../../../../libs/analytics/src/widgets/analytics-report.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAa,OAAO,EAAE,MAAM,KAAK,CAAC;AAYrD,OAAO,0BAA0B,CAAC;AAClC,OAAO,YAAY,CAAC;AAEpB;;;;GAIG;AACH,qBACa,eAAgB,SAAQ,UAAU;IAC7C,OAAgB,MAAM,0BAyFpB;IAEF,oHAAoH;IACxD,QAAQ,EAAE,MAAM,GAAG,MAAM,CAAC;IAEtF,0CAA0C;IACgB,MAAM,EAAE,MAAM,CAAC;IAEzE,gJAAgJ;IACjF,WAAW,EAAE,MAAM,CAAC;IAEnF,6DAA6D;IACzB,KAAK,EAAE,MAAM,CAAC;IAElD,sEAAsE;IAClC,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,CAAC,CAAC;IAE1F,QAAyB,KAAK,CAAS;IACvC,QAAyB,QAAQ,CAAqB;IACtD,QAAyB,OAAO,CAA4C;IAC5E,QAAyB,eAAe,CAAS;IACjD,QAAyB,WAAW,CAAS;IAC7C,QAAyB,aAAa,CAAS;IAC/C,QAAyB,QAAQ,CAAU;IAC3C,QAAyB,MAAM,CAAgB;;IAmBtC,iBAAiB,IAAI,IAAI;IAKzB,oBAAoB,IAAI,IAAI;IAK5B,OAAO,CAAC,OAAO,EAAE,GAAG,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI;YAevC,WAAW;IAwBzB,wJAAwJ;IACxJ,OAAO,CAAC,+BAA+B;IAWvC,OAAO,CAAC,eAAe;IAMvB,OAAO,KAAK,QAAQ,GAGnB;IAED,OAAO,KAAK,WAAW,GAItB;IAED,OAAO,KAAK,OAAO,GAIlB;IAED,OAAO,KAAK,SAAS,GAIpB;IAED,OAAO,CAAC,MAAM;IAIL,MAAM;CAiDhB;AAED,OAAO,CAAC,MAAM,CAAC;IACb,UAAU,qBAAqB;QAC7B,kBAAkB,EAAE,eAAe,CAAC;KACrC;CACF"}
1
+ {"version":3,"file":"analytics-report.d.ts","sourceRoot":"","sources":["../../../../libs/analytics/src/widgets/analytics-report.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAa,OAAO,EAAE,MAAM,KAAK,CAAC;AAYrD,OAAO,0BAA0B,CAAC;AAClC,OAAO,YAAY,CAAC;AAEpB;;;;GAIG;AACH,qBACa,eAAgB,SAAQ,UAAU;IAC7C,OAAgB,MAAM,0BAiHpB;IAEF,oHAAoH;IACxD,QAAQ,EAAE,MAAM,GAAG,MAAM,CAAC;IAEtF,0CAA0C;IACgB,MAAM,EAAE,MAAM,CAAC;IAEzE,gJAAgJ;IACjF,WAAW,EAAE,MAAM,CAAC;IAEnF,6DAA6D;IACzB,KAAK,EAAE,MAAM,CAAC;IAElD,sEAAsE;IAClC,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,CAAC,CAAC;IAE1F,QAAyB,KAAK,CAAS;IACvC,QAAyB,QAAQ,CAAqB;IACtD,QAAyB,OAAO,CAA4C;IAC5E,QAAyB,eAAe,CAAS;IACjD,QAAyB,WAAW,CAAS;IAC7C,QAAyB,aAAa,CAAS;IAC/C,QAAyB,QAAQ,CAAU;IAC3C,QAAyB,MAAM,CAAgB;IACtC,OAAO,CAAC,WAAW,CAAK;;IAmBxB,iBAAiB,IAAI,IAAI;IAKzB,oBAAoB,IAAI,IAAI;IAK5B,OAAO,CAAC,OAAO,EAAE,GAAG,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI;YAevC,WAAW;IAwBzB,wJAAwJ;IACxJ,OAAO,CAAC,+BAA+B;IAWvC,OAAO,CAAC,eAAe;IAMvB,OAAO,KAAK,QAAQ,GAGnB;IAED,OAAO,KAAK,WAAW,GAItB;IAED,OAAO,KAAK,OAAO,GAIlB;IAED,OAAO,KAAK,SAAS,GAIpB;IAED,OAAO,CAAC,MAAM;IAId,OAAO,CAAC,UAAU;IAIT,MAAM;CAgEhB;AAED,OAAO,CAAC,MAAM,CAAC;IACb,UAAU,qBAAqB;QAC7B,kBAAkB,EAAE,eAAe,CAAC;KACrC;CACF"}
@@ -34,11 +34,12 @@ let AnalyticsReport = class AnalyticsReport extends LitElement {
34
34
  padding: 0.5rem 1rem;
35
35
  border-bottom: 1px solid var(--analytics-report-border, #e2e8f0);
36
36
  background: var(--analytics-report-header-bg, #f8fafc);
37
+ color: var(--analytics-report-header-color, #1e293b);
37
38
  }
38
39
  .report-title {
39
40
  font-size: 1rem;
40
41
  font-weight: 600;
41
- color: var(--analytics-report-title-color, #1e293b);
42
+ color: var(--analytics-report-header-color, #1e293b);
42
43
  margin: 0;
43
44
  }
44
45
  .report-actions {
@@ -62,6 +63,29 @@ let AnalyticsReport = class AnalyticsReport extends LitElement {
62
63
  background: var(--analytics-report-btn-hover-bg, #f1f5f9);
63
64
  color: var(--analytics-report-btn-hover-color, #0f172a);
64
65
  }
66
+ .btn-refresh,
67
+ .report-actions button.btn-refresh {
68
+ display: inline-flex;
69
+ align-items: center;
70
+ justify-content: center;
71
+ width: 1.75rem;
72
+ height: 1.75rem;
73
+ padding: 0;
74
+ border: none;
75
+ border-radius: 4px;
76
+ background: transparent;
77
+ color: var(--analytics-report-header-color, #334155);
78
+ cursor: pointer;
79
+ transition: color 0.15s ease, background-color 0.15s ease;
80
+ }
81
+ .btn-refresh:hover {
82
+ color: var(--analytics-report-header-color, #0f172a);
83
+ background: var(--analytics-report-btn-hover-bg, #f1f5f9);
84
+ }
85
+ .btn-refresh svg {
86
+ width: 1rem;
87
+ height: 1rem;
88
+ }
65
89
  .report-filters {
66
90
  flex-shrink: 0;
67
91
  border-bottom: 1px solid var(--analytics-report-border, #e2e8f0);
@@ -103,6 +127,7 @@ let AnalyticsReport = class AnalyticsReport extends LitElement {
103
127
  `; }
104
128
  constructor() {
105
129
  super();
130
+ this._refreshKey = 0;
106
131
  this.reportId = '';
107
132
  this.apiUrl = '';
108
133
  this.customTitle = '';
@@ -213,6 +238,9 @@ let AnalyticsReport = class AnalyticsReport extends LitElement {
213
238
  _print() {
214
239
  window.open(this._previewUrl, '_blank', 'noopener')?.print();
215
240
  }
241
+ _onRefresh() {
242
+ this._refreshKey = Date.now();
243
+ }
216
244
  render() {
217
245
  if (this._loading) {
218
246
  return html `
@@ -234,6 +262,20 @@ let AnalyticsReport = class AnalyticsReport extends LitElement {
234
262
  <div class="report-header">
235
263
  <h1 class="report-title">${displayTitle}</h1>
236
264
  <div class="report-actions">
265
+ <button
266
+ type="button"
267
+ class="btn-refresh"
268
+ title="Refresh"
269
+ aria-label="Refresh data"
270
+ @click=${this._onRefresh}
271
+ >
272
+ <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">
273
+ <path d="M21 12a9 9 0 0 0-9-9 9.75 9.75 0 0 0-6.74 2.74L3 8" />
274
+ <path d="M3 3v5h5" />
275
+ <path d="M3 12a9 9 0 0 0 9 9 9.75 9.75 0 0 0 6.74-2.74L21 16" />
276
+ <path d="M16 21h5v-5" />
277
+ </svg>
278
+ </button>
237
279
  <button type="button" @click=${this._print}>Print</button>
238
280
  <a href=${this._pdfUrl} target="_blank" rel="noopener" download>Download PDF</a>
239
281
  <a href=${this._excelUrl} target="_blank" rel="noopener" download>Download Excel</a>
@@ -253,8 +295,9 @@ let AnalyticsReport = class AnalyticsReport extends LitElement {
253
295
  <div class="report-table-wrap">
254
296
  <analytics-table
255
297
  data-url=${this._dataUrl}
256
- .dataParams=${this._params}
298
+ .dataParams=${{ ...this._params, _refresh: this._refreshKey }}
257
299
  .title=${''}
300
+ hide-refresh-button
258
301
  ></analytics-table>
259
302
  </div>
260
303
  </div>
@@ -300,6 +343,9 @@ __decorate([
300
343
  __decorate([
301
344
  state()
302
345
  ], AnalyticsReport.prototype, "_error", void 0);
346
+ __decorate([
347
+ state()
348
+ ], AnalyticsReport.prototype, "_refreshKey", void 0);
303
349
  AnalyticsReport = __decorate([
304
350
  customElement('analytics-report')
305
351
  ], AnalyticsReport);
@@ -88,6 +88,7 @@ export declare abstract class BaseChartWidget extends LitElement {
88
88
  type?: string;
89
89
  }>, _widgetData?: unknown): EChartsOption;
90
90
  private _onWidgetFilterChange;
91
+ private _onRefresh;
91
92
  render(): import("lit-html").TemplateResult<1>;
92
93
  }
93
94
  //# sourceMappingURL=base-chart.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"base-chart.d.ts","sourceRoot":"","sources":["../../../../libs/analytics/src/widgets/base-chart.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"base-chart.d.ts","sourceRoot":"","sources":["../../../../libs/analytics/src/widgets/base-chart.ts"],"names":[],"mappings":"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"}
@@ -68,6 +68,7 @@ export class BaseChartWidget extends LitElement {
68
68
  min-height: 120px;
69
69
  display: flex;
70
70
  flex-direction: column;
71
+ --analytics-widget-toolbar-top: 2.5rem;
71
72
  }
72
73
  .widget-with-toolbar:hover analytics-widget-toolbar {
73
74
  opacity: 1;
@@ -77,12 +78,18 @@ export class BaseChartWidget extends LitElement {
77
78
  flex-shrink: 0;
78
79
  padding: 0.5rem 0.75rem 0.25rem 0.75rem;
79
80
  min-width: 0;
81
+ display: flex;
82
+ align-items: center;
83
+ justify-content: space-between;
84
+ gap: 0.5rem;
85
+ background: var(--analytics-widget-header-bg, #fff);
86
+ color: var(--analytics-widget-header-color, #374151);
80
87
  }
81
88
  .widget-title {
82
89
  margin: 0;
83
90
  font-size: 0.9375rem;
84
91
  font-weight: 600;
85
- color: #374151;
92
+ color: var(--analytics-widget-header-color, #374151);
86
93
  line-height: 1.3;
87
94
  display: -webkit-box;
88
95
  -webkit-box-orient: vertical;
@@ -100,6 +107,33 @@ export class BaseChartWidget extends LitElement {
100
107
  height: 100%;
101
108
  min-height: 100px;
102
109
  }
110
+ .btn-refresh {
111
+ flex-shrink: 0;
112
+ display: inline-flex;
113
+ align-items: center;
114
+ justify-content: center;
115
+ width: 1.75rem;
116
+ height: 1.75rem;
117
+ padding: 0;
118
+ border: none;
119
+ border-radius: 4px;
120
+ background: transparent;
121
+ color: var(--analytics-widget-header-color, #6b7280);
122
+ cursor: pointer;
123
+ transition: color 0.15s ease, background-color 0.15s ease;
124
+ }
125
+ .btn-refresh:hover {
126
+ color: var(--analytics-widget-header-color, #374151);
127
+ background: #f3f4f6;
128
+ }
129
+ .btn-refresh:disabled {
130
+ cursor: not-allowed;
131
+ opacity: 0.6;
132
+ }
133
+ .btn-refresh svg {
134
+ width: 1rem;
135
+ height: 1rem;
136
+ }
103
137
  `; }
104
138
  /** Delay (ms) after last resize event before calling chart.resize(). */
105
139
  static { this._RESIZE_DELAY_MS = 300; }
@@ -427,14 +461,44 @@ export class BaseChartWidget extends LitElement {
427
461
  _onWidgetFilterChange(e) {
428
462
  this._widgetFilterParams = { ...(e.detail?.params ?? {}) };
429
463
  }
464
+ _onRefresh() {
465
+ if (this._loading)
466
+ return;
467
+ this._loadData();
468
+ }
430
469
  render() {
431
470
  const hasWidgetFilters = this._widgetFilters.length > 0 && !this._hideFilter;
432
471
  const widgetActiveCount = Object.keys(this._widgetFilterParams).filter((k) => this._widgetFilterParams[k] !== '' && this._widgetFilterParams[k] != null).length;
472
+ const canRefresh = Boolean(this._getEffectiveDataUrl());
473
+ const headerContent = this._effectiveTitle || canRefresh
474
+ ? html `
475
+ <header class="widget-header">
476
+ ${this._effectiveTitle ? html `<h2 class="widget-title">${this._effectiveTitle}</h2>` : html `<span></span>`}
477
+ ${canRefresh
478
+ ? html `
479
+ <button
480
+ type="button"
481
+ class="btn-refresh"
482
+ title="Refresh"
483
+ aria-label="Refresh data"
484
+ ?disabled=${this._loading}
485
+ @click=${this._onRefresh}
486
+ >
487
+ <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">
488
+ <path d="M21 12a9 9 0 0 0-9-9 9.75 9.75 0 0 0-6.74 2.74L3 8" />
489
+ <path d="M3 3v5h5" />
490
+ <path d="M3 12a9 9 0 0 0 9 9 9.75 9.75 0 0 0 6.74-2.74L21 16" />
491
+ <path d="M16 21h5v-5" />
492
+ </svg>
493
+ </button>
494
+ `
495
+ : ''}
496
+ </header>
497
+ `
498
+ : '';
433
499
  return html `
434
500
  <div class="widget-with-toolbar">
435
- ${this._effectiveTitle
436
- ? html `<header class="widget-header"><h2 class="widget-title">${this._effectiveTitle}</h2></header>`
437
- : ''}
501
+ ${headerContent}
438
502
  <div class="widget-body">
439
503
  ${this._error
440
504
  ? html `<div class="error">${this._error}</div>`
@@ -12,6 +12,8 @@ export declare class TableWidget extends LitElement {
12
12
  static styles: import("lit").CSSResult;
13
13
  /** Optional title override. When unset, the widget uses the title from the API definition. */
14
14
  title: string;
15
+ /** When true, the header refresh button is hidden (e.g. when table is embedded in analytics-report which has its own refresh). */
16
+ hideRefreshButton: boolean;
15
17
  /** API URL to fetch data (e.g. /api/analytics/widgets/1/data). When widgetId + apiUrl are set, overridden by buildWidgetDataUrl(apiUrl, widgetId). */
16
18
  dataUrl: string;
17
19
  /** Widget id (used with apiUrl to build data URL: /widgets/{id}/data). */
@@ -59,6 +61,7 @@ export declare class TableWidget extends LitElement {
59
61
  private _viewportUnobserve;
60
62
  constructor();
61
63
  private _boundOnDashboardFilterChange;
64
+ private _onRefresh;
62
65
  private _boundOnDashboardRefresh;
63
66
  connectedCallback(): void;
64
67
  disconnectedCallback(): void;
@@ -1 +1 @@
1
- {"version":3,"file":"table.d.ts","sourceRoot":"","sources":["../../../../libs/analytics/src/widgets/table.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"table.d.ts","sourceRoot":"","sources":["../../../../libs/analytics/src/widgets/table.ts"],"names":[],"mappings":"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"}
package/widgets/table.js CHANGED
@@ -20,7 +20,6 @@ let TableWidget = class TableWidget extends LitElement {
20
20
  flex-direction: column;
21
21
  width: 100%;
22
22
  height: 100%;
23
- overflow: hidden;
24
23
  }
25
24
  table {
26
25
  width: 100%;
@@ -105,6 +104,33 @@ let TableWidget = class TableWidget extends LitElement {
105
104
  padding: 2rem 0.75rem;
106
105
  color: #9ca3af;
107
106
  }
107
+ .btn-refresh {
108
+ flex-shrink: 0;
109
+ display: inline-flex;
110
+ align-items: center;
111
+ justify-content: center;
112
+ width: 1.75rem;
113
+ height: 1.75rem;
114
+ padding: 0;
115
+ border: none;
116
+ border-radius: 4px;
117
+ background: transparent;
118
+ color: var(--analytics-widget-header-color, #6b7280);
119
+ cursor: pointer;
120
+ transition: color 0.15s ease, background-color 0.15s ease;
121
+ }
122
+ .btn-refresh:hover {
123
+ color: var(--analytics-widget-header-color, #374151);
124
+ background: #f3f4f6;
125
+ }
126
+ .btn-refresh:disabled {
127
+ cursor: not-allowed;
128
+ opacity: 0.6;
129
+ }
130
+ .btn-refresh svg {
131
+ width: 1rem;
132
+ height: 1rem;
133
+ }
108
134
  .widget-with-toolbar {
109
135
  position: relative;
110
136
  width: 100%;
@@ -112,6 +138,7 @@ let TableWidget = class TableWidget extends LitElement {
112
138
  display: flex;
113
139
  flex-direction: column;
114
140
  min-height: 0;
141
+ --analytics-widget-toolbar-top: 2.5rem;
115
142
  }
116
143
  .widget-with-toolbar:hover analytics-widget-toolbar {
117
144
  opacity: 1;
@@ -121,12 +148,18 @@ let TableWidget = class TableWidget extends LitElement {
121
148
  flex-shrink: 0;
122
149
  padding: 0.5rem 0.75rem 0.25rem 0.75rem;
123
150
  min-width: 0;
151
+ display: flex;
152
+ align-items: center;
153
+ justify-content: space-between;
154
+ gap: 0.5rem;
155
+ background: var(--analytics-widget-header-bg, #fff);
156
+ color: var(--analytics-widget-header-color, #374151);
124
157
  }
125
158
  .widget-title {
126
159
  margin: 0;
127
160
  font-size: 0.9375rem;
128
161
  font-weight: 600;
129
- color: #374151;
162
+ color: var(--analytics-widget-header-color, #374151);
130
163
  line-height: 1.3;
131
164
  display: -webkit-box;
132
165
  -webkit-box-orient: vertical;
@@ -184,6 +217,11 @@ let TableWidget = class TableWidget extends LitElement {
184
217
  this._viewportVisible = true;
185
218
  this._definitionTitle = '';
186
219
  }
220
+ _onRefresh() {
221
+ if (this._loading)
222
+ return;
223
+ this._loadData();
224
+ }
187
225
  connectedCallback() {
188
226
  super.connectedCallback();
189
227
  this._attachDashboard();
@@ -538,6 +576,33 @@ let TableWidget = class TableWidget extends LitElement {
538
576
  const wd = this._widgetData;
539
577
  const hasHeaderRows = Boolean(wd?.header_rows?.length);
540
578
  const tableFontSizeStyle = wd?.font_size ? `font-size: ${wd.font_size}` : nothing;
579
+ const canRefresh = Boolean(this._getEffectiveDataUrl()) && !this.hideRefreshButton;
580
+ const headerContent = this._effectiveTitle || canRefresh
581
+ ? html `
582
+ <header class="widget-header">
583
+ ${this._effectiveTitle ? html `<h2 class="widget-title">${this._effectiveTitle}</h2>` : html `<span></span>`}
584
+ ${canRefresh
585
+ ? html `
586
+ <button
587
+ type="button"
588
+ class="btn-refresh"
589
+ title="Refresh"
590
+ aria-label="Refresh data"
591
+ ?disabled=${this._loading}
592
+ @click=${this._onRefresh}
593
+ >
594
+ <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">
595
+ <path d="M21 12a9 9 0 0 0-9-9 9.75 9.75 0 0 0-6.74 2.74L3 8" />
596
+ <path d="M3 3v5h5" />
597
+ <path d="M3 12a9 9 0 0 0 9 9 9.75 9.75 0 0 0 6.74-2.74L21 16" />
598
+ <path d="M16 21h5v-5" />
599
+ </svg>
600
+ </button>
601
+ `
602
+ : ''}
603
+ </header>
604
+ `
605
+ : '';
541
606
  const filterToolbar = hasWidgetFilters
542
607
  ? html `
543
608
  <analytics-widget-toolbar
@@ -577,9 +642,7 @@ let TableWidget = class TableWidget extends LitElement {
577
642
  `;
578
643
  return html `
579
644
  <div class="widget-with-toolbar">
580
- ${this._effectiveTitle
581
- ? html `<header class="widget-header"><h2 class="widget-title">${this._effectiveTitle}</h2></header>`
582
- : ''}
645
+ ${headerContent}
583
646
  <div class="widget-body">
584
647
  ${bodyContent}
585
648
  ${this._loading
@@ -658,6 +721,9 @@ let TableWidget = class TableWidget extends LitElement {
658
721
  __decorate([
659
722
  property({ type: String })
660
723
  ], TableWidget.prototype, "title", void 0);
724
+ __decorate([
725
+ property({ type: Boolean, attribute: 'hide-refresh-button' })
726
+ ], TableWidget.prototype, "hideRefreshButton", void 0);
661
727
  __decorate([
662
728
  property({ type: String, attribute: 'data-url' })
663
729
  ], TableWidget.prototype, "dataUrl", void 0);