From bc5cbe0d9660a3afc4209d0f2f20491cb8da5060 Mon Sep 17 00:00:00 2001 From: Laszlo Cseh <33250678+laszlocseh@users.noreply.github.com> Date: Thu, 7 Mar 2024 17:09:46 +0200 Subject: [PATCH] feat(download): implement scroll to iframes to ensure print to pdf has preview of iframes (#213) * feat: set isPrint redux state when window.print() is triggered * add isPrint missing files * test: add Logo.test.jsx * test: fix in Logo.test.jsx * test: added HomePageView.test.jsx and HomePageInverseView.test.jsx * chore: cleanup unused RemoveSchema code * chore: cleanup unused RemoveSchema code * test: added TokenWidget.test.jsx and TopicsWidget.test.jsx * Automated release 1.28.4 * Bump version to 1.29.0 from 1.28.4 * Automated release 1.29.0 * fix: smaller timeout in window.print * test: TokenWidget.test.jsx and TopicsWidget.test.jsx cover more conditions * Automated release 1.29.0 --------- Co-authored-by: EEA Jenkins <@users.noreply.github.com> Co-authored-by: Claudia Ifrim --- CHANGELOG.md | 24 ++++ package.json | 2 +- src/actions/index.js | 2 +- src/actions/print.js | 13 +++ src/actions/schema.js | 5 - src/components/theme/Banner/View.jsx | 106 ++++++++++++++++-- .../Homepage/HomePageInverseView.test.jsx | 16 +++ .../theme/Homepage/HomePageView.test.jsx | 16 +++ src/components/theme/Logo.test.jsx | 31 +++++ .../theme/Widgets/TokenWidget.test.jsx | 54 +++++++++ .../theme/Widgets/TopicsWidget.test.jsx | 54 +++++++++ src/constants/ActionTypes.js | 6 + src/index.js | 8 +- src/index.test.js | 5 + src/reducers/index.js | 1 + src/reducers/print.js | 21 ++++ 16 files changed, 345 insertions(+), 19 deletions(-) create mode 100644 src/actions/print.js delete mode 100644 src/actions/schema.js create mode 100644 src/components/theme/Homepage/HomePageInverseView.test.jsx create mode 100644 src/components/theme/Homepage/HomePageView.test.jsx create mode 100644 src/components/theme/Logo.test.jsx create mode 100644 src/components/theme/Widgets/TokenWidget.test.jsx create mode 100644 src/components/theme/Widgets/TopicsWidget.test.jsx create mode 100644 src/constants/ActionTypes.js create mode 100644 src/reducers/index.js create mode 100644 src/reducers/print.js diff --git a/CHANGELOG.md b/CHANGELOG.md index b38b1c41..8aea8f5b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,30 @@ All notable changes to this project will be documented in this file. Dates are d Generated by [`auto-changelog`](https://github.com/CookPete/auto-changelog). +### [1.29.0](https://github.com/eea/volto-eea-website-theme/compare/1.28.3...1.29.0) - 7 March 2024 + +#### :rocket: New Features + +- feat: set isPrint redux state when window.print() is triggered [laszlocseh - [`4d07b9a`](https://github.com/eea/volto-eea-website-theme/commit/4d07b9a76af0e43340e100db10ad1051c61f3a89)] + +#### :bug: Bug Fixes + +- fix: smaller timeout in window.print [laszlocseh - [`808d7e9`](https://github.com/eea/volto-eea-website-theme/commit/808d7e9ef406f38e008a718fd4883fe735c296de)] + +#### :house: Internal changes + +- chore: cleanup unused RemoveSchema code [laszlocseh - [`6d8de0a`](https://github.com/eea/volto-eea-website-theme/commit/6d8de0a27dd6bfd5645bb730d2c66f2d4784c158)] +- chore: cleanup unused RemoveSchema code [laszlocseh - [`c1f2650`](https://github.com/eea/volto-eea-website-theme/commit/c1f2650f0f7ffb27c168399fabcbf69d0299235b)] + +#### :hammer_and_wrench: Others + +- test: TokenWidget.test.jsx and TopicsWidget.test.jsx cover more conditions [laszlocseh - [`dd154bb`](https://github.com/eea/volto-eea-website-theme/commit/dd154bb520237f458be563280cac1545eb381bdf)] +- Bump version to 1.29.0 from 1.28.4 [Claudia Ifrim - [`7bc8eab`](https://github.com/eea/volto-eea-website-theme/commit/7bc8eabd4b0462fc5afc07ed131d074af642cc89)] +- test: added TokenWidget.test.jsx and TopicsWidget.test.jsx [laszlocseh - [`f7292bb`](https://github.com/eea/volto-eea-website-theme/commit/f7292bb426591f758dcc7bc159b5dbd75b7afb36)] +- test: added HomePageView.test.jsx and HomePageInverseView.test.jsx [laszlocseh - [`2076651`](https://github.com/eea/volto-eea-website-theme/commit/2076651820693825b5e20b0a7774307cd78eeb57)] +- test: fix in Logo.test.jsx [laszlocseh - [`6d552f8`](https://github.com/eea/volto-eea-website-theme/commit/6d552f89d5aff6e47ef3032d4862a1bcbe364c01)] +- test: add Logo.test.jsx [laszlocseh - [`752c562`](https://github.com/eea/volto-eea-website-theme/commit/752c5629840d906382858f088b97d33147684ca8)] +- add isPrint missing files [laszlocseh - [`d995789`](https://github.com/eea/volto-eea-website-theme/commit/d995789f337a00455d45b5ec26de9c4c0c898ce6)] ### [1.28.3](https://github.com/eea/volto-eea-website-theme/compare/1.28.2...1.28.3) - 5 March 2024 #### :bug: Bug Fixes diff --git a/package.json b/package.json index cb93e2e9..0da207b9 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@eeacms/volto-eea-website-theme", - "version": "1.28.3", + "version": "1.29.0", "description": "@eeacms/volto-eea-website-theme: Volto add-on", "main": "src/index.js", "author": "European Environment Agency: IDM2 A-Team", diff --git a/src/actions/index.js b/src/actions/index.js index e27a6e2f..47560feb 100644 --- a/src/actions/index.js +++ b/src/actions/index.js @@ -1 +1 @@ -export * from './schema'; +export * from './print'; diff --git a/src/actions/print.js b/src/actions/print.js new file mode 100644 index 00000000..f293ec5a --- /dev/null +++ b/src/actions/print.js @@ -0,0 +1,13 @@ +/** + * Print action. + * @module actions/print + */ + +import { SET_ISPRINT } from '@eeacms/volto-eea-website-theme/constants/ActionTypes'; + +export const setIsPrint = (data) => { + return { + type: SET_ISPRINT, + payload: data, + }; +}; diff --git a/src/actions/schema.js b/src/actions/schema.js deleted file mode 100644 index 72b0313e..00000000 --- a/src/actions/schema.js +++ /dev/null @@ -1,5 +0,0 @@ -export function removeSchema() { - return { - type: 'REMOVE_SCHEMA', - }; -} diff --git a/src/components/theme/Banner/View.jsx b/src/components/theme/Banner/View.jsx index 86c40317..63d0153d 100644 --- a/src/components/theme/Banner/View.jsx +++ b/src/components/theme/Banner/View.jsx @@ -1,11 +1,11 @@ import React, { useCallback, useMemo, useRef } from 'react'; import { Helmet } from '@plone/volto/helpers'; import { compose } from 'redux'; -import { connect } from 'react-redux'; +import { connect, useDispatch } from 'react-redux'; import { withRouter } from 'react-router'; import { defineMessages, injectIntl } from 'react-intl'; import startCase from 'lodash/startCase'; -import { Icon } from 'semantic-ui-react'; +import { Icon, Loader } from 'semantic-ui-react'; import Popup from '@eeacms/volto-eea-design-system/ui/Popup/Popup'; import config from '@plone/volto/registry'; import Banner from '@eeacms/volto-eea-design-system/ui/Banner/Banner'; @@ -14,7 +14,8 @@ import { sharePage, } from '@eeacms/volto-eea-design-system/ui/Banner/Banner'; import Copyright from '@eeacms/volto-eea-design-system/ui/Copyright/Copyright'; - +import { setIsPrint } from '@eeacms/volto-eea-website-theme/actions/print'; +import cx from 'classnames'; import './styles.less'; const messages = defineMessages({ @@ -65,6 +66,7 @@ const Title = ({ config = {}, properties }) => { }; const View = (props) => { + const dispatch = useDispatch(); const { banner = {}, intl } = props; const metadata = props.metadata || props.properties; const popupRef = useRef(null); @@ -164,14 +166,95 @@ const View = (props) => { )} {!hideDownloadButton && ( - { - window.print(); - }} - /> + <> + { + // set tabs to be visible + const tabs = document.getElementsByClassName('ui tab'); + Array.from(tabs).forEach((tab) => { + tab.style.display = 'block'; + }); + + dispatch(setIsPrint(true)); + // display loader + const printLoader = document.getElementById( + 'download-print-loader', + ); + printLoader.style.display = 'flex'; + + let timeoutValue = 1000; + // if we have plotlycharts increase timeout + setTimeout(() => { + const plotlyCharts = document.getElementsByClassName( + 'visualization-wrapper', + ); + if (plotlyCharts.length > 0) { + timeoutValue = timeoutValue + 1000; + } + }, timeoutValue); + + // scroll to iframes to make them be in the viewport + // use timeout to wait for load + setTimeout(() => { + const iframes = document.getElementsByTagName('iframe'); + if (iframes.length > 0) { + timeoutValue = timeoutValue + 2000; + Array.from(iframes).forEach((element, index) => { + setTimeout(() => { + element.scrollIntoView({ + behavior: 'instant', + block: 'nearest', + inline: 'center', + }); + }, timeoutValue); + timeoutValue = timeoutValue + 3000; + }); + timeoutValue = timeoutValue + 1000; + } + + setTimeout(() => { + window.scrollTo({ + top: 0, + }); + Array.from(tabs).forEach((tab) => { + tab.style.display = ''; + }); + printLoader.style.display = 'none'; + dispatch(setIsPrint(false)); + window.print(); + }, timeoutValue); + }, timeoutValue); + }} + /> +
+ +
Preparing download
+
+ )} {rssLinks?.map((rssLink, index) => ( <> @@ -253,6 +336,7 @@ export default compose( connect((state) => { return { types: state.types.types, + isPrint: state.isPrint, }; }), )(View); diff --git a/src/components/theme/Homepage/HomePageInverseView.test.jsx b/src/components/theme/Homepage/HomePageInverseView.test.jsx new file mode 100644 index 00000000..4200fba8 --- /dev/null +++ b/src/components/theme/Homepage/HomePageInverseView.test.jsx @@ -0,0 +1,16 @@ +import React from 'react'; +import { render } from '@testing-library/react'; +import HomePageInverseView from './HomePageInverseView'; +import '@testing-library/jest-dom/extend-expect'; + +describe('HomePageInverseView Component', () => { + it('renders without crashing', () => { + const mockContent = ( + +
Mock content
+ + ); + const { container } = render(); + expect(container).toBeTruthy(); + }); +}); diff --git a/src/components/theme/Homepage/HomePageView.test.jsx b/src/components/theme/Homepage/HomePageView.test.jsx new file mode 100644 index 00000000..e089081e --- /dev/null +++ b/src/components/theme/Homepage/HomePageView.test.jsx @@ -0,0 +1,16 @@ +import React from 'react'; +import { render } from '@testing-library/react'; +import HomePageView from './HomePageView'; +import '@testing-library/jest-dom/extend-expect'; + +describe('HomePageView Component', () => { + it('renders without crashing', () => { + const mockContent = ( + +
Mock content
+ + ); + const { container } = render(); + expect(container).toBeTruthy(); + }); +}); diff --git a/src/components/theme/Logo.test.jsx b/src/components/theme/Logo.test.jsx new file mode 100644 index 00000000..c6ac8ee9 --- /dev/null +++ b/src/components/theme/Logo.test.jsx @@ -0,0 +1,31 @@ +import React from 'react'; +import { render } from '@testing-library/react'; +import { Provider } from 'react-intl-redux'; +import configureStore from 'redux-mock-store'; +import { Router } from 'react-router-dom'; +import { createMemoryHistory } from 'history'; +import EEALogo from './Logo'; + +const mockStore = configureStore(); +let history = createMemoryHistory(); + +describe('EEALogo Component', () => { + it('renders without crashing', () => { + const store = mockStore({ + intl: { + locale: 'en', + messages: {}, + }, + }); + + const { container } = render( + + + + + , + ); + + expect(container).toBeTruthy(); + }); +}); diff --git a/src/components/theme/Widgets/TokenWidget.test.jsx b/src/components/theme/Widgets/TokenWidget.test.jsx new file mode 100644 index 00000000..d7e6ee54 --- /dev/null +++ b/src/components/theme/Widgets/TokenWidget.test.jsx @@ -0,0 +1,54 @@ +import React from 'react'; +import { render } from '@testing-library/react'; +import { Provider } from 'react-intl-redux'; +import configureStore from 'redux-mock-store'; +import { Router } from 'react-router-dom'; +import { createMemoryHistory } from 'history'; +import { TokenWidget } from './TokenWidget'; + +const mockStore = configureStore(); +let history = createMemoryHistory(); + +describe('TokenWidget Component', () => { + it('renders without crashing', () => { + const store = mockStore({ + intl: { + locale: 'en', + messages: {}, + }, + }); + + const { container } = render( + + + + + , + ); + + expect(container).toBeTruthy(); + }); + + it('renders without crashing, without value', () => { + const store = mockStore({ + intl: { + locale: 'en', + messages: {}, + }, + }); + + const { container } = render( + + + + + , + ); + + expect(container).toBeTruthy(); + }); +}); diff --git a/src/components/theme/Widgets/TopicsWidget.test.jsx b/src/components/theme/Widgets/TopicsWidget.test.jsx new file mode 100644 index 00000000..478de267 --- /dev/null +++ b/src/components/theme/Widgets/TopicsWidget.test.jsx @@ -0,0 +1,54 @@ +import React from 'react'; +import { render } from '@testing-library/react'; +import { Provider } from 'react-intl-redux'; +import configureStore from 'redux-mock-store'; +import { Router } from 'react-router-dom'; +import { createMemoryHistory } from 'history'; +import { TopicsWidget } from './TopicsWidget'; + +const mockStore = configureStore(); +let history = createMemoryHistory(); + +describe('TopicsWidget Component', () => { + it('renders without crashing, with value', () => { + const store = mockStore({ + intl: { + locale: 'en', + messages: {}, + }, + }); + + const { container } = render( + + + + + , + ); + + expect(container).toBeTruthy(); + }); + + it('renders without crashing, without value', () => { + const store = mockStore({ + intl: { + locale: 'en', + messages: {}, + }, + }); + + const { container } = render( + + + + + , + ); + + expect(container).toBeTruthy(); + }); +}); diff --git a/src/constants/ActionTypes.js b/src/constants/ActionTypes.js new file mode 100644 index 00000000..9d45401a --- /dev/null +++ b/src/constants/ActionTypes.js @@ -0,0 +1,6 @@ +/** + * Action types. + * @module constants/ActionTypes + */ + +export const SET_ISPRINT = 'SET_ISPRINT'; diff --git a/src/index.js b/src/index.js index 70f82432..dab7f3ac 100644 --- a/src/index.js +++ b/src/index.js @@ -27,7 +27,7 @@ import contentBoxSVG from './icons/content-box.svg'; import okMiddleware from './middleware/ok'; import voltoCustomMiddleware from './middleware/voltoCustom'; import installSlate from './slate'; - +import { print } from './reducers'; import { nanoid } from '@plone/volto-slate/utils'; import { v4 as uuid } from 'uuid'; @@ -534,6 +534,12 @@ const applyConfig = (config) => { }; } + // addonReducers + config.addonReducers = { + ...(config.addonReducers || {}), + print, + }; + // Breadcrumbs config.settings.apiExpanders.push({ match: '', diff --git a/src/index.test.js b/src/index.test.js index 92ac856c..1758381b 100644 --- a/src/index.test.js +++ b/src/index.test.js @@ -215,6 +215,11 @@ describe('applyConfig', () => { title: 'Horizontal', isDefault: false, }, + { + id: 'accordion', + title: 'Accordion responsive', + isDefault: false, + }, ], }, columnsBlock: {}, diff --git a/src/reducers/index.js b/src/reducers/index.js new file mode 100644 index 00000000..04527318 --- /dev/null +++ b/src/reducers/index.js @@ -0,0 +1 @@ +export print from './print'; diff --git a/src/reducers/print.js b/src/reducers/print.js new file mode 100644 index 00000000..c4a2a7d0 --- /dev/null +++ b/src/reducers/print.js @@ -0,0 +1,21 @@ +/** + * Print reducer. + * @module reducers/print + */ + +import { SET_ISPRINT } from '@eeacms/volto-eea-website-theme/constants/ActionTypes'; + +const initialState = { + isPrint: false, +}; + +export default function print(state = initialState, action) { + if (action.type === SET_ISPRINT) { + return { + ...state, + isPrint: action.payload, + }; + } else { + return state; + } +}