@gisce/react-ooui 1.2.0-rc.7 → 1.2.0-rc.71

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 (133) hide show
  1. package/dist/actionbar/FormActionBar.d.ts.map +1 -1
  2. package/dist/actionbar/TreeActionBar.d.ts.map +1 -1
  3. package/dist/common/DatePicker.d.ts +12 -0
  4. package/dist/common/DatePicker.d.ts.map +1 -1
  5. package/dist/context/ActionViewContext.d.ts +5 -1
  6. package/dist/context/ActionViewContext.d.ts.map +1 -1
  7. package/dist/context/ContentRootContext.d.ts.map +1 -1
  8. package/dist/context/FormContext.d.ts +4 -2
  9. package/dist/context/FormContext.d.ts.map +1 -1
  10. package/dist/helpers/formHelper.d.ts +5 -3
  11. package/dist/helpers/formHelper.d.ts.map +1 -1
  12. package/dist/helpers/iconMapper.d.ts +5 -1
  13. package/dist/helpers/iconMapper.d.ts.map +1 -1
  14. package/dist/helpers/one2manyHelper.d.ts +12 -4
  15. package/dist/helpers/one2manyHelper.d.ts.map +1 -1
  16. package/dist/helpers/searchHelper.d.ts +1 -1
  17. package/dist/helpers/searchHelper.d.ts.map +1 -1
  18. package/dist/helpers/treeHelper.d.ts +1 -1
  19. package/dist/helpers/treeHelper.d.ts.map +1 -1
  20. package/dist/hooks/useExport.d.ts +44 -0
  21. package/dist/hooks/useExport.d.ts.map +1 -0
  22. package/dist/index.d.ts +2 -1
  23. package/dist/index.d.ts.map +1 -1
  24. package/dist/locales/ca_ES.d.ts +2 -0
  25. package/dist/locales/ca_ES.d.ts.map +1 -1
  26. package/dist/locales/en_US.d.ts +2 -0
  27. package/dist/locales/en_US.d.ts.map +1 -1
  28. package/dist/locales/es_ES.d.ts +2 -0
  29. package/dist/locales/es_ES.d.ts.map +1 -1
  30. package/dist/react-ooui.es.js +25403 -27411
  31. package/dist/react-ooui.es.js.map +1 -1
  32. package/dist/react-ooui.umd.js +46 -184
  33. package/dist/react-ooui.umd.js.map +1 -1
  34. package/dist/types/index.d.ts +1 -0
  35. package/dist/types/index.d.ts.map +1 -1
  36. package/dist/views/RootView.d.ts.map +1 -1
  37. package/dist/views/actionViews/GraphActionView.d.ts.map +1 -1
  38. package/dist/views/actionViews/TreeActionView.d.ts.map +1 -1
  39. package/dist/widgets/WidgetFactory.d.ts.map +1 -1
  40. package/dist/widgets/base/Integer.d.ts.map +1 -1
  41. package/dist/widgets/base/Label.d.ts.map +1 -1
  42. package/dist/widgets/base/Reference.d.ts.map +1 -1
  43. package/dist/widgets/base/ReferenceTree.d.ts +8 -0
  44. package/dist/widgets/base/ReferenceTree.d.ts.map +1 -0
  45. package/dist/widgets/base/Separator.d.ts.map +1 -1
  46. package/dist/widgets/base/many2one/Many2one.d.ts.map +1 -1
  47. package/dist/widgets/base/many2one/Many2oneTree.d.ts +6 -0
  48. package/dist/widgets/base/many2one/Many2oneTree.d.ts.map +1 -0
  49. package/dist/widgets/base/one2many/One2manyInput.d.ts.map +1 -1
  50. package/dist/widgets/containers/Group.d.ts.map +1 -1
  51. package/dist/widgets/custom/MultiCheckbox.d.ts.map +1 -1
  52. package/dist/widgets/custom/Tag.d.ts +5 -0
  53. package/dist/widgets/custom/Tag.d.ts.map +1 -0
  54. package/dist/widgets/custom/Tags.d.ts.map +1 -1
  55. package/dist/widgets/custom/Timeline.d.ts.map +1 -1
  56. package/dist/widgets/modals/ExportModal.d.ts +2 -1
  57. package/dist/widgets/modals/ExportModal.d.ts.map +1 -1
  58. package/dist/widgets/views/Dashboard/Dashboard.d.ts.map +1 -1
  59. package/dist/widgets/views/Dashboard/DashboardTree.d.ts.map +1 -1
  60. package/dist/widgets/views/Form.d.ts.map +1 -1
  61. package/dist/widgets/views/Graph/GraphChart.d.ts.map +1 -1
  62. package/dist/widgets/views/Graph/GraphDefaults.d.ts +36 -0
  63. package/dist/widgets/views/Graph/GraphDefaults.d.ts.map +1 -1
  64. package/dist/widgets/views/SearchTree.d.ts.map +1 -1
  65. package/dist/widgets/views/Tree.d.ts +2 -0
  66. package/dist/widgets/views/Tree.d.ts.map +1 -1
  67. package/dist/widgets/views/searchFilter/SearchFilter.d.ts +1 -0
  68. package/dist/widgets/views/searchFilter/SearchFilter.d.ts.map +1 -1
  69. package/package.json +8 -7
  70. package/src/__tests__/iconMapper.test.ts +20 -5
  71. package/src/actionbar/ChangeViewButton.tsx +2 -2
  72. package/src/actionbar/FormActionBar.tsx +82 -11
  73. package/src/actionbar/TreeActionBar.tsx +23 -28
  74. package/src/common/DatePicker.tsx +4 -3
  75. package/src/context/ActionViewContext.tsx +7 -4
  76. package/src/context/ContentRootContext.tsx +15 -7
  77. package/src/context/FormContext.tsx +1 -4
  78. package/src/helpers/formHelper.ts +26 -5
  79. package/src/helpers/iconMapper.ts +134 -107
  80. package/src/helpers/one2manyHelper.ts +94 -39
  81. package/src/helpers/searchHelper.ts +8 -7
  82. package/src/helpers/treeHelper.ts +17 -5
  83. package/src/hooks/useExport.ts +439 -0
  84. package/src/index.ts +2 -0
  85. package/src/locales/ca_ES.tsx +2 -0
  86. package/src/locales/en_US.tsx +2 -0
  87. package/src/locales/es_ES.tsx +2 -0
  88. package/src/stories/Label.stories.tsx +7 -8
  89. package/src/stories/Separator.stories.tsx +33 -0
  90. package/src/stories/containers/Group.stories.tsx +24 -0
  91. package/src/stories/containers/Notebook.stories.tsx +27 -0
  92. package/src/stories/custom/Tag.stories.tsx +57 -0
  93. package/src/stories/mocks/models/crm_case.ts +7 -10
  94. package/src/stories/views/Tree.stories.jsx +5 -5
  95. package/src/types/index.ts +1 -0
  96. package/src/ui/FavouriteButton.tsx +4 -4
  97. package/src/views/RootView.tsx +7 -1
  98. package/src/views/actionViews/GraphActionView.tsx +1 -0
  99. package/src/views/actionViews/TreeActionView.tsx +10 -1
  100. package/src/widgets/WidgetFactory.tsx +3 -0
  101. package/src/widgets/base/Integer.tsx +1 -0
  102. package/src/widgets/base/Label.tsx +5 -9
  103. package/src/widgets/base/Reference.tsx +13 -3
  104. package/src/widgets/base/ReferenceTree.tsx +62 -0
  105. package/src/widgets/base/Separator.tsx +11 -3
  106. package/src/widgets/base/many2one/Many2one.tsx +10 -19
  107. package/src/widgets/base/many2one/Many2oneTree.tsx +18 -0
  108. package/src/widgets/base/one2many/One2manyInput.tsx +79 -23
  109. package/src/widgets/containers/Group.tsx +7 -4
  110. package/src/widgets/custom/ButtonGroup.tsx +1 -1
  111. package/src/widgets/custom/MultiCheckbox.tsx +1 -0
  112. package/src/widgets/custom/Tag.tsx +24 -0
  113. package/src/widgets/custom/Tags.tsx +27 -28
  114. package/src/widgets/custom/Timeline.tsx +9 -3
  115. package/src/widgets/modals/ExportModal.tsx +33 -134
  116. package/src/widgets/views/Dashboard/Dashboard.tsx +15 -4
  117. package/src/widgets/views/Dashboard/DashboardTree.tsx +1 -0
  118. package/src/widgets/views/Form.tsx +38 -31
  119. package/src/widgets/views/Graph/GraphChart.tsx +6 -1
  120. package/src/widgets/views/Graph/GraphDefaults.ts +113 -0
  121. package/src/widgets/views/Graph/GraphIndicator.tsx +17 -3
  122. package/src/widgets/views/SearchTree.tsx +3 -0
  123. package/src/widgets/views/Tree.tsx +111 -25
  124. package/src/widgets/views/searchFilter/SearchFilter.tsx +12 -6
  125. package/dist/helpers/icons/antd_icons.d.ts +0 -4
  126. package/dist/helpers/icons/antd_icons.d.ts.map +0 -1
  127. package/dist/helpers/icons/tabler_icons.d.ts +0 -4
  128. package/dist/helpers/icons/tabler_icons.d.ts.map +0 -1
  129. package/dist/ui/Fieldset.d.ts +0 -8
  130. package/dist/ui/Fieldset.d.ts.map +0 -1
  131. package/src/helpers/icons/antd_icons.ts +0 -1583
  132. package/src/helpers/icons/tabler_icons.ts +0 -5367
  133. package/src/ui/Fieldset.tsx +0 -31
