@plone/volto 16.13.0 → 17.0.0-alpha.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.draft +12 -11
- package/.storybook/main.js +53 -69
- package/.yarn/install-state.gz +0 -0
- package/CHANGELOG.md +33 -0
- package/README.md +21 -19
- package/cypress/support/commands.js +7 -7
- package/cypress/support/guillotina.js +2 -2
- package/cypress/support/reset-fixture.js +2 -2
- package/cypress/support/upgradetests.js +1 -1
- package/cypress.config.js +1 -1
- package/docker-compose.yml +2 -3
- package/locales/ca/LC_MESSAGES/volto.po +30 -0
- package/locales/ca.json +1 -1
- package/locales/de/LC_MESSAGES/volto.po +30 -0
- package/locales/de.json +1 -1
- package/locales/en/LC_MESSAGES/volto.po +30 -0
- package/locales/en.json +1 -1
- package/locales/es/LC_MESSAGES/volto.po +30 -0
- package/locales/es.json +1 -1
- package/locales/eu/LC_MESSAGES/volto.po +30 -0
- package/locales/eu.json +1 -1
- package/locales/fi.json +1 -1
- package/locales/fr/LC_MESSAGES/volto.po +30 -0
- package/locales/fr.json +1 -1
- package/locales/it/LC_MESSAGES/volto.po +30 -0
- package/locales/it.json +1 -1
- package/locales/ja/LC_MESSAGES/volto.po +30 -0
- package/locales/ja.json +1 -1
- package/locales/nl/LC_MESSAGES/volto.po +30 -0
- package/locales/nl.json +1 -1
- package/locales/pt/LC_MESSAGES/volto.po +30 -0
- package/locales/pt.json +1 -1
- package/locales/pt_BR/LC_MESSAGES/volto.po +31 -1
- package/locales/pt_BR.json +1 -1
- package/locales/ro/LC_MESSAGES/volto.po +30 -0
- package/locales/ro.json +1 -1
- package/locales/volto.pot +31 -1
- package/locales/zh_CN/LC_MESSAGES/volto.po +30 -0
- package/locales/zh_CN.json +1 -1
- package/package.json +22 -20
- package/packages/volto-slate/package.json +1 -1
- package/razzle.config.js +3 -3
- package/src/components/manage/Blocks/Teaser/Body.jsx +30 -0
- package/src/components/manage/Blocks/Teaser/Data.jsx +71 -0
- package/src/components/manage/Blocks/Teaser/DefaultBody.jsx +89 -0
- package/src/components/manage/Blocks/Teaser/Edit.jsx +25 -0
- package/src/components/manage/Blocks/Teaser/View.jsx +9 -0
- package/src/components/manage/Blocks/Teaser/adapter.js +23 -0
- package/src/components/manage/Blocks/Teaser/schema.js +103 -0
- package/src/components/manage/Blocks/Teaser/utils.js +44 -0
- package/src/components/manage/Blocks/Teaser/utils.test.jsx +229 -0
- package/src/components/manage/Controlpanels/VersionOverview.jsx +6 -10
- package/src/components/manage/Diff/DiffField.jsx +6 -6
- package/src/components/theme/FormattedDate/FormattedDate.jsx +3 -3
- package/src/config/Blocks.jsx +28 -0
- package/src/express-middleware/sitemap.js +1 -1
- package/src/helpers/Blocks/Blocks.test.js +50 -0
- package/src/helpers/Utils/Date.js +4 -2
- package/src/helpers/Utils/Date.test.js +3 -1
- package/src/helpers/index.js +0 -1
- package/theme/themes/pastanaga/extras/blocks.less +2 -0
- package/theme/themes/pastanaga/extras/teaser.less +166 -0
- package/webpack-plugins/webpack-relative-resolver.js +33 -19
- package/webpack-plugins/webpack-root-resolver.js +25 -14
- package/webpack-plugins/webpack-svg-plugin.js +11 -4
- package/locales/fi/LC_MESSAGES/volto.po +0 -4581
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { isEmpty } from 'lodash';
|
|
2
|
+
|
|
3
|
+
export const TeaserBlockDataAdapter = ({
|
|
4
|
+
block,
|
|
5
|
+
data,
|
|
6
|
+
id,
|
|
7
|
+
onChangeBlock,
|
|
8
|
+
value,
|
|
9
|
+
}) => {
|
|
10
|
+
let dataSaved = {
|
|
11
|
+
...data,
|
|
12
|
+
[id]: value,
|
|
13
|
+
};
|
|
14
|
+
if (id === 'href' && !isEmpty(value) && !data.title && !data.description) {
|
|
15
|
+
dataSaved = {
|
|
16
|
+
...dataSaved,
|
|
17
|
+
title: value[0].Title,
|
|
18
|
+
description: value[0].Description,
|
|
19
|
+
head_title: value[0].head_title,
|
|
20
|
+
};
|
|
21
|
+
}
|
|
22
|
+
onChangeBlock(block, dataSaved);
|
|
23
|
+
};
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
import { defineMessages } from 'react-intl';
|
|
2
|
+
import { addStyling } from '@plone/volto/helpers/Extensions/withBlockSchemaEnhancer';
|
|
3
|
+
|
|
4
|
+
const messages = defineMessages({
|
|
5
|
+
Target: {
|
|
6
|
+
id: 'Target',
|
|
7
|
+
defaultMessage: 'Target',
|
|
8
|
+
},
|
|
9
|
+
imageOverride: {
|
|
10
|
+
id: 'Image override',
|
|
11
|
+
defaultMessage: 'Image override',
|
|
12
|
+
},
|
|
13
|
+
openLinkInNewTab: {
|
|
14
|
+
id: 'Open in a new tab',
|
|
15
|
+
defaultMessage: 'Open in a new tab',
|
|
16
|
+
},
|
|
17
|
+
title: {
|
|
18
|
+
id: 'Title',
|
|
19
|
+
defaultMessage: 'Title',
|
|
20
|
+
},
|
|
21
|
+
description: {
|
|
22
|
+
id: 'Description',
|
|
23
|
+
defaultMessage: 'Description',
|
|
24
|
+
},
|
|
25
|
+
head_title: {
|
|
26
|
+
id: 'head_title',
|
|
27
|
+
defaultMessage: 'Head title',
|
|
28
|
+
},
|
|
29
|
+
teaser: {
|
|
30
|
+
id: 'Teaser',
|
|
31
|
+
defaultMessage: 'Teaser',
|
|
32
|
+
},
|
|
33
|
+
align: {
|
|
34
|
+
id: 'Alignment',
|
|
35
|
+
defaultMessage: 'Alignment',
|
|
36
|
+
},
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
export const TeaserSchema = ({ intl }) => {
|
|
40
|
+
const schema = {
|
|
41
|
+
title: intl.formatMessage(messages.teaser),
|
|
42
|
+
fieldsets: [
|
|
43
|
+
{
|
|
44
|
+
id: 'default',
|
|
45
|
+
title: 'Default',
|
|
46
|
+
fields: ['href', 'title', 'head_title', 'description', 'preview_image'],
|
|
47
|
+
},
|
|
48
|
+
],
|
|
49
|
+
|
|
50
|
+
properties: {
|
|
51
|
+
href: {
|
|
52
|
+
title: intl.formatMessage(messages.Target),
|
|
53
|
+
widget: 'object_browser',
|
|
54
|
+
mode: 'link',
|
|
55
|
+
selectedItemAttrs: [
|
|
56
|
+
'Title',
|
|
57
|
+
'head_title',
|
|
58
|
+
'Description',
|
|
59
|
+
'hasPreviewImage',
|
|
60
|
+
'image_field',
|
|
61
|
+
'image_scales',
|
|
62
|
+
'@type',
|
|
63
|
+
],
|
|
64
|
+
allowExternals: true,
|
|
65
|
+
},
|
|
66
|
+
title: {
|
|
67
|
+
title: intl.formatMessage(messages.title),
|
|
68
|
+
},
|
|
69
|
+
head_title: {
|
|
70
|
+
title: intl.formatMessage(messages.head_title),
|
|
71
|
+
},
|
|
72
|
+
description: {
|
|
73
|
+
title: intl.formatMessage(messages.description),
|
|
74
|
+
widget: 'textarea',
|
|
75
|
+
},
|
|
76
|
+
preview_image: {
|
|
77
|
+
title: intl.formatMessage(messages.imageOverride),
|
|
78
|
+
widget: 'object_browser',
|
|
79
|
+
mode: 'image',
|
|
80
|
+
allowExternals: true,
|
|
81
|
+
selectedItemAttrs: ['image_field', 'image_scales'],
|
|
82
|
+
},
|
|
83
|
+
openLinkInNewTab: {
|
|
84
|
+
title: intl.formatMessage(messages.openLinkInNewTab),
|
|
85
|
+
type: 'boolean',
|
|
86
|
+
},
|
|
87
|
+
},
|
|
88
|
+
required: [],
|
|
89
|
+
};
|
|
90
|
+
|
|
91
|
+
addStyling({ schema, intl });
|
|
92
|
+
|
|
93
|
+
schema.properties.styles.schema.properties.align = {
|
|
94
|
+
widget: 'align',
|
|
95
|
+
title: intl.formatMessage(messages.align),
|
|
96
|
+
actions: ['left', 'right', 'center'],
|
|
97
|
+
default: 'left',
|
|
98
|
+
};
|
|
99
|
+
|
|
100
|
+
schema.properties.styles.schema.fieldsets[0].fields = ['align'];
|
|
101
|
+
|
|
102
|
+
return schema;
|
|
103
|
+
};
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { isInternalURL } from '@plone/volto/helpers';
|
|
2
|
+
import config from '@plone/volto/registry';
|
|
3
|
+
|
|
4
|
+
export function getTeaserImageURL({ href, image, align }) {
|
|
5
|
+
// The default scale used in teasers is the 'teaser' scale
|
|
6
|
+
// except if it's customized otherwise in the teaser block settings
|
|
7
|
+
// or if the teaser is center (top)
|
|
8
|
+
const imageScale =
|
|
9
|
+
align === 'center'
|
|
10
|
+
? 'great'
|
|
11
|
+
: config.blocks.blocksConfig['teaser'].imageScale || 'teaser';
|
|
12
|
+
|
|
13
|
+
if (image) {
|
|
14
|
+
// If the image is overriden locally in the teaser block
|
|
15
|
+
if (isInternalURL(image['@id'])) {
|
|
16
|
+
// If it's internal check if image_scales catalog info is present
|
|
17
|
+
if (image?.image_scales?.[image?.image_field]) {
|
|
18
|
+
return `${image['@id']}/${
|
|
19
|
+
image.image_scales[image.image_field]?.[0].scales[imageScale]
|
|
20
|
+
?.download || image.image_scales[image.image_field]?.[0].download
|
|
21
|
+
}`;
|
|
22
|
+
} else {
|
|
23
|
+
// If not, fallback to content scale URL shortcut
|
|
24
|
+
return `${image['@id']}/@@images/${image.image_field}/${imageScale}`;
|
|
25
|
+
}
|
|
26
|
+
} else {
|
|
27
|
+
// If it's external, return the plain URL
|
|
28
|
+
return image['@id'];
|
|
29
|
+
}
|
|
30
|
+
} else {
|
|
31
|
+
// If the image is not overriden
|
|
32
|
+
if (href?.image_scales?.[href?.image_field]) {
|
|
33
|
+
return `${href['@id']}/${
|
|
34
|
+
href.image_scales[href.image_field]?.[0].scales[imageScale]?.download ||
|
|
35
|
+
href.image_scales[href.image_field]?.[0].download
|
|
36
|
+
}`;
|
|
37
|
+
} else {
|
|
38
|
+
// If not, fallback to content scale URL shortcut
|
|
39
|
+
return `${href['@id']}/@@images/${
|
|
40
|
+
href.image_field || 'preview_image'
|
|
41
|
+
}/${imageScale}`;
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
}
|
|
@@ -0,0 +1,229 @@
|
|
|
1
|
+
import { getTeaserImageURL } from './utils';
|
|
2
|
+
import config from '@plone/volto/registry';
|
|
3
|
+
|
|
4
|
+
beforeAll(() => {
|
|
5
|
+
config.blocks.blocksConfig.teaser = {};
|
|
6
|
+
config.blocks.blocksConfig.teaser.imageScale = 'teaser';
|
|
7
|
+
});
|
|
8
|
+
|
|
9
|
+
describe('getTeaserImageURL tests', () => {
|
|
10
|
+
it('getTeaserImageURL internal URL - no overriden', () => {
|
|
11
|
+
const align = 'left';
|
|
12
|
+
const href = {
|
|
13
|
+
'@id': '/document',
|
|
14
|
+
image_field: 'preview_image',
|
|
15
|
+
image_scales: {
|
|
16
|
+
preview_image: [
|
|
17
|
+
{
|
|
18
|
+
download: '@@images/default_original_URL',
|
|
19
|
+
scales: {
|
|
20
|
+
teaser: {
|
|
21
|
+
download: '@@images/teaser_scale_URL',
|
|
22
|
+
},
|
|
23
|
+
},
|
|
24
|
+
},
|
|
25
|
+
],
|
|
26
|
+
},
|
|
27
|
+
};
|
|
28
|
+
const image = undefined;
|
|
29
|
+
expect(getTeaserImageURL({ href, image, align })).toBe(
|
|
30
|
+
'/document/@@images/teaser_scale_URL',
|
|
31
|
+
);
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
it('getTeaserImageURL internal URL - no overriden - no scale', () => {
|
|
35
|
+
const align = 'left';
|
|
36
|
+
const href = {
|
|
37
|
+
'@id': '/document',
|
|
38
|
+
image_field: 'preview_image',
|
|
39
|
+
image_scales: {
|
|
40
|
+
preview_image: [
|
|
41
|
+
{
|
|
42
|
+
download: '@@images/default_original_URL',
|
|
43
|
+
scales: {},
|
|
44
|
+
},
|
|
45
|
+
],
|
|
46
|
+
},
|
|
47
|
+
};
|
|
48
|
+
const image = undefined;
|
|
49
|
+
expect(getTeaserImageURL({ href, image, align })).toBe(
|
|
50
|
+
'/document/@@images/default_original_URL',
|
|
51
|
+
);
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
it('getTeaserImageURL internal URL - no overriden - no catalog image info', () => {
|
|
55
|
+
const align = 'left';
|
|
56
|
+
const href = {
|
|
57
|
+
'@id': '/document',
|
|
58
|
+
image_field: 'image',
|
|
59
|
+
image_scales: {
|
|
60
|
+
preview_image: [
|
|
61
|
+
{
|
|
62
|
+
download: '@@images/default_original_URL',
|
|
63
|
+
scales: {},
|
|
64
|
+
},
|
|
65
|
+
],
|
|
66
|
+
},
|
|
67
|
+
};
|
|
68
|
+
const image = undefined;
|
|
69
|
+
expect(getTeaserImageURL({ href, image, align })).toBe(
|
|
70
|
+
'/document/@@images/image/teaser',
|
|
71
|
+
);
|
|
72
|
+
});
|
|
73
|
+
|
|
74
|
+
it('getTeaserImageURL internal URL - no overriden - center', () => {
|
|
75
|
+
const align = 'center';
|
|
76
|
+
const href = {
|
|
77
|
+
'@id': '/document',
|
|
78
|
+
image_field: 'preview_image',
|
|
79
|
+
image_scales: {
|
|
80
|
+
preview_image: [
|
|
81
|
+
{
|
|
82
|
+
download: '@@images/default_original_URL',
|
|
83
|
+
scales: {
|
|
84
|
+
great: {
|
|
85
|
+
download: '@@images/great_scale_URL',
|
|
86
|
+
},
|
|
87
|
+
teaser: {
|
|
88
|
+
download: '@@images/teaser_scale_URL',
|
|
89
|
+
},
|
|
90
|
+
},
|
|
91
|
+
},
|
|
92
|
+
],
|
|
93
|
+
},
|
|
94
|
+
};
|
|
95
|
+
const image = undefined;
|
|
96
|
+
expect(getTeaserImageURL({ href, image, align })).toBe(
|
|
97
|
+
'/document/@@images/great_scale_URL',
|
|
98
|
+
);
|
|
99
|
+
});
|
|
100
|
+
|
|
101
|
+
it('getTeaserImageURL internal URL - no overriden - center - no great scale', () => {
|
|
102
|
+
const align = 'center';
|
|
103
|
+
const href = {
|
|
104
|
+
'@id': '/document',
|
|
105
|
+
image_field: 'preview_image',
|
|
106
|
+
image_scales: {
|
|
107
|
+
preview_image: [
|
|
108
|
+
{
|
|
109
|
+
download: '@@images/default_original_URL',
|
|
110
|
+
scales: {
|
|
111
|
+
teaser: {
|
|
112
|
+
download: '@@images/teaser_scale_URL',
|
|
113
|
+
},
|
|
114
|
+
},
|
|
115
|
+
},
|
|
116
|
+
],
|
|
117
|
+
},
|
|
118
|
+
};
|
|
119
|
+
const image = undefined;
|
|
120
|
+
expect(getTeaserImageURL({ href, image, align })).toBe(
|
|
121
|
+
'/document/@@images/default_original_URL',
|
|
122
|
+
);
|
|
123
|
+
});
|
|
124
|
+
|
|
125
|
+
it('getTeaserImageURL internal URL - image overriden', () => {
|
|
126
|
+
const align = 'left';
|
|
127
|
+
const href = {
|
|
128
|
+
'@id': '/document',
|
|
129
|
+
image_field: 'preview_image',
|
|
130
|
+
image_scales: {
|
|
131
|
+
preview_image: [
|
|
132
|
+
{
|
|
133
|
+
download: '@@images/default_original_URL',
|
|
134
|
+
scales: {
|
|
135
|
+
teaser: {
|
|
136
|
+
download: '@@images/teaser_scale_URL',
|
|
137
|
+
},
|
|
138
|
+
},
|
|
139
|
+
},
|
|
140
|
+
],
|
|
141
|
+
},
|
|
142
|
+
};
|
|
143
|
+
const image = {
|
|
144
|
+
'@id': '/document/image',
|
|
145
|
+
image_field: 'image',
|
|
146
|
+
image_scales: {
|
|
147
|
+
image: [
|
|
148
|
+
{
|
|
149
|
+
download: '@@images/overriden_image_default_original_URL',
|
|
150
|
+
scales: {
|
|
151
|
+
teaser: {
|
|
152
|
+
download: '@@images/overriden_image_teaser_scale_URL',
|
|
153
|
+
},
|
|
154
|
+
},
|
|
155
|
+
},
|
|
156
|
+
],
|
|
157
|
+
},
|
|
158
|
+
};
|
|
159
|
+
expect(getTeaserImageURL({ href, image, align })).toBe(
|
|
160
|
+
'/document/image/@@images/overriden_image_teaser_scale_URL',
|
|
161
|
+
);
|
|
162
|
+
});
|
|
163
|
+
|
|
164
|
+
it('getTeaserImageURL internal URL - image overriden - center - no great scale', () => {
|
|
165
|
+
const align = 'center';
|
|
166
|
+
const href = {
|
|
167
|
+
'@id': '/document',
|
|
168
|
+
image_field: 'preview_image',
|
|
169
|
+
image_scales: {
|
|
170
|
+
preview_image: [
|
|
171
|
+
{
|
|
172
|
+
download: '@@images/default_original_URL',
|
|
173
|
+
scales: {
|
|
174
|
+
teaser: {
|
|
175
|
+
download: '@@images/teaser_scale_URL',
|
|
176
|
+
},
|
|
177
|
+
},
|
|
178
|
+
},
|
|
179
|
+
],
|
|
180
|
+
},
|
|
181
|
+
};
|
|
182
|
+
const image = {
|
|
183
|
+
'@id': '/document/image',
|
|
184
|
+
image_field: 'image',
|
|
185
|
+
image_scales: {
|
|
186
|
+
image: [
|
|
187
|
+
{
|
|
188
|
+
download: '@@images/overriden_image_default_original_URL',
|
|
189
|
+
scales: {
|
|
190
|
+
teaser: {
|
|
191
|
+
download: '@@images/overriden_image_teaser_scale_URL',
|
|
192
|
+
},
|
|
193
|
+
},
|
|
194
|
+
},
|
|
195
|
+
],
|
|
196
|
+
},
|
|
197
|
+
};
|
|
198
|
+
expect(getTeaserImageURL({ href, image, align })).toBe(
|
|
199
|
+
'/document/image/@@images/overriden_image_default_original_URL',
|
|
200
|
+
);
|
|
201
|
+
});
|
|
202
|
+
|
|
203
|
+
it('getTeaserImageURL internal URL - image overriden - external', () => {
|
|
204
|
+
const align = 'left';
|
|
205
|
+
const href = {
|
|
206
|
+
'@id': '/document',
|
|
207
|
+
image_field: 'preview_image',
|
|
208
|
+
image_scales: {
|
|
209
|
+
preview_image: [
|
|
210
|
+
{
|
|
211
|
+
download: '@@images/default_original_URL',
|
|
212
|
+
scales: {
|
|
213
|
+
teaser: {
|
|
214
|
+
download: '@@images/teaser_scale_URL',
|
|
215
|
+
},
|
|
216
|
+
},
|
|
217
|
+
},
|
|
218
|
+
],
|
|
219
|
+
},
|
|
220
|
+
};
|
|
221
|
+
const image = {
|
|
222
|
+
'@id': 'https://plone.org/document/image.png',
|
|
223
|
+
};
|
|
224
|
+
|
|
225
|
+
expect(getTeaserImageURL({ href, image, align })).toBe(
|
|
226
|
+
'https://plone.org/document/image.png',
|
|
227
|
+
);
|
|
228
|
+
});
|
|
229
|
+
});
|
|
@@ -7,14 +7,8 @@ import React from 'react';
|
|
|
7
7
|
import { FormattedMessage } from 'react-intl';
|
|
8
8
|
import { isEmpty } from 'lodash';
|
|
9
9
|
|
|
10
|
-
import
|
|
11
|
-
|
|
12
|
-
name as voltoName,
|
|
13
|
-
} from '../../../../package.json';
|
|
14
|
-
import {
|
|
15
|
-
version as projectVersion,
|
|
16
|
-
name as projectName,
|
|
17
|
-
} from '@root/../package.json';
|
|
10
|
+
import voltoPackageJson from '../../../../package.json';
|
|
11
|
+
import projectPackageJson from '@root/../package.json';
|
|
18
12
|
|
|
19
13
|
import { defineMessages, useIntl } from 'react-intl';
|
|
20
14
|
import config from '@plone/volto/registry';
|
|
@@ -26,6 +20,8 @@ const messages = defineMessages({
|
|
|
26
20
|
},
|
|
27
21
|
});
|
|
28
22
|
|
|
23
|
+
const voltoVersion = voltoPackageJson.version;
|
|
24
|
+
|
|
29
25
|
const VersionOverview = ({
|
|
30
26
|
cmf_version,
|
|
31
27
|
debug_mode,
|
|
@@ -37,7 +33,7 @@ const VersionOverview = ({
|
|
|
37
33
|
}) => {
|
|
38
34
|
const intl = useIntl();
|
|
39
35
|
const { addonsInfo } = config.settings;
|
|
40
|
-
const isProject =
|
|
36
|
+
const isProject = voltoPackageJson.name !== projectPackageJson.name;
|
|
41
37
|
|
|
42
38
|
return (
|
|
43
39
|
<>
|
|
@@ -50,7 +46,7 @@ const VersionOverview = ({
|
|
|
50
46
|
>
|
|
51
47
|
{isProject ? (
|
|
52
48
|
<li>
|
|
53
|
-
{
|
|
49
|
+
{projectPackageJson.name} {projectPackageJson.version}
|
|
54
50
|
</li>
|
|
55
51
|
) : null}
|
|
56
52
|
{voltoVersion && <li>Volto {voltoVersion}</li>}
|
|
@@ -61,12 +61,12 @@ const DiffField = ({
|
|
|
61
61
|
break;
|
|
62
62
|
case 'datetime':
|
|
63
63
|
parts = diffWords(
|
|
64
|
-
new Intl.DateTimeFormat(language, readable_date_format)
|
|
65
|
-
new Date(one)
|
|
66
|
-
|
|
67
|
-
new Intl.DateTimeFormat(language, readable_date_format)
|
|
68
|
-
new Date(two)
|
|
69
|
-
|
|
64
|
+
new Intl.DateTimeFormat(language, readable_date_format)
|
|
65
|
+
.format(new Date(one))
|
|
66
|
+
.replace('\u202F', ' '),
|
|
67
|
+
new Intl.DateTimeFormat(language, readable_date_format)
|
|
68
|
+
.format(new Date(two))
|
|
69
|
+
.replace('\u202F', ' '),
|
|
70
70
|
);
|
|
71
71
|
break;
|
|
72
72
|
case 'json':
|
|
@@ -23,9 +23,9 @@ const FormattedDate = ({
|
|
|
23
23
|
<time
|
|
24
24
|
className={className}
|
|
25
25
|
dateTime={date}
|
|
26
|
-
title={new Intl.DateTimeFormat(language, long_date_format)
|
|
27
|
-
new Date(toDate(date))
|
|
28
|
-
|
|
26
|
+
title={new Intl.DateTimeFormat(language, long_date_format)
|
|
27
|
+
.format(new Date(toDate(date)))
|
|
28
|
+
.replace('\u202F', ' ')}
|
|
29
29
|
>
|
|
30
30
|
{children
|
|
31
31
|
? children(
|
package/src/config/Blocks.jsx
CHANGED
|
@@ -42,6 +42,7 @@ import tableSVG from '@plone/volto/icons/table.svg';
|
|
|
42
42
|
import listingBlockSVG from '@plone/volto/icons/content-listing.svg';
|
|
43
43
|
import tocSVG from '@plone/volto/icons/list-bullet.svg';
|
|
44
44
|
import searchSVG from '@plone/volto/icons/zoom.svg';
|
|
45
|
+
import imagesSVG from '@plone/volto/icons/images.svg';
|
|
45
46
|
|
|
46
47
|
import ImageGalleryListingBlockTemplate from '@plone/volto/components/manage/Blocks/Listing/ImageGallery';
|
|
47
48
|
import BlockSettingsSchema from '@plone/volto/components/manage/Blocks/Block/Schema';
|
|
@@ -73,6 +74,12 @@ import SearchBlockSchema from '@plone/volto/components/manage/Blocks/Search/sche
|
|
|
73
74
|
|
|
74
75
|
import ToCVariations from '@plone/volto/components/manage/Blocks/ToC/variations';
|
|
75
76
|
|
|
77
|
+
import TeaserViewBlock from '@plone/volto/components/manage/Blocks/Teaser/View';
|
|
78
|
+
import TeaserEditBlock from '@plone/volto/components/manage/Blocks/Teaser/Edit';
|
|
79
|
+
import TeaserBlockDefaultBody from '@plone/volto/components/manage/Blocks/Teaser/DefaultBody';
|
|
80
|
+
import { TeaserSchema } from '@plone/volto/components/manage/Blocks/Teaser/schema';
|
|
81
|
+
import { TeaserBlockDataAdapter } from '@plone/volto/components/manage/Blocks/Teaser/adapter';
|
|
82
|
+
|
|
76
83
|
defineMessages({
|
|
77
84
|
title: {
|
|
78
85
|
id: 'title',
|
|
@@ -451,6 +458,27 @@ const blocksConfig = {
|
|
|
451
458
|
},
|
|
452
459
|
},
|
|
453
460
|
},
|
|
461
|
+
teaser: {
|
|
462
|
+
id: 'teaser',
|
|
463
|
+
title: 'Teaser',
|
|
464
|
+
icon: imagesSVG,
|
|
465
|
+
group: 'common',
|
|
466
|
+
view: TeaserViewBlock,
|
|
467
|
+
edit: TeaserEditBlock,
|
|
468
|
+
restricted: false,
|
|
469
|
+
mostUsed: true,
|
|
470
|
+
sidebarTab: 1,
|
|
471
|
+
blockSchema: TeaserSchema,
|
|
472
|
+
dataAdapter: TeaserBlockDataAdapter,
|
|
473
|
+
variations: [
|
|
474
|
+
{
|
|
475
|
+
id: 'default',
|
|
476
|
+
isDefault: true,
|
|
477
|
+
title: 'Default',
|
|
478
|
+
template: TeaserBlockDefaultBody,
|
|
479
|
+
},
|
|
480
|
+
],
|
|
481
|
+
},
|
|
454
482
|
};
|
|
455
483
|
|
|
456
484
|
const requiredBlocks = ['title'];
|
|
@@ -744,6 +744,56 @@ describe('Blocks', () => {
|
|
|
744
744
|
},
|
|
745
745
|
});
|
|
746
746
|
});
|
|
747
|
+
|
|
748
|
+
it('Sets data according to schema default values, keeps existing data', () => {
|
|
749
|
+
const schema = {
|
|
750
|
+
properties: {
|
|
751
|
+
style: {
|
|
752
|
+
widget: 'object',
|
|
753
|
+
schema: {
|
|
754
|
+
title: 'Style',
|
|
755
|
+
fieldsets: [
|
|
756
|
+
{
|
|
757
|
+
id: 'default',
|
|
758
|
+
fields: ['color', 'theme'],
|
|
759
|
+
title: 'Default',
|
|
760
|
+
},
|
|
761
|
+
],
|
|
762
|
+
properties: {
|
|
763
|
+
color: {
|
|
764
|
+
title: 'Color',
|
|
765
|
+
default: 'red',
|
|
766
|
+
},
|
|
767
|
+
theme: {
|
|
768
|
+
title: 'Theme',
|
|
769
|
+
default: 'primary',
|
|
770
|
+
},
|
|
771
|
+
},
|
|
772
|
+
required: [],
|
|
773
|
+
},
|
|
774
|
+
},
|
|
775
|
+
},
|
|
776
|
+
};
|
|
777
|
+
|
|
778
|
+
expect(
|
|
779
|
+
applySchemaDefaults({
|
|
780
|
+
schema,
|
|
781
|
+
data: {
|
|
782
|
+
'@type': 'slider',
|
|
783
|
+
style: {
|
|
784
|
+
theme: 'secondary',
|
|
785
|
+
},
|
|
786
|
+
},
|
|
787
|
+
intl: {},
|
|
788
|
+
}),
|
|
789
|
+
).toEqual({
|
|
790
|
+
'@type': 'slider',
|
|
791
|
+
style: {
|
|
792
|
+
color: 'red',
|
|
793
|
+
theme: 'secondary',
|
|
794
|
+
},
|
|
795
|
+
});
|
|
796
|
+
});
|
|
747
797
|
});
|
|
748
798
|
|
|
749
799
|
describe('applyBlockDefaults', () => {
|
|
@@ -48,7 +48,9 @@ export function formatDate({
|
|
|
48
48
|
: short_date_format;
|
|
49
49
|
|
|
50
50
|
const formatter = new Intl.DateTimeFormat(locale, format);
|
|
51
|
-
return formatToParts
|
|
51
|
+
return formatToParts
|
|
52
|
+
? formatter.formatToParts(date)
|
|
53
|
+
: formatter.format(date).replace('\u202F', ' ');
|
|
52
54
|
}
|
|
53
55
|
|
|
54
56
|
export function formatRelativeDate({
|
|
@@ -93,5 +95,5 @@ export function formatRelativeDate({
|
|
|
93
95
|
? ''
|
|
94
96
|
: formatToParts
|
|
95
97
|
? formatter.formatToParts(v, tag)
|
|
96
|
-
: formatter.format(v, tag); // use "now" ?
|
|
98
|
+
: formatter.format(v, tag).replace('\u202F', ' '); // use "now" ?
|
|
97
99
|
}
|
|
@@ -192,6 +192,8 @@ describe('formatRelativeDate helper', () => {
|
|
|
192
192
|
it('can use alternate style narrow', () => {
|
|
193
193
|
const now = Date.now();
|
|
194
194
|
const d = new Date(now + 3 * MONTH);
|
|
195
|
-
expect(
|
|
195
|
+
expect(['in 3 mo.', 'in 3mo']).toContain(
|
|
196
|
+
formatRelativeDate({ date: d, style: 'narrow' }),
|
|
197
|
+
);
|
|
196
198
|
});
|
|
197
199
|
});
|
package/src/helpers/index.js
CHANGED