@eeacms/volto-eea-website-theme 1.34.0 → 2.0.1

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 (54) hide show
  1. package/.eslintrc.js +7 -2
  2. package/CHANGELOG.md +53 -1
  3. package/docker-compose.yml +1 -1
  4. package/jest-addon.config.js +3 -0
  5. package/package.json +2 -1
  6. package/src/components/manage/Blocks/LayoutSettings/index.js +3 -1
  7. package/src/components/manage/Blocks/Title/index.js +3 -1
  8. package/src/components/manage/Blocks/Title/schema.js +3 -1
  9. package/src/components/theme/Banner/View.jsx +12 -5
  10. package/src/components/theme/DraftBackground/DraftBackground.jsx +30 -21
  11. package/src/components/theme/DraftBackground/DraftBackground.test.jsx +85 -0
  12. package/src/config.js +2 -0
  13. package/src/customizations/@plone/volto-slate/blocks/Text/TextBlockView.jsx +32 -0
  14. package/src/customizations/@plone/volto-slate/editor/render.jsx +75 -0
  15. package/src/customizations/@plone/volto-slate/elementEditor/utils.js +76 -75
  16. package/src/customizations/volto/components/manage/Blocks/Grid/Edit.jsx +70 -0
  17. package/src/customizations/volto/components/manage/Blocks/Grid/View.jsx +61 -0
  18. package/src/customizations/volto/components/manage/Blocks/Grid/readme.md +1 -0
  19. package/src/customizations/volto/components/manage/Blocks/Image/Edit.jsx +82 -23
  20. package/src/customizations/volto/components/manage/Blocks/Image/Edit.test.jsx +10 -3
  21. package/src/customizations/volto/components/manage/Blocks/Image/View.jsx +110 -111
  22. package/src/customizations/volto/components/manage/Blocks/Image/schema.js +17 -2
  23. package/src/customizations/volto/components/manage/Blocks/LeadImage/Edit.jsx +35 -14
  24. package/src/customizations/volto/components/manage/Blocks/LeadImage/View.jsx +65 -79
  25. package/src/customizations/volto/components/manage/Display/Display.jsx +306 -0
  26. package/src/customizations/volto/components/manage/Display/Readme.md +1 -0
  27. package/src/customizations/volto/components/manage/Sidebar/SidebarPopup copy.jsx +82 -0
  28. package/src/customizations/volto/components/manage/Toolbar/More.jsx +541 -0
  29. package/src/customizations/volto/components/manage/UniversalLink/UniversalLink.jsx +3 -1
  30. package/src/customizations/volto/components/manage/Widgets/ObjectBrowserWidget.jsx +24 -14
  31. package/src/customizations/volto/components/manage/Widgets/README.md +1 -0
  32. package/src/customizations/volto/components/manage/Workflow/README.txt +1 -0
  33. package/src/customizations/volto/components/manage/Workflow/Workflow.jsx +324 -0
  34. package/src/customizations/volto/components/manage/Workflow/Workflow.test.jsx +81 -0
  35. package/src/customizations/volto/components/theme/Comments/Comments.jsx +1 -2
  36. package/src/customizations/volto/components/theme/ContactForm/ContactForm.jsx +1 -1
  37. package/src/customizations/volto/components/theme/EventDetails/EventDetails.jsx +1 -0
  38. package/src/index.js +21 -16
  39. package/src/middleware/ok.js +4 -2
  40. package/src/middleware/voltoCustom.js +4 -2
  41. package/src/slate.js +10 -8
  42. package/src/customizations/@plone/volto-slate/editor/plugins/StyleMenu/README.txt +0 -1
  43. package/src/customizations/@plone/volto-slate/editor/plugins/StyleMenu/StyleMenu.jsx +0 -157
  44. package/src/customizations/@plone/volto-slate/editor/plugins/StyleMenu/utils.js +0 -168
  45. package/src/customizations/volto/components/manage/Add/Add.jsx +0 -498
  46. package/src/customizations/volto/components/manage/Add/readme.md +0 -1
  47. package/src/customizations/volto/components/manage/Contents/ContentsPropertiesModal.jsx +0 -232
  48. package/src/customizations/volto/components/manage/Form/Form.jsx +0 -810
  49. package/src/customizations/volto/components/manage/Form/Form.test.jsx +0 -1124
  50. package/src/customizations/volto/components/manage/Form/ModalForm.jsx +0 -326
  51. package/src/customizations/volto/components/manage/Sharing/Sharing.jsx +0 -528
  52. package/src/customizations/volto/components/manage/Sharing/Sharing.test.jsx +0 -72
  53. package/src/customizations/volto/components/manage/Widgets/ObjectBrowserWidget.test.jsx +0 -193
  54. package/src/customizations/volto/components/theme/AppExtras/AppExtras.jsx +0 -27
@@ -1,810 +0,0 @@
1
- /**
2
- * Form component.
3
- * @module components/manage/Form/Form
4
- */
5
-
6
- import { BlocksForm, Field, Icon, Toast } from '@plone/volto/components';
7
- import {
8
- difference,
9
- FormValidation,
10
- getBlocksFieldname,
11
- getBlocksLayoutFieldname,
12
- messages,
13
- } from '@plone/volto/helpers';
14
- import aheadSVG from '@plone/volto/icons/ahead.svg';
15
- import clearSVG from '@plone/volto/icons/clear.svg';
16
- import {
17
- findIndex,
18
- isEmpty,
19
- keys,
20
- map,
21
- mapValues,
22
- pickBy,
23
- without,
24
- cloneDeep,
25
- } from 'lodash';
26
- import isBoolean from 'lodash/isBoolean';
27
- import PropTypes from 'prop-types';
28
- import React, { Component } from 'react';
29
- import { injectIntl } from 'react-intl';
30
- import { Portal } from 'react-portal';
31
- import { connect } from 'react-redux';
32
- import {
33
- Button,
34
- Container,
35
- Form as UiForm,
36
- Message,
37
- Segment,
38
- Tab,
39
- } from 'semantic-ui-react';
40
- import { v4 as uuid } from 'uuid';
41
- import { toast } from 'react-toastify';
42
- import { BlocksToolbar, UndoToolbar } from '@plone/volto/components';
43
- import { setSidebarTab } from '@plone/volto/actions';
44
- import { compose } from 'redux';
45
- import config from '@plone/volto/registry';
46
-
47
- /**
48
- * Form container class.
49
- * @class Form
50
- * @extends Component
51
- */
52
- class Form extends Component {
53
- /**
54
- * Property types.
55
- * @property {Object} propTypes Property types.
56
- * @static
57
- */
58
- static propTypes = {
59
- schema: PropTypes.shape({
60
- fieldsets: PropTypes.arrayOf(
61
- PropTypes.shape({
62
- fields: PropTypes.arrayOf(PropTypes.string),
63
- id: PropTypes.string,
64
- title: PropTypes.string,
65
- }),
66
- ),
67
- properties: PropTypes.objectOf(PropTypes.any),
68
- definitions: PropTypes.objectOf(PropTypes.any),
69
- required: PropTypes.arrayOf(PropTypes.string),
70
- }),
71
- formData: PropTypes.objectOf(PropTypes.any),
72
- pathname: PropTypes.string,
73
- onSubmit: PropTypes.func,
74
- onCancel: PropTypes.func,
75
- submitLabel: PropTypes.string,
76
- resetAfterSubmit: PropTypes.bool,
77
- resetOnCancel: PropTypes.bool,
78
- isEditForm: PropTypes.bool,
79
- isAdminForm: PropTypes.bool,
80
- title: PropTypes.string,
81
- error: PropTypes.shape({
82
- message: PropTypes.string,
83
- }),
84
- loading: PropTypes.bool,
85
- hideActions: PropTypes.bool,
86
- description: PropTypes.string,
87
- visual: PropTypes.bool,
88
- blocks: PropTypes.arrayOf(PropTypes.object),
89
- isFormSelected: PropTypes.bool,
90
- onSelectForm: PropTypes.func,
91
- editable: PropTypes.bool,
92
- onChangeFormData: PropTypes.func,
93
- requestError: PropTypes.string,
94
- allowedBlocks: PropTypes.arrayOf(PropTypes.string),
95
- showRestricted: PropTypes.bool,
96
- };
97
-
98
- /**
99
- * Default properties.
100
- * @property {Object} defaultProps Default properties.
101
- * @static
102
- */
103
- static defaultProps = {
104
- formData: null,
105
- onSubmit: null,
106
- onCancel: null,
107
- submitLabel: null,
108
- resetAfterSubmit: false,
109
- resetOnCancel: false,
110
- isEditForm: false,
111
- isAdminForm: false,
112
- title: null,
113
- description: null,
114
- error: null,
115
- loading: null,
116
- hideActions: false,
117
- visual: false,
118
- blocks: [],
119
- pathname: '',
120
- schema: {},
121
- isFormSelected: true,
122
- onSelectForm: null,
123
- editable: true,
124
- requestError: null,
125
- allowedBlocks: null,
126
- };
127
-
128
- /**
129
- * Constructor
130
- * @method constructor
131
- * @param {Object} props Component properties
132
- * @constructs Form
133
- */
134
- constructor(props) {
135
- super(props);
136
- const ids = {
137
- title: uuid(),
138
- text: uuid(),
139
- };
140
- let { formData } = props;
141
- // TODO Tiberiu: customized here
142
- formData = formData || {}; // when coming from login screen, formData is null
143
- // this fixes a bug where, if you go to an /edit page, it will show login (you need to wait the 5 seconds timeout), after login you get redirected back to the edit, then it crashes
144
- // end customized
145
- const blocksFieldname = getBlocksFieldname(formData);
146
- const blocksLayoutFieldname = getBlocksLayoutFieldname(formData);
147
-
148
- if (!props.isEditForm) {
149
- // It's a normal (add form), get defaults from schema
150
- formData = {
151
- ...mapValues(props.schema.properties, 'default'),
152
- ...formData,
153
- };
154
- }
155
- // defaults for block editor; should be moved to schema on server side
156
- // Adding fallback in case the fields are empty, so we are sure that the edit form
157
- // shows at least the default blocks
158
- if (
159
- formData.hasOwnProperty(blocksFieldname) &&
160
- formData.hasOwnProperty(blocksLayoutFieldname)
161
- ) {
162
- if (
163
- !formData[blocksLayoutFieldname] ||
164
- isEmpty(formData[blocksLayoutFieldname].items)
165
- ) {
166
- formData[blocksLayoutFieldname] = {
167
- items: [ids.title, ids.text],
168
- };
169
- }
170
- if (!formData[blocksFieldname] || isEmpty(formData[blocksFieldname])) {
171
- formData[blocksFieldname] = {
172
- [ids.title]: {
173
- '@type': 'title',
174
- },
175
- [ids.text]: {
176
- '@type': config.settings.defaultBlockType,
177
- },
178
- };
179
- }
180
- }
181
-
182
- let selectedBlock = null;
183
- if (
184
- formData.hasOwnProperty(blocksLayoutFieldname) &&
185
- formData[blocksLayoutFieldname].items.length > 0
186
- ) {
187
- if (config.blocks?.initialBlocksFocus === null) {
188
- selectedBlock = null;
189
- } else if (this.props.type in config.blocks?.initialBlocksFocus) {
190
- // Default selected is not the first block, but the one from config.
191
- // TODO Select first block and not an arbitrary one.
192
- Object.keys(formData[blocksFieldname]).forEach((b_key) => {
193
- if (
194
- formData[blocksFieldname][b_key]['@type'] ===
195
- config.blocks?.initialBlocksFocus?.[this.props.type]
196
- ) {
197
- selectedBlock = b_key;
198
- }
199
- });
200
- } else {
201
- selectedBlock = formData[blocksLayoutFieldname].items[0];
202
- }
203
- }
204
-
205
- this.state = {
206
- formData,
207
- initialFormData: cloneDeep(formData),
208
- errors: {},
209
- selected: selectedBlock,
210
- multiSelected: [],
211
- isClient: false,
212
- // Ensure focus remain in field after change
213
- inFocus: {},
214
- };
215
- this.onChangeField = this.onChangeField.bind(this);
216
- this.onSelectBlock = this.onSelectBlock.bind(this);
217
- this.onSubmit = this.onSubmit.bind(this);
218
- this.onCancel = this.onCancel.bind(this);
219
- this.onTabChange = this.onTabChange.bind(this);
220
- this.onBlurField = this.onBlurField.bind(this);
221
- this.onClickInput = this.onClickInput.bind(this);
222
- }
223
-
224
- /**
225
- * On updates caused by props change
226
- * if errors from Backend come, these will be shown to their corresponding Fields
227
- * also the first Tab to have any errors will be selected
228
- * @param {Object} prevProps
229
- */
230
- async componentDidUpdate(prevProps, prevState) {
231
- let { requestError } = this.props;
232
- let errors = {};
233
- let activeIndex = 0;
234
-
235
- if (requestError && prevProps.requestError !== requestError) {
236
- errors = FormValidation.giveServerErrorsToCorrespondingFields(
237
- requestError,
238
- );
239
- activeIndex = FormValidation.showFirstTabWithErrors({
240
- errors,
241
- schema: this.props.schema,
242
- });
243
-
244
- this.setState({
245
- errors,
246
- activeIndex,
247
- });
248
- }
249
-
250
- if (this.props.onChangeFormData) {
251
- if (
252
- // TODO: use fast-deep-equal
253
- JSON.stringify(prevState?.formData) !==
254
- JSON.stringify(this.state.formData)
255
- ) {
256
- this.props.onChangeFormData(this.state.formData);
257
- }
258
- }
259
- }
260
-
261
- /**
262
- * Tab selection is done only by setting activeIndex in state
263
- */
264
- onTabChange(e, { activeIndex }) {
265
- const defaultFocus = this.props.schema.fieldsets[activeIndex].fields[0];
266
- this.setState({
267
- activeIndex,
268
- ...(defaultFocus ? { inFocus: { [defaultFocus]: true } } : {}),
269
- });
270
- }
271
-
272
- /**
273
- * If user clicks on input, the form will be not considered pristine
274
- * this will avoid onBlur effects without interraction with the form
275
- * @param {Object} e event
276
- */
277
- onClickInput(e) {
278
- this.setState({ isFormPristine: false });
279
- }
280
-
281
- /**
282
- * Validate fields on blur
283
- * @method onBlurField
284
- * @param {string} id Id of the field
285
- * @param {*} value Value of the field
286
- * @returns {undefined}
287
- */
288
- onBlurField(id, value) {
289
- if (!this.state.isFormPristine) {
290
- const errors = FormValidation.validateFieldsPerFieldset({
291
- schema: this.props.schema,
292
- formData: this.state.formData,
293
- formatMessage: this.props.intl.formatMessage,
294
- touchedField: { [id]: value },
295
- });
296
-
297
- this.setState({
298
- errors,
299
- });
300
- }
301
- }
302
-
303
- /**
304
- * Component did mount
305
- * @method componentDidMount
306
- * @returns {undefined}
307
- */
308
- componentDidMount() {
309
- this.setState({ isClient: true });
310
- }
311
-
312
- static getDerivedStateFromProps(props, state) {
313
- let newState = { ...state };
314
- if (!props.isFormSelected) {
315
- newState.selected = null;
316
- }
317
-
318
- return newState;
319
- }
320
-
321
- /**
322
- * Change field handler
323
- * Remove errors for changed field
324
- * @method onChangeField
325
- * @param {string} id Id of the field
326
- * @param {*} value Value of the field
327
- * @returns {undefined}
328
- */
329
- onChangeField(id, value) {
330
- this.setState((prevState) => {
331
- const { errors, formData } = prevState;
332
- delete errors[id];
333
- return {
334
- errors,
335
- formData: {
336
- ...formData,
337
- // We need to catch also when the value equals false this fixes #888
338
- [id]:
339
- value || (value !== undefined && isBoolean(value)) ? value : null,
340
- },
341
- // Changing the form data re-renders the select widget which causes the
342
- // focus to get lost. To circumvent this, we set the focus back to
343
- // the input.
344
- // This could fix other widgets too but currently targeted
345
- // against the select widget only.
346
- // Ensure field to be in focus after the change
347
- inFocus: { [id]: true },
348
- };
349
- });
350
- }
351
-
352
- /**
353
- * Select block handler
354
- * @method onSelectBlock
355
- * @param {string} id Id of the field
356
- * @param {string} isMultipleSelection true if multiple blocks are selected
357
- * @returns {undefined}
358
- */
359
- onSelectBlock(id, isMultipleSelection, event) {
360
- let multiSelected = [];
361
- let selected = id;
362
-
363
- if (isMultipleSelection) {
364
- selected = null;
365
- const blocksLayoutFieldname = getBlocksLayoutFieldname(
366
- this.state.formData,
367
- );
368
-
369
- const blocks_layout = this.state.formData[blocksLayoutFieldname].items;
370
-
371
- if (event.shiftKey) {
372
- const anchor =
373
- this.state.multiSelected.length > 0
374
- ? blocks_layout.indexOf(this.state.multiSelected[0])
375
- : blocks_layout.indexOf(this.state.selected);
376
- const focus = blocks_layout.indexOf(id);
377
-
378
- if (anchor === focus) {
379
- multiSelected = [id];
380
- } else if (focus > anchor) {
381
- multiSelected = [...blocks_layout.slice(anchor, focus + 1)];
382
- } else {
383
- multiSelected = [...blocks_layout.slice(focus, anchor + 1)];
384
- }
385
- }
386
-
387
- if ((event.ctrlKey || event.metaKey) && !event.shiftKey) {
388
- multiSelected = this.state.multiSelected || [];
389
- if (!this.state.multiSelected.includes(this.state.selected)) {
390
- multiSelected = [...multiSelected, this.state.selected];
391
- selected = null;
392
- }
393
- if (this.state.multiSelected.includes(id)) {
394
- selected = null;
395
- multiSelected = without(multiSelected, id);
396
- } else {
397
- multiSelected = [...multiSelected, id];
398
- }
399
- }
400
- }
401
-
402
- this.setState({
403
- selected,
404
- multiSelected,
405
- });
406
-
407
- if (this.props.onSelectForm) {
408
- if (event) event.nativeEvent.stopImmediatePropagation();
409
- this.props.onSelectForm();
410
- }
411
- }
412
-
413
- /**
414
- * Cancel handler
415
- * It prevents event from triggering submit, reset form if props.resetAfterSubmit
416
- * and calls this.props.onCancel
417
- * @method onCancel
418
- * @param {Object} event Event object.
419
- * @returns {undefined}
420
- */
421
- onCancel(event) {
422
- if (event) {
423
- event.preventDefault();
424
- }
425
- if (this.props.resetOnCancel || this.props.resetAfterSubmit) {
426
- this.setState({
427
- formData: this.props.formData,
428
- });
429
- }
430
- this.props.onCancel(event);
431
- }
432
-
433
- /**
434
- * Submit handler also validate form and collect errors
435
- * @method onSubmit
436
- * @param {Object} event Event object.
437
- * @returns {undefined}
438
- */
439
- onSubmit(event) {
440
- if (event) {
441
- event.preventDefault();
442
- }
443
-
444
- const errors = this.props.schema
445
- ? FormValidation.validateFieldsPerFieldset({
446
- schema: this.props.schema,
447
- formData: this.state.formData,
448
- formatMessage: this.props.intl.formatMessage,
449
- })
450
- : {};
451
-
452
- if (keys(errors).length > 0) {
453
- const activeIndex = FormValidation.showFirstTabWithErrors({
454
- errors,
455
- schema: this.props.schema,
456
- });
457
- this.setState(
458
- {
459
- errors,
460
- activeIndex,
461
- },
462
- () => {
463
- Object.keys(errors).forEach((err) =>
464
- toast.error(
465
- <Toast
466
- error
467
- title={this.props.schema.properties[err].title || err}
468
- content={errors[err].join(', ')}
469
- />,
470
- ),
471
- );
472
- },
473
- );
474
- // Changes the focus to the metadata tab in the sidebar if error
475
- this.props.setSidebarTab(0);
476
- } else {
477
- // Get only the values that have been modified (Edit forms), send all in case that
478
- // it's an add form
479
- if (this.props.isEditForm) {
480
- this.props.onSubmit(this.getOnlyFormModifiedValues());
481
- } else {
482
- this.props.onSubmit(this.state.formData);
483
- }
484
- if (this.props.resetAfterSubmit) {
485
- this.setState({
486
- formData: this.props.formData,
487
- });
488
- }
489
- }
490
- }
491
-
492
- /**
493
- * getOnlyFormModifiedValues handler
494
- * It returns only the values of the fields that are have really changed since the
495
- * form was loaded. Useful for edit forms and PATCH operations, when we only want to
496
- * send the changed data.
497
- * @method getOnlyFormModifiedValues
498
- * @param {Object} event Event object.
499
- * @returns {undefined}
500
- */
501
- getOnlyFormModifiedValues = () => {
502
- const fieldsModified = Object.keys(
503
- difference(this.state.formData, this.state.initialFormData),
504
- );
505
- return {
506
- ...pickBy(this.state.formData, (value, key) =>
507
- fieldsModified.includes(key),
508
- ),
509
- ...(this.state.formData['@static_behaviors'] && {
510
- '@static_behaviors': this.state.formData['@static_behaviors'],
511
- }),
512
- };
513
- };
514
-
515
- /**
516
- * Removed blocks and blocks_layout fields from the form.
517
- * @method removeBlocksLayoutFields
518
- * @param {object} schema The schema definition of the form.
519
- * @returns A modified copy of the given schema.
520
- */
521
- removeBlocksLayoutFields = (schema) => {
522
- const newSchema = { ...schema };
523
- const layoutFieldsetIndex = findIndex(
524
- newSchema.fieldsets,
525
- (fieldset) => fieldset.id === 'layout',
526
- );
527
- if (layoutFieldsetIndex > -1) {
528
- const layoutFields = newSchema.fieldsets[layoutFieldsetIndex].fields;
529
- newSchema.fieldsets[layoutFieldsetIndex].fields = layoutFields.filter(
530
- (field) => field !== 'blocks' && field !== 'blocks_layout',
531
- );
532
- if (newSchema.fieldsets[layoutFieldsetIndex].fields.length === 0) {
533
- newSchema.fieldsets = [
534
- ...newSchema.fieldsets.slice(0, layoutFieldsetIndex),
535
- ...newSchema.fieldsets.slice(layoutFieldsetIndex + 1),
536
- ];
537
- }
538
- }
539
- return newSchema;
540
- };
541
-
542
- /**
543
- * Render method.
544
- * @method render
545
- * @returns {string} Markup for the component.
546
- */
547
- render() {
548
- const { settings } = config;
549
- const { schema: originalSchema, onCancel, onSubmit } = this.props;
550
- const { formData } = this.state;
551
- const schema = this.removeBlocksLayoutFields(originalSchema);
552
-
553
- return this.props.visual ? (
554
- // Removing this from SSR is important, since react-beautiful-dnd supports SSR,
555
- // but draftJS don't like it much and the hydration gets messed up
556
- this.state.isClient && (
557
- <div className="ui container">
558
- <BlocksToolbar
559
- formData={this.state.formData}
560
- selectedBlock={this.state.selected}
561
- selectedBlocks={this.state.multiSelected}
562
- onChangeBlocks={(newBlockData) =>
563
- this.setState({
564
- formData: {
565
- ...formData,
566
- ...newBlockData,
567
- },
568
- })
569
- }
570
- onSetSelectedBlocks={(blockIds) =>
571
- this.setState({ multiSelected: blockIds })
572
- }
573
- onSelectBlock={this.onSelectBlock}
574
- />
575
- <UndoToolbar
576
- state={{
577
- formData: this.state.formData,
578
- selected: this.state.selected,
579
- multiSelected: this.state.multiSelected,
580
- }}
581
- enableHotKeys
582
- onUndoRedo={({ state }) => this.setState(state)}
583
- />
584
- <BlocksForm
585
- onChangeFormData={(newFormData) =>
586
- this.setState({
587
- formData: {
588
- ...formData,
589
- ...newFormData,
590
- },
591
- })
592
- }
593
- onChangeField={this.onChangeField}
594
- onSelectBlock={this.onSelectBlock}
595
- properties={formData}
596
- pathname={this.props.pathname}
597
- selectedBlock={this.state.selected}
598
- multiSelected={this.state.multiSelected}
599
- manage={this.props.isAdminForm}
600
- allowedBlocks={this.props.allowedBlocks}
601
- showRestricted={this.props.showRestricted}
602
- editable={this.props.editable}
603
- isMainForm={this.props.editable}
604
- />
605
- {this.state.isClient && this.props.editable && (
606
- <Portal
607
- node={__CLIENT__ && document.getElementById('sidebar-metadata')}
608
- >
609
- <UiForm
610
- method="post"
611
- onSubmit={this.onSubmit}
612
- error={keys(this.state.errors).length > 0}
613
- >
614
- {schema &&
615
- map(schema.fieldsets, (item) => [
616
- <Segment
617
- secondary
618
- attached
619
- className={`fieldset-${item.id}`}
620
- key={item.title}
621
- >
622
- {item.title}
623
- </Segment>,
624
- <Segment attached key={`fieldset-contents-${item.title}`}>
625
- {map(item.fields, (field, index) => (
626
- <Field
627
- {...schema.properties[field]}
628
- id={field}
629
- fieldSet={item.title.toLowerCase()}
630
- formData={this.state.formData}
631
- focus={this.state.inFocus[field]}
632
- value={this.state.formData?.[field]}
633
- required={schema.required.indexOf(field) !== -1}
634
- onChange={this.onChangeField}
635
- onBlur={this.onBlurField}
636
- onClick={this.onClickInput}
637
- key={field}
638
- error={this.state.errors[field]}
639
- />
640
- ))}
641
- </Segment>,
642
- ])}
643
- </UiForm>
644
- </Portal>
645
- )}
646
- </div>
647
- )
648
- ) : (
649
- <Container>
650
- <UiForm
651
- method="post"
652
- onSubmit={this.onSubmit}
653
- error={keys(this.state.errors).length > 0}
654
- className={settings.verticalFormTabs ? 'vertical-form' : ''}
655
- >
656
- <fieldset className="invisible">
657
- <Segment.Group raised>
658
- {schema && schema.fieldsets.length > 1 && (
659
- <>
660
- {settings.verticalFormTabs && this.props.title && (
661
- <Segment secondary attached key={this.props.title}>
662
- {this.props.title}
663
- </Segment>
664
- )}
665
- <Tab
666
- menu={{
667
- secondary: true,
668
- pointing: true,
669
- attached: true,
670
- tabular: true,
671
- className: 'formtabs',
672
- vertical: settings.verticalFormTabs,
673
- }}
674
- grid={{ paneWidth: 9, tabWidth: 3, stackable: true }}
675
- onTabChange={this.onTabChange}
676
- activeIndex={this.state.activeIndex}
677
- panes={map(schema.fieldsets, (item) => ({
678
- menuItem: item.title,
679
- render: () => [
680
- !settings.verticalFormTabs && this.props.title && (
681
- <Segment secondary attached key={this.props.title}>
682
- {this.props.title}
683
- </Segment>
684
- ),
685
- item.description && (
686
- <Message attached="bottom">
687
- {item.description}
688
- </Message>
689
- ),
690
- ...map(item.fields, (field, index) => (
691
- <Field
692
- {...schema.properties[field]}
693
- isDisabled={!this.props.editable}
694
- id={field}
695
- formData={this.state.formData}
696
- fieldSet={item.title.toLowerCase()}
697
- focus={this.state.inFocus[field]}
698
- value={this.state.formData?.[field]}
699
- required={schema.required.indexOf(field) !== -1}
700
- onChange={this.onChangeField}
701
- onBlur={this.onBlurField}
702
- onClick={this.onClickInput}
703
- key={field}
704
- error={this.state.errors[field]}
705
- />
706
- )),
707
- ],
708
- }))}
709
- />
710
- </>
711
- )}
712
- {schema && schema.fieldsets.length === 1 && (
713
- <Segment>
714
- {this.props.title && (
715
- <Segment className="primary">
716
- <h1 style={{ fontSize: '16px' }}> {this.props.title}</h1>
717
- </Segment>
718
- )}
719
- {this.props.description && (
720
- <Segment secondary>{this.props.description}</Segment>
721
- )}
722
- {keys(this.state.errors).length > 0 && (
723
- <Message
724
- icon="warning"
725
- negative
726
- attached
727
- header={this.props.intl.formatMessage(messages.error)}
728
- content={this.props.intl.formatMessage(
729
- messages.thereWereSomeErrors,
730
- )}
731
- />
732
- )}
733
- {this.props.error && (
734
- <Message
735
- icon="warning"
736
- negative
737
- attached
738
- header={this.props.intl.formatMessage(messages.error)}
739
- content={this.props.error.message}
740
- />
741
- )}
742
- {map(schema.fieldsets[0].fields, (field) => (
743
- <Field
744
- {...schema.properties[field]}
745
- id={field}
746
- value={this.state.formData?.[field]}
747
- required={schema.required.indexOf(field) !== -1}
748
- onChange={this.onChangeField}
749
- onBlur={this.onBlurField}
750
- onClick={this.onClickInput}
751
- key={field}
752
- error={this.state.errors[field]}
753
- />
754
- ))}
755
- </Segment>
756
- )}
757
- {!this.props.hideActions && (
758
- <Segment className="actions" clearing>
759
- {onSubmit && (
760
- <Button
761
- basic
762
- icon
763
- primary
764
- floated="right"
765
- type="submit"
766
- aria-label={
767
- this.props.submitLabel
768
- ? this.props.submitLabel
769
- : this.props.intl.formatMessage(messages.save)
770
- }
771
- title={
772
- this.props.submitLabel
773
- ? this.props.submitLabel
774
- : this.props.intl.formatMessage(messages.save)
775
- }
776
- loading={this.props.loading}
777
- >
778
- <Icon className="circled" name={aheadSVG} size="30px" />
779
- </Button>
780
- )}
781
- {onCancel && (
782
- <Button
783
- basic
784
- icon
785
- secondary
786
- aria-label={this.props.intl.formatMessage(
787
- messages.cancel,
788
- )}
789
- title={this.props.intl.formatMessage(messages.cancel)}
790
- floated="right"
791
- onClick={this.onCancel}
792
- >
793
- <Icon className="circled" name={clearSVG} size="30px" />
794
- </Button>
795
- )}
796
- </Segment>
797
- )}
798
- </Segment.Group>
799
- </fieldset>
800
- </UiForm>
801
- </Container>
802
- );
803
- }
804
- }
805
-
806
- const FormIntl = injectIntl(Form, { forwardRef: true });
807
-
808
- export default compose(
809
- connect(null, { setSidebarTab }, null, { forwardRef: true }),
810
- )(FormIntl);