datasync-dynamic-form 1.3.3 → 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.
@@ -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) => __awaiter(this, void 0, void 0, function* () {
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,22 +426,22 @@ export class DsDynamicForm extends Component {
385
426
  };
386
427
  this._rowRendering = (row) => {
387
428
  try {
388
- return (_jsx(ReactstrapRow, { children: row.Cols.map((col, ii) => {
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(ReactstrapCol, { children: ["Error ", err.message] }));
434
+ return (_jsxs(FlexCol, { children: ["Error ", err.message] }));
394
435
  }
395
436
  };
396
437
  this._colRendering = (col) => {
397
438
  try {
398
- return (_jsx(ReactstrapCol, { xs: "12", sm: "12", md: "6", lg: "4", id: `${col.Id ? col.Id : ''}`, children: col.Fields.map((field, ii) => {
439
+ return (_jsx(FlexCol, { id: `${col.Id ? col.Id : ''}`, children: col.Fields.map((field, ii) => {
399
440
  return this._fieldRendering(field, ii);
400
441
  }) }));
401
442
  }
402
443
  catch (err) {
403
- return (_jsxs(ReactstrapCol, { children: ["Error ", err.message] }));
444
+ return (_jsxs(FlexCol, { children: ["Error ", err.message] }));
404
445
  }
405
446
  };
406
447
  this._fieldRendering = (field, ii) => {
@@ -474,7 +515,7 @@ export class DsDynamicForm extends Component {
474
515
  if (buttonIsHidden)
475
516
  return (_jsx(_Fragment, {}));
476
517
  else {
477
- return (_jsx(ReactstrapCol, { xs: "12", sm: "12", md: "6", lg: "4", children: _jsx(Button, { id: "dsdf_clear_button", block: true, className: "btn-round", color: "danger", outline: true, type: "reset", onClick: () => { this.clearForm(); }, children: buttonCaption }) }));
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 }) }));
478
519
  }
479
520
  };
480
521
  this._submitButton = () => {
@@ -483,7 +524,7 @@ export class DsDynamicForm extends Component {
483
524
  if (buttonIsHidden)
484
525
  return (_jsx(_Fragment, {}));
485
526
  else {
486
- return (_jsx(ReactstrapCol, { xs: "12", sm: "12", md: "6", lg: "4", children: _jsx(Button, { id: "dsdf_submit_button", block: true, className: "btn-round", color: "danger", outline: true, type: "submit", onClick: () => { this.onClickSubmitFormHandler(); }, children: buttonCaption }) }));
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 }) }));
487
528
  }
488
529
  };
489
530
  this.render = () => {
@@ -498,12 +539,12 @@ export class DsDynamicForm extends Component {
498
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) => {
499
540
  return (_jsx("div", { children: this._rowRendering(row) }, rowIndex));
500
541
  }) }, pageIndex));
501
- }) }), _jsxs(ReactstrapRow, { id: "dsdf_buttons_container", className: "buttons-row", children: [this._cancelButton(), this._submitButton(), this.props.custom_button_caption &&
502
- _jsx(ReactstrapCol, { xs: "12", sm: "12", md: "6", lg: "4", children: _jsx(Button, { id: "dsdf_custom_button", block: true, className: "btn-round", color: "primary", type: "submit", onClick: (e) => { if (this.props.custom_button_handler)
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)
503
544
  this.props.custom_button_handler(this.state.form);
504
545
  else
505
546
  console.error("custom_button_handler unset !"); }, children: this.props.custom_button_caption }) }), this.props.custom_button_caption2 &&
506
- _jsx(ReactstrapCol, { xs: "12", sm: "12", md: "6", lg: "4", children: _jsx(Button, { id: "dsdf_custom_button2", block: true, className: "btn-round", color: "primary", type: "submit", onClick: (e) => { if (this.props.custom_button_handler2)
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)
507
548
  this.props.custom_button_handler2(this.state.form);
508
549
  else
509
550
  console.error("custom_button_handler2 unset !"); }, children: this.props.custom_button_caption2 }) })] })] }));
@@ -522,6 +563,9 @@ export class DsDynamicForm extends Component {
522
563
  this.clearForm();
523
564
  }
524
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 });
525
569
  if (globals.parameters.debugging)
526
570
  console.log("active_page has changed !");
527
571
  try {
@@ -548,14 +592,18 @@ export const DsDynamicFormForwardRef = forwardRef((props, ref) => {
548
592
  const innerRef = React.useRef(null);
549
593
  useImperativeHandle(ref, () => ({
550
594
  clearForm: () => {
551
- var _a;
552
- (_a = innerRef.current) === null || _a === void 0 ? void 0 : _a.clearForm();
595
+ innerRef.current?.clearForm();
553
596
  },
554
597
  onClickSubmitFormHandler: (event) => {
555
598
  return innerRef.current
556
599
  ? innerRef.current.onClickSubmitFormHandler(event)
557
600
  : Promise.resolve(false);
558
601
  },
602
+ checkCurrentPage: (event) => {
603
+ return innerRef.current
604
+ ? innerRef.current.checkCurrentPage(event)
605
+ : Promise.resolve(false);
606
+ },
559
607
  }));
560
- return (_jsx(DsDynamicForm, Object.assign({}, props, { ref: innerRef })));
608
+ return (_jsx(DsDynamicForm, { ...props, ref: innerRef }));
561
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;
@@ -97,6 +104,10 @@ interface DsDynamicFormProps {
97
104
  custom_button_handler2?: (form: Form) => void;
98
105
  show_hidden?: boolean;
99
106
  active_page?: number;
107
+ col_xs?: number | string;
108
+ col_sm?: number | string;
109
+ col_md?: number | string;
110
+ col_lg?: number | string;
100
111
  }
101
112
  interface DsDynamicFormState {
102
113
  form: Form;
@@ -140,6 +151,7 @@ export declare class DsDynamicForm extends Component<DsDynamicFormProps, DsDynam
140
151
  saveFormToDatasyncProcess: () => void;
141
152
  /** Form Handlers */
142
153
  onClickSubmitFormHandler: (event?: React.MouseEvent<HTMLButtonElement>) => Promise<boolean>;
154
+ checkCurrentPage: (event?: React.MouseEvent<HTMLButtonElement>) => Promise<boolean>;
143
155
  onFormSavedLocalHandler: (blob: DataBlob) => void;
144
156
  onFormUpdatedLocalHandler: (blob: DataBlob) => void;
145
157
  onFormFailedLocalHandler: (err: string) => void;
@@ -163,6 +175,7 @@ export declare class DsDynamicForm extends Component<DsDynamicFormProps, DsDynam
163
175
  export type DsDynamicFormRef = {
164
176
  clearForm: () => void;
165
177
  onClickSubmitFormHandler: (event?: React.MouseEvent<HTMLButtonElement>) => Promise<boolean>;
178
+ checkCurrentPage: (event?: React.MouseEvent<HTMLButtonElement>) => Promise<boolean>;
166
179
  };
167
- export declare const DsDynamicFormForwardRef: any;
180
+ export declare const DsDynamicFormForwardRef: React.ForwardRefExoticComponent<DsDynamicFormProps & React.RefAttributes<DsDynamicFormRef>>;
168
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.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": "",