@@ -3,22 +3,20 @@ import {
3
3
  ExportModal as ExportModalFmg,
4
4
  Locale,
5
5
  } from "@gisce/react-formiga-components";
6
- import { ExportOptions } from "@gisce/react-formiga-components/dist/components/other/ExportModal/ExportModal.types";
7
- import React, { useCallback, useRef } from "react";
8
- import showInfo from "@/ui/InfoDialog";
9
- import { tForLang } from "@/context/LocaleContext";
10
- import { getMimeType, openBase64InNewTab } from "@/helpers/filesHelper";
6
+ import React from "react";
7
+ import { useExport } from "@/hooks/useExport";
11
8
 
12
9
  export type ExportModalProps = {
13
10
  visible: boolean;
14
11
  locale: string;
15
12
  onClose: () => void;
16
- selectedRegistersToExport?: number;
13
+ selectedRegistersToExport?: any[];
17
14
  totalRegisters: number;
18
15
  model: string;
19
16
  domain: any[];
20
17
  limit?: number;
21
18
  context?: any;
19
+ visibleRegisters: number;
22
20
  };
23
21
 
24
22
  export const ExportModal = (props: ExportModalProps) => {
@@ -32,145 +30,46 @@ export const ExportModal = (props: ExportModalProps) => {
32
30
  totalRegisters,
33
31
  domain,
34
32
  limit,
33
+ visibleRegisters,
35
34
  } = props;
36
- const fields = useRef<any>({});
37
35
 
38
- const onSucceed = useCallback(
39
- async (options: ExportOptions) => {
40
- if (options.selectedKeys.length === 0) {
41
- showInfo(tForLang("selectAtLeastOneField", locale));
42
- return;
43
- }
44
-
45
- const { datas } = await ConnectionProvider.getHandler().exportData({
46
- model,
47
- fields: options.selectedKeys,
48
- domain: options.registersAmount === "all" ? [] : domain,
49
- limit: options.registersAmount === "all" ? undefined : limit,
50
- context,
51
- format: options.exportType,
52
- });
53
-
54
- onClose();
55
-
56
- await new Promise((resolve) => setTimeout(resolve, 200));
57
-
58
- const fileType: any = await getMimeType(datas);
59
- openBase64InNewTab(datas, fileType.mime);
60
- },
61
- [locale, model, domain, limit, context, onClose]
62
- );
63
-
64
- const onGetFields = useCallback(async () => {
65
- const viewData = await ConnectionProvider.getHandler().getFields({
66
- model,
67
- context,
68
- fields: [],
69
- });
70
- fields.current["/"] = viewData;
71
- return convertToExportField({ fields: viewData });
72
- }, [model, context, fields]);
73
-
74
- const onGetFieldChilds = useCallback(
75
- async ({ key, title }: any) => {
76
- let fieldDefinition;
77
-
78
- const sanitizedKey =
79
- key.split("/")[key.split("/").length - 1] === "id"
80
- ? key.split("/").slice(0, -1).join("/")
81
- : key;
82
-
83
- if (sanitizedKey.indexOf("/") === -1) {
84
- fieldDefinition = fields.current["/"];
85
- } else {
86
- fieldDefinition = fields.current[getParentKey(sanitizedKey)];
87
- }
88
-
89
- const optsForField = fieldDefinition[getChildKey(sanitizedKey)];
90
- const relation = optsForField.relation;
91
- const viewData = await ConnectionProvider.getHandler().getFields({
92
- model: relation,
93
- context,
94
- fields: [],
95
- });
96
-
97
- fields.current[sanitizedKey] = viewData;
98
-
99
- return convertToExportField({
100
- fields: viewData,
101
- parentTitle: title,
102
- parentKey: sanitizedKey,
103
- });
104
- },
105
- [fields, model, context]
106
- );
36
+ const {
37
+ onExport,
38
+ onGetFieldChilds,
39
+ onGetFields,
40
+ onGetPredefinedExports,
41
+ onSavePredefinedExport,
42
+ onRemovePredefinedExport,
43
+ } = useExport({
44
+ model,
45
+ context,
46
+ domain,
47
+ limit,
48
+ selectedRegistersToExport,
49
+ onClose,
50
+ locale,
51
+ });
107
52
 
108
53
  return (
109
54
  <ExportModalFmg
110
55
  visible={visible}
111
56
  locale={locale as Locale}
112
- onSucceed={onSucceed}
57
+ onSucceed={onExport}
113
58
  onCancel={onClose}
114
- selectedRegistersToExport={selectedRegistersToExport}
59
+ selectedRegistersToExport={
60
+ selectedRegistersToExport &&
61
+ selectedRegistersToExport.length &&
62
+ selectedRegistersToExport.length > 0
63
+ ? selectedRegistersToExport.length
64
+ : undefined
65
+ }
115
66
  totalRegisters={totalRegisters}
116
67
  onGetFieldChilds={onGetFieldChilds}
117
68
  onGetFields={onGetFields}
69
+ visibleRegisters={visibleRegisters}
70
+ onGetPredefinedExports={onGetPredefinedExports}
71
+ onSavePredefinedExport={onSavePredefinedExport}
72
+ onRemovePredefinedExport={onRemovePredefinedExport}
118
73
  />
119
74
  );
120
75
  };
