@apia/dashboard-controller 4.0.89 → 4.0.92

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/dist/index.d.ts CHANGED
@@ -1,9 +1,9 @@
1
1
  import * as _apia_util from '@apia/util';
2
- import { TId, EventEmitter } from '@apia/util';
2
+ import { TId, EventEmitter, TasksQueue } from '@apia/util';
3
3
  import * as react from 'react';
4
4
  import { ReactNode, FC, KeyboardEvent, MouseEvent as MouseEvent$1, ComponentType, ReactPortal } from 'react';
5
- import { TApiaApiResult, IApiaApiRequestConfig } from '@apia/api';
6
5
  import { TSpacingLayout } from '@apia/theme';
6
+ import { TApiaApiResult, IApiaApiRequestConfig } from '@apia/api';
7
7
  import * as _reduxjs_toolkit_dist_configureStore from '@reduxjs/toolkit/dist/configureStore';
8
8
  import * as redux_thunk from 'redux-thunk';
9
9
  import * as redux from 'redux';
@@ -73,6 +73,92 @@ interface TPanelIdentifierProps {
73
73
  }
74
74
  declare const PanelIdentifier: ({ children, name, id, title, type, }: TPanelIdentifierProps) => react.JSX.Element;
75
75
 
76
+ type TPanelLayout = TSpacingLayout;
77
+
78
+ /**
79
+ * **Favor de leer con cuidado el siguiente contenido, es muy importante para
80
+ * la performance**
81
+ *
82
+ * El hook useYieldPanelIsReady es una parte muy importante del flujo de
83
+ * trabajo de los dashboards. **El no reportar la carga de un panel tiene
84
+ * penalizaciones graves en el tiempo de renderizado inicial**, esto es porque
85
+ * el dashboard espera que todos los paneles hayan terminado la carga
86
+ * estructural básica antes de empezar con los refresh iniciales, y esto termina
87
+ * impactando en el tiempo que demora en bajar la cortina.
88
+ *
89
+ * **Aclaración:** Actualmente se espera las cargas estructurales para lanzar
90
+ * los refresh iniciales por motivos de arquitectura. Esa restricción será
91
+ * eliminada probablemente en el corto plazo, pero eso no cambia la necesidad de
92
+ * reportar las estructuras ya que esta información es igualmente utilizada para
93
+ * el bajado de la cortina de Skeletons.
94
+ *
95
+ * Por ejemplo, si todos los paneles están optimizados para lograr cargas
96
+ * iniciales rápidas pero el logo de la aplicación no reporta que su estructura
97
+ * está pronta, el dashboard va a bajar su cortina solamente luego de que expire
98
+ * el timeout **DASH_COURTAIN_TRESHOLD**, que por defecto viene establecido en 5
99
+ * segundos.
100
+ *
101
+ * Esto significa que aún cuando la cortina se hubiera podido bajar quizás a
102
+ * los pocos ms de cargado el html inicial, no lo hará porque supone que el
103
+ * panel Logo aún no terminó su carga estructural.
104
+ *
105
+ * Siempre que un panel esté presente en un dashboard, deberá reportar cuando
106
+ * la carga estructural esté pronta. Esto puede ser hecho de dos formas:
107
+ *
108
+ * - Usando { setRef } = usePanelContext(): En el elemento crucial de HTML del
109
+ * elemento hacer ref={setRef}. Esta es la forma más óptima ya que nos garantiza
110
+ * que el panel se reporte cuando su estructura HTML ya esté disponible,
111
+ * evitando ninguna demora.
112
+ *
113
+ * - Usando useYieldPanelIsReady(): Este hook es una alternativa disponible
114
+ * para las situaciones en las que no tenemos ningún elemento HTML de
115
+ * importancia o cuando ese elemento no está disponible hasta después de la
116
+ * carga inicial. Al usar este hook el panel se reportará automáticamente una
117
+ * vez que haya hecho el renderizado inicial.
118
+ */
119
+ declare function useYieldPanelIsReady(): void;
120
+
121
+ type TPanelContext = {
122
+ /**
123
+ * Permite establecer contenido arbitrario en el footer del panel.
124
+ */
125
+ setFooterContent(content: ReactNode): void;
126
+ /**
127
+ * setLayout es una función que permite decidir en qué formato se muestran
128
+ * los contenidos del panel.
129
+ *
130
+ * dense: No hay paddings
131
+ * clever: Hay paddings grandes
132
+ */
133
+ setLayout: (newLayout: TPanelLayout) => void;
134
+ setTitle: (newTitle: string) => void;
135
+ panelProps: Omit<TPanelProps$1, 'children'>;
136
+ /**
137
+ * Cuando un panel renderiza sus hijos en pantalla, debe setear el ref de
138
+ * modo que se pueda continuar con el flujo normal del panel. Este ref puede
139
+ * estar en cualquier nivel, cuando sea instanciado, se llamará al refresh
140
+ * inicial.
141
+ */
142
+ setRef: (el: HTMLElement | null) => void;
143
+ };
144
+ declare function usePanelContext(): TPanelContext;
145
+ declare const PanelContextProvider: ({ children, value, }: {
146
+ children: ReactNode;
147
+ value: TPanelContext;
148
+ }) => react.JSX.Element;
149
+ declare function useMakePanelContext(panelProps: Omit<TPanelProps$1, 'children'>): {
150
+ footerContent: ReactNode;
151
+ title: string;
152
+ footer: TFooter | null;
153
+ handleFooterClick: (ev: react.MouseEvent | react.KeyboardEvent) => void;
154
+ contextValue: TPanelContext;
155
+ ref: (el: HTMLDivElement) => void;
156
+ };
157
+
158
+ declare const EmptyPanelWrapper: PanelContainer;
159
+
160
+ type TOnSucceed = (hasSucceed: boolean, data: TActionResult) => unknown;
161
+
76
162
  declare const eventsController: {
77
163
  callbacks: TPanelEventRegister<any>[];
78
164
  broadcast(eventType: string, payload: any): void;
@@ -110,8 +196,6 @@ type TBasicAction = {
110
196
  };
111
197
  declare function handleAction(panelIdentifier: TPanelIdentifier, event: KeyboardEvent | MouseEvent$1, action: TBasicAction): void;
112
198
 
113
- type TOnSucceed = (hasSucceed: boolean, data: TActionResult) => unknown;
114
-
115
199
  type TFooter = TBasicAction & {
116
200
  force?: boolean;
117
201
  };
@@ -171,6 +255,12 @@ type TActionHandler = (result: TActionResult) => unknown;
171
255
  */
172
256
  declare function usePanelActions(actionsHandler?: Record<string, TActionHandler>): TActionDispatcher;
173
257
 
258
+ type TUsePanelFooter = {
259
+ footerContent?: ReactNode;
260
+ footer: TFooter | null;
261
+ handleFooterClick: (ev: MouseEvent$1 | KeyboardEvent) => void;
262
+ };
263
+
174
264
  declare const externalFirePanelAction: TExternalActionDispatcher;
175
265
 
176
266
  declare function usePanelIsLoading(): boolean;
@@ -187,96 +277,6 @@ declare const useActionEventHandlers: () => {
187
277
  onKeyDown: (ev: React.KeyboardEvent<HTMLElement>) => (action: TBasicAction) => void;
188
278
  };
189
279
 
190
- type TPanelLayout = TSpacingLayout;
191
-
192
- /**
193
- * **Favor de leer con cuidado el siguiente contenido, es muy importante para
194
- * la performance**
195
- *
196
- * El hook useYieldPanelIsReady es una parte muy importante del flujo de
197
- * trabajo de los dashboards. **El no reportar la carga de un panel tiene
198
- * penalizaciones graves en el tiempo de renderizado inicial**, esto es porque
199
- * el dashboard espera que todos los paneles hayan terminado la carga
200
- * estructural básica antes de empezar con los refresh iniciales, y esto termina
201
- * impactando en el tiempo que demora en bajar la cortina.
202
- *
203
- * **Aclaración:** Actualmente se espera las cargas estructurales para lanzar
204
- * los refresh iniciales por motivos de arquitectura. Esa restricción será
205
- * eliminada probablemente en el corto plazo, pero eso no cambia la necesidad de
206
- * reportar las estructuras ya que esta información es igualmente utilizada para
207
- * el bajado de la cortina de Skeletons.
208
- *
209
- * Por ejemplo, si todos los paneles están optimizados para lograr cargas
210
- * iniciales rápidas pero el logo de la aplicación no reporta que su estructura
211
- * está pronta, el dashboard va a bajar su cortina solamente luego de que expire
212
- * el timeout **DASH_COURTAIN_TRESHOLD**, que por defecto viene establecido en 5
213
- * segundos.
214
- *
215
- * Esto significa que aún cuando la cortina se hubiera podido bajar quizás a
216
- * los pocos ms de cargado el html inicial, no lo hará porque supone que el
217
- * panel Logo aún no terminó su carga estructural.
218
- *
219
- * Siempre que un panel esté presente en un dashboard, deberá reportar cuando
220
- * la carga estructural esté pronta. Esto puede ser hecho de dos formas:
221
- *
222
- * - Usando { setRef } = usePanelContext(): En el elemento crucial de HTML del
223
- * elemento hacer ref={setRef}. Esta es la forma más óptima ya que nos garantiza
224
- * que el panel se reporte cuando su estructura HTML ya esté disponible,
225
- * evitando ninguna demora.
226
- *
227
- * - Usando useYieldPanelIsReady(): Este hook es una alternativa disponible
228
- * para las situaciones en las que no tenemos ningún elemento HTML de
229
- * importancia o cuando ese elemento no está disponible hasta después de la
230
- * carga inicial. Al usar este hook el panel se reportará automáticamente una
231
- * vez que haya hecho el renderizado inicial.
232
- */
233
- declare function useYieldPanelIsReady(): void;
234
-
235
- type TPanelContext = {
236
- /**
237
- * Permite establecer contenido arbitrario en el footer del panel.
238
- */
239
- setFooterContent(content: ReactNode): void;
240
- /**
241
- * setLayout es una función que permite decidir en qué formato se muestran
242
- * los contenidos del panel.
243
- *
244
- * dense: No hay paddings
245
- * clever: Hay paddings grandes
246
- */
247
- setLayout: (newLayout: TPanelLayout) => void;
248
- setTitle: (newTitle: string) => void;
249
- panelProps: Omit<TPanelProps$1, 'children'>;
250
- /**
251
- * Cuando un panel renderiza sus hijos en pantalla, debe setear el ref de
252
- * modo que se pueda continuar con el flujo normal del panel. Este ref puede
253
- * estar en cualquier nivel, cuando sea instanciado, se llamará al refresh
254
- * inicial.
255
- */
256
- setRef: (el: HTMLElement | null) => void;
257
- };
258
- declare function usePanelContext(): TPanelContext;
259
- declare const PanelContextProvider: ({ children, value, }: {
260
- children: ReactNode;
261
- value: TPanelContext;
262
- }) => react.JSX.Element;
263
- declare function useMakePanelContext(panelProps: Omit<TPanelProps$1, 'children'>): {
264
- footerContent: ReactNode;
265
- title: string;
266
- footer: TFooter | null;
267
- handleFooterClick: (ev: react.MouseEvent | react.KeyboardEvent) => void;
268
- contextValue: TPanelContext;
269
- ref: (el: HTMLDivElement) => void;
270
- };
271
-
272
- declare const EmptyPanelWrapper: PanelContainer;
273
-
274
- type TUsePanelFooter = {
275
- footerContent?: ReactNode;
276
- footer: TFooter | null;
277
- handleFooterClick: (ev: MouseEvent$1 | KeyboardEvent) => void;
278
- };
279
-
280
280
  /**
281
281
  * Permite acceder a la identidad del panel actual.
282
282
  */
@@ -364,6 +364,7 @@ declare class DashboardPanel extends EventEmitter<{
364
364
  isCollapsed: boolean;
365
365
  portal: ReactPortal;
366
366
  props: TPanelProps;
367
+ tasksQueue: TasksQueue;
367
368
  constructor({ id, dashboard, PanelContainer, }: {
368
369
  id: string;
369
370
  dashboard: Dashboard;
@@ -376,7 +377,8 @@ declare class DashboardPanel extends EventEmitter<{
376
377
  getContainer(): HTMLElement;
377
378
  getParameters(): TParamsStore;
378
379
  hide(): void;
379
- refresh(): Promise<TActionResult>;
380
+ refresh(): Promise<TActionResult | undefined>;
381
+ queuedRefresh(): Promise<TActionResult | undefined>;
380
382
  setHasLoaded(): void;
381
383
  show(): void;
382
384
  PanelElement: ({ ActualPanelContainer, Element, }: {
@@ -418,6 +420,7 @@ declare class Dashboard extends EventEmitter<{
418
420
  urlContext: string;
419
421
  bootstrapper: DashboardPanelsBootstraper;
420
422
  panels: Record<string, DashboardPanel> | null;
423
+ queueRefresh: boolean;
421
424
  router: Router;
422
425
  scenes: Record<string, string[]>;
423
426
  getPanel: (id: string) => DashboardPanel;
package/dist/index.js CHANGED
@@ -1,5 +1,5 @@
1
1
  import { ApiaApi, makeApiaUrl } from '@apia/api';
2
- import { EventEmitter, useMount, useImperativeComponentEvents, getLabel, makeImperativeComponent, toBoolean, parseXmlAsync, isChild, getSpecificParent, ucfirst, downloadUrl, useLatest } from '@apia/util';
2
+ import { EventEmitter, useMount, useImperativeComponentEvents, getLabel, makeImperativeComponent, TasksQueue, toBoolean, parseXmlAsync, isChild, getSpecificParent, ucfirst, downloadUrl, useLatest } from '@apia/util';
3
3
  import { createContext, useMemo, useContext, useState, useEffect, useCallback, useRef, useDeferredValue, Suspense, lazy, Component, startTransition } from 'react';
4
4
  import { jsx, jsxs, Fragment } from '@apia/theme/jsx-runtime';
5
5
  import { Icon } from '@apia/icons';
@@ -494,7 +494,6 @@ function useMakePanelContext(panelProps) {
494
494
  );
495
495
  const { footer, handleFooterClick } = usePanelFooter(panelProps);
496
496
  const [footerContent, setFooterContent] = useState(null);
497
- const dispatch = usePanelActions();
498
497
  const hasRefreshedOnStartup = useRef(false);
499
498
  const dashboard = useDashboardContext();
500
499
  const setRef = useCallback(
@@ -502,7 +501,7 @@ function useMakePanelContext(panelProps) {
502
501
  if (el && !hasRefreshedOnStartup.current) {
503
502
  hasRefreshedOnStartup.current = true;
504
503
  if (panelProps.refreshOnStart) {
505
- void dispatch({ action: "refresh" }).then(() => {
504
+ dashboard.getPanel(panelProps.id).refresh().then(() => {
506
505
  dashboard.bootstrapper.setPanelHasLoaded(identifier.panelId);
507
506
  });
508
507
  } else {
@@ -510,12 +509,7 @@ function useMakePanelContext(panelProps) {
510
509
  }
511
510
  }
512
511
  },
513
- [
514
- dashboard.bootstrapper,
515
- dispatch,
516
- identifier.panelId,
517
- panelProps.refreshOnStart
518
- ]
512
+ [dashboard, identifier.panelId, panelProps.id, panelProps.refreshOnStart]
519
513
  );
520
514
  const contextValue = useMemo(
521
515
  () => ({ setFooterContent, setTitle, setLayout, panelProps, setRef }),
@@ -941,6 +935,7 @@ class DashboardPanel extends EventEmitter {
941
935
  __publicField$3(this, "isCollapsed", false);
942
936
  __publicField$3(this, "portal");
943
937
  __publicField$3(this, "props", {});
938
+ __publicField$3(this, "tasksQueue", new TasksQueue());
944
939
  __privateAdd$3(this, _elements, {
945
940
  props: () => {
946
941
  const panelData = document.querySelector(
@@ -1119,7 +1114,16 @@ class DashboardPanel extends EventEmitter {
1119
1114
  this.emit("isVisible", this.isVisible);
1120
1115
  }
1121
1116
  refresh() {
1122
- return this.fireAction({ action: "refresh" });
1117
+ if (this.dashboard.queueRefresh) {
1118
+ return this.queuedRefresh();
1119
+ } else {
1120
+ return this.fireAction({ action: "refresh" });
1121
+ }
1122
+ }
1123
+ queuedRefresh() {
1124
+ return this.tasksQueue.run(async () => {
1125
+ return await this.fireAction({ action: "refresh" });
1126
+ });
1123
1127
  }
1124
1128
  setHasLoaded() {
1125
1129
  this.hasLoaded = true;
@@ -1748,6 +1752,8 @@ class Dashboard extends EventEmitter {
1748
1752
  this.urlContext = urlContext;
1749
1753
  __publicField(this, "bootstrapper", new DashboardPanelsBootstraper(this));
1750
1754
  __publicField(this, "panels", null);
1755
+ __publicField(this, "queueRefresh", true);
1756
+ //TODO: Crear parametro del dashboard
1751
1757
  __publicField(this, "router", new Router());
1752
1758
  __publicField(this, "scenes", {});
1753
1759
  __privateAdd(this, _currentScene, "/");