@plone/volto 19.0.0-alpha.26 → 19.0.0-alpha.28

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 (203) hide show
  1. package/.eslintignore +1 -0
  2. package/.eslintrc +0 -3
  3. package/CHANGELOG.md +69 -0
  4. package/README.md +0 -1
  5. package/babel.js +0 -6
  6. package/locales/af/LC_MESSAGES/volto.po +5455 -0
  7. package/locales/af.json +1 -1
  8. package/locales/ar/LC_MESSAGES/volto.po +5455 -0
  9. package/locales/ar.json +1 -1
  10. package/locales/bg/LC_MESSAGES/volto.po +5455 -0
  11. package/locales/bg.json +1 -1
  12. package/locales/bn/LC_MESSAGES/volto.po +5455 -0
  13. package/locales/bn.json +1 -1
  14. package/locales/ca/LC_MESSAGES/volto.po +406 -345
  15. package/locales/ca.json +1 -1
  16. package/locales/cs/LC_MESSAGES/volto.po +5455 -0
  17. package/locales/cs.json +1 -1
  18. package/locales/cy/LC_MESSAGES/volto.po +5455 -0
  19. package/locales/cy.json +1 -1
  20. package/locales/da/LC_MESSAGES/volto.po +5455 -0
  21. package/locales/da.json +1 -1
  22. package/locales/de/LC_MESSAGES/volto.po +70 -8
  23. package/locales/de.json +1 -1
  24. package/locales/el/LC_MESSAGES/volto.po +5455 -0
  25. package/locales/el.json +1 -1
  26. package/locales/en/LC_MESSAGES/volto.po +66 -0
  27. package/locales/en.json +1 -1
  28. package/locales/en_AU/LC_MESSAGES/volto.po +5455 -0
  29. package/locales/en_AU.json +1 -1
  30. package/locales/en_GB/LC_MESSAGES/volto.po +5455 -0
  31. package/locales/en_GB.json +1 -1
  32. package/locales/eo/LC_MESSAGES/volto.po +5455 -0
  33. package/locales/eo.json +1 -1
  34. package/locales/es/LC_MESSAGES/volto.po +173 -112
  35. package/locales/es.json +1 -1
  36. package/locales/et/LC_MESSAGES/volto.po +5455 -0
  37. package/locales/et.json +1 -1
  38. package/locales/eu/LC_MESSAGES/volto.po +256 -195
  39. package/locales/eu.json +1 -1
  40. package/locales/fa/LC_MESSAGES/volto.po +5455 -0
  41. package/locales/fa.json +1 -1
  42. package/locales/fi/LC_MESSAGES/volto.po +62 -1
  43. package/locales/fi.json +1 -1
  44. package/locales/fr/LC_MESSAGES/volto.po +61 -0
  45. package/locales/fr.json +1 -1
  46. package/locales/fu/LC_MESSAGES/volto.po +5455 -0
  47. package/locales/fu.json +1 -1
  48. package/locales/gl/LC_MESSAGES/volto.po +5456 -0
  49. package/locales/gl.json +1 -1
  50. package/locales/he/LC_MESSAGES/volto.po +5455 -0
  51. package/locales/he.json +1 -1
  52. package/locales/hi/LC_MESSAGES/volto.po +66 -0
  53. package/locales/hi.json +1 -1
  54. package/locales/hr/LC_MESSAGES/volto.po +5455 -0
  55. package/locales/hr.json +1 -1
  56. package/locales/hu/LC_MESSAGES/volto.po +5455 -0
  57. package/locales/hu.json +1 -1
  58. package/locales/hy/LC_MESSAGES/volto.po +5455 -0
  59. package/locales/hy.json +1 -1
  60. package/locales/id/LC_MESSAGES/volto.po +5455 -0
  61. package/locales/id.json +1 -1
  62. package/locales/it/LC_MESSAGES/volto.po +90 -24
  63. package/locales/it.json +1 -1
  64. package/locales/ja/LC_MESSAGES/volto.po +105 -43
  65. package/locales/ja.json +1 -1
  66. package/locales/ka/LC_MESSAGES/volto.po +5455 -0
  67. package/locales/ka.json +1 -1
  68. package/locales/kn/LC_MESSAGES/volto.po +5455 -0
  69. package/locales/kn.json +1 -1
  70. package/locales/ko/LC_MESSAGES/volto.po +5455 -0
  71. package/locales/ko.json +1 -1
  72. package/locales/lt/LC_MESSAGES/volto.po +5455 -0
  73. package/locales/lt.json +1 -1
  74. package/locales/lv/LC_MESSAGES/volto.po +5455 -0
  75. package/locales/lv.json +1 -1
  76. package/locales/mi/LC_MESSAGES/volto.po +5455 -0
  77. package/locales/mi.json +1 -1
  78. package/locales/mk/LC_MESSAGES/volto.po +5455 -0
  79. package/locales/mk.json +1 -1
  80. package/locales/my/LC_MESSAGES/volto.po +5455 -0
  81. package/locales/my.json +1 -1
  82. package/locales/nb_NO/LC_MESSAGES/volto.po +5455 -0
  83. package/locales/nb_NO.json +1 -1
  84. package/locales/nl/LC_MESSAGES/volto.po +93 -31
  85. package/locales/nl.json +1 -1
  86. package/locales/nn/LC_MESSAGES/volto.po +5455 -0
  87. package/locales/nn.json +1 -1
  88. package/locales/pl/LC_MESSAGES/volto.po +5455 -0
  89. package/locales/pl.json +1 -1
  90. package/locales/pt/LC_MESSAGES/volto.po +723 -662
  91. package/locales/pt.json +1 -1
  92. package/locales/pt_BR/LC_MESSAGES/volto.po +61 -0
  93. package/locales/pt_BR.json +1 -1
  94. package/locales/rm/LC_MESSAGES/volto.po +5455 -0
  95. package/locales/rm.json +1 -1
  96. package/locales/ro/LC_MESSAGES/volto.po +61 -0
  97. package/locales/ro.json +1 -1
  98. package/locales/ru/LC_MESSAGES/volto.po +61 -0
  99. package/locales/ru.json +1 -1
  100. package/locales/sk/LC_MESSAGES/volto.po +5455 -0
  101. package/locales/sk.json +1 -1
  102. package/locales/sl/LC_MESSAGES/volto.po +5455 -0
  103. package/locales/sl.json +1 -1
  104. package/locales/sm/LC_MESSAGES/volto.po +5455 -0
  105. package/locales/sm.json +1 -1
  106. package/locales/sq/LC_MESSAGES/volto.po +5455 -0
  107. package/locales/sq.json +1 -1
  108. package/locales/sr/LC_MESSAGES/volto.po +5455 -0
  109. package/locales/sr.json +1 -1
  110. package/locales/sr@cyrl/LC_MESSAGES/volto.po +5455 -0
  111. package/locales/sr@cyrl.json +1 -1
  112. package/locales/sr@latn/LC_MESSAGES/volto.po +5455 -0
  113. package/locales/sr@latn.json +1 -1
  114. package/locales/sv/LC_MESSAGES/volto.po +5455 -0
  115. package/locales/sv.json +1 -1
  116. package/locales/ta/LC_MESSAGES/volto.po +5456 -0
  117. package/locales/ta.json +1 -1
  118. package/locales/te/LC_MESSAGES/volto.po +5455 -0
  119. package/locales/te.json +1 -1
  120. package/locales/th/LC_MESSAGES/volto.po +5455 -0
  121. package/locales/th.json +1 -1
  122. package/locales/to/LC_MESSAGES/volto.po +5455 -0
  123. package/locales/to.json +1 -1
  124. package/locales/tr/LC_MESSAGES/volto.po +5456 -0
  125. package/locales/tr.json +1 -1
  126. package/locales/uk/LC_MESSAGES/volto.po +5455 -0
  127. package/locales/uk.json +1 -1
  128. package/locales/vi/LC_MESSAGES/volto.po +5455 -0
  129. package/locales/vi.json +1 -1
  130. package/locales/volto.pot +62 -1
  131. package/locales/zh_CN/LC_MESSAGES/volto.po +62 -0
  132. package/locales/zh_CN.json +1 -1
  133. package/locales/zh_Hant/LC_MESSAGES/volto.po +5455 -0
  134. package/locales/zh_Hant.json +1 -1
  135. package/locales/zh_Hant_HK/LC_MESSAGES/volto.po +5455 -0
  136. package/locales/zh_Hant_HK.json +1 -1
  137. package/package.json +19 -35
  138. package/razzle.config.js +12 -5
  139. package/src/actions/blockTypes/blockTypes.ts +24 -0
  140. package/src/components/manage/Add/Add.jsx +7 -6
  141. package/src/components/manage/Blocks/Block/Order/Item.jsx +9 -3
  142. package/src/components/manage/Blocks/Block/Order/Order.jsx +116 -67
  143. package/src/components/manage/Blocks/Block/Order/utilities.js +28 -11
  144. package/src/components/manage/Blocks/Listing/Edit.jsx +1 -0
  145. package/src/components/manage/Blocks/Title/Edit.jsx +5 -0
  146. package/src/components/manage/Controlpanels/AddonsControlpanel.jsx +7 -0
  147. package/src/components/manage/Controlpanels/BlockType.tsx +166 -0
  148. package/src/components/manage/Controlpanels/BlockTypes.tsx +145 -0
  149. package/src/components/manage/Controlpanels/Controlpanels.jsx +28 -5
  150. package/src/components/manage/Controlpanels/Controlpanels.test.jsx +10 -0
  151. package/src/components/manage/Controlpanels/DatabaseInformation.jsx +9 -0
  152. package/src/components/manage/Controlpanels/ModerateComments.jsx +8 -0
  153. package/src/components/manage/Controlpanels/Users/UsersControlpanel.jsx +4 -5
  154. package/src/components/manage/Controlpanels/Users/UsersControlpanel.test.jsx +57 -11
  155. package/src/components/manage/Diff/Diff.jsx +201 -298
  156. package/src/components/manage/Multilingual/CreateTranslation.jsx +8 -5
  157. package/src/components/manage/Multilingual/ManageTranslations.jsx +1 -1
  158. package/src/components/manage/Multilingual/TranslationObject.jsx +9 -6
  159. package/src/components/manage/Preferences/PersonalPreferences.jsx +8 -5
  160. package/src/components/manage/Sidebar/ObjectBrowserBody.jsx +5 -1
  161. package/src/components/manage/Toolbar/Types.crash.test.jsx +48 -0
  162. package/src/components/manage/Widgets/FileWidget.jsx +7 -0
  163. package/src/components/manage/Widgets/RegistryImageWidget.jsx +1 -1
  164. package/src/components/theme/PasswordReset/PasswordReset.jsx +108 -191
  165. package/src/config/ControlPanels.js +2 -0
  166. package/src/config/index.js +1 -1
  167. package/src/config/validation.ts +8 -0
  168. package/src/constants/ActionTypes.js +1 -0
  169. package/src/express-middleware/devproxy.js +3 -1
  170. package/src/helpers/Blocks/Blocks.js +81 -18
  171. package/src/helpers/FormValidation/FormValidation.test.js +31 -0
  172. package/src/helpers/FormValidation/validators.ts +21 -0
  173. package/src/helpers/MessageLabels/MessageLabels.js +5 -0
  174. package/src/helpers/Utils/Utils.jsx +17 -0
  175. package/src/helpers/Utils/Utils.test.jsx +39 -0
  176. package/src/middleware/api.js +7 -3
  177. package/src/reducers/blockTypes/blockTypes.js +38 -0
  178. package/src/reducers/index.js +2 -0
  179. package/src/reducers/users/users.js +1 -1
  180. package/src/routes.js +10 -0
  181. package/src/server.jsx +7 -5
  182. package/test-setup-globals.js +26 -0
  183. package/theme/themes/pastanaga/extras/block-types.less +17 -0
  184. package/theme/themes/pastanaga/extras/main.less +1 -2
  185. package/types/actions/blockTypes/blockTypes.d.ts +7 -0
  186. package/types/components/index.d.ts +1 -1
  187. package/types/components/manage/Blocks/Block/Order/utilities.d.ts +2 -1
  188. package/types/components/manage/Controlpanels/BlockType.d.ts +7 -0
  189. package/types/components/manage/Controlpanels/BlockTypes.d.ts +7 -0
  190. package/types/components/manage/Diff/Diff.d.ts +7 -2
  191. package/types/components/manage/Toolbar/Types.crash.test.d.ts +1 -0
  192. package/types/components/theme/PasswordReset/PasswordReset.d.ts +6 -2
  193. package/types/config/ControlPanels.d.ts +1 -0
  194. package/types/constants/ActionTypes.d.ts +1 -0
  195. package/types/helpers/Blocks/Blocks.d.ts +3 -0
  196. package/types/helpers/FormValidation/validators.d.ts +7 -0
  197. package/types/helpers/MessageLabels/MessageLabels.d.ts +100 -94
  198. package/types/helpers/Utils/Utils.d.ts +1 -0
  199. package/types/reducers/blockTypes/blockTypes.d.ts +16 -0
  200. package/types/reducers/index.d.ts +2 -0
  201. package/types/routes.d.ts +7 -5
  202. package/vitest.config.mjs +84 -42
  203. package/webpack-plugins/webpack-less-plugin.js +1 -1
