@aj-shadow/z-abs-complayer-modaldialog-client 0.0.0-aj-beta.221

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.
Files changed (39) hide show
  1. package/.gitattributes +26 -0
  2. package/LICENSE.txt +96 -0
  3. package/README.md +5 -0
  4. package/npm-shrinkwrap.json +13 -0
  5. package/package.json +10 -0
  6. package/project/client/_build/Bundle-CompLayer-Modaldialog-client.bld +38 -0
  7. package/project/client/_build/Client-CompLayer-Modaldialog-client-jsx.bld +10 -0
  8. package/project/client/_build/Client-CompLayer-Modaldialog-client.bld +10 -0
  9. package/project/client/_build/Client-css-CompLayer-Modaldialog-bundle.bld +9 -0
  10. package/project/client/_build/z-abs-complayer-modaldialog-client.prj +36 -0
  11. package/project/client/actions/action-modal-dialog.js +29 -0
  12. package/project/client/css/abstraction_add.css +10 -0
  13. package/project/client/css/modal-dialog-file.css +5 -0
  14. package/project/client/css/modal.css +162 -0
  15. package/project/client/css/modal_body.css +18 -0
  16. package/project/client/css/modal_header.css +11 -0
  17. package/project/client/helper/helper-event-listener.js +29 -0
  18. package/project/client/helper/helper-modal-popover.js +35 -0
  19. package/project/client/helper/input-analyzer.js +47 -0
  20. package/project/client/images/actor-image.jsx +260 -0
  21. package/project/client/images/file-image.jsx +44 -0
  22. package/project/client/images/msg-image.jsx +31 -0
  23. package/project/client/modal-dialog-abstraction-add.jsx +992 -0
  24. package/project/client/modal-dialog-abstraction-properties.jsx +220 -0
  25. package/project/client/modal-dialog-file-add.jsx +183 -0
  26. package/project/client/modal-dialog-file-new.jsx +489 -0
  27. package/project/client/modal-dialog-file-properties.jsx +206 -0
  28. package/project/client/modal-dialog-file-remove.jsx +157 -0
  29. package/project/client/modal-dialog-folder-add.jsx +292 -0
  30. package/project/client/modal-dialog-folder-new.jsx +231 -0
  31. package/project/client/modal-dialog-folder-properties.jsx +237 -0
  32. package/project/client/modal-dialog-folder-remove.jsx +149 -0
  33. package/project/client/modal-dialog-search.jsx +144 -0
  34. package/project/client/modal-dialog-wizard-list.jsx +49 -0
  35. package/project/client/modal-dialog-wizard.jsx +145 -0
  36. package/project/client/modal-dialog-workspace-new.jsx +157 -0
  37. package/project/client/modal-dialog-workspace-open.jsx +306 -0
  38. package/project/client/stores/modal-dialog-store.js +63 -0
  39. package/project/z-abs-complayer-modaldialog-client.tree +41 -0