121
-
122
- const convertToExportField = ({
123
- fields,
124
- parentKey,
125
- parentTitle,
126
- }: {
127
- fields: any;
128
- parentTitle?: string;
129
- parentKey?: string;
130
- }) => {
131
- const exportFields = [];
132
-
133
- for (const key of Object.keys(fields)) {
134
- const valuesForField = fields[key];
135
-
136
- if (valuesForField.relation && valuesForField.is_function === true) {
137
- continue;
138
- }
139
-
140
- const relationField =
141
- valuesForField.type === "many2one" ||
142
- valuesForField.type === "one2many" ||
143
- valuesForField.type === "many2many";
144
-
145
- let newKey = `${parentKey ? parentKey + "/" : ""}${key}`;
146
-
147
- if (relationField) {
148
- newKey += "/id";
149
- }
150
-
151
- exportFields.push({
152
- key: newKey,
153
- title: `${parentTitle ? parentTitle + "/" : ""}${valuesForField.string}`,
154
- tooltip: valuesForField.help,
155
- required: valuesForField.required,
156
- isLeaf: !relationField,
157
- });
158
- }
159
- return exportFields;
160
- };
161
-
162
- const getParentKey = (key: string) => {
163
- if (key.indexOf("/") === -1) {
164
- return key;
165
- }
166
- const items = key.split("/");
167
- return items.slice(0, -1).join("/");
168
- };
169
-
170
- const getChildKey = (key: string) => {
171
- if (key.indexOf("/") === -1) {
172
- return key;
173
- }
174
- const items = key.split("/");
175
- return items[items.length - 1];
176
- };
@@ -105,13 +105,19 @@ function Dashboard(props: DashboardProps, ref: any) {
105
105
  })) as FormView
