@uxland/primary-shell 5.6.4 → 5.6.6

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.
Files changed (17) hide show
  1. package/dist/index.js +142 -83
  2. package/dist/index.js.map +1 -1
  3. package/dist/index.umd.cjs +43 -30
  4. package/dist/index.umd.cjs.map +1 -1
  5. package/dist/primary/shell/src/internal-plugins/activity-history/activity-history-item/add/handle-busy/is-grouping-busy/component.d.ts +6 -0
  6. package/dist/primary/shell/src/internal-plugins/activity-history/activity-history-item/add/handle-busy/is-grouping-busy/template.d.ts +3 -0
  7. package/dist/primary/shell/src/internal-plugins/activity-history/localization.d.ts +5 -0
  8. package/package.json +1 -1
  9. package/src/internal-plugins/activity-history/activity-history-item/add/add-history-item/handler.ts +2 -2
  10. package/src/internal-plugins/activity-history/activity-history-item/add/add-history-items/handler.ts +2 -2
  11. package/src/internal-plugins/activity-history/activity-history-item/add/handle-busy/is-grouping-busy/component.ts +15 -0
  12. package/src/internal-plugins/activity-history/activity-history-item/add/handle-busy/is-grouping-busy/styles.css +8 -0
  13. package/src/internal-plugins/activity-history/activity-history-item/add/handle-busy/is-grouping-busy/template.ts +10 -0
  14. package/src/internal-plugins/activity-history/activity-history-item/list/UI/timeline/activity-history-timeline.ts +12 -5
  15. package/src/internal-plugins/activity-history/activity-history-item/list/UI/timeline/template.ts +20 -13
  16. package/src/internal-plugins/activity-history/activity-history-item/list/group-history-items/group-history-items.ts +69 -36
  17. package/src/internal-plugins/activity-history/localization.ts +5 -0