@@ -0,0 +1,992 @@
1
+
2
+ 'use strict';
3
+
4
+ import HelperEventListener from './helper/helper-event-listener';
5
+ import HelperModalPopover from './helper/helper-modal-popover';
6
+ import InputAnalyzer from './helper/input-analyzer';
7
+ import Modal from 'z-abs-complayer-bootstrap-client/client/modal';
8
+ import ModalHeader from 'z-abs-complayer-bootstrap-client/client/modal-header';
9
+ import ModalBody from 'z-abs-complayer-bootstrap-client/client/modal-body';
10
+ import ModalFooter from 'z-abs-complayer-bootstrap-client/client/modal-footer';
11
+ import Popover from 'z-abs-complayer-bootstrap-client/client/popover';
12
+ import ComponentDocument from 'z-abs-complayer-markup-client/client/react-components/markup/component-document';
13
+ import MarkupDocumentationPage from 'z-abs-complayer-markup-client/client/markup/markup-documentation/markup-documentation-page';
14
+ import ReactComponentBase from 'z-abs-corelayer-client/client/react-component/react-component-base';
15
+ import React from 'react';
16
+
17
+
18
+ export default class ModalDialogAbstractionAdd extends ReactComponentBase {
19
+ constructor(props) {
20
+ super(props, {
21
+ show: false,
22
+ name: '',
23
+ description: '',
24
+ repo: '',
25
+ wizardName: '',
26
+ templateName: '',
27
+ wizard: {
28
+ viewIndex: -1,
29
+ view: '',
30
+ heading: '',
31
+ testDataViews: [],
32
+ optionalViews: new Map()
33
+ },
34
+ valid: false,
35
+ error: false,
36
+ errorText: ''
37
+ });
38
+ this.helperModalPopover = new HelperModalPopover();
39
+ this.inputRef = React.createRef();
40
+ this.inputAnalyzer = new InputAnalyzer(this.props.capitalFirst ? true : false);
41
+ this.eventListener = new HelperEventListener('keydown', this._keyDown.bind(this), true);
42
+ }
43
+
44
+ didMount() {
45
+ this.props.onLoad && this.props.onLoad();
46
+ this.helperModalPopover.didMount();
47
+ }
48
+
49
+ shouldUpdate(nextProps, nextState) {
50
+ return !this.shallowCompare(this.props.result, nextProps.result)
51
+ || !this.shallowCompare(this.props.heading, nextProps.heading)
52
+ || !this.shallowCompare(this.props.nameplaceholder, nextProps.nameplaceholder)
53
+ || !this.shallowCompare(this.props.descriptionplaceholder, nextProps.descriptionplaceholder)
54
+ || !this.shallowCompare(this.props.specialName, nextProps.specialName)
55
+ || !this.shallowCompare(this.props.wizardNames, nextProps.wizardNames)
56
+ || !this.shallowCompare(this.props.templates, nextProps.templates)
57
+ || !this.shallowCompare(this.state, nextState);
58
+ }
59
+
60
+ didUpdate(prevProps, prevState) {
61
+ if(this.state.wizardName !== prevState.wizardName || this.state.templateName !== prevState.templateName || this.props.templates !== prevProps.templates) {
62
+ const template = this._getTemplate(true);
63
+ if(template) {
64
+ if('object' === typeof template) {
65
+ if(template.testDataViews) {
66
+ const testDataValueViews = [];
67
+ const optionalViews = new Map();
68
+ template.testDataViews.forEach((testDataTemplateView) => {
69
+ if('single' === testDataTemplateView.view) {
70
+ const testDataValueView = {
71
+ name: testDataTemplateView.name,
72
+ view: testDataTemplateView.view,
73
+ data: []
74
+ };
75
+ testDataValueViews.push(testDataValueView);
76
+ testDataTemplateView.data.forEach((data) => {
77
+ testDataValueView.data.push({
78
+ name: data.name,
79
+ value: 'preview' !== data.type ? data.value : '',
80
+ include: 'optional:false' === data.include ? false : true,
81
+ preview: 'preview' === data.type,
82
+ valid: data.valid
83
+ });
84
+ });
85
+ }
86
+ else if('optional' === testDataTemplateView.view) {
87
+ const testDataValueOptionalViews = {
88
+ name: testDataTemplateView.name,
89
+ view: testDataTemplateView.view,
90
+ optionalName: testDataTemplateView.optionalName,
91
+ views: []
92
+ };
93
+ testDataValueViews.push(testDataValueOptionalViews);
94
+ if(0 !== testDataTemplateView.views.length) {
95
+ optionalViews.set(testDataTemplateView.optionalName, {
96
+ name: testDataTemplateView.views[0].name,
97
+ index: 0
98
+ });
99
+ }
100
+ testDataTemplateView.views.forEach((view) => {
101
+ const testDataValueViews = {
102
+ name: view.name,
103
+ data: []
104
+ };
105
+ testDataValueOptionalViews.views.push(testDataValueViews);
106
+ testDataValueViews.name = view.name;
107
+ view.data.forEach((data) => {
108
+ testDataValueViews.data.push({
109
+ name: data.name,
110
+ value: 'preview' !== data.type ? data.value : '',
111
+ include: 'optional:false' === data.include ? false : true,
112
+ preview: 'preview' === data.type,
113
+ valid: data.valid
114
+ });
115
+ });
116
+ });
117
+ }
118
+ else if('plugin' === testDataTemplateView.view) {
119
+ ddb.error('plugin not implemented');
120
+ }
121
+ });
122
+ if('single' === template.testDataViews[0].view
123
+ || 'optional' === template.testDataViews[0].view
124
+ || 'plugin' === template.testDataViews[0].view) {
125
+ this.updateState({wizard: {
126
+ viewIndex: {$set: 0},
127
+ view: {$set: template.testDataViews[0].view},
128
+ heading: {$set: template.testDataViews[0].name},
129
+ testDataViews: {$set: testDataValueViews},
130
+ optionalViews: {$set: optionalViews}
131
+ }});
132
+ }
133
+ else {
134
+ this.updateState({wizard: {
135
+ viewIndex: {$set: -1},
136
+ view: {$set: ''},
137
+ heading: {$set: ''},
138
+ testDataViews: {$set: []}
139
+ }});
140
+ }
141
+ }
142
+ }
143
+ else if('string' === typeof template) {
144
+ this.updateState({templateName: {$set: template}});
145
+ }
146
+ }
147
+ }
148
+ }
149
+
150
+ willUnmount() {
151
+ this.eventListener.exit();
152
+ }
153
+
154
+ show() {
155
+ this.updateState({show: {$set: true}});
156
+ this.updateState({name: {$set: ''}});
157
+ this.updateState({description: {$set: ''}});
158
+ this.updateState({repo: {$set: 'actorjs-data-local'}});
159
+ this.updateState({wizardName: {$set: this.props.wizardNames && 1 <= this.props.wizardNames.length ? this.props.wizardNames[0] : ''}});
160
+ this.updateState({templateName: {$set: ''}});
161
+ this.updateState({wizard: {
162
+ viewIndex: {$set: -1},
163
+ view: {$set: ''},
164
+ heading: {$set: ''},
165
+ testDataViews: {$set: []}
166
+ }});
167
+ this.updateState({valid: {$set: false}});
168
+ this.updateState({error: {$set: false}});
169
+ this.updateState({errorText: {$set: ''}});
170
+ this.eventListener.init();
171
+ }
172
+
173
+ hide() {
174
+ this.eventListener.exit();
175
+ this.updateState({
176
+ show: {$set: false},
177
+ valid: {$set: false}
178
+ });
179
+ }
180
+
181
+ _keyDown(e) {
182
+ if(!e.ctrlKey && !e.shiftKey && 'Enter' === e.key) {
183
+ if(!this.state.error && this.state.valid) {
184
+ e.preventDefault();
185
+ this.add();
186
+ this.hide();
187
+ }
188
+ }
189
+ else if(e.ctrlKey && e.shiftKey && 'C' === e.key) {
190
+ e.preventDefault();
191
+ this.clear();
192
+ this.hide();
193
+ }
194
+ }
195
+
196
+ add() {
197
+ if('tc' === this.props.type) {
198
+ this.props.onAdd && this.props.onAdd(this.state.name, this.state.description, this.state.wizardName, this.state.templateName, this.state.wizard.testDataViews);
199
+ }
200
+ else if('ts' === this.props.type || 'fut' === this.props.type || 'repo' === this.props.type) {
201
+ this.props.onAdd && this.props.onAdd(this.state.name, this.state.description);
202
+ }
203
+ else if('sut' === this.props.type) {
204
+ this.props.onAdd && this.props.onAdd(this.state.name, this.state.description, this.state.repo);
205
+ }
206
+ }
207
+
208
+ clear() {
209
+ this.props.onClear && this.props.onClear();
210
+ }
211
+
212
+ renderErrorMessage() {
213
+ if(this.state.error) {
214
+ const errorDivStyle = {
215
+ float: 'left',
216
+ textAlign: 'left',
217
+ width: 440
218
+ };
219
+ const labelStyle = {
220
+ top: '6px',
221
+ position: 'relative'
222
+ };
223
+ return (
224
+ <div style={errorDivStyle}>
225
+ <p className="text-danger control-label modal_body_p_as_label" style={labelStyle}>{this.state.errorText}</p>
226
+ </div>
227
+ );
228
+ }
229
+ else if(this.props.result.code !== 'success') {
230
+ const errorDivStyle = {
231
+ float: 'left',
232
+ textAlign: 'left',
233
+ width: 440
234
+ };
235
+ const labelStyle = {
236
+ top: '6px',
237
+ position: 'relative'
238
+ };
239
+ return (
240
+ <div style={errorDivStyle}>
241
+ <p className="text-danger control-label modal_body_p_as_label" style={labelStyle}>{this.props.result.msg}</p>
242
+ </div>
243
+ );
244
+ }
245
+ }
246
+
247
+ renderRepoOptions() {
248
+ const repos = [...this.props.repos];
249
+ repos.sort((a, b) => {
250
+ if('actorjs-data-local' === a || 'actorjs-data-global' === b) {
251
+ return -1;
252
+ }
253
+ else if('actorjs-data-local' === b || 'actorjs-data-global' === a) {
254
+ return 1;
255
+ }
256
+ else if(a < b) {
257
+ return -1;
258
+ }
259
+ else if(a > b) {
260
+ return 1;
261
+ }
262
+ else {
263
+ return 0;
264
+ }
265
+ });
266
+ return repos.map((repo, index) => {
267
+ return (
268
+ <option key={index} value={repo}>{repo}</option>
269
+ );
270
+ });
271
+ }
272
+
273
+ renderRepo() {
274
+ if(this.props.repos) {
275
+ return (
276
+ <>
277
+ <br />
278
+ <div className="row" style={{textAlign: 'right'}}>
279
+ <div className={ModalDialogAbstractionAdd.COLUMN_LIST_START}>
280
+ <label htmlFor="modal_dialog_abstraction_add_repo" className="control-label">Repo</label>
281
+ </div>
282
+ <div className={ModalDialogAbstractionAdd.COLUMN_LIST_END}>
283
+ <select className="form-control input-sm" id="modal_dialog_abstraction_add_repo" value={this.state.repo}
284
+ onChange={(e) => {
285
+ this.updateState({repo: {$set: e.target.value}});
286
+ }}
287
+ >
288
+ {this.renderRepoOptions()}
289
+ </select>
290
+ </div>
291
+ </div>
292
+ </>
293
+ );
294
+ }
295
+ }
296
+
297
+ renderDescription() {
298
+ const id = 'modal_dialog_abstraction_add_description' + (this.props.id ? '_' + this.props.id : '');
299
+ return (
300
+ <>
301
+ <br />
302
+ <div className="row" style={{textAlign: 'right'}}>
303
+ <div className={ModalDialogAbstractionAdd.COLUMN_LIST_START}>
304
+ <label htmlFor={id} className="control-label">Description</label>
305
+ </div>
306
+ <div className={ModalDialogAbstractionAdd.COLUMN_LIST_END}>
307
+ <input type="text" id={id} className="form-control input-sm" value={this.state.description} placeholder={this.props.descriptionplaceholder}
308
+ onChange={(e) => {
309
+ this.updateState({description: {$set: e.target.value}});
310
+ }}
311
+ />
312
+ </div>
313
+ </div>
314
+ </>
315
+ );
316
+ }
317
+
318
+ renderWizardOptions() {
319
+ return this.props.wizardNames.map((wizardName, index) => {
320
+ return (
321
+ <option key={index} value={wizardName}>{wizardName}</option>
322
+ );
323
+ });
324
+ }
325
+
326
+ renderWizard() {
327
+ if(this.props.wizardNames && 0 !== this.props.wizardNames.length) {
328
+ return (
329
+ <>
330
+ <br />
331
+ <div className="row" style={{textAlign: 'right'}}>
332
+ <div className={ModalDialogAbstractionAdd.COLUMN_LIST_START}>
333
+ <label htmlFor="modal_dialog_abstraction_add_wizard" className="control-label">Wizard</label>
334
+ </div>
335
+ <div className={ModalDialogAbstractionAdd.COLUMN_LIST_END}>
336
+ <select id="modal_dialog_abstraction_add_wizard" className="form-control input-sm" value={this.state.wizardName}
337
+ onChange={(e) => {
338
+ const wizardName = e.target.value;
339
+ this.updateState({wizardName: {$set: wizardName}});
340
+ this.updateState({templateName: {$set: ''}});
341
+ this.updateState({wizard: {
342
+ viewIndex: {$set: -1},
343
+ view: {$set: ''},
344
+ heading: {$set: ''},
345
+ testDataViews: {$set: []}
346
+ }});
347
+ }}
348
+ >
349
+ {this.renderWizardOptions()}
350
+ </select>
351
+ </div>
352
+ </div>
353
+ </>
354
+ );
355
+ }
356
+ }
357
+
358
+ renderTemplateOptions() {
359
+ const templates = this.props.templates.get(this.state.wizardName);
360
+ const options = [];
361
+ let index = -1;
362
+ templates.forEach((template, displayName) => {
363
+ options.push(
364
+ <option key={++index} value={displayName}>{displayName}</option>
365
+ );
366
+ });
367
+ return options;
368
+ }
369
+
370
+ renderTemplate(template) {
371
+ if(this.props.wizardNames && 0 !== this.props.wizardNames.length && 'none' !== this.state.wizardName) {
372
+ if(template) {
373
+ return (
374
+ <>
375
+ <br />
376
+ <div className="row" style={{textAlign: 'right'}}>
377
+ <div className={ModalDialogAbstractionAdd.COLUMN_LIST_START}>
378
+ <label htmlFor="modal_dialog_abstraction_add_template" className="control-label">Template</label>
379
+ </div>
380
+ <div className={ModalDialogAbstractionAdd.COLUMN_LIST_END}>
381
+ <select id="modal_dialog_abstraction_add_template" className="form-control input-sm" value={template.displayName}
382
+ onChange={(e) => {
383
+ const templateName = e.target.value;
384
+ this.updateState({templateName: {$set: templateName}});
385
+ this.updateState({wizard: {
386
+ viewIndex: {$set: -1},
387
+ view: {$set: ''},
388
+ heading: {$set: ''},
389
+ testDataViews: {$set: []}
390
+ }});
391
+ }}
392
+ >
393
+ {this.renderTemplateOptions()}
394
+ </select>
395
+ </div>
396
+ </div>
397
+ </>
398
+ );
399
+ }
400
+ }
401
+ }
402
+
403
+ renderMarkup(template) {
404
+ const document = MarkupDocumentationPage.parse(template ? template.markup : (this.props.defaultMarkup ? this.props.defaultMarkup.markup : ''));
405
+ const style = {marginTop:'-16px'};
406
+ if(!template && this.props.defaultMarkup) {
407
+ Object.assign(style, this.props.defaultMarkup.markupStyle);
408
+ }
409
+ return (
410
+ <div style={style}>
411
+ <ComponentDocument document={document} waitMount></ComponentDocument>
412
+ </div>
413
+ );
414
+ }
415
+
416
+ renderTestDataHeading(heading) {
417
+ return (
418
+ <>
419
+ <div className="modal_abstraction_add_test_data_heading">
420
+ <div className={`modal_abstraction_add_test_data_heading_inner ${ModalDialogAbstractionAdd.COLUMN_TEST_DATA_START}`}>
421
+ <p className="control-label modal_body_p_as_label">{heading}</p>
422
+ </div>
423
+ </div>
424
+ </>
425
+ );
426
+ }
427
+
428
+ _getPreviewValue(name, prefixes, testDataValueView) {
429
+ const foundValue = testDataValueView.data.find((data) => {
430
+ return data.name === name;
431
+ });
432
+ if(foundValue && foundValue.include) {
433
+ if(prefixes) {
434
+ const foundPrefix = prefixes.find((prefix) => {
435
+ return prefix[0] === name;
436
+ });
437
+ if(foundPrefix) {
438
+ return foundPrefix[1] + foundValue.value;
439
+ }
440
+ }
441
+ return foundValue.value;
442
+ }
443
+ else {
444
+ return '';
445
+ }
446
+ }
447
+
448
+ _setPreviewValue(name, testDataValueView, value, valid) {
449
+ const foundValue = testDataValueView.data.find((data) => {
450
+ return data.name === name;
451
+ });
452
+ if(foundValue) {
453
+ foundValue.value = value;
454
+ foundValue.valid = valid;
455
+ }
456
+ }
457
+
458
+ _formatPreview(previewFormat, prefixes, testDataValueView) {
459
+ const regexp = /\${([^}]*)}/g;
460
+ const formatters = [...previewFormat.matchAll(regexp)];
461
+ let preview = previewFormat;
462
+ formatters.forEach((formatter) => {
463
+ const value = this._getPreviewValue(formatter[1], prefixes, testDataValueView);
464
+ preview = preview.replace(formatter[0], value);
465
+ });
466
+ return preview;
467
+ }
468
+
469
+ _validate(testDataTemplate, name, preview) {
470
+ if(!testDataTemplate.validate) {
471
+ return 0; // NONE
472
+ }
473
+ else {
474
+ try {
475
+ return new Function('name', 'preview', testDataTemplate.validate)(name, preview);
476
+ }
477
+ catch(err) {
478
+ ddb.error(err);
479
+ return 3; // ERROR
480
+ }
481
+ }
482
+ }
483
+
484
+ _getValidDivClass(valid) {
485
+ switch(valid) {
486
+ case 0:
487
+ return '';
488
+ case 1:
489
+ return 'has-success';
490
+ case 2:
491
+ return 'has-warning';
492
+ case 3:
493
+ return 'has-error';
494
+ }
495
+ }
496
+
497
+ _getValidInputClass(valid) {
498
+ switch(valid) {
499
+ case 0:
500
+ return '';
501
+ case 1:
502
+ return 'alert alert-success';
503
+ case 2:
504
+ return 'alert alert-warning';
505
+ case 3:
506
+ return 'alert alert-danger';
507
+ }
508
+ }
509
+
510
+ _updatePreview(testDataTemplateView, testDataValueView) {
511
+ testDataValueView.data.forEach((testDataValue) => {
512
+ if(testDataValue.preview) {
513
+ const foundTestDataTemplate = testDataTemplateView.data.find((testDataTemplate) => {
514
+ return testDataTemplate.name === testDataValue.name;
515
+ });
516
+ if(foundTestDataTemplate) {
517
+ const preview = this._formatPreview(foundTestDataTemplate.value, foundTestDataTemplate.prefixes, testDataValueView);
518
+ const valid = this._validate(foundTestDataTemplate, testDataValue.name, preview);
519
+ this._setPreviewValue(testDataValue.name, testDataValueView, preview, valid);
520
+ }
521
+ }
522
+ });
523
+ }
524
+
525
+ renderInputTextarea(testDataTemplate, testDataTemplateView, testDataValue, testDataValueView, index) {
526
+ const foundTestDataValue = testDataValueView.data.find((testDataValue) => {
527
+ return testDataTemplate.name === testDataValue.name;
528
+ });
529
+ const absoluteStyleInner = {
530
+ position: 'relative',
531
+ marginBottom: '8px'
532
+ };
533
+ const textAreaStyle = {
534
+ position: 'relative',
535
+ top: '2px',
536
+ left: '6px',
537
+ overflow: 'auto',
538
+ resize: 'none',
539
+ display: 'block',
540
+ margin: '0px',
541
+ padding: '4px',
542
+ fontFamily: 'Menlo, Monaco, Consolas, \"Courier New\", monospace',
543
+ fontSize: '100%',
544
+ width: 'calc(100% - 12px)',
545
+ lineHeight: 1.09,
546
+ height: '100%'
547
+ };
548
+ return (
549
+ <div key={`value_${index}`} style={absoluteStyleInner}>
550
+ <textarea id={this.props.id} className="form-control" style={textAreaStyle} value={testDataValue.value} rows={testDataTemplate.rows} wrap="off"
551
+ onChange={(e) => {
552
+ const value = e.target.value;
553
+ testDataValue.value = value;
554
+ this._updatePreview(testDataTemplateView, testDataValueView);
555
+ this.updateState({wizard: {testDataViews: {$set: this.state.wizard.testDataViews}}});
556
+ }}
557
+ />
558
+ </div>
559
+ );
560
+ }
561
+
562
+ renderInputText(testDataTemplate, testDataTemplateView, testDataValue, testDataValueView, index) {
563
+ const foundTestDataValue = testDataValueView.data.find((testDataValue) => {
564
+ return testDataTemplate.name === testDataValue.name;
565
+ });
566
+ const idCheckbox = 'modal_dialog_abstraction_input_checkbox' + (this.props.id ? '_' + this.props.id : '');
567
+ const idText = 'modal_dialog_abstraction_input_text' + (this.props.id ? '_' + this.props.id : '');
568
+ return (
569
+ <div className="col_sm_8">
570
+ <div className={`input-group ${this._getValidDivClass(foundTestDataValue.valid)}`} style={{marginRight:'4px'}}>
571
+ <span className="input-group-addon">
572
+ <input type="checkbox" id={idCheckbox} defaultChecked={testDataValue.include} disabled={!testDataTemplate.include || !testDataTemplate.include.startsWith('optional:')} aria-label="..." onChange={(e) => {
573
+ const checked = e.target.checked;
574
+ testDataValue.include = checked;
575
+ this._updatePreview(testDataTemplateView, testDataValueView);
576
+ this.updateState({wizard: {testDataViews: {$set: this.state.wizard.testDataViews}}});
577
+ }}
578
+ />
579
+ </span>
580
+ <input type="text" id={idText} className={`form-control input-sm ${this._getValidInputClass(foundTestDataValue.valid)}`} id={`modal_dialog_abstraction_add_input_text_${index}`} value={testDataValue.value} placeholder={testDataTemplate.placeHolder} disabled={!testDataValue.include}
581
+ onChange={(e) => {
582
+ const value = e.target.value.trim();
583
+ const foundTestDataTemplate = testDataTemplateView.data.find((testDataTemplate) => {
584
+ return testDataTemplate.name === testDataValue.name;
585
+ });
586
+ const valid = this._validate(foundTestDataTemplate, testDataValue.name, value);
587
+ testDataValue.value = value;
588
+ testDataValue.valid = valid;
589
+ this._updatePreview(testDataTemplateView, testDataValueView);
590
+ this.updateState({wizard: {testDataViews: {$set: this.state.wizard.testDataViews}}});
591
+ }}
592
+ />
593
+ </div>
594
+ </div>
595
+ );
596
+ }
597
+
598
+ renderInputRadio(testDataTemplate, testDataTemplateView, testDataValue, testDataValueView, index) {
599
+ const radios = testDataTemplate.values.map((value, i) => {
600
+ const radioId = `modal_dialog_abstraction_add_input_radio_${index}_${i}`;
601
+ const currentIndex = i;
602
+ return (
603
+ <div key={i} className="col_sm_4 input_column" style={{textAlign:'left',paddingTop:'3px',width:'auto'}}>
604
+ <input type="radio" id={radioId} style={{position:'relative',top:'1px'}} aria-label="..." checked={testDataTemplate.values[currentIndex] === testDataValue.value} onChange={(e) => {
605
+ testDataValue.value = testDataTemplate.values[currentIndex];
606
+ this._updatePreview(testDataTemplateView, testDataValueView);
607
+ this.updateState({wizard: {testDataViews: {$set: this.state.wizard.testDataViews}}});
608
+ }}/>
609
+ <label htmlFor={radioId} style={{paddingLeft:'4px'}}>{value}</label>
610
+ </div>
611
+ );
612
+ });
613
+ return (
614
+ <div className="col_sm_8">
615
+ {radios}
616
+ </div>
617
+ );
618
+ }
619
+
620
+ renderInputCheckbox(testDataTemplate, testDataTemplateView, testDataValue, testDataValueView, index) {
621
+ const checkboxId = `modal_dialog_abstraction_add_input_checkbox_${index}`;
622
+ return (
623
+ <div className="col_sm_8">
624
+ <div className="col_sm_4 input_column" style={{textAlign:'left',paddingTop:'5px',width:'auto'}}>
625
+ <input type="checkbox" id={checkboxId} style={{position:'relative',top:'-1px'}} aria-label="..." checked={testDataValue.value} onChange={(e) => {
626
+ testDataValue.value = e.target.checked;
627
+ this._updatePreview(testDataTemplateView, testDataValueView);
628
+ this.updateState({wizard: {testDataViews: {$set: this.state.wizard.testDataViews}}});
629
+ }}/>
630
+ </div>
631
+ </div>
632
+ );
633
+ }
634
+
635
+ renderPreview(testDataTemplate, testDataTemplateView, testDataValue, testDataValueView, index) {
636
+ const foundTestDataValue = testDataValueView.data.find((testDataValue) => {
637
+ return testDataTemplate.name === testDataValue.name;
638
+ });
639
+ const preview = foundTestDataValue ? foundTestDataValue.value : '';
640
+ return (
641
+ <div className="col_sm_8">
642
+ <div key={index} className={`input_column ${this._getValidDivClass(foundTestDataValue.valid)}`} style={{textAlign:'left',paddingLeft:'0px'}}>
643
+ <input type="text" className={`form-control input-sm ${this._getValidInputClass(foundTestDataValue.valid)}`} value={preview} readOnly style={{paddingLeft:'4px',marginBottom:'0px',fontWeight:'bold'}} />
644
+ </div>
645
+ </div>
646
+ );
647
+ }
648
+
649
+ renderInputName(input, testDataTemplate, index) {
650
+ return (
651
+ <div key={`value_${index}`} className="row test_data_row" style={{textAlign: 'right'}}>
652
+ <div className={ModalDialogAbstractionAdd.COLUMN_TEST_DATA_START} style={{right:'-20px'}}>
653
+ <label htmlFor={`modal_dialog_abstraction_add_description_${index}`} className="control-label test_data_name">{testDataTemplate.name}</label>
654
+ </div>
655
+ {input}
656
+ </div>
657
+ );
658
+ }
659
+
660
+ renderInput(testDataTemplate, testDataTemplateView, testDataValue, testDataValueView, index) {
661
+ if(testDataTemplate.depends) {
662
+ const params = testDataTemplate.depends.split(',');
663
+ const dependName = params[0];
664
+ const dependValues = params[1].split('|');
665
+ const found = testDataValueView.data.find((dataValue) => {
666
+ return dependName === dataValue.name;
667
+ });
668
+ if(!found || !dependValues.includes(found.value)) {
669
+ return null;
670
+ }
671
+ }
672
+ if('input' === testDataTemplate.type) {
673
+ const input = this.renderInputText(testDataTemplate, testDataTemplateView, testDataValue, testDataValueView, index);
674
+ return this.renderInputName(input, testDataTemplate, index);
675
+ }
676
+ else if('radio' === testDataTemplate.type) {
677
+ const input = this.renderInputRadio(testDataTemplate, testDataTemplateView, testDataValue, testDataValueView, index);
678
+ return this.renderInputName(input, testDataTemplate, index);
679
+ }
680
+ else if('checkbox' === testDataTemplate.type) {
681
+ const input = this.renderInputCheckbox(testDataTemplate, testDataTemplateView, testDataValue, testDataValueView, index);
682
+ return this.renderInputName(input, testDataTemplate, index);
683
+ }
684
+ else if('preview' === testDataTemplate.type) {
685
+ const input = this.renderPreview(testDataTemplate, testDataTemplateView, testDataValue, testDataValueView, index);
686
+ return this.renderInputName(input, testDataTemplate, index);
687
+ }
688
+ else if('textarea' === testDataTemplate.type) {
689
+ return this.renderInputTextarea(testDataTemplate, testDataTemplateView, testDataValue, testDataValueView, index);
690
+ }
691
+ else {
692
+ return null;
693
+ }
694
+ }
695
+
696
+ renderTestDataViewSingle(testDataTemplateView, testDataValueView) {
697
+ const testDataInput = [];
698
+ testDataTemplateView.data.forEach((testDataTemplate, index) => {
699
+ if(undefined !== testDataTemplate.heading) {
700
+ testDataInput.push(
701
+ <div key={`header_${index}`} className="row test_data_row">
702
+ {this.renderTestDataHeading(testDataTemplate.heading)}
703
+ </div>
704
+ );
705
+ }
706
+ const currentIndex = index;
707
+ const testDataValue = testDataValueView.data[currentIndex];
708
+ const input = this.renderInput(testDataTemplate, testDataTemplateView, testDataValue, testDataValueView, index);
709
+ testDataInput.push(input);
710
+ });
711
+ return testDataInput;
712
+ }
713
+
714
+ renderTestDataViewOptional(testDataTemplateView) {
715
+ const testDataValueOptionalView = this.state.wizard.testDataViews[this.state.wizard.viewIndex];
716
+ const optionalViews = testDataTemplateView.views.map((testCaseDataView, index) => {
717
+ const currentIndex = index;
718
+ const radioId = `radio_${testCaseDataView.name}`;
719
+ return (
720
+ <div key={currentIndex} className="modal_abstraction_add_abstraction_optional">
721
+ <input type="radio" id={radioId} checked={this.state.wizard.optionalViews.get(testDataValueOptionalView.optionalName)?.name === testDataValueOptionalView.views[currentIndex].name} aria-label="..." style={{top:'2px',position:'relative'}} disabled={testCaseDataView.disabled} onChange={(e) => {
722
+ this.updateState({wizard: {optionalViews: (optionalViews) => {
723
+ //optionalViews.set(testDataValueOptionalView.optionalName, testDataValueOptionalView.views[currentIndex].name);
724
+ const optionalView = optionalViews.get(testDataValueOptionalView.optionalName);
725
+ optionalView.name = testDataValueOptionalView.views[currentIndex].name;
726
+ optionalView.index = currentIndex;
727
+ }}});
728
+ }}/>
729
+ <label htmlFor={radioId} style={{paddingLeft:'4px',position:'relative',top:'2px'}}>{testCaseDataView.name}</label>
730
+ </div>
731
+ );
732
+ });
733
+ const optionalView = this.state.wizard.optionalViews.get(testDataValueOptionalView.optionalName);
734
+ return (
735
+ <>
736
+ <div className="input-group" style={{marginTop:'-6px',marginBottom:'6px',display:'inline-table'}}>
737
+ <span className="input-group-addon" style={{paddingTop:'8px'}}>
738
+ {optionalViews}
739
+ </span>
740
+ </div>
741
+ {this.renderTestDataViewSingle(testDataTemplateView.views[optionalView.index], testDataValueOptionalView.views[optionalView.index])}
742
+ </>
743
+ );
744
+ }
745
+
746
+ renderTestDataViewPlugin(testDataTemplateView) {
747
+ const groups = testDataTemplateView.groups.map((group, index) => {
748
+ return (
749
+ <div key={index} style={{backgroundColor:'blue'}}>
750
+ {group.name}
751
+ </div>
752
+ );
753
+ });
754
+ return (
755
+ <div style={{backgroundColor:'red'}}>
756
+ {groups}
757
+ </div>
758
+ );
759
+ }
760
+
761
+ renderTestDataView(testDataTemplateView) {
762
+ const view = this.state.wizard.view;
763
+
764
+ if('single' === view) {
765
+ return this.renderTestDataViewSingle(testDataTemplateView, this.state.wizard.testDataViews[this.state.wizard.viewIndex]);
766
+ }
767
+ else if('optional' === view) {
768
+ return this.renderTestDataViewOptional(testDataTemplateView);
769
+ }
770
+ else if('plugin' === view) {
771
+ return this.renderTestDataViewPlugin(testDataTemplateView);
772
+ }
773
+ }
774
+
775
+ renderTestDataWizardNavigationButtons(step, steps, template) {
776
+ if(2 <= steps) {
777
+ const buttonSpecializedName = this.props.specialName ? this.props.specialName + '_' : '';
778
+ return (
779
+ <>
780
+ <Popover ref={this.helperModalPopover.getPopoverRef()} placement="bottom" heading="" content="" shortcut="Ctrl+Shift+C" style={{display:'inline-block',marginLeft:'5px'}} disabled={!this.state.show}>
781
+ <button id={`abstraction_add_${buttonSpecializedName}previous_button`} type="button" className="btn btn-primary modal_abstraction_add_test_case_data" disabled={1 === step}
782
+ onClick={(e) => {
783
+ this.updateState({wizard: {
784
+ viewIndex: {$set: this.state.wizard.viewIndex - 1},
785
+ view: {$set: template.testDataViews[this.state.wizard.viewIndex - 1].view},
786
+ heading: {$set: template.testDataViews[this.state.wizard.viewIndex - 1].name}
787
+ }});
788
+ }}
789
+ >Previous</button>
790
+ </Popover>
791
+ <Popover ref={this.helperModalPopover.getPopoverRef()} placement="bottom" heading="" content="" shortcut="Ctrl+Shift+C" style={{display:'inline-block',marginLeft:'5px'}} disabled={!this.state.show}>
792
+ <button id={`abstraction_add_${buttonSpecializedName}next_button`} type="button" className="btn btn-primary modal_abstraction_add_test_case_data" disabled={steps === step}
793
+ onClick={(e) => {
794
+ this.updateState({wizard: {
795
+ viewIndex: {$set: this.state.wizard.viewIndex + 1},
796
+ view: {$set: template.testDataViews[this.state.wizard.viewIndex + 1].view},
797
+ heading: {$set: template.testDataViews[this.state.wizard.viewIndex + 1].name}
798
+ }});
799
+ }}
800
+ >Next</button>
801
+ </Popover>
802
+ </>
803
+ );
804
+ }
805
+ else {
806
+ return null;
807
+ }
808
+ }
809
+
810
+ renderWizardView() {
811
+
812
+ }
813
+
814
+ renderRegressionText(regressionFriendly) {
815
+ let text = '';
816
+ if('yes' === regressionFriendly) {
817
+ text = 'Use in regression';
818
+ }
819
+ else if('no' === regressionFriendly) {
820
+ text = 'Do not use in regression';
821
+ }
822
+ else if('not_optimal' === regressionFriendly) {
823
+ text = 'Not optimal to use in regression';
824
+ }
825
+ else {
826
+ return null;
827
+ }
828
+ return (
829
+ <>
830
+ <p className={`modal_abstraction_add_test_case_data_regression modal_abstraction_add_test_case_data_regression_flag_${regressionFriendly}`}>&#9873;&nbsp;</p>
831
+ <p className="modal_abstraction_add_test_case_data_regression">{text}</p>
832
+ </>
833
+ );
834
+ }
835
+
836
+ renderTestDataWizard(template) {
837
+ if(-1 !== this.state.wizard.viewIndex) {
838
+ const testDataTemplateView = template.testDataViews[this.state.wizard.viewIndex];
839
+ if(testDataTemplateView.name === this.state.wizard.heading) {
840
+ const view = this.state.wizard.testDataViews[this.state.wizard.viewIndex];
841
+ const step = this.state.wizard.viewIndex + 1;
842
+ const steps = this.state.wizard.testDataViews.length;
843
+ return (
844
+ <div className="modal_abstraction_add_test_case_data">
845
+ <div className="modal_abstraction_add_test_case_data_caption">
846
+ <p className="modal_abstraction_add_test_case_data_display">
847
+ {testDataTemplateView.displayName}
848
+ </p>
849
+ {this.renderRegressionText(template.regressionFriendly)}
850
+ </div>
851
+ <div className="modal_abstraction_add_test_case_data_step">
852
+ {this.renderTestDataView(testDataTemplateView)}
853
+ </div>
854
+ <div className="modal_abstraction_add_test_case_data_footer">
855
+ <div className="modal_abstraction_add_test_case_step">
856
+ {`${(step)}/${steps}`}
857
+ </div>
858
+ {this.renderTestDataWizardNavigationButtons(step, steps, template)}
859
+ </div>
860
+ </div>
861
+ );
862
+ }
863
+ }
864
+ return null;
865
+ }
866
+
867
+ render() {
868
+ const template = this._getTemplate();
869
+ const markupNodes = template ? template.markupNodes : 2;
870
+ const infoStyle = {
871
+ width: 3 === markupNodes ? '308px' : '178px',
872
+ height: this.state.wizardName ? (template ? '180px' : '130px') : (this.props.repos ? '130px' : '80px'),
873
+ position: 'absolute',
874
+ right: '16px',
875
+ borderRadius: '3px',
876
+ border: 'solid 1.5px lightgray',
877
+ backgroundColor: 'AliceBlue'
878
+ };
879
+ const width = 3 === markupNodes ? '730px' : undefined;
880
+ let nameDivLabelClassName = ModalDialogAbstractionAdd.COLUMN_LIST_END;
881
+ let errorShow = false;
882
+ if(undefined !== this.props.result.status && !this.props.result.status.name.status) {
883
+ nameDivLabelClassName += ' has-error';
884
+ errorShow = true;
885
+ }
886
+ else if(this.state.error) {
887
+ nameDivLabelClassName += ' has-error';
888
+ }
889
+ const inputNameClass = this.state.error ? 'form-control has-error' : 'form-control';
890
+ const buttonSpecializedName = this.props.specialName ? this.props.specialName + '_' : '';
891
+ this.helperModalPopover.onRender();
892
+ const idAddName = 'modal_dialog_abstraction_add_name' + (this.props.id ? '_' + this.props.id : '');
893
+ return (
894
+ <Modal ref={this.helperModalPopover.modalRef} id={`modal_abstraction_${buttonSpecializedName}add`} show={this.state.show || errorShow} width={width}
895
+ onShown={(e) => {
896
+ this.inputRef.current.focus();
897
+ }}
898
+ onHide={(e) => {
899
+ this.clear();
900
+ this.hide();
901
+ }}
902
+ >
903
+ <ModalHeader closeButton>
904
+ <img className="modal_header_icon pull-left" src="/abs-images/svg/ActorJsA.svg" alt="ActorJs Icon"></img>
905
+ <h4 className="modal_header_heading modal-sm">{this.props.heading}</h4>
906
+ </ModalHeader>
907
+ <ModalBody>
908
+ <div style={infoStyle}>
909
+ {this.renderMarkup(template)}
910
+ </div>
911
+ <div className="form-group">
912
+ <div className="row" style={{textAlign: 'right'}}>
913
+ <div className={ModalDialogAbstractionAdd.COLUMN_LIST_START}>
914
+ <label htmlFor={idAddName} className="control-label">Name</label>
915
+ </div>
916
+ <div className={nameDivLabelClassName}>
917
+ <input ref={this.inputRef} id={idAddName} type="text" className="form-control input-sm" value={this.state.name} placeholder={this.props.nameplaceholder}
918
+ onChange={(e) => {
919
+ const result = this.inputAnalyzer.analyze(e.target.value);
920
+ if(result.success) {
921
+ this.updateState({valid: {$set: true}});
922
+ this.updateState({error: {$set: false}});
923
+ }
924
+ else {
925
+ this.updateState({valid: {$set: false}});
926
+ this.updateState({error: {$set: true}});
927
+ if(!result.upperCaseValidation) {
928
+ this.updateState({errorText: {$set: 'The name must start with a capital letter'}});
929
+ }
930
+ else if(!result.regexpValidation) {
931
+ this.updateState({errorText: {$set: `The filename contains not allowed characters: '${result.noneValidCharacters}'`}});
932
+ }
933
+ else if(!result.filenameValidation) {
934
+ this.updateState({errorText: {$set: `The filename is not allowed: '${result.noneValidFilename}'`}});
935
+ }
936
+ }
937
+ this.updateState({name: {$set: result.text}});
938
+ }}
939
+ />
940
+ </div>
941
+ </div>
942
+ {this.renderDescription()}
943
+ {this.renderWizard()}
944
+ {this.renderTemplate(template)}
945
+ {this.renderTestDataWizard(template)}
946
+ {this.renderRepo()}
947
+ </div>
948
+ </ModalBody>
949
+ <ModalFooter>
950
+ {this.renderErrorMessage()}
951
+ <Popover ref={this.helperModalPopover.getPopoverRef()} placement="bottom" heading="" content="" shortcut="Enter" style={{display:'inline-block'}} disabled={!this.state.show}>
952
+ <button id={`abstraction_add_${buttonSpecializedName}add_button`} type="button" className="btn btn-primary" disabled={!this.state.valid}
953
+ onClick={(e) => {
954
+ this.add();
955
+ this.hide();
956
+ }}
957
+ >Add</button>
958
+ </Popover>
959
+ <Popover ref={this.helperModalPopover.getPopoverRef()} placement="bottom" heading="" content="" shortcut="Ctrl+Shift+C" style={{display:'inline-block',marginLeft:'5px'}} disabled={!this.state.show}>
960
+ <button id={`abstraction_add_${buttonSpecializedName}close_button`} type="button" className="btn btn-default" disabled={!this.state.show}
961
+ onClick={(e) => {
962
+ this.clear();
963
+ this.hide();
964
+ }}
965
+ >Close</button>
966
+ </Popover>
967
+ </ModalFooter>
968
+ </Modal>
969
+ );
970
+ }
971
+
972
+ _getTemplate(getFirstName=false) {
973
+ if(this.state.wizardName && this.props.templates) {
974
+ const templates = this.props.templates.get(this.state.wizardName);
975
+ if(templates && 0 !== templates.size) {
976
+ if(this.state.templateName) {
977
+ return templates.get(this.state.templateName);
978
+ }
979
+ else if(getFirstName) {
980
+ const [firstTemplateName] = templates.keys();
981
+ return firstTemplateName;
982
+ }
983
+ }
984
+ }
985
+ return null;
986
+ }
987
+ }
988
+
989
+
990
+ ModalDialogAbstractionAdd.COLUMN_LIST_START = 'col_sm_2';
991
+ ModalDialogAbstractionAdd.COLUMN_TEST_DATA_START = 'col_sm_4';
992
+ ModalDialogAbstractionAdd.COLUMN_LIST_END = 'col_sm_6';