@plone/volto 17.0.0-alpha.24 → 17.0.0-alpha.25
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/.yarn/install-state.gz +0 -0
- package/CHANGELOG.md +41 -0
- package/CONTRIBUTING.md +5 -1
- package/README.md +2 -1
- 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/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 +6 -1
- package/locales/zh_CN/LC_MESSAGES/volto.po +5 -0
- package/locales/zh_CN.json +1 -1
- package/package.json +1 -1
- package/packages/volto-slate/build/messages/src/blocks/Table/TableBlockEdit.json +90 -0
- package/packages/volto-slate/build/messages/src/blocks/Text/DefaultTextBlockEditor.json +6 -0
- package/packages/volto-slate/build/messages/src/blocks/Text/DetachedTextBlockEditor.json +6 -0
- package/packages/volto-slate/build/messages/src/blocks/Text/SlashMenu.json +6 -0
- package/packages/volto-slate/build/messages/src/editor/plugins/AdvancedLink/index.json +10 -0
- package/packages/volto-slate/build/messages/src/editor/plugins/Link/index.json +10 -0
- package/packages/volto-slate/build/messages/src/editor/plugins/Table/index.json +30 -0
- package/packages/volto-slate/build/messages/src/elementEditor/messages.json +10 -0
- package/packages/volto-slate/build/messages/src/widgets/HtmlSlateWidget.json +6 -0
- package/packages/volto-slate/build/messages/src/widgets/RichTextWidgetView.json +6 -0
- package/packages/volto-slate/package.json +1 -1
- package/src/actions/index.js +1 -0
- package/src/actions/relations/relations.js +17 -0
- package/src/components/manage/Blocks/Image/schema.js +5 -1
- package/src/components/manage/Blocks/Listing/withQuerystringResults.jsx +18 -11
- package/src/components/manage/Blocks/ToC/variations/DefaultTocRenderer.jsx +4 -3
- package/src/components/manage/Blocks/ToC/variations/DefaultTocRenderer.test.jsx +44 -0
- package/src/components/manage/Contents/Contents.jsx +27 -0
- package/src/components/manage/Controlpanels/Relations/BrokenRelations.jsx +11 -9
- package/src/components/manage/Controlpanels/Relations/Relations.jsx +3 -3
- package/src/components/manage/Controlpanels/Relations/RelationsListing.jsx +8 -7
- package/src/components/manage/Controlpanels/Relations/RelationsMatrix.jsx +15 -9
- package/src/components/manage/Controlpanels/Users/UsersControlpanel.jsx +25 -10
- package/src/components/manage/Diff/DiffField.jsx +25 -1
- package/src/components/manage/LinksToItem/LinksToItem.jsx +1 -1
- package/src/components/manage/LinksToItem/LinksToItem.test.jsx +1 -1
- package/src/components/manage/Sharing/Sharing.jsx +11 -5
- package/src/components/manage/Widgets/FormFieldWrapper.jsx +1 -1
- package/src/components/theme/Comments/Comment.stories.jsx +84 -0
- package/src/components/theme/Comments/Comments.jsx +273 -378
- package/src/components/theme/Logout/Logout.jsx +36 -83
- package/src/components/theme/Search/SearchTags.jsx +30 -60
- package/src/components/theme/Sitemap/Sitemap.jsx +24 -13
- package/src/components/theme/Sitemap/Sitemap.test.jsx +23 -2
- package/src/constants/ActionTypes.js +1 -0
- package/src/reducers/relations/relations.js +74 -46
- package/src/server.jsx +9 -0
- package/theme/themes/pastanaga/collections/form.overrides +46 -0
- package/theme/themes/pastanaga/elements/input.overrides +6 -0
- package/theme/themes/pastanaga/elements/label.overrides +10 -0
- package/.gitignore~ +0 -71
- package/news/4547.breaking~ +0 -1
- package/package.json~ +0 -444
- package/src/config/index.js~ +0 -223
|
@@ -1,19 +1,11 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
import React, { Component } from 'react';
|
|
7
|
-
import PropTypes from 'prop-types';
|
|
8
|
-
import { connect } from 'react-redux';
|
|
9
|
-
import { compose } from 'redux';
|
|
10
|
-
import { defineMessages, injectIntl } from 'react-intl';
|
|
1
|
+
import { useEffect, useMemo } from 'react';
|
|
2
|
+
import { useDispatch, useSelector, shallowEqual } from 'react-redux';
|
|
3
|
+
import { useHistory } from 'react-router-dom';
|
|
4
|
+
import { defineMessages, useIntl } from 'react-intl';
|
|
11
5
|
import qs from 'query-string';
|
|
12
|
-
|
|
13
|
-
import { Login } from '@plone/volto/components';
|
|
6
|
+
import { Login, Toast } from '@plone/volto/components';
|
|
14
7
|
import { logout, purgeMessages } from '@plone/volto/actions';
|
|
15
8
|
import { toast } from 'react-toastify';
|
|
16
|
-
import { Toast } from '@plone/volto/components';
|
|
17
9
|
|
|
18
10
|
const messages = defineMessages({
|
|
19
11
|
loggedOut: {
|
|
@@ -26,83 +18,44 @@ const messages = defineMessages({
|
|
|
26
18
|
},
|
|
27
19
|
});
|
|
28
20
|
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
static defaultProps = {
|
|
54
|
-
query: null,
|
|
55
|
-
};
|
|
56
|
-
|
|
57
|
-
componentDidMount() {
|
|
58
|
-
this.props.logout();
|
|
59
|
-
this.props.purgeMessages();
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
/**
|
|
63
|
-
* Component will receive props
|
|
64
|
-
* @method componentWillReceiveProps
|
|
65
|
-
* @param {Object} nextProps Next properties
|
|
66
|
-
* @returns {undefined}
|
|
67
|
-
*/
|
|
68
|
-
UNSAFE_componentWillReceiveProps(nextProps) {
|
|
69
|
-
if (!nextProps.token) {
|
|
70
|
-
this.props.history.replace(this.props.returnUrl || '/');
|
|
21
|
+
const Logout = ({ location }) => {
|
|
22
|
+
const token = useSelector((state) => state.userSession.token, shallowEqual);
|
|
23
|
+
const history = useHistory();
|
|
24
|
+
const dispatch = useDispatch();
|
|
25
|
+
const intl = useIntl();
|
|
26
|
+
|
|
27
|
+
const returnUrl = useMemo(
|
|
28
|
+
() =>
|
|
29
|
+
qs.parse(location.search).return_url ||
|
|
30
|
+
location.pathname
|
|
31
|
+
.replace(/\/login\/?$/, '')
|
|
32
|
+
.replace(/\/logout\/?$/, '') ||
|
|
33
|
+
'/',
|
|
34
|
+
[location],
|
|
35
|
+
);
|
|
36
|
+
|
|
37
|
+
useEffect(() => {
|
|
38
|
+
dispatch(logout());
|
|
39
|
+
dispatch(purgeMessages());
|
|
40
|
+
}, [dispatch]);
|
|
41
|
+
|
|
42
|
+
useEffect(() => {
|
|
43
|
+
if (!token) {
|
|
44
|
+
history.replace(returnUrl || '/');
|
|
71
45
|
if (!toast.isActive('loggedOut')) {
|
|
72
46
|
toast.info(
|
|
73
47
|
<Toast
|
|
74
48
|
info
|
|
75
|
-
title={
|
|
76
|
-
content={
|
|
49
|
+
title={intl.formatMessage(messages.loggedOut)}
|
|
50
|
+
content={intl.formatMessage(messages.loggedOutContent)}
|
|
77
51
|
/>,
|
|
78
52
|
{ autoClose: false, toastId: 'loggedOut' },
|
|
79
53
|
);
|
|
80
54
|
}
|
|
81
55
|
}
|
|
82
|
-
}
|
|
56
|
+
}, [history, returnUrl, intl, token]);
|
|
57
|
+
|
|
58
|
+
return <Login location={{ query: location.query }} />;
|
|
59
|
+
};
|
|
83
60
|
|
|
84
|
-
|
|
85
|
-
* Render method.
|
|
86
|
-
* @method render
|
|
87
|
-
* @returns {string} Markup for the component.
|
|
88
|
-
*/
|
|
89
|
-
render() {
|
|
90
|
-
return <Login location={{ query: this.props.location.query }} />;
|
|
91
|
-
}
|
|
92
|
-
}
|
|
93
|
-
export default compose(
|
|
94
|
-
injectIntl,
|
|
95
|
-
connect(
|
|
96
|
-
(state, props) => ({
|
|
97
|
-
query: qs.parse(props.location.search),
|
|
98
|
-
token: state.userSession.token,
|
|
99
|
-
returnUrl:
|
|
100
|
-
qs.parse(props.location.search).return_url ||
|
|
101
|
-
props.location.pathname
|
|
102
|
-
.replace(/\/login\/?$/, '')
|
|
103
|
-
.replace(/\/logout\/?$/, '') ||
|
|
104
|
-
'/',
|
|
105
|
-
}),
|
|
106
|
-
{ logout, purgeMessages },
|
|
107
|
-
),
|
|
108
|
-
)(Logout);
|
|
61
|
+
export default Logout;
|
|
@@ -1,71 +1,41 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
* @module components/theme/Search/SearchTags
|
|
4
|
-
*/
|
|
5
|
-
|
|
6
|
-
import React, { Component } from 'react';
|
|
7
|
-
import PropTypes from 'prop-types';
|
|
8
|
-
import { connect } from 'react-redux';
|
|
1
|
+
import { useEffect } from 'react';
|
|
2
|
+
import { useDispatch, useSelector, shallowEqual } from 'react-redux';
|
|
9
3
|
import { Link } from 'react-router-dom';
|
|
10
4
|
|
|
11
5
|
import { getVocabulary } from '@plone/volto/actions';
|
|
12
6
|
|
|
13
7
|
const vocabulary = 'plone.app.vocabularies.Keywords';
|
|
14
8
|
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
* @class SearchTags
|
|
18
|
-
* @extends Component
|
|
19
|
-
*/
|
|
20
|
-
class SearchTags extends Component {
|
|
21
|
-
/**
|
|
22
|
-
* Property types.
|
|
23
|
-
* @property {Object} propTypes Property types.
|
|
24
|
-
* @static
|
|
25
|
-
*/
|
|
26
|
-
static propTypes = {
|
|
27
|
-
getVocabulary: PropTypes.func.isRequired,
|
|
28
|
-
items: PropTypes.arrayOf(
|
|
29
|
-
PropTypes.shape({
|
|
30
|
-
label: PropTypes.string,
|
|
31
|
-
}),
|
|
32
|
-
).isRequired,
|
|
33
|
-
};
|
|
34
|
-
|
|
35
|
-
componentDidMount() {
|
|
36
|
-
this.props.getVocabulary({ vocabNameOrURL: vocabulary });
|
|
37
|
-
}
|
|
9
|
+
const SearchTags = () => {
|
|
10
|
+
const dispatch = useDispatch();
|
|
38
11
|
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
* @returns {string} Markup for the component.
|
|
43
|
-
*/
|
|
44
|
-
render() {
|
|
45
|
-
return this.props.items && this.props.items.length > 0 ? (
|
|
46
|
-
<div>
|
|
47
|
-
{this.props.items.map((item) => (
|
|
48
|
-
<Link
|
|
49
|
-
className="ui label"
|
|
50
|
-
to={`/search?Subject=${item.label}`}
|
|
51
|
-
key={item.label}
|
|
52
|
-
>
|
|
53
|
-
{item.label}
|
|
54
|
-
</Link>
|
|
55
|
-
))}
|
|
56
|
-
</div>
|
|
57
|
-
) : (
|
|
58
|
-
<span />
|
|
59
|
-
);
|
|
60
|
-
}
|
|
61
|
-
}
|
|
12
|
+
useEffect(() => {
|
|
13
|
+
dispatch(getVocabulary({ vocabNameOrURL: vocabulary }));
|
|
14
|
+
}, [dispatch]);
|
|
62
15
|
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
items:
|
|
16
|
+
const items = useSelector(
|
|
17
|
+
(state) =>
|
|
66
18
|
state.vocabularies[vocabulary] && state.vocabularies[vocabulary].items
|
|
67
19
|
? state.vocabularies[vocabulary].items
|
|
68
20
|
: [],
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
21
|
+
shallowEqual,
|
|
22
|
+
);
|
|
23
|
+
|
|
24
|
+
return items && items.length > 0 ? (
|
|
25
|
+
<div>
|
|
26
|
+
{items.map((item) => (
|
|
27
|
+
<Link
|
|
28
|
+
className="ui label"
|
|
29
|
+
to={`/search?Subject=${item.label}`}
|
|
30
|
+
key={item.label}
|
|
31
|
+
>
|
|
32
|
+
{item.label}
|
|
33
|
+
</Link>
|
|
34
|
+
))}
|
|
35
|
+
</div>
|
|
36
|
+
) : (
|
|
37
|
+
<span />
|
|
38
|
+
);
|
|
39
|
+
};
|
|
40
|
+
|
|
41
|
+
export default SearchTags;
|
|
@@ -22,6 +22,13 @@ const messages = defineMessages({
|
|
|
22
22
|
defaultMessage: 'Sitemap',
|
|
23
23
|
},
|
|
24
24
|
});
|
|
25
|
+
|
|
26
|
+
export function getSitemapPath(pathname = '', lang) {
|
|
27
|
+
const prefix = pathname.replace(/\/sitemap$/gm, '').replace(/^\//, '');
|
|
28
|
+
const path = prefix || lang || '';
|
|
29
|
+
return path;
|
|
30
|
+
}
|
|
31
|
+
|
|
25
32
|
/**
|
|
26
33
|
* Sitemap class.
|
|
27
34
|
* @class Sitemap
|
|
@@ -39,11 +46,13 @@ class Sitemap extends Component {
|
|
|
39
46
|
|
|
40
47
|
componentDidMount() {
|
|
41
48
|
const { settings } = config;
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
49
|
+
|
|
50
|
+
const lang = settings.isMultilingual
|
|
51
|
+
? `${toBackendLang(this.props.lang)}`
|
|
52
|
+
: null;
|
|
53
|
+
|
|
54
|
+
const path = getSitemapPath(this.props.location.pathname, lang);
|
|
55
|
+
this.props.getNavigation(path, 4);
|
|
47
56
|
}
|
|
48
57
|
|
|
49
58
|
/**
|
|
@@ -105,15 +114,17 @@ export default compose(
|
|
|
105
114
|
{
|
|
106
115
|
key: 'navigation',
|
|
107
116
|
promise: ({ location, store: { dispatch, getState } }) => {
|
|
117
|
+
if (!__SERVER__) return;
|
|
108
118
|
const { settings } = config;
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
119
|
+
|
|
120
|
+
const path = getSitemapPath(
|
|
121
|
+
location.pathname,
|
|
122
|
+
settings.isMultilingual
|
|
123
|
+
? toBackendLang(getState().intl.locale)
|
|
124
|
+
: null,
|
|
125
|
+
);
|
|
126
|
+
|
|
127
|
+
return dispatch(getNavigation(path, 4));
|
|
117
128
|
},
|
|
118
129
|
},
|
|
119
130
|
]),
|
|
@@ -4,7 +4,7 @@ import configureStore from 'redux-mock-store';
|
|
|
4
4
|
import { Provider } from 'react-intl-redux';
|
|
5
5
|
import { MemoryRouter } from 'react-router-dom';
|
|
6
6
|
|
|
7
|
-
import { __test__ as Sitemap } from './Sitemap';
|
|
7
|
+
import { __test__ as Sitemap, getSitemapPath } from './Sitemap';
|
|
8
8
|
|
|
9
9
|
const mockStore = configureStore();
|
|
10
10
|
|
|
@@ -46,7 +46,7 @@ describe('Sitemap', () => {
|
|
|
46
46
|
const component = renderer.create(
|
|
47
47
|
<Provider store={store}>
|
|
48
48
|
<MemoryRouter>
|
|
49
|
-
<Sitemap />
|
|
49
|
+
<Sitemap location={{ pathname: '/page-1' }} />
|
|
50
50
|
</MemoryRouter>
|
|
51
51
|
</Provider>,
|
|
52
52
|
);
|
|
@@ -54,3 +54,24 @@ describe('Sitemap', () => {
|
|
|
54
54
|
expect(json).toMatchSnapshot();
|
|
55
55
|
});
|
|
56
56
|
});
|
|
57
|
+
|
|
58
|
+
describe('getSitemapPath', () => {
|
|
59
|
+
it('accepts empty path', () => {
|
|
60
|
+
expect(getSitemapPath('', null)).toBe('');
|
|
61
|
+
});
|
|
62
|
+
|
|
63
|
+
it('accepts a path', () => {
|
|
64
|
+
expect(getSitemapPath('/page-1/sitemap', null)).toBe('page-1');
|
|
65
|
+
});
|
|
66
|
+
it('accepts a path', () => {
|
|
67
|
+
expect(getSitemapPath('/page-1/sitemap', null)).toBe('page-1');
|
|
68
|
+
});
|
|
69
|
+
|
|
70
|
+
it('uses a language as default root', () => {
|
|
71
|
+
expect(getSitemapPath('/', 'de')).toBe('de');
|
|
72
|
+
});
|
|
73
|
+
|
|
74
|
+
it('accepts language-rooted paths', () => {
|
|
75
|
+
expect(getSitemapPath('/de/mission', 'de')).toBe('de/mission');
|
|
76
|
+
});
|
|
77
|
+
});
|
|
@@ -39,6 +39,7 @@ export const GET_QUERYSTRING_RESULTS = 'GET_QUERYSTRING_RESULTS';
|
|
|
39
39
|
export const CREATE_RELATIONS = 'CREATE_RELATIONS';
|
|
40
40
|
export const DELETE_RELATIONS = 'DELETE_RELATIONS';
|
|
41
41
|
export const LIST_RELATIONS = 'LIST_RELATIONS';
|
|
42
|
+
export const STATS_RELATIONS = 'STATS_RELATIONS';
|
|
42
43
|
export const REBUILD_RELATIONS = 'REBUILD_RELATIONS';
|
|
43
44
|
export const GET_SCHEMA = 'GET_SCHEMA';
|
|
44
45
|
export const POST_SCHEMA = 'POST_SCHEMA';
|
|
@@ -7,23 +7,29 @@ import {
|
|
|
7
7
|
CREATE_RELATIONS,
|
|
8
8
|
DELETE_RELATIONS,
|
|
9
9
|
LIST_RELATIONS,
|
|
10
|
+
STATS_RELATIONS,
|
|
10
11
|
REBUILD_RELATIONS,
|
|
11
12
|
} from '@plone/volto/constants/ActionTypes';
|
|
12
13
|
|
|
13
14
|
const initialState = {
|
|
14
|
-
relations:
|
|
15
|
-
stats: null,
|
|
16
|
-
create: {
|
|
15
|
+
relations: {
|
|
17
16
|
error: null,
|
|
18
17
|
loaded: false,
|
|
19
18
|
loading: false,
|
|
19
|
+
data: null,
|
|
20
20
|
},
|
|
21
|
-
|
|
21
|
+
stats: {
|
|
22
|
+
error: null,
|
|
23
|
+
loaded: false,
|
|
24
|
+
loading: false,
|
|
25
|
+
data: null,
|
|
26
|
+
},
|
|
27
|
+
create: {
|
|
22
28
|
error: null,
|
|
23
29
|
loaded: false,
|
|
24
30
|
loading: false,
|
|
25
31
|
},
|
|
26
|
-
|
|
32
|
+
delete: {
|
|
27
33
|
error: null,
|
|
28
34
|
loaded: false,
|
|
29
35
|
loading: false,
|
|
@@ -55,17 +61,6 @@ function getRequestKey(actionType) {
|
|
|
55
61
|
*/
|
|
56
62
|
export default function relations(state = initialState, action = {}) {
|
|
57
63
|
switch (action.type) {
|
|
58
|
-
case `${CREATE_RELATIONS}_PENDING`:
|
|
59
|
-
case `${DELETE_RELATIONS}_PENDING`:
|
|
60
|
-
case `${REBUILD_RELATIONS}_PENDING`:
|
|
61
|
-
return {
|
|
62
|
-
...state,
|
|
63
|
-
[getRequestKey(action.type)]: {
|
|
64
|
-
loading: true,
|
|
65
|
-
loaded: false,
|
|
66
|
-
error: null,
|
|
67
|
-
},
|
|
68
|
-
};
|
|
69
64
|
case `${LIST_RELATIONS}_PENDING`:
|
|
70
65
|
return action.subrequest
|
|
71
66
|
? {
|
|
@@ -73,10 +68,7 @@ export default function relations(state = initialState, action = {}) {
|
|
|
73
68
|
subrequests: {
|
|
74
69
|
...state.subrequests,
|
|
75
70
|
[action.subrequest]: {
|
|
76
|
-
|
|
77
|
-
relations: null,
|
|
78
|
-
stats: null,
|
|
79
|
-
}),
|
|
71
|
+
data: null,
|
|
80
72
|
loaded: false,
|
|
81
73
|
loading: true,
|
|
82
74
|
error: null,
|
|
@@ -85,7 +77,8 @@ export default function relations(state = initialState, action = {}) {
|
|
|
85
77
|
}
|
|
86
78
|
: {
|
|
87
79
|
...state,
|
|
88
|
-
|
|
80
|
+
relations: {
|
|
81
|
+
data: null,
|
|
89
82
|
loading: true,
|
|
90
83
|
loaded: false,
|
|
91
84
|
error: null,
|
|
@@ -98,39 +91,22 @@ export default function relations(state = initialState, action = {}) {
|
|
|
98
91
|
subrequests: {
|
|
99
92
|
...state.subrequests,
|
|
100
93
|
[action.subrequest]: {
|
|
94
|
+
data: action.result.relations,
|
|
101
95
|
loading: false,
|
|
102
96
|
loaded: true,
|
|
103
97
|
error: null,
|
|
104
|
-
relations: action.result.relations
|
|
105
|
-
? action.result.relations
|
|
106
|
-
: [],
|
|
107
|
-
stats: null,
|
|
108
98
|
},
|
|
109
99
|
},
|
|
110
100
|
}
|
|
111
101
|
: {
|
|
112
102
|
...state,
|
|
113
|
-
relations:
|
|
114
|
-
|
|
115
|
-
: state.relations,
|
|
116
|
-
stats: action.result.stats ? action.result : state.stats,
|
|
117
|
-
[getRequestKey(action.type)]: {
|
|
103
|
+
relations: {
|
|
104
|
+
data: action.result.relations,
|
|
118
105
|
loading: false,
|
|
119
106
|
loaded: true,
|
|
120
107
|
error: null,
|
|
121
108
|
},
|
|
122
109
|
};
|
|
123
|
-
case `${CREATE_RELATIONS}_SUCCESS`:
|
|
124
|
-
case `${DELETE_RELATIONS}_SUCCESS`:
|
|
125
|
-
case `${REBUILD_RELATIONS}_SUCCESS`:
|
|
126
|
-
return {
|
|
127
|
-
...state,
|
|
128
|
-
[getRequestKey(action.type)]: {
|
|
129
|
-
loading: false,
|
|
130
|
-
loaded: true,
|
|
131
|
-
error: null,
|
|
132
|
-
},
|
|
133
|
-
};
|
|
134
110
|
case `${LIST_RELATIONS}_FAIL`:
|
|
135
111
|
return action.subrequest
|
|
136
112
|
? {
|
|
@@ -138,8 +114,7 @@ export default function relations(state = initialState, action = {}) {
|
|
|
138
114
|
subrequests: {
|
|
139
115
|
...state.subrequests,
|
|
140
116
|
[action.subrequest]: {
|
|
141
|
-
|
|
142
|
-
stats: null,
|
|
117
|
+
data: null,
|
|
143
118
|
loading: false,
|
|
144
119
|
loaded: false,
|
|
145
120
|
error: action.error,
|
|
@@ -148,14 +123,67 @@ export default function relations(state = initialState, action = {}) {
|
|
|
148
123
|
}
|
|
149
124
|
: {
|
|
150
125
|
...state,
|
|
151
|
-
relations:
|
|
152
|
-
|
|
153
|
-
[getRequestKey(action.type)]: {
|
|
126
|
+
relations: {
|
|
127
|
+
data: null,
|
|
154
128
|
loading: false,
|
|
155
129
|
loaded: false,
|
|
156
130
|
error: action.error,
|
|
157
131
|
},
|
|
158
132
|
};
|
|
133
|
+
|
|
134
|
+
case `${STATS_RELATIONS}_PENDING`:
|
|
135
|
+
return {
|
|
136
|
+
...state,
|
|
137
|
+
[getRequestKey(action.type)]: {
|
|
138
|
+
loading: true,
|
|
139
|
+
loaded: false,
|
|
140
|
+
error: null,
|
|
141
|
+
data: null,
|
|
142
|
+
},
|
|
143
|
+
};
|
|
144
|
+
case `${STATS_RELATIONS}_SUCCESS`:
|
|
145
|
+
return {
|
|
146
|
+
...state,
|
|
147
|
+
[getRequestKey(action.type)]: {
|
|
148
|
+
loading: false,
|
|
149
|
+
loaded: true,
|
|
150
|
+
error: null,
|
|
151
|
+
data: action.result,
|
|
152
|
+
},
|
|
153
|
+
};
|
|
154
|
+
case `${STATS_RELATIONS}_FAIL`:
|
|
155
|
+
return {
|
|
156
|
+
...state,
|
|
157
|
+
[getRequestKey(action.type)]: {
|
|
158
|
+
loading: false,
|
|
159
|
+
loaded: false,
|
|
160
|
+
error: action.error,
|
|
161
|
+
data: null,
|
|
162
|
+
},
|
|
163
|
+
};
|
|
164
|
+
|
|
165
|
+
case `${CREATE_RELATIONS}_PENDING`:
|
|
166
|
+
case `${DELETE_RELATIONS}_PENDING`:
|
|
167
|
+
case `${REBUILD_RELATIONS}_PENDING`:
|
|
168
|
+
return {
|
|
169
|
+
...state,
|
|
170
|
+
[getRequestKey(action.type)]: {
|
|
171
|
+
loading: true,
|
|
172
|
+
loaded: false,
|
|
173
|
+
error: null,
|
|
174
|
+
},
|
|
175
|
+
};
|
|
176
|
+
case `${CREATE_RELATIONS}_SUCCESS`:
|
|
177
|
+
case `${DELETE_RELATIONS}_SUCCESS`:
|
|
178
|
+
case `${REBUILD_RELATIONS}_SUCCESS`:
|
|
179
|
+
return {
|
|
180
|
+
...state,
|
|
181
|
+
[getRequestKey(action.type)]: {
|
|
182
|
+
loading: false,
|
|
183
|
+
loaded: true,
|
|
184
|
+
error: null,
|
|
185
|
+
},
|
|
186
|
+
};
|
|
159
187
|
case `${CREATE_RELATIONS}_FAIL`:
|
|
160
188
|
case `${DELETE_RELATIONS}_FAIL`:
|
|
161
189
|
case `${REBUILD_RELATIONS}_FAIL`:
|
package/src/server.jsx
CHANGED
|
@@ -263,6 +263,15 @@ server.get('/*', (req, res) => {
|
|
|
263
263
|
const readCriticalCss =
|
|
264
264
|
config.settings.serverConfig.readCriticalCss || defaultReadCriticalCss;
|
|
265
265
|
|
|
266
|
+
// If we are showing an "old browser" warning,
|
|
267
|
+
// make sure it doesn't get cached in a shared cache
|
|
268
|
+
const browserdetect = store.getState().browserdetect;
|
|
269
|
+
if (config.settings.notSupportedBrowsers.includes(browserdetect?.name)) {
|
|
270
|
+
res.set({
|
|
271
|
+
'Cache-Control': 'private',
|
|
272
|
+
});
|
|
273
|
+
}
|
|
274
|
+
|
|
266
275
|
if (context.url) {
|
|
267
276
|
res.redirect(flattenToAppURL(context.url));
|
|
268
277
|
} else if (context.error_code) {
|
|
@@ -49,6 +49,52 @@
|
|
|
49
49
|
}
|
|
50
50
|
}
|
|
51
51
|
|
|
52
|
+
.ui.form .fields.error .field textarea,
|
|
53
|
+
.ui.form .fields.error .field select,
|
|
54
|
+
.ui.form .fields.error .field input:not([type]),
|
|
55
|
+
.ui.form .fields.error .field input[type='date'],
|
|
56
|
+
.ui.form .fields.error .field input[type='datetime-local'],
|
|
57
|
+
.ui.form .fields.error .field input[type='email'],
|
|
58
|
+
.ui.form .fields.error .field input[type='number'],
|
|
59
|
+
.ui.form .fields.error .field input[type='password'],
|
|
60
|
+
.ui.form .fields.error .field input[type='search'],
|
|
61
|
+
.ui.form .fields.error .field input[type='tel'],
|
|
62
|
+
.ui.form .fields.error .field input[type='time'],
|
|
63
|
+
.ui.form .fields.error .field input[type='text'],
|
|
64
|
+
.ui.form .fields.error .field input[type='file'],
|
|
65
|
+
.ui.form .fields.error .field input[type='url'],
|
|
66
|
+
.ui.form .field.error textarea,
|
|
67
|
+
.ui.form .field.error select,
|
|
68
|
+
.ui.form .field.error input:not([type]),
|
|
69
|
+
.ui.form .field.error input[type='date'],
|
|
70
|
+
.ui.form .field.error input[type='datetime-local'],
|
|
71
|
+
.ui.form .field.error input[type='email'],
|
|
72
|
+
.ui.form .field.error input[type='number'],
|
|
73
|
+
.ui.form .field.error input[type='password'],
|
|
74
|
+
.ui.form .field.error input[type='search'],
|
|
75
|
+
.ui.form .field.error input[type='tel'],
|
|
76
|
+
.ui.form .field.error input[type='time'],
|
|
77
|
+
.ui.form .field.error input[type='text'],
|
|
78
|
+
.ui.form .field.error input[type='file'],
|
|
79
|
+
.ui.form .field.error input[type='url'],
|
|
80
|
+
.ui.form .field.error textarea:focus,
|
|
81
|
+
.ui.form .field.error select:focus,
|
|
82
|
+
.ui.form .field.error input:not([type]):focus,
|
|
83
|
+
.ui.form .field.error input[type='date']:focus,
|
|
84
|
+
.ui.form .field.error input[type='datetime-local']:focus,
|
|
85
|
+
.ui.form .field.error input[type='email']:focus,
|
|
86
|
+
.ui.form .field.error input[type='number']:focus,
|
|
87
|
+
.ui.form .field.error input[type='password']:focus,
|
|
88
|
+
.ui.form .field.error input[type='search']:focus,
|
|
89
|
+
.ui.form .field.error input[type='tel']:focus,
|
|
90
|
+
.ui.form .field.error input[type='time']:focus,
|
|
91
|
+
.ui.form .field.error input[type='text']:focus,
|
|
92
|
+
.ui.form .field.error input[type='file']:focus,
|
|
93
|
+
.ui.form .field.error input[type='url']:focus {
|
|
94
|
+
border-color: #d01157;
|
|
95
|
+
background: none;
|
|
96
|
+
}
|
|
97
|
+
|
|
52
98
|
.ui.form .field > .selection.dropdown {
|
|
53
99
|
height: 60px;
|
|
54
100
|
}
|
|
@@ -6,6 +6,12 @@
|
|
|
6
6
|
font-weight: @inputFontWeight;
|
|
7
7
|
}
|
|
8
8
|
|
|
9
|
+
/* This aligns the height of the field name label to the other side in case
|
|
10
|
+
of an error is present, it overrides a default from SemanticUI grid definitions. */
|
|
11
|
+
.ui.grid > .stretched.row > .column > .wrapper {
|
|
12
|
+
flex-grow: 0;
|
|
13
|
+
}
|
|
14
|
+
|
|
9
15
|
.inline.field {
|
|
10
16
|
.wrapper {
|
|
11
17
|
display: flex;
|