@plone/volto 17.0.0-alpha.0 → 17.0.0-alpha.10
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 +451 -19
- package/CONTRIBUTING.md +1 -1
- package/README.md +12 -15
- package/addon-registry.js +34 -0
- package/create-theme-addons-loader.js +79 -0
- package/cypress/support/commands.js +25 -0
- package/locales/ca/LC_MESSAGES/volto.po +187 -6
- package/locales/ca.json +1 -1
- package/locales/de/LC_MESSAGES/volto.po +206 -25
- package/locales/de.json +1 -1
- package/locales/en/LC_MESSAGES/volto.po +186 -5
- package/locales/en.json +1 -1
- package/locales/es/LC_MESSAGES/volto.po +187 -6
- package/locales/es.json +1 -1
- package/locales/eu/LC_MESSAGES/volto.po +187 -6
- package/locales/eu.json +1 -1
- package/locales/fi/LC_MESSAGES/volto.po +4792 -0
- package/locales/fi.json +1 -1
- package/locales/fr/LC_MESSAGES/volto.po +187 -6
- package/locales/fr.json +1 -1
- package/locales/it/LC_MESSAGES/volto.po +187 -6
- package/locales/it.json +1 -1
- package/locales/ja/LC_MESSAGES/volto.po +187 -6
- package/locales/ja.json +1 -1
- package/locales/nl/LC_MESSAGES/volto.po +842 -649
- package/locales/nl.json +1 -1
- package/locales/pt/LC_MESSAGES/volto.po +187 -6
- package/locales/pt.json +1 -1
- package/locales/pt_BR/LC_MESSAGES/volto.po +195 -14
- package/locales/pt_BR.json +1 -1
- package/locales/ro/LC_MESSAGES/volto.po +187 -6
- package/locales/ro.json +1 -1
- package/locales/volto.pot +187 -6
- package/locales/zh_CN/LC_MESSAGES/volto.po +187 -6
- package/locales/zh_CN.json +1 -1
- package/package-why.json +0 -1
- package/package.json +9 -8
- package/packages/volto-slate/build/messages/src/blocks/Table/TableBlockEdit.json +1 -1
- package/packages/volto-slate/build/messages/src/blocks/Text/DefaultTextBlockEditor.json +1 -1
- package/packages/volto-slate/build/messages/src/blocks/Text/DetachedTextBlockEditor.json +1 -1
- package/packages/volto-slate/build/messages/src/blocks/Text/SlashMenu.json +1 -1
- package/packages/volto-slate/build/messages/src/editor/plugins/AdvancedLink/index.json +1 -1
- package/packages/volto-slate/build/messages/src/editor/plugins/Link/index.json +1 -1
- package/packages/volto-slate/build/messages/src/editor/plugins/Table/index.json +1 -1
- package/packages/volto-slate/build/messages/src/elementEditor/messages.json +1 -1
- package/packages/volto-slate/build/messages/src/widgets/HtmlSlateWidget.json +1 -1
- package/packages/volto-slate/build/messages/src/widgets/RichTextWidgetView.json +1 -1
- package/packages/volto-slate/package.json +1 -1
- package/packages/volto-slate/src/blocks/Table/TableBlockView.jsx +4 -4
- package/packages/volto-slate/src/blocks/Table/index.js +2 -0
- package/packages/volto-slate/src/blocks/Text/SlashMenu.jsx +4 -3
- package/packages/volto-slate/src/editor/deserialize.js +0 -1
- package/packages/volto-slate/src/editor/plugins/StyleMenu/StyleMenu.jsx +14 -4
- package/razzle.config.js +28 -0
- package/src/actions/index.js +6 -0
- package/src/actions/language/language.js +9 -8
- package/src/actions/querystringsearch/querystringsearch.js +20 -14
- package/src/actions/relations/rebuild.js +25 -0
- package/src/actions/relations/relations.js +86 -0
- package/src/actions/relations/relations.test.js +15 -0
- package/src/components/index.js +1 -0
- package/src/components/manage/Add/Add.jsx +2 -2
- package/src/components/manage/BlockChooser/BlockChooser.jsx +14 -5
- package/src/components/manage/BlockChooser/BlockChooser.test.jsx +5 -0
- package/src/components/manage/BlockChooser/BlockChooserButton.jsx +63 -29
- package/src/components/manage/BlockChooser/BlockChooserSearch.jsx +0 -1
- package/src/components/manage/Blocks/Listing/Edit.jsx +0 -19
- package/src/components/manage/Blocks/Listing/ListingBody.jsx +77 -61
- package/src/components/manage/Blocks/Listing/View.jsx +0 -4
- package/src/components/manage/Blocks/Listing/getAsyncData.js +10 -2
- package/src/components/manage/Blocks/Listing/withQuerystringResults.jsx +18 -13
- package/src/components/manage/Blocks/Search/SearchBlockEdit.jsx +5 -4
- package/src/components/manage/Blocks/Search/SearchBlockView.jsx +2 -1
- package/src/components/manage/Blocks/Search/components/DateRangeFacet.jsx +4 -1
- package/src/components/manage/Blocks/Search/components/Facets.jsx +58 -2
- package/src/components/manage/Blocks/Search/hocs/withSearch.jsx +24 -11
- package/src/components/manage/Blocks/Search/layout/LeftColumnFacets.jsx +17 -5
- package/src/components/manage/Blocks/Search/layout/RightColumnFacets.jsx +17 -5
- package/src/components/manage/Blocks/Search/layout/TopSideFacets.jsx +21 -5
- package/src/components/manage/Blocks/Search/schema.js +16 -1
- package/src/components/manage/Blocks/ToC/Edit.jsx +1 -0
- package/src/components/manage/Contents/Contents.jsx +69 -33
- package/src/components/manage/Contents/ContentsItem.jsx +6 -0
- package/src/components/manage/Controlpanels/AddonsControlpanel.jsx +3 -3
- package/src/components/manage/Controlpanels/Controlpanels.jsx +199 -224
- package/src/components/manage/Controlpanels/Controlpanels.test.jsx +46 -7
- package/src/components/manage/Controlpanels/Relations/BrokenRelations.jsx +66 -0
- package/src/components/manage/Controlpanels/Relations/Relations.jsx +114 -0
- package/src/components/manage/Controlpanels/Relations/RelationsListing.jsx +479 -0
- package/src/components/manage/Controlpanels/Relations/RelationsMatrix.jsx +531 -0
- package/src/components/manage/Controlpanels/Users/UserGroupMembershipControlPanel.jsx +3 -3
- package/src/components/manage/Controlpanels/Users/UserGroupMembershipListing.jsx +51 -82
- package/src/components/manage/Controlpanels/Users/UserGroupMembershipMatrix.jsx +79 -75
- package/src/components/manage/DragDropList/DragDropList.jsx +63 -42
- package/src/components/manage/Form/BlocksToolbar.jsx +5 -1
- package/src/components/manage/Form/Form.jsx +11 -5
- package/src/components/manage/Form/InlineForm.jsx +39 -9
- package/src/components/manage/Form/InlineFormState.js +8 -0
- package/src/components/manage/History/History.jsx +35 -18
- package/src/components/manage/Multilingual/CreateTranslation.jsx +2 -2
- package/src/components/manage/Multilingual/TranslationObject.jsx +4 -3
- package/src/components/manage/Preferences/ChangePassword.jsx +2 -2
- package/src/components/manage/Preferences/PersonalPreferences.jsx +2 -2
- package/src/components/manage/Toast/Toast.jsx +1 -1
- package/src/components/manage/Toolbar/Types.jsx +2 -2
- package/src/components/manage/Widgets/DatetimeWidget.jsx +9 -5
- package/src/components/manage/Widgets/ObjectListWidget.jsx +3 -8
- package/src/components/manage/Widgets/RecurrenceWidget/ByDayField.jsx +2 -1
- package/src/components/manage/Widgets/RecurrenceWidget/MonthOfTheYearField.jsx +2 -1
- package/src/components/manage/Widgets/RecurrenceWidget/Occurences.jsx +2 -1
- package/src/components/manage/Widgets/RecurrenceWidget/RecurrenceWidget.jsx +7 -2
- package/src/components/manage/Widgets/RecurrenceWidget/WeekdayOfTheMonthField.jsx +2 -1
- package/src/components/manage/Widgets/SelectUtils.js +1 -1
- package/src/components/manage/Widgets/SelectWidget.jsx +1 -1
- package/src/components/theme/Footer/Footer.jsx +2 -13
- package/src/components/theme/Header/Header.jsx +37 -63
- package/src/components/theme/Header/Header.test.jsx +18 -0
- package/src/components/theme/Icon/Icon.jsx +2 -2
- package/src/components/theme/LanguageSelector/LanguageSelector.js +8 -3
- package/src/components/theme/Login/Login.jsx +1 -0
- package/src/components/theme/Logo/Logo.jsx +2 -1
- package/src/components/theme/MultilingualRedirector/MultilingualRedirector.jsx +2 -2
- package/src/components/theme/Navigation/NavItem.jsx +4 -2
- package/src/components/theme/NotFound/NotFound.jsx +55 -41
- package/src/components/theme/PasswordReset/PasswordReset.jsx +7 -4
- package/src/components/theme/PasswordReset/RequestPasswordReset.jsx +1 -1
- package/src/components/theme/Sitemap/Sitemap.jsx +5 -3
- package/src/components/theme/View/DefaultView.jsx +1 -1
- package/src/components/theme/View/EventDatesInfo.jsx +2 -1
- package/src/components/theme/View/EventView.jsx +1 -1
- package/src/components/theme/View/NewsItemView.jsx +1 -1
- package/src/components/theme/View/RenderBlocks.jsx +7 -1
- package/src/components/theme/Widgets/DateWidget.jsx +2 -1
- package/src/components/theme/Widgets/DatetimeWidget.jsx +2 -1
- package/src/components/theme/Widgets/RelationsWidget.jsx +13 -11
- package/src/config/ControlPanels.js +2 -0
- package/src/config/Widgets.jsx +1 -0
- package/src/config/index.js +3 -0
- package/src/config/server.js +19 -0
- package/src/constants/ActionTypes.js +4 -0
- package/src/constants/Languages.js +8 -4
- package/src/express-middleware/devproxy.js +4 -2
- package/src/express-middleware/sitemap.js +36 -4
- package/src/express-middleware/static.js +32 -0
- package/src/helpers/Api/Api.js +1 -1
- package/src/helpers/FormValidation/FormValidation.js +11 -2
- package/src/helpers/FormValidation/FormValidation.test.js +73 -0
- package/src/helpers/Html/Html.jsx +3 -1
- package/src/helpers/Html/Html.test.jsx +5 -0
- package/src/helpers/MessageLabels/MessageLabels.js +72 -0
- package/src/helpers/Robots/Robots.js +24 -6
- package/src/helpers/Sitemap/Sitemap.js +44 -2
- package/src/helpers/Url/Url.js +27 -6
- package/src/helpers/Url/Url.test.js +26 -0
- package/src/helpers/Utils/Utils.js +38 -13
- package/src/helpers/Utils/Utils.test.js +4 -4
- package/src/helpers/index.js +7 -2
- package/src/hooks/userSession/useToken.js +5 -0
- package/src/middleware/Api.test.js +54 -0
- package/src/middleware/api.js +8 -4
- package/src/reducers/actions/actions.js +1 -1
- package/src/reducers/breadcrumbs/breadcrumbs.js +1 -1
- package/src/reducers/index.js +2 -0
- package/src/reducers/navigation/navigation.js +1 -1
- package/src/reducers/relations/relations.js +173 -0
- package/src/reducers/types/types.js +1 -1
- package/src/routes.js +5 -0
- package/src/server.jsx +29 -30
- package/src/start-server.js +4 -2
- package/test-setup-config.js +1 -0
- package/theme/themes/pastanaga/extras/blocks.less +0 -9
- package/theme/themes/pastanaga/extras/contents.less +1 -0
- package/theme/themes/pastanaga/extras/main.less +80 -1
- package/theme/themes/pastanaga/extras/search.less +6 -0
- package/theme/themes/pastanaga/extras/sidebar.less +4 -0
- package/theme/themes/pastanaga/extras/userscontrolpanel.less +99 -76
- package/.changelog.draft +0 -22
- package/.editorconfig +0 -36
- package/.storybook/main.js +0 -127
- package/.storybook/manager.js +0 -15
- package/.storybook/preview.js +0 -21
- package/.storybook/static/previewImage.svg +0 -48
- package/.yarnrc.yml +0 -5
- package/jsdoc.json +0 -16
- package/netlify.toml +0 -5
- package/pyvenv.cfg +0 -3
- package/share/man/man1/ttx.1 +0 -225
- package/src/components/theme/Header/Header.md +0 -27
- package/towncrier.toml +0 -33
|
@@ -1,5 +1,9 @@
|
|
|
1
1
|
import { updateIntl } from 'react-intl-redux';
|
|
2
|
-
import {
|
|
2
|
+
import {
|
|
3
|
+
toGettextLang,
|
|
4
|
+
toReactIntlLang,
|
|
5
|
+
getCookieOptions,
|
|
6
|
+
} from '@plone/volto/helpers';
|
|
3
7
|
import Cookies from 'universal-cookie';
|
|
4
8
|
|
|
5
9
|
export function changeLanguageCookies(language, req) {
|
|
@@ -7,18 +11,15 @@ export function changeLanguageCookies(language, req) {
|
|
|
7
11
|
|
|
8
12
|
const cookieOptions = getCookieOptions({
|
|
9
13
|
secure: req?.protocol?.startsWith('https') ? true : false,
|
|
14
|
+
sameSite: 'strict',
|
|
10
15
|
});
|
|
11
16
|
|
|
12
17
|
if (!req) {
|
|
13
|
-
cookies.set(
|
|
14
|
-
'I18N_LANGUAGE',
|
|
15
|
-
normalizeLanguageName(language) || '',
|
|
16
|
-
cookieOptions,
|
|
17
|
-
);
|
|
18
|
+
cookies.set('I18N_LANGUAGE', toGettextLang(language) || '', cookieOptions);
|
|
18
19
|
} else {
|
|
19
20
|
req.universalCookies.set(
|
|
20
21
|
'I18N_LANGUAGE',
|
|
21
|
-
|
|
22
|
+
toGettextLang(language) || '',
|
|
22
23
|
cookieOptions,
|
|
23
24
|
);
|
|
24
25
|
}
|
|
@@ -35,7 +36,7 @@ export function changeLanguage(language, locale, req) {
|
|
|
35
36
|
changeLanguageCookies(language, req);
|
|
36
37
|
|
|
37
38
|
return updateIntl({
|
|
38
|
-
locale: language,
|
|
39
|
+
locale: toReactIntlLang(language),
|
|
39
40
|
messages: locale,
|
|
40
41
|
});
|
|
41
42
|
}
|
|
@@ -31,24 +31,30 @@ export function getQueryStringResults(path, data, subrequest, page) {
|
|
|
31
31
|
}
|
|
32
32
|
}
|
|
33
33
|
|
|
34
|
+
const query = {
|
|
35
|
+
...requestData,
|
|
36
|
+
...(!requestData.b_size && {
|
|
37
|
+
b_size: settings.defaultPageSize,
|
|
38
|
+
}),
|
|
39
|
+
...(page && {
|
|
40
|
+
b_start: requestData.b_size
|
|
41
|
+
? data.b_size * (page - 1)
|
|
42
|
+
: settings.defaultPageSize * (page - 1),
|
|
43
|
+
}),
|
|
44
|
+
query: requestData?.query,
|
|
45
|
+
};
|
|
46
|
+
|
|
34
47
|
return {
|
|
35
48
|
type: GET_QUERYSTRING_RESULTS,
|
|
36
49
|
subrequest,
|
|
37
50
|
request: {
|
|
38
|
-
op: 'post',
|
|
39
|
-
path: `${path}/@querystring-search
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
...(page && {
|
|
46
|
-
b_start: requestData.b_size
|
|
47
|
-
? data.b_size * (page - 1)
|
|
48
|
-
: settings.defaultPageSize * (page - 1),
|
|
49
|
-
}),
|
|
50
|
-
query: requestData?.query,
|
|
51
|
-
},
|
|
51
|
+
op: settings.querystringSearchGet ? 'get' : 'post',
|
|
52
|
+
path: `${path}/@querystring-search${
|
|
53
|
+
settings.querystringSearchGet
|
|
54
|
+
? `?query=${encodeURIComponent(JSON.stringify(query))}`
|
|
55
|
+
: ''
|
|
56
|
+
}`,
|
|
57
|
+
data: settings.querystringSearchGet ? null : query,
|
|
52
58
|
},
|
|
53
59
|
};
|
|
54
60
|
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Rebuild relations action.
|
|
3
|
+
* @module actions/relations/rebuild
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import { REBUILD_RELATIONS } from '@plone/volto/constants/ActionTypes';
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Rebuild relation function.
|
|
10
|
+
* @function rebuildRelations
|
|
11
|
+
* @param {Boolean} flush Flush intids
|
|
12
|
+
* @returns {Object} Rebuild relation action.
|
|
13
|
+
*/
|
|
14
|
+
export function rebuildRelations(flush = false) {
|
|
15
|
+
let path = '/@relations';
|
|
16
|
+
var searchParams = new URLSearchParams();
|
|
17
|
+
searchParams.append('rebuild', '1');
|
|
18
|
+
flush && searchParams.append('flush', '1');
|
|
19
|
+
const searchParamsToString = searchParams.toString();
|
|
20
|
+
path += `?${searchParamsToString}`;
|
|
21
|
+
return {
|
|
22
|
+
type: REBUILD_RELATIONS,
|
|
23
|
+
request: { op: 'get', path: path },
|
|
24
|
+
};
|
|
25
|
+
}
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Relations actions.
|
|
3
|
+
* @module actions/relations/relations
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import {
|
|
7
|
+
CREATE_RELATIONS,
|
|
8
|
+
DELETE_RELATIONS,
|
|
9
|
+
LIST_RELATIONS,
|
|
10
|
+
} from '@plone/volto/constants/ActionTypes';
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Create relation function.
|
|
14
|
+
* @function createRelations
|
|
15
|
+
* @param {Object|Array} content Relation data.
|
|
16
|
+
* @returns {Object} Create relation action.
|
|
17
|
+
*/
|
|
18
|
+
export function createRelations(content) {
|
|
19
|
+
return {
|
|
20
|
+
type: CREATE_RELATIONS,
|
|
21
|
+
request: {
|
|
22
|
+
op: 'post',
|
|
23
|
+
path: '/@relations',
|
|
24
|
+
data: {
|
|
25
|
+
items: content,
|
|
26
|
+
},
|
|
27
|
+
},
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* Delete relation function.
|
|
33
|
+
* @function deleteRelations
|
|
34
|
+
* @param {string} id Relation id
|
|
35
|
+
* @returns {Object} Delete relation action.
|
|
36
|
+
*/
|
|
37
|
+
export function deleteRelations(content) {
|
|
38
|
+
return {
|
|
39
|
+
type: DELETE_RELATIONS,
|
|
40
|
+
request: {
|
|
41
|
+
op: 'del',
|
|
42
|
+
path: `/@relations`,
|
|
43
|
+
data: {
|
|
44
|
+
items: content,
|
|
45
|
+
},
|
|
46
|
+
},
|
|
47
|
+
};
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* Query relations
|
|
52
|
+
* @function queryRelations
|
|
53
|
+
* @param {string} relation Name of relation
|
|
54
|
+
* @param {boolean} onlyBroken
|
|
55
|
+
* @returns {Object} List relations action
|
|
56
|
+
*/
|
|
57
|
+
export function queryRelations(
|
|
58
|
+
relation = null,
|
|
59
|
+
onlyBroken = false,
|
|
60
|
+
subrequest = null,
|
|
61
|
+
source = null,
|
|
62
|
+
target = null,
|
|
63
|
+
query_source = null,
|
|
64
|
+
query_target = null,
|
|
65
|
+
) {
|
|
66
|
+
let path = '/@relations';
|
|
67
|
+
var searchParams = new URLSearchParams();
|
|
68
|
+
relation && searchParams.append('relation', relation);
|
|
69
|
+
onlyBroken && searchParams.append('onlyBroken', onlyBroken);
|
|
70
|
+
source && searchParams.append('source', source);
|
|
71
|
+
target && searchParams.append('target', target);
|
|
72
|
+
query_source && searchParams.append('query_source', query_source);
|
|
73
|
+
query_target && searchParams.append('query_target', query_target);
|
|
74
|
+
const searchParamsToString = searchParams.toString();
|
|
75
|
+
if (searchParamsToString) {
|
|
76
|
+
path += `?${searchParamsToString}`;
|
|
77
|
+
}
|
|
78
|
+
return {
|
|
79
|
+
type: LIST_RELATIONS,
|
|
80
|
+
subrequest,
|
|
81
|
+
request: {
|
|
82
|
+
op: 'get',
|
|
83
|
+
path: path,
|
|
84
|
+
},
|
|
85
|
+
};
|
|
86
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { queryRelations } from './relations';
|
|
2
|
+
import { LIST_RELATIONS } from '@plone/volto/constants/ActionTypes';
|
|
3
|
+
|
|
4
|
+
describe('Relations action', () => {
|
|
5
|
+
describe('queryRelations', () => {
|
|
6
|
+
it('should create an action to get relations of type "relatedItems"', () => {
|
|
7
|
+
const relation = 'relatedItems';
|
|
8
|
+
const action = queryRelations(relation);
|
|
9
|
+
|
|
10
|
+
expect(action.type).toEqual(LIST_RELATIONS);
|
|
11
|
+
expect(action.request.op).toEqual('get');
|
|
12
|
+
expect(action.request.path).toEqual(`/@relations?relation=${relation}`);
|
|
13
|
+
});
|
|
14
|
+
});
|
|
15
|
+
});
|
package/src/components/index.js
CHANGED
|
@@ -89,6 +89,7 @@ export ContentTypeSchema from '@plone/volto/components/manage/Controlpanels/Cont
|
|
|
89
89
|
export ContentTypesActions from '@plone/volto/components/manage/Controlpanels/ContentTypesActions';
|
|
90
90
|
export UsersControlpanel from '@plone/volto/components/manage/Controlpanels/Users/UsersControlpanel';
|
|
91
91
|
export UserGroupMembershipControlPanel from '@plone/volto/components/manage/Controlpanels/Users/UserGroupMembershipControlPanel';
|
|
92
|
+
export Relations from '@plone/volto/components/manage/Controlpanels/Relations/Relations';
|
|
92
93
|
export GroupsControlpanel from '@plone/volto/components/manage/Controlpanels/Groups/GroupsControlpanel';
|
|
93
94
|
export RulesControlpanel from '@plone/volto/components/manage/Controlpanels/Rules/Rules';
|
|
94
95
|
export AddRuleControlpanel from '@plone/volto/components/manage/Controlpanels/Rules/AddRule';
|
|
@@ -33,7 +33,7 @@ import {
|
|
|
33
33
|
getBlocksLayoutFieldname,
|
|
34
34
|
getLanguageIndependentFields,
|
|
35
35
|
langmap,
|
|
36
|
-
|
|
36
|
+
toGettextLang,
|
|
37
37
|
} from '@plone/volto/helpers';
|
|
38
38
|
|
|
39
39
|
import { preloadLazyLibs } from '@plone/volto/helpers/Loadable';
|
|
@@ -219,7 +219,7 @@ class Add extends Component {
|
|
|
219
219
|
onCancel() {
|
|
220
220
|
if (this.props.location?.state?.translationOf) {
|
|
221
221
|
const language = this.props.location.state.languageFrom;
|
|
222
|
-
const langFileName =
|
|
222
|
+
const langFileName = toGettextLang(language);
|
|
223
223
|
import('@root/../locales/' + langFileName + '.json').then((locale) => {
|
|
224
224
|
this.props.changeLanguage(language, locale.default);
|
|
225
225
|
});
|
|
@@ -33,17 +33,22 @@ const BlockChooser = ({
|
|
|
33
33
|
properties = {},
|
|
34
34
|
}) => {
|
|
35
35
|
const intl = useIntl();
|
|
36
|
-
const
|
|
36
|
+
const hasAllowedBlocks = !isEmpty(allowedBlocks);
|
|
37
37
|
|
|
38
38
|
const filteredBlocksConfig = filter(blocksConfig, (item) => {
|
|
39
|
+
// Check if the block is well formed (has at least id and title)
|
|
40
|
+
const blockIsWellFormed = Boolean(item.title && item.id);
|
|
41
|
+
if (!blockIsWellFormed) {
|
|
42
|
+
return false;
|
|
43
|
+
}
|
|
39
44
|
if (showRestricted) {
|
|
40
|
-
if (
|
|
45
|
+
if (hasAllowedBlocks) {
|
|
41
46
|
return allowedBlocks.includes(item.id);
|
|
42
47
|
} else {
|
|
43
48
|
return true;
|
|
44
49
|
}
|
|
45
50
|
} else {
|
|
46
|
-
if (
|
|
51
|
+
if (hasAllowedBlocks) {
|
|
47
52
|
return allowedBlocks.includes(item.id);
|
|
48
53
|
} else {
|
|
49
54
|
// Overload restricted as a function, so we can decide the availability of a block
|
|
@@ -89,14 +94,18 @@ const BlockChooser = ({
|
|
|
89
94
|
function blocksAvailableFilter(blocks) {
|
|
90
95
|
return blocks.filter(
|
|
91
96
|
(block) =>
|
|
92
|
-
getFormatMessage(block.title)
|
|
97
|
+
getFormatMessage(block.title)
|
|
98
|
+
.toLowerCase()
|
|
99
|
+
.includes(filterValue.toLowerCase()) ||
|
|
93
100
|
filterVariations(block)?.length,
|
|
94
101
|
);
|
|
95
102
|
}
|
|
96
103
|
function filterVariations(block) {
|
|
97
104
|
return block.variations?.filter(
|
|
98
105
|
(variation) =>
|
|
99
|
-
getFormatMessage(variation.title)
|
|
106
|
+
getFormatMessage(variation.title)
|
|
107
|
+
.toLowerCase()
|
|
108
|
+
.includes(filterValue.toLowerCase()) &&
|
|
100
109
|
!variation.title.toLowerCase().includes('default'),
|
|
101
110
|
);
|
|
102
111
|
}
|
|
@@ -4,8 +4,10 @@ import addSVG from '@plone/volto/icons/circle-plus.svg';
|
|
|
4
4
|
import { blockHasValue } from '@plone/volto/helpers';
|
|
5
5
|
import { Icon, BlockChooser } from '@plone/volto/components';
|
|
6
6
|
import config from '@plone/volto/registry';
|
|
7
|
-
import { Button } from 'semantic-ui-react';
|
|
7
|
+
import { Button, Ref } from 'semantic-ui-react';
|
|
8
8
|
import { defineMessages, useIntl } from 'react-intl';
|
|
9
|
+
import { usePopper } from 'react-popper';
|
|
10
|
+
import { Portal } from 'react-portal';
|
|
9
11
|
|
|
10
12
|
const messages = defineMessages({
|
|
11
13
|
addBlock: {
|
|
@@ -76,41 +78,73 @@ const BlockChooserButton = (props) => {
|
|
|
76
78
|
};
|
|
77
79
|
}, [handleClickOutside]);
|
|
78
80
|
|
|
81
|
+
const [referenceElement, setReferenceElement] = React.useState(null);
|
|
82
|
+
const [popperElement, setPopperElement] = React.useState(null);
|
|
83
|
+
const { styles, attributes } = usePopper(referenceElement, popperElement, {
|
|
84
|
+
placement: config.experimental.addBlockButton.enabled
|
|
85
|
+
? 'bottom'
|
|
86
|
+
: 'right-start',
|
|
87
|
+
modifiers: [
|
|
88
|
+
{
|
|
89
|
+
name: 'offset',
|
|
90
|
+
options: {
|
|
91
|
+
offset: [-10, 5],
|
|
92
|
+
},
|
|
93
|
+
},
|
|
94
|
+
{
|
|
95
|
+
name: 'flip',
|
|
96
|
+
options: {
|
|
97
|
+
fallbackPlacements: ['right-end', 'top-start'],
|
|
98
|
+
},
|
|
99
|
+
},
|
|
100
|
+
],
|
|
101
|
+
});
|
|
102
|
+
|
|
79
103
|
return (
|
|
80
104
|
<>
|
|
81
105
|
{!disableNewBlocks &&
|
|
82
106
|
(config.experimental.addBlockButton.enabled ||
|
|
83
107
|
!blockHasValue(data)) && (
|
|
84
|
-
<
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
108
|
+
<Ref innerRef={setReferenceElement}>
|
|
109
|
+
<Component
|
|
110
|
+
{...props}
|
|
111
|
+
onShowBlockChooser={() => setAddNewBlockOpened(true)}
|
|
112
|
+
/>
|
|
113
|
+
</Ref>
|
|
88
114
|
)}
|
|
89
115
|
{addNewBlockOpened && (
|
|
90
|
-
<
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
116
|
+
<Portal node={document.getElementById('body')}>
|
|
117
|
+
<div
|
|
118
|
+
ref={setPopperElement}
|
|
119
|
+
style={styles.popper}
|
|
120
|
+
{...attributes.popper}
|
|
121
|
+
>
|
|
122
|
+
<BlockChooser
|
|
123
|
+
onMutateBlock={
|
|
124
|
+
onMutateBlock
|
|
125
|
+
? (id, value) => {
|
|
126
|
+
setAddNewBlockOpened(false);
|
|
127
|
+
onMutateBlock(id, value);
|
|
128
|
+
}
|
|
129
|
+
: null
|
|
130
|
+
}
|
|
131
|
+
onInsertBlock={
|
|
132
|
+
onInsertBlock
|
|
133
|
+
? (id, value) => {
|
|
134
|
+
setAddNewBlockOpened(false);
|
|
135
|
+
onInsertBlock(id, value);
|
|
136
|
+
}
|
|
137
|
+
: null
|
|
138
|
+
}
|
|
139
|
+
currentBlock={block}
|
|
140
|
+
allowedBlocks={allowedBlocks}
|
|
141
|
+
blocksConfig={blocksConfig}
|
|
142
|
+
properties={properties}
|
|
143
|
+
showRestricted={showRestricted}
|
|
144
|
+
ref={blockChooserRef}
|
|
145
|
+
/>
|
|
146
|
+
</div>
|
|
147
|
+
</Portal>
|
|
114
148
|
)}
|
|
115
149
|
</>
|
|
116
150
|
);
|
|
@@ -26,35 +26,16 @@ const messages = defineMessages({
|
|
|
26
26
|
const Edit = React.memo(
|
|
27
27
|
(props) => {
|
|
28
28
|
const { data, onChangeBlock, block, selected, pathname } = props;
|
|
29
|
-
|
|
30
29
|
const intl = useIntl();
|
|
31
|
-
|
|
32
|
-
// componentDidMount
|
|
33
|
-
React.useEffect(() => {
|
|
34
|
-
if (!data.query) {
|
|
35
|
-
onChangeBlock(block, {
|
|
36
|
-
...data,
|
|
37
|
-
query: [],
|
|
38
|
-
block,
|
|
39
|
-
});
|
|
40
|
-
}
|
|
41
|
-
/* eslint-disable react-hooks/exhaustive-deps */
|
|
42
|
-
}, []);
|
|
43
|
-
|
|
44
30
|
const placeholder =
|
|
45
31
|
data.placeholder ||
|
|
46
32
|
(data?.querystring?.query?.length
|
|
47
33
|
? intl.formatMessage(messages.results)
|
|
48
34
|
: intl.formatMessage(messages.items));
|
|
49
35
|
|
|
50
|
-
const HeadlineTag = data.headlineTag || 'h2';
|
|
51
|
-
|
|
52
36
|
return (
|
|
53
37
|
<>
|
|
54
38
|
<p className="items-preview">{placeholder}</p>
|
|
55
|
-
{data.headline && (
|
|
56
|
-
<HeadlineTag className="headline">{data.headline}</HeadlineTag>
|
|
57
|
-
)}
|
|
58
39
|
<ListingBody {...props} path={getBaseUrl(pathname)} isEditMode />
|
|
59
40
|
<SidebarPortal selected={selected}>
|
|
60
41
|
<ListingData
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import React, { createRef } from 'react';
|
|
2
2
|
import { FormattedMessage, injectIntl } from 'react-intl';
|
|
3
|
+
import cx from 'classnames';
|
|
3
4
|
import { Pagination, Dimmer, Loader } from 'semantic-ui-react';
|
|
4
5
|
import { Icon } from '@plone/volto/components';
|
|
5
6
|
import config from '@plone/volto/registry';
|
|
@@ -44,70 +45,85 @@ const ListingBody = withQuerystringResults((props) => {
|
|
|
44
45
|
? variation.noResultsComponent
|
|
45
46
|
: config.blocks?.blocksConfig['listing'].noResultsComponent;
|
|
46
47
|
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
prevItem={{
|
|
68
|
-
content: <Icon name={paginationLeftSVG} size="18px" />,
|
|
69
|
-
icon: true,
|
|
70
|
-
'aria-disabled': !prevBatch,
|
|
71
|
-
className: !prevBatch ? 'disabled' : null,
|
|
72
|
-
}}
|
|
73
|
-
nextItem={{
|
|
74
|
-
content: <Icon name={paginationRightSVG} size="18px" />,
|
|
75
|
-
icon: true,
|
|
76
|
-
'aria-disabled': !nextBatch,
|
|
77
|
-
className: !nextBatch ? 'disabled' : null,
|
|
78
|
-
}}
|
|
48
|
+
const HeadlineTag = data.headlineTag || 'h2';
|
|
49
|
+
|
|
50
|
+
return (
|
|
51
|
+
<>
|
|
52
|
+
{data.headline && (
|
|
53
|
+
<HeadlineTag
|
|
54
|
+
className={cx('headline', {
|
|
55
|
+
emptyListing: !listingItems?.length > 0,
|
|
56
|
+
})}
|
|
57
|
+
>
|
|
58
|
+
{data.headline}
|
|
59
|
+
</HeadlineTag>
|
|
60
|
+
)}
|
|
61
|
+
{listingItems?.length > 0 ? (
|
|
62
|
+
<div ref={listingRef}>
|
|
63
|
+
<ListingBodyTemplate
|
|
64
|
+
items={listingItems}
|
|
65
|
+
isEditMode={isEditMode}
|
|
66
|
+
{...data}
|
|
67
|
+
{...variation}
|
|
79
68
|
/>
|
|
69
|
+
{totalPages > 1 && (
|
|
70
|
+
<div className="pagination-wrapper">
|
|
71
|
+
<Pagination
|
|
72
|
+
activePage={currentPage}
|
|
73
|
+
totalPages={totalPages}
|
|
74
|
+
onPageChange={(e, { activePage }) => {
|
|
75
|
+
!isEditMode &&
|
|
76
|
+
listingRef.current.scrollIntoView({ behavior: 'smooth' });
|
|
77
|
+
onPaginationChange(e, { activePage });
|
|
78
|
+
}}
|
|
79
|
+
firstItem={null}
|
|
80
|
+
lastItem={null}
|
|
81
|
+
prevItem={{
|
|
82
|
+
content: <Icon name={paginationLeftSVG} size="18px" />,
|
|
83
|
+
icon: true,
|
|
84
|
+
'aria-disabled': !prevBatch,
|
|
85
|
+
className: !prevBatch ? 'disabled' : null,
|
|
86
|
+
}}
|
|
87
|
+
nextItem={{
|
|
88
|
+
content: <Icon name={paginationRightSVG} size="18px" />,
|
|
89
|
+
icon: true,
|
|
90
|
+
'aria-disabled': !nextBatch,
|
|
91
|
+
className: !nextBatch ? 'disabled' : null,
|
|
92
|
+
}}
|
|
93
|
+
/>
|
|
94
|
+
</div>
|
|
95
|
+
)}
|
|
96
|
+
</div>
|
|
97
|
+
) : isEditMode ? (
|
|
98
|
+
<div className="listing message" ref={listingRef}>
|
|
99
|
+
{isFolderContentsListing && (
|
|
100
|
+
<FormattedMessage
|
|
101
|
+
id="No items found in this container."
|
|
102
|
+
defaultMessage="No items found in this container."
|
|
103
|
+
/>
|
|
104
|
+
)}
|
|
105
|
+
{hasLoaded && NoResults && (
|
|
106
|
+
<NoResults isEditMode={isEditMode} {...data} />
|
|
107
|
+
)}
|
|
108
|
+
<Dimmer active={!hasLoaded} inverted>
|
|
109
|
+
<Loader indeterminate size="small">
|
|
110
|
+
<FormattedMessage id="loading" defaultMessage="Loading" />
|
|
111
|
+
</Loader>
|
|
112
|
+
</Dimmer>
|
|
113
|
+
</div>
|
|
114
|
+
) : (
|
|
115
|
+
<div className="emptyListing">
|
|
116
|
+
{hasLoaded && NoResults && (
|
|
117
|
+
<NoResults isEditMode={isEditMode} {...data} />
|
|
118
|
+
)}
|
|
119
|
+
<Dimmer active={!hasLoaded} inverted>
|
|
120
|
+
<Loader indeterminate size="small">
|
|
121
|
+
<FormattedMessage id="loading" defaultMessage="Loading" />
|
|
122
|
+
</Loader>
|
|
123
|
+
</Dimmer>
|
|
80
124
|
</div>
|
|
81
125
|
)}
|
|
82
|
-
|
|
83
|
-
) : isEditMode ? (
|
|
84
|
-
<div className="listing message" ref={listingRef}>
|
|
85
|
-
{isFolderContentsListing && (
|
|
86
|
-
<FormattedMessage
|
|
87
|
-
id="No items found in this container."
|
|
88
|
-
defaultMessage="No items found in this container."
|
|
89
|
-
/>
|
|
90
|
-
)}
|
|
91
|
-
{hasLoaded && NoResults && (
|
|
92
|
-
<NoResults isEditMode={isEditMode} {...data} />
|
|
93
|
-
)}
|
|
94
|
-
<Dimmer active={!hasLoaded} inverted>
|
|
95
|
-
<Loader indeterminate size="small">
|
|
96
|
-
<FormattedMessage id="loading" defaultMessage="Loading" />
|
|
97
|
-
</Loader>
|
|
98
|
-
</Dimmer>
|
|
99
|
-
</div>
|
|
100
|
-
) : (
|
|
101
|
-
<div>
|
|
102
|
-
{hasLoaded && NoResults && (
|
|
103
|
-
<NoResults isEditMode={isEditMode} {...data} />
|
|
104
|
-
)}
|
|
105
|
-
<Dimmer active={!hasLoaded} inverted>
|
|
106
|
-
<Loader indeterminate size="small">
|
|
107
|
-
<FormattedMessage id="loading" defaultMessage="Loading" />
|
|
108
|
-
</Loader>
|
|
109
|
-
</Dimmer>
|
|
110
|
-
</div>
|
|
126
|
+
</>
|
|
111
127
|
);
|
|
112
128
|
});
|
|
113
129
|
|
|
@@ -7,15 +7,11 @@ import { ListingBlockBody as ListingBody } from '@plone/volto/components';
|
|
|
7
7
|
|
|
8
8
|
const View = (props) => {
|
|
9
9
|
const { data, path, pathname, className } = props;
|
|
10
|
-
const HeadlineTag = data.headlineTag || 'h2';
|
|
11
10
|
|
|
12
11
|
return (
|
|
13
12
|
<div
|
|
14
13
|
className={cx('block listing', data.variation || 'default', className)}
|
|
15
14
|
>
|
|
16
|
-
{data.headline && (
|
|
17
|
-
<HeadlineTag className="headline">{data.headline}</HeadlineTag>
|
|
18
|
-
)}
|
|
19
15
|
<ListingBody {...props} path={path ?? pathname} />
|
|
20
16
|
</div>
|
|
21
17
|
);
|
|
@@ -1,7 +1,13 @@
|
|
|
1
1
|
import { getQueryStringResults } from '@plone/volto/actions';
|
|
2
2
|
import { resolveBlockExtensions } from '@plone/volto/helpers';
|
|
3
3
|
|
|
4
|
-
|
|
4
|
+
const getListingBlockAsyncData = ({
|
|
5
|
+
dispatch,
|
|
6
|
+
id,
|
|
7
|
+
data,
|
|
8
|
+
path,
|
|
9
|
+
blocksConfig,
|
|
10
|
+
}) => {
|
|
5
11
|
const { resolvedExtensions } = resolveBlockExtensions(data, blocksConfig);
|
|
6
12
|
|
|
7
13
|
return [
|
|
@@ -14,8 +20,10 @@ export default ({ dispatch, data, path, blocksConfig }) => {
|
|
|
14
20
|
? { fullobjects: 1 }
|
|
15
21
|
: { metadata_fields: '_all' }),
|
|
16
22
|
},
|
|
17
|
-
|
|
23
|
+
id,
|
|
18
24
|
),
|
|
19
25
|
),
|
|
20
26
|
];
|
|
21
27
|
};
|
|
28
|
+
|
|
29
|
+
export default getListingBlockAsyncData;
|