@@ -0,0 +1,6 @@
1
+ import { LitElement } from 'lit';
2
+
3
+ export declare class ActivityHistoryIsGroupingBusy extends LitElement {
4
+ static styles: import('lit').CSSResult;
5
+ render(): import('lit').TemplateResult<1>;
6
+ }
@@ -0,0 +1,3 @@
1
+ import { ActivityHistoryIsGroupingBusy } from './component';
2
+
3
+ export declare const template: (_props: ActivityHistoryIsGroupingBusy) => import('lit').TemplateResult<1>;
@@ -18,6 +18,11 @@ export declare const locales: {
18
18
  goToDate: string;
19
19
  busyEntriesLoading: string;
20
20
  noResults: string;
21
+ noData: {
22
+ title: string;
23
+ description: string;
24
+ };
25
+ isGrouping: string;
21
26
  searchBarResults: string;
22
27
  actions: {
23
28
  cronogram: string;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@uxland/primary-shell",
3
- "version": "5.6.4",
3
+ "version": "5.6.6",
4
4
  "description": "Primaria Shell",
5
5
  "author": "UXLand <dev@uxland.es>",
6
6
  "homepage": "https://github.com/uxland/harmonix/tree/app#readme",
@@ -9,14 +9,14 @@ export class AddHistoryItemHandler extends StoreBaseHandler {
9
9
  async handle(payload: AddHistoryItemPayload) {
10
10
  try {
11
11
  ensureAreValidBasicActivityHistoryItems([payload.item]);
12
+ handleAddDiagnosticsFilter([payload.item], this.store);
13
+ handleAddUpFilter([payload.item], this.store);
12
14
  this.store.dispatch(
13
15
  addActivityHistoryItem({
14
16
  id: payload.entityId,
15
17
  item: payload.item,
16
18
  }),
17
19
  );
18
- handleAddDiagnosticsFilter([payload.item], this.store);
19
- handleAddUpFilter([payload.item], this.store);
20
20
  } catch (e) {
21
21
  console.log(e.message);
22
22
  }
@@ -9,6 +9,8 @@ export class AddHistoryItemsHandler extends StoreBaseHandler {
9
9
  async handle(payload: AddHistoryItemsPayload) {
10
10
  try {
11
11
  const validItems = validateAndFilterBasicItems(payload.items);
12
+ handleAddDiagnosticsFilter(validItems, this.store);
13
+ handleAddUpFilter(validItems, this.store);
12
14
  this.store.dispatch(
13
15
  addActivityHistoryItems({
14
16
  id: payload.entityId,
@@ -17,8 +19,6 @@ export class AddHistoryItemsHandler extends StoreBaseHandler {
17
19
  searchPredicate: payload.searchPredicate,
18
20
  }),
19
21
  );
20
- handleAddDiagnosticsFilter(validItems, this.store);
21
- handleAddUpFilter(validItems, this.store);
22
22
  } catch (e) {
23
23
  console.log(e.message);
24
24
  }
@@ -0,0 +1,15 @@
1
+ import { LitElement, html, css, unsafeCSS } from "lit";
2
+ import { customElement } from "lit/decorators.js";
3
+ import styles from "./styles.css?inline";
4
+ import { template } from "./template";
5
+
6
+ @customElement("activity-history-is-grouping-busy")
7
+ export class ActivityHistoryIsGroupingBusy extends LitElement {
8
+ static styles = css`
9
+ ${unsafeCSS(styles)}
10
+ `;
11
+
12
+ render() {
13
+ return template(this);
14
+ }
15
+ }
@@ -0,0 +1,8 @@
1
+ .grouping-busy-container {
2
+ display: flex;
3
+ flex-direction: row;
4
+ align-items: center;
5
+ gap: 24px;
6
+ justify-content: center;
7
+ padding-top:16px
8
+ }
@@ -0,0 +1,10 @@
1
+ import { html } from "lit";
2
+ import { ActivityHistoryIsGroupingBusy } from "./component";
3
+ import { translate } from "../../../../localization";
4
+
5
+ export const template = (_props: ActivityHistoryIsGroupingBusy) => html`
6
+ <div class="grouping-busy-container">
7
+ <dss-spinner size="sm"></dss-spinner>
8
+ <div>${translate("isGrouping")}</div>
9
+ </div>
10
+ `;
@@ -1,5 +1,5 @@
1
1
  import { LitElement, PropertyValues, css, html, unsafeCSS } from "lit";
2
- import { customElement, query } from "lit/decorators.js";
2
+ import { customElement, query, state } from "lit/decorators.js";
3
3
  import { connectedProperty } from "../../../../infrastructure/state/connected-property";
4
4
  import { IActivityHistoryGroup } from "../../../domain/model";
5
5
  import { activityHistorySearchStringSelector } from "../../../search/selectors";
@@ -52,11 +52,18 @@ export class ActivityHistoryTimeline extends LitElement {
52
52
 
53
53
  @query(".virtualizer") private _virtualizer!: HTMLElement;
54
54
 
55
- _hasUpdatedOnce = false;
55
+ @state()
56
+ renderGroupsControlTimeExpired = false;
56
57
 
57
- firstUpdated(_changeProps: PropertyValues) {
58
- super.firstUpdated(_changeProps);
59
- this._hasUpdatedOnce = true;
58
+ connectedCallback(): void {
59
+ super.connectedCallback();
60
+ setTimeout(() => {
61
+ this.renderGroupsControlTimeExpired = true;
62
+ }, 8000);
63
+ }
64
+
65
+ disconnectedCallback(): void {
66
+ super.disconnectedCallback();
60
67
  }
61
68
 
62
69
  async updated(changedProperties) {
@@ -9,7 +9,6 @@ import {
9
9
  IActivityHistoryGroup,
10
10
  IActivityHistoryItem,
11
11
  IActivityHistoryItemWithComponent,
12
- IActivityHistorySubGroup,
13
12
  } from "../../../domain/model";
14
13
  import { translate } from "../../../../localization";
15
14
  import { hasItemDivider, shouldShowRole } from "../../../domain/business-rules";
@@ -17,11 +16,9 @@ import {
17
16
  ActivityHistoryEntry,
18
17
  mergeHistoryItemsAndSubgroups,
19
18
  } from "../../merge-history-items-and-subgroups/merge-history-items-and-subgroups";
19
+ import "../../../add/handle-busy/is-grouping-busy/component";
20
20
 
21
21
  export const template = (props: ActivityHistoryTimeline) => {
22
- if (!props._hasUpdatedOnce) {
23
- return html`<div class="container"></div>`;
24
- }
25
22
  return html`
26
23
  <div class="container">
27
24
  <activity-history-full-data-error></activity-history-full-data-error>
@@ -78,20 +75,30 @@ export const template = (props: ActivityHistoryTimeline) => {
78
75
  `}
79
76
  ></lit-virtualizer>
80
77
  `
81
- : !props.isCollectionInitialState && !props.isSomeCollectionLoadedAndOtherLoading
82
- ? html`
83
- <dss-user-feedback
84
- class="feedback"
85
- imagesrc=${notFound}
86
- title=${translate("noResults")}>
87
- </dss-user-feedback>
88
- `
89
- : nothing
78
+ : noGroupsTemplate(props)
90
79
  }
91
80
  </div>
92
81
  `;
93
82
  };
94
83
 
84
+ const noGroupsTemplate = (props: ActivityHistoryTimeline)=> html `
85
+ ${props.searchString?.length > 1
86
+ ? html`
87
+ <dss-user-feedback
88
+ class="feedback"
89
+ imagesrc=${notFound}
90
+ title=${translate("noResults")}>
91
+ </dss-user-feedback>
92
+ `
93
+ : props.renderGroupsControlTimeExpired
94
+ ? html`<dss-user-feedback
95
+ class="feedback"
96
+ imagesrc=${notFound}
97
+ title=${translate("noData.title")}
98
+ description=${translate("noData.description")}>
99
+ </dss-user-feedback>`
100
+ : html`<activity-history-is-grouping-busy></activity-history-is-grouping-busy>`}`;
101
+
95
102
  const visitHeaderTemplate = (props: ActivityHistoryTimeline, item: IActivityHistoryItem | undefined) => {
96
103
  if (!item) return nothing;
97
104
  return html`
@@ -2,25 +2,37 @@ import { IActivityHistoryItem, IActivityHistoryGroup, IActivityHistorySubGroup }
2
2
  import { areSameDiagnostics } from "../../domain/validation/diagnostics/are-same-diagnostics";
3
3
  import { hasValidDiagnostics } from "../../domain/validation/diagnostics/has-valid-diagnostics";
4
4
 
5
- const isSameVisit = (item1: IActivityHistoryItem, item2: IActivityHistoryItem): boolean => {
6
- const sameProfessional =
7
- item1.professional?.id === item2.professional?.id &&
8
- item1.professional?.role?.id === item2.professional?.role?.id &&
9
- item1.professional?.speciality?.id === item2.professional?.speciality?.id;
10
- const sameLocation =
11
- item1.ep?.id === item2.ep?.id &&
12
- item1.up?.id === item2.up?.id &&
13
- item1.center?.id === item2.center?.id &&
14
- item1.service?.id === item2.service?.id;
15
-
16
- const sameDay = new Date(item1.date).toDateString() === new Date(item2.date).toDateString();
17
-
18
- return sameProfessional && sameLocation && sameDay;
5
+ // Cache para evitar recalcular fechas
6
+ const dateStringCache = new Map<string, string>();
7
+ const dateObjectCache = new Map<string, Date>();
8
+
9
+ const getDateString = (dateStr: string): string => {
10
+ if (!dateStringCache.has(dateStr)) {
11
+ dateStringCache.set(dateStr, new Date(dateStr).toDateString());
12
+ }
13
+ return dateStringCache.get(dateStr)!;
14
+ };
15
+
16
+ const getDateObject = (dateStr: string): Date => {
17
+ if (!dateObjectCache.has(dateStr)) {
18
+ dateObjectCache.set(dateStr, new Date(dateStr));
19
+ }
20
+ return dateObjectCache.get(dateStr)!;
21
+ };
22
+
23
+ // Crear una clave única para cada combinación de visita
24
+ const createVisitKey = (item: IActivityHistoryItem): string => {
25
+ const professionalKey = `${item.professional?.id || 'null'}-${item.professional?.role?.id || 'null'}-${item.professional?.speciality?.id || 'null'}`;
26
+ const locationKey = `${item.ep?.id || 'null'}-${item.up?.id || 'null'}-${item.center?.id || 'null'}-${item.service?.id || 'null'}`;
27
+ const dayKey = getDateString(item.date);
28
+
29
+ return `${professionalKey}|${locationKey}|${dayKey}`;
19
30
  };
20
31
 
21
32
  const withinEightHours = (date1: string, date2: string): boolean => {
22
- const timeDifference = Math.abs(new Date(date1).getTime() - new Date(date2).getTime());
23
- return timeDifference <= 8 * 60 * 60 * 1000; // 8 hours in milliseconds
33
+ const time1 = getDateObject(date1).getTime();
34
+ const time2 = getDateObject(date2).getTime();
35
+ return Math.abs(time1 - time2) <= 8 * 60 * 60 * 1000; // 8 hours in milliseconds
24
36
  };
25
37
 
26
38
  function groupByValidDiagnostics(groups: IActivityHistoryGroup[]) {
@@ -30,12 +42,12 @@ function groupByValidDiagnostics(groups: IActivityHistoryGroup[]) {
30
42
 
31
43
  group.items.forEach((item) => {
32
44
  const diagnostics = item.diagnostics;
33
-
34
45
  const allDiagnosticsValid = diagnostics?.length > 0 && hasValidDiagnostics(diagnostics);
35
46
 
36
47
  if (allDiagnosticsValid) {
37
48
  let addedToSubGroup = false;
38
49
 
50
+ // Optimización: usar for...of con break para salir temprano
39
51
  for (const subGroup of subGroups) {
40
52
  const firstSubGroupItem = subGroup.items[0];
41
53
 
@@ -63,38 +75,59 @@ function groupByValidDiagnostics(groups: IActivityHistoryGroup[]) {
63
75
  }
64
76
 
65
77
  const groupActivityHistoryItems = (items: IActivityHistoryItem[]): IActivityHistoryGroup[] => {
66
- const groups: IActivityHistoryGroup[] = [];
78
+ if (!items?.length) return [];
67
79
 
68
- items?.forEach((item) => {
69
- let added = false;
80
+ // Limpiar caches al inicio
81
+ dateStringCache.clear();
82
+ dateObjectCache.clear();
70
83
 
71
- for (const group of groups) {
72
- const firstItem = group.items[0];
73
- const lastItem = group.items[group.items.length - 1];
84
+ // Mapa para agrupar por clave de visita
85
+ const visitGroups = new Map<string, IActivityHistoryGroup>();
86
+
87
+ items.forEach((item) => {
88
+ const visitKey = createVisitKey(item);
89
+
90
+ if (!visitGroups.has(visitKey)) {
91
+ // Crear nuevo grupo
92
+ visitGroups.set(visitKey, {
93
+ idGroup: Math.random().toString(36).substr(2, 9),
94
+ items: [item],
95
+ });
96
+ } else {
97
+ // Verificar si está dentro del rango de 8 horas
98
+ const existingGroup = visitGroups.get(visitKey)!;
99
+ const firstItem = existingGroup.items[0];
100
+ const lastItem = existingGroup.items[existingGroup.items.length - 1];
74
101
 
75
102
  if (
76
- isSameVisit(firstItem, item) &&
77
103
  withinEightHours(firstItem.date, item.date) &&
78
104
  withinEightHours(lastItem.date, item.date)
79
105
  ) {
80
- group.items.push(item);
81
- added = true;
82
- break;
106
+ existingGroup.items.push(item);
107
+ } else {
108
+ // Si no está dentro del rango, crear un nuevo grupo con un sufijo
109
+ let counter = 1;
110
+ let newKey = `${visitKey}_${counter}`;
111
+
112
+ while (visitGroups.has(newKey)) {
113
+ counter++;
114
+ newKey = `${visitKey}_${counter}`;
115
+ }
116
+
117
+ visitGroups.set(newKey, {
118
+ idGroup: Math.random().toString(36).substr(2, 9),
119
+ items: [item],
120
+ });
83
121
  }
84
122
  }
85
-
86
- if (!added) {
87
- groups.push({
88
- idGroup: Math.random().toString(36).substr(2, 9),
89
- items: [item],
90
- });
91
- }
92
123
  });
93
124
 
94
- // Crear subgrupos por diagnósticos iguales. Los items que no tienen diagnostico, se quedan fuera de subgrupos (remaining items)
125
+ const groups = Array.from(visitGroups.values());
126
+
127
+ // Crear subgrupos por diagnósticos iguales
95
128
  groupByValidDiagnostics(groups);
96
129
 
97
130
  return groups;
98
131
  };
99
132
 
100
- export { groupActivityHistoryItems };
133
+ export { groupActivityHistoryItems };
@@ -32,6 +32,11 @@ export const locales = {
32
32
  goToDate: "Anar a data",
33
33
  busyEntriesLoading: "Carregant totes les entrades",
34
34
  noResults: "Sense resultats. Modifica la cerca",
35
+ noData: {
36
+ title: "Sense dades",
37
+ description: "No existeix informació per a mostrar"
38
+ },
39
+ isGrouping: "Creant agrupacions i preparant les dades...",
35
40
  searchBarResults: "Resultats per",
36
41
  actions: {
37
42
  cronogram: "Cronograma",