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.
@@ -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,23 +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
- var _a, _b, _c, _d;
398
438
  try {
399
- return (_jsx(ReactstrapCol, { xs: (_a = this.props.col_xs) !== null && _a !== void 0 ? _a : 12, sm: (_b = this.props.col_sm) !== null && _b !== void 0 ? _b : 12, md: (_c = this.props.col_md) !== null && _c !== void 0 ? _c : 6, lg: (_d = this.props.col_lg) !== null && _d !== void 0 ? _d : 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) => {
400
440
  return this._fieldRendering(field, ii);
401
441
  }) }));
402
442
  }
403
443
  catch (err) {
404
- return (_jsxs(ReactstrapCol, { children: ["Error ", err.message] }));
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(ReactstrapCol, { xs: (_a = this.props.col_xs) !== null && _a !== void 0 ? _a : 12, sm: (_b = this.props.col_sm) !== null && _b !== void 0 ? _b : 12, md: (_c = this.props.col_md) !== null && _c !== void 0 ? _c : 6, lg: (_d = this.props.col_lg) !== null && _d !== void 0 ? _d : 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 }) }));
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(ReactstrapCol, { xs: (_a = this.props.col_xs) !== null && _a !== void 0 ? _a : 12, sm: (_b = this.props.col_sm) !== null && _b !== void 0 ? _b : 12, md: (_c = this.props.col_md) !== null && _c !== void 0 ? _c : 6, lg: (_d = this.props.col_lg) !== null && _d !== void 0 ? _d : 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 }) }));
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(ReactstrapRow, { id: "dsdf_buttons_container", className: "buttons-row", children: [this._cancelButton(), this._submitButton(), this.props.custom_button_caption &&
506
- _jsx(ReactstrapCol, { xs: (_a = this.props.col_xs) !== null && _a !== void 0 ? _a : 12, sm: (_b = this.props.col_sm) !== null && _b !== void 0 ? _b : 12, md: (_c = this.props.col_md) !== null && _c !== void 0 ? _c : 6, lg: (_d = this.props.col_lg) !== null && _d !== void 0 ? _d : 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)
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(ReactstrapCol, { xs: (_e = this.props.col_xs) !== null && _e !== void 0 ? _e : 12, sm: (_f = this.props.col_sm) !== null && _f !== void 0 ? _f : 12, md: (_g = this.props.col_md) !== null && _g !== void 0 ? _g : 6, lg: (_h = this.props.col_lg) !== null && _h !== void 0 ? _h : 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)
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
- var _a;
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, Object.assign({}, props, { ref: innerRef })));
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: any;
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",
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": "",