@plone/volto 19.0.0-alpha.0 → 19.0.0-alpha.2
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/.eslintignore +1 -0
- package/.eslintrc +2 -0
- package/CHANGELOG.md +63 -2
- package/locales/ca/LC_MESSAGES/volto.po +15 -0
- package/locales/ca.json +1 -1
- package/locales/de/LC_MESSAGES/volto.po +15 -0
- package/locales/de.json +1 -1
- package/locales/en/LC_MESSAGES/volto.po +15 -0
- package/locales/en.json +1 -1
- package/locales/es/LC_MESSAGES/volto.po +15 -0
- package/locales/es.json +1 -1
- package/locales/eu/LC_MESSAGES/volto.po +15 -0
- package/locales/eu.json +1 -1
- package/locales/fi/LC_MESSAGES/volto.po +15 -0
- package/locales/fi.json +1 -1
- package/locales/fr/LC_MESSAGES/volto.po +15 -0
- package/locales/fr.json +1 -1
- package/locales/hi/LC_MESSAGES/volto.po +15 -0
- package/locales/hi.json +1 -1
- package/locales/it/LC_MESSAGES/volto.po +15 -0
- package/locales/it.json +1 -1
- package/locales/ja/LC_MESSAGES/volto.po +15 -0
- package/locales/ja.json +1 -1
- package/locales/nl/LC_MESSAGES/volto.po +15 -0
- package/locales/nl.json +1 -1
- package/locales/pt/LC_MESSAGES/volto.po +15 -0
- package/locales/pt.json +1 -1
- package/locales/pt_BR/LC_MESSAGES/volto.po +15 -0
- package/locales/pt_BR.json +1 -1
- package/locales/ro/LC_MESSAGES/volto.po +15 -0
- package/locales/ro.json +1 -1
- package/locales/ru/LC_MESSAGES/volto.po +15 -0
- package/locales/ru.json +1 -1
- package/locales/volto.pot +15 -0
- package/locales/zh_CN/LC_MESSAGES/volto.po +15 -0
- package/locales/zh_CN.json +1 -1
- package/package.json +15 -8
- package/src/actions/actions/actions.test.js +3 -3
- package/src/actions/addons/addons.test.js +15 -12
- package/src/actions/aliases/aliases.test.js +1 -1
- package/src/actions/querystring/querystring.test.js +2 -2
- package/src/actions/types/types.test.js +1 -1
- package/src/components/manage/Actions/Actions.test.jsx +5 -1
- package/src/components/manage/Add/Add.jsx +22 -20
- package/src/components/manage/Add/Add.test.jsx +6 -3
- package/src/components/manage/Aliases/Aliases.test.jsx +7 -7
- package/src/components/manage/Blocks/Block/BlocksForm.jsx +1 -0
- package/src/components/manage/Blocks/Block/BlocksForm.test.jsx +48 -16
- package/src/components/manage/Blocks/Block/Edit.jsx +2 -1
- package/src/components/manage/Blocks/Block/Settings.test.jsx +5 -1
- package/src/components/manage/Blocks/Block/StyleWrapper.jsx +11 -3
- package/src/components/manage/Blocks/Description/View.test.jsx +1 -1
- package/src/components/manage/Blocks/HTML/Edit.test.jsx +12 -5
- package/src/components/manage/Blocks/HTML/View.test.jsx +1 -1
- package/src/components/manage/Blocks/Image/ImageSidebar.test.jsx +6 -2
- package/src/components/manage/Blocks/LeadImage/LeadImageSidebar.test.jsx +8 -1
- package/src/components/manage/Blocks/Listing/View.test.jsx +3 -1
- package/src/components/manage/Blocks/Maps/MapsSidebar.test.jsx +5 -1
- package/src/components/manage/Blocks/Search/components/DateRangeFacet.test.jsx +13 -7
- package/src/components/manage/Blocks/Search/components/SelectFacet.test.jsx +12 -6
- package/src/components/manage/Blocks/Title/Edit.jsx +8 -2
- package/src/components/manage/Blocks/ToC/variations/DefaultTocRenderer.test.jsx +11 -1
- package/src/components/manage/Blocks/Video/VideoSidebar.test.jsx +5 -1
- package/src/components/manage/ConditionalLink/ConditionalLink.test.tsx +109 -0
- package/src/components/manage/ConditionalLink/ConditionalLink.tsx +36 -0
- package/src/components/manage/Contents/Contents.test.jsx +29 -13
- package/src/components/manage/Contents/ContentsPropertiesModal.test.jsx +5 -1
- package/src/components/manage/Contents/ContentsRenameModal.test.jsx +5 -1
- package/src/components/manage/Contents/ContentsTagsModal.test.jsx +5 -1
- package/src/components/manage/Contents/ContentsWorkflowModal.test.jsx +5 -1
- package/src/components/manage/Contents/__mocks__/index.tsx +16 -0
- package/src/components/manage/Contents/__mocks__/index.vitest.tsx +5 -0
- package/src/components/manage/Controlpanels/AddonsControlpanel.test.jsx +28 -3
- package/src/components/manage/Controlpanels/Aliases.test.jsx +35 -3
- package/src/components/manage/Controlpanels/ContentType.test.jsx +29 -3
- package/src/components/manage/Controlpanels/ContentTypeLayout.test.jsx +4 -2
- package/src/components/manage/Controlpanels/ContentTypes.test.jsx +25 -2
- package/src/components/manage/Controlpanels/Controlpanel.test.jsx +37 -6
- package/src/components/manage/Controlpanels/Controlpanels.test.jsx +47 -3
- package/src/components/manage/Controlpanels/Groups/GroupsControlpanel.test.jsx +15 -9
- package/src/components/manage/Controlpanels/ModerateComments.test.jsx +31 -5
- package/src/components/manage/Controlpanels/Rules/AddRule.test.jsx +13 -4
- package/src/components/manage/Controlpanels/Rules/ConfigureRule.test.jsx +9 -5
- package/src/components/manage/Controlpanels/Rules/EditRule.test.jsx +12 -4
- package/src/components/manage/Controlpanels/Rules/Rules.test.jsx +7 -3
- package/src/components/manage/Controlpanels/UndoControlpanel.test.jsx +33 -4
- package/src/components/manage/Controlpanels/Users/UserGroupMembershipControlPanel.test.jsx +3 -1
- package/src/components/manage/Controlpanels/Users/UsersControlpanel.test.jsx +15 -9
- package/src/components/manage/Delete/Delete.test.jsx +45 -4
- package/src/components/manage/Diff/Diff.test.jsx +15 -6
- package/src/components/manage/Diff/DiffField.test.jsx +12 -6
- package/src/components/manage/Display/Display.test.jsx +17 -6
- package/src/components/manage/Edit/Edit.test.jsx +11 -3
- package/src/components/manage/Form/BlockDataForm.test.jsx +5 -1
- package/src/components/manage/Form/Form.jsx +32 -0
- package/src/components/manage/Form/Form.test.jsx +27 -19
- package/src/components/manage/Form/InlineForm.test.jsx +5 -1
- package/src/components/manage/Form/ModalForm.test.jsx +5 -1
- package/src/components/manage/Form/__mocks__/index.tsx +17 -0
- package/src/components/manage/Form/__mocks__/index.vitest.tsx +73 -0
- package/src/components/manage/History/History.test.jsx +3 -1
- package/src/components/manage/LinksToItem/LinksToItem.test.jsx +6 -4
- package/src/components/manage/MaybeWrap/MaybeWrap.tsx +15 -0
- package/src/components/manage/Multilingual/ManageTranslations.test.jsx +3 -2
- package/src/components/manage/Preferences/ChangePassword.test.jsx +9 -2
- package/src/components/manage/Preferences/PersonalInformation.test.jsx +3 -1
- package/src/components/manage/Preferences/PersonalPreferences.test.jsx +20 -7
- package/src/components/manage/Rules/Rules.test.jsx +6 -3
- package/src/components/manage/Sharing/Sharing.test.jsx +3 -1
- package/src/components/manage/Sidebar/ObjectBrowserNav.test.jsx +3 -3
- package/src/components/manage/Toolbar/More.test.jsx +6 -7
- package/src/components/manage/UniversalLink/UniversalLink.test.jsx +196 -14
- package/src/components/manage/UniversalLink/UniversalLink.tsx +214 -0
- package/src/components/manage/Widgets/ArrayWidget.test.jsx +22 -5
- package/src/components/manage/Widgets/CheckboxGroupWidget.test.jsx +12 -5
- package/src/components/manage/Widgets/DatetimeWidget.test.jsx +21 -6
- package/src/components/manage/Widgets/ImageWidget.jsx +5 -2
- package/src/components/manage/Widgets/NumberWidget.test.jsx +8 -7
- package/src/components/manage/Widgets/ObjectListWidget.jsx +11 -1
- package/src/components/manage/Widgets/ObjectListWidget.test.jsx +18 -8
- package/src/components/manage/Widgets/ObjectWidget.test.jsx +5 -1
- package/src/components/manage/Widgets/RadioGroupWidget.test.jsx +12 -5
- package/src/components/manage/Widgets/RecurrenceWidget/RecurrenceWidget.test.jsx +12 -6
- package/src/components/manage/Widgets/RegistryImageWidget.test.jsx +43 -41
- package/src/components/manage/Widgets/SchemaWidget.test.jsx +12 -5
- package/src/components/manage/Widgets/SchemaWidgetFieldset.test.jsx +12 -5
- package/src/components/manage/Widgets/SelectAutoComplete.test.jsx +12 -6
- package/src/components/manage/Widgets/SelectWidget.jsx +3 -1
- package/src/components/manage/Widgets/SelectWidget.test.jsx +12 -6
- package/src/components/manage/Widgets/TimeWidget.test.jsx +13 -5
- package/src/components/manage/Widgets/TokenWidget.test.jsx +12 -6
- package/src/components/manage/Widgets/VocabularyTermsWidget.test.jsx +18 -9
- package/src/components/manage/Widgets/__mocks__/index.tsx +16 -0
- package/src/components/manage/Widgets/__mocks__/index.vitest.tsx +41 -0
- package/src/components/manage/Workflow/Workflow.test.jsx +17 -7
- package/src/components/theme/App/App.test.jsx +21 -17
- package/src/components/theme/AppExtras/AppExtras.test.jsx +6 -6
- package/src/components/theme/Comments/CommentEditModal.test.jsx +5 -1
- package/src/components/theme/Comments/Comments.test.jsx +29 -12
- package/src/components/theme/ContactForm/ContactForm.test.jsx +8 -4
- package/src/components/theme/Header/Header.test.jsx +19 -13
- package/src/components/theme/Logout/Logout.test.jsx +1 -1
- package/src/components/theme/PasswordReset/PasswordReset.test.jsx +10 -1
- package/src/components/theme/PasswordReset/RequestPasswordReset.test.jsx +5 -1
- package/src/components/theme/Register/Register.test.jsx +5 -1
- package/src/components/theme/Search/Search.test.jsx +6 -4
- package/src/components/theme/TsTest/TsTest.test.tsx +0 -1
- package/src/components/theme/View/EventDatesInfo.test.jsx +12 -5
- package/src/components/theme/View/EventView.test.jsx +12 -5
- package/src/components/theme/View/ListingView.test.jsx +2 -0
- package/src/components/theme/View/SummaryView.test.jsx +10 -0
- package/src/components/theme/View/TabularView.test.jsx +1 -0
- package/src/components/theme/View/View.test.jsx +42 -23
- package/src/helpers/Api/Api.plone.rest.test.js +11 -9
- package/src/helpers/Api/Api.test.js +11 -14
- package/src/helpers/AsyncConnect/AsyncConnect.test.jsx +145 -189
- package/src/helpers/AuthToken/AuthToken.test.js +60 -22
- package/src/helpers/Blocks/Blocks.test.js +1 -1
- package/src/helpers/Html/Html.test.jsx +32 -28
- package/src/helpers/Loadable/__mocks__/Loadable.jsx +16 -1
- package/src/helpers/Loadable/__mocks__/Loadable.vitest.jsx +39 -0
- package/src/helpers/Utils/withSaveAsDraft.jsx +241 -0
- package/src/middleware/Api.test.js +47 -0
- package/src/middleware/api.js +1 -1
- package/src/middleware/storeProtectLoadUtils.test.js +90 -78
- package/test-setup-globals-vitest.js +46 -0
- package/theme/themes/pastanaga/collections/table.overrides +9 -0
- package/theme/themes/pastanaga/extras/main.less +15 -0
- package/tsconfig.declarations.json +12 -1
- package/tsconfig.json +2 -1
- package/types/components/manage/ConditionalLink/ConditionalLink.d.ts +11 -15
- package/types/components/manage/Contents/__mocks__/index.vitest.d.ts +2 -0
- package/types/components/manage/Form/__mocks__/index.vitest.d.ts +8 -0
- package/types/components/manage/MaybeWrap/MaybeWrap.d.ts +7 -5
- package/types/components/manage/UniversalLink/UniversalLink.d.ts +54 -20
- package/types/components/manage/Widgets/__mocks__/index.vitest.d.ts +33 -0
- package/types/helpers/Loadable/__mocks__/Loadable.vitest.d.ts +3 -0
- package/types/helpers/Utils/withSaveAsDraft.d.ts +1 -0
- package/types/react-router-hash-link.d.ts +12 -0
- package/types/routes.d.ts +4 -0
- package/types/server.d.ts +1 -1
- package/vite-plugins/svg.mjs +81 -0
- package/vitest.config.mjs +77 -0
- package/src/components/manage/ConditionalLink/ConditionalLink.jsx +0 -27
- package/src/components/manage/ConditionalLink/ConditionalLink.test.jsx +0 -30
- package/src/components/manage/MaybeWrap/MaybeWrap.jsx +0 -9
- package/src/components/manage/UniversalLink/UniversalLink.jsx +0 -154
- package/src/components/manage/Widgets/FileWidget.test.jsx +0 -91
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
export declare const AlignWidget: any;
|
|
2
|
+
export declare const ButtonsWidget: any;
|
|
3
|
+
export declare const ArrayWidget: any;
|
|
4
|
+
export declare const CheckboxWidget: any;
|
|
5
|
+
export declare const FileWidget: any;
|
|
6
|
+
export declare const IdWidget: any;
|
|
7
|
+
export declare const PasswordWidget: any;
|
|
8
|
+
export declare const QueryWidget: any;
|
|
9
|
+
export declare const QuerySortOnWidget: any;
|
|
10
|
+
export declare const QuerystringWidget: any;
|
|
11
|
+
export declare const SchemaWidget: any;
|
|
12
|
+
export declare const SelectWidget: any;
|
|
13
|
+
export declare const TextareaWidget: any;
|
|
14
|
+
export declare const TextWidget: any;
|
|
15
|
+
export declare const TokenWidget: any;
|
|
16
|
+
export declare const WysiwygWidget: any;
|
|
17
|
+
export declare const UrlWidget: any;
|
|
18
|
+
export declare const InternalUrlWidget: any;
|
|
19
|
+
export declare const EmailWidget: any;
|
|
20
|
+
export declare const NumberWidget: any;
|
|
21
|
+
export declare const ImageSizeWidget: any;
|
|
22
|
+
export declare const RegistryImageWidget: any;
|
|
23
|
+
export declare const ReferenceWidget: any;
|
|
24
|
+
export declare const ObjectBrowserWidget: any;
|
|
25
|
+
export declare const ObjectWidget: any;
|
|
26
|
+
export declare const ObjectListWidget: any;
|
|
27
|
+
export declare const VocabularyTermsWidget: any;
|
|
28
|
+
export declare const SelectMetadataWidget: any;
|
|
29
|
+
export declare const SelectAutoComplete: any;
|
|
30
|
+
export declare const ColorPickerWidget: any;
|
|
31
|
+
export declare const DatetimeWidget: any;
|
|
32
|
+
export declare const RecurrenceWidget: any;
|
|
33
|
+
export declare const FormFieldWrapper: any;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export default function withSaveAsDraft(options: any): (WrappedComponent: any) => any;
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
declare module 'react-router-hash-link' {
|
|
2
|
+
import { ComponentType } from 'react';
|
|
3
|
+
import { NavLinkProps } from 'react-router-dom';
|
|
4
|
+
|
|
5
|
+
interface HashLinkProps extends NavLinkProps {
|
|
6
|
+
smooth?: boolean;
|
|
7
|
+
scroll?: (element: HTMLElement) => void;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
export const HashLink: ComponentType<HashLinkProps>;
|
|
11
|
+
export const NavHashLink: ComponentType<HashLinkProps>;
|
|
12
|
+
}
|
package/types/routes.d.ts
CHANGED
package/types/server.d.ts
CHANGED
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
import { promises as fs } from 'fs';
|
|
2
|
+
import { optimize as optimizeSvg } from 'svgo';
|
|
3
|
+
import _debug from 'debug';
|
|
4
|
+
|
|
5
|
+
const debug = _debug('volto-vite-svg-loader');
|
|
6
|
+
|
|
7
|
+
export function svgLoader(options = {}) {
|
|
8
|
+
const { svgoConfig, svgo, defaultImport } = options;
|
|
9
|
+
|
|
10
|
+
const svgRegex = /icons\/.*\.svg(\?(raw|skipsvgo))?$/;
|
|
11
|
+
|
|
12
|
+
return {
|
|
13
|
+
name: 'svg-loader',
|
|
14
|
+
enforce: 'pre',
|
|
15
|
+
|
|
16
|
+
async load(id) {
|
|
17
|
+
if (!id.match(svgRegex)) {
|
|
18
|
+
return;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
debug('\n', `Processing: ${id}.`);
|
|
22
|
+
|
|
23
|
+
const [path, query] = id.split('?', 2);
|
|
24
|
+
const importType = query || defaultImport;
|
|
25
|
+
|
|
26
|
+
if (importType === 'url') {
|
|
27
|
+
return; // Use default svg loader
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
let content;
|
|
31
|
+
try {
|
|
32
|
+
content = await fs.readFile(path, 'utf-8');
|
|
33
|
+
} catch (ex) {
|
|
34
|
+
debug(
|
|
35
|
+
'\n',
|
|
36
|
+
`${id} couldn't be loaded by vite-svg-loader, fallback to default loader`,
|
|
37
|
+
);
|
|
38
|
+
|
|
39
|
+
return;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
if (importType === 'raw') {
|
|
43
|
+
return `export default ${JSON.stringify(content)}`;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
if (svgo !== false && query !== 'skipsvgo') {
|
|
47
|
+
content = optimizeSvg(content, {
|
|
48
|
+
...svgoConfig,
|
|
49
|
+
path,
|
|
50
|
+
}).data;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
const match = content.match(/<svg([^>]+)+>([\s\S]+)<\/svg>/i);
|
|
54
|
+
let attrs = {};
|
|
55
|
+
|
|
56
|
+
if (match) {
|
|
57
|
+
attrs = match[1];
|
|
58
|
+
if (attrs) {
|
|
59
|
+
attrs = attrs
|
|
60
|
+
.match(/([\w-:]+)(=)?("[^<>"]*"|'[^<>']*'|[\w-:]+)/g)
|
|
61
|
+
.reduce(function (obj, attr) {
|
|
62
|
+
var split = attr.split('=');
|
|
63
|
+
var name = split[0];
|
|
64
|
+
var value = true;
|
|
65
|
+
if (split && split[1]) {
|
|
66
|
+
value = split[1].replace(/['"]/g, '');
|
|
67
|
+
}
|
|
68
|
+
obj[name] = value;
|
|
69
|
+
return obj;
|
|
70
|
+
}, {});
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
content = match[2] || '';
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
content = content.replace(/\n/g, ' ').trim();
|
|
77
|
+
|
|
78
|
+
return `export default ${JSON.stringify({ attributes: attrs, content: content })}`;
|
|
79
|
+
},
|
|
80
|
+
};
|
|
81
|
+
}
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
import { defineConfig } from 'vitest/config';
|
|
2
|
+
import react from '@vitejs/plugin-react';
|
|
3
|
+
import path from 'path';
|
|
4
|
+
import { svgLoader } from './vite-plugins/svg.mjs';
|
|
5
|
+
import { fileURLToPath } from 'url';
|
|
6
|
+
import { createRequire } from 'module';
|
|
7
|
+
|
|
8
|
+
const require = createRequire(import.meta.url);
|
|
9
|
+
|
|
10
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
11
|
+
const __dirname = path.dirname(__filename);
|
|
12
|
+
|
|
13
|
+
const projectRoot = path.resolve(__dirname);
|
|
14
|
+
|
|
15
|
+
export default defineConfig({
|
|
16
|
+
plugins: [
|
|
17
|
+
react(),
|
|
18
|
+
svgLoader({
|
|
19
|
+
svgoConfig: {
|
|
20
|
+
plugins: [
|
|
21
|
+
{
|
|
22
|
+
name: 'preset-default',
|
|
23
|
+
params: {
|
|
24
|
+
overrides: {
|
|
25
|
+
convertPathData: false,
|
|
26
|
+
removeViewBox: false,
|
|
27
|
+
},
|
|
28
|
+
},
|
|
29
|
+
},
|
|
30
|
+
'removeTitle',
|
|
31
|
+
'removeUselessStrokeAndFill',
|
|
32
|
+
],
|
|
33
|
+
},
|
|
34
|
+
}),
|
|
35
|
+
],
|
|
36
|
+
resolve: {
|
|
37
|
+
alias: {
|
|
38
|
+
'@plone/volto': path.resolve(__dirname, 'src'),
|
|
39
|
+
'@plone/volto-slate': path.resolve(__dirname, '../volto-slate/src'),
|
|
40
|
+
'@root': path.resolve(__dirname, 'src'),
|
|
41
|
+
'promise-file-reader': require.resolve('promise-file-reader'),
|
|
42
|
+
'react-dropzone': require.resolve('react-dropzone'),
|
|
43
|
+
'prop-types': require.resolve('prop-types'),
|
|
44
|
+
},
|
|
45
|
+
},
|
|
46
|
+
test: {
|
|
47
|
+
isolate: true,
|
|
48
|
+
deps: {
|
|
49
|
+
moduleDirectories: ['node_modules'],
|
|
50
|
+
},
|
|
51
|
+
snapshotFormat: { printBasicPrototype: false },
|
|
52
|
+
globals: true,
|
|
53
|
+
environment: 'jsdom',
|
|
54
|
+
setupFiles: [
|
|
55
|
+
`${projectRoot}/test-setup-globals-vitest.js`,
|
|
56
|
+
`${projectRoot}/test-setup-config.jsx`,
|
|
57
|
+
`${projectRoot}/jest-setup-afterenv.js`,
|
|
58
|
+
`${projectRoot}/jest-addons-loader.js`,
|
|
59
|
+
],
|
|
60
|
+
globalSetup: `${projectRoot}/global-test-setup.js`,
|
|
61
|
+
coverage: {
|
|
62
|
+
provider: 'v8',
|
|
63
|
+
reporter: ['text', 'json', 'html'],
|
|
64
|
+
include: [
|
|
65
|
+
'src/**/*.{test,spec}.{js,ts,jsx,tsx}',
|
|
66
|
+
'__test__/**/*.{test,spec}.{js,ts,jsx,tsx}',
|
|
67
|
+
],
|
|
68
|
+
exclude: [
|
|
69
|
+
'node_modules/**',
|
|
70
|
+
'**/dist/**',
|
|
71
|
+
'**/*.config.{js,ts}',
|
|
72
|
+
'**/jest-*.js',
|
|
73
|
+
],
|
|
74
|
+
},
|
|
75
|
+
css: true,
|
|
76
|
+
},
|
|
77
|
+
});
|
|
@@ -1,27 +0,0 @@
|
|
|
1
|
-
import React from 'react';
|
|
2
|
-
import UniversalLink from '@plone/volto/components/manage/UniversalLink/UniversalLink';
|
|
3
|
-
import PropTypes from 'prop-types';
|
|
4
|
-
|
|
5
|
-
const ConditionalLink = ({ condition, to, item, ...props }) => {
|
|
6
|
-
if (condition) {
|
|
7
|
-
return (
|
|
8
|
-
<UniversalLink href={to} item={item} {...props}>
|
|
9
|
-
{props.children}
|
|
10
|
-
</UniversalLink>
|
|
11
|
-
);
|
|
12
|
-
} else {
|
|
13
|
-
return <>{props.children}</>;
|
|
14
|
-
}
|
|
15
|
-
};
|
|
16
|
-
|
|
17
|
-
ConditionalLink.propTypes = {
|
|
18
|
-
condition: PropTypes.bool,
|
|
19
|
-
to: PropTypes.string,
|
|
20
|
-
item: PropTypes.shape({
|
|
21
|
-
'@id': PropTypes.string,
|
|
22
|
-
remoteUrl: PropTypes.string, //of plone @type 'Link'
|
|
23
|
-
}),
|
|
24
|
-
children: PropTypes.node,
|
|
25
|
-
};
|
|
26
|
-
|
|
27
|
-
export default ConditionalLink;
|
|
@@ -1,30 +0,0 @@
|
|
|
1
|
-
import React from 'react';
|
|
2
|
-
import renderer from 'react-test-renderer';
|
|
3
|
-
import { MemoryRouter } from 'react-router-dom';
|
|
4
|
-
|
|
5
|
-
import ConditionalLink from './ConditionalLink';
|
|
6
|
-
|
|
7
|
-
describe('ConditionalLink', () => {
|
|
8
|
-
it('renders a ConditionalLink component not link', () => {
|
|
9
|
-
const component = renderer.create(
|
|
10
|
-
<MemoryRouter>
|
|
11
|
-
<ConditionalLink>
|
|
12
|
-
<h1>Title</h1>
|
|
13
|
-
</ConditionalLink>
|
|
14
|
-
</MemoryRouter>,
|
|
15
|
-
);
|
|
16
|
-
const json = component.toJSON();
|
|
17
|
-
expect(json).toMatchSnapshot();
|
|
18
|
-
});
|
|
19
|
-
it('renders a ConditionalLink component with link', () => {
|
|
20
|
-
const component = renderer.create(
|
|
21
|
-
<MemoryRouter>
|
|
22
|
-
<ConditionalLink isLink>
|
|
23
|
-
<h1>Title</h1>
|
|
24
|
-
</ConditionalLink>
|
|
25
|
-
</MemoryRouter>,
|
|
26
|
-
);
|
|
27
|
-
const json = component.toJSON();
|
|
28
|
-
expect(json).toMatchSnapshot();
|
|
29
|
-
});
|
|
30
|
-
});
|
|
@@ -1,154 +0,0 @@
|
|
|
1
|
-
/*
|
|
2
|
-
* UniversalLink
|
|
3
|
-
* @module components/UniversalLink
|
|
4
|
-
*/
|
|
5
|
-
|
|
6
|
-
import React from 'react';
|
|
7
|
-
import PropTypes from 'prop-types';
|
|
8
|
-
import { HashLink as Link } from 'react-router-hash-link';
|
|
9
|
-
import { useSelector } from 'react-redux';
|
|
10
|
-
import {
|
|
11
|
-
flattenToAppURL,
|
|
12
|
-
isInternalURL,
|
|
13
|
-
URLUtils,
|
|
14
|
-
} from '@plone/volto/helpers/Url/Url';
|
|
15
|
-
|
|
16
|
-
import config from '@plone/volto/registry';
|
|
17
|
-
import cx from 'classnames';
|
|
18
|
-
|
|
19
|
-
const UniversalLink = ({
|
|
20
|
-
href,
|
|
21
|
-
item = null,
|
|
22
|
-
openLinkInNewTab,
|
|
23
|
-
download = false,
|
|
24
|
-
children,
|
|
25
|
-
className = null,
|
|
26
|
-
title = null,
|
|
27
|
-
...props
|
|
28
|
-
}) => {
|
|
29
|
-
const token = useSelector((state) => state.userSession?.token);
|
|
30
|
-
|
|
31
|
-
let url = href;
|
|
32
|
-
if (!href && item) {
|
|
33
|
-
if (item['@id'] === '') {
|
|
34
|
-
url = config.settings.publicURL;
|
|
35
|
-
} else if (!item['@id']) {
|
|
36
|
-
// eslint-disable-next-line no-console
|
|
37
|
-
console.error(
|
|
38
|
-
'Invalid item passed to UniversalLink',
|
|
39
|
-
item,
|
|
40
|
-
props,
|
|
41
|
-
children,
|
|
42
|
-
);
|
|
43
|
-
url = '#';
|
|
44
|
-
} else {
|
|
45
|
-
//case: generic item
|
|
46
|
-
url = flattenToAppURL(item['@id']);
|
|
47
|
-
|
|
48
|
-
//case: item like a Link
|
|
49
|
-
let remoteUrl = item.remoteUrl || item.getRemoteUrl;
|
|
50
|
-
if (!token && remoteUrl) {
|
|
51
|
-
url = remoteUrl;
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
//case: item of type 'File'
|
|
55
|
-
if (
|
|
56
|
-
!token &&
|
|
57
|
-
config.settings.downloadableObjects.includes(item['@type'])
|
|
58
|
-
) {
|
|
59
|
-
url = `${url}/@@download/file`;
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
if (
|
|
63
|
-
!token &&
|
|
64
|
-
config.settings.viewableInBrowserObjects.includes(item['@type'])
|
|
65
|
-
) {
|
|
66
|
-
url = `${url}/@@display-file/file`;
|
|
67
|
-
}
|
|
68
|
-
}
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
const isExternal = !isInternalURL(url);
|
|
72
|
-
|
|
73
|
-
const isDownload = (!isExternal && url.includes('@@download')) || download;
|
|
74
|
-
const isDisplayFile =
|
|
75
|
-
(!isExternal && url.includes('@@display-file')) || false;
|
|
76
|
-
|
|
77
|
-
const checkedURL = URLUtils.checkAndNormalizeUrl(url);
|
|
78
|
-
|
|
79
|
-
url = checkedURL.url;
|
|
80
|
-
let tag = (
|
|
81
|
-
<Link
|
|
82
|
-
to={flattenToAppURL(url)}
|
|
83
|
-
target={openLinkInNewTab ?? false ? '_blank' : null}
|
|
84
|
-
title={title}
|
|
85
|
-
className={className}
|
|
86
|
-
smooth={config.settings.hashLinkSmoothScroll}
|
|
87
|
-
{...props}
|
|
88
|
-
>
|
|
89
|
-
{children}
|
|
90
|
-
</Link>
|
|
91
|
-
);
|
|
92
|
-
|
|
93
|
-
if (isExternal) {
|
|
94
|
-
const isTelephoneOrMail = checkedURL.isMail || checkedURL.isTelephone;
|
|
95
|
-
tag = (
|
|
96
|
-
<a
|
|
97
|
-
href={url}
|
|
98
|
-
title={title}
|
|
99
|
-
target={
|
|
100
|
-
!isTelephoneOrMail && !(openLinkInNewTab === false) ? '_blank' : null
|
|
101
|
-
}
|
|
102
|
-
rel="noopener noreferrer"
|
|
103
|
-
className={cx({ external: !isTelephoneOrMail }, className)}
|
|
104
|
-
{...props}
|
|
105
|
-
>
|
|
106
|
-
{children}
|
|
107
|
-
</a>
|
|
108
|
-
);
|
|
109
|
-
} else if (isDownload) {
|
|
110
|
-
tag = (
|
|
111
|
-
<a
|
|
112
|
-
href={flattenToAppURL(url)}
|
|
113
|
-
download
|
|
114
|
-
title={title}
|
|
115
|
-
className={className}
|
|
116
|
-
{...props}
|
|
117
|
-
>
|
|
118
|
-
{children}
|
|
119
|
-
</a>
|
|
120
|
-
);
|
|
121
|
-
} else if (isDisplayFile) {
|
|
122
|
-
tag = (
|
|
123
|
-
<a
|
|
124
|
-
href={flattenToAppURL(url)}
|
|
125
|
-
title={title}
|
|
126
|
-
target="_blank"
|
|
127
|
-
rel="noopener noreferrer"
|
|
128
|
-
className={className}
|
|
129
|
-
{...props}
|
|
130
|
-
>
|
|
131
|
-
{children}
|
|
132
|
-
</a>
|
|
133
|
-
);
|
|
134
|
-
}
|
|
135
|
-
return tag;
|
|
136
|
-
};
|
|
137
|
-
|
|
138
|
-
UniversalLink.propTypes = {
|
|
139
|
-
href: PropTypes.string,
|
|
140
|
-
openLinkInNewTab: PropTypes.bool,
|
|
141
|
-
download: PropTypes.bool,
|
|
142
|
-
className: PropTypes.string,
|
|
143
|
-
title: PropTypes.string,
|
|
144
|
-
item: PropTypes.shape({
|
|
145
|
-
'@id': PropTypes.string.isRequired,
|
|
146
|
-
remoteUrl: PropTypes.string, //of plone @type 'Link'
|
|
147
|
-
}),
|
|
148
|
-
children: PropTypes.oneOfType([
|
|
149
|
-
PropTypes.arrayOf(PropTypes.node),
|
|
150
|
-
PropTypes.node,
|
|
151
|
-
]),
|
|
152
|
-
};
|
|
153
|
-
|
|
154
|
-
export default UniversalLink;
|
|
@@ -1,91 +0,0 @@
|
|
|
1
|
-
import React from 'react';
|
|
2
|
-
import { Provider } from 'react-intl-redux';
|
|
3
|
-
import { render, waitFor } from '@testing-library/react';
|
|
4
|
-
import configureStore from 'redux-mock-store';
|
|
5
|
-
|
|
6
|
-
import FileWidget from './FileWidget';
|
|
7
|
-
|
|
8
|
-
jest.spyOn(global.Date, 'now').mockImplementation(() => '0');
|
|
9
|
-
|
|
10
|
-
const mockStore = configureStore();
|
|
11
|
-
|
|
12
|
-
describe('FileWidget', () => {
|
|
13
|
-
test('renders an empty file widget component', async () => {
|
|
14
|
-
const store = mockStore({
|
|
15
|
-
intl: {
|
|
16
|
-
locale: 'en',
|
|
17
|
-
messages: {},
|
|
18
|
-
},
|
|
19
|
-
});
|
|
20
|
-
|
|
21
|
-
const { container } = render(
|
|
22
|
-
<Provider store={store}>
|
|
23
|
-
<FileWidget
|
|
24
|
-
id="my-field"
|
|
25
|
-
title="My field"
|
|
26
|
-
fieldSet="default"
|
|
27
|
-
onChange={() => {}}
|
|
28
|
-
/>
|
|
29
|
-
</Provider>,
|
|
30
|
-
);
|
|
31
|
-
|
|
32
|
-
await waitFor(() => {});
|
|
33
|
-
expect(container).toMatchSnapshot();
|
|
34
|
-
});
|
|
35
|
-
test('renders a file widget component with value', async () => {
|
|
36
|
-
const store = mockStore({
|
|
37
|
-
intl: {
|
|
38
|
-
locale: 'en',
|
|
39
|
-
messages: {},
|
|
40
|
-
},
|
|
41
|
-
});
|
|
42
|
-
|
|
43
|
-
const { container } = render(
|
|
44
|
-
<Provider store={store}>
|
|
45
|
-
<FileWidget
|
|
46
|
-
id="my-field"
|
|
47
|
-
title="My field"
|
|
48
|
-
fieldSet="default"
|
|
49
|
-
onChange={() => {}}
|
|
50
|
-
value={{
|
|
51
|
-
download: 'http://myfile',
|
|
52
|
-
'content-type': 'image/png',
|
|
53
|
-
filename: 'myfile',
|
|
54
|
-
encoding: '',
|
|
55
|
-
}}
|
|
56
|
-
/>
|
|
57
|
-
</Provider>,
|
|
58
|
-
);
|
|
59
|
-
|
|
60
|
-
await waitFor(() => {});
|
|
61
|
-
expect(container).toMatchSnapshot();
|
|
62
|
-
});
|
|
63
|
-
test('renders a file widget component with value in raw data', async () => {
|
|
64
|
-
const store = mockStore({
|
|
65
|
-
intl: {
|
|
66
|
-
locale: 'en',
|
|
67
|
-
messages: {},
|
|
68
|
-
},
|
|
69
|
-
});
|
|
70
|
-
|
|
71
|
-
const { container } = render(
|
|
72
|
-
<Provider store={store}>
|
|
73
|
-
<FileWidget
|
|
74
|
-
id="my-field"
|
|
75
|
-
title="My field"
|
|
76
|
-
fieldSet="default"
|
|
77
|
-
onChange={() => {}}
|
|
78
|
-
value={{
|
|
79
|
-
data: 'oiweurtksdgfjaslfqw9523563456',
|
|
80
|
-
'content-type': 'image/png',
|
|
81
|
-
filename: 'myfile',
|
|
82
|
-
encoding: 'base64',
|
|
83
|
-
}}
|
|
84
|
-
/>
|
|
85
|
-
</Provider>,
|
|
86
|
-
);
|
|
87
|
-
|
|
88
|
-
await waitFor(() => {});
|
|
89
|
-
expect(container).toMatchSnapshot();
|
|
90
|
-
});
|
|
91
|
-
});
|