@eeacms/volto-tableau 6.0.0 → 6.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +30 -4
- package/Dockerfile +1 -1
- package/Jenkinsfile +153 -135
- package/Makefile +35 -2
- package/cypress.config.js +2 -2
- package/package.json +1 -1
- package/src/Blocks/EmbedTableauVisualization/View.jsx +6 -8
- package/src/Blocks/EmbedTableauVisualization/View.test.jsx +1 -1
- package/src/Tableau/Tableau.jsx +31 -25
- package/src/Utils/{Download/Download.jsx → Download.jsx} +31 -38
- package/src/Utils/index.js +2 -0
- package/src/Views/VisualizationView.jsx +4 -0
- package/src/Widgets/VisualizationViewWidget.jsx +6 -1
- package/src/Widgets/VisualizationViewWidget.test.jsx +33 -0
- package/src/Widgets/VisualizationWidget.jsx +16 -4
- package/src/Widgets/VisualizationWidget.test.jsx +45 -0
- package/src/Widgets/schema.js +2 -1
- package/src/helpers.js +0 -24
- package/src/Utils/Download/Download.test.jsx +0 -22
- package/src/Utils/FigureNote/FigureNote.jsx +0 -43
- package/src/Utils/FigureNote/FigureNote.test.jsx +0 -25
- package/src/Utils/MoreInfoLink/MoreInfoLink.jsx +0 -22
- package/src/Utils/MoreInfoLink/MoreInfoLink.test.jsx +0 -24
- package/src/Utils/Share/Share.jsx +0 -69
- package/src/Utils/Sources/Sources.jsx +0 -67
- /package/src/Utils/{JsonCodeSnippet/JsonCodeSnippet.jsx → JsonCodeSnippet.jsx} +0 -0
package/src/Tableau/Tableau.jsx
CHANGED
|
@@ -14,17 +14,21 @@ import isUndefined from 'lodash/isUndefined';
|
|
|
14
14
|
import cx from 'classnames';
|
|
15
15
|
import { Button } from 'semantic-ui-react';
|
|
16
16
|
import { Toast, Icon } from '@plone/volto/components';
|
|
17
|
+
import {
|
|
18
|
+
FigureNote,
|
|
19
|
+
Sources,
|
|
20
|
+
MoreInfo,
|
|
21
|
+
Share,
|
|
22
|
+
} from '@eeacms/volto-embed/Toolbar';
|
|
17
23
|
import { useTableau } from '@eeacms/volto-tableau/hooks';
|
|
18
|
-
import JsonCodeSnippet from '@eeacms/volto-tableau/Utils
|
|
19
|
-
|
|
20
|
-
import Sources from '@eeacms/volto-tableau/Utils/Sources/Sources';
|
|
21
|
-
import MoreInfoLink from '@eeacms/volto-tableau/Utils/MoreInfoLink/MoreInfoLink';
|
|
22
|
-
import Download from '@eeacms/volto-tableau/Utils/Download/Download';
|
|
23
|
-
import Share from '@eeacms/volto-tableau/Utils/Share/Share';
|
|
24
|
+
import { JsonCodeSnippet, Download } from '@eeacms/volto-tableau/Utils';
|
|
25
|
+
|
|
24
26
|
import { getSheetnames, getActiveSheetname, getDevice } from './helpers';
|
|
25
27
|
|
|
26
28
|
import resetSVG from '@plone/volto/icons/reset.svg';
|
|
27
29
|
|
|
30
|
+
import '@eeacms/volto-embed/Toolbar/styles.less';
|
|
31
|
+
|
|
28
32
|
const TableauDebug = ({ mode, data, vizState, url, version, clearData }) => {
|
|
29
33
|
const { loaded, error } = vizState;
|
|
30
34
|
const { filters = {}, parameters = {} } = data;
|
|
@@ -96,12 +100,12 @@ const Tableau = forwardRef((props, ref) => {
|
|
|
96
100
|
toolbarPosition = 'Top',
|
|
97
101
|
breakpointUrls = [],
|
|
98
102
|
tableau_vis_url,
|
|
99
|
-
with_note,
|
|
100
|
-
with_sources,
|
|
101
|
-
with_more_info,
|
|
102
|
-
with_download,
|
|
103
|
-
with_share,
|
|
104
|
-
tableau_height
|
|
103
|
+
with_note = true,
|
|
104
|
+
with_sources = true,
|
|
105
|
+
with_more_info = true,
|
|
106
|
+
with_download = true,
|
|
107
|
+
with_share = true,
|
|
108
|
+
tableau_height,
|
|
105
109
|
} = data;
|
|
106
110
|
const device = useMemo(
|
|
107
111
|
() => getDevice(breakpoints, screen.page?.width || Infinity),
|
|
@@ -412,25 +416,27 @@ const Tableau = forwardRef((props, ref) => {
|
|
|
412
416
|
clearData={clearData}
|
|
413
417
|
/>
|
|
414
418
|
<div
|
|
415
|
-
style={{ height: tableau_height + 'px' }}
|
|
419
|
+
style={{ height: tableau_height ? tableau_height + 'px' : '100%' }}
|
|
416
420
|
className={cx('tableau', `tableau-${version}`, {
|
|
417
421
|
'tableau-autoscale': autoScale,
|
|
418
422
|
})}
|
|
419
423
|
ref={vizEl}
|
|
420
424
|
/>
|
|
421
|
-
|
|
422
|
-
<div className="visualization-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
<
|
|
427
|
-
|
|
425
|
+
{loaded && (
|
|
426
|
+
<div className="visualization-toolbar">
|
|
427
|
+
<div className="left-col">
|
|
428
|
+
{with_note && <FigureNote note={figure_note || []} />}
|
|
429
|
+
{with_sources && <Sources sources={sources} />}
|
|
430
|
+
{with_more_info && <MoreInfo href={tableau_vis_url || data.url} />}
|
|
431
|
+
</div>
|
|
432
|
+
<div className="right-col">
|
|
433
|
+
{with_download && loaded && <Download viz={viz.current} />}
|
|
434
|
+
{with_share && loaded && (
|
|
435
|
+
<Share href={tableau_vis_url || data.url} />
|
|
436
|
+
)}
|
|
437
|
+
</div>
|
|
428
438
|
</div>
|
|
429
|
-
|
|
430
|
-
{with_download && loaded && <Download viz={viz.current} />}
|
|
431
|
-
{with_share && loaded && <Share contentTypeLink={tableau_vis_url} />}
|
|
432
|
-
</div>
|
|
433
|
-
</div>
|
|
439
|
+
)}
|
|
434
440
|
</div>
|
|
435
441
|
);
|
|
436
442
|
});
|
|
@@ -3,37 +3,37 @@ import { Popup } from 'semantic-ui-react';
|
|
|
3
3
|
import cx from 'classnames';
|
|
4
4
|
|
|
5
5
|
const Download = ({ viz }) => {
|
|
6
|
-
const [
|
|
6
|
+
const [open, setOpen] = React.useState(false);
|
|
7
7
|
const popupRef = React.useRef();
|
|
8
8
|
|
|
9
9
|
return (
|
|
10
10
|
<Popup
|
|
11
|
-
popper={{ id: '
|
|
12
|
-
trigger={
|
|
13
|
-
<div className="tableau-download-container">
|
|
14
|
-
<button className={cx('tableau-download-button', { expanded })}>
|
|
15
|
-
Download <i class="ri-download-fill"></i>
|
|
16
|
-
</button>
|
|
17
|
-
</div>
|
|
18
|
-
}
|
|
11
|
+
popper={{ id: 'vis-toolbar-popup', className: 'download-popup' }}
|
|
19
12
|
position="bottom left"
|
|
20
13
|
on="click"
|
|
14
|
+
open={open}
|
|
21
15
|
onClose={() => {
|
|
22
|
-
|
|
16
|
+
setOpen(false);
|
|
23
17
|
}}
|
|
24
18
|
onOpen={() => {
|
|
25
|
-
|
|
19
|
+
setOpen(true);
|
|
26
20
|
}}
|
|
27
21
|
ref={popupRef}
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
22
|
+
trigger={
|
|
23
|
+
<div className="tableau-download-container">
|
|
24
|
+
<button className={cx('trigger-button', { open })}>
|
|
25
|
+
<i className="ri-download-fill" />
|
|
26
|
+
Download
|
|
27
|
+
</button>
|
|
28
|
+
</div>
|
|
29
|
+
}
|
|
30
|
+
content={
|
|
31
|
+
<>
|
|
32
|
+
<div className="item">
|
|
33
|
+
<span className="label">Data formats</span>
|
|
34
|
+
<div className="types">
|
|
35
|
+
<div className="type">
|
|
35
36
|
<button
|
|
36
|
-
className="tableau-download-button tableau-format-download"
|
|
37
37
|
onClick={() => {
|
|
38
38
|
viz.showExportCrossTabDialog();
|
|
39
39
|
popupRef.current.triggerRef.current.click();
|
|
@@ -42,9 +42,8 @@ const Download = ({ viz }) => {
|
|
|
42
42
|
<span>CSV</span>
|
|
43
43
|
</button>
|
|
44
44
|
</div>
|
|
45
|
-
<div>
|
|
45
|
+
<div className="type">
|
|
46
46
|
<button
|
|
47
|
-
className="tableau-download-button tableau-format-download"
|
|
48
47
|
onClick={() => {
|
|
49
48
|
viz.exportCrossTabToExcel();
|
|
50
49
|
popupRef.current.triggerRef.current.click();
|
|
@@ -55,14 +54,11 @@ const Download = ({ viz }) => {
|
|
|
55
54
|
</div>
|
|
56
55
|
</div>
|
|
57
56
|
</div>
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
<div className="visualization-info">
|
|
63
|
-
<div>
|
|
57
|
+
<div className="item">
|
|
58
|
+
<span className="label">Image formats</span>
|
|
59
|
+
<div className="types">
|
|
60
|
+
<div className="type">
|
|
64
61
|
<button
|
|
65
|
-
className="tableau-download-button tableau-format-download"
|
|
66
62
|
onClick={() => {
|
|
67
63
|
viz.showExportImageDialog();
|
|
68
64
|
popupRef.current.triggerRef.current.click();
|
|
@@ -73,14 +69,11 @@ const Download = ({ viz }) => {
|
|
|
73
69
|
</div>
|
|
74
70
|
</div>
|
|
75
71
|
</div>
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
<div className="visualization-info">
|
|
81
|
-
<div>
|
|
72
|
+
<div className="item">
|
|
73
|
+
<span className="label">Other formats</span>
|
|
74
|
+
<div className="types">
|
|
75
|
+
<div className="type">
|
|
82
76
|
<button
|
|
83
|
-
className="tableau-download-button tableau-format-download"
|
|
84
77
|
onClick={() => {
|
|
85
78
|
viz.showExportPDFDialog();
|
|
86
79
|
popupRef.current.triggerRef.current.click();
|
|
@@ -91,9 +84,9 @@ const Download = ({ viz }) => {
|
|
|
91
84
|
</div>
|
|
92
85
|
</div>
|
|
93
86
|
</div>
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
87
|
+
</>
|
|
88
|
+
}
|
|
89
|
+
/>
|
|
97
90
|
);
|
|
98
91
|
};
|
|
99
92
|
|
|
@@ -3,14 +3,19 @@ import config from '@plone/volto/registry';
|
|
|
3
3
|
|
|
4
4
|
export default function VisualizationViewWidget(props) {
|
|
5
5
|
const { value = {} } = props;
|
|
6
|
+
|
|
6
7
|
return (
|
|
7
8
|
<Tableau
|
|
8
9
|
data={{
|
|
9
10
|
...value,
|
|
11
|
+
with_note: false,
|
|
12
|
+
with_sources: false,
|
|
13
|
+
with_more_info: true,
|
|
14
|
+
with_share: true,
|
|
10
15
|
with_download: true,
|
|
11
16
|
}}
|
|
12
17
|
breakpoints={
|
|
13
|
-
config.blocks.blocksConfig
|
|
18
|
+
config.blocks.blocksConfig?.embed_tableau_visualization?.breakpoints
|
|
14
19
|
}
|
|
15
20
|
/>
|
|
16
21
|
);
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { render } from '@testing-library/react';
|
|
3
|
+
import '@testing-library/jest-dom/extend-expect';
|
|
4
|
+
import { Provider } from 'react-redux';
|
|
5
|
+
import configureStore from 'redux-mock-store';
|
|
6
|
+
import VisualizationViewWidget from './VisualizationViewWidget';
|
|
7
|
+
|
|
8
|
+
const mockStore = configureStore([]);
|
|
9
|
+
const store = mockStore({});
|
|
10
|
+
|
|
11
|
+
jest.mock('@plone/volto/components', () => ({
|
|
12
|
+
Icon: ({ children }) => <img alt="incon">{children}</img>,
|
|
13
|
+
Toast: ({ children }) => <p>{children}</p>,
|
|
14
|
+
}));
|
|
15
|
+
|
|
16
|
+
describe('VisualizationViewWidget', () => {
|
|
17
|
+
it('should render the component', () => {
|
|
18
|
+
const data = {
|
|
19
|
+
url: 'http://localhost:3000/tableau-ct',
|
|
20
|
+
with_download: true,
|
|
21
|
+
with_more_info: true,
|
|
22
|
+
with_note: true,
|
|
23
|
+
with_share: true,
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
const { container } = render(
|
|
27
|
+
<Provider store={store}>
|
|
28
|
+
<VisualizationViewWidget data={data} />
|
|
29
|
+
</Provider>,
|
|
30
|
+
);
|
|
31
|
+
expect(container.querySelector('.tableau-wrapper')).toBeInTheDocument();
|
|
32
|
+
});
|
|
33
|
+
});
|
|
@@ -72,11 +72,18 @@ const VisualizationWidget = (props) => {
|
|
|
72
72
|
>
|
|
73
73
|
<Tableau
|
|
74
74
|
ref={viz}
|
|
75
|
-
data={
|
|
75
|
+
data={{
|
|
76
|
+
...(value || {}),
|
|
77
|
+
with_note: false,
|
|
78
|
+
with_sources: false,
|
|
79
|
+
with_more_info: false,
|
|
80
|
+
with_share: false,
|
|
81
|
+
with_download: false,
|
|
82
|
+
}}
|
|
76
83
|
mode="edit"
|
|
77
84
|
breakpoints={
|
|
78
|
-
config.blocks.blocksConfig
|
|
79
|
-
|
|
85
|
+
config.blocks.blocksConfig?.embed_tableau_visualization
|
|
86
|
+
?.breakpoints
|
|
80
87
|
}
|
|
81
88
|
extraOptions={extraOptions}
|
|
82
89
|
setVizState={setVizState}
|
|
@@ -116,9 +123,14 @@ const VisualizationWidget = (props) => {
|
|
|
116
123
|
data={{
|
|
117
124
|
...props.value,
|
|
118
125
|
autoScale: true,
|
|
126
|
+
with_note: false,
|
|
127
|
+
with_sources: false,
|
|
128
|
+
with_more_info: false,
|
|
129
|
+
with_share: false,
|
|
130
|
+
with_download: false,
|
|
119
131
|
}}
|
|
120
132
|
breakpoints={
|
|
121
|
-
config.blocks.blocksConfig
|
|
133
|
+
config.blocks.blocksConfig?.embed_tableau_visualization?.breakpoints
|
|
122
134
|
}
|
|
123
135
|
extraOptions={extraOptions}
|
|
124
136
|
/>
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { render } from '@testing-library/react';
|
|
3
|
+
import '@testing-library/jest-dom/extend-expect';
|
|
4
|
+
import { Provider } from 'react-redux';
|
|
5
|
+
import configureStore from 'redux-mock-store';
|
|
6
|
+
import VisualizationWidget from './VisualizationWidget';
|
|
7
|
+
|
|
8
|
+
const mockStore = configureStore([]);
|
|
9
|
+
const store = mockStore({});
|
|
10
|
+
|
|
11
|
+
jest.mock('@plone/volto/components', () => ({
|
|
12
|
+
FormFieldWrapper: jest.fn(({ children }) => <>{children}</>),
|
|
13
|
+
InlineForm: jest.fn(() => <div>Mocked InlineForm</div>),
|
|
14
|
+
Icon: ({ children }) => <img alt="incon">{children}</img>,
|
|
15
|
+
Toast: ({ children }) => <p>{children}</p>,
|
|
16
|
+
}));
|
|
17
|
+
|
|
18
|
+
describe('VisualizationWidget', () => {
|
|
19
|
+
it('should render the component', () => {
|
|
20
|
+
const data = {
|
|
21
|
+
value: {
|
|
22
|
+
url: 'http://localhost:3000/tableau-ct',
|
|
23
|
+
with_download: true,
|
|
24
|
+
with_more_info: true,
|
|
25
|
+
with_note: true,
|
|
26
|
+
with_share: true,
|
|
27
|
+
hideTabs: false,
|
|
28
|
+
staticParameters: [
|
|
29
|
+
{
|
|
30
|
+
'@id': '1f050748-c020-4a48-8109-e99a25bf558d',
|
|
31
|
+
field: 'Tableau field',
|
|
32
|
+
value: 'Tableau value',
|
|
33
|
+
},
|
|
34
|
+
],
|
|
35
|
+
},
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
const { container } = render(
|
|
39
|
+
<Provider store={store}>
|
|
40
|
+
<VisualizationWidget {...data} />
|
|
41
|
+
</Provider>,
|
|
42
|
+
);
|
|
43
|
+
expect(container.querySelector('.tableau-wrapper')).toBeInTheDocument();
|
|
44
|
+
});
|
|
45
|
+
});
|
package/src/Widgets/schema.js
CHANGED
|
@@ -38,7 +38,8 @@ const staticParameters = {
|
|
|
38
38
|
};
|
|
39
39
|
|
|
40
40
|
const breakpointUrlSchema = (config) => {
|
|
41
|
-
const breakpoints =
|
|
41
|
+
const breakpoints =
|
|
42
|
+
config.blocks.blocksConfig?.tableau_block?.breakpoints || {};
|
|
42
43
|
|
|
43
44
|
return {
|
|
44
45
|
title: 'URL',
|
package/src/helpers.js
CHANGED
|
@@ -1,5 +1,3 @@
|
|
|
1
|
-
import React from 'react';
|
|
2
|
-
|
|
3
1
|
export const loadTableauScript = (callback, version) => {
|
|
4
2
|
if (!__CLIENT__) return;
|
|
5
3
|
const source = `https://public.tableau.com/javascripts/api/tableau-${version}.min.js`;
|
|
@@ -34,25 +32,3 @@ export const loadTableauScript = (callback, version) => {
|
|
|
34
32
|
// https://public.tableau.com/javascripts/api/tableau-2.2.2.min.js
|
|
35
33
|
// https://public.tableau.com/javascripts/api/tableau-2.1.2.min.js
|
|
36
34
|
// https://public.tableau.com/javascripts/api/tableau-2.0.3.min.js
|
|
37
|
-
|
|
38
|
-
export const useCopyToClipboard = (text) => {
|
|
39
|
-
const [copyStatus, setCopyStatus] = React.useState('inactive');
|
|
40
|
-
const copy = React.useCallback(() => {
|
|
41
|
-
navigator.clipboard.writeText(text).then(
|
|
42
|
-
() => setCopyStatus('copied'),
|
|
43
|
-
() => setCopyStatus('failed'),
|
|
44
|
-
);
|
|
45
|
-
}, [text]);
|
|
46
|
-
|
|
47
|
-
React.useEffect(() => {
|
|
48
|
-
if (copyStatus === 'inactive') {
|
|
49
|
-
return;
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
const timeout = setTimeout(() => setCopyStatus('inactive'), 3000);
|
|
53
|
-
|
|
54
|
-
return () => clearTimeout(timeout);
|
|
55
|
-
}, [copyStatus]);
|
|
56
|
-
|
|
57
|
-
return [copyStatus, copy];
|
|
58
|
-
};
|
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
import React from 'react';
|
|
2
|
-
import { render } from '@testing-library/react';
|
|
3
|
-
import '@testing-library/jest-dom/extend-expect';
|
|
4
|
-
|
|
5
|
-
import Download from './Download';
|
|
6
|
-
|
|
7
|
-
window.URL.createObjectURL = jest.fn(() => 'test');
|
|
8
|
-
|
|
9
|
-
jest.mock('@plone/volto/components', () => ({
|
|
10
|
-
Icon: ({ children }) => <img alt="incon">{children}</img>,
|
|
11
|
-
}));
|
|
12
|
-
|
|
13
|
-
describe('Download', () => {
|
|
14
|
-
const viz = {};
|
|
15
|
-
|
|
16
|
-
it('should render the component', () => {
|
|
17
|
-
const { container } = render(<Download viz={viz} />);
|
|
18
|
-
expect(
|
|
19
|
-
container.querySelector('.tableau-download-container'),
|
|
20
|
-
).toBeInTheDocument();
|
|
21
|
-
});
|
|
22
|
-
});
|
|
@@ -1,43 +0,0 @@
|
|
|
1
|
-
import React from 'react';
|
|
2
|
-
import cx from 'classnames';
|
|
3
|
-
import { Popup } from 'semantic-ui-react';
|
|
4
|
-
import {
|
|
5
|
-
serializeNodes,
|
|
6
|
-
serializeNodesToText,
|
|
7
|
-
} from '@plone/volto-slate/editor/render';
|
|
8
|
-
import { isArray } from 'lodash';
|
|
9
|
-
|
|
10
|
-
export const serializeText = (note) => {
|
|
11
|
-
if (!serializeNodesToText(note))
|
|
12
|
-
return <p>There are no notes set for this visualization</p>;
|
|
13
|
-
return isArray(note) ? serializeNodes(note) : note;
|
|
14
|
-
};
|
|
15
|
-
|
|
16
|
-
const FigureNote = ({ note = [] }) => {
|
|
17
|
-
const [expanded, setExpanded] = React.useState(false);
|
|
18
|
-
|
|
19
|
-
return (
|
|
20
|
-
<div className="tableau-note-container">
|
|
21
|
-
<Popup
|
|
22
|
-
position="bottom left"
|
|
23
|
-
popper={{ id: 'tableau-note-popup' }}
|
|
24
|
-
trigger={
|
|
25
|
-
<button className={cx('tableau-note-button', { expanded })}>
|
|
26
|
-
Note
|
|
27
|
-
</button>
|
|
28
|
-
}
|
|
29
|
-
on="click"
|
|
30
|
-
onClose={() => {
|
|
31
|
-
setExpanded(false);
|
|
32
|
-
}}
|
|
33
|
-
onOpen={() => {
|
|
34
|
-
setExpanded(true);
|
|
35
|
-
}}
|
|
36
|
-
>
|
|
37
|
-
<Popup.Content>{serializeText(note)}</Popup.Content>
|
|
38
|
-
</Popup>
|
|
39
|
-
</div>
|
|
40
|
-
);
|
|
41
|
-
};
|
|
42
|
-
|
|
43
|
-
export default FigureNote;
|
|
@@ -1,25 +0,0 @@
|
|
|
1
|
-
import React from 'react';
|
|
2
|
-
import { render } from '@testing-library/react';
|
|
3
|
-
import '@testing-library/jest-dom/extend-expect';
|
|
4
|
-
|
|
5
|
-
import FigureNote from './FigureNote';
|
|
6
|
-
|
|
7
|
-
window.URL.createObjectURL = jest.fn(() => 'test');
|
|
8
|
-
|
|
9
|
-
const slateEditor = require('@plone/volto-slate/editor/render');
|
|
10
|
-
slateEditor.serializeNodes = jest.fn();
|
|
11
|
-
|
|
12
|
-
jest.mock('@plone/volto-slate/editor/render', () => ({
|
|
13
|
-
serializeNodesToText: ({ note = [] }) => note,
|
|
14
|
-
}));
|
|
15
|
-
|
|
16
|
-
describe('FigureNote', () => {
|
|
17
|
-
const note = [];
|
|
18
|
-
|
|
19
|
-
it('should render the component', () => {
|
|
20
|
-
const { container } = render(<FigureNote note={note} />);
|
|
21
|
-
expect(
|
|
22
|
-
container.querySelector('.tableau-note-container'),
|
|
23
|
-
).toBeInTheDocument();
|
|
24
|
-
});
|
|
25
|
-
});
|
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
import React from 'react';
|
|
2
|
-
import cx from 'classnames';
|
|
3
|
-
import { UniversalLink } from '@plone/volto/components';
|
|
4
|
-
|
|
5
|
-
const Link = ({ children, ...props }) => {
|
|
6
|
-
if (props.href) {
|
|
7
|
-
return <UniversalLink {...props}>{children}</UniversalLink>;
|
|
8
|
-
}
|
|
9
|
-
return <span {...props}>{children}</span>;
|
|
10
|
-
};
|
|
11
|
-
|
|
12
|
-
const MoreInfoLink = ({ contentTypeLink }) => {
|
|
13
|
-
return (
|
|
14
|
-
<Link href={contentTypeLink}>
|
|
15
|
-
<button className={cx('tableau-more-info-button')}>
|
|
16
|
-
More info <i class="ri-external-link-line"></i>
|
|
17
|
-
</button>
|
|
18
|
-
</Link>
|
|
19
|
-
);
|
|
20
|
-
};
|
|
21
|
-
|
|
22
|
-
export default MoreInfoLink;
|
|
@@ -1,24 +0,0 @@
|
|
|
1
|
-
import React from 'react';
|
|
2
|
-
import { render } from '@testing-library/react';
|
|
3
|
-
import '@testing-library/jest-dom/extend-expect';
|
|
4
|
-
|
|
5
|
-
import MoreInfoLink from './MoreInfoLink';
|
|
6
|
-
|
|
7
|
-
window.URL.createObjectURL = jest.fn(() => 'test');
|
|
8
|
-
|
|
9
|
-
jest.mock('@plone/volto/components', () => ({
|
|
10
|
-
UniversalLink: ({ children }) => <div>{children}</div>,
|
|
11
|
-
}));
|
|
12
|
-
|
|
13
|
-
describe('MoreInfoLink', () => {
|
|
14
|
-
const contentTypeLink = '/tableau-content-type';
|
|
15
|
-
|
|
16
|
-
it('should render the component', () => {
|
|
17
|
-
const { container } = render(
|
|
18
|
-
<MoreInfoLink contentTypeLink={contentTypeLink} />,
|
|
19
|
-
);
|
|
20
|
-
expect(
|
|
21
|
-
container.querySelector('.tableau-more-info-button'),
|
|
22
|
-
).toBeInTheDocument();
|
|
23
|
-
});
|
|
24
|
-
});
|
|
@@ -1,69 +0,0 @@
|
|
|
1
|
-
import React from 'react';
|
|
2
|
-
import { Popup, Input, Button } from 'semantic-ui-react';
|
|
3
|
-
import { useCopyToClipboard } from '../../helpers.js';
|
|
4
|
-
import cx from 'classnames';
|
|
5
|
-
|
|
6
|
-
const Share = ({ contentTypeLink = '' }) => {
|
|
7
|
-
const [expanded, setExpanded] = React.useState(false);
|
|
8
|
-
const popupRef = React.useRef();
|
|
9
|
-
|
|
10
|
-
const CopyUrlButton = ({ className, url, buttonText }) => {
|
|
11
|
-
const [copyUrlStatus, copyUrl] = useCopyToClipboard(url);
|
|
12
|
-
|
|
13
|
-
if (copyUrlStatus === 'copied') {
|
|
14
|
-
buttonText = 'Copied!';
|
|
15
|
-
} else if (copyUrlStatus === 'failed') {
|
|
16
|
-
buttonText = 'Copy failed. Please try again.';
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
return (
|
|
20
|
-
<Button
|
|
21
|
-
primary
|
|
22
|
-
onClick={copyUrl}
|
|
23
|
-
className={cx('copy-button', className)}
|
|
24
|
-
>
|
|
25
|
-
{buttonText}
|
|
26
|
-
</Button>
|
|
27
|
-
);
|
|
28
|
-
};
|
|
29
|
-
|
|
30
|
-
return (
|
|
31
|
-
<Popup
|
|
32
|
-
popper={{ id: 'tableau-share-popup' }}
|
|
33
|
-
trigger={
|
|
34
|
-
<div className="tableau-share-container">
|
|
35
|
-
<button className={cx('tableau-share-button', { expanded })}>
|
|
36
|
-
<span>Share</span>
|
|
37
|
-
<i class="ri-share-fill"></i>
|
|
38
|
-
</button>
|
|
39
|
-
</div>
|
|
40
|
-
}
|
|
41
|
-
position="bottom left"
|
|
42
|
-
on="click"
|
|
43
|
-
onClose={() => {
|
|
44
|
-
setExpanded(false);
|
|
45
|
-
}}
|
|
46
|
-
onOpen={() => {
|
|
47
|
-
setExpanded(true);
|
|
48
|
-
}}
|
|
49
|
-
ref={popupRef}
|
|
50
|
-
>
|
|
51
|
-
<div>
|
|
52
|
-
<span className="tableau-share-popup-text">Copy link</span>
|
|
53
|
-
<div className="tableau-share-popup-container">
|
|
54
|
-
<Input
|
|
55
|
-
className="tableau-share-link"
|
|
56
|
-
defaultValue={contentTypeLink}
|
|
57
|
-
/>
|
|
58
|
-
<CopyUrlButton
|
|
59
|
-
className="tableau-copy-button"
|
|
60
|
-
url={contentTypeLink}
|
|
61
|
-
buttonText="Copy"
|
|
62
|
-
/>
|
|
63
|
-
</div>
|
|
64
|
-
</div>
|
|
65
|
-
</Popup>
|
|
66
|
-
);
|
|
67
|
-
};
|
|
68
|
-
|
|
69
|
-
export default Share;
|