106
106
  ).fields;
107
107
 
108
- return await readObjectValues({
109
- treeFields: itemsFields.current,
110
- formFields: itemsFields.current,
108
+ const [results] = await readObjectValues({
109
+ treeView: {
110
+ fields: itemsFields.current,
111
+ },
112
+ formView: {
113
+ fields: itemsFields.current,
114
+ },
111
115
  model,
112
116
  items,
113
117
  context,
118
+ currentView: "form",
114
119
  });
120
+ return results;
115
121
  }
116
122
 
117
123
  async function fetchValues(view: FormView) {
@@ -214,6 +220,7 @@ function Dashboard(props: DashboardProps, ref: any) {
214
220
  }
215
221
 
216
222
  if (error) {
223
+ console.log(error);
217
224
  return (
218
225
  <Alert className="mt-10 mb-20" message={error} type="error" banner />
219
226
  );
@@ -308,6 +315,10 @@ function Dashboard(props: DashboardProps, ref: any) {
308
315
  />
309
316
  );
310
317
  } else if (initialView !== undefined) {
318
+ const formattedInitialView =
319
+ initialView && Array.isArray(initialView.id)
320
+ ? { ...initialView, id: initialView.id[0] }
321
+ : initialView;
311
322
  childContent = (
312
323
  <ActionView
313
324
  action_id={actionId}
@@ -319,7 +330,7 @@ function Dashboard(props: DashboardProps, ref: any) {
319
330
  context={context}
320
331
  domain={domain}
321
332
  setCanWeClose={() => {}}
322
- initialView={initialView}
333
+ initialView={formattedInitialView}
323
334
  limit={limit}
324
335
  />
325
336
  );
@@ -219,6 +219,7 @@ function DashboardTree(props: Props) {
219
219
  });
220
220
  setResults(sortedResults);
221
221
  }}
222
+ context={parentContext}
222
223
  />
223
224
  </div>
224
225
  );
@@ -15,6 +15,7 @@ import {
15
15
  Row,
16
16
  Alert,
17
17
  Spin,
18
+ message,
18
19
  } from "antd";
19
20
  import Measure from "react-measure";
20
21
  import { CheckOutlined, CloseOutlined } from "@ant-design/icons";
@@ -54,6 +55,7 @@ import {
54
55
  ContentRootContextType,
55
56
  } from "@/context/ContentRootContext";
56
57
  import { LocaleContext, LocaleContextType } from "@/context/LocaleContext";
58
+ import { convertToPlain2ManyValues } from "@/helpers/one2manyHelper";
57
59
 
58
60
  export type FormProps = {
59
61
  model: string;
@@ -105,7 +107,7 @@ function Form(props: FormProps, ref: any) {
105
107
  defaultValues,
106
108
  forcedValues = {},
107
109
  } = props;
108
- const { lang } = useContext(LocaleContext) as LocaleContextType;
110
+ const { t, lang } = useContext(LocaleContext) as LocaleContextType;
109
111
 
110
112
  const [isSubmitting, setIsSubmitting] = useState<boolean>(false);
111
113
  const [error, setError] = useState<string>();
@@ -126,7 +128,8 @@ function Form(props: FormProps, ref: any) {
126
128
  const responsiveBehaviour = containerWidth < WIDTH_BREAKPOINT;
127
129
 
128
130
  const formContext = useContext(FormContext) as FormContextType;
129
- const { activeId: parentId } = formContext || {};
131
+ const { activeId: parentId, getPlainValues: getParentPlainValues } =
132
+ formContext || {};
130
133
 
131
134
  const actionViewContext = useContext(
132
135
  ActionViewContext
@@ -137,6 +140,8 @@ function Form(props: FormProps, ref: any) {
137
140
  setCurrentId = undefined,
138
141
  setFormIsLoading = undefined,
139
142
  setAttachments = undefined,
143
+ title = undefined,
144
+ setTitle = undefined,
140
145
  } = (rootForm ? actionViewContext : {}) || {};
141
146
 
142
147
  const contentRootContext = useContext(
@@ -342,6 +347,7 @@ function Form(props: FormProps, ref: any) {
342
347
  await antForm.validateFields();
343
348
  return false;
344
349
  } catch (verror) {
350
+ message.error(t("fillRequiredFields"));
345
351
  return true;
346
352
  }
347
353
  }
@@ -398,13 +404,11 @@ function Form(props: FormProps, ref: any) {
398
404
  if (valuesProps) {
399
405
  values = valuesProps;
400
406
  } else {
401
- ({
402
- values,
403
- defaultGetCalled: hasDefaultGetCalled,
404
- } = await fetchValuesFromApi({
405
- fields: _fields,
406
- arch: _arch!,
407
- }));
407
+ ({ values, defaultGetCalled: hasDefaultGetCalled } =
408
+ await fetchValuesFromApi({
409
+ fields: _fields,
410
+ arch: _arch!,
411
+ }));
408
412
  }
409
413
 
410
414
  if (actionDomain) {
@@ -428,11 +432,6 @@ function Form(props: FormProps, ref: any) {
428
432
  }
429
433
  };
430
434
 
431
- function setOriginalValue(field: string, value: any) {
432
- originalFormValues.current[field] = value;
433
- setFormHasChanges?.(formHasChanges());
434
- }
435
-
436
435
  const cancelUnsavedChanges = async () => {
437
436
  return new Promise(async (resolve) => {
438
437
  if (formHasChanges()) {
@@ -455,15 +454,13 @@ function Form(props: FormProps, ref: any) {
455
454
 
456
455
  const getFormView = async (): Promise<FormView> => {
457
456
  if (getDataFromAction) {
458
- const action = await ConnectionProvider.getHandler().getActionStringForModel(
459
- model
460
- );
461
- const viewsForAction = await ConnectionProvider.getHandler().getViewsForAction(
462
- {
457
+ const action =
458
+ await ConnectionProvider.getHandler().getActionStringForModel(model);
459
+ const viewsForAction =
460
+ await ConnectionProvider.getHandler().getViewsForAction({
463
461
  action,
464
462
  context: parentContext,
465
- }
466
- );
463
+ });
467
464
  return viewsForAction.views.get("form");
468
465
  }
469
466
 
@@ -609,13 +606,13 @@ function Form(props: FormProps, ref: any) {
609
606
  formSubmitting.current = false;
610
607
  setFormHasChanges?.(false);
611
608
  onCancel?.();
612
- return true;
609
+ return { succeed: true, id: getCurrentId()! };
613
610
  }
614
611
 
615
612
  if (await checkIfFormHasErrors()) {
616
613
  formSubmitting.current = false;
617
614
  formErrorsDialog(lang);
618
- return false;
615
+ return { succeed: false, id: getCurrentId()! };
619
616
  }
620
617
 
621
618
  setIsSubmitting(true);
@@ -640,6 +637,7 @@ function Form(props: FormProps, ref: any) {
640
637
  setIsSubmitting(false);
641
638
  setFormIsSaving?.(false);
642
639
  onSubmitError?.(err);
640
+ message.error(t("errorWhileSavingForm"));
643
641
  setError(err?.message ? err.message : err);
644
642
  } finally {
645
643
  formSubmitting.current = false;
@@ -647,7 +645,7 @@ function Form(props: FormProps, ref: any) {
647
645
  setIsSubmitting(false);
648
646
  }
649
647
 
650
- return submitSucceed;
648
+ return { succeed: submitSucceed, id: getCurrentId()! };
651
649
  };
652
650
 
653
651
  const parseForm = ({
@@ -663,13 +661,20 @@ function Form(props: FormProps, ref: any) {
663
661
  // TODO: Here we must inject `values` to the ooui parser in order to evaluate arch+values and get the new form container
664
662
  ooui.parse(arch, {
665
663
  readOnly,
666
- values: {
667
- ...values,
668
- ...getAdditionalValues(),
669
- },
664
+ values: convertToPlain2ManyValues(
665
+ {
666
+ ...values,
667
+ ...getAdditionalValues(),
668
+ },
669
+ fields
670
+ ),
670
671
  });
671
672
  setFormOoui(ooui);
672
673
 
674
+ if (ooui.string && ooui.string !== title) {
675
+ setTitle?.(ooui.string);
676
+ }
677
+
673
678
  if (formModalContext && ooui.string)
674
679
  formModalContext.setTitle?.(ooui.string);
675
680
  };
@@ -695,7 +700,7 @@ function Form(props: FormProps, ref: any) {
695
700
  if (
696
701
  checkFieldsType({
697
702
  changedFields,
698
- fields,
703
+ formOoui: formOoui!,
699
704
  types: [
700
705
  "text",
701
706
  "codeeditor",
@@ -756,6 +761,7 @@ function Form(props: FormProps, ref: any) {
756
761
  ...formOoui?.context,
757
762
  },
758
763
  },
764
+ parentValues: getParentPlainValues?.(),
759
765
  onChangeFieldActionArgs: onChangeFieldAction.args,
760
766
  });
761
767
 
@@ -943,7 +949,9 @@ function Form(props: FormProps, ref: any) {
943
949
  }
944
950
 
945
951
  try {
946
- await submitForm({ callOnSubmitSucceed: false });
952
+ if (formHasChanges() || getCurrentId() === undefined) {
953
+ await submitForm({ callOnSubmitSucceed: false });
954
+ }
947
955
 
948
956
  if (type === "object") {
949
957
  await runObjectButton({ action, context });
@@ -983,7 +991,6 @@ function Form(props: FormProps, ref: any) {
983
991
  getFieldValue={getFieldValue}
984
992
  executeButtonAction={executeButtonAction}
985
993
  getContext={getContext}
986
- setOriginalValue={setOriginalValue}
987
994
  submitForm={submitForm}
988
995
  fetchValues={fetchValues}
989
996
  formHasChanges={formHasChanges}
@@ -57,7 +57,12 @@ export const GraphChart = (props: GraphChartProps) => {
57
57
  return (
58
58
  <div style={{ padding: "1rem" }}>
59
59
  <p style={{ textAlign: "right" }}>
60
- {`${t("totalRegisters")} ${evaluatedEntries?.length}`}
60
+ {`${t("totalRegisters")} ${evaluatedEntries?.length?.toLocaleString(
61
+ "es-ES",
62
+ {
63
+ useGrouping: true,
64
+ }
65
+ )}`}
61
66
  </p>
62
67
  <Chart
63
68
  {...getGraphProps({
@@ -1,13 +1,67 @@
1
+ import moment from "moment";
2
+
3
+ const formatter = (graphType: "pie" | "default" | "barGrouped") => {
4
+ return (object: any) => {
5
+ const formattedValue = object.value.toLocaleString("es-ES", {
6
+ useGrouping: true,
7
+ });
8
+ const name = graphType === "pie" ? object.x : object.type;
9
+ return { name, value: formattedValue };
10
+ };
11
+ };
12
+
13
+ const axisFormatter = (value: any) => {
14
+ if (typeof value === "string" && stringIsValidNumeric(value)) {
15
+ return parseFloat(value).toLocaleString("es-ES", {
16
+ useGrouping: true,
17
+ });
18
+ } else if (isNumber(value)) {
19
+ return value.toLocaleString("es-ES", {
20
+ useGrouping: true,
21
+ });
22
+ } else if (isValidDateString(value)) {
23
+ const dateType = getDateType(value);
24
+ if (dateType === null) {
25
+ return value;
26
+ }
27
+ return moment(value, (dateFormats.input as any)[dateType]).format(
28
+ (dateFormats.output as any)[dateType]
29
+ );
30
+ } else {
31
+ return value;
32
+ }
33
+ };
34
+
35
+ const stringIsValidNumeric = (value: string) => {
36
+ const regex = /^[-+]?[0-9]*\.?[0-9]+([eE][-+]?[0-9]+)?$/;
37
+ return regex.test(value);
38
+ };
39
+
40
+ const isNumber = (value: any) => {
41
+ return typeof value === "number" && !isNaN(value);
42
+ };
43
+
1
44
  const DefaultGraphOptions = {
2
45
  default: {
3
46
  padding: "auto",
4
47
  xAxis: {
5
48
  tickCount: 5,
49
+ label: {
50
+ formatter: axisFormatter,
51
+ },
52
+ },
53
+ yAxis: {
54
+ label: {
55
+ formatter: axisFormatter,
56
+ },
6
57
  },
7
58
  legend: {
8
59
  maxWidthRatio: 0.5,
9
60
  maxItemWidth: 1000,
10
61
  },
62
+ tooltip: {
63
+ formatter: formatter("default"),
64
+ },
11
65
  },
12
66
  pie: {
13
67
  appendPadding: 10,
@@ -25,6 +79,9 @@ const DefaultGraphOptions = {
25
79
  maxWidthRatio: 0.5,
26
80
  maxItemWidth: 1000,
27
81
  },
82
+ tooltip: {
83
+ formatter: formatter("pie"),
84
+ },
28
85
  interactions: [
29
86
  {
30
87
  type: "element-active",
@@ -37,6 +94,19 @@ const DefaultGraphOptions = {
37
94
  maxWidthRatio: 0.5,
38
95
  maxItemWidth: 1000,
39
96
  },
97
+ tooltip: {
98
+ formatter: formatter("barGrouped"),
99
+ },
100
+ xAxis: {
101
+ label: {
102
+ formatter: axisFormatter,
103
+ },
104
+ },
105
+ yAxis: {
106
+ label: {
107
+ formatter: axisFormatter,
108
+ },
109
+ },
40
110
  label: {
41
111
  position: "middle",
42
112
  layout: [
@@ -54,4 +124,47 @@ const DefaultGraphOptions = {
54
124
  },
55
125
  };
56
126
 
127
+ function isValidDateString(variable: any): boolean {
128
+ // Check if the variable is defined and is a string
129
+ if (typeof variable !== "string" || variable === undefined) {
130
+ return false;
131
+ }
132
+
133
+ // Check if the string is a valid date
134
+ const date = new Date(variable);
135
+ return date.toString() !== "Invalid Date";
136
+ }
137
+
138
+ const dateFormats = {
139
+ input: {
140
+ hours: "YYYY-MM-DD HH:mm",
141
+ days: "YYYY-MM-DD",
142
+ weeks: "YYYY-[W]WW",
143
+ months: "YYYY-MM",
144
+ years: "YYYY",
145
+ },
146
+ output: {
147
+ hours: "DD/MM/YYYY HH:mm",
148
+ days: "DD/MM/YYYY",
149
+ weeks: "[W]WW/YYYY",
150
+ months: "MM/YYYY",
151
+ years: "YYYY",
152
+ },
153
+ };
154
+
155
+ function getDateType(dateString: string): string | null {
156
+ for (const format in dateFormats.input) {
157
+ const isValidFormat = moment(
158
+ dateString,
159
+ (dateFormats.input as any)[format],
160
+ true
161
+ ).isValid();
162
+ if (isValidFormat) {
163
+ return format;
164
+ }
165
+ }
166
+
167
+ return null;
168
+ }
169
+
57
170
  export default DefaultGraphOptions;
@@ -273,7 +273,11 @@ function CommonIndicator({
273
273
  ? minFontSize
274
274
  : height * fontGrowFactor;
275
275
 
276
- let finalValue = total ? `${value}/${total}` : `${value}`;
276
+ const localeValue = value?.toLocaleString("es-ES", {
277
+ useGrouping: true,
278
+ });
279
+
280
+ let finalValue = total ? `${localeValue}/${total}` : `${localeValue}`;
277
281
 
278
282
  if (suffix) {
279
283
  finalValue += " " + suffix;
@@ -342,13 +346,23 @@ function PercentageIndicator({
342
346
  ? minFontSize
343
347
  : twoLinesHeight * fontGrowFactor;
344
348
 
345
- let finalValue = total ? `${value}/${total}` : `${value}`;
349
+ const localeValue = value?.toLocaleString("es-ES", {
350
+ useGrouping: true,
351
+ });
352
+
353
+ let finalValue = total
354
+ ? `${localeValue}/${total?.toLocaleString("es-ES", {
355
+ useGrouping: true,
356
+ })}`
357
+ : `${localeValue}`;
346
358
 
347
359
  if (suffix) {
348
360
  finalValue += " " + suffix;
349
361
  }
350
362
 
351
- const percentValue = `${percent}%`;
363
+ const percentValue = `${percent?.toLocaleString("es-ES", {
364
+ useGrouping: true,
365
+ })}%`;
352
366
 
353
367
  let tw = getTextWidth(
354
368
  percentValue,
@@ -295,6 +295,7 @@ function SearchTree(props: Props, ref: any) {
295
295
  formView.search_fields,
296
296
  treeView.search_fields,
297
297
  ])}
298
+ formXml={formView.arch}
298
299
  onClear={clear}
299
300
  limit={limit}
300
301
  offset={offset}
@@ -307,6 +308,7 @@ function SearchTree(props: Props, ref: any) {
307
308
  searchValues={searchValues}
308
309
  />
309
310
  <Tree
311
+ context={parentContext}
310
312
  total={totalItems}
311
313
  limit={limit}
312
314
  page={page}
@@ -327,6 +329,7 @@ function SearchTree(props: Props, ref: any) {
327
329
  treeView.isExpandable ? fetchChildrenForRecord : undefined
328
330
  }
329
331
  childField={treeView.field_parent}
332
+ rootTree={rootTree}
330
333
  />
331
334
  </>
332
335
  );