@@ -3,18 +3,16 @@
3
3
  * @module components/manage/Diff/Diff
4
4
  */
5
5
 
6
- import React, { Component } from 'react';
7
- import PropTypes from 'prop-types';
6
+ import React, { useEffect, useMemo } from 'react';
8
7
  import Helmet from '@plone/volto/helpers/Helmet/Helmet';
9
- import { connect } from 'react-redux';
10
- import { compose } from 'redux';
8
+ import { useSelector, useDispatch } from 'react-redux';
11
9
  import filter from 'lodash/filter';
12
10
  import isEqual from 'lodash/isEqual';
13
11
  import map from 'lodash/map';
14
12
  import { Container, Button, Dropdown, Grid, Table } from 'semantic-ui-react';
15
- import { Link, withRouter } from 'react-router-dom';
13
+ import { Link, useLocation, useHistory } from 'react-router-dom';
16
14
  import { createPortal } from 'react-dom';
17
- import { FormattedMessage, defineMessages, injectIntl } from 'react-intl';
15
+ import { FormattedMessage, defineMessages, useIntl } from 'react-intl';
18
16
  import qs from 'query-string';
19
17
 
20
18
  import { getDiff } from '@plone/volto/actions/diff/diff';
@@ -31,6 +29,7 @@ import Icon from '@plone/volto/components/theme/Icon/Icon';
31
29
  import Toolbar from '@plone/volto/components/manage/Toolbar/Toolbar';
32
30
  import Unauthorized from '@plone/volto/components/theme/Unauthorized/Unauthorized';
33
31
  import DiffField from '@plone/volto/components/manage/Diff/DiffField';
32
+ import { useClient } from '@plone/volto/hooks/client/useClient';
34
33
 
35
34
  import backSVG from '@plone/volto/icons/back.svg';
36
35
 
@@ -54,100 +53,41 @@ const messages = defineMessages({
54
53
  });
55
54
 
56
55
  /**
57
- * Diff class.
58
- * @class Diff
59
- * @extends Component
56
+ * Diff component.
57
+ * @function Diff
58
+ * @returns {JSX.Element}
60
59
  */
61
- class Diff extends Component {
62
- /**
63
- * Property types.
64
- * @property {Object} propTypes Property types.
65
- * @static
66
- */
67
- static propTypes = {
68
- getDiff: PropTypes.func.isRequired,
69
- getSchema: PropTypes.func.isRequired,
70
- getHistory: PropTypes.func.isRequired,
71
- schema: PropTypes.objectOf(PropTypes.any),
72
- error: PropTypes.objectOf(PropTypes.any),
73
- pathname: PropTypes.string.isRequired,
74
- one: PropTypes.string.isRequired,
75
- two: PropTypes.string.isRequired,
76
- view: PropTypes.string.isRequired,
77
- data: PropTypes.arrayOf(
78
- PropTypes.shape({
79
- '@id': PropTypes.string,
80
- }),
81
- ).isRequired,
82
- historyEntries: PropTypes.arrayOf(
83
- PropTypes.shape({
84
- version: PropTypes.number,
85
- time: PropTypes.string,
86
- actor: PropTypes.shape({ fullname: PropTypes.string }),
87
- }),
88
- ).isRequired,
89
- title: PropTypes.string.isRequired,
90
- type: PropTypes.string.isRequired,
91
- };
60
+ function Diff() {
61
+ const dispatch = useDispatch();
62
+ const location = useLocation();
63
+ const history = useHistory();
64
+ const isClient = useClient();
65
+ const intl = useIntl();
92
66
 
93
- /**
94
- * Default properties
95
- * @property {Object} defaultProps Default properties.
96
- * @static
97
- */
98
- static defaultProps = {
99
- schema: null,
100
- };
67
+ const data = useSelector((state) => state.diff.data);
68
+ const historyEntries = useSelector((state) => state.history.entries);
69
+ const schema = useSelector((state) => state.schema.schema);
70
+ const error = useSelector((state) => state.diff.error);
71
+ const title = useSelector((state) => state.content.data?.title);
72
+ const type = useSelector((state) => state.content.data?.['@type']);
101
73
 
102
- /**
103
- * Constructor
104
- * @method constructor
105
- * @param {Object} props Component properties
106
- * @constructs DiffComponent
107
- */
108
- constructor(props) {
109
- super(props);
110
- this.onChangeOne = this.onChangeOne.bind(this);
111
- this.onChangeTwo = this.onChangeTwo.bind(this);
112
- this.onSelectView = this.onSelectView.bind(this);
113
- this.state = { isClient: false };
114
- }
74
+ const pathname = location.pathname;
75
+ const searchParams = qs.parse(location.search);
76
+ const one = searchParams.one;
77
+ const two = searchParams.two;
78
+ const view = searchParams.view || 'split';
115
79
 
116
- /**
117
- * Component did mount
118
- * @method componentDidMount
119
- * @returns {undefined}
120
- */
121
- componentDidMount() {
122
- this.props.getSchema(this.props.type);
123
- this.props.getHistory(getBaseUrl(this.props.pathname));
124
- this.props.getDiff(
125
- getBaseUrl(this.props.pathname),
126
- this.props.one,
127
- this.props.two,
128
- );
129
- this.setState({ isClient: true });
130
- }
131
-
132
- /**
133
- * Component will receive props
134
- * @method componentWillReceiveProps
135
- * @param {Object} nextProps Next properties
136
- * @returns {undefined}
137
- */
138
- UNSAFE_componentWillReceiveProps(nextProps) {
139
- if (
140
- this.props.pathname !== nextProps.pathname ||
141
- this.props.one !== nextProps.one ||
142
- this.props.two !== nextProps.two
143
- ) {
144
- this.props.getDiff(
145
- getBaseUrl(nextProps.pathname),
146
- nextProps.one,
147
- nextProps.two,
148
- );
80
+ useEffect(() => {
81
+ if (type) {
82
+ dispatch(getSchema(type));
83
+ }
84
+ if (pathname) {
85
+ dispatch(getHistory(getBaseUrl(pathname)));
149
86
  }
150
- }
87
+ if (pathname && one && two) {
88
+ dispatch(getDiff(getBaseUrl(pathname), one, two));
89
+ }
90
+ }, [pathname, one, two, type, dispatch]);
151
91
 
152
92
  /**
153
93
  * On select view handler
@@ -156,11 +96,9 @@ class Diff extends Component {
156
96
  * @param {string} value Value
157
97
  * @returns {undefined}
158
98
  */
159
- onSelectView(event, { value }) {
160
- this.props.history.push(
161
- `${this.props.pathname}?one=${this.props.one}&two=${this.props.two}&view=${value}`,
162
- );
163
- }
99
+ const onSelectView = (event, { value }) => {
100
+ history.push(`${pathname}?one=${one}&two=${two}&view=${value}`);
101
+ };
164
102
 
165
103
  /**
166
104
  * On change one handler
@@ -169,11 +107,9 @@ class Diff extends Component {
169
107
  * @param {string} value Value
170
108
  * @returns {undefined}
171
109
  */
172
- onChangeOne(event, { value }) {
173
- this.props.history.push(
174
- `${this.props.pathname}?one=${value}&two=${this.props.two}&view=${this.props.view}`,
175
- );
176
- }
110
+ const onChangeOne = (event, { value }) => {
111
+ history.push(`${pathname}?one=${value}&two=${two}&view=${view}`);
112
+ };
177
113
 
178
114
  /**
179
115
  * On change two handler
@@ -182,202 +118,169 @@ class Diff extends Component {
182
118
  * @param {string} value Value
183
119
  * @returns {undefined}
184
120
  */
185
- onChangeTwo(event, { value }) {
186
- this.props.history.push(
187
- `${this.props.pathname}?one=${this.props.one}&two=${value}&view=${this.props.view}`,
188
- );
189
- }
121
+ const onChangeTwo = (event, { value }) => {
122
+ history.push(`${pathname}?one=${one}&two=${value}&view=${view}`);
123
+ };
190
124
 
191
- /**
192
- * Render method.
193
- * @method render
194
- * @returns {string} Markup for the component.
195
- */
196
- render() {
197
- const versions = map(
198
- filter(this.props.historyEntries, (entry) => 'version' in entry),
199
- (entry, index) => ({
200
- text: (
201
- <>
202
- {index === 0 ? 'Current' : entry.version}&nbsp;(
203
- <FormattedDate date={entry.time} long className="text" />, &nbsp;
204
- {entry.actor.fullname})
205
- </>
206
- ),
207
- value: `${entry.version}`,
208
- key: `${entry.version}`,
209
- }),
210
- );
125
+ const versions = useMemo(
126
+ () =>
127
+ map(
128
+ filter(historyEntries, (entry) => 'version' in entry),
129
+ (entry, index) => ({
130
+ text: (
131
+ <>
132
+ {index === 0 ? 'Current' : entry.version}&nbsp;(
133
+ <FormattedDate date={entry.time} long className="text" />, &nbsp;
134
+ {entry.actor.fullname})
135
+ </>
136
+ ),
137
+ value: `${entry.version}`,
138
+ key: `${entry.version}`,
139
+ }),
140
+ ),
141
+ [historyEntries],
142
+ );
211
143
 
212
- return this.props.error?.status === 401 ? (
213
- <Unauthorized />
214
- ) : (
215
- <Container id="page-diff">
216
- <Helmet title={this.props.intl.formatMessage(messages.diff)} />
217
- <h1>
218
- <FormattedMessage
219
- id="Difference between revision {one} and {two} of {title}"
220
- defaultMessage="Difference between revision {one} and {two} of {title}"
221
- values={{
222
- one: this.props.one,
223
- two: this.props.two,
224
- title: this.props.title,
225
- }}
226
- />
227
- </h1>
228
- <Grid>
229
- <Grid.Column width={9}>
230
- <p className="description">
231
- <FormattedMessage
232
- id="You can view the difference of the revisions below."
233
- defaultMessage="You can view the difference of the revisions below."
234
- />
235
- </p>
236
- </Grid.Column>
237
- <Grid.Column width={3} textAlign="right">
238
- <Button.Group>
239
- {map(
240
- [
241
- {
242
- id: 'split',
243
- label: this.props.intl.formatMessage(messages.split),
244
- },
245
- {
246
- id: 'unified',
247
- label: this.props.intl.formatMessage(messages.unified),
248
- },
249
- ],
250
- (view) => (
251
- <Button
252
- type="button"
253
- key={view.id}
254
- value={view.id}
255
- active={this.props.view === view.id}
256
- onClick={this.onSelectView}
257
- >
258
- {view.label}
259
- </Button>
260
- ),
261
- )}
262
- </Button.Group>
263
- </Grid.Column>
264
- </Grid>
265
- {this.props.historyEntries.length > 0 && (
266
- <Table basic="very">
267
- <Table.Header>
268
- <Table.Row>
269
- <Table.HeaderCell width={6}>
270
- <FormattedMessage id="Base" defaultMessage="Base" />
271
- <Dropdown
272
- onChange={this.onChangeOne}
273
- value={this.props.one}
274
- selection
275
- fluid
276
- options={versions}
277
- />
278
- </Table.HeaderCell>
279
- <Table.HeaderCell width={6}>
280
- <FormattedMessage id="Compare" defaultMessage="Compare" />
281
- <Dropdown
282
- onChange={this.onChangeTwo}
283
- value={this.props.two}
284
- selection
285
- fluid
286
- options={versions}
287
- />
288
- </Table.HeaderCell>
289
- </Table.Row>
290
- </Table.Header>
291
- </Table>
292
- )}
293
- {this.props.schema &&
294
- this.props.data.length > 0 &&
295
- map(this.props.schema.fieldsets, (fieldset) =>
296
- map(
297
- fieldset.fields,
298
- (field) =>
299
- !isEqual(
300
- this.props.data[0][field],
301
- this.props.data[1][field],
302
- ) &&
303
- field !== getBlocksFieldname(this.props.data[0]) &&
304
- field !== getBlocksLayoutFieldname(this.props.data[0]) && (
305
- <DiffField
306
- key={field}
307
- one={this.props.data[0][field]}
308
- two={this.props.data[1][field]}
309
- schema={this.props.schema.properties[field]}
310
- view={this.props.view}
311
- />
312
- ),
313
- ),
314
- )}
315
- {this.props.schema &&
316
- this.props.data.length > 0 &&
317
- hasBlocksData(this.props.data[0]) &&
318
- (!isEqual(
319
- this.props.data[0][getBlocksFieldname(this.props.data[0])],
320
- this.props.data[1][getBlocksFieldname(this.props.data[1])],
321
- ) ||
322
- !isEqual(
323
- this.props.data[0][getBlocksLayoutFieldname(this.props.data[0])],
324
- this.props.data[1][getBlocksLayoutFieldname(this.props.data[1])],
325
- )) && (
326
- <DiffField
327
- one={this.props.data[0][getBlocksFieldname(this.props.data[0])]}
328
- two={this.props.data[1][getBlocksFieldname(this.props.data[1])]}
329
- contentOne={this.props.data[0]}
330
- contentTwo={this.props.data[1]}
331
- schema={
332
- this.props.schema.properties[
333
- getBlocksFieldname(this.props.data[0])
334
- ]
335
- }
336
- view={this.props.view}
144
+ return error?.status === 401 ? (
145
+ <Unauthorized />
146
+ ) : (
147
+ <Container id="page-diff">
148
+ <Helmet title={intl.formatMessage(messages.diff)} />
149
+ <h1>
150
+ <FormattedMessage
151
+ id="Difference between revision {one} and {two} of {title}"
152
+ defaultMessage="Difference between revision {one} and {two} of {title}"
153
+ values={{
154
+ one,
155
+ two,
156
+ title,
157
+ }}
158
+ />
159
+ </h1>
160
+ <Grid>
161
+ <Grid.Column width={9}>
162
+ <p className="description">
163
+ <FormattedMessage
164
+ id="You can view the difference of the revisions below."
165
+ defaultMessage="You can view the difference of the revisions below."
337
166
  />
338
- )}
339
- {this.state.isClient &&
340
- createPortal(
341
- <Toolbar
342
- pathname={this.props.pathname}
343
- hideDefaultViewButtons
344
- inner={
345
- <Link
346
- to={`${getBaseUrl(this.props.pathname)}/historyview`}
347
- className="item"
167
+ </p>
168
+ </Grid.Column>
169
+ <Grid.Column width={3} textAlign="right">
170
+ <Button.Group>
171
+ {map(
172
+ [
173
+ {
174
+ id: 'split',
175
+ label: intl.formatMessage(messages.split),
176
+ },
177
+ {
178
+ id: 'unified',
179
+ label: intl.formatMessage(messages.unified),
180
+ },
181
+ ],
182
+ (viewOption) => (
183
+ <Button
184
+ type="button"
185
+ key={viewOption.id}
186
+ value={viewOption.id}
187
+ active={view === viewOption.id}
188
+ onClick={onSelectView}
348
189
  >
349
- <Icon
350
- name={backSVG}
351
- className="contents circled"
352
- size="30px"
353
- title={this.props.intl.formatMessage(messages.back)}
354
- />
355
- </Link>
356
- }
357
- />,
358
- document.getElementById('toolbar'),
359
- )}
360
- </Container>
361
- );
362
- }
190
+ {viewOption.label}
191
+ </Button>
192
+ ),
193
+ )}
194
+ </Button.Group>
195
+ </Grid.Column>
196
+ </Grid>
197
+ {historyEntries.length > 0 && (
198
+ <Table basic="very">
199
+ <Table.Header>
200
+ <Table.Row>
201
+ <Table.HeaderCell width={6}>
202
+ <FormattedMessage id="Base" defaultMessage="Base" />
203
+ <Dropdown
204
+ onChange={onChangeOne}
205
+ value={one}
206
+ selection
207
+ fluid
208
+ options={versions}
209
+ />
210
+ </Table.HeaderCell>
211
+ <Table.HeaderCell width={6}>
212
+ <FormattedMessage id="Compare" defaultMessage="Compare" />
213
+ <Dropdown
214
+ onChange={onChangeTwo}
215
+ value={two}
216
+ selection
217
+ fluid
218
+ options={versions}
219
+ />
220
+ </Table.HeaderCell>
221
+ </Table.Row>
222
+ </Table.Header>
223
+ </Table>
224
+ )}
225
+ {schema &&
226
+ data.length > 0 &&
227
+ map(schema.fieldsets, (fieldset) =>
228
+ map(
229
+ fieldset.fields,
230
+ (field) =>
231
+ !isEqual(data[0][field], data[1][field]) &&
232
+ field !== getBlocksFieldname(data[0]) &&
233
+ field !== getBlocksLayoutFieldname(data[0]) && (
234
+ <DiffField
235
+ key={field}
236
+ one={data[0][field]}
237
+ two={data[1][field]}
238
+ schema={schema.properties[field]}
239
+ view={view}
240
+ />
241
+ ),
242
+ ),
243
+ )}
244
+ {schema &&
245
+ data.length > 0 &&
246
+ hasBlocksData(data[0]) &&
247
+ (!isEqual(
248
+ data[0][getBlocksFieldname(data[0])],
249
+ data[1][getBlocksFieldname(data[1])],
250
+ ) ||
251
+ !isEqual(
252
+ data[0][getBlocksLayoutFieldname(data[0])],
253
+ data[1][getBlocksLayoutFieldname(data[1])],
254
+ )) && (
255
+ <DiffField
256
+ one={data[0][getBlocksFieldname(data[0])]}
257
+ two={data[1][getBlocksFieldname(data[1])]}
258
+ contentOne={data[0]}
259
+ contentTwo={data[1]}
260
+ schema={schema.properties[getBlocksFieldname(data[0])]}
261
+ view={view}
262
+ />
263
+ )}
264
+ {isClient &&
265
+ createPortal(
266
+ <Toolbar
267
+ pathname={pathname}
268
+ hideDefaultViewButtons
269
+ inner={
270
+ <Link to={`${getBaseUrl(pathname)}/historyview`} className="item">
271
+ <Icon
272
+ name={backSVG}
273
+ className="contents circled"
274
+ size="30px"
275
+ title={intl.formatMessage(messages.back)}
276
+ />
277
+ </Link>
278
+ }
279
+ />,
280
+ document.getElementById('toolbar'),
281
+ )}
282
+ </Container>
283
+ );
363
284
  }
364
285
 
365
- export default compose(
366
- withRouter,
367
- injectIntl,
368
- connect(
369
- (state, props) => ({
370
- data: state.diff.data,
371
- historyEntries: state.history.entries,
372
- schema: state.schema.schema,
373
- error: state.diff.error,
374
- pathname: props.location.pathname,
375
- one: qs.parse(props.location.search).one,
376
- two: qs.parse(props.location.search).two,
377
- view: qs.parse(props.location.search).view || 'split',
378
- title: state.content.data?.title,
379
- type: state.content.data?.['@type'],
380
- }),
381
- { getDiff, getSchema, getHistory },
382
- ),
383
- )(Diff);
286
+ export default Diff;
@@ -32,11 +32,14 @@ const CreateTranslation = (props) => {
32
32
  // We change the interface language
33
33
  if (config.settings.supportedLanguages.includes(language)) {
34
34
  const langFileName = toGettextLang(language);
35
- import(
36
- /* @vite-ignore */ '@root/../locales/' + langFileName + '.json'
37
- ).then((locale) => {
38
- dispatch(changeLanguage(language, locale.default));
39
- });
35
+ import(/* @vite-ignore */ '@root/../locales/' + langFileName + '.json')
36
+ .then((locale) => {
37
+ dispatch(changeLanguage(language, locale.default));
38
+ })
39
+ .catch(() => {
40
+ // If locale file doesn't exist, still switch language with empty locale
41
+ dispatch(changeLanguage(language, {}));
42
+ });
40
43
  }
41
44
  };
42
45
  // On mount only
@@ -178,7 +178,7 @@ const ManageTranslations = (props) => {
178
178
  <FormattedMessage
179
179
  id="Manage translations for {title}"
180
180
  defaultMessage="Manage translations for {title}"
181
- values={{ title: <q>{content.title}</q> }}
181
+ values={{ title: <q>{content?.title || ''}</q> }}
182
182
  />
183
183
  </Segment>
184
184
  {content && (
@@ -48,12 +48,15 @@ const TranslationObject = ({
48
48
  let lang =
49
49
  config.settings.supportedLanguages[Object.keys(locales).length];
50
50
  const langFileName = toGettextLang(lang);
51
- import(
52
- /* @vite-ignore */ '@root/../locales/' + langFileName + '.json'
53
- ).then((locale) => {
54
- setLocales({ ...locales, [toReactIntlLang(lang)]: locale.default });
55
- setLoadingLocale(false);
56
- });
51
+ import(/* @vite-ignore */ '@root/../locales/' + langFileName + '.json')
52
+ .then((locale) => {
53
+ setLocales({ ...locales, [toReactIntlLang(lang)]: locale.default });
54
+ setLoadingLocale(false);
55
+ })
56
+ .catch(() => {
57
+ setLocales({ ...locales, [toReactIntlLang(lang)]: {} });
58
+ setLoadingLocale(false);
59
+ });
57
60
  }
58
61
  }, [loadingLocale, locales]);
59
62
 
@@ -53,11 +53,14 @@ const PersonalPreferences = (props) => {
53
53
  let language = data.language || 'en';
54
54
  if (config.settings.supportedLanguages.includes(language)) {
55
55
  const langFileName = toGettextLang(language);
56
- import(
57
- /* @vite-ignore */ '@root/../locales/' + langFileName + '.json'
58
- ).then((locale) => {
59
- dispatch(changeLanguage(language, locale.default));
60
- });
56
+ import(/* @vite-ignore */ '@root/../locales/' + langFileName + '.json')
57
+ .then((locale) => {
58
+ dispatch(changeLanguage(language, locale.default));
59
+ })
60
+ .catch(() => {
61
+ // If locale file doesn't exist, still switch language with empty locale
62
+ dispatch(changeLanguage(language, {}));
63
+ });
61
64
  }
62
65
  toast.success(<Toast success title={intl.formatMessage(messages.saved)} />);
63
66
  closeMenu();
@@ -144,10 +144,14 @@ class ObjectBrowserBody extends Component {
144
144
  showSearchInput: false,
145
145
  // In image mode, the searchable types default to the image types which
146
146
  // can be overridden with the property if specified.
147
+ // If selectableTypes are passed, the searchableTypes are the selectableTypes
147
148
  searchableTypes:
148
149
  this.props.mode === 'image'
149
150
  ? this.props.searchableTypes || config.settings.imageObjects
150
- : this.props.searchableTypes,
151
+ : [
152
+ ...(this.props.searchableTypes ?? []),
153
+ ...(this.props.selectableTypes ?? []),
154
+ ],
151
155
  view: this.props.mode === 'image' ? 'icons' : 'list',
152
156
  };
153
157
  this.searchInputRef = React.createRef();