@plone/volto 14.3.0 → 14.7.0
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 +48 -0
- package/addon-registry.js +15 -2
- 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/fr/LC_MESSAGES/volto.po +5 -0
- package/locales/fr.json +1 -1
- package/locales/it/LC_MESSAGES/volto.po +10 -5
- 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 +6 -1
- package/package.json +4 -2
- package/razzle.config.js +1 -1
- package/src/components/index.js +2 -0
- package/src/components/manage/Add/Add.jsx +14 -3
- package/src/components/manage/Blocks/Block/BlocksForm.test.jsx +6 -0
- package/src/components/manage/Blocks/Listing/ListingBody.jsx +6 -0
- package/src/components/manage/Contents/Contents.jsx +15 -6
- package/src/components/manage/Contents/Contents.test.jsx +0 -7
- package/src/components/manage/Contents/ContentsIndexHeader.jsx +46 -34
- package/src/components/manage/Contents/ContentsItem.jsx +69 -61
- package/src/components/manage/Contents/ContentsUploadModal.jsx +2 -4
- package/src/components/manage/Controlpanels/ModerateComments.jsx +7 -5
- package/src/components/manage/Diff/Diff.jsx +13 -5
- package/src/components/manage/Diff/Diff.test.jsx +0 -6
- package/src/components/manage/Diff/DiffField.jsx +12 -3
- package/src/components/manage/Diff/DiffField.test.jsx +0 -6
- package/src/components/manage/DragDropList/DragDropList.jsx +4 -2
- package/src/components/manage/Form/Field.jsx +12 -2
- package/src/components/manage/History/History.jsx +6 -5
- package/src/components/manage/History/History.test.jsx +12 -7
- package/src/components/manage/Widgets/DatetimeWidget.jsx +10 -3
- package/src/components/manage/Widgets/DatetimeWidget.test.jsx +2 -2
- package/src/components/manage/Widgets/FormFieldWrapper.jsx +14 -1
- package/src/components/manage/Widgets/ObjectListWidget.stories.js +3 -3
- package/src/components/manage/Widgets/ObjectListWidget.test.js +6 -0
- package/src/components/manage/Widgets/RecurrenceWidget/ByDayField.jsx +4 -3
- package/src/components/manage/Widgets/RecurrenceWidget/MonthOfTheYearField.jsx +10 -3
- package/src/components/manage/Widgets/RecurrenceWidget/Occurences.jsx +8 -4
- package/src/components/manage/Widgets/RecurrenceWidget/RecurrenceWidget.jsx +21 -13
- package/src/components/manage/Widgets/RecurrenceWidget/RecurrenceWidget.test.jsx +6 -0
- package/src/components/manage/Widgets/RecurrenceWidget/Utils.js +1 -2
- package/src/components/manage/Widgets/RecurrenceWidget/WeekdayOfTheMonthField.jsx +5 -3
- package/src/components/manage/Widgets/SchemaWidget.jsx +4 -2
- package/src/components/manage/Widgets/SchemaWidget.test.jsx +6 -0
- package/src/components/manage/Widgets/SchemaWidgetFieldset.jsx +8 -4
- package/src/components/manage/Widgets/SchemaWidgetFieldset.test.jsx +7 -1
- package/src/components/manage/Widgets/VocabularyTermsWidget.jsx +41 -7
- package/src/components/manage/Widgets/VocabularyTermsWidget.stories.js +6 -21
- package/src/components/manage/Widgets/VocabularyTermsWidget.test.jsx +6 -0
- package/src/components/theme/Comments/Comments.jsx +3 -1
- package/src/components/theme/Comments/Comments.test.jsx +6 -0
- package/src/components/theme/FormattedDate/FormattedDate.jsx +42 -0
- package/src/components/theme/FormattedDate/FormattedDate.stories.jsx +91 -0
- package/src/components/theme/FormattedDate/FormattedRelativeDate.jsx +57 -0
- package/src/components/theme/FormattedDate/FormattedRelativeDate.stories.jsx +122 -0
- package/src/components/theme/Navigation/Navigation.jsx +1 -1
- package/src/components/theme/View/EventDatesInfo.jsx +12 -6
- package/src/components/theme/View/EventDatesInfo.test.jsx +6 -0
- package/src/components/theme/View/EventView.test.jsx +6 -0
- package/src/config/Loadables.jsx +3 -0
- package/src/config/index.js +1 -0
- package/src/helpers/Content/Content.js +16 -0
- package/src/helpers/Content/Content.test.js +20 -1
- package/src/helpers/FormValidation/FormValidation.js +1 -1
- package/src/helpers/Utils/Date.js +97 -0
- package/src/helpers/Utils/Date.test.js +197 -0
- package/src/helpers/Utils/Utils.js +1 -2
- package/src/helpers/Utils/Utils.test.js +25 -0
- package/src/helpers/index.js +1 -0
- package/theme/themes/pastanaga/extras/widgets.less +12 -0
- package/volto.config.js +3 -3
|
@@ -8,10 +8,8 @@ import { Button, Dropdown, Table } from 'semantic-ui-react';
|
|
|
8
8
|
import { Link } from 'react-router-dom';
|
|
9
9
|
import PropTypes from 'prop-types';
|
|
10
10
|
import { map } from 'lodash';
|
|
11
|
-
import moment from 'moment';
|
|
12
|
-
import { DragSource, DropTarget } from 'react-dnd';
|
|
13
11
|
import { useIntl, defineMessages, FormattedMessage } from 'react-intl';
|
|
14
|
-
import {
|
|
12
|
+
import { Circle, FormattedDate, Icon } from '@plone/volto/components';
|
|
15
13
|
import { getContentIcon } from '@plone/volto/helpers';
|
|
16
14
|
import moreSVG from '@plone/volto/icons/more.svg';
|
|
17
15
|
import checkboxUncheckedSVG from '@plone/volto/icons/checkbox-unchecked.svg';
|
|
@@ -26,6 +24,8 @@ import editingSVG from '@plone/volto/icons/editing.svg';
|
|
|
26
24
|
import dragSVG from '@plone/volto/icons/drag.svg';
|
|
27
25
|
import cx from 'classnames';
|
|
28
26
|
|
|
27
|
+
import { injectLazyLibs } from '@plone/volto/helpers/Loadable/Loadable';
|
|
28
|
+
|
|
29
29
|
const messages = defineMessages({
|
|
30
30
|
private: {
|
|
31
31
|
id: 'private',
|
|
@@ -47,6 +47,10 @@ const messages = defineMessages({
|
|
|
47
47
|
id: 'no workflow state',
|
|
48
48
|
defaultMessage: 'No workflow state',
|
|
49
49
|
},
|
|
50
|
+
none: {
|
|
51
|
+
id: 'None',
|
|
52
|
+
defaultMessage: 'None',
|
|
53
|
+
},
|
|
50
54
|
});
|
|
51
55
|
|
|
52
56
|
function getColor(string) {
|
|
@@ -186,21 +190,13 @@ export const ContentsItemComponent = ({
|
|
|
186
190
|
</div>
|
|
187
191
|
)}
|
|
188
192
|
{index.type === 'date' && (
|
|
189
|
-
|
|
190
|
-
title={
|
|
191
|
-
item[index.id] !== 'None' ? (
|
|
192
|
-
moment(item[index.id]).format('LLLL')
|
|
193
|
-
) : (
|
|
194
|
-
<FormattedMessage id="None" defaultMessage="None" />
|
|
195
|
-
)
|
|
196
|
-
}
|
|
197
|
-
>
|
|
193
|
+
<>
|
|
198
194
|
{item[index.id] !== 'None' ? (
|
|
199
|
-
|
|
195
|
+
<FormattedDate date={item[index.id]} />
|
|
200
196
|
) : (
|
|
201
|
-
|
|
197
|
+
intl.formatMessage(messages.none)
|
|
202
198
|
)}
|
|
203
|
-
|
|
199
|
+
</>
|
|
204
200
|
)}
|
|
205
201
|
{index.type === 'array' && (
|
|
206
202
|
<span>{item[index.id]?.join(', ')}</span>
|
|
@@ -313,55 +309,67 @@ ContentsItemComponent.propTypes = {
|
|
|
313
309
|
onOrderItem: PropTypes.func.isRequired,
|
|
314
310
|
};
|
|
315
311
|
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
{
|
|
319
|
-
hover(props, monitor) {
|
|
320
|
-
const id = monitor.getItem().id;
|
|
321
|
-
const dragOrder = monitor.getItem().order;
|
|
322
|
-
const hoverOrder = props.order;
|
|
312
|
+
const DragDropConnector = (props) => {
|
|
313
|
+
const { DropTarget, DragSource } = props.reactDnd;
|
|
323
314
|
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
315
|
+
const DndConnectedContentsItem = React.useMemo(
|
|
316
|
+
() =>
|
|
317
|
+
DropTarget(
|
|
318
|
+
'item',
|
|
319
|
+
{
|
|
320
|
+
hover(props, monitor) {
|
|
321
|
+
const id = monitor.getItem().id;
|
|
322
|
+
const dragOrder = monitor.getItem().order;
|
|
323
|
+
const hoverOrder = props.order;
|
|
327
324
|
|
|
328
|
-
|
|
325
|
+
if (dragOrder === hoverOrder) {
|
|
326
|
+
return;
|
|
327
|
+
}
|
|
329
328
|
|
|
330
|
-
|
|
331
|
-
},
|
|
332
|
-
drop(props, monitor) {
|
|
333
|
-
const id = monitor.getItem().id;
|
|
334
|
-
const dragOrder = monitor.getItem().startOrder;
|
|
335
|
-
const dropOrder = props.order;
|
|
329
|
+
props.onOrderItem(id, dragOrder, hoverOrder - dragOrder, false);
|
|
336
330
|
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
331
|
+
monitor.getItem().order = hoverOrder;
|
|
332
|
+
},
|
|
333
|
+
drop(props, monitor) {
|
|
334
|
+
const id = monitor.getItem().id;
|
|
335
|
+
const dragOrder = monitor.getItem().startOrder;
|
|
336
|
+
const dropOrder = props.order;
|
|
340
337
|
|
|
341
|
-
|
|
338
|
+
if (dragOrder === dropOrder) {
|
|
339
|
+
return;
|
|
340
|
+
}
|
|
342
341
|
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
)
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
)
|
|
342
|
+
props.onOrderItem(id, dragOrder, dropOrder - dragOrder, true);
|
|
343
|
+
|
|
344
|
+
monitor.getItem().order = dropOrder;
|
|
345
|
+
},
|
|
346
|
+
},
|
|
347
|
+
(connect) => ({
|
|
348
|
+
connectDropTarget: connect.dropTarget(),
|
|
349
|
+
}),
|
|
350
|
+
)(
|
|
351
|
+
DragSource(
|
|
352
|
+
'item',
|
|
353
|
+
{
|
|
354
|
+
beginDrag(props) {
|
|
355
|
+
return {
|
|
356
|
+
id: props.item['@id'],
|
|
357
|
+
order: props.order,
|
|
358
|
+
startOrder: props.order,
|
|
359
|
+
};
|
|
360
|
+
},
|
|
361
|
+
},
|
|
362
|
+
(connect, monitor) => ({
|
|
363
|
+
connectDragSource: connect.dragSource(),
|
|
364
|
+
connectDragPreview: connect.dragPreview(),
|
|
365
|
+
isDragging: monitor.isDragging(),
|
|
366
|
+
}),
|
|
367
|
+
)(ContentsItemComponent),
|
|
368
|
+
),
|
|
369
|
+
[DragSource, DropTarget],
|
|
370
|
+
);
|
|
371
|
+
|
|
372
|
+
return <DndConnectedContentsItem {...props} />;
|
|
373
|
+
};
|
|
374
|
+
|
|
375
|
+
export default injectLazyLibs('reactDnd')(DragDropConnector);
|
|
@@ -20,10 +20,10 @@ import {
|
|
|
20
20
|
} from 'semantic-ui-react';
|
|
21
21
|
import loadable from '@loadable/component';
|
|
22
22
|
import { concat, filter, map } from 'lodash';
|
|
23
|
-
import moment from 'moment';
|
|
24
23
|
import filesize from 'filesize';
|
|
25
24
|
import { readAsDataURL } from 'promise-file-reader';
|
|
26
25
|
import { FormattedMessage, defineMessages, injectIntl } from 'react-intl';
|
|
26
|
+
import { FormattedRelativeDate } from '@plone/volto/components';
|
|
27
27
|
import { createContent } from '@plone/volto/actions';
|
|
28
28
|
|
|
29
29
|
const Dropzone = loadable(() => import('react-dropzone'));
|
|
@@ -180,8 +180,6 @@ class ContentsUploadModal extends Component {
|
|
|
180
180
|
* @returns {string} Markup for the component.
|
|
181
181
|
*/
|
|
182
182
|
render() {
|
|
183
|
-
moment.locale(this.props.intl.locale);
|
|
184
|
-
|
|
185
183
|
return (
|
|
186
184
|
this.props.open && (
|
|
187
185
|
<Modal open={this.props.open}>
|
|
@@ -269,7 +267,7 @@ class ContentsUploadModal extends Component {
|
|
|
269
267
|
<Table.Row className="upload-row" key={file.name}>
|
|
270
268
|
<Table.Cell>{file.name}</Table.Cell>
|
|
271
269
|
<Table.Cell>
|
|
272
|
-
{
|
|
270
|
+
<FormattedRelativeDate date={file.lastModifiedDate} />
|
|
273
271
|
</Table.Cell>
|
|
274
272
|
<Table.Cell>
|
|
275
273
|
{filesize(file.size, { round: 0 })}
|
|
@@ -11,11 +11,15 @@ import { Link } from 'react-router-dom';
|
|
|
11
11
|
import { getParentUrl, Helmet } from '@plone/volto/helpers';
|
|
12
12
|
import { Portal } from 'react-portal';
|
|
13
13
|
import { Container, Button, Table } from 'semantic-ui-react';
|
|
14
|
-
import moment from 'moment';
|
|
15
14
|
import { FormattedMessage, defineMessages, injectIntl } from 'react-intl';
|
|
16
15
|
|
|
17
16
|
import { deleteComment, searchContent } from '@plone/volto/actions';
|
|
18
|
-
import {
|
|
17
|
+
import {
|
|
18
|
+
CommentEditModal,
|
|
19
|
+
FormattedRelativeDate,
|
|
20
|
+
Icon,
|
|
21
|
+
Toolbar,
|
|
22
|
+
} from '@plone/volto/components';
|
|
19
23
|
|
|
20
24
|
import backSVG from '@plone/volto/icons/back.svg';
|
|
21
25
|
|
|
@@ -230,9 +234,7 @@ class ModerateComments extends Component {
|
|
|
230
234
|
<Table.Row key={item['@id']}>
|
|
231
235
|
<Table.Cell>{item.author_name}</Table.Cell>
|
|
232
236
|
<Table.Cell>
|
|
233
|
-
<
|
|
234
|
-
{moment(item.creation_date).fromNow()}
|
|
235
|
-
</span>
|
|
237
|
+
<FormattedRelativeDate date={item.creation_date} />
|
|
236
238
|
</Table.Cell>
|
|
237
239
|
<Table.Cell>{item.text.data}</Table.Cell>
|
|
238
240
|
<Table.Cell>
|
|
@@ -12,7 +12,6 @@ import { filter, isEqual, map } from 'lodash';
|
|
|
12
12
|
import { Container, Button, Dropdown, Grid, Table } from 'semantic-ui-react';
|
|
13
13
|
import { Link, withRouter } from 'react-router-dom';
|
|
14
14
|
import { Portal } from 'react-portal';
|
|
15
|
-
import moment from 'moment';
|
|
16
15
|
import { FormattedMessage, defineMessages, injectIntl } from 'react-intl';
|
|
17
16
|
import qs from 'query-string';
|
|
18
17
|
|
|
@@ -23,7 +22,12 @@ import {
|
|
|
23
22
|
getBlocksLayoutFieldname,
|
|
24
23
|
hasBlocksData,
|
|
25
24
|
} from '@plone/volto/helpers';
|
|
26
|
-
import {
|
|
25
|
+
import {
|
|
26
|
+
DiffField,
|
|
27
|
+
FormattedDate,
|
|
28
|
+
Icon,
|
|
29
|
+
Toolbar,
|
|
30
|
+
} from '@plone/volto/components';
|
|
27
31
|
|
|
28
32
|
import backSVG from '@plone/volto/icons/back.svg';
|
|
29
33
|
|
|
@@ -189,9 +193,13 @@ class Diff extends Component {
|
|
|
189
193
|
const versions = map(
|
|
190
194
|
filter(this.props.historyEntries, (entry) => 'version' in entry),
|
|
191
195
|
(entry, index) => ({
|
|
192
|
-
text:
|
|
193
|
-
|
|
194
|
-
|
|
196
|
+
text: (
|
|
197
|
+
<>
|
|
198
|
+
{index === 0 ? 'Current' : entry.version} (
|
|
199
|
+
<FormattedDate date={entry.time} long className="text" />,
|
|
200
|
+
{entry.actor.fullname})
|
|
201
|
+
</>
|
|
202
|
+
),
|
|
195
203
|
value: `${entry.version}`,
|
|
196
204
|
key: `${entry.version}`,
|
|
197
205
|
}),
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
|
-
// import renderer from 'react-test-renderer';
|
|
3
2
|
import configureStore from 'redux-mock-store';
|
|
4
3
|
import { Provider } from 'react-intl-redux';
|
|
5
4
|
import { MemoryRouter } from 'react-router-dom';
|
|
@@ -12,11 +11,6 @@ const mockStore = configureStore();
|
|
|
12
11
|
jest.mock('react-portal', () => ({
|
|
13
12
|
Portal: jest.fn(() => <div id="Portal" />),
|
|
14
13
|
}));
|
|
15
|
-
jest.mock('moment', () =>
|
|
16
|
-
jest.fn(() => ({
|
|
17
|
-
format: jest.fn(() => 'Sunday, April 23, 2017 3:38 AM'),
|
|
18
|
-
})),
|
|
19
|
-
);
|
|
20
14
|
|
|
21
15
|
jest.mock('@plone/volto/helpers/Loadable/Loadable');
|
|
22
16
|
beforeAll(
|
|
@@ -8,11 +8,11 @@ import React from 'react';
|
|
|
8
8
|
import { join, map } from 'lodash';
|
|
9
9
|
import PropTypes from 'prop-types';
|
|
10
10
|
import { Table } from 'semantic-ui-react';
|
|
11
|
-
import moment from 'moment';
|
|
12
11
|
import ReactDOMServer from 'react-dom/server';
|
|
13
12
|
import { Provider } from 'react-intl-redux';
|
|
14
13
|
import { createBrowserHistory } from 'history';
|
|
15
14
|
import { ConnectedRouter } from 'connected-react-router';
|
|
15
|
+
import { useSelector } from 'react-redux';
|
|
16
16
|
|
|
17
17
|
import { Api } from '@plone/volto/helpers';
|
|
18
18
|
import configureStore from '@plone/volto/store';
|
|
@@ -44,6 +44,11 @@ const DiffField = ({
|
|
|
44
44
|
schema,
|
|
45
45
|
diffLib,
|
|
46
46
|
}) => {
|
|
47
|
+
const language = useSelector((state) => state.intl.locale);
|
|
48
|
+
const readable_date_format = {
|
|
49
|
+
dateStyle: 'full',
|
|
50
|
+
timeStyle: 'short',
|
|
51
|
+
};
|
|
47
52
|
const diffWords = (oneStr, twoStr) => {
|
|
48
53
|
return diffLib.diffWords(String(oneStr), String(twoStr));
|
|
49
54
|
};
|
|
@@ -56,8 +61,12 @@ const DiffField = ({
|
|
|
56
61
|
break;
|
|
57
62
|
case 'datetime':
|
|
58
63
|
parts = diffWords(
|
|
59
|
-
|
|
60
|
-
|
|
64
|
+
new Intl.DateTimeFormat(language, readable_date_format).format(
|
|
65
|
+
new Date(one),
|
|
66
|
+
),
|
|
67
|
+
new Intl.DateTimeFormat(language, readable_date_format).format(
|
|
68
|
+
new Date(two),
|
|
69
|
+
),
|
|
61
70
|
);
|
|
62
71
|
break;
|
|
63
72
|
case 'json':
|
|
@@ -5,12 +5,6 @@ import { waitFor, render, screen } from '@testing-library/react';
|
|
|
5
5
|
|
|
6
6
|
import DiffField from './DiffField';
|
|
7
7
|
|
|
8
|
-
jest.mock('moment', () =>
|
|
9
|
-
jest.fn(() => ({
|
|
10
|
-
format: jest.fn(() => 'Sunday, April 23, 2017 3:38 AM'),
|
|
11
|
-
})),
|
|
12
|
-
);
|
|
13
|
-
|
|
14
8
|
jest.mock('@plone/volto/helpers/Loadable/Loadable');
|
|
15
9
|
beforeAll(
|
|
16
10
|
async () =>
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import React, { useRef } from 'react';
|
|
2
2
|
import { isEmpty } from 'lodash';
|
|
3
|
-
import {
|
|
3
|
+
import { injectLazyLibs } from '@plone/volto/helpers/Loadable/Loadable';
|
|
4
4
|
import { v4 as uuid } from 'uuid';
|
|
5
5
|
|
|
6
6
|
const getPlaceholder = (draggedDOM, sourceIndex, destinationIndex) => {
|
|
@@ -55,7 +55,9 @@ const DragDropList = (props) => {
|
|
|
55
55
|
as = 'div',
|
|
56
56
|
style,
|
|
57
57
|
forwardedAriaLabelledBy,
|
|
58
|
+
reactBeautifulDnd,
|
|
58
59
|
} = props; //renderChild
|
|
60
|
+
const { DragDropContext, Draggable, Droppable } = reactBeautifulDnd;
|
|
59
61
|
const [placeholderProps, setPlaceholderProps] = React.useState({});
|
|
60
62
|
const [uid] = React.useState(uuid());
|
|
61
63
|
// queueing timed action
|
|
@@ -157,4 +159,4 @@ const DragDropList = (props) => {
|
|
|
157
159
|
);
|
|
158
160
|
};
|
|
159
161
|
|
|
160
|
-
export default DragDropList;
|
|
162
|
+
export default injectLazyLibs(['reactBeautifulDnd'])(DragDropList);
|
|
@@ -5,9 +5,9 @@
|
|
|
5
5
|
|
|
6
6
|
import React from 'react';
|
|
7
7
|
import PropTypes from 'prop-types';
|
|
8
|
-
import { DragSource, DropTarget } from 'react-dnd';
|
|
9
8
|
import { injectIntl } from 'react-intl';
|
|
10
9
|
import config from '@plone/volto/registry';
|
|
10
|
+
import { injectLazyLibs } from '@plone/volto/helpers/Loadable/Loadable';
|
|
11
11
|
|
|
12
12
|
const MODE_HIDDEN = 'hidden'; //hidden mode. If mode is hidden, field is not rendered
|
|
13
13
|
/**
|
|
@@ -150,7 +150,7 @@ const getWidgetByType = (type) => config.widgets.type[type] || null;
|
|
|
150
150
|
* @param {Object} props Properties.
|
|
151
151
|
* @returns {string} Markup of the component.
|
|
152
152
|
*/
|
|
153
|
-
const
|
|
153
|
+
const UnconnectedField = (props, { intl }) => {
|
|
154
154
|
const Widget =
|
|
155
155
|
getWidgetByFieldId(props.id) ||
|
|
156
156
|
getWidgetFromTaggedValues(props.widgetOptions) ||
|
|
@@ -173,6 +173,7 @@ const Field = (props, { intl }) => {
|
|
|
173
173
|
};
|
|
174
174
|
|
|
175
175
|
if (props.onOrder) {
|
|
176
|
+
const { DropTarget, DragSource } = props.reactDnd;
|
|
176
177
|
const WrappedWidget = DropTarget(
|
|
177
178
|
'field',
|
|
178
179
|
{
|
|
@@ -230,6 +231,15 @@ const Field = (props, { intl }) => {
|
|
|
230
231
|
return <Widget {...widgetProps} />;
|
|
231
232
|
};
|
|
232
233
|
|
|
234
|
+
const DndConnectedField = injectLazyLibs(['reactDnd'])(UnconnectedField);
|
|
235
|
+
|
|
236
|
+
const Field = (props) =>
|
|
237
|
+
props.onOrder ? (
|
|
238
|
+
<DndConnectedField {...props} />
|
|
239
|
+
) : (
|
|
240
|
+
<UnconnectedField {...props} />
|
|
241
|
+
);
|
|
242
|
+
|
|
233
243
|
/**
|
|
234
244
|
* Property types.
|
|
235
245
|
* @property {Object} propTypes Property types.
|
|
@@ -12,10 +12,13 @@ import { compose } from 'redux';
|
|
|
12
12
|
import { Container, Dropdown, Icon, Segment, Table } from 'semantic-ui-react';
|
|
13
13
|
import { concat, map, reverse } from 'lodash';
|
|
14
14
|
import { Portal } from 'react-portal';
|
|
15
|
-
import moment from 'moment';
|
|
16
15
|
import { FormattedMessage, defineMessages, injectIntl } from 'react-intl';
|
|
17
16
|
|
|
18
|
-
import {
|
|
17
|
+
import {
|
|
18
|
+
FormattedRelativeDate,
|
|
19
|
+
Icon as IconNext,
|
|
20
|
+
Toolbar,
|
|
21
|
+
} from '@plone/volto/components';
|
|
19
22
|
import { getHistory, revertHistory } from '@plone/volto/actions';
|
|
20
23
|
import { getBaseUrl } from '@plone/volto/helpers';
|
|
21
24
|
|
|
@@ -206,9 +209,7 @@ class History extends Component {
|
|
|
206
209
|
</Table.Cell>
|
|
207
210
|
<Table.Cell>{entry.actor.fullname}</Table.Cell>
|
|
208
211
|
<Table.Cell>
|
|
209
|
-
<
|
|
210
|
-
{moment(entry.time).fromNow()}
|
|
211
|
-
</span>
|
|
212
|
+
<FormattedRelativeDate date={entry.time} />
|
|
212
213
|
</Table.Cell>
|
|
213
214
|
<Table.Cell>{entry.comments}</Table.Cell>
|
|
214
215
|
<Table.Cell>
|
|
@@ -3,21 +3,26 @@ import renderer from 'react-test-renderer';
|
|
|
3
3
|
import configureStore from 'redux-mock-store';
|
|
4
4
|
import { Provider } from 'react-intl-redux';
|
|
5
5
|
|
|
6
|
+
import FakeTimers from '@sinonjs/fake-timers';
|
|
7
|
+
|
|
6
8
|
import History from './History';
|
|
7
9
|
|
|
8
10
|
const mockStore = configureStore();
|
|
9
|
-
|
|
10
11
|
jest.mock('react-portal', () => ({
|
|
11
12
|
Portal: jest.fn(() => <div id="Portal" />),
|
|
12
13
|
}));
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
format: jest.fn(() => 'Sunday, April 23, 2017 3:38 AM'),
|
|
16
|
-
fromNow: jest.fn(() => 'a few seconds ago'),
|
|
17
|
-
})),
|
|
18
|
-
);
|
|
14
|
+
|
|
15
|
+
const FIXED_SYSTEM_TIME = '2017-04-23T15:38:00.000Z';
|
|
19
16
|
|
|
20
17
|
describe('History', () => {
|
|
18
|
+
let clock;
|
|
19
|
+
beforeEach(() => {
|
|
20
|
+
clock = FakeTimers.install({ now: Date.parse(FIXED_SYSTEM_TIME) });
|
|
21
|
+
});
|
|
22
|
+
afterEach(() => {
|
|
23
|
+
clock.uninstall();
|
|
24
|
+
});
|
|
25
|
+
|
|
21
26
|
it('renders a history component', () => {
|
|
22
27
|
const store = mockStore({
|
|
23
28
|
history: {
|
|
@@ -93,7 +93,7 @@ export class DatetimeWidgetComponent extends Component {
|
|
|
93
93
|
*/
|
|
94
94
|
constructor(props) {
|
|
95
95
|
super(props);
|
|
96
|
-
|
|
96
|
+
this.moment = props.moment.default;
|
|
97
97
|
|
|
98
98
|
this.state = {
|
|
99
99
|
focused: false,
|
|
@@ -102,12 +102,19 @@ export class DatetimeWidgetComponent extends Component {
|
|
|
102
102
|
parseDateTime(
|
|
103
103
|
this.props.intl.locale,
|
|
104
104
|
this.props.value,
|
|
105
|
-
|
|
105
|
+
undefined,
|
|
106
|
+
this.moment,
|
|
107
|
+
)?.toISOString() === this.moment().utc().toISOString(),
|
|
106
108
|
};
|
|
107
109
|
}
|
|
108
110
|
|
|
109
111
|
getInternalValue() {
|
|
110
|
-
return parseDateTime(
|
|
112
|
+
return parseDateTime(
|
|
113
|
+
this.props.intl.locale,
|
|
114
|
+
this.props.value,
|
|
115
|
+
undefined,
|
|
116
|
+
this.moment,
|
|
117
|
+
);
|
|
111
118
|
}
|
|
112
119
|
|
|
113
120
|
getDateOnly() {
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import moment from 'moment';
|
|
2
1
|
import React from 'react';
|
|
3
2
|
import { Provider } from 'react-intl-redux';
|
|
4
3
|
import configureStore from 'redux-mock-store';
|
|
@@ -20,6 +19,7 @@ test('renders a datetime widget component', async () => {
|
|
|
20
19
|
messages: {},
|
|
21
20
|
},
|
|
22
21
|
});
|
|
22
|
+
const isoDate = new Date('2019-10-21').toISOString();
|
|
23
23
|
const { container } = render(
|
|
24
24
|
<Provider store={store}>
|
|
25
25
|
<DatetimeWidget
|
|
@@ -27,7 +27,7 @@ test('renders a datetime widget component', async () => {
|
|
|
27
27
|
title="My field"
|
|
28
28
|
fieldSet="default"
|
|
29
29
|
onChange={() => {}}
|
|
30
|
-
value={
|
|
30
|
+
value={isoDate}
|
|
31
31
|
/>
|
|
32
32
|
</Provider>,
|
|
33
33
|
);
|
|
@@ -18,6 +18,10 @@ const messages = defineMessages({
|
|
|
18
18
|
id: 'Delete',
|
|
19
19
|
defaultMessage: 'Delete',
|
|
20
20
|
},
|
|
21
|
+
language_independent: {
|
|
22
|
+
id: 'Language independent field.',
|
|
23
|
+
defaultMessage: 'Language independent field.',
|
|
24
|
+
},
|
|
21
25
|
});
|
|
22
26
|
/**
|
|
23
27
|
* FormFieldWrapper component class.
|
|
@@ -85,6 +89,7 @@ class FormFieldWrapper extends Component {
|
|
|
85
89
|
onDelete,
|
|
86
90
|
intl,
|
|
87
91
|
noForInFieldLabel,
|
|
92
|
+
multilingual_options,
|
|
88
93
|
} = this.props;
|
|
89
94
|
const wdg = (
|
|
90
95
|
<>
|
|
@@ -107,6 +112,9 @@ class FormFieldWrapper extends Component {
|
|
|
107
112
|
description ? 'help' : '',
|
|
108
113
|
className,
|
|
109
114
|
`field-wrapper-${id}`,
|
|
115
|
+
multilingual_options?.language_independent
|
|
116
|
+
? 'language-independent-field'
|
|
117
|
+
: null,
|
|
110
118
|
)}
|
|
111
119
|
>
|
|
112
120
|
<Grid>
|
|
@@ -160,7 +168,12 @@ class FormFieldWrapper extends Component {
|
|
|
160
168
|
{description && (
|
|
161
169
|
<Grid.Row stretched>
|
|
162
170
|
<Grid.Column stretched width="12">
|
|
163
|
-
<p className="help">
|
|
171
|
+
<p className="help">
|
|
172
|
+
{this.props.multilingual_options
|
|
173
|
+
? `${intl.formatMessage(messages.language_independent)} `
|
|
174
|
+
: null}
|
|
175
|
+
{description}
|
|
176
|
+
</p>
|
|
164
177
|
</Grid.Column>
|
|
165
178
|
</Grid.Row>
|
|
166
179
|
)}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import ObjectListWidgetDefault from './ObjectListWidget';
|
|
2
|
-
import
|
|
2
|
+
import { RealStoreWrapper, FormUndoWrapper } from '@plone/volto/storybook';
|
|
3
3
|
import React from 'react';
|
|
4
4
|
import { searchResults } from './ObjectBrowserWidget.stories';
|
|
5
5
|
|
|
@@ -109,7 +109,7 @@ const ObjectListWidgetComponent = ({
|
|
|
109
109
|
...args
|
|
110
110
|
}) => {
|
|
111
111
|
return (
|
|
112
|
-
<
|
|
112
|
+
<RealStoreWrapper
|
|
113
113
|
location={{ pathname: '/folder2/folder21/doc212' }}
|
|
114
114
|
customStore={customStore}
|
|
115
115
|
>
|
|
@@ -157,7 +157,7 @@ const ObjectListWidgetComponent = ({
|
|
|
157
157
|
</div>
|
|
158
158
|
)}
|
|
159
159
|
</FormUndoWrapper>
|
|
160
|
-
</
|
|
160
|
+
</RealStoreWrapper>
|
|
161
161
|
);
|
|
162
162
|
};
|
|
163
163
|
|
|
@@ -5,6 +5,12 @@ import configureStore from 'redux-mock-store';
|
|
|
5
5
|
import '@testing-library/jest-dom/extend-expect';
|
|
6
6
|
import ObjectListWidget from './ObjectListWidget';
|
|
7
7
|
|
|
8
|
+
jest.mock('@plone/volto/helpers/Loadable/Loadable');
|
|
9
|
+
beforeAll(
|
|
10
|
+
async () =>
|
|
11
|
+
await require('@plone/volto/helpers/Loadable/Loadable').__setLoadables(),
|
|
12
|
+
);
|
|
13
|
+
|
|
8
14
|
let mockSerial = 0;
|
|
9
15
|
const mockStore = configureStore();
|
|
10
16
|
|
|
@@ -6,17 +6,18 @@
|
|
|
6
6
|
import React from 'react';
|
|
7
7
|
import PropTypes from 'prop-types';
|
|
8
8
|
import { Form, Grid, Button } from 'semantic-ui-react';
|
|
9
|
-
import moment from 'moment';
|
|
10
9
|
import { Days } from './Utils';
|
|
11
10
|
import { useIntl } from 'react-intl';
|
|
11
|
+
import { injectLazyLibs } from '@plone/volto/helpers/Loadable/Loadable';
|
|
12
12
|
|
|
13
13
|
/**
|
|
14
14
|
* ByDayField component class.
|
|
15
15
|
* @function ByDayField
|
|
16
16
|
* @returns {string} Markup of the component.
|
|
17
17
|
*/
|
|
18
|
-
const ByDayField = ({ label, value, onChange }) => {
|
|
18
|
+
const ByDayField = ({ label, value, onChange, moment: momentlib }) => {
|
|
19
19
|
const intl = useIntl();
|
|
20
|
+
const moment = momentlib.default;
|
|
20
21
|
moment.locale(intl.locale);
|
|
21
22
|
|
|
22
23
|
const toggleWeekDay = (dayName) => {
|
|
@@ -84,4 +85,4 @@ ByDayField.defaultProps = {
|
|
|
84
85
|
onChange: null,
|
|
85
86
|
};
|
|
86
87
|
|
|
87
|
-
export default ByDayField;
|
|
88
|
+
export default injectLazyLibs(['moment'])(ByDayField);
|
|
@@ -6,17 +6,24 @@
|
|
|
6
6
|
import React from 'react';
|
|
7
7
|
import PropTypes from 'prop-types';
|
|
8
8
|
import { map } from 'lodash';
|
|
9
|
-
import moment from 'moment';
|
|
10
9
|
import { useIntl } from 'react-intl';
|
|
11
10
|
import { Form } from 'semantic-ui-react';
|
|
12
11
|
import SelectInput from './SelectInput';
|
|
12
|
+
import { injectLazyLibs } from '@plone/volto/helpers/Loadable/Loadable';
|
|
13
13
|
|
|
14
14
|
/**
|
|
15
15
|
* MonthOfTheYearField component class.
|
|
16
16
|
* @function MonthOfTheYearField
|
|
17
17
|
* @returns {string} Markup of the component.
|
|
18
18
|
*/
|
|
19
|
-
const MonthOfTheYearField = ({
|
|
19
|
+
const MonthOfTheYearField = ({
|
|
20
|
+
value,
|
|
21
|
+
disabled,
|
|
22
|
+
inline,
|
|
23
|
+
onChange,
|
|
24
|
+
moment: momentlib,
|
|
25
|
+
}) => {
|
|
26
|
+
const moment = momentlib.default;
|
|
20
27
|
const intl = useIntl();
|
|
21
28
|
moment.locale(intl.locale);
|
|
22
29
|
const monthList = [
|
|
@@ -63,4 +70,4 @@ MonthOfTheYearField.defaultProps = {
|
|
|
63
70
|
onChange: null,
|
|
64
71
|
};
|
|
65
72
|
|
|
66
|
-
export default MonthOfTheYearField;
|
|
73
|
+
export default injectLazyLibs(['moment'])(MonthOfTheYearField);
|