@plone/volto 15.1.1 → 15.2.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.
package/netlify.toml CHANGED
@@ -1,2 +1,5 @@
1
1
  [build.environment]
2
2
  PYTHON_VERSION = "3.8"
3
+
4
+ [build]
5
+ ignore = "git diff --quiet $CACHED_COMMIT_REF $COMMIT_REF ./docs/"
package/package.json CHANGED
@@ -9,7 +9,7 @@
9
9
  }
10
10
  ],
11
11
  "license": "MIT",
12
- "version": "15.1.1",
12
+ "version": "15.2.1",
13
13
  "repository": {
14
14
  "type": "git",
15
15
  "url": "git@github.com:plone/volto.git"
@@ -296,6 +296,7 @@
296
296
  "cypress-axe": "0.12.2",
297
297
  "cypress-file-upload": "5.0.7",
298
298
  "debug": "4.3.2",
299
+ "deep-freeze": "0.0.1",
299
300
  "dependency-graph": "0.10.0",
300
301
  "detect-browser": "5.1.0",
301
302
  "diff": "3.5.0",
package/razzle.config.js CHANGED
@@ -189,7 +189,7 @@ const defaultModify = ({
189
189
 
190
190
  const addonsLoaderPath = createAddonsLoader(
191
191
  registry.getAddonDependencies(),
192
- pickBy(registry.packages, (value) => value.isRegisteredAddon),
192
+ registry.getAddons(),
193
193
  );
194
194
 
195
195
  config.resolve.plugins = [
@@ -231,15 +231,17 @@ const defaultModify = ({
231
231
  if (packageJson.name !== '@plone/volto') {
232
232
  include.push(fs.realpathSync(`${registry.voltoPath}/src`));
233
233
  }
234
+
234
235
  // Add babel support external (ie. node_modules npm published packages)
235
- if (registry.addonNames && registry.addonNames.length > 0) {
236
- registry.addonNames.forEach((addon) => {
236
+ const packagesNames = Object.keys(registry.packages);
237
+ if (registry.packages && packagesNames.length > 0) {
238
+ packagesNames.forEach((addon) => {
237
239
  const p = fs.realpathSync(registry.packages[addon].modulePath);
238
240
  if (include.indexOf(p) === -1) {
239
241
  include.push(p);
240
242
  }
241
243
  });
242
- addonsAsExternals = registry.addonNames.map((addon) => new RegExp(addon));
244
+ addonsAsExternals = packagesNames.map((addon) => new RegExp(addon));
243
245
  }
244
246
 
245
247
  if (process.env.ADDONS) {
@@ -251,9 +253,12 @@ const defaultModify = ({
251
253
  if (include.indexOf(p) === -1) {
252
254
  include.push(p);
253
255
  }
254
- addonsAsExternals = registry.addonNames.map(
255
- (normalizedAddonName) => new RegExp(normalizedAddonName),
256
- );
256
+ addonsAsExternals = [
257
+ ...addonsAsExternals,
258
+ ...packagesNames.map(
259
+ (normalizedAddonName) => new RegExp(normalizedAddonName),
260
+ ),
261
+ ];
257
262
  });
258
263
  }
259
264
 
@@ -53,8 +53,8 @@ const VersionOverview = ({
53
53
  <p>{intl.formatMessage(messages.no_addons)}</p>
54
54
  ) : (
55
55
  <ul style={{ fontSize: '16px', fontFamily: 'Monospace' }}>
56
- {Object.keys(addonsInfo).map((addon) => (
57
- <li>{`${addon} ${addonsInfo[addon].version || ''}`}</li>
56
+ {addonsInfo.map((addon) => (
57
+ <li>{`${addon.name} ${addon.version || ''}`}</li>
58
58
  ))}
59
59
  </ul>
60
60
  )}
@@ -78,7 +78,12 @@ const ManageTranslations = (props) => {
78
78
  // Only execute the link API call on the final item selected, once the ObjectBrowser
79
79
  // is closed
80
80
  if (!isObjectBrowserOpen && currentSelectedItem.current) {
81
- dispatch(linkTranslation(content['@id'], currentSelectedItem.current))
81
+ dispatch(
82
+ linkTranslation(
83
+ flattenToAppURL(content['@id']),
84
+ currentSelectedItem.current,
85
+ ),
86
+ )
82
87
  .then((resp) => {
83
88
  toast.success(
84
89
  <Toast
@@ -128,7 +133,7 @@ const ManageTranslations = (props) => {
128
133
  }
129
134
 
130
135
  function onDeleteTranslation(lang) {
131
- dispatch(deleteLinkTranslation(content['@id'], lang))
136
+ dispatch(deleteLinkTranslation(flattenToAppURL(content['@id']), lang))
132
137
  .then((resp) => {
133
138
  toast.success(
134
139
  <Toast
@@ -15,7 +15,7 @@ function PreviewImage(props) {
15
15
  ? flattenToAppURL(`${item['@id']}/@@images/${item.image_field}/${size}`)
16
16
  : DefaultImageSVG;
17
17
 
18
- return <img src={src} alt={alt || item.title} {...rest} />;
18
+ return <img src={src} alt={alt ?? item.title} {...rest} />;
19
19
  }
20
20
 
21
21
  PreviewImage.propTypes = {
@@ -62,4 +62,28 @@ describe('PreviewImage', () => {
62
62
  const json = component.toJSON();
63
63
  expect(json).toMatchSnapshot();
64
64
  });
65
+
66
+ it('renders a fallback image with alt prop empty', () => {
67
+ const item = {
68
+ title: 'Item title',
69
+ '@id': 'http://localhost:3000/something',
70
+ };
71
+ const component = renderer.create(
72
+ <PreviewImage item={item} className="extra" alt="" />,
73
+ );
74
+ const json = component.toJSON();
75
+ expect(json).toMatchSnapshot();
76
+ });
77
+
78
+ it('renders a fallback image with alt prop', () => {
79
+ const item = {
80
+ title: 'Item title',
81
+ '@id': 'http://localhost:3000/something',
82
+ };
83
+ const component = renderer.create(
84
+ <PreviewImage item={item} className="extra" alt="Alt prop" />,
85
+ );
86
+ const json = component.toJSON();
87
+ expect(json).toMatchSnapshot();
88
+ });
65
89
  });
@@ -80,6 +80,10 @@ const langmap = new Proxy(
80
80
  nativeName: 'Brezhoneg',
81
81
  englishName: 'Breton',
82
82
  },
83
+ bs: {
84
+ nativeName: 'Bosanski',
85
+ englishName: 'Bosnian',
86
+ },
83
87
  'bs-BA': {
84
88
  nativeName: 'Bosanski',
85
89
  englishName: 'Bosnian',
@@ -109,6 +109,7 @@ const safeColors = [
109
109
  'Teal',
110
110
  ];
111
111
  const namedColors = {};
112
+
112
113
  /**
113
114
  * Will generate initials from string
114
115
  * @param {string} name
@@ -198,3 +199,53 @@ export const hasApiExpander = (expander, path = '', type = 'GET_CONTENT') => {
198
199
  .map((expand) => expand[type]),
199
200
  ).includes(expander);
200
201
  };
202
+
203
+ /**
204
+ * Insert element into array at a give index
205
+ * @param {Array} array Array with data
206
+ * @param {*} element Element to be inserted
207
+ * @param {number} index Index of item to be inserted at
208
+ * @returns {Array} Array with inserted element
209
+ */
210
+ export const insertInArray = (array, element, index) => [
211
+ ...array.slice(0, index),
212
+ element,
213
+ ...array.slice(index),
214
+ ];
215
+
216
+ /**
217
+ * Replace element in array at a give index
218
+ * @param {Array} array Array with data
219
+ * @param {*} element Element to be replaced
220
+ * @param {number} index Index of item to be replaced at
221
+ * @returns {Array} Array with replaced element
222
+ */
223
+ export const replaceItemOfArray = (array, index, value) =>
224
+ Object.assign([...array], { [index]: value });
225
+
226
+ /**
227
+ * Remove item from array at given index
228
+ * @param {Array} array Array with data
229
+ * @param {number} index Index of item to be removed
230
+ * @returns {Array} Array without deleted element
231
+ */
232
+ export const removeFromArray = (array, index) => {
233
+ let newArray = array.slice();
234
+ newArray.splice(index, 1);
235
+ return newArray;
236
+ };
237
+
238
+ /**
239
+ * Reorder array
240
+ * @param {Array} array Array with data
241
+ * @param {number} origin Index of item to be reordered
242
+ * @param {number} target Index of item to be reordered to
243
+ * @returns {Array} Array with reordered elements
244
+ */
245
+ export const reorderArray = (array, origin, target) => {
246
+ const result = Array.from(array);
247
+ const [removed] = result.splice(origin, 1);
248
+ result.splice(target, 0, removed);
249
+
250
+ return result;
251
+ };
@@ -4,12 +4,16 @@ import {
4
4
  difference,
5
5
  getColor,
6
6
  getInitials,
7
- safeWrapper,
8
- normalizeLanguageName,
9
7
  hasApiExpander,
8
+ normalizeLanguageName,
10
9
  parseDateTime,
10
+ removeFromArray,
11
+ reorderArray,
12
+ replaceItemOfArray,
13
+ safeWrapper,
11
14
  } from './Utils';
12
15
  import moment from 'moment';
16
+ import deepFreeze from 'deep-freeze';
13
17
 
14
18
  describe('Utils tests', () => {
15
19
  describe('difference', () => {
@@ -345,4 +349,31 @@ describe('Utils tests', () => {
345
349
  ).toBe(`${isoDate}Z`);
346
350
  });
347
351
  });
352
+
353
+ describe('replaceItemOfArray', () => {
354
+ it('replaces the position of an element into an array immutable-ish', () => {
355
+ const array = ['a', 'b', 'c'];
356
+ deepFreeze(array);
357
+ const result = replaceItemOfArray(array, 2, 'v');
358
+ expect(result).toEqual(['a', 'b', 'v']);
359
+ });
360
+ });
361
+
362
+ describe('removeFromArray', () => {
363
+ it('removes an element from the array immutable-ish', () => {
364
+ const array = ['a', 'b', 'c'];
365
+ deepFreeze(array);
366
+ const result = removeFromArray(array, 2);
367
+ expect(result).toEqual(['a', 'b']);
368
+ });
369
+ });
370
+
371
+ describe('reorderArray', () => {
372
+ it('reorders an array immutable-ish', () => {
373
+ const array = ['a', 'b', 'c'];
374
+ deepFreeze(array);
375
+ const result = reorderArray(array, 2, 0);
376
+ expect(result).toEqual(['c', 'a', 'b']);
377
+ });
378
+ });
348
379
  });