@gisce/react-ooui 2.0.0-rc.0 → 2.0.0-rc.11
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/actionbar/TreeActionBar.d.ts.map +1 -1
- package/dist/common/SelectAllRecordsRow.d.ts +10 -0
- package/dist/common/SelectAllRecordsRow.d.ts.map +1 -0
- package/dist/context/ContentRootContext.d.ts.map +1 -1
- package/dist/helpers/dynamicColumnsHelper.d.ts +9 -1
- package/dist/helpers/dynamicColumnsHelper.d.ts.map +1 -1
- package/dist/helpers/formHelper.d.ts +1 -0
- package/dist/helpers/formHelper.d.ts.map +1 -1
- package/dist/helpers/treeHelper.d.ts +2 -1
- package/dist/helpers/treeHelper.d.ts.map +1 -1
- package/dist/hooks/useSearch.d.ts +1 -0
- package/dist/hooks/useSearch.d.ts.map +1 -1
- package/dist/index.d.ts +2 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/locales/ca_ES.d.ts +4 -0
- package/dist/locales/ca_ES.d.ts.map +1 -1
- package/dist/locales/en_US.d.ts +4 -0
- package/dist/locales/en_US.d.ts.map +1 -1
- package/dist/locales/es_ES.d.ts +4 -0
- package/dist/locales/es_ES.d.ts.map +1 -1
- package/dist/react-ooui.es.js +5621 -5204
- package/dist/react-ooui.es.js.map +1 -1
- package/dist/react-ooui.umd.js +19 -14
- package/dist/react-ooui.umd.js.map +1 -1
- package/dist/types/index.d.ts +30 -29
- package/dist/types/index.d.ts.map +1 -1
- package/dist/views/actionViews/GraphActionView.d.ts.map +1 -1
- package/dist/widgets/WidgetFactory.d.ts.map +1 -1
- package/dist/widgets/base/Integer.d.ts.map +1 -1
- package/dist/widgets/base/many2one/Many2oneSuffix.d.ts.map +1 -1
- package/dist/widgets/base/one2many/One2manyInput.d.ts.map +1 -1
- package/dist/widgets/custom/Avatar.d.ts.map +1 -1
- package/dist/widgets/custom/Comments.d.ts +35 -0
- package/dist/widgets/custom/Comments.d.ts.map +1 -0
- package/dist/widgets/views/Form.d.ts +2 -2
- package/dist/widgets/views/Form.d.ts.map +1 -1
- package/dist/widgets/views/SearchTree.d.ts.map +1 -1
- package/dist/widgets/views/Tree.d.ts +1 -0
- package/dist/widgets/views/Tree.d.ts.map +1 -1
- package/dist/widgets/views/searchFilter/SearchFilter.d.ts +0 -1
- package/dist/widgets/views/searchFilter/SearchFilter.d.ts.map +1 -1
- package/package.json +5 -3
- package/src/actionbar/FormActionBar.tsx +1 -1
- package/src/actionbar/TreeActionBar.tsx +84 -82
- package/src/common/SelectAllRecordsRow.tsx +95 -0
- package/src/context/ContentRootContext.tsx +5 -3
- package/src/helpers/dynamicColumnsHelper.ts +1 -1
- package/src/helpers/formHelper.ts +5 -0
- package/src/helpers/iconMapper.ts +1 -2
- package/src/helpers/treeHelper.ts +14 -3
- package/src/hooks/useExport.ts +2 -3
- package/src/hooks/useSearch.ts +16 -3
- package/src/index.ts +2 -0
- package/src/locales/ca_ES.tsx +5 -0
- package/src/locales/en_US.tsx +5 -0
- package/src/locales/es_ES.tsx +5 -0
- package/src/stories/custom/Comments.stories.tsx +190 -0
- package/src/stories/dashboard/DashboardGrid.stories.tsx +13 -0
- package/src/stories/mocks/models/cups.ts +16 -3
- package/src/types/index.ts +92 -41
- package/src/views/actionViews/GraphActionView.tsx +0 -1
- package/src/widgets/WidgetFactory.tsx +3 -0
- package/src/widgets/base/Integer.tsx +14 -1
- package/src/widgets/base/many2one/Many2oneSuffix.tsx +24 -12
- package/src/widgets/base/one2many/One2manyInput.tsx +11 -3
- package/src/widgets/custom/Avatar.tsx +0 -1
- package/src/widgets/custom/Comments.tsx +144 -0
- package/src/widgets/views/Form.tsx +83 -9
- package/src/widgets/views/Graph/GraphIndicator.tsx +3 -3
- package/src/widgets/views/SearchTree.tsx +12 -8
- package/src/widgets/views/Tree.tsx +62 -48
- package/src/widgets/views/searchFilter/SearchFilter.tsx +1 -3
|
@@ -33,6 +33,7 @@ import {
|
|
|
33
33
|
Steps,
|
|
34
34
|
Tag,
|
|
35
35
|
CodeEditor,
|
|
36
|
+
CommentsTimelineField,
|
|
36
37
|
} from "@/index";
|
|
37
38
|
import { Image } from "./base/Image";
|
|
38
39
|
import { FiberGrid } from "./custom/FiberGrid";
|
|
@@ -118,6 +119,8 @@ const getWidgetType = (type: string) => {
|
|
|
118
119
|
return Steps;
|
|
119
120
|
case "codeeditor":
|
|
120
121
|
return CodeEditor;
|
|
122
|
+
case "comments_timeline":
|
|
123
|
+
return CommentsTimelineField;
|
|
121
124
|
default:
|
|
122
125
|
return undefined;
|
|
123
126
|
}
|
|
@@ -27,7 +27,20 @@ export const Integer = (props: IntegerProps) => {
|
|
|
27
27
|
className={"w-full "}
|
|
28
28
|
disabled={readOnly}
|
|
29
29
|
formatter={(value) => {
|
|
30
|
-
|
|
30
|
+
// Check if value is not undefined and is a valid number
|
|
31
|
+
if (value === undefined) {
|
|
32
|
+
return "";
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
if (typeof value === "string" && !isNaN(parseFloat(value))) {
|
|
36
|
+
let truncatedValue = Math.trunc(parseFloat(value));
|
|
37
|
+
return `${truncatedValue}`.replace(/[^0-9\-]+/g, "");
|
|
38
|
+
} else if (typeof value === "number") {
|
|
39
|
+
let truncatedValue = Math.trunc(value);
|
|
40
|
+
return `${truncatedValue}`.replace(/[^0-9\-]+/g, "");
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
return "";
|
|
31
44
|
}}
|
|
32
45
|
onChange={(newValue: any) => {
|
|
33
46
|
const newNumber = newValue as number;
|
|
@@ -20,6 +20,7 @@ import ConnectionProvider from "@/ConnectionProvider";
|
|
|
20
20
|
import { processValues } from "@/helpers/formHelper";
|
|
21
21
|
import showErrorDialog from "@/ui/ActionErrorDialog";
|
|
22
22
|
import { LocaleContext, LocaleContextType } from "@/context/LocaleContext";
|
|
23
|
+
import { parseContextFields, parseDomainFields } from "@gisce/ooui";
|
|
23
24
|
|
|
24
25
|
type Props = {
|
|
25
26
|
id: number;
|
|
@@ -60,18 +61,29 @@ export const Many2oneSuffix = (props: Props) => {
|
|
|
60
61
|
context,
|
|
61
62
|
}) as FormView;
|
|
62
63
|
setFormView(formView);
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
64
|
+
let fields: string[] = [];
|
|
65
|
+
const { toolbar } = formView;
|
|
66
|
+
toolbar.action?.filter((item: any) => item.hasOwnProperty('context')).map((item: any) => fields.push(...parseContextFields(item.context)));
|
|
67
|
+
toolbar.action?.filter((item: any) => item.hasOwnProperty('domain')).map((item: any) => fields.push(...parseDomainFields(item.domain)));
|
|
68
|
+
toolbar.relate?.filter((item: any) => item.hasOwnProperty('context')).map((item: any) => fields.push(...parseContextFields(item.context)));
|
|
69
|
+
toolbar.relate?.filter((item: any) => item.hasOwnProperty('domain')).map((item: any) => fields.push(...parseDomainFields(item.domain)));
|
|
70
|
+
toolbar.print?.filter((item: any) => item.hasOwnProperty('context')).map((item: any) => fields.push(...parseContextFields(item.context)));
|
|
71
|
+
fields = fields.filter((i) => Object.keys(formView.fields).indexOf(i) > -1)
|
|
72
|
+
|
|
73
|
+
let values = {}
|
|
74
|
+
|
|
75
|
+
if (fields.length > 0) {
|
|
76
|
+
values = (
|
|
77
|
+
await ConnectionProvider.getHandler().readObjects({
|
|
78
|
+
model,
|
|
79
|
+
ids: [id],
|
|
80
|
+
fieldsToRetrieve: fields,
|
|
81
|
+
context,
|
|
82
|
+
})
|
|
83
|
+
)[0];
|
|
84
|
+
}
|
|
85
|
+
values = { ...processValues(values, fields), active_id: id };
|
|
86
|
+
setTargetValues(values);
|
|
75
87
|
|
|
76
88
|
setIsLoading(false);
|
|
77
89
|
} catch (err) {
|
|
@@ -437,11 +437,19 @@ const One2manyInput: React.FC<One2manyInputProps> = (
|
|
|
437
437
|
const onFormModalSubmitSucceed = (
|
|
438
438
|
id: number | undefined,
|
|
439
439
|
_: any,
|
|
440
|
-
values: any
|
|
440
|
+
values: any,
|
|
441
|
+
x2manyPendingLink: boolean = false
|
|
441
442
|
) => {
|
|
442
443
|
let updatedItems: One2manyItem[];
|
|
443
444
|
|
|
444
|
-
if (
|
|
445
|
+
if (x2manyPendingLink) {
|
|
446
|
+
updatedItems = items.concat({
|
|
447
|
+
id,
|
|
448
|
+
operation: "pendingLink",
|
|
449
|
+
values: { ...values, id },
|
|
450
|
+
treeValues: { ...values, id },
|
|
451
|
+
});
|
|
452
|
+
} else if (id) {
|
|
445
453
|
updatedItems = items.map((item: One2manyItem) => {
|
|
446
454
|
if (item.id === id) {
|
|
447
455
|
return {
|
|
@@ -683,7 +691,7 @@ const One2manyInput: React.FC<One2manyInputProps> = (
|
|
|
683
691
|
formView={views.get("form")}
|
|
684
692
|
model={relation}
|
|
685
693
|
id={modalItem?.id}
|
|
686
|
-
submitMode={"
|
|
694
|
+
submitMode={"2many"}
|
|
687
695
|
values={modalItem?.values}
|
|
688
696
|
defaultValues={modalItem?.defaultValues}
|
|
689
697
|
visible={showFormModal}
|
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
import React, {useContext} from "react";
|
|
2
|
+
import Field from "@/common/Field";
|
|
3
|
+
import { WidgetProps } from "@/types";
|
|
4
|
+
import {Card, Space, Typography, Avatar, Tag, Timeline, TimelineItemProps} from "antd"
|
|
5
|
+
import { LocaleContext, LocaleContextType } from "@/context/LocaleContext";
|
|
6
|
+
|
|
7
|
+
const { Meta } = Card;
|
|
8
|
+
const { Text} = Typography;
|
|
9
|
+
|
|
10
|
+
import dayjs from "dayjs";
|
|
11
|
+
import relativeTime from "dayjs/plugin/relativeTime";
|
|
12
|
+
import md5 from "md5";
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
dayjs.extend(relativeTime);
|
|
16
|
+
|
|
17
|
+
type GravatarProps = {
|
|
18
|
+
email: string,
|
|
19
|
+
size?: number,
|
|
20
|
+
theme: string,
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
type CommentDataType = {
|
|
24
|
+
id: number,
|
|
25
|
+
isSender: boolean,
|
|
26
|
+
isAuthor: boolean,
|
|
27
|
+
text: string,
|
|
28
|
+
email: string,
|
|
29
|
+
date: string,
|
|
30
|
+
author: string,
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
type CommentProps = {
|
|
34
|
+
data: CommentDataType,
|
|
35
|
+
style?: any,
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
type CommentsTypeProps = {
|
|
39
|
+
data: CommentDataType[],
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
type CommentsTimelineProps = {
|
|
43
|
+
value?: EventsType[],
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
type EventActionType = {
|
|
48
|
+
date: string,
|
|
49
|
+
action: string,
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
export type EventsType = {
|
|
53
|
+
type: "action" | "comment",
|
|
54
|
+
event: EventActionType | CommentDataType
|
|
55
|
+
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
const Gravatar = ({ email, size = 40, theme = '' } : GravatarProps) => {
|
|
59
|
+
// Genera el enlace de Gravatar utilizando el email
|
|
60
|
+
const gravatarUrl = `https://www.gravatar.com/avatar/${md5(email)}?s=${size}&d=${theme}`;
|
|
61
|
+
|
|
62
|
+
return (
|
|
63
|
+
<Avatar src={gravatarUrl} size={size} />
|
|
64
|
+
);
|
|
65
|
+
};
|
|
66
|
+
|
|
67
|
+
|
|
68
|
+
function TextWithNewlines({ text }:{text: string}) {
|
|
69
|
+
const textParts = text.split('\n');
|
|
70
|
+
|
|
71
|
+
return (
|
|
72
|
+
<div>
|
|
73
|
+
{textParts.map((part, index) => (
|
|
74
|
+
<React.Fragment key={index}>
|
|
75
|
+
{part}
|
|
76
|
+
{index !== textParts.length - 1 && <br />}
|
|
77
|
+
</React.Fragment>
|
|
78
|
+
))}
|
|
79
|
+
</div>
|
|
80
|
+
);
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
export const Comment = (props: CommentProps) => {
|
|
84
|
+
const {data, style} = props;
|
|
85
|
+
const { t } = useContext(LocaleContext) as LocaleContextType;
|
|
86
|
+
return (
|
|
87
|
+
<Card key={data.id} style={{...style, ...{textAlign: 'start'}}}>
|
|
88
|
+
<Meta avatar={<Gravatar email={data.email} theme='mp'/>}
|
|
89
|
+
title={data.author}
|
|
90
|
+
description={(
|
|
91
|
+
<Space direction="horizontal">
|
|
92
|
+
<span title={data.date}>{dayjs(data.date).fromNow()}</span>
|
|
93
|
+
{data.isAuthor && <Tag color="blue">{t('author')}</Tag>}
|
|
94
|
+
</Space>
|
|
95
|
+
)} style={{marginBottom: '5px'}}/>
|
|
96
|
+
<Text>
|
|
97
|
+
<TextWithNewlines text={data.text} />
|
|
98
|
+
</Text>
|
|
99
|
+
</Card>
|
|
100
|
+
)
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
export const Comments = (props: CommentsTypeProps) => {
|
|
104
|
+
const { data = [] } = props;
|
|
105
|
+
const comments = data.map((c) => {
|
|
106
|
+
const style = {float: c.isSender ? 'right' : 'left', width: '60%'};
|
|
107
|
+
return <Comment data={c} style={style}/>
|
|
108
|
+
});
|
|
109
|
+
return (
|
|
110
|
+
<div>
|
|
111
|
+
<Space direction="vertical" size="middle" style={{ display: 'flex' }}>
|
|
112
|
+
{comments}
|
|
113
|
+
</Space>
|
|
114
|
+
</div>
|
|
115
|
+
)
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
|
|
119
|
+
export const CommentsTimeline = (props: CommentsTimelineProps) => {
|
|
120
|
+
const { value } = props;
|
|
121
|
+
const items = (value || []).map(i => {
|
|
122
|
+
if (i.type === 'action') {
|
|
123
|
+
return {
|
|
124
|
+
children: `${i.event.date} - ${(i.event as EventActionType).action}`
|
|
125
|
+
}
|
|
126
|
+
} else if (i.type === "comment") {
|
|
127
|
+
return {
|
|
128
|
+
color: 'gray',
|
|
129
|
+
position: (i.event as CommentDataType).isSender ? 'left' : 'right',
|
|
130
|
+
label: i.event.date,
|
|
131
|
+
children: <Comment data={i.event as CommentDataType} />,
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
})
|
|
135
|
+
return <Timeline mode="alternate" items={items as TimelineItemProps[]} />
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
export const CommentsTimelineField = (props: WidgetProps) => {
|
|
139
|
+
return (
|
|
140
|
+
<Field {...props}>
|
|
141
|
+
<CommentsTimeline />
|
|
142
|
+
</Field>
|
|
143
|
+
);
|
|
144
|
+
}
|
|
@@ -67,8 +67,13 @@ export type FormProps = {
|
|
|
67
67
|
showFooter?: boolean;
|
|
68
68
|
getDataFromAction?: boolean;
|
|
69
69
|
mustClearAfterSave?: boolean;
|
|
70
|
-
submitMode?: "api" | "values";
|
|
71
|
-
onSubmitSucceed?: (
|
|
70
|
+
submitMode?: "api" | "values" | "2many";
|
|
71
|
+
onSubmitSucceed?: (
|
|
72
|
+
id?: number,
|
|
73
|
+
values?: any,
|
|
74
|
+
formValues?: any,
|
|
75
|
+
x2manyPendingLink?: boolean
|
|
76
|
+
) => void;
|
|
72
77
|
onSubmitError?: (error: any) => void;
|
|
73
78
|
onCancel?: () => void;
|
|
74
79
|
onFieldsChange?: (values: any) => void;
|
|
@@ -127,6 +132,7 @@ function Form(props: FormProps, ref: any) {
|
|
|
127
132
|
const lastAssignedValues = useRef<any>({});
|
|
128
133
|
const warningIsShown = useRef<boolean>(false);
|
|
129
134
|
const formSubmitting = useRef<boolean>(false);
|
|
135
|
+
const x2manyPendingLink = useRef<boolean>(false);
|
|
130
136
|
|
|
131
137
|
const widthToEvaluate =
|
|
132
138
|
parentWidth !== undefined ? parentWidth : containerWidth;
|
|
@@ -203,10 +209,15 @@ function Form(props: FormProps, ref: any) {
|
|
|
203
209
|
}
|
|
204
210
|
}, [defaultGetCalled]);
|
|
205
211
|
|
|
206
|
-
const onSubmitSucceed = (
|
|
212
|
+
const onSubmitSucceed = (
|
|
213
|
+
id?: number,
|
|
214
|
+
values?: any,
|
|
215
|
+
formValues?: any,
|
|
216
|
+
x2manyPendingLink?: boolean
|
|
217
|
+
) => {
|
|
207
218
|
setFormHasChanges?.(false);
|
|
208
219
|
setFormIsSaving?.(false);
|
|
209
|
-
propsOnSubmitSucceed?.(id, values, formValues);
|
|
220
|
+
propsOnSubmitSucceed?.(id, values, formValues, x2manyPendingLink);
|
|
210
221
|
setCurrentId?.(id);
|
|
211
222
|
};
|
|
212
223
|
|
|
@@ -294,6 +305,15 @@ function Form(props: FormProps, ref: any) {
|
|
|
294
305
|
return { ...parentContext, ...formOoui?.context };
|
|
295
306
|
}
|
|
296
307
|
|
|
308
|
+
function getActiveIdsContext() {
|
|
309
|
+
const currentId = getCurrentId()!;
|
|
310
|
+
|
|
311
|
+
if (!currentId) {
|
|
312
|
+
return {};
|
|
313
|
+
}
|
|
314
|
+
return { active_id: getCurrentId()!, active_ids: [getCurrentId()!] };
|
|
315
|
+
}
|
|
316
|
+
|
|
297
317
|
function getAdditionalValues() {
|
|
298
318
|
return {
|
|
299
319
|
id: getCurrentId()!,
|
|
@@ -608,6 +628,32 @@ function Form(props: FormProps, ref: any) {
|
|
|
608
628
|
formSubmitting.current = true;
|
|
609
629
|
|
|
610
630
|
setError(undefined);
|
|
631
|
+
|
|
632
|
+
if (
|
|
633
|
+
x2manyPendingLink.current &&
|
|
634
|
+
!formHasChanges() &&
|
|
635
|
+
getCurrentId()! &&
|
|
636
|
+
callOnSubmitSucceed
|
|
637
|
+
) {
|
|
638
|
+
formSubmitting.current = false;
|
|
639
|
+
setFormHasChanges?.(false);
|
|
640
|
+
onSubmitSucceed?.(
|
|
641
|
+
getCurrentId(),
|
|
642
|
+
getValues(),
|
|
643
|
+
getFormValues(),
|
|
644
|
+
x2manyPendingLink.current
|
|
645
|
+
);
|
|
646
|
+
x2manyPendingLink.current = false;
|
|
647
|
+
const currentId = getCurrentId()!;
|
|
648
|
+
|
|
649
|
+
if (mustClearAfterSave) {
|
|
650
|
+
createdId.current = undefined;
|
|
651
|
+
assignNewValuesToForm({ values: {}, fields, reset: true });
|
|
652
|
+
}
|
|
653
|
+
|
|
654
|
+
return { succeed: true, id: currentId };
|
|
655
|
+
}
|
|
656
|
+
|
|
611
657
|
if (!formHasChanges() && getCurrentId()! && callOnSubmitSucceed) {
|
|
612
658
|
formSubmitting.current = false;
|
|
613
659
|
setFormHasChanges?.(false);
|
|
@@ -659,15 +705,17 @@ function Form(props: FormProps, ref: any) {
|
|
|
659
705
|
fields,
|
|
660
706
|
arch,
|
|
661
707
|
values,
|
|
708
|
+
operationInProgress = false,
|
|
662
709
|
}: {
|
|
663
710
|
arch: string;
|
|
664
711
|
fields: any;
|
|
665
712
|
values: any;
|
|
713
|
+
operationInProgress?: boolean;
|
|
666
714
|
}) => {
|
|
667
715
|
const ooui = new FormOoui(fields);
|
|
668
716
|
// TODO: Here we must inject `values` to the ooui parser in order to evaluate arch+values and get the new form container
|
|
669
717
|
ooui.parse(arch, {
|
|
670
|
-
readOnly,
|
|
718
|
+
readOnly: readOnly || operationInProgress,
|
|
671
719
|
values: convertToPlain2ManyValues(
|
|
672
720
|
{
|
|
673
721
|
...values,
|
|
@@ -833,9 +881,9 @@ function Form(props: FormProps, ref: any) {
|
|
|
833
881
|
action,
|
|
834
882
|
payload: [getCurrentId()!],
|
|
835
883
|
context: {
|
|
836
|
-
...context,
|
|
837
884
|
...formOoui?.context,
|
|
838
885
|
...parentContext,
|
|
886
|
+
...context,
|
|
839
887
|
},
|
|
840
888
|
});
|
|
841
889
|
|
|
@@ -934,6 +982,15 @@ function Form(props: FormProps, ref: any) {
|
|
|
934
982
|
checkFieldsChanges({ elementHasLostFocus: true });
|
|
935
983
|
}
|
|
936
984
|
|
|
985
|
+
function updateOperationInProgress(value: boolean) {
|
|
986
|
+
parseForm({
|
|
987
|
+
fields,
|
|
988
|
+
arch: arch!,
|
|
989
|
+
values: getCurrentValues(fields),
|
|
990
|
+
operationInProgress: value,
|
|
991
|
+
});
|
|
992
|
+
}
|
|
993
|
+
|
|
937
994
|
async function executeButtonAction({
|
|
938
995
|
type,
|
|
939
996
|
action,
|
|
@@ -955,19 +1012,36 @@ function Form(props: FormProps, ref: any) {
|
|
|
955
1012
|
return;
|
|
956
1013
|
}
|
|
957
1014
|
|
|
1015
|
+
let mustBlockButtons = false;
|
|
1016
|
+
|
|
958
1017
|
try {
|
|
959
1018
|
if (formHasChanges() || getCurrentId() === undefined) {
|
|
960
|
-
|
|
1019
|
+
mustBlockButtons = true;
|
|
1020
|
+
updateOperationInProgress(true);
|
|
1021
|
+
if (submitMode === "2many") {
|
|
1022
|
+
await submitApi({ callOnSubmitSucceed: false });
|
|
1023
|
+
x2manyPendingLink.current = true;
|
|
1024
|
+
} else {
|
|
1025
|
+
await submitForm({ callOnSubmitSucceed: false });
|
|
1026
|
+
}
|
|
961
1027
|
}
|
|
962
1028
|
|
|
1029
|
+
const additionalContext = x2manyPendingLink.current
|
|
1030
|
+
? getActiveIdsContext()
|
|
1031
|
+
: {};
|
|
1032
|
+
|
|
1033
|
+
const updatedContext = { ...context, ...additionalContext };
|
|
1034
|
+
|
|
963
1035
|
if (type === "object") {
|
|
964
|
-
await runObjectButton({ action, context });
|
|
1036
|
+
await runObjectButton({ action, context: updatedContext });
|
|
965
1037
|
} else if (type === "workflow") {
|
|
966
1038
|
await runWorkflowButton({ action });
|
|
967
1039
|
} else if (type === "action") {
|
|
968
|
-
await runActionButton({ action, context });
|
|
1040
|
+
await runActionButton({ action, context: updatedContext });
|
|
969
1041
|
}
|
|
1042
|
+
mustBlockButtons && updateOperationInProgress(false);
|
|
970
1043
|
} catch (err) {
|
|
1044
|
+
mustBlockButtons && updateOperationInProgress(false);
|
|
971
1045
|
showErrorDialog(err);
|
|
972
1046
|
}
|
|
973
1047
|
}
|
|
@@ -297,7 +297,7 @@ function CommonIndicator({
|
|
|
297
297
|
fontSize = maxFontSize;
|
|
298
298
|
}
|
|
299
299
|
|
|
300
|
-
const IconElement: any = icon && iconMapper(icon);
|
|
300
|
+
const IconElement: any = icon && iconMapper(icon, {style: {fontSize: fontSize * 0.7}});
|
|
301
301
|
|
|
302
302
|
return (
|
|
303
303
|
<div
|
|
@@ -373,13 +373,13 @@ function PercentageIndicator({
|
|
|
373
373
|
tw = tw * 1.5;
|
|
374
374
|
}
|
|
375
375
|
|
|
376
|
-
const IconElement: any = icon && iconMapper(icon);
|
|
377
|
-
|
|
378
376
|
if (tw >= width * 0.85 || fontSize * 2 < twoLinesHeight) {
|
|
379
377
|
const maxFontSize = ((width * 0.85) / tw) * fontSize;
|
|
380
378
|
fontSize = maxFontSize;
|
|
381
379
|
}
|
|
382
380
|
|
|
381
|
+
const IconElement: any = icon && iconMapper(icon, {style: {fontSize}});
|
|
382
|
+
|
|
383
383
|
return (
|
|
384
384
|
<div
|
|
385
385
|
ref={measureRef}
|
|
@@ -125,10 +125,11 @@ function SearchTree(props: Props, ref: any) {
|
|
|
125
125
|
colorsForResults,
|
|
126
126
|
statusForResults,
|
|
127
127
|
totalItems,
|
|
128
|
+
getAllIds,
|
|
128
129
|
} = useSearch({
|
|
129
130
|
model: currentModel!,
|
|
130
131
|
setSearchTreeNameSearch,
|
|
131
|
-
setSelectedRowItems,
|
|
132
|
+
setSelectedRowItems: changeSelectedRowKeys,
|
|
132
133
|
setSearchParams,
|
|
133
134
|
setSearchValues,
|
|
134
135
|
searchParams,
|
|
@@ -182,9 +183,9 @@ function SearchTree(props: Props, ref: any) {
|
|
|
182
183
|
setInitialFetchDone(true);
|
|
183
184
|
} catch (error) {
|
|
184
185
|
setInitialError(error);
|
|
186
|
+
setTreeIsLoading?.(false);
|
|
185
187
|
} finally {
|
|
186
188
|
setIsLoading(false);
|
|
187
|
-
setTreeIsLoading?.(false);
|
|
188
189
|
}
|
|
189
190
|
};
|
|
190
191
|
|
|
@@ -269,13 +270,16 @@ function SearchTree(props: Props, ref: any) {
|
|
|
269
270
|
};
|
|
270
271
|
|
|
271
272
|
function changeSelectedRowKeys(selectedRowKeys: any[]) {
|
|
272
|
-
|
|
273
|
-
selectedRowKeys.includes(entry.id)
|
|
274
|
-
);
|
|
275
|
-
setSelectedRowItems?.(selectedRowItems);
|
|
273
|
+
setSelectedRowItems?.(selectedRowKeys.map((id: number) => ({ id })));
|
|
276
274
|
onChangeSelectedRowKeys?.(selectedRowKeys);
|
|
277
275
|
}
|
|
278
276
|
|
|
277
|
+
async function selectAllRecords() {
|
|
278
|
+
const allIds = await getAllIds();
|
|
279
|
+
setSelectedRowItems?.(allIds.map((id: number) => ({ id })));
|
|
280
|
+
onChangeSelectedRowKeys?.(allIds);
|
|
281
|
+
}
|
|
282
|
+
|
|
279
283
|
function calculateTableHeight() {
|
|
280
284
|
if (treeView?.isExpandable) {
|
|
281
285
|
return height - 160;
|
|
@@ -291,12 +295,11 @@ function SearchTree(props: Props, ref: any) {
|
|
|
291
295
|
return (
|
|
292
296
|
<>
|
|
293
297
|
<SearchFilter
|
|
294
|
-
fields={{ ...
|
|
298
|
+
fields={{ ...formView.fields, ...treeView.fields }}
|
|
295
299
|
searchFields={mergeSearchFields([
|
|
296
300
|
formView.search_fields,
|
|
297
301
|
treeView.search_fields,
|
|
298
302
|
])}
|
|
299
|
-
formXml={formView.arch}
|
|
300
303
|
onClear={clear}
|
|
301
304
|
limit={limit}
|
|
302
305
|
offset={offset}
|
|
@@ -332,6 +335,7 @@ function SearchTree(props: Props, ref: any) {
|
|
|
332
335
|
}
|
|
333
336
|
childField={treeView.field_parent}
|
|
334
337
|
rootTree={rootTree}
|
|
338
|
+
onSelectAllRecords={selectAllRecords}
|
|
335
339
|
/>
|
|
336
340
|
</>
|
|
337
341
|
);
|