datasync-dynamic-form 1.3.4 → 1.3.5
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/DsDynamicForm.js +71 -27
- package/dist/flex-grid.css +51 -0
- package/dist/types/DsDynamicForm.d.ts +10 -1
- package/package.json +5 -3
package/dist/DsDynamicForm.js
CHANGED
|
@@ -1,12 +1,3 @@
|
|
|
1
|
-
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
2
|
-
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
3
|
-
return new (P || (P = Promise))(function (resolve, reject) {
|
|
4
|
-
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
5
|
-
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
6
|
-
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
7
|
-
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
8
|
-
});
|
|
9
|
-
};
|
|
10
1
|
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
11
2
|
import React, { Component, useImperativeHandle, forwardRef } from "react";
|
|
12
3
|
import Multiselect from 'multiselect-react-dropdown';
|
|
@@ -15,11 +6,15 @@ import { DsBlob } from "datasync-blob";
|
|
|
15
6
|
import { DsPdf } from "datasync-pdf";
|
|
16
7
|
// reactstrap components
|
|
17
8
|
import { Button, Label, FormGroup, Input, InputGroupText, InputGroup, Row as ReactstrapRow, Col as ReactstrapCol, } from "reactstrap";
|
|
9
|
+
import "./flex-grid.css";
|
|
10
|
+
const FlexRow = ({ className, ...props }) => (_jsx(ReactstrapRow, { className: ["flex-row", className].filter(Boolean).join(" "), ...props }));
|
|
11
|
+
const FlexCol = ({ className, ...props }) => (_jsx(ReactstrapCol, { className: ["flex-col", className].filter(Boolean).join(" "), ...props }));
|
|
18
12
|
const debugging = false;
|
|
19
13
|
const globals = {
|
|
20
14
|
parameters: {
|
|
21
15
|
debugging: debugging,
|
|
22
16
|
local: true,
|
|
17
|
+
production: false,
|
|
23
18
|
use_navigate: false,
|
|
24
19
|
save_failed_alert: false,
|
|
25
20
|
form_version: "1.0",
|
|
@@ -187,8 +182,11 @@ export class DsDynamicForm extends Component {
|
|
|
187
182
|
this.onFormSavedLocalHandler, this.onFormUpdatedLocalHandler, this.onFormFailedLocalHandler, null);
|
|
188
183
|
};
|
|
189
184
|
/** Form Handlers */
|
|
190
|
-
this.onClickSubmitFormHandler = (event) =>
|
|
185
|
+
this.onClickSubmitFormHandler = async (event) => {
|
|
191
186
|
try {
|
|
187
|
+
//Trigger handler as user click submit button in order to animate checking + saving progress bar.
|
|
188
|
+
if (this.props.onBeforeFormSubmit)
|
|
189
|
+
this.props.onBeforeFormSubmit(this.local_data_blob);
|
|
192
190
|
if (event)
|
|
193
191
|
event.preventDefault();
|
|
194
192
|
//Force all fields check
|
|
@@ -247,7 +245,50 @@ export class DsDynamicForm extends Component {
|
|
|
247
245
|
console.error(`onClickSubmitFormHandler raises "${error}"`);
|
|
248
246
|
return false;
|
|
249
247
|
}
|
|
250
|
-
}
|
|
248
|
+
};
|
|
249
|
+
this.checkCurrentPage = async (event) => {
|
|
250
|
+
try {
|
|
251
|
+
/*Trigger typically called from external to check curetn page fields.
|
|
252
|
+
returns true when all fields are correct. User is then allowed to pursue to next page*/
|
|
253
|
+
if (event)
|
|
254
|
+
event.preventDefault();
|
|
255
|
+
//Force all fields check
|
|
256
|
+
let canSubmit = true;
|
|
257
|
+
let firstErrFieldName = null;
|
|
258
|
+
let iPage = this.props.active_page || 0; //Process only current page
|
|
259
|
+
let iRow = 0;
|
|
260
|
+
while (iRow < this.state.form.Pages[iPage].Rows.length) {
|
|
261
|
+
let iCol = 0;
|
|
262
|
+
while (iCol < this.state.form.Pages[iPage].Rows[iRow].Cols.length) {
|
|
263
|
+
let ii = 0;
|
|
264
|
+
while (ii < this.state.form.Pages[iPage].Rows[iRow].Cols[iCol].Fields.length) {
|
|
265
|
+
const field = this.state.form.Pages[iPage].Rows[iRow].Cols[iCol].Fields[ii];
|
|
266
|
+
const isValid = this.checkValidation(field);
|
|
267
|
+
if (!isValid && firstErrFieldName === null) {
|
|
268
|
+
firstErrFieldName = field.name;
|
|
269
|
+
}
|
|
270
|
+
canSubmit = canSubmit && isValid;
|
|
271
|
+
ii++;
|
|
272
|
+
}
|
|
273
|
+
iCol++;
|
|
274
|
+
}
|
|
275
|
+
iRow++;
|
|
276
|
+
}
|
|
277
|
+
if (!canSubmit) {
|
|
278
|
+
let err_message = `La page ${iPage} de formulaire comporte des erreurs !`;
|
|
279
|
+
if (this.props.onFormFailed)
|
|
280
|
+
this.props.onFormFailed(err_message);
|
|
281
|
+
else
|
|
282
|
+
console.error(`checkCurrentPage ${iPage} raises "${err_message}"`);
|
|
283
|
+
return false;
|
|
284
|
+
}
|
|
285
|
+
return canSubmit;
|
|
286
|
+
}
|
|
287
|
+
catch (error) {
|
|
288
|
+
console.error(`checkCurrentPage raises "${error}"`);
|
|
289
|
+
return false;
|
|
290
|
+
}
|
|
291
|
+
};
|
|
251
292
|
this.onFormSavedLocalHandler = (blob) => {
|
|
252
293
|
if (this.props.onFormSaved)
|
|
253
294
|
this.props.onFormSaved(blob);
|
|
@@ -385,23 +426,22 @@ export class DsDynamicForm extends Component {
|
|
|
385
426
|
};
|
|
386
427
|
this._rowRendering = (row) => {
|
|
387
428
|
try {
|
|
388
|
-
return (_jsx(
|
|
429
|
+
return (_jsx(FlexRow, { children: row.Cols.map((col, ii) => {
|
|
389
430
|
return (this._colRendering(col));
|
|
390
431
|
}) }));
|
|
391
432
|
}
|
|
392
433
|
catch (err) {
|
|
393
|
-
return (_jsxs(
|
|
434
|
+
return (_jsxs(FlexCol, { children: ["Error ", err.message] }));
|
|
394
435
|
}
|
|
395
436
|
};
|
|
396
437
|
this._colRendering = (col) => {
|
|
397
|
-
var _a, _b, _c, _d;
|
|
398
438
|
try {
|
|
399
|
-
return (_jsx(
|
|
439
|
+
return (_jsx(FlexCol, { id: `${col.Id ? col.Id : ''}`, children: col.Fields.map((field, ii) => {
|
|
400
440
|
return this._fieldRendering(field, ii);
|
|
401
441
|
}) }));
|
|
402
442
|
}
|
|
403
443
|
catch (err) {
|
|
404
|
-
return (_jsxs(
|
|
444
|
+
return (_jsxs(FlexCol, { children: ["Error ", err.message] }));
|
|
405
445
|
}
|
|
406
446
|
};
|
|
407
447
|
this._fieldRendering = (field, ii) => {
|
|
@@ -470,27 +510,24 @@ export class DsDynamicForm extends Component {
|
|
|
470
510
|
}
|
|
471
511
|
};
|
|
472
512
|
this._cancelButton = () => {
|
|
473
|
-
var _a, _b, _c, _d;
|
|
474
513
|
let buttonIsHidden = (this.props.read_only || (this.props.buttons_options && this.props.buttons_options.cancel_button_hidden)) ? true : false;
|
|
475
514
|
let buttonCaption = (this.props.buttons_options && this.props.buttons_options.cancel_button_caption) ? this.props.buttons_options.cancel_button_caption : "Annuler";
|
|
476
515
|
if (buttonIsHidden)
|
|
477
516
|
return (_jsx(_Fragment, {}));
|
|
478
517
|
else {
|
|
479
|
-
return (_jsx(
|
|
518
|
+
return (_jsx(FlexCol, { children: _jsx(Button, { id: "dsdf_clear_button", block: true, className: "btn-round", color: "danger", outline: true, type: "reset", onClick: () => { this.clearForm(); }, children: buttonCaption }) }));
|
|
480
519
|
}
|
|
481
520
|
};
|
|
482
521
|
this._submitButton = () => {
|
|
483
|
-
var _a, _b, _c, _d;
|
|
484
522
|
let buttonIsHidden = (this.props.read_only || (this.props.buttons_options && this.props.buttons_options.submit_button_hidden)) ? true : false;
|
|
485
523
|
let buttonCaption = (this.props.buttons_options && this.props.buttons_options.submit_button_caption) ? this.props.buttons_options.submit_button_caption : "Soumettre";
|
|
486
524
|
if (buttonIsHidden)
|
|
487
525
|
return (_jsx(_Fragment, {}));
|
|
488
526
|
else {
|
|
489
|
-
return (_jsx(
|
|
527
|
+
return (_jsx(FlexCol, { children: _jsx(Button, { id: "dsdf_submit_button", block: true, className: "btn-round", color: "danger", outline: true, type: "submit", onClick: () => { this.onClickSubmitFormHandler(); }, children: buttonCaption }) }));
|
|
490
528
|
}
|
|
491
529
|
};
|
|
492
530
|
this.render = () => {
|
|
493
|
-
var _a, _b, _c, _d, _e, _f, _g, _h;
|
|
494
531
|
return (_jsxs(_Fragment, { children: [_jsx(_Fragment, {}), !this.state.form &&
|
|
495
532
|
_jsx("div", { children: _jsx("h1", { children: "Form loading..." }) }), !(this.state.form &&
|
|
496
533
|
this.state.form.Pages) &&
|
|
@@ -502,12 +539,12 @@ export class DsDynamicForm extends Component {
|
|
|
502
539
|
return (_jsx("div", { id: `dsdf_page_${pageIndex}`, className: `form-page ${((pageIndex == this.state.active_page) || this.props.read_only) ? "page_visible" : ""}`, children: page.Rows.map((row, rowIndex) => {
|
|
503
540
|
return (_jsx("div", { children: this._rowRendering(row) }, rowIndex));
|
|
504
541
|
}) }, pageIndex));
|
|
505
|
-
}) }), _jsxs(
|
|
506
|
-
_jsx(
|
|
542
|
+
}) }), _jsxs(FlexRow, { id: "dsdf_buttons_container", className: "buttons-row", children: [this._cancelButton(), this._submitButton(), this.props.custom_button_caption &&
|
|
543
|
+
_jsx(FlexCol, { children: _jsx(Button, { id: "dsdf_custom_button", block: true, className: "btn-round", color: "primary", type: "submit", onClick: (e) => { if (this.props.custom_button_handler)
|
|
507
544
|
this.props.custom_button_handler(this.state.form);
|
|
508
545
|
else
|
|
509
546
|
console.error("custom_button_handler unset !"); }, children: this.props.custom_button_caption }) }), this.props.custom_button_caption2 &&
|
|
510
|
-
_jsx(
|
|
547
|
+
_jsx(FlexCol, { children: _jsx(Button, { id: "dsdf_custom_button2", block: true, className: "btn-round", color: "primary", type: "submit", onClick: (e) => { if (this.props.custom_button_handler2)
|
|
511
548
|
this.props.custom_button_handler2(this.state.form);
|
|
512
549
|
else
|
|
513
550
|
console.error("custom_button_handler2 unset !"); }, children: this.props.custom_button_caption2 }) })] })] }));
|
|
@@ -526,6 +563,9 @@ export class DsDynamicForm extends Component {
|
|
|
526
563
|
this.clearForm();
|
|
527
564
|
}
|
|
528
565
|
if (this.props.active_page != prevProps.active_page) {
|
|
566
|
+
//Page is about to change, then triger onPageChanging Handler
|
|
567
|
+
if (this.props.onPageChanging)
|
|
568
|
+
this.props.onPageChanging({ "active_page": prevProps.active_page ?? 0, "next_page": this.props.active_page ?? 0, "last_page": this.state.form.Pages.length - 1 });
|
|
529
569
|
if (globals.parameters.debugging)
|
|
530
570
|
console.log("active_page has changed !");
|
|
531
571
|
try {
|
|
@@ -552,14 +592,18 @@ export const DsDynamicFormForwardRef = forwardRef((props, ref) => {
|
|
|
552
592
|
const innerRef = React.useRef(null);
|
|
553
593
|
useImperativeHandle(ref, () => ({
|
|
554
594
|
clearForm: () => {
|
|
555
|
-
|
|
556
|
-
(_a = innerRef.current) === null || _a === void 0 ? void 0 : _a.clearForm();
|
|
595
|
+
innerRef.current?.clearForm();
|
|
557
596
|
},
|
|
558
597
|
onClickSubmitFormHandler: (event) => {
|
|
559
598
|
return innerRef.current
|
|
560
599
|
? innerRef.current.onClickSubmitFormHandler(event)
|
|
561
600
|
: Promise.resolve(false);
|
|
562
601
|
},
|
|
602
|
+
checkCurrentPage: (event) => {
|
|
603
|
+
return innerRef.current
|
|
604
|
+
? innerRef.current.checkCurrentPage(event)
|
|
605
|
+
: Promise.resolve(false);
|
|
606
|
+
},
|
|
563
607
|
}));
|
|
564
|
-
return (_jsx(DsDynamicForm,
|
|
608
|
+
return (_jsx(DsDynamicForm, { ...props, ref: innerRef }));
|
|
565
609
|
});
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
.flex-row {
|
|
2
|
+
display: flex;
|
|
3
|
+
flex-wrap: wrap;
|
|
4
|
+
gap: 10px;
|
|
5
|
+
margin-bottom: 10px;
|
|
6
|
+
/* Make all .flex-col in a flex-row equal height */
|
|
7
|
+
align-items: stretch;
|
|
8
|
+
/* For multi-line rows, ensure lines use full vertical space */
|
|
9
|
+
align-content: stretch;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
.flex-col {
|
|
13
|
+
flex: 1 1 0;
|
|
14
|
+
/* Fill available vertical space of its flex line */
|
|
15
|
+
height: 100%;
|
|
16
|
+
min-height: 100px;
|
|
17
|
+
border: 3px solid;
|
|
18
|
+
border-radius: 8px;
|
|
19
|
+
display: flex;
|
|
20
|
+
align-items: center;
|
|
21
|
+
justify-content: center;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
.box-next {
|
|
25
|
+
flex: 1 1 0;
|
|
26
|
+
display: flex;
|
|
27
|
+
flex-wrap: wrap;
|
|
28
|
+
align-content: center;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
/* Media query pour 600px : diviser par 2 le nombre de div par ligne */
|
|
32
|
+
@media (max-width: 600px) {
|
|
33
|
+
.box {
|
|
34
|
+
flex: 1 1 calc(50% - 5px);
|
|
35
|
+
max-width: calc(50% - 5px);
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
/* Si une div est seule sur sa ligne, elle prend 100% */
|
|
39
|
+
.box:only-child {
|
|
40
|
+
flex: 1 1 100%;
|
|
41
|
+
max-width: 100%;
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
/* Media query pour 300px : toutes les divs à 100% de la largeur */
|
|
46
|
+
@media (max-width: 300px) {
|
|
47
|
+
.box {
|
|
48
|
+
flex: 1 1 100%;
|
|
49
|
+
max-width: 100%;
|
|
50
|
+
}
|
|
51
|
+
}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import React, { Component, ChangeEvent } from "react";
|
|
2
|
+
import "./flex-grid.css";
|
|
2
3
|
interface Field {
|
|
3
4
|
name: string;
|
|
4
5
|
input_type: string;
|
|
@@ -79,10 +80,16 @@ interface DsDynamicFormProps {
|
|
|
79
80
|
read_only?: boolean;
|
|
80
81
|
foreign_keys?: DataTier;
|
|
81
82
|
onFormChange?: (data: DataTier) => void;
|
|
83
|
+
onBeforeFormSubmit?: (data: DataBlob) => void;
|
|
82
84
|
onFormSubmit?: (data: DataBlob) => void;
|
|
83
85
|
onFormSaved?: (blob: DataBlob) => void;
|
|
84
86
|
onFormUpdated?: (blob: DataBlob) => void;
|
|
85
87
|
onFormFailed?: (error: string) => void;
|
|
88
|
+
onPageChanging?: (pageInfo: {
|
|
89
|
+
active_page: number;
|
|
90
|
+
next_page: number;
|
|
91
|
+
last_page: number;
|
|
92
|
+
}) => void;
|
|
86
93
|
clearOnSave?: boolean;
|
|
87
94
|
clearOnUpdate?: boolean;
|
|
88
95
|
onTerminated?: () => void;
|
|
@@ -144,6 +151,7 @@ export declare class DsDynamicForm extends Component<DsDynamicFormProps, DsDynam
|
|
|
144
151
|
saveFormToDatasyncProcess: () => void;
|
|
145
152
|
/** Form Handlers */
|
|
146
153
|
onClickSubmitFormHandler: (event?: React.MouseEvent<HTMLButtonElement>) => Promise<boolean>;
|
|
154
|
+
checkCurrentPage: (event?: React.MouseEvent<HTMLButtonElement>) => Promise<boolean>;
|
|
147
155
|
onFormSavedLocalHandler: (blob: DataBlob) => void;
|
|
148
156
|
onFormUpdatedLocalHandler: (blob: DataBlob) => void;
|
|
149
157
|
onFormFailedLocalHandler: (err: string) => void;
|
|
@@ -167,6 +175,7 @@ export declare class DsDynamicForm extends Component<DsDynamicFormProps, DsDynam
|
|
|
167
175
|
export type DsDynamicFormRef = {
|
|
168
176
|
clearForm: () => void;
|
|
169
177
|
onClickSubmitFormHandler: (event?: React.MouseEvent<HTMLButtonElement>) => Promise<boolean>;
|
|
178
|
+
checkCurrentPage: (event?: React.MouseEvent<HTMLButtonElement>) => Promise<boolean>;
|
|
170
179
|
};
|
|
171
|
-
export declare const DsDynamicFormForwardRef:
|
|
180
|
+
export declare const DsDynamicFormForwardRef: React.ForwardRefExoticComponent<DsDynamicFormProps & React.RefAttributes<DsDynamicFormRef>>;
|
|
172
181
|
export {};
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "datasync-dynamic-form",
|
|
3
3
|
"description": "Datasync Dynamic Form component",
|
|
4
|
-
"version": "1.3.
|
|
4
|
+
"version": "1.3.5",
|
|
5
5
|
"main": "dist/DsDynamicForm.js",
|
|
6
6
|
"module": "dist/DsDynamicForm.js",
|
|
7
7
|
"types": "dist/types/DsDynamicForm.d.ts",
|
|
@@ -21,14 +21,16 @@
|
|
|
21
21
|
"multiselect-react-dropdown": "^2.0.25",
|
|
22
22
|
"react": ">=18.2.0",
|
|
23
23
|
"reactstrap": ">=8.4.1",
|
|
24
|
-
"typescript": "^5.9.2"
|
|
24
|
+
"typescript": "^5.9.2",
|
|
25
|
+
"@types/react": "^18.2.75",
|
|
26
|
+
"@types/react-dom": "^18.2.25"
|
|
25
27
|
},
|
|
26
28
|
"peerDependencies": {
|
|
27
29
|
"multiselect-react-dropdown": "^2.0.25",
|
|
28
30
|
"react": "^17 || ^18"
|
|
29
31
|
},
|
|
30
32
|
"scripts": {
|
|
31
|
-
"hybrid": "tsc"
|
|
33
|
+
"hybrid": "tsc && cp src/flex-grid.css dist/flex-grid.css"
|
|
32
34
|
},
|
|
33
35
|
"keywords": [],
|
|
34
36
|
"author": "",
|