@plone/volto 18.0.0-alpha.33 → 18.0.0-alpha.34
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.
- package/CHANGELOG.md +18 -0
- package/locales/ca/LC_MESSAGES/volto.po +5 -0
- package/locales/ca.json +1 -1
- package/locales/de/LC_MESSAGES/volto.po +5 -0
- package/locales/de.json +1 -1
- package/locales/en/LC_MESSAGES/volto.po +5 -0
- package/locales/en.json +1 -1
- package/locales/es/LC_MESSAGES/volto.po +5 -0
- package/locales/es.json +1 -1
- package/locales/eu/LC_MESSAGES/volto.po +5 -0
- package/locales/eu.json +1 -1
- package/locales/fi/LC_MESSAGES/volto.po +5 -0
- package/locales/fi.json +1 -1
- package/locales/fr/LC_MESSAGES/volto.po +5 -0
- package/locales/fr.json +1 -1
- package/locales/hi/LC_MESSAGES/volto.po +5 -0
- package/locales/hi.json +1 -1
- package/locales/it/LC_MESSAGES/volto.po +5 -0
- package/locales/it.json +1 -1
- package/locales/ja/LC_MESSAGES/volto.po +5 -0
- package/locales/ja.json +1 -1
- package/locales/nl/LC_MESSAGES/volto.po +5 -0
- package/locales/nl.json +1 -1
- package/locales/pt/LC_MESSAGES/volto.po +5 -0
- package/locales/pt.json +1 -1
- package/locales/pt_BR/LC_MESSAGES/volto.po +5 -0
- package/locales/pt_BR.json +1 -1
- package/locales/ro/LC_MESSAGES/volto.po +5 -0
- package/locales/ro.json +1 -1
- package/locales/volto.pot +5 -0
- package/locales/zh_CN/LC_MESSAGES/volto.po +5 -0
- package/locales/zh_CN.json +1 -1
- package/package.json +9 -6
- package/razzle.config.js +13 -4
- package/src/actions/form/form.js +18 -2
- package/src/actions/index.js +1 -1
- package/src/components/manage/Blocks/Block/BlocksForm.jsx +157 -81
- package/src/components/manage/Blocks/Block/BlocksForm.test.jsx +8 -0
- package/src/components/manage/Blocks/Block/Edit.jsx +37 -4
- package/src/components/manage/Blocks/Block/Order/Item.jsx +122 -0
- package/src/components/manage/Blocks/Block/Order/Order.jsx +367 -0
- package/src/components/manage/Blocks/Block/Order/SortableItem.jsx +58 -0
- package/src/components/manage/Blocks/Block/Order/utilities.js +113 -0
- package/src/components/manage/Blocks/Container/Edit.jsx +1 -0
- package/src/components/manage/Blocks/Grid/Edit.jsx +6 -4
- package/src/components/manage/Blocks/Image/schema.js +2 -0
- package/src/components/manage/Controlpanels/Relations/RelationsListing.jsx +1 -1
- package/src/components/manage/Controlpanels/Relations/RelationsMatrix.jsx +1 -1
- package/src/components/manage/Form/Form.jsx +159 -151
- package/src/components/manage/Sidebar/Sidebar.jsx +28 -1
- package/src/components/manage/Widgets/InternalUrlWidget.jsx +10 -14
- package/src/components/theme/FormattedDate/FormattedDate.jsx +13 -1
- package/src/components/theme/Icon/Icon.jsx +4 -4
- package/src/config/Loadables.jsx +18 -0
- package/src/constants/ActionTypes.js +1 -0
- package/src/helpers/Blocks/Blocks.js +182 -1
- package/src/helpers/Blocks/Blocks.test.js +136 -0
- package/src/helpers/index.js +4 -0
- package/src/reducers/form/form.js +18 -1
- package/src/reducers/form/form.test.js +15 -1
- package/theme/themes/pastanaga/extras/blocks.less +7 -6
- package/theme/themes/pastanaga/extras/sidebar.less +145 -0
- package/types/actions/form/form.d.ts +8 -1
- package/types/actions/index.d.ts +1 -1
- package/types/components/manage/Blocks/Block/Order/Item.d.ts +2 -0
- package/types/components/manage/Blocks/Block/Order/Order.d.ts +13 -0
- package/types/components/manage/Blocks/Block/Order/SortableItem.d.ts +9 -0
- package/types/components/manage/Blocks/Block/Order/utilities.d.ts +9 -0
- package/types/components/manage/Blocks/Image/schema.d.ts +2 -0
- package/types/components/theme/Icon/Icon.d.ts +8 -8
- package/types/config/Loadables.d.ts +15 -162
- package/types/constants/ActionTypes.d.ts +1 -0
- package/types/helpers/Blocks/Blocks.d.ts +13 -0
- package/types/helpers/index.d.ts +2 -2
|
@@ -52,6 +52,7 @@ import {
|
|
|
52
52
|
resetMetadataFocus,
|
|
53
53
|
setSidebarTab,
|
|
54
54
|
setFormData,
|
|
55
|
+
setUIState,
|
|
55
56
|
} from '@plone/volto/actions';
|
|
56
57
|
import { compose } from 'redux';
|
|
57
58
|
import config from '@plone/volto/registry';
|
|
@@ -230,13 +231,17 @@ class Form extends Component {
|
|
|
230
231
|
this.props.setFormData(formData);
|
|
231
232
|
}
|
|
232
233
|
|
|
234
|
+
this.props.setUIState({
|
|
235
|
+
selected: selectedBlock,
|
|
236
|
+
multiSelected: [],
|
|
237
|
+
hovered: null,
|
|
238
|
+
});
|
|
239
|
+
|
|
233
240
|
// Set initial state
|
|
234
241
|
this.state = {
|
|
235
242
|
formData,
|
|
236
243
|
initialFormData,
|
|
237
244
|
errors: {},
|
|
238
|
-
selected: selectedBlock,
|
|
239
|
-
multiSelected: [],
|
|
240
245
|
isClient: false,
|
|
241
246
|
// Ensure focus remain in field after change
|
|
242
247
|
inFocus: {},
|
|
@@ -263,6 +268,12 @@ class Form extends Component {
|
|
|
263
268
|
let errors = {};
|
|
264
269
|
let activeIndex = 0;
|
|
265
270
|
|
|
271
|
+
if (!this.props.isFormSelected && prevProps.isFormSelected) {
|
|
272
|
+
this.props.setUIState({
|
|
273
|
+
selected: null,
|
|
274
|
+
});
|
|
275
|
+
}
|
|
276
|
+
|
|
266
277
|
if (requestError && prevProps.requestError !== requestError) {
|
|
267
278
|
errors =
|
|
268
279
|
FormValidation.giveServerErrorsToCorrespondingFields(requestError);
|
|
@@ -376,15 +387,6 @@ class Form extends Component {
|
|
|
376
387
|
this.setState({ isClient: true });
|
|
377
388
|
}
|
|
378
389
|
|
|
379
|
-
static getDerivedStateFromProps(props, state) {
|
|
380
|
-
let newState = { ...state };
|
|
381
|
-
if (!props.isFormSelected) {
|
|
382
|
-
newState.selected = null;
|
|
383
|
-
}
|
|
384
|
-
|
|
385
|
-
return newState;
|
|
386
|
-
}
|
|
387
|
-
|
|
388
390
|
/**
|
|
389
391
|
* Change field handler
|
|
390
392
|
* Remove errors for changed field
|
|
@@ -439,9 +441,9 @@ class Form extends Component {
|
|
|
439
441
|
|
|
440
442
|
if (event.shiftKey) {
|
|
441
443
|
const anchor =
|
|
442
|
-
this.
|
|
443
|
-
? blocks_layout.indexOf(this.
|
|
444
|
-
: blocks_layout.indexOf(this.
|
|
444
|
+
this.props.uiState.multiSelected.length > 0
|
|
445
|
+
? blocks_layout.indexOf(this.props.uiState.multiSelected[0])
|
|
446
|
+
: blocks_layout.indexOf(this.props.uiState.selected);
|
|
445
447
|
const focus = blocks_layout.indexOf(id);
|
|
446
448
|
|
|
447
449
|
if (anchor === focus) {
|
|
@@ -451,15 +453,16 @@ class Form extends Component {
|
|
|
451
453
|
} else {
|
|
452
454
|
multiSelected = [...blocks_layout.slice(focus, anchor + 1)];
|
|
453
455
|
}
|
|
456
|
+
window.getSelection().empty();
|
|
454
457
|
}
|
|
455
458
|
|
|
456
459
|
if ((event.ctrlKey || event.metaKey) && !event.shiftKey) {
|
|
457
|
-
multiSelected = this.
|
|
458
|
-
if (!this.
|
|
459
|
-
multiSelected = [...multiSelected, this.
|
|
460
|
+
multiSelected = this.props.uiState.multiSelected || [];
|
|
461
|
+
if (!this.props.uiState.multiSelected.includes(this.state.selected)) {
|
|
462
|
+
multiSelected = [...multiSelected, this.props.uiState.selected];
|
|
460
463
|
selected = null;
|
|
461
464
|
}
|
|
462
|
-
if (this.
|
|
465
|
+
if (this.props.uiState.multiSelected.includes(id)) {
|
|
463
466
|
selected = null;
|
|
464
467
|
multiSelected = without(multiSelected, id);
|
|
465
468
|
} else {
|
|
@@ -468,9 +471,10 @@ class Form extends Component {
|
|
|
468
471
|
}
|
|
469
472
|
}
|
|
470
473
|
|
|
471
|
-
this.
|
|
474
|
+
this.props.setUIState({
|
|
472
475
|
selected,
|
|
473
476
|
multiSelected,
|
|
477
|
+
gridSelected: null,
|
|
474
478
|
});
|
|
475
479
|
|
|
476
480
|
if (this.props.onSelectForm) {
|
|
@@ -660,141 +664,143 @@ class Form extends Component {
|
|
|
660
664
|
/>
|
|
661
665
|
|
|
662
666
|
<Container>
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
this.props.
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
onSelectBlock={this.onSelectBlock}
|
|
683
|
-
/>
|
|
684
|
-
<UndoToolbar
|
|
685
|
-
state={{
|
|
686
|
-
formData,
|
|
687
|
-
selected: this.state.selected,
|
|
688
|
-
multiSelected: this.state.multiSelected,
|
|
689
|
-
}}
|
|
690
|
-
enableHotKeys
|
|
691
|
-
onUndoRedo={({ state }) => {
|
|
692
|
-
if (this.props.global) {
|
|
693
|
-
this.props.setFormData(state.formData);
|
|
667
|
+
<>
|
|
668
|
+
<BlocksToolbar
|
|
669
|
+
formData={formData}
|
|
670
|
+
selectedBlock={this.props.uiState.selected}
|
|
671
|
+
selectedBlocks={this.props.uiState.multiSelected}
|
|
672
|
+
onChangeBlocks={(newBlockData) => {
|
|
673
|
+
const newFormData = {
|
|
674
|
+
...formData,
|
|
675
|
+
...newBlockData,
|
|
676
|
+
};
|
|
677
|
+
this.setState({
|
|
678
|
+
formData: newFormData,
|
|
679
|
+
});
|
|
680
|
+
if (this.props.global) {
|
|
681
|
+
this.props.setFormData(newFormData);
|
|
682
|
+
}
|
|
683
|
+
}}
|
|
684
|
+
onSetSelectedBlocks={(blockIds) =>
|
|
685
|
+
this.props.setUIState({ multiSelected: blockIds })
|
|
694
686
|
}
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
this.
|
|
709
|
-
}
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
|
|
687
|
+
onSelectBlock={this.onSelectBlock}
|
|
688
|
+
/>
|
|
689
|
+
<UndoToolbar
|
|
690
|
+
state={{
|
|
691
|
+
formData,
|
|
692
|
+
selected: this.props.uiState.selected,
|
|
693
|
+
multiSelected: this.props.uiState.multiSelected,
|
|
694
|
+
}}
|
|
695
|
+
enableHotKeys
|
|
696
|
+
onUndoRedo={({ state }) => {
|
|
697
|
+
if (this.props.global) {
|
|
698
|
+
this.props.setFormData(state.formData);
|
|
699
|
+
}
|
|
700
|
+
return this.setState(state);
|
|
701
|
+
}}
|
|
702
|
+
/>
|
|
703
|
+
<BlocksForm
|
|
704
|
+
onChangeFormData={(newData) => {
|
|
705
|
+
const newFormData = {
|
|
706
|
+
...formData,
|
|
707
|
+
...newData,
|
|
708
|
+
};
|
|
709
|
+
this.setState({
|
|
710
|
+
formData: newFormData,
|
|
711
|
+
});
|
|
712
|
+
if (this.props.global) {
|
|
713
|
+
this.props.setFormData(newFormData);
|
|
714
|
+
}
|
|
715
|
+
}}
|
|
716
|
+
onChangeField={this.onChangeField}
|
|
717
|
+
onSelectBlock={this.onSelectBlock}
|
|
718
|
+
properties={formData}
|
|
719
|
+
navRoot={navRoot}
|
|
720
|
+
type={type}
|
|
721
|
+
pathname={this.props.pathname}
|
|
722
|
+
selectedBlock={this.props.uiState.selected}
|
|
723
|
+
multiSelected={this.props.uiState.multiSelected}
|
|
724
|
+
manage={this.props.isAdminForm}
|
|
725
|
+
allowedBlocks={this.props.allowedBlocks}
|
|
726
|
+
showRestricted={this.props.showRestricted}
|
|
727
|
+
editable={this.props.editable}
|
|
728
|
+
isMainForm={this.props.editable}
|
|
729
|
+
// Properties to pass to the BlocksForm to match the View ones
|
|
730
|
+
history={this.props.history}
|
|
731
|
+
location={this.props.location}
|
|
732
|
+
token={this.props.token}
|
|
733
|
+
/>
|
|
734
|
+
{this.state.isClient &&
|
|
735
|
+
this.state.sidebarMetadataIsAvailable &&
|
|
736
|
+
this.props.editable &&
|
|
737
|
+
createPortal(
|
|
738
|
+
<UiForm
|
|
739
|
+
method="post"
|
|
740
|
+
onSubmit={this.onSubmit}
|
|
741
|
+
error={keys(this.state.errors).length > 0}
|
|
742
|
+
>
|
|
743
|
+
{schema &&
|
|
744
|
+
map(schema.fieldsets, (fieldset) => (
|
|
745
|
+
<Accordion
|
|
746
|
+
fluid
|
|
747
|
+
styled
|
|
748
|
+
className="form"
|
|
749
|
+
key={fieldset.title}
|
|
749
750
|
>
|
|
750
|
-
<
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
onClick={this.onToggleMetadataFieldset}
|
|
754
|
-
>
|
|
755
|
-
{fieldset.title}
|
|
756
|
-
{metadataFieldsets.includes(fieldset.id) ? (
|
|
757
|
-
<Icon name={upSVG} size="20px" />
|
|
758
|
-
) : (
|
|
759
|
-
<Icon name={downSVG} size="20px" />
|
|
760
|
-
)}
|
|
761
|
-
</Accordion.Title>
|
|
762
|
-
<Accordion.Content
|
|
763
|
-
active={metadataFieldsets.includes(fieldset.id)}
|
|
751
|
+
<div
|
|
752
|
+
key={fieldset.id}
|
|
753
|
+
id={`metadataform-fieldset-${fieldset.id}`}
|
|
764
754
|
>
|
|
765
|
-
<
|
|
766
|
-
{
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
|
|
755
|
+
<Accordion.Title
|
|
756
|
+
active={metadataFieldsets.includes(fieldset.id)}
|
|
757
|
+
index={fieldset.id}
|
|
758
|
+
onClick={this.onToggleMetadataFieldset}
|
|
759
|
+
>
|
|
760
|
+
{fieldset.title}
|
|
761
|
+
{metadataFieldsets.includes(fieldset.id) ? (
|
|
762
|
+
<Icon name={upSVG} size="20px" />
|
|
763
|
+
) : (
|
|
764
|
+
<Icon name={downSVG} size="20px" />
|
|
765
|
+
)}
|
|
766
|
+
</Accordion.Title>
|
|
767
|
+
<Accordion.Content
|
|
768
|
+
active={metadataFieldsets.includes(fieldset.id)}
|
|
769
|
+
>
|
|
770
|
+
<Segment className="attached">
|
|
771
|
+
{map(fieldset.fields, (field, index) => (
|
|
772
|
+
<Field
|
|
773
|
+
{...schema.properties[field]}
|
|
774
|
+
id={field}
|
|
775
|
+
fieldSet={fieldset.title.toLowerCase()}
|
|
776
|
+
formData={formData}
|
|
777
|
+
focus={this.state.inFocus[field]}
|
|
778
|
+
value={formData?.[field]}
|
|
779
|
+
required={
|
|
780
|
+
schema.required.indexOf(field) !== -1
|
|
781
|
+
}
|
|
782
|
+
onChange={this.onChangeField}
|
|
783
|
+
onBlur={this.onBlurField}
|
|
784
|
+
onClick={this.onClickInput}
|
|
785
|
+
key={field}
|
|
786
|
+
error={this.state.errors[field]}
|
|
787
|
+
/>
|
|
788
|
+
))}
|
|
789
|
+
</Segment>
|
|
790
|
+
</Accordion.Content>
|
|
791
|
+
</div>
|
|
792
|
+
</Accordion>
|
|
793
|
+
))}
|
|
794
|
+
</UiForm>,
|
|
795
|
+
document.getElementById('sidebar-metadata'),
|
|
796
|
+
)}
|
|
797
|
+
|
|
798
|
+
<SlotRenderer
|
|
799
|
+
name="belowContent"
|
|
800
|
+
content={this.props.content}
|
|
801
|
+
navRoot={navRoot}
|
|
802
|
+
/>
|
|
803
|
+
</>
|
|
798
804
|
</Container>
|
|
799
805
|
</>
|
|
800
806
|
)
|
|
@@ -964,6 +970,7 @@ export default compose(
|
|
|
964
970
|
(state, props) => ({
|
|
965
971
|
content: state.content.data,
|
|
966
972
|
globalData: state.form?.global,
|
|
973
|
+
uiState: state.form?.ui,
|
|
967
974
|
metadataFieldsets: state.sidebar?.metadataFieldsets,
|
|
968
975
|
metadataFieldFocus: state.sidebar?.metadataFieldFocus,
|
|
969
976
|
}),
|
|
@@ -971,6 +978,7 @@ export default compose(
|
|
|
971
978
|
setMetadataFieldsets,
|
|
972
979
|
setSidebarTab,
|
|
973
980
|
setFormData,
|
|
981
|
+
setUIState,
|
|
974
982
|
resetMetadataFocus,
|
|
975
983
|
},
|
|
976
984
|
null,
|
|
@@ -34,12 +34,23 @@ const messages = defineMessages({
|
|
|
34
34
|
id: 'Expand sidebar',
|
|
35
35
|
defaultMessage: 'Expand sidebar',
|
|
36
36
|
},
|
|
37
|
+
order: {
|
|
38
|
+
id: 'Order',
|
|
39
|
+
defaultMessage: 'Order',
|
|
40
|
+
},
|
|
37
41
|
});
|
|
38
42
|
|
|
39
43
|
const Sidebar = (props) => {
|
|
40
44
|
const dispatch = useDispatch();
|
|
41
45
|
const intl = useIntl();
|
|
42
|
-
const {
|
|
46
|
+
const {
|
|
47
|
+
cookies,
|
|
48
|
+
content,
|
|
49
|
+
documentTab,
|
|
50
|
+
blockTab,
|
|
51
|
+
settingsTab,
|
|
52
|
+
orderTab = true,
|
|
53
|
+
} = props;
|
|
43
54
|
const [expanded, setExpanded] = useState(
|
|
44
55
|
cookies.get('sidebar_expanded') !== 'false',
|
|
45
56
|
);
|
|
@@ -172,6 +183,22 @@ const Sidebar = (props) => {
|
|
|
172
183
|
</Tab.Pane>
|
|
173
184
|
),
|
|
174
185
|
},
|
|
186
|
+
!!orderTab && {
|
|
187
|
+
menuItem: intl.formatMessage(messages.order),
|
|
188
|
+
pane: (
|
|
189
|
+
<Tab.Pane
|
|
190
|
+
key="order"
|
|
191
|
+
className="tab-wrapper"
|
|
192
|
+
id="sidebar-order"
|
|
193
|
+
>
|
|
194
|
+
<Icon
|
|
195
|
+
className="tab-forbidden"
|
|
196
|
+
name={forbiddenSVG}
|
|
197
|
+
size="48px"
|
|
198
|
+
/>
|
|
199
|
+
</Tab.Pane>
|
|
200
|
+
),
|
|
201
|
+
},
|
|
175
202
|
!!settingsTab && {
|
|
176
203
|
menuItem: intl.formatMessage(messages.settings),
|
|
177
204
|
pane: (
|
|
@@ -15,13 +15,13 @@ import navTreeSVG from '@plone/volto/icons/nav.svg';
|
|
|
15
15
|
|
|
16
16
|
/** Widget to edit urls
|
|
17
17
|
*
|
|
18
|
-
* This is
|
|
18
|
+
* This is a widget used for getting and setting an internal url. You can also use
|
|
19
19
|
* it by declaring a field like:
|
|
20
20
|
*
|
|
21
21
|
* ```jsx
|
|
22
22
|
* {
|
|
23
23
|
* title: "URL",
|
|
24
|
-
* widget: '
|
|
24
|
+
* widget: 'internal_url',
|
|
25
25
|
* }
|
|
26
26
|
* ```
|
|
27
27
|
*/
|
|
@@ -35,20 +35,20 @@ export const InternalUrlWidget = (props) => {
|
|
|
35
35
|
maxLength,
|
|
36
36
|
placeholder,
|
|
37
37
|
isDisabled,
|
|
38
|
+
value,
|
|
38
39
|
} = props;
|
|
39
40
|
const inputId = `field-${id}`;
|
|
40
41
|
|
|
41
|
-
const [value, setValue] = useState(flattenToAppURL(props.value));
|
|
42
42
|
const [isInvalid, setIsInvalid] = useState(false);
|
|
43
|
+
|
|
43
44
|
/**
|
|
44
45
|
* Clear handler
|
|
45
46
|
* @method clear
|
|
46
47
|
* @param {Object} value Value
|
|
47
|
-
* @returns {
|
|
48
|
+
* @returns {string} Empty string
|
|
48
49
|
*/
|
|
49
50
|
const clear = () => {
|
|
50
|
-
|
|
51
|
-
onChange(id, undefined);
|
|
51
|
+
onChange(id, '');
|
|
52
52
|
};
|
|
53
53
|
|
|
54
54
|
const onChangeValue = (_value) => {
|
|
@@ -63,8 +63,6 @@ export const InternalUrlWidget = (props) => {
|
|
|
63
63
|
}
|
|
64
64
|
}
|
|
65
65
|
|
|
66
|
-
setValue(newValue);
|
|
67
|
-
|
|
68
66
|
newValue = isInternalURL(newValue) ? flattenToAppURL(newValue) : newValue;
|
|
69
67
|
|
|
70
68
|
if (!isInternalURL(newValue) && newValue.length > 0) {
|
|
@@ -75,7 +73,7 @@ export const InternalUrlWidget = (props) => {
|
|
|
75
73
|
}
|
|
76
74
|
}
|
|
77
75
|
|
|
78
|
-
onChange(id, newValue
|
|
76
|
+
onChange(id, newValue);
|
|
79
77
|
};
|
|
80
78
|
|
|
81
79
|
return (
|
|
@@ -89,12 +87,10 @@ export const InternalUrlWidget = (props) => {
|
|
|
89
87
|
disabled={isDisabled}
|
|
90
88
|
placeholder={placeholder}
|
|
91
89
|
onChange={({ target }) => onChangeValue(target.value)}
|
|
92
|
-
onBlur={({ target }) =>
|
|
93
|
-
onBlur(id, target.value === '' ? undefined : target.value)
|
|
94
|
-
}
|
|
90
|
+
onBlur={({ target }) => onBlur(id, target.value)}
|
|
95
91
|
onClick={() => onClick()}
|
|
96
|
-
minLength={minLength
|
|
97
|
-
maxLength={maxLength
|
|
92
|
+
minLength={minLength}
|
|
93
|
+
maxLength={maxLength}
|
|
98
94
|
error={isInvalid}
|
|
99
95
|
/>
|
|
100
96
|
{value?.length > 0 ? (
|
|
@@ -18,13 +18,25 @@ const FormattedDate = ({
|
|
|
18
18
|
const language = useSelector((state) => locale || state.intl.locale);
|
|
19
19
|
const toDate = (d) => (typeof d === 'string' ? new Date(d) : d);
|
|
20
20
|
const args = { date, long, includeTime, format, locale: language };
|
|
21
|
+
const new_date = new Date(toDate(date));
|
|
22
|
+
// Dat check taken from https://stackoverflow.com/questions/1353684/detecting-an-invalid-date-date-instance-in-javascript#1353711
|
|
23
|
+
if (Object.prototype.toString.call(new_date) === '[object Date]') {
|
|
24
|
+
// it is a date
|
|
25
|
+
if (isNaN(new_date)) {
|
|
26
|
+
// date object is not valid
|
|
27
|
+
return <span>bad date</span>;
|
|
28
|
+
}
|
|
29
|
+
} else {
|
|
30
|
+
// not a date object
|
|
31
|
+
return <span>not a date</span>;
|
|
32
|
+
}
|
|
21
33
|
|
|
22
34
|
return (
|
|
23
35
|
<time
|
|
24
36
|
className={className}
|
|
25
37
|
dateTime={date}
|
|
26
38
|
title={new Intl.DateTimeFormat(language, long_date_format)
|
|
27
|
-
.format(
|
|
39
|
+
.format(new_date)
|
|
28
40
|
.replace('\u202F', ' ')}
|
|
29
41
|
>
|
|
30
42
|
{children
|
|
@@ -12,10 +12,10 @@ const defaultSize = '36px';
|
|
|
12
12
|
* @function Field
|
|
13
13
|
* @param {Object} props Component properties.
|
|
14
14
|
* @param {string} props.name Name source object.
|
|
15
|
-
* @param {string} props.size Size of the Icon (in px).
|
|
16
|
-
* @param {string} props.color Color of the Icon.
|
|
17
|
-
* @param {string} props.className className to add to the component.
|
|
18
|
-
* @param {string} props.title Title (a11y).
|
|
15
|
+
* @param {string} [props.size] Size of the Icon (in px).
|
|
16
|
+
* @param {string} [props.color] Color of the Icon.
|
|
17
|
+
* @param {string} [props.className] className to add to the component.
|
|
18
|
+
* @param {string} [props.title] Title (a11y).
|
|
19
19
|
* @returns {string} Markup of the component.
|
|
20
20
|
*
|
|
21
21
|
* Use:
|
package/src/config/Loadables.jsx
CHANGED
|
@@ -1,5 +1,20 @@
|
|
|
1
1
|
import loadable from '@loadable/component';
|
|
2
2
|
|
|
3
|
+
// This is to make happy the types declaration extractor (tsc) that is not able to
|
|
4
|
+
// extract one private method the types from `@dnd-kit` library:
|
|
5
|
+
// error TS9006: Declaration emit for this file requires using private name
|
|
6
|
+
// 'DefaultDropAnimationSideEffectsOptions' from module '".../node_modules/@dnd-kit/core/dist/components/DragOverlay/hooks/useDropAnimation"'.
|
|
7
|
+
// An explicit type annotation may unblock declaration emit
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* @typedef {Object} LoadableLib
|
|
11
|
+
* @property {() => Promise<any>} import
|
|
12
|
+
* @property {Object} [options]
|
|
13
|
+
*/
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* @type {{ [key: string]: LoadableLib }}
|
|
17
|
+
*/
|
|
3
18
|
export const loadables = {
|
|
4
19
|
prettierStandalone: loadable.lib(() => import('prettier/standalone')),
|
|
5
20
|
prettierParserHtml: loadable.lib(() => import('prettier/plugins/html')),
|
|
@@ -35,4 +50,7 @@ export const loadables = {
|
|
|
35
50
|
reactDndHtml5Backend: loadable.lib(() => import('react-dnd-html5-backend')),
|
|
36
51
|
reactBeautifulDnd: loadable.lib(() => import('react-beautiful-dnd')),
|
|
37
52
|
rrule: loadable.lib(() => import('rrule')),
|
|
53
|
+
dndKitCore: loadable.lib(() => import('@dnd-kit/core')),
|
|
54
|
+
dndKitSortable: loadable.lib(() => import('@dnd-kit/sortable')),
|
|
55
|
+
dndKitUtilities: loadable.lib(() => import('@dnd-kit/utilities')),
|
|
38
56
|
};
|
|
@@ -145,4 +145,5 @@ export const RESET_LOGIN_REQUEST = 'RESET_LOGIN_REQUEST';
|
|
|
145
145
|
export const GET_SITE = 'GET_SITE';
|
|
146
146
|
export const GET_NAVROOT = 'GET_NAVROOT';
|
|
147
147
|
export const SET_FORM_DATA = 'SET_FORM_DATA';
|
|
148
|
+
export const SET_UI_STATE = 'SET_UI_STATE';
|
|
148
149
|
export const UPDATE_UPLOADED_FILES = 'UPDATE_UPLOADED_FILES';
|