datasync-dynamic-form 1.0.1 → 1.0.3

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,1067 +0,0 @@
1
- import React, { Component } from "react";
2
- // react plugin that creates an input with badges
3
- {/** Blob must be defined as npm component
4
- <Blob
5
- import Blob from "components/Blob/Blob";*/}
6
- import Multiselect from 'multiselect-react-dropdown';
7
- //Defined as const import {saveDataTierToDatasync} from '../DataSync3/DataSync3.jsx'
8
- //2DO disabled import "./DynamicForm3Tiers2.css"
9
-
10
- // reactstrap components
11
- import {
12
- Button,
13
- Label,
14
- FormGroup,
15
- Input,
16
- InputGroupAddon,
17
- InputGroupText,
18
- InputGroup,
19
- Container,
20
- Row,
21
- Col,
22
- } from "reactstrap";
23
- const debugging = true;
24
- const local = true;
25
- const production = !local;
26
- const globals = {
27
- parameters:{
28
- root_url:"/topics-page",
29
- admin_url:"/authent",
30
- debugging:debugging,
31
- cookie_debugging : true,
32
- master_detail_debugging : true,
33
- local:true,
34
- production:false,
35
- use_navigate : false,
36
- save_failed_alert : false,
37
- form_version : "1.0",
38
- form_modified_version : 2
39
- },
40
- home : {
41
- ...(local && {url : 'http://localhost:3000'}),
42
- ...(production && {url : 'https://www.chainedeprieres.com'})
43
- },
44
-
45
- datasync :{
46
- /*DATASYNC*/
47
- praychain_company_guid:local?"36178327-E810-3A73-A833-8417F639295E":"2EA619F2-2A23-7905-69C7-6ABA65BDF585",
48
- praychain_time_table_guid:local?"CA09A7FB-431C-29A6-A974-72E4F949EC81":"566062CD-30F8-B1E2-DF80-6AB667F466C4",
49
- invitation_table_guid:local?"AE99F45B-9D22-D280-13DA-29B4860C7FEE":"3F92D25C-4223-E5D2-8484-4880B6B83E9A",
50
- praychain_contact_table_guid:local?"E2AEE1AB-838F-A68A-355C-C1A912698002":"0458D1BE-3E8D-049D-09FB-5A8E14F76A53",
51
- praychain_authent_table_guid:local?"B5A0C0AA-200F-B88B-67DE-355D222A6E52":"21A2464D-B413-6A0C-0848-EDA45266DAC0",
52
- praychain_user_table_guid:local?"7841F7FF-1BF9-8716-7C66-BD8C5634E1F6":"1D65037E-9A04-51EB-5CAE-06BCB7BE30AF",
53
- praychain_topics_table_guid:local?"E25E87B5-5E0C-7446-AF58-ECAE4301AE40":"CE2A92BE-47A5-8AAE-7014-64FF5986A2BD",
54
-
55
- /* MAC local */
56
- ...(local && {
57
- syncTestUrl : "http://localhost:8888/datasync-service/test.php",
58
- syncPushUrl : "http://localhost:8888/datasync-service/Sync.php",
59
- syncPushSerializedUrl : "http://localhost:8888/datasync-service/Sync.php",
60
- syncStartUrl: "http://localhost:8888/datasync-service/Sync.php?action=syncStart",
61
- syncDeleteUrl: "http://localhost:8888/datasync-service/Sync.php?action=syncDelete",
62
- syncSeekUrl: "http://localhost:8888/datasync-service/Sync.php?action=syncSeek",
63
- syncStopUrl: "http://localhost:8888/datasync-service/Sync.php?action=syncStop",
64
- syncPullUrl : "http://localhost:8888/datasync-service/Sync.php?action=syncPull",
65
- syncPullSerializedUrl : "http://localhost:8888/datasync-service/Sync.php?action=syncPullSerialized",
66
- syncMobilePullUrl : "http://localhost:8888/datasync-service/Sync.php?action=syncMobilePull",
67
- syncPassThruUrl : "http://localhost:8888/datasync-service/Sync.php?action=syncPassThru"}),
68
-
69
- /* chainedeprieres.com Production Server */
70
- ...(production && {
71
- syncTestUrl : "https://rest.datasync.ovh/test.php",
72
- syncPushUrl : "https://rest.datasync.ovh/Sync.php",
73
- syncPushSerializedUrl : "https://rest.datasync.ovh/Sync.php",
74
- syncStartUrl: "https://rest.datasync.ovh/Sync.php?action=syncStart",
75
- syncDeleteUrl: "http://rest.datasync.ovh/Sync.php?action=syncDelete",
76
- syncSeekUrl: "https://rest.datasync.ovh/Sync.php?action=syncSeek",
77
- syncStopUrl: "https://rest.datasync.ovh/Sync.php?action=syncStop",
78
- syncPullUrl : "https://rest.datasync.ovh/Sync.php?action=syncPull",
79
- syncPullSerializedUrl : "https://rest.datasync.ovh/Sync.php?action=syncPullSerialized",
80
- syncMobilePullUrl : "https://rest.datasync.ovh/Sync.php?action=syncMobilePull",
81
- syncPassThruUrl : "https://rest.datasync.ovh/Sync.php?action=syncPassThru"
82
- })
83
-
84
- }
85
- }
86
-
87
- const randomize = (min, max) => {
88
- return Math.floor(min + Math.random() * (max - min));
89
- }
90
-
91
- const cTimeStamp = () => {
92
- let lDate = new Date();
93
- let l_sTimeStamp = '';
94
-
95
- l_sTimeStamp = 1900 + lDate.getYear();
96
- l_sTimeStamp += '-';
97
- l_sTimeStamp += ('0' + (lDate.getMonth() + 1)).slice(-2);
98
- l_sTimeStamp += '-';
99
- l_sTimeStamp += ('0' + lDate.getDate()).slice(-2);
100
- l_sTimeStamp += ' ';
101
-
102
- l_sTimeStamp += ('0' + lDate.getHours()).slice(-2);
103
- l_sTimeStamp += ('0' + lDate.getMinutes()).slice(-2);
104
- l_sTimeStamp += ('0' + lDate.getSeconds()).slice(-2);
105
-
106
- return (l_sTimeStamp);
107
- }
108
-
109
- /* Prototype : cGUID
110
- * Purpose : Generates a Global Unique ID
111
- * Return : Return GUID
112
- * History : Created on 2015-02-06
113
- *
114
- **/
115
- const CGUID = () => {
116
- let d = new Date().getTime();
117
- let uuid = 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) {
118
- var r = (d + Math.random() * 16) % 16 | 0;
119
- d = Math.floor(d / 16);
120
- return (c === 'x' ? r : (r & 0x3 | 0x8)).toString(16);
121
- });
122
- return uuid;
123
- };
124
-
125
- /**
126
- * Write data_tier form to data blob
127
- */
128
- const saveDataTierToDatasync = async (
129
- p_data_guid,
130
- p_o_data_blob,
131
- p_s_company_guid,
132
- p_s_table_guid,
133
- p_dt_createstamp,
134
- p_dt_updatestamp,
135
- p_dt_deletestamp,
136
- on_save_handler,
137
- on_update_handler,
138
- on_failed_handler,
139
- p_extra_data
140
- ) => {
141
-
142
- if (globals.parameters.debugging_data_tier)
143
- console.log(`10/07:this.data_tier:${JSON.stringify(p_o_data_blob)}`)
144
-
145
- //Post object using DataSyncLayer
146
- //Copy datasync compliant object data from state structure
147
- let formBlobObject = {
148
- data_guid: p_data_guid?p_data_guid:CGUID(),
149
-
150
- data_blob:{
151
- data_tier: p_o_data_blob.data_tier
152
- }}
153
-
154
- if (p_dt_createstamp){
155
- formBlobObject.createstamp = p_dt_createstamp
156
- }
157
-
158
- if (p_dt_updatestamp){
159
- formBlobObject.updatestamp = p_dt_updatestamp
160
- }
161
-
162
- if (p_dt_deletestamp){
163
- formBlobObject.deletestamp = p_dt_deletestamp
164
- }
165
-
166
- let l_o_datasync = Object.assign({}, formBlobObject);
167
-
168
- if (globals.parameters.debugging){
169
- console.log("l_o_datasync to be stored => ", l_o_datasync)
170
- }
171
-
172
- //Set datasync container sytem properties values
173
- //Set user custom data_blob properties values
174
- l_o_datasync.data_blob.modified = globals.parameters.form_modified_version; //ReUse moidified flag as modified version
175
- //and so on...
176
-
177
- //Stringify whole datasync object one more time
178
- let l_s_sync_object_stringified
179
- try{
180
- l_s_sync_object_stringified = JSON.stringify(l_o_datasync).replace(/'/g, "'").replace(/\\n/g, '\\\\n');
181
- if (globals.parameters.debugging)
182
- console.log(`l_s_sync_object_stringified succedeed :${l_s_sync_object_stringified}`)
183
- }
184
- catch(err){
185
- console.error(`l_s_sync_object_stringified:${l_s_sync_object_stringified}`)
186
- alert(`l_s_sync_object_stringified StringiFy failed with error:${err}`)
187
- }
188
-
189
- //Prepare datasync syncPush POST request
190
- const POSTform = new FormData();
191
-
192
- POSTform.append("action", "syncPushSerialized"); //
193
- POSTform.append("company_guid", p_s_company_guid);
194
- POSTform.append("table_guid", p_s_table_guid);
195
-
196
- POSTform.append("data_sync", l_s_sync_object_stringified);
197
-
198
- //SyncPush Data
199
- fetch(`${globals.datasync.syncPushSerializedUrl}`,{method: "POST", body: POSTform})
200
- .then(results => {return results.text();})
201
- .then(
202
- sync_server_response => {
203
- let json_response = JSON.parse(sync_server_response);
204
- if (globals.parameters.debugging)
205
- console.log("json_response ->", json_response)
206
- if (json_response.data_blob){
207
- //Save succedeed
208
- if ((p_data_guid == null) && on_save_handler) on_save_handler(json_response, p_extra_data);
209
- //Update succedeed
210
- if ((p_data_guid != null) && on_update_handler) on_update_handler(json_response, p_extra_data);
211
-
212
- //debugging
213
- if (globals.parameters.debugging){
214
- let data_blob = json_response.data_blob
215
- console.log("data_blob",data_blob)
216
- }
217
- }
218
- else{
219
- //Save or update failed
220
- console.error("DataSync::saveFormToDatasync => Save or update failed")
221
- if (on_failed_handler) on_failed_handler("Internal DataSync save error", p_extra_data);
222
- }
223
- }).catch(err => {alert(`Erreur de sauvegarde ${err}`)})
224
- }
225
-
226
-
227
- const wScrollTo = (pStargetAnchorId) => {
228
- let targetDomAnchor = document.getElementById(pStargetAnchorId)
229
- if (targetDomAnchor)
230
- targetDomAnchor.scrollIntoView({
231
- behavior: "smooth",
232
- block: "start",
233
- inline: "nearest",
234
- });
235
- else{
236
- if (globals.parameters.debugging){
237
- console.log(`wScrollTo failed => ${pStargetAnchorId} not found in DOM !`)
238
- }
239
- }
240
- }
241
-
242
- export class DsDynamicForm extends Component {
243
- constructor (props){
244
- super(props);
245
-
246
- if (globals.parameters.debugging){
247
- console.log("30:DynamicForm3Tiers2::this.props.data_blob",this.props.data_blob)
248
- console.log("30DynamicForm3Tiers::this.props.form",this.props.form)
249
- }
250
-
251
- this.state = {form:{}}
252
- //this.data_blob = {data_tier:{}}
253
- //2DO debug this.data_tier = (this.props.data_blob && this.props.data_blob.data_tier)?this.props.data_blob.data_tier:{}
254
- this.data_blob = (this.props.data_blob && this.props.data_blob.data_tier)?this.props.data_blob:{data_tier:{}}
255
- }
256
-
257
- componentDidMount = () => {
258
- //Component initialization in edit mode
259
- if (this.props.form) {
260
- this.clearForm();
261
- }
262
- }
263
-
264
- componentDidUpdate(prevProps) {
265
- // Typical usage (don't forget to compare props):
266
- if (this.props.form !== prevProps.form) {
267
- //Lookup field props has changed
268
- if (globals.parameters.debugging)
269
- console.log("09/07:componentDidUpdate -> props.form:has changed", this.props.form)
270
- this.clearForm()
271
- }
272
-
273
- if (this.props.data_blob !== prevProps.data_blob) {
274
- //Lookup field props has changed
275
- if (globals.parameters.debugging)
276
- console.log("09/07:componentDidUpdate -> props.data_blob.data_tier:has changed", this.props.data_blob.data_tier)
277
- this.clearForm()
278
- }
279
- }
280
-
281
- clearForm = () => {
282
- /** Duplicate props.form */
283
- let clearObject2 = JSON.parse(JSON.stringify(this.props.form));
284
-
285
- /** set data_tier with (props.foreign_keys + props.data_tier) */
286
- if (this.props.data_blob){
287
- //Set internal data_tier component property
288
- //OBSOLETE this.data_tier = this.props.data_blob.data_tier
289
- if (globals.parameters.debugging) console.log("01:this.props.data_blob ->", this.props.data_blob)
290
- clearObject2.data_tier = this.props.data_blob.data_tier
291
- }
292
- else{
293
- if (globals.parameters.debugging) console.log("01:this.props.data_blob.data_tier unDefined")
294
- clearObject2.data_tier = {} //Set empty data_tier
295
- }
296
-
297
- /** Override data with foreign keys wne props.foreign_key is available */
298
- if (this.props.foreign_keys){
299
- clearObject2.data_tier = Object.assign(clearObject2.data_tier, this.props.foreign_keys)//Dead code to be checked !!!
300
- this.data_blob.data_tier = Object.assign(clearObject2.data_tier, this.props.foreign_keys)//Dead code to be checked !!!
301
- }
302
-
303
-
304
- if (globals.parameters.debugging){
305
- console.log("01:----- clearForm -----")
306
- console.log("01:clearForm::this.props.form->",this.props.form)
307
- console.log("01:clearForm::clearObject2 mixed with data_tier ->",clearObject2)
308
- console.log("01:clearForm::internal this.data_blob ->",this.data_blob)
309
- }
310
-
311
- this.setState({fieldError:[],form:{},captcha1:randomize(0,5), captcha2:randomize(0,5)}, //Clear forced
312
- ()=>{
313
- if (globals.parameters.debugging) console.log("09/07:DynamicForm3Tiers2 state cleansed 2:", this.state)
314
- this.setState({fieldError:[],form:clearObject2})
315
- });
316
- }
317
-
318
- getFieldData = (pFieldObject) => {
319
- /** Return data value form field object */
320
- let nextFieldData = this.data_blob.data_tier[pFieldObject.name]?this.data_blob.data_tier[pFieldObject.name]:"";
321
-
322
- if (globals.parameters.debugging)
323
- console.log("01:getFieldData[", pFieldObject.name ,"] nextFieldData->", nextFieldData)
324
- return nextFieldData
325
- }
326
-
327
- setFieldData = (pFieldObject, value) => {
328
- this.data_blob.data_tier[pFieldObject.name] = value
329
-
330
- if (globals.parameters.debugging)
331
- console.log("01:setFieldData[", pFieldObject.name ,"] value->", value)
332
- console.log("01:setFieldData[", pFieldObject.name ,"] this.data_blob.data_tier ->", this.data_blob.data_tier)
333
- console.log("01:setFieldData[", pFieldObject.name ,"] this.data_blob ->", this.data_blob)
334
- }
335
-
336
- getSelectedFieldValues_V1 = (pFieldObject) => {
337
- return pFieldObject.selected_values?pFieldObject.selected_values:"";
338
- }
339
-
340
- setFieldError = (pFieldObject, value) => {
341
- try{
342
- pFieldObject.err = value;
343
- let nextFieldError = this.state.fieldError;
344
- nextFieldError[pFieldObject.name] = value
345
- this.setState({ fieldError : nextFieldError})
346
- //Scroll form to first erroneous field
347
- wScrollTo(pFieldObject.name)
348
- }
349
- catch(e){
350
- console.log(`Error caught on ${e}`)
351
- }
352
- }
353
-
354
- getFieldError = (pFieldObject) => {
355
- /** Return data value form field object */
356
- try {
357
- return pFieldObject.err?pFieldObject.err:"";
358
- }
359
- catch(e){
360
- return("")
361
- }
362
- }
363
-
364
- _error_label = field => {
365
- return(
366
- <label className="dynamic-form-error">
367
- {this.getfieldErrorLabel(field)}
368
- </label>
369
- )
370
- }
371
-
372
- getfieldErrorLabel = (pFieldObject) => {
373
- return this.getFieldError(pFieldObject)
374
- }
375
-
376
- getFieldLabelTitle = (pFieldObject) => {
377
- return(
378
- <h6 id={pFieldObject.name}>
379
- {pFieldObject.title?pFieldObject.title:pFieldObject.placeholder}
380
- {(pFieldObject.required && !this.props.read_only) && <span className="icon-danger">*</span>}
381
- </h6>
382
- )
383
- }
384
-
385
- getCaptchaFieldLabelTitle = (pFieldObject) => {
386
- return(
387
- <h6 id={pFieldObject.name}>
388
- {`${this.state.captcha1} + ${this.state.captcha2}`}
389
- {pFieldObject.required && <span className="icon-danger">*</span>}
390
- </h6>
391
- )
392
- }
393
-
394
- getFieldData_V1 = (pFieldObject) => {
395
- return(
396
- pFieldObject.value?pFieldObject.value:(pFieldObject.default_value?pFieldObject.default_value:"")
397
- )
398
- }
399
-
400
- getFieldPrompt = (pFieldObject) => {
401
- return(
402
- pFieldObject.placeholder?pFieldObject.placeholder:pFieldObject.title
403
- )
404
- }
405
-
406
- _numeric_field_with_add_on = (field,fa_symbol) => {
407
- return(
408
- <>
409
- {this.getFieldLabelTitle(field)}
410
- <InputGroup className="border-input">
411
- <Input
412
- readOnly={this.props.read_only?this.props.read_only:false}
413
- type={field.input_type}
414
- value={this.getFieldData(field)}
415
- placeholder={field.placeholder}
416
- autocomplete="on"
417
- id={field.name}
418
- name={field.name}
419
- onChange={(e)=>{
420
- e.preventDefault();
421
- this.dynamicInputNumericChangeHandler({event:e, fieldObject:field})}}
422
- />
423
-
424
- {/** Euro symbol */}
425
-
426
- {fa_symbol &&
427
- <InputGroupAddon addonType="append">
428
- <InputGroupText>
429
- <i className={`fa ${fa_symbol}`}/>
430
- </InputGroupText>
431
- </InputGroupAddon>}
432
-
433
- </InputGroup>
434
- {this._error_label(field)}
435
- </>
436
- )
437
- }
438
-
439
- _captcha_field = (field,fa_symbol) => {
440
- return(
441
- <>
442
- {this.getCaptchaFieldLabelTitle(field)}
443
- <InputGroup className="border-input">
444
- <Input
445
- readOnly={this.props.read_only?this.props.read_only:false}
446
- type={field.input_type}
447
- value={this.getFieldData(field)}
448
- placeholder={field.placeholder}
449
- autocomplete="on"
450
- id={field.name}
451
- name={field.name}
452
- onChange={(e)=>{
453
- e.preventDefault();
454
- this.dynamicInputNumericChangeHandler({event:e, fieldObject:field})}}
455
- />
456
- </InputGroup>
457
- {this._error_label(field)}
458
- </>
459
- )
460
- }
461
-
462
- _text_field = field => {
463
- return(
464
- <div>
465
- {this.getFieldLabelTitle(field)}
466
- <Input
467
- readOnly={this.props.read_only?this.props.read_only:false}
468
- type={field.input_type}
469
- value={this.getFieldData(field)}
470
- placeholder={field.placeholder}
471
- autocomplete="off"
472
- onChange={(e)=>{
473
- e.preventDefault();
474
- this.dynamicInputTextChangeHandler({event:e, fieldObject:field})}}
475
- />
476
- {this._error_label(field)}
477
- </div>)
478
- }
479
-
480
- _email_field = field => {
481
- return(
482
- <div>
483
- {this.getFieldLabelTitle(field)}
484
- <Input
485
- readOnly={this.props.read_only?this.props.read_only:false}
486
- type={field.input_type}
487
- value={this.getFieldData(field)}
488
- placeholder={field.placeholder}
489
- pattern="[a-z0-9._%+-]+@[a-z0-9.-]+\.[a-z]{2,4}$"
490
- autocomplete="on"
491
- id={field.name}
492
- name={field.name}
493
- onChange={(e)=>{
494
- e.preventDefault();
495
- this.dynamicInputTextChangeHandler({event:e, fieldObject:field})}}
496
- />
497
- {this._error_label(field)}
498
- </div>)
499
- }
500
-
501
- _memo_field = field => {
502
- return(
503
- <div>
504
- {this.getFieldLabelTitle(field)}
505
- <textarea
506
- className="form-control"
507
- readOnly={this.props.read_only?this.props.read_only:false}
508
- type={field.input_type}
509
- value={this.getFieldData(field)}
510
- placeholder={field.placeholder}
511
- rows={field.rows}
512
- onChange={(e)=>{
513
- e.preventDefault();
514
- this.dynamicInputTextChangeHandler({event:e, fieldObject:field})}}
515
- />
516
- {this._error_label(field)}
517
- </div>)
518
- }
519
-
520
- _combo_field = field => {
521
- return(
522
- <div>
523
- {this.getFieldLabelTitle(field)}
524
- <Multiselect
525
- showArrow
526
- options={field.combo_list}
527
- isObject={false}
528
- displayValue="key"
529
- selectedValues={this.getFieldData(field)?this.getFieldData(field).split(";"):[]}
530
- placeholder= {field.placeholder}
531
- emptyRecordMsg = ""
532
- onSelect = {(selectedList, selectedItem) => {this.setFieldData(field, selectedList.join(";"));}}
533
- onRemove = {(selectedList, selectedItem) => {this.setFieldData(field, selectedList.join(";"));}}
534
- disable = {this.props.read_only}
535
- singleSelect = {true}
536
- />
537
- {this._error_label(field)}
538
- </div>)
539
- }
540
-
541
- _multi_field = field => {
542
- return(
543
- <div>
544
- {this.getFieldLabelTitle(field)}
545
- <Multiselect
546
- showArrow
547
- options={field.combo_list}
548
- isObject={false}
549
- displayValue="key"
550
- selectedValues={this.getFieldData(field)?this.getFieldData(field).split(";"):[]}
551
- placeholder= {field.placeholder}
552
- emptyRecordMsg = ""
553
- onSelect = {(selectedList, selectedItem) => {this.setFieldData(field, selectedList.join(";")); }}
554
- onRemove = {(selectedList, selectedItem) => {this.setFieldData(field, selectedList.join(";")); }}
555
- disable = {this.props.read_only}
556
- singleSelect = {false}
557
- />
558
- {this._error_label(field)}
559
- </div>)
560
- }
561
-
562
- saveFormToDatasyncProcess = () => {
563
- //Everything sounds ok in Form, Go ahead
564
- let hasDataGuid = (this.props.datasync_object && this.props.datasync_object.data_guid)
565
- saveDataTierToDatasync (
566
- hasDataGuid?this.props.datasync_object.data_guid:null, //data_guid
567
- this.data_blob, //p_o_data_blob,
568
- this.props.company_guid,//p_s_company_guid,
569
- this.props.table_guid,//p_s_table_guid,
570
- hasDataGuid?this.props.datasync_object.createstamp:cTimeStamp(), //p_dt_createstamp,
571
- hasDataGuid?cTimeStamp():null,//p_dt_updatestamp,
572
- null,//p_dt_deletestamp,
573
- this.onFormSavedLocalHandler,
574
- this.onFormUpdatedLocalHandler,
575
- this.onFormFailedLocalHandler,
576
- null)
577
- }
578
-
579
- /** Form Handlers */
580
- onClickSubmitFormHandler = async event => {
581
- if (event)
582
- event.preventDefault();
583
-
584
- //Force all fields check
585
- let canSubmit = true
586
-
587
- let iRow = 0;
588
- while(
589
- (iRow < this.state.form.Rows.length)
590
- && (canSubmit)){
591
- let iCol = 0;
592
- while ((iCol < this.state.form.Rows[iRow].Cols.length) && canSubmit){
593
- let ii=0
594
- while(
595
- (ii < this.state.form.Rows[iRow].Cols[iCol].Fields.length)
596
- && (canSubmit &= this.checkValidation(this.state.form.Rows[iRow].Cols[iCol].Fields[ii]))){
597
-
598
- if (globals.parameters.debugging)
599
- console.log(`Fields[${ii}]|${this.state.form.Rows[iRow].Cols[iCol].Fields[ii].name}| canSubmit=${canSubmit}`)
600
-
601
- ii++;
602
- }
603
- iCol++
604
- }
605
- iRow++;
606
- }
607
-
608
- if (globals.parameters.debugging)
609
- console.log("canSubmit:", canSubmit)
610
-
611
- if (!canSubmit) {
612
- let err_message = "Le formulaire comporte des erreurs !"
613
- if (this.props.onFormFailed)
614
- this.props.onFormFailed(err_message)
615
- else
616
- alert(`${err_message}`)
617
- return false;
618
- }
619
-
620
- //Invoke onFormSubmit props
621
-
622
- if (this.props.onFormSubmit){
623
- if (globals.parameters.debugging)
624
- alert("onFormSubmit => filter log with AsyncDebug:: prefixe")
625
- //If props function return false then cancel form submit and do not save !
626
- this.props.onFormSubmit(this.data_blob,this.saveFormToDatasyncProcess)
627
- }
628
- else {
629
- //Call save anyway
630
- this.saveFormToDatasyncProcess()
631
- }
632
-
633
-
634
-
635
- //this.saveFormToDatasync_OLD((this.props.datasync_object && this.props.datasync_object.data_guid)?this.props.datasync_object.data_guid:null);
636
- }
637
-
638
- onFormSavedLocalHandler = (blob) => {
639
- if (this.props.onFormSaved)
640
- this.props.onFormSaved(blob)
641
- else
642
- console.error("DynamicForm3Tiers2.onFormSaved props is not defined !")
643
- //clear form
644
- if (this.props.clearOnSave) this.clearForm()
645
- //Call onTerminated if set by user
646
- if (this.props.onTerminated) this.props.onTerminated()
647
- }
648
-
649
- onFormUpdatedLocalHandler = (blob) => {
650
- if (this.props.onFormUpdated)
651
- this.props.onFormUpdated(blob)
652
- else
653
- console.error("DynamicForm3Tiers2.onFormUpdated props is not defined !")
654
- //clear form
655
- if (this.props.clearOnUpdate) this.clearForm()
656
- //Call onTerminated if set by user
657
- if (this.props.onTerminated) this.props.onTerminated()
658
- }
659
-
660
- onFormFailedLocalHandler = (err) => {
661
- if (this.props.onFormFailed)
662
- this.props.onFormFailed(err)
663
- else {
664
- console.error("DynamicForm3Tiers2.onFormFailed props is not defined !")
665
- alert("Erreur de sauvegarde !!!")
666
- }
667
- }
668
-
669
- checkValidation = (pFieldObject) => {
670
- let fieldName = pFieldObject.name;
671
-
672
- /** Get field properties */
673
- let min = pFieldObject.min_length
674
- let max = pFieldObject.max_length
675
- let fieldValue = this.getFieldData(pFieldObject);
676
- console.log("d3t3:checkValidation fieldValue->", fieldValue)
677
- let errorsFieldName = `err_${fieldName}` /** Error data displayed in dedicated error label, beside input field in Form */
678
- let nextErrors = [];
679
-
680
- if (globals.parameters.debugging)
681
- console.log(`d3t:min:${min} - max:${max}`)
682
-
683
- /** Check basic field validity except combo and radio */
684
- if ((pFieldObject.required) && (fieldValue.trim().length <= 0))
685
- nextErrors.push(`obligatoire`)
686
-
687
- if ((min > 0) && (pFieldObject.required) && (fieldValue.trim().length < min))
688
- nextErrors.push(`trop court.`)
689
-
690
- //Captcha check
691
- if (pFieldObject.input_type.toLowerCase() == "captcha"){
692
- if (parseInt(fieldValue) !== (this.state.captcha1 + this.state.captcha2))
693
- nextErrors.push(`calcul faux !`)
694
- }
695
-
696
- //Email check
697
- if (pFieldObject.input_type.toLowerCase() == "email"){
698
- if (!fieldValue.match(/^([\w.%+-]+)@([\w-]+\.)+([\w]{2,})$/i))
699
- nextErrors.push(`Format de mail incorrect !`)
700
- }
701
-
702
- if ((max > 0) && (fieldValue.trim().length > max))
703
- nextErrors.push(`trop long, ${fieldValue.trim().length - max} caractères en trop.`)
704
- /* Special validation handlers
705
- if (parseInt(this.state[fieldName]) !== (this.state.v1 + this.state.v2))
706
- nextErrors.push(`calcul faux !`)*/
707
-
708
- if (globals.parameters.debugging){
709
- console.log(`d3t:-----------------`)
710
- console.log(`d3t:fieldName => ${fieldName}`)
711
- console.log(`d3t:value => ${fieldValue}`)
712
-
713
- console.log(`errorsFieldName => ${errorsFieldName}`)
714
- console.log(`nextErrors => ${nextErrors}`)
715
- console.log(`nextErrors.length => ${nextErrors.length}`)
716
- }
717
-
718
- //update error field
719
- if (globals.parameters.debugging){
720
- console.log("nextFieldsErrorsArray=>",nextErrors)
721
- }
722
-
723
- this.setFieldError(pFieldObject, nextErrors.join("/"))
724
-
725
- if (globals.parameters.debugging){
726
- console.log(`new fieldError : ${this.getFieldError(pFieldObject)}`)
727
- }
728
-
729
- //set change flag
730
- //nextState.has_changed = true
731
-
732
- //Return validation predicate
733
- return (nextErrors.length === 0) //returns true if no error occurs
734
- }
735
-
736
- dynamicInputTextChangeHandler = (eventObject) => {
737
- if (eventObject && eventObject.event)
738
- eventObject.event.preventDefault();
739
- if (globals.parameters.debugging)
740
- console.log(`d3t:dynamicInputTextChangeHandler eventObject -> `,eventObject)
741
-
742
- this.setFieldData(eventObject.fieldObject, eventObject.event.target.value)
743
-
744
- //Validate field
745
- this.checkValidation(eventObject.fieldObject)
746
- }
747
-
748
- dynamicInputNumericChangeHandler = (eventObject) => {
749
- if (eventObject && eventObject.event)
750
- eventObject.event.preventDefault();
751
- if (globals.parameters.debugging)
752
- console.log(`d3t:dynamicInputNumericChangeHandler ${eventObject.fieldObject.name} Input field has changed`)
753
-
754
- if (
755
- eventObject.event.target.value.length == 0 ||
756
- !isNaN(eventObject.event.target.value) &&
757
- !isNaN(parseFloat(eventObject.event.target.value)))
758
- this.setFieldData(eventObject.fieldObject, eventObject.event.target.value)
759
- else{
760
- if (globals.parameters.debugging)
761
- console.log(`d3t:Value rejected -> ${eventObject.event.target.value}`)
762
- }
763
-
764
- //Validate field
765
- if (globals.parameters.debugging)
766
- console.log(`#${eventObject.fieldObject.name} => ${this.getFieldData(eventObject.fieldObject)}`)
767
-
768
- this.checkValidation(eventObject.fieldObject)
769
- }
770
-
771
- _colRendering = col => {
772
- try{
773
- return(
774
- <Col>
775
- {
776
- col.Fields.map(
777
- (field,ii)=>{
778
- return this._fieldRendering(field, ii)
779
- }
780
- )
781
- }
782
- </Col>
783
- )}
784
- catch(err){
785
- return(<Col>Error {err.message}</Col>)
786
- }
787
- }
788
-
789
- _rowRendering = row => {
790
- try{
791
- return(
792
- <Row>
793
- {
794
- row.Cols.map(
795
- (col,ii)=>{
796
- return(this._colRendering(col))
797
- })
798
- }
799
- </Row>
800
- )}
801
- catch(err){
802
- return(<Col>Error {err.message}</Col>)
803
- }
804
- }
805
-
806
- migrate_field = (pFieldObject, migrated_value) => {
807
- //Set data_tier property with former form value
808
- this.data_blob.data_tier[pFieldObject.name] = migrated_value;
809
- if (globals.parameters.debugging) console.log("09/07:migrate_field -> pFieldObject.name=", pFieldObject.name)
810
- }
811
-
812
- data_tier_migration = (field, ii) => {
813
- if (!this.props.data_blob) return;//Discard migration
814
- return
815
- //data_tier_migration disbled
816
- console.log("09/07:data_tier_migration ### Migration check !!!")
817
- console.log("09/07:this.data_blob.modified ->", (this.data_blob && this.data_blob.modified)?this.data_blob.modified:"null")
818
- //Check if migration required
819
- if ((this.data_blob && this.data_blob.modified) && (this.data_blob.modified < globals.parameters.form_modified_version))
820
- if (globals.parameters.debugging)
821
- console.log("09/07:field needs migration from version 1 to version 2")
822
- else{
823
- if (globals.parameters.debugging)
824
- console.log("09/07:Field is up to date")
825
- //Don't care migration process
826
- return
827
- }
828
-
829
- if (globals.parameters.debugging){
830
- console.log("09/07:data_tier_migration ->", field.input_type)
831
- }
832
-
833
- switch (field.input_type.toLowerCase()){
834
- /** Dynamic fields */
835
- case "checkbox-DISABLED" :
836
- case "checkbox" :
837
- case "blob":
838
- case "email":
839
- case "text":
840
- case "memo":
841
- case "multi":
842
- case "numeric":
843
- case "amount":
844
- case "percent":
845
- case "captcha":
846
- case "textarea":
847
- //Migrate single field
848
- if (globals.parameters.debugging){
849
- console.log("09/07:data_tier_migration single field ->", field.name)
850
- }
851
- this.migrate_field(field, this.getFieldData_V1(field))
852
- break;
853
-
854
- case "combo":
855
- case "radio":
856
- //Migrate selected field
857
- if (globals.parameters.debugging){
858
- console.log("09/07:data_tier_migration selected field ->", field.name)
859
- }
860
- this.migrate_field(field, this.getSelectedFieldValues_V1(field))
861
- break;
862
-
863
- default:
864
- alert("data_tier_migration --> Field type not supported ->" + field.input_type)
865
- }
866
- }
867
-
868
- _fieldRendering = (field, ii) => {
869
- console.log("09/07:_fieldRendering -> data_tier_migration call")
870
- this.data_tier_migration(field, ii)
871
- //Do not display field if empty in read only mode
872
- if (this.props.read_only &&
873
- ((this.getFieldData(field) == null) || (!this.getFieldData(field)) || (this.getFieldData(field).trim().length == 0)))
874
- return (<></>)
875
-
876
- //Do not display hidden field
877
- if (field.hidden && !this.props.show_hidden)
878
- return (<></>)
879
-
880
- switch (field.input_type.toLowerCase()){
881
- /** Dynamic fields */
882
- case "checkbox-DISABLED" :
883
- return(
884
- <FormGroup check>
885
- {/*-- set anchor ID here --*/}
886
- <Label check>
887
- <Input defaultValue="" type="checkbox" readOnly={this.props.read_only?this.props.read_only:false}/>
888
- {field.placeholder}
889
- <span className="form-check-sign" />
890
- </Label>
891
- </FormGroup>
892
- );
893
-
894
- case "checkbox" :
895
- /* Checkbox is override with combobox */
896
- return(
897
- <div>
898
- {this.getFieldLabelTitle(field)}
899
- <Multiselect
900
- showArrow
901
- options={["Oui","Non"]}
902
- isObject={false}
903
- displayValue="key"
904
- selectedValues={this.getFieldData(field)?this.getFieldData(field).split(";"):[]}
905
- placeholder= {field.placeholder}
906
- emptyRecordMsg = ""
907
- onSelect = {(selectedList, selectedItem) => {this.setFieldData(field, selectedList.join(";")); }}
908
- onRemove = {(selectedList, selectedItem) => {this.setFieldData(field, selectedList.join(";")); }}
909
- disable = {this.props.read_only}
910
- singleSelect = {true}
911
- />
912
- {this._error_label(field)}
913
- </div>)
914
-
915
- case "blob":
916
- return(
917
- <>
918
- {this.getFieldLabelTitle(field)}
919
- {/*
920
- <label className="col-md-12 col-form-label">{`${this.getFieldPrompt(field)}:`}</label>
921
- */}
922
- <div className="col-md-10">
923
- {/** Blob must be defined as npm component
924
- <Blob
925
- readOnly={this.props.read_only?this.props.read_only:false}
926
- Caption={`${this.getFieldPrompt(field)} ...`}
927
- data={this.getFieldData(field)}
928
- uploadPicture={(UploadFile) => {this.setFieldData(field,UploadFile.data); this.checkValidation(field)}}
929
- pictureStyle="pic"
930
- buttonStyle = {"btn btn-secondary"}/> */}
931
-
932
- {/* Sticky error label */}
933
- {this._error_label(field)}
934
- </div>
935
- </>
936
- )
937
-
938
- case "email":
939
- return this._email_field(field);
940
-
941
- case "text":
942
- return this._text_field(field);
943
-
944
- case "memo":
945
- return this._memo_field(field);
946
-
947
- case "combo":
948
- case "radio":
949
- return this._combo_field(field);
950
-
951
- case "multi":
952
- return this._multi_field(field);
953
-
954
- case "numeric":
955
- return this._numeric_field_with_add_on(field,"*");
956
-
957
- case "amount":
958
- return this._numeric_field_with_add_on(field,"fa-euro");
959
-
960
- case "percent":
961
- return this._numeric_field_with_add_on(field,"%");
962
-
963
- case "captcha":
964
- return this._captcha_field(field);
965
-
966
- default:
967
- console.log("alert à Malibu");
968
- }
969
- }
970
-
971
- _cancelButton = () => {
972
- let buttonIsHidden = (this.props.read_only || (this.props.buttons_options && this.props.buttons_options.cancel_button_hidden))
973
- let buttonCaption = (this.props.buttons_options && this.props.buttons_options.cancel_button_caption)?this.props.buttons_options.cancel_button_caption:"Annuler"
974
- if (buttonIsHidden) return(<></>)
975
- else{
976
-
977
- return(
978
- <Col md="4" sm="4">
979
- <Button
980
- block
981
- className="btn-round"
982
- color="danger"
983
- outline
984
- type="reset"
985
- onClick = {()=>{this.clearForm()}}
986
- >{buttonCaption}</Button>
987
- </Col>)
988
- }
989
- }
990
-
991
- _submitButton = () => {
992
- let buttonIsHidden = (this.props.read_only || (this.props.buttons_options && this.props.buttons_options.submit_button_hidden))
993
- let buttonCaption = (this.props.buttons_options && this.props.buttons_options.submit_button_caption)?this.props.buttons_options.submit_button_caption:"Soumettre"
994
- if (buttonIsHidden) return(<></>)
995
- else{
996
-
997
- return(
998
- <Col md="4" sm="4">
999
- <Button
1000
- block
1001
- className="btn-round"
1002
- color="danger"
1003
- outline
1004
- type="submit"
1005
- onClick = {()=>{this.onClickSubmitFormHandler()}}
1006
- >{buttonCaption}</Button>
1007
- </Col>)
1008
- }
1009
- }
1010
-
1011
- render = () => {
1012
- return (
1013
- <>
1014
- {!this.state.form &&
1015
- <div>
1016
- <h1>Form loading...</h1>
1017
- </div>}
1018
-
1019
- <form>
1020
- {
1021
- this.state.form &&
1022
- this.state.form.Rows &&
1023
- this.state.form.Rows.map(
1024
- row => {
1025
- return(
1026
- this._rowRendering(row)
1027
- )
1028
- })
1029
- }
1030
- </form>
1031
- <Row className="buttons-row">
1032
- {this._cancelButton()}
1033
-
1034
- {this._submitButton()}
1035
-
1036
- {this.props.custom_button_caption &&
1037
- <Col md="4" sm="4">
1038
- <Button
1039
- block
1040
- className="btn-round"
1041
- color="primary"
1042
- type="submit"
1043
- onClick = {(e) => {if (this.props.custom_button_handler) this.props.custom_button_handler(this.state.form); else console.error("custom_button_handler unset !")}}
1044
- >
1045
- {this.props.custom_button_caption}
1046
- </Button>
1047
- </Col>}
1048
-
1049
- {this.props.custom_button_caption2 &&
1050
- <Col md="4" sm="4">
1051
- <Button
1052
- block
1053
- className="btn-round"
1054
- color="primary"
1055
- type="submit"
1056
- onClick = {(e) => {if (this.props.custom_button_handler2) this.props.custom_button_handler2(this.state.form); else console.error("custom_button_handler2 unset !")}}
1057
- >
1058
- {this.props.custom_button_caption2}
1059
- </Button>
1060
- </Col>}
1061
- </Row>
1062
- </>
1063
- );
1064
- }
1065
- };
1066
-
1067
- export {CGUID}