@gisce/react-ooui 1.2.0-rc.4 → 1.2.0-rc.41

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 (105) 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/context/ActionViewContext.d.ts +5 -1
  4. package/dist/context/ActionViewContext.d.ts.map +1 -1
  5. package/dist/context/ContentRootContext.d.ts.map +1 -1
  6. package/dist/context/FormContext.d.ts +4 -1
  7. package/dist/context/FormContext.d.ts.map +1 -1
  8. package/dist/helpers/formHelper.d.ts +5 -3
  9. package/dist/helpers/formHelper.d.ts.map +1 -1
  10. package/dist/helpers/iconMapper.d.ts +5 -1
  11. package/dist/helpers/iconMapper.d.ts.map +1 -1
  12. package/dist/helpers/one2manyHelper.d.ts +2 -1
  13. package/dist/helpers/one2manyHelper.d.ts.map +1 -1
  14. package/dist/helpers/treeHelper.d.ts +1 -1
  15. package/dist/helpers/treeHelper.d.ts.map +1 -1
  16. package/dist/index.d.ts +2 -1
  17. package/dist/index.d.ts.map +1 -1
  18. package/dist/locales/ca_ES.d.ts +4 -0
  19. package/dist/locales/ca_ES.d.ts.map +1 -1
  20. package/dist/locales/en_US.d.ts +4 -0
  21. package/dist/locales/en_US.d.ts.map +1 -1
  22. package/dist/locales/es_ES.d.ts +4 -0
  23. package/dist/locales/es_ES.d.ts.map +1 -1
  24. package/dist/react-ooui.es.js +16980 -18378
  25. package/dist/react-ooui.es.js.map +1 -1
  26. package/dist/react-ooui.umd.js +78 -51
  27. package/dist/react-ooui.umd.js.map +1 -1
  28. package/dist/types/index.d.ts +1 -0
  29. package/dist/types/index.d.ts.map +1 -1
  30. package/dist/views/ActionView.d.ts.map +1 -1
  31. package/dist/views/RootView.d.ts.map +1 -1
  32. package/dist/views/actionViews/TreeActionView.d.ts.map +1 -1
  33. package/dist/widgets/WidgetFactory.d.ts.map +1 -1
  34. package/dist/widgets/base/Integer.d.ts.map +1 -1
  35. package/dist/widgets/base/Label.d.ts.map +1 -1
  36. package/dist/widgets/base/ReferenceTree.d.ts +8 -0
  37. package/dist/widgets/base/ReferenceTree.d.ts.map +1 -0
  38. package/dist/widgets/base/many2one/Many2one.d.ts.map +1 -1
  39. package/dist/widgets/base/many2one/Many2oneTree.d.ts +6 -0
  40. package/dist/widgets/base/many2one/Many2oneTree.d.ts.map +1 -0
  41. package/dist/widgets/base/one2many/One2manyInput.d.ts.map +1 -1
  42. package/dist/widgets/custom/MultiCheckbox.d.ts.map +1 -1
  43. package/dist/widgets/custom/Tag.d.ts +5 -0
  44. package/dist/widgets/custom/Tag.d.ts.map +1 -0
  45. package/dist/widgets/custom/Tags.d.ts.map +1 -1
  46. package/dist/widgets/modals/ExportModal.d.ts +2 -2
  47. package/dist/widgets/modals/ExportModal.d.ts.map +1 -1
  48. package/dist/widgets/views/Dashboard/Dashboard.d.ts.map +1 -1
  49. package/dist/widgets/views/Dashboard/DashboardTree.d.ts.map +1 -1
  50. package/dist/widgets/views/Form.d.ts.map +1 -1
  51. package/dist/widgets/views/SearchTree.d.ts.map +1 -1
  52. package/dist/widgets/views/Tree.d.ts +2 -0
  53. package/dist/widgets/views/Tree.d.ts.map +1 -1
  54. package/package.json +6 -5
  55. package/src/__tests__/iconMapper.test.ts +20 -5
  56. package/src/actionbar/ChangeViewButton.tsx +2 -2
  57. package/src/actionbar/FormActionBar.tsx +94 -11
  58. package/src/actionbar/TreeActionBar.tsx +86 -69
  59. package/src/context/ActionViewContext.tsx +7 -4
  60. package/src/context/ContentRootContext.tsx +15 -7
  61. package/src/context/FormContext.tsx +1 -1
  62. package/src/helpers/formHelper.ts +26 -5
  63. package/src/helpers/iconMapper.ts +134 -107
  64. package/src/helpers/one2manyHelper.ts +27 -9
  65. package/src/helpers/treeHelper.ts +17 -5
  66. package/src/index.ts +2 -0
  67. package/src/locales/ca_ES.tsx +4 -0
  68. package/src/locales/en_US.tsx +4 -0
  69. package/src/locales/es_ES.tsx +4 -0
  70. package/src/stories/Label.stories.tsx +7 -8
  71. package/src/stories/containers/Notebook.stories.tsx +27 -0
  72. package/src/stories/custom/Tag.stories.tsx +57 -0
  73. package/src/stories/mocks/models/crm_case.ts +7 -10
  74. package/src/stories/views/Tree.stories.jsx +5 -5
  75. package/src/types/index.ts +1 -0
  76. package/src/views/ActionView.tsx +15 -4
  77. package/src/views/RootView.tsx +7 -1
  78. package/src/views/actionViews/TreeActionView.tsx +10 -1
  79. package/src/widgets/WidgetFactory.tsx +3 -0
  80. package/src/widgets/base/Integer.tsx +1 -0
  81. package/src/widgets/base/Label.tsx +5 -9
  82. package/src/widgets/base/ReferenceTree.tsx +62 -0
  83. package/src/widgets/base/many2one/Many2one.tsx +8 -9
  84. package/src/widgets/base/many2one/Many2oneTree.tsx +18 -0
  85. package/src/widgets/base/one2many/One2manyInput.tsx +2 -0
  86. package/src/widgets/containers/Group.tsx +3 -3
  87. package/src/widgets/custom/ButtonGroup.tsx +1 -1
  88. package/src/widgets/custom/MultiCheckbox.tsx +1 -0
  89. package/src/widgets/custom/Tag.tsx +24 -0
  90. package/src/widgets/custom/Tags.tsx +27 -28
  91. package/src/widgets/modals/ExportModal.tsx +53 -15
  92. package/src/widgets/views/Dashboard/Dashboard.tsx +5 -1
  93. package/src/widgets/views/Dashboard/DashboardTree.tsx +1 -0
  94. package/src/widgets/views/Form.tsx +35 -24
  95. package/src/widgets/views/SearchTree.tsx +2 -0
  96. package/src/widgets/views/Tree.tsx +88 -25
  97. package/dist/helpers/icons/antd_icons.d.ts +0 -4
  98. package/dist/helpers/icons/antd_icons.d.ts.map +0 -1
  99. package/dist/helpers/icons/tabler_icons.d.ts +0 -4
  100. package/dist/helpers/icons/tabler_icons.d.ts.map +0 -1
  101. package/dist/ui/Fieldset.d.ts +0 -8
  102. package/dist/ui/Fieldset.d.ts.map +0 -1
  103. package/src/helpers/icons/antd_icons.ts +0 -1583
  104. package/src/helpers/icons/tabler_icons.ts +0 -5367
  105. package/src/ui/Fieldset.tsx +0 -31
@@ -132,13 +132,12 @@ export const Many2oneInput: React.FC<Many2oneInputProps> = (
132
132
  if (transformedDomain.current && transformedDomain.current.length > 0) {
133
133
  tryFetchFirstResultOrShowSearch(inputTextRef.current as string);
134
134
  } else {
135
- const results: any[] = await ConnectionProvider.getHandler().nameSearch(
136
- {
135
+ const results: any[] =
136
+ await ConnectionProvider.getHandler().nameSearch({
137
137
  model: relation,
138
138
  payload: inputTextRef.current as string,
139
139
  context: { ...getContext?.(), ...context },
140
- }
141
- );
140
+ });
142
141
 
143
142
  if (results.length === 1) {
144
143
  inputTextRef.current = undefined;
@@ -207,16 +206,16 @@ export const Many2oneInput: React.FC<Many2oneInputProps> = (
207
206
 
208
207
  async function parseDomain() {
209
208
  if (widgetDomain) {
210
- transformedDomain.current = await ConnectionProvider.getHandler().evalDomain(
211
- {
209
+ transformedDomain.current =
210
+ await ConnectionProvider.getHandler().evalDomain({
212
211
  domain: widgetDomain,
213
212
  values: transformPlainMany2Ones({
214
213
  fields: getFields(),
215
214
  values: getValues(),
216
215
  }),
216
+ fields: getFields(),
217
217
  context: getContext(),
218
- }
219
- );
218
+ });
220
219
  }
221
220
 
222
221
  if (domain && domain.length > 0) {
@@ -232,7 +231,7 @@ export const Many2oneInput: React.FC<Many2oneInputProps> = (
232
231
  }
233
232
 
234
233
  async function onKeyDown(event: any) {
235
- if (event.code === "Enter") {
234
+ if (event.keyCode === 13) {
236
235
  event.preventDefault();
237
236
  event.stopPropagation();
238
237
  await onElementLostFocus();
@@ -0,0 +1,18 @@
1
+ import { Space } from "antd";
2
+ import React from "react";
3
+ import { Many2oneSuffix } from "./Many2oneSuffix";
4
+
5
+ export type Many2oneTreeProps = { m2oField: any };
6
+
7
+ export const Many2oneTree = (props: Many2oneTreeProps): React.ReactElement => {
8
+ const { m2oField } = props;
9
+ if (!m2oField) {
10
+ return <></>;
11
+ }
12
+ return (
13
+ <Space>
14
+ <>{m2oField.value}</>
15
+ <Many2oneSuffix id={m2oField.id} model={m2oField.model} />
16
+ </Space>
17
+ );
18
+ };
@@ -168,6 +168,7 @@ const One2manyInput: React.FC<One2manyInputProps> = (
168
168
  fields: getFields(),
169
169
  values: getValues(),
170
170
  }),
171
+ fields: getFields(),
171
172
  context: getContext(),
172
173
  }),
173
174
  widgetFieldName: fieldName,
@@ -573,6 +574,7 @@ const One2manyInput: React.FC<One2manyInputProps> = (
573
574
  }}
574
575
  sorter={sorter}
575
576
  onChangeSort={setSorter}
577
+ context={{ ...getContext?.(), ...context }}
576
578
  />
577
579
  );
578
580
  }
@@ -1,7 +1,7 @@
1
1
  import React from "react";
2
2
  import { Group as GroupOoui } from "@gisce/ooui";
3
3
  import Container from "./Container";
4
- import Fieldset from "@/ui/Fieldset";
4
+ import { FieldSet } from "@gisce/react-formiga-components";
5
5
 
6
6
  type Props = {
7
7
  ooui: GroupOoui;
@@ -15,12 +15,12 @@ function Group(props: Props): React.ReactElement {
15
15
  return (
16
16
  <>
17
17
  {ooui.label && showLabel ? (
18
- <Fieldset label={ooui.label}>
18
+ <FieldSet label={ooui.label}>
19
19
  <Container
20
20
  container={ooui!.container}
21
21
  responsiveBehaviour={responsiveBehaviour}
22
22
  />
23
- </Fieldset>
23
+ </FieldSet>
24
24
  ) : (
25
25
  <Container
26
26
  container={ooui!.container}
@@ -83,7 +83,7 @@ export const ButtonGroup = (props: ButtonGroupProps) => {
83
83
  type={primary ? "primary" : undefined}
84
84
  //danger={danger ? true : undefined} This works but typescript
85
85
  // doesn't accept
86
- overlay={<Items ooui={secondaryButtons} />}
86
+ overlay={Items({ooui: secondaryButtons})}
87
87
  >
88
88
  {getButtonIcon()}
89
89
  {caption}
@@ -62,6 +62,7 @@ export const MultiCheckboxInput = (props: MultiCheckboxInputProps) => {
62
62
  fields: formContext?.getFields(),
63
63
  values: formContext.getPlainValues(),
64
64
  }),
65
+ fields: formContext?.getFields(),
65
66
  context: formContext.getContext(),
66
67
  });
67
68
  params = [...params, ...evaluatedDomain];
@@ -0,0 +1,24 @@
1
+ import Field from "@/common/Field";
2
+ import { WidgetProps } from "@/types";
3
+ import { Tag as AntdTag } from 'antd';
4
+ import { colorFromString } from "@/helpers/formHelper";
5
+
6
+
7
+ export const Tag = (props: WidgetProps) => {
8
+ return (
9
+ <Field {...props}>
10
+ <TagInput {...props}/>
11
+ </Field>
12
+ );
13
+ };
14
+
15
+ export const TagInput = (props) => {
16
+ const {ooui, value} = props;
17
+ if (!value) {
18
+ return null
19
+ }
20
+ const color = ooui.colors === "auto" ? colorFromString(value) : ooui.colors[value]
21
+ return (
22
+ <AntdTag color={color}>{ooui.selectionValues.get(value)}</AntdTag>
23
+ );
24
+ }
@@ -23,7 +23,7 @@ export const Tags = (props: TagsProps) => {
23
23
 
24
24
  return (
25
25
  <Field type={"array"} {...props}>
26
- <TagsInput ooui={ooui} />
26
+ <TagsInput ooui={ooui} />
27
27
  </Field>
28
28
  );
29
29
  };
@@ -31,16 +31,15 @@ export const Tags = (props: TagsProps) => {
31
31
  export const TagsInput = (props: TagsInputProps) => {
32
32
  const { value, ooui, onChange } = props;
33
33
  const { items = [] } = value || {};
34
- const itemsToShow = items.filter(
35
- (item) => item.operation !== "pendingRemove"
36
- ).map((item) => item.id) as number[];
34
+ const itemsToShow = items
35
+ .filter((item) => item.operation !== "pendingRemove")
36
+ .map((item) => item.id) as number[];
37
37
 
38
38
  const [options, setOptions] = useState<any[]>([]);
39
39
  const [error, setError] = useState<string>();
40
40
  const [isLoadingOptions, setIsLoadingOptions] = useState<boolean>(false);
41
41
  const { relation, context, readOnly, field } = ooui;
42
42
 
43
-
44
43
  const formContext = useContext(FormContext) as FormContextType;
45
44
  const { getContext } = formContext || {};
46
45
 
@@ -62,16 +61,16 @@ export const TagsInput = (props: TagsInputProps) => {
62
61
  params = [["id", "in", itemsToShow]];
63
62
  }
64
63
  if (ooui.domain) {
65
- const evaluatedDomain = await ConnectionProvider.getHandler().evalDomain(
66
- {
64
+ const evaluatedDomain =
65
+ await ConnectionProvider.getHandler().evalDomain({
67
66
  domain: ooui.domain,
68
67
  values: transformPlainMany2Ones({
69
68
  fields: formContext?.getFields(),
70
69
  values: formContext.getPlainValues(),
71
70
  }),
72
- context: formContext.getContext(),
73
- }
74
- );
71
+ fields: formContext?.getFields(),
72
+ context: formContext.getContext(),
73
+ });
75
74
  params = [...params, ...evaluatedDomain];
76
75
  }
77
76
 
@@ -81,18 +80,17 @@ export const TagsInput = (props: TagsInputProps) => {
81
80
  fields: [field],
82
81
  context: { ...getContext?.(), ...context },
83
82
  });
84
- const options = optionsRead.map((item:any) => {
83
+ const options = optionsRead.map((item: any) => {
85
84
  const value = item[field];
86
85
  let formattedValue = value;
87
86
  if (Array.isArray(value)) {
88
87
  formattedValue = value[1];
89
88
  }
90
- return {label: formattedValue, value: item.id}
89
+ return { label: formattedValue, value: item.id };
91
90
  });
92
91
  setOptions(options);
93
-
94
92
  } catch (err) {
95
- setError(err as any)
93
+ setError(err as any);
96
94
  } finally {
97
95
  setIsLoadingOptions(false);
98
96
  }
@@ -104,19 +102,21 @@ export const TagsInput = (props: TagsInputProps) => {
104
102
  if (item.operation == "pendingRemove") {
105
103
  return {
106
104
  ...item,
107
- operation: "pendingLink"
108
- }
105
+ operation: "pendingLink",
106
+ };
109
107
  } else {
110
- return item
108
+ return item;
111
109
  }
112
110
  } else {
113
- return {id: item.id, operation: 'pendingRemove'}
111
+ return { id: item.id, operation: "pendingRemove" };
114
112
  }
115
- })
116
- const currentIds = newItems.map(item => item.id)
117
- ids.filter(id => !currentIds.includes(id)).map((id) => {
118
- newItems.push({id, operation: 'pendingLink'});
119
113
  });
114
+ const currentIds = newItems.map((item) => item.id);
115
+ ids
116
+ .filter((id) => !currentIds.includes(id))
117
+ .map((id) => {
118
+ newItems.push({ id, operation: "pendingLink" });
119
+ });
120
120
  triggerChange(newItems);
121
121
  };
122
122
 
@@ -130,10 +130,11 @@ export const TagsInput = (props: TagsInputProps) => {
130
130
  <AntTag
131
131
  color={colorFromString(label)}
132
132
  onMouseDown={onPreventMouseDown}
133
- style={{margin: '5px'}}
133
+ style={{ margin: "5px" }}
134
134
  closable={closable}
135
- onClose={onClose}>
136
- {label}
135
+ onClose={onClose}
136
+ >
137
+ {label}
137
138
  </AntTag>
138
139
  );
139
140
  };
@@ -154,10 +155,8 @@ export const TagsInput = (props: TagsInputProps) => {
154
155
  options={options}
155
156
  onChange={onChangeSelected}
156
157
  loading={isLoadingOptions}
157
- >
158
- </Select>
158
+ ></Select>
159
159
  </div>
160
160
  </>
161
161
  );
162
-
163
162
  };
@@ -13,13 +13,13 @@ export type ExportModalProps = {
13
13
  visible: boolean;
14
14
  locale: string;
15
15
  onClose: () => void;
16
- selectedRegistersToExport?: number;
16
+ selectedRegistersToExport?: any[];
17
17
  totalRegisters: number;
18
18
  model: string;
19
19
  domain: any[];
20
20
  limit?: number;
21
- treeFields?: any;
22
21
  context?: any;
22
+ visibleRegisters: number;
23
23
  };
24
24
 
25
25
  export const ExportModal = (props: ExportModalProps) => {
@@ -29,26 +29,40 @@ export const ExportModal = (props: ExportModalProps) => {
29
29
  onClose,
30
30
  model,
31
31
  context,
32
- treeFields,
33
32
  selectedRegistersToExport,
34
33
  totalRegisters,
35
34
  domain,
36
35
  limit,
36
+ visibleRegisters,
37
37
  } = props;
38
38
  const fields = useRef<any>({});
39
39
 
40
40
  const onSucceed = useCallback(
41
41
  async (options: ExportOptions) => {
42
- if (options.selectedKeys.length === 0) {
42
+ if (
43
+ options.selectedKeys === undefined ||
44
+ options.selectedKeys.length === 0
45
+ ) {
43
46
  showInfo(tForLang("selectAtLeastOneField", locale));
44
47
  return;
45
48
  }
46
49
 
50
+ let exportDomain = domain;
51
+
52
+ if (
53
+ options.registersAmount === "selected" &&
54
+ selectedRegistersToExport?.length !== 0
55
+ ) {
56
+ exportDomain = [
57
+ ["id", "in", selectedRegistersToExport?.map((r) => r.id)],
58
+ ];
59
+ }
60
+
47
61
  const { datas } = await ConnectionProvider.getHandler().exportData({
48
62
  model,
49
63
  fields: options.selectedKeys,
50
- domain: options.registersAmount === "all" ? [] : domain,
51
- limit: options.registersAmount === "all" ? undefined : limit,
64
+ domain: exportDomain,
65
+ limit: options.registersAmount === "all" ? 0 : limit,
52
66
  context,
53
67
  format: options.exportType,
54
68
  });
@@ -77,13 +91,18 @@ export const ExportModal = (props: ExportModalProps) => {
77
91
  async ({ key, title }: any) => {
78
92
  let fieldDefinition;
79
93
 
80
- if (key.indexOf("/") === -1) {
94
+ const sanitizedKey =
95
+ key.split("/")[key.split("/").length - 1] === "id"
96
+ ? key.split("/").slice(0, -1).join("/")
97
+ : key;
98
+
99
+ if (sanitizedKey.indexOf("/") === -1) {
81
100
  fieldDefinition = fields.current["/"];
82
101
  } else {
83
- fieldDefinition = fields.current[getParentKey(key)];
102
+ fieldDefinition = fields.current[getParentKey(sanitizedKey)];
84
103
  }
85
104
 
86
- const optsForField = fieldDefinition[getChildKey(key)];
105
+ const optsForField = fieldDefinition[getChildKey(sanitizedKey)];
87
106
  const relation = optsForField.relation;
88
107
  const viewData = await ConnectionProvider.getHandler().getFields({
89
108
  model: relation,
@@ -91,12 +110,12 @@ export const ExportModal = (props: ExportModalProps) => {
91
110
  fields: [],
92
111
  });
93
112
 
94
- fields.current[key] = viewData;
113
+ fields.current[sanitizedKey] = viewData;
95
114
 
96
115
  return convertToExportField({
97
116
  fields: viewData,
98
117
  parentTitle: title,
99
- parentKey: key,
118
+ parentKey: sanitizedKey,
100
119
  });
101
120
  },
102
121
  [fields, model, context]
@@ -108,11 +127,17 @@ export const ExportModal = (props: ExportModalProps) => {
108
127
  locale={locale as Locale}
109
128
  onSucceed={onSucceed}
110
129
  onCancel={onClose}
111
- selectedRegistersToExport={selectedRegistersToExport}
130
+ selectedRegistersToExport={
131
+ selectedRegistersToExport &&
132
+ selectedRegistersToExport.length &&
133
+ selectedRegistersToExport.length > 0
134
+ ? selectedRegistersToExport.length
135
+ : undefined
136
+ }
112
137
  totalRegisters={totalRegisters}
113
138
  onGetFieldChilds={onGetFieldChilds}
114
139
  onGetFields={onGetFields}
115
- selectedKeys={treeFields ? Object.keys(treeFields) : undefined}
140
+ visibleRegisters={visibleRegisters}
116
141
  />
117
142
  );
118
143
  };
@@ -130,14 +155,27 @@ const convertToExportField = ({
130
155
 
131
156
  for (const key of Object.keys(fields)) {
132
157
  const valuesForField = fields[key];
158
+
159
+ if (valuesForField.relation && valuesForField.is_function === true) {
160
+ continue;
161
+ }
162
+
133
163
  const relationField =
134
164
  valuesForField.type === "many2one" ||
135
165
  valuesForField.type === "one2many" ||
136
166
  valuesForField.type === "many2many";
137
167
 
168
+ let newKey = `${parentKey ? parentKey + "/" : ""}${key}`;
169
+
170
+ if (relationField) {
171
+ newKey += "/id";
172
+ }
173
+
138
174
  exportFields.push({
139
- key: `${parentKey ? parentKey + "/" : ""}${key}`,
140
- title: `${parentTitle ? parentTitle + "/" : ""}${valuesForField.string}`,
175
+ key: newKey,
176
+ title: `${parentTitle ? parentTitle + "" : ""}${
177
+ valuesForField.string
178
+ }`,
141
179
  tooltip: valuesForField.help,
142
180
  required: valuesForField.required,
143
181
  isLeaf: !relationField,
@@ -308,6 +308,10 @@ function Dashboard(props: DashboardProps, ref: any) {
308
308
  />
309
309
  );
310
310
  } else if (initialView !== undefined) {
311
+ const formattedInitialView =
312
+ initialView && Array.isArray(initialView.id)
313
+ ? { ...initialView, id: initialView.id[0] }
314
+ : initialView;
311
315
  childContent = (
312
316
  <ActionView
313
317
  action_id={actionId}
@@ -319,7 +323,7 @@ function Dashboard(props: DashboardProps, ref: any) {
319
323
  context={context}
320
324
  domain={domain}
321
325
  setCanWeClose={() => {}}
322
- initialView={initialView}
326
+ initialView={formattedInitialView}
323
327
  limit={limit}
324
328
  />
325
329
  );
@@ -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) {
@@ -455,15 +459,13 @@ function Form(props: FormProps, ref: any) {
455
459
 
456
460
  const getFormView = async (): Promise<FormView> => {
457
461
  if (getDataFromAction) {
458
- const action = await ConnectionProvider.getHandler().getActionStringForModel(
459
- model
460
- );
461
- const viewsForAction = await ConnectionProvider.getHandler().getViewsForAction(
462
- {
462
+ const action =
463
+ await ConnectionProvider.getHandler().getActionStringForModel(model);
464
+ const viewsForAction =
465
+ await ConnectionProvider.getHandler().getViewsForAction({
463
466
  action,
464
467
  context: parentContext,
465
- }
466
- );
468
+ });
467
469
  return viewsForAction.views.get("form");
468
470
  }
469
471
 
@@ -609,13 +611,13 @@ function Form(props: FormProps, ref: any) {
609
611
  formSubmitting.current = false;
610
612
  setFormHasChanges?.(false);
611
613
  onCancel?.();
612
- return true;
614
+ return { succeed: true, id: getCurrentId()! };
613
615
  }
614
616
 
615
617
  if (await checkIfFormHasErrors()) {
616
618
  formSubmitting.current = false;
617
619
  formErrorsDialog(lang);
618
- return false;
620
+ return { succeed: false, id: getCurrentId()! };
619
621
  }
620
622
 
621
623
  setIsSubmitting(true);
@@ -640,6 +642,7 @@ function Form(props: FormProps, ref: any) {
640
642
  setIsSubmitting(false);
641
643
  setFormIsSaving?.(false);
642
644
  onSubmitError?.(err);
645
+ message.error(t("errorWhileSavingForm"));
643
646
  setError(err?.message ? err.message : err);
644
647
  } finally {
645
648
  formSubmitting.current = false;
@@ -647,7 +650,7 @@ function Form(props: FormProps, ref: any) {
647
650
  setIsSubmitting(false);
648
651
  }
649
652
 
650
- return submitSucceed;
653
+ return { succeed: submitSucceed, id: getCurrentId()! };
651
654
  };
652
655
 
653
656
  const parseForm = ({
@@ -663,13 +666,20 @@ function Form(props: FormProps, ref: any) {
663
666
  // TODO: Here we must inject `values` to the ooui parser in order to evaluate arch+values and get the new form container
664
667
  ooui.parse(arch, {
665
668
  readOnly,
666
- values: {
667
- ...values,
668
- ...getAdditionalValues(),
669
- },
669
+ values: convertToPlain2ManyValues(
670
+ {
671
+ ...values,
672
+ ...getAdditionalValues(),
673
+ },
674
+ fields
675
+ ),
670
676
  });
671
677
  setFormOoui(ooui);
672
678
 
679
+ if (ooui.string && ooui.string !== title) {
680
+ setTitle?.(ooui.string);
681
+ }
682
+
673
683
  if (formModalContext && ooui.string)
674
684
  formModalContext.setTitle?.(ooui.string);
675
685
  };
@@ -695,7 +705,7 @@ function Form(props: FormProps, ref: any) {
695
705
  if (
696
706
  checkFieldsType({
697
707
  changedFields,
698
- fields,
708
+ formOoui: formOoui!,
699
709
  types: [
700
710
  "text",
701
711
  "codeeditor",
@@ -756,6 +766,7 @@ function Form(props: FormProps, ref: any) {
756
766
  ...formOoui?.context,
757
767
  },
758
768
  },
769
+ parentValues: getParentPlainValues?.(),
759
770
  onChangeFieldActionArgs: onChangeFieldAction.args,
760
771
  });
761
772
 
@@ -307,6 +307,7 @@ function SearchTree(props: Props, ref: any) {
307
307
  searchValues={searchValues}
308
308
  />
309
309
  <Tree
310
+ context={parentContext}
310
311
  total={totalItems}
311
312
  limit={limit}
312
313
  page={page}
@@ -327,6 +328,7 @@ function SearchTree(props: Props, ref: any) {
327
328
  treeView.isExpandable ? fetchChildrenForRecord : undefined
328
329
  }
329
330
  childField={treeView.field_parent}
331
+ rootTree={rootTree}
330
332
  />
331
333
  </>
332
334
  );