@tsed/react-formio 2.3.1 → 2.3.2
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/coverage.json +4 -4
- package/dist/components/actions-table/actionsTable.stories.d.ts +8 -53
- package/dist/components/form-access/formAccess.component.d.ts +2 -13
- package/dist/components/form-access/formAccess.stories.d.ts +3 -44
- package/dist/components/form-control/formControl.component.d.ts +3 -11
- package/dist/components/select/select.component.d.ts +5 -18
- package/dist/components/table/components/defaultCellOperations.component.d.ts +12 -1
- package/dist/components/table/components/defaultOperationButton.component.d.ts +4 -4
- package/dist/components/table/hooks/useOperations.hook.d.ts +2 -2
- package/dist/index.js +1178 -1330
- package/dist/index.js.map +1 -1
- package/dist/index.modern.js +291 -309
- package/dist/index.modern.js.map +1 -1
- package/package.json +11 -8
- package/src/components/__fixtures__/form-actions.json +240 -0
- package/src/components/actions-table/__fixtures__/data.json +12 -0
- package/src/components/actions-table/actionsTable.component.spec.tsx +42 -11
- package/src/components/actions-table/actionsTable.component.tsx +2 -1
- package/src/components/actions-table/actionsTable.stories.tsx +71 -289
- package/src/components/form-access/formAccess.component.tsx +2 -12
- package/src/components/form-access/formAccess.stories.tsx +55 -49
- package/src/components/form-control/formControl.component.tsx +4 -11
- package/src/components/select/select.component.tsx +9 -22
- package/src/components/table/components/defaultCellOperations.component.tsx +17 -4
- package/src/components/table/components/defaultOperationButton.component.tsx +9 -4
- package/src/components/table/hooks/useOperations.hook.tsx +3 -3
- package/dist/package.json +0 -3
|
@@ -1,5 +1,8 @@
|
|
|
1
|
-
import
|
|
1
|
+
import type { Meta, StoryObj } from "@storybook/react";
|
|
2
|
+
import { expect, fn, userEvent, within } from "@storybook/test";
|
|
2
3
|
|
|
4
|
+
import availableActions from "../__fixtures__/form-actions.json";
|
|
5
|
+
import data from "./__fixtures__/data.json";
|
|
3
6
|
import { ActionsTable } from "./actionsTable.component";
|
|
4
7
|
|
|
5
8
|
export default {
|
|
@@ -21,11 +24,6 @@ export default {
|
|
|
21
24
|
type: "boolean"
|
|
22
25
|
}
|
|
23
26
|
},
|
|
24
|
-
isEmpty: {
|
|
25
|
-
control: {
|
|
26
|
-
type: "boolean"
|
|
27
|
-
}
|
|
28
|
-
},
|
|
29
27
|
disableFilters: {
|
|
30
28
|
control: {
|
|
31
29
|
type: "boolean"
|
|
@@ -36,296 +34,80 @@ export default {
|
|
|
36
34
|
type: "boolean"
|
|
37
35
|
}
|
|
38
36
|
},
|
|
39
|
-
tags: {
|
|
40
|
-
control: {
|
|
41
|
-
type: "object"
|
|
42
|
-
}
|
|
43
|
-
},
|
|
44
37
|
onAddAction: {
|
|
45
38
|
action: "onAddAction"
|
|
46
39
|
}
|
|
47
40
|
},
|
|
48
41
|
parameters: {}
|
|
49
|
-
}
|
|
42
|
+
} satisfies Meta<typeof ActionsTable>;
|
|
50
43
|
|
|
51
|
-
|
|
52
|
-
return <ActionsTable {...args} data={args.isEmpty ? [] : args.data} />;
|
|
53
|
-
};
|
|
44
|
+
type Story = StoryObj<typeof ActionsTable>;
|
|
54
45
|
|
|
55
|
-
Sandbox
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
access: { handler: false, method: false }
|
|
111
|
-
},
|
|
112
|
-
{
|
|
113
|
-
name: "resetpass",
|
|
114
|
-
title: "Reset Password",
|
|
115
|
-
description: "Provides a way to reset a password field.",
|
|
116
|
-
defaults: {
|
|
117
|
-
handler: ["after", "before"],
|
|
118
|
-
method: ["form", "create"],
|
|
119
|
-
priority: 0,
|
|
120
|
-
name: "resetpass",
|
|
121
|
-
title: "Reset Password"
|
|
122
|
-
},
|
|
123
|
-
access: { handler: false, method: false }
|
|
124
|
-
},
|
|
125
|
-
{
|
|
126
|
-
name: "save",
|
|
127
|
-
title: "Save Submission",
|
|
128
|
-
description: "Saves the submission into the database.",
|
|
129
|
-
priority: 10,
|
|
130
|
-
defaults: {
|
|
131
|
-
handler: ["before"],
|
|
132
|
-
method: ["create", "update"],
|
|
133
|
-
priority: 10,
|
|
134
|
-
name: "save",
|
|
135
|
-
title: "Save Submission"
|
|
136
|
-
},
|
|
137
|
-
access: { handler: false, method: false }
|
|
138
|
-
},
|
|
139
|
-
{
|
|
140
|
-
name: "login",
|
|
141
|
-
title: "Login",
|
|
142
|
-
description: "Provides a way to login to the application.",
|
|
143
|
-
priority: 2,
|
|
144
|
-
defaults: {
|
|
145
|
-
handler: ["before"],
|
|
146
|
-
method: ["create"],
|
|
147
|
-
priority: 2,
|
|
148
|
-
name: "login",
|
|
149
|
-
title: "Login"
|
|
150
|
-
},
|
|
151
|
-
access: { handler: false, method: false }
|
|
152
|
-
},
|
|
153
|
-
{
|
|
154
|
-
name: "office365contact",
|
|
155
|
-
title: "Office 365 Contacts (Premium)",
|
|
156
|
-
description: "Allows you to integrate into your Office 365 Contacts.",
|
|
157
|
-
priority: 0,
|
|
158
|
-
defaults: {
|
|
159
|
-
handler: ["after"],
|
|
160
|
-
method: ["create", "update", "delete"],
|
|
161
|
-
priority: 0,
|
|
162
|
-
name: "office365contact",
|
|
163
|
-
title: "Office 365 Contacts (Premium)"
|
|
164
|
-
},
|
|
165
|
-
premium: true
|
|
166
|
-
},
|
|
167
|
-
{
|
|
168
|
-
name: "office365calendar",
|
|
169
|
-
title: "Office 365 Calendar (Premium)",
|
|
170
|
-
description: "Allows you to integrate into your Office 365 Calendar.",
|
|
171
|
-
premium: true,
|
|
172
|
-
priority: 0,
|
|
173
|
-
defaults: {
|
|
174
|
-
handler: ["after"],
|
|
175
|
-
method: ["create", "update", "delete"],
|
|
176
|
-
priority: 0,
|
|
177
|
-
name: "office365calendar",
|
|
178
|
-
title: "Office 365 Calendar (Premium)"
|
|
179
|
-
}
|
|
180
|
-
},
|
|
181
|
-
{
|
|
182
|
-
name: "hubspotContact",
|
|
183
|
-
title: "Hubspot Contact (Premium)",
|
|
184
|
-
description: "Allows you to change contact fields in hubspot.",
|
|
185
|
-
priority: 0,
|
|
186
|
-
defaults: {
|
|
187
|
-
handler: ["after"],
|
|
188
|
-
method: ["create"],
|
|
189
|
-
priority: 0,
|
|
190
|
-
name: "hubspotContact",
|
|
191
|
-
title: "Hubspot Contact (Premium)"
|
|
192
|
-
},
|
|
193
|
-
premium: true
|
|
194
|
-
},
|
|
195
|
-
{
|
|
196
|
-
name: "oauth",
|
|
197
|
-
title: "OAuth (Premium)",
|
|
198
|
-
description: "Provides OAuth authentication behavior to this form.",
|
|
199
|
-
priority: 20,
|
|
200
|
-
defaults: {
|
|
201
|
-
handler: ["after"],
|
|
202
|
-
method: ["form", "create"],
|
|
203
|
-
priority: 20,
|
|
204
|
-
name: "oauth",
|
|
205
|
-
title: "OAuth (Premium)"
|
|
206
|
-
},
|
|
207
|
-
premium: true
|
|
208
|
-
},
|
|
209
|
-
{
|
|
210
|
-
name: "ldap",
|
|
211
|
-
title: "LDAP Login (Premium)",
|
|
212
|
-
description: "Provides ldap login.",
|
|
213
|
-
priority: 3,
|
|
214
|
-
defaults: {
|
|
215
|
-
handler: ["before"],
|
|
216
|
-
method: ["create"],
|
|
217
|
-
priority: 3,
|
|
218
|
-
name: "ldap",
|
|
219
|
-
title: "LDAP Login (Premium)"
|
|
220
|
-
},
|
|
221
|
-
premium: true
|
|
222
|
-
},
|
|
223
|
-
{
|
|
224
|
-
name: "googlesheet",
|
|
225
|
-
title: "Google Sheets (Premium)",
|
|
226
|
-
description: "Allows you to integrate data into Google sheets.",
|
|
227
|
-
priority: 0,
|
|
228
|
-
defaults: {
|
|
229
|
-
handler: ["after"],
|
|
230
|
-
method: ["create", "update", "delete"],
|
|
231
|
-
priority: 0,
|
|
232
|
-
name: "googlesheet",
|
|
233
|
-
title: "Google Sheets (Premium)"
|
|
234
|
-
},
|
|
235
|
-
premium: true
|
|
236
|
-
},
|
|
237
|
-
{
|
|
238
|
-
name: "sqlconnector",
|
|
239
|
-
title: "SQL Connector (Premium)",
|
|
240
|
-
description: "Allows you to execute a remote SQL Query via Resquel.",
|
|
241
|
-
priority: 0,
|
|
242
|
-
defaults: {
|
|
243
|
-
handler: ["after"],
|
|
244
|
-
method: ["create", "update", "delete"],
|
|
245
|
-
priority: 0,
|
|
246
|
-
name: "sqlconnector",
|
|
247
|
-
title: "SQL Connector (Premium)"
|
|
248
|
-
},
|
|
249
|
-
premium: true
|
|
250
|
-
},
|
|
251
|
-
{
|
|
252
|
-
name: "jira",
|
|
253
|
-
title: "Jira (Premium)",
|
|
254
|
-
description: "Allows you to create issues within Jira.",
|
|
255
|
-
priority: 0,
|
|
256
|
-
defaults: {
|
|
257
|
-
handler: ["after"],
|
|
258
|
-
method: ["create", "update", "delete"],
|
|
259
|
-
priority: 0,
|
|
260
|
-
name: "jira",
|
|
261
|
-
title: "Jira (Premium)"
|
|
262
|
-
},
|
|
263
|
-
premium: true
|
|
264
|
-
},
|
|
265
|
-
{
|
|
266
|
-
name: "group",
|
|
267
|
-
title: "Group Assignment (Premium)",
|
|
268
|
-
premium: true,
|
|
269
|
-
description: "Provides the Group Assignment capabilities.",
|
|
270
|
-
priority: 5,
|
|
271
|
-
defaults: {
|
|
272
|
-
handler: ["after"],
|
|
273
|
-
method: ["create", "update", "delete"],
|
|
274
|
-
priority: 5,
|
|
275
|
-
name: "group",
|
|
276
|
-
title: "Group Assignment (Premium)"
|
|
46
|
+
export const Sandbox: Story = {
|
|
47
|
+
async play({ canvasElement, args }) {
|
|
48
|
+
const canvas = within(canvasElement);
|
|
49
|
+
|
|
50
|
+
const select = canvas.getByTestId("action-table-select");
|
|
51
|
+
const addButton = canvas.getByTestId("action-table-add");
|
|
52
|
+
|
|
53
|
+
expect(addButton).toHaveAttribute("disabled");
|
|
54
|
+
|
|
55
|
+
await userEvent.selectOptions(select, "save", {
|
|
56
|
+
delay: 100
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
await userEvent.click(addButton);
|
|
60
|
+
|
|
61
|
+
expect(args.onAddAction).toHaveBeenCalledWith("save");
|
|
62
|
+
|
|
63
|
+
const editButton = await canvas.getByRole("button", { name: /Operation button: Edit/i });
|
|
64
|
+
const deleteButton = await canvas.getByRole("button", { name: /Operation button: delete/i });
|
|
65
|
+
|
|
66
|
+
expect(editButton).toBeInTheDocument();
|
|
67
|
+
expect(deleteButton).toBeInTheDocument();
|
|
68
|
+
|
|
69
|
+
await userEvent.click(editButton);
|
|
70
|
+
|
|
71
|
+
expect(args.onClick).toHaveBeenCalledWith(
|
|
72
|
+
args.data[0],
|
|
73
|
+
args.operations!.find(({ action }) => action === "edit")
|
|
74
|
+
);
|
|
75
|
+
|
|
76
|
+
await userEvent.click(deleteButton);
|
|
77
|
+
|
|
78
|
+
expect(args.onClick).toHaveBeenCalledWith(
|
|
79
|
+
args.data[0],
|
|
80
|
+
args.operations!.find(({ action }) => action === "delete")
|
|
81
|
+
);
|
|
82
|
+
},
|
|
83
|
+
args: {
|
|
84
|
+
onAddAction: fn(),
|
|
85
|
+
onClick: fn(),
|
|
86
|
+
availableActions: availableActions.map(({ name, title }) => ({
|
|
87
|
+
label: title,
|
|
88
|
+
value: name
|
|
89
|
+
})),
|
|
90
|
+
data: data as never,
|
|
91
|
+
operations: [
|
|
92
|
+
{
|
|
93
|
+
title: "Edit",
|
|
94
|
+
action: "edit",
|
|
95
|
+
alias: "row",
|
|
96
|
+
path: "/resources/:resourceId/submissions/:submissionId",
|
|
97
|
+
icon: "edit",
|
|
98
|
+
permissionsResolver() {
|
|
99
|
+
return true;
|
|
100
|
+
}
|
|
277
101
|
},
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
defaults: {
|
|
287
|
-
handler: ["after"],
|
|
288
|
-
method: ["create"],
|
|
289
|
-
priority: 0,
|
|
290
|
-
name: "twilioSMS",
|
|
291
|
-
title: "Twilio SMS (Premium)"
|
|
292
|
-
}
|
|
293
|
-
}
|
|
294
|
-
].map(({ name, title }) => ({
|
|
295
|
-
label: title,
|
|
296
|
-
value: name
|
|
297
|
-
})),
|
|
298
|
-
data: [
|
|
299
|
-
{
|
|
300
|
-
_id: "602967600685b2158b24e99a",
|
|
301
|
-
handler: ["before"],
|
|
302
|
-
method: ["create", "update"],
|
|
303
|
-
priority: 10,
|
|
304
|
-
name: "save",
|
|
305
|
-
title: "Save Submission",
|
|
306
|
-
form: "602967600685b24dbe24e999",
|
|
307
|
-
machineName: "tcspjwhsevrzpcd:testForm:save"
|
|
308
|
-
}
|
|
309
|
-
],
|
|
310
|
-
operations: [
|
|
311
|
-
{
|
|
312
|
-
title: "Edit",
|
|
313
|
-
action: "edit",
|
|
314
|
-
alias: "row",
|
|
315
|
-
path: "/resources/:resourceId/submissions/:submissionId",
|
|
316
|
-
icon: "edit",
|
|
317
|
-
permissionsResolver() {
|
|
318
|
-
return true;
|
|
102
|
+
{
|
|
103
|
+
action: "delete",
|
|
104
|
+
path: "/resources/:resourceId/submissions/:submissionId/delete",
|
|
105
|
+
icon: "trash",
|
|
106
|
+
buttonType: "danger",
|
|
107
|
+
permissionsResolver() {
|
|
108
|
+
return true;
|
|
109
|
+
}
|
|
319
110
|
}
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
action: "delete",
|
|
323
|
-
path: "/resources/:resourceId/submissions/:submissionId/delete",
|
|
324
|
-
icon: "trash",
|
|
325
|
-
buttonType: "danger",
|
|
326
|
-
permissionsResolver() {
|
|
327
|
-
return true;
|
|
328
|
-
}
|
|
329
|
-
}
|
|
330
|
-
]
|
|
111
|
+
]
|
|
112
|
+
}
|
|
331
113
|
};
|
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
import
|
|
2
|
-
import React, { PropsWithChildren, ReactElement, useCallback, useEffect, useMemo, useState } from "react";
|
|
1
|
+
import React, { PropsWithChildren, useCallback, useEffect, useMemo, useState } from "react";
|
|
3
2
|
|
|
4
3
|
import type { FormOptions, FormSchema, Submission } from "../../interfaces";
|
|
5
4
|
import { Card } from "../card/card.component";
|
|
@@ -96,7 +95,7 @@ function NamedFormAccess({ name, form, submissions, options, onChange, onSubmit,
|
|
|
96
95
|
);
|
|
97
96
|
}
|
|
98
97
|
|
|
99
|
-
export function FormAccess(props: PropsWithChildren<FormAccessProps>)
|
|
98
|
+
export function FormAccess(props: PropsWithChildren<FormAccessProps>) {
|
|
100
99
|
const { type, form, submissions, options, onChange, onSubmit } = useFormAccess(props);
|
|
101
100
|
|
|
102
101
|
return (
|
|
@@ -155,12 +154,3 @@ export function FormAccess(props: PropsWithChildren<FormAccessProps>): ReactElem
|
|
|
155
154
|
</div>
|
|
156
155
|
);
|
|
157
156
|
}
|
|
158
|
-
|
|
159
|
-
FormAccess.propTypes = {
|
|
160
|
-
type: PropTypes.string.isRequired,
|
|
161
|
-
form: PropTypes.object,
|
|
162
|
-
roles: PropTypes.any,
|
|
163
|
-
children: PropTypes.any,
|
|
164
|
-
options: PropTypes.any,
|
|
165
|
-
onSubmit: PropTypes.func
|
|
166
|
-
};
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import
|
|
1
|
+
import type { Meta, StoryObj } from "@storybook/react";
|
|
2
|
+
import { expect, fn, userEvent, within } from "@storybook/test";
|
|
2
3
|
|
|
3
4
|
import { FormAccess } from "./formAccess.component";
|
|
4
5
|
|
|
@@ -6,17 +7,7 @@ export default {
|
|
|
6
7
|
title: "ReactFormio/FormAccess",
|
|
7
8
|
component: FormAccess,
|
|
8
9
|
argTypes: {
|
|
9
|
-
onSubmit: { action: "onSubmit" }
|
|
10
|
-
actionInfo: {
|
|
11
|
-
control: {
|
|
12
|
-
type: "object"
|
|
13
|
-
}
|
|
14
|
-
},
|
|
15
|
-
options: {
|
|
16
|
-
control: {
|
|
17
|
-
type: "object"
|
|
18
|
-
}
|
|
19
|
-
}
|
|
10
|
+
onSubmit: { action: "onSubmit" }
|
|
20
11
|
},
|
|
21
12
|
parameters: {
|
|
22
13
|
docs: {
|
|
@@ -25,45 +16,60 @@ export default {
|
|
|
25
16
|
}
|
|
26
17
|
}
|
|
27
18
|
}
|
|
28
|
-
}
|
|
19
|
+
} satisfies Meta<typeof FormAccess>;
|
|
29
20
|
|
|
30
|
-
|
|
31
|
-
// @ts-ignore
|
|
32
|
-
return <FormAccess {...args} options={{ template: "tailwind", iconset: "bx" }} />;
|
|
33
|
-
};
|
|
21
|
+
type Story = StoryObj<typeof FormAccess>;
|
|
34
22
|
|
|
35
|
-
Sandbox
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
type: "read_all"
|
|
51
|
-
}
|
|
52
|
-
],
|
|
53
|
-
controller: "",
|
|
54
|
-
properties: {},
|
|
55
|
-
settings: {},
|
|
56
|
-
name: "textField",
|
|
57
|
-
path: "textfield",
|
|
58
|
-
machineName: "tcspjwhsevrzpcd:textField"
|
|
23
|
+
export const Sandbox: Story = {
|
|
24
|
+
play: async ({ canvasElement, args }) => {
|
|
25
|
+
const canvas = within(canvasElement);
|
|
26
|
+
|
|
27
|
+
// Vérifiez que le bouton "Save access" est présent
|
|
28
|
+
const saveButtons = await canvas.getAllByRole("button", { name: /Save access/i });
|
|
29
|
+
const saveButton = saveButtons[0];
|
|
30
|
+
|
|
31
|
+
expect(saveButton).toBeInTheDocument();
|
|
32
|
+
|
|
33
|
+
// Simulez un clic sur le bouton "Save access"
|
|
34
|
+
await userEvent.click(saveButton);
|
|
35
|
+
|
|
36
|
+
// Vérifiez que l'action onSubmit a été appelée
|
|
37
|
+
expect(args.onSubmit).toHaveBeenCalled();
|
|
59
38
|
},
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
_id: "
|
|
39
|
+
args: {
|
|
40
|
+
onSubmit: fn(),
|
|
41
|
+
form: {
|
|
42
|
+
_id: "6023f8fe4b1a2ab9a3aae096",
|
|
43
|
+
type: "form",
|
|
44
|
+
tags: [],
|
|
45
|
+
owner: "5d0797a382461b6656d2c790",
|
|
46
|
+
access: [
|
|
47
|
+
{
|
|
48
|
+
roles: ["5d0797bc872fc747da559858", "5d0797bc872fc71d05559859", "5d0797bc872fc7da3b55985a"],
|
|
49
|
+
type: "read_all"
|
|
50
|
+
}
|
|
51
|
+
],
|
|
52
|
+
submissionAccess: [
|
|
53
|
+
{
|
|
54
|
+
roles: ["5d0797bc872fc747da559858"],
|
|
55
|
+
type: "read_all"
|
|
56
|
+
}
|
|
57
|
+
],
|
|
58
|
+
controller: "",
|
|
59
|
+
properties: {},
|
|
60
|
+
settings: {},
|
|
61
|
+
name: "textField",
|
|
62
|
+
path: "textfield",
|
|
63
|
+
machineName: "tcspjwhsevrzpcd:textField"
|
|
64
64
|
},
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
65
|
+
roles: [
|
|
66
|
+
{
|
|
67
|
+
title: "Administrator",
|
|
68
|
+
_id: "5d0797bc872fc747da559858"
|
|
69
|
+
},
|
|
70
|
+
{ title: "Authenticated", _id: "5d0797bc872fc71d05559859" },
|
|
71
|
+
{ title: "Anonymous", _id: "5d0797bc872fc7da3b55985a" }
|
|
72
|
+
],
|
|
73
|
+
options: { template: "tailwind", iconset: "bx" }
|
|
74
|
+
}
|
|
69
75
|
};
|
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
import classnames from "classnames";
|
|
2
|
-
import
|
|
3
|
-
import React from "react";
|
|
2
|
+
import React, { HTMLAttributes } from "react";
|
|
4
3
|
|
|
5
|
-
export interface FormControlProps {
|
|
4
|
+
export interface FormControlProps<Data = any> {
|
|
6
5
|
name: string;
|
|
6
|
+
value?: Data;
|
|
7
7
|
required?: boolean;
|
|
8
8
|
label?: string;
|
|
9
9
|
className?: string;
|
|
10
|
+
onChange?: (name: string, value: any) => void;
|
|
10
11
|
description?: string | React.ComponentType | any;
|
|
11
12
|
prefix?: JSX.Element | React.ComponentType | any;
|
|
12
13
|
suffix?: JSX.Element | React.ComponentType | any;
|
|
@@ -55,11 +56,3 @@ export function FormControl({
|
|
|
55
56
|
</div>
|
|
56
57
|
);
|
|
57
58
|
}
|
|
58
|
-
|
|
59
|
-
FormControl.propTypes = {
|
|
60
|
-
label: PropTypes.string,
|
|
61
|
-
name: PropTypes.string.isRequired,
|
|
62
|
-
children: PropTypes.any,
|
|
63
|
-
required: PropTypes.bool,
|
|
64
|
-
description: PropTypes.any
|
|
65
|
-
};
|
|
@@ -1,24 +1,20 @@
|
|
|
1
1
|
import Choices from "@formio/choices.js";
|
|
2
2
|
import classnames from "classnames";
|
|
3
|
-
import
|
|
4
|
-
import React, { ReactElement, useEffect, useRef } from "react";
|
|
3
|
+
import React, { HTMLAttributes, ReactElement, useEffect, useRef } from "react";
|
|
5
4
|
|
|
6
5
|
import { getEventValue } from "../../utils/getEventValue";
|
|
7
6
|
import { FormControl, FormControlProps } from "../form-control/formControl.component";
|
|
8
7
|
|
|
9
|
-
export interface SelectProps<
|
|
10
|
-
value?: any;
|
|
8
|
+
export interface SelectProps<Data = any> extends FormControlProps, Omit<HTMLAttributes<HTMLSelectElement>, "onChange" | "prefix"> {
|
|
11
9
|
size?: string;
|
|
12
|
-
onChange?: (name: string, value: any) => void;
|
|
13
10
|
placeholder?: string;
|
|
14
|
-
choices: { label: string; value:
|
|
11
|
+
choices: { label: string; value: Data }[];
|
|
15
12
|
layout?: "html5" | "choicesjs";
|
|
13
|
+
disabled?: boolean;
|
|
16
14
|
multiple?: boolean;
|
|
17
|
-
|
|
18
|
-
[key: string]: any;
|
|
19
15
|
}
|
|
20
16
|
|
|
21
|
-
export function Select<
|
|
17
|
+
export function Select<Data = any>({
|
|
22
18
|
name,
|
|
23
19
|
label,
|
|
24
20
|
size,
|
|
@@ -33,14 +29,14 @@ export function Select<T = any>({
|
|
|
33
29
|
multiple,
|
|
34
30
|
layout,
|
|
35
31
|
...props
|
|
36
|
-
}: SelectProps<
|
|
37
|
-
const ref = useRef<
|
|
32
|
+
}: SelectProps<Data>): ReactElement {
|
|
33
|
+
const ref = useRef<HTMLSelectElement>(null);
|
|
38
34
|
|
|
39
35
|
useEffect(() => {
|
|
40
36
|
let instance: any;
|
|
41
37
|
|
|
42
38
|
if (layout === "choicesjs") {
|
|
43
|
-
instance = new Choices(ref.current, {
|
|
39
|
+
instance = new Choices(ref.current as unknown as HTMLInputElement, {
|
|
44
40
|
removeItemButton: true,
|
|
45
41
|
placeholderValue: placeholder
|
|
46
42
|
});
|
|
@@ -67,8 +63,8 @@ export function Select<T = any>({
|
|
|
67
63
|
{/* eslint-disable-next-line jsx-a11y/no-onchange */}
|
|
68
64
|
<select
|
|
69
65
|
ref={ref}
|
|
70
|
-
{...props}
|
|
71
66
|
data-testid={`select_${name}`}
|
|
67
|
+
{...props}
|
|
72
68
|
className={classnames("form-control", size && `form-control-${size}`)}
|
|
73
69
|
name={name}
|
|
74
70
|
id={name}
|
|
@@ -90,12 +86,3 @@ export function Select<T = any>({
|
|
|
90
86
|
</FormControl>
|
|
91
87
|
);
|
|
92
88
|
}
|
|
93
|
-
|
|
94
|
-
Select.propTypes = {
|
|
95
|
-
label: PropTypes.string,
|
|
96
|
-
name: PropTypes.string.isRequired,
|
|
97
|
-
value: PropTypes.any,
|
|
98
|
-
required: PropTypes.bool,
|
|
99
|
-
onChange: PropTypes.func,
|
|
100
|
-
choices: PropTypes.array.isRequired
|
|
101
|
-
};
|
|
@@ -1,19 +1,32 @@
|
|
|
1
1
|
import React from "react";
|
|
2
2
|
|
|
3
|
-
import { DefaultOperationButton } from "./defaultOperationButton.component";
|
|
3
|
+
import { DefaultOperationButton, OperationButtonProps } from "./defaultOperationButton.component";
|
|
4
4
|
|
|
5
|
-
export
|
|
5
|
+
export interface DefaultCellOperationsProps {
|
|
6
|
+
operations: (OperationButtonProps & {
|
|
7
|
+
OperationButton: typeof DefaultOperationButton;
|
|
8
|
+
permissionsResolver?(data: unknown, ctx: any): boolean;
|
|
9
|
+
})[];
|
|
10
|
+
row: any;
|
|
11
|
+
|
|
12
|
+
onClick: (data: any, action: string) => void;
|
|
13
|
+
ctx: any;
|
|
14
|
+
i18n: (i18n: string) => string;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export function DefaultCellOperations({ operations, row, onClick, ctx, i18n }: DefaultCellOperationsProps) {
|
|
6
18
|
const data = row.original;
|
|
7
19
|
|
|
8
20
|
return (
|
|
9
21
|
<div className='btn-group'>
|
|
10
22
|
{operations
|
|
11
|
-
.filter(({ permissionsResolver }
|
|
12
|
-
.map(({ OperationButton = DefaultOperationButton, ...operation }:
|
|
23
|
+
.filter(({ permissionsResolver }) => !permissionsResolver || permissionsResolver(data, ctx))
|
|
24
|
+
.map(({ OperationButton = DefaultOperationButton, ...operation }, index: number) => {
|
|
13
25
|
return (
|
|
14
26
|
<OperationButton
|
|
15
27
|
key={operation.action}
|
|
16
28
|
{...operation}
|
|
29
|
+
data-testid={`operation-${index}-${operation.action}`}
|
|
17
30
|
onClick={(action: string) => onClick(data, action)}
|
|
18
31
|
data={data}
|
|
19
32
|
i18n={i18n}
|