From f37e8c12f5e2cc930344cdcb3e85e71710b4c6db Mon Sep 17 00:00:00 2001 From: Suman Mondal <70449874suman@gmail.com> Date: Sat, 9 Sep 2023 21:34:49 +0530 Subject: [PATCH 01/12] Bugfix : Responsive Error in login page (#4309) Co-authored-by: Steve Piercy --- news/3250.bugfix | 1 + theme/themes/pastanaga/extras/login.less | 2 ++ 2 files changed, 3 insertions(+) create mode 100644 news/3250.bugfix diff --git a/news/3250.bugfix b/news/3250.bugfix new file mode 100644 index 0000000000..4f41d37c73 --- /dev/null +++ b/news/3250.bugfix @@ -0,0 +1 @@ +Fix for responsive error in the login page when the width of the screen decreases. @suman9893 \ No newline at end of file diff --git a/theme/themes/pastanaga/extras/login.less b/theme/themes/pastanaga/extras/login.less index 4eeceab041..95026a6db0 100644 --- a/theme/themes/pastanaga/extras/login.less +++ b/theme/themes/pastanaga/extras/login.less @@ -1,4 +1,6 @@ #page-login { + display: flex; + justify-content: center; .help { a { &:hover, From 55cd7570b7e2a15d4a92ee0824ec07fdfc0808e9 Mon Sep 17 00:00:00 2001 From: Suman Mondal <70449874suman@gmail.com> Date: Mon, 11 Sep 2023 08:49:46 +0530 Subject: [PATCH 02/12] fix : RecursiveWidget is incorrectly translated (#4513) Co-authored-by: Mikel Larreategi Co-authored-by: Fred van Dijk --- locales/ca/LC_MESSAGES/volto.po | 2 +- locales/de/LC_MESSAGES/volto.po | 2 +- locales/es/LC_MESSAGES/volto.po | 2 +- locales/fr/LC_MESSAGES/volto.po | 2 +- locales/nl/LC_MESSAGES/volto.po | 2 +- locales/pt/LC_MESSAGES/volto.po | 2 +- locales/ro/LC_MESSAGES/volto.po | 2 +- locales/zh_CN/LC_MESSAGES/volto.po | 2 +- news/4503.bugfix | 1 + 9 files changed, 9 insertions(+), 8 deletions(-) create mode 100644 news/4503.bugfix diff --git a/locales/ca/LC_MESSAGES/volto.po b/locales/ca/LC_MESSAGES/volto.po index b1af99cfea..d197af6a01 100644 --- a/locales/ca/LC_MESSAGES/volto.po +++ b/locales/ca/LC_MESSAGES/volto.po @@ -4645,7 +4645,7 @@ msgstr "a" #: components/manage/Widgets/RecurrenceWidget/Utils # defaultMessage: [month] [day], [year] msgid "rrule_dateFormat" -msgstr "[mes] [dia], [any]" +msgstr "[month] [day], [year]" #: components/manage/Widgets/RecurrenceWidget/Utils # defaultMessage: day diff --git a/locales/de/LC_MESSAGES/volto.po b/locales/de/LC_MESSAGES/volto.po index b2f5740b5f..f4db91efd4 100644 --- a/locales/de/LC_MESSAGES/volto.po +++ b/locales/de/LC_MESSAGES/volto.po @@ -4642,7 +4642,7 @@ msgstr "Regel AT" #: components/manage/Widgets/RecurrenceWidget/Utils # defaultMessage: [month] [day], [year] msgid "rrule_dateFormat" -msgstr "Regel Datumsformat" +msgstr "[day] [month] [year]" #: components/manage/Widgets/RecurrenceWidget/Utils # defaultMessage: day diff --git a/locales/es/LC_MESSAGES/volto.po b/locales/es/LC_MESSAGES/volto.po index 6af24edc03..b937a85540 100644 --- a/locales/es/LC_MESSAGES/volto.po +++ b/locales/es/LC_MESSAGES/volto.po @@ -4647,7 +4647,7 @@ msgstr "a las" #: components/manage/Widgets/RecurrenceWidget/Utils # defaultMessage: [month] [day], [year] msgid "rrule_dateFormat" -msgstr "formato de fecha" +msgstr "[day]/[month]/[year]" #: components/manage/Widgets/RecurrenceWidget/Utils # defaultMessage: day diff --git a/locales/fr/LC_MESSAGES/volto.po b/locales/fr/LC_MESSAGES/volto.po index d849d06ae5..dc469ad9ae 100644 --- a/locales/fr/LC_MESSAGES/volto.po +++ b/locales/fr/LC_MESSAGES/volto.po @@ -4653,7 +4653,7 @@ msgstr "à" #: components/manage/Widgets/RecurrenceWidget/Utils # defaultMessage: [month] [day], [year] msgid "rrule_dateFormat" -msgstr "[mois] [jour], [année]" +msgstr "[month] [day], [year]" #: components/manage/Widgets/RecurrenceWidget/Utils # defaultMessage: day diff --git a/locales/nl/LC_MESSAGES/volto.po b/locales/nl/LC_MESSAGES/volto.po index 790469f57b..6d031b47a7 100644 --- a/locales/nl/LC_MESSAGES/volto.po +++ b/locales/nl/LC_MESSAGES/volto.po @@ -4655,7 +4655,7 @@ msgstr "" #: components/manage/Widgets/RecurrenceWidget/Utils # defaultMessage: [month] [day], [year] msgid "rrule_dateFormat" -msgstr "" +msgstr "[month] [day], [year]" #: components/manage/Widgets/RecurrenceWidget/Utils # defaultMessage: day diff --git a/locales/pt/LC_MESSAGES/volto.po b/locales/pt/LC_MESSAGES/volto.po index 03c909fa0d..743fe4ecef 100644 --- a/locales/pt/LC_MESSAGES/volto.po +++ b/locales/pt/LC_MESSAGES/volto.po @@ -4644,7 +4644,7 @@ msgstr "" #: components/manage/Widgets/RecurrenceWidget/Utils # defaultMessage: [month] [day], [year] msgid "rrule_dateFormat" -msgstr "" +msgstr "[day] de [month] de [year]" #: components/manage/Widgets/RecurrenceWidget/Utils # defaultMessage: day diff --git a/locales/ro/LC_MESSAGES/volto.po b/locales/ro/LC_MESSAGES/volto.po index eebc7a7058..cbf003e233 100644 --- a/locales/ro/LC_MESSAGES/volto.po +++ b/locales/ro/LC_MESSAGES/volto.po @@ -4636,7 +4636,7 @@ msgstr "La" #: components/manage/Widgets/RecurrenceWidget/Utils # defaultMessage: [month] [day], [year] msgid "rrule_dateFormat" -msgstr "" +msgstr "[year]-[month]-[day]" #: components/manage/Widgets/RecurrenceWidget/Utils # defaultMessage: day diff --git a/locales/zh_CN/LC_MESSAGES/volto.po b/locales/zh_CN/LC_MESSAGES/volto.po index e100c4dd85..ed63fbdba1 100644 --- a/locales/zh_CN/LC_MESSAGES/volto.po +++ b/locales/zh_CN/LC_MESSAGES/volto.po @@ -4642,7 +4642,7 @@ msgstr "" #: components/manage/Widgets/RecurrenceWidget/Utils # defaultMessage: [month] [day], [year] msgid "rrule_dateFormat" -msgstr "" +msgstr "[year]-[month]-[day]" #: components/manage/Widgets/RecurrenceWidget/Utils # defaultMessage: day diff --git a/news/4503.bugfix b/news/4503.bugfix new file mode 100644 index 0000000000..9e78d10a74 --- /dev/null +++ b/news/4503.bugfix @@ -0,0 +1 @@ +fix : RecursiveWidget is incorrectly translated. @suman9893 \ No newline at end of file From 388087ef21b5fd37c9b97440e2d9c5a58aa2e4e6 Mon Sep 17 00:00:00 2001 From: Ion Lizarazu Date: Mon, 11 Sep 2023 13:41:00 +0200 Subject: [PATCH 03/12] fix search block search results number (#5171) --- cypress/tests/core/blocks/blocks-search.js | 53 +++++++++++++++++++ news/5171.bugfix | 1 + news/5171.feature | 1 + .../Blocks/Listing/withQuerystringResults.jsx | 2 +- 4 files changed, 56 insertions(+), 1 deletion(-) create mode 100644 news/5171.bugfix create mode 100644 news/5171.feature diff --git a/cypress/tests/core/blocks/blocks-search.js b/cypress/tests/core/blocks/blocks-search.js index 055d9b7948..d9157567d7 100644 --- a/cypress/tests/core/blocks/blocks-search.js +++ b/cypress/tests/core/blocks/blocks-search.js @@ -1,4 +1,5 @@ describe('Search Block Tests', () => { + var results_number = 3; beforeEach(() => { cy.intercept('GET', `/**/*?expand*`).as('content'); cy.intercept('GET', '/**/Document').as('schema'); @@ -91,6 +92,12 @@ describe('Search Block Tests', () => { cy.wait(500); + // test search results number + cy.get('.search-details').should( + 'contain', + `Search results: ${results_number}`, + ); + // test if type facet works cy.get('.block.search .facets > .facet .entries > .entry label') .contains('Event') @@ -158,6 +165,12 @@ describe('Search Block Tests', () => { cy.get('#toolbar-save > .icon').click(); cy.wait(500); + + // test search results number + cy.get('.search-details').should( + 'contain', + `Search results: ${results_number}`, + ); }); it('Search block - test live searchbox', () => { @@ -201,6 +214,13 @@ describe('Search Block Tests', () => { cy.wait('@content'); cy.wait(500); + + // test search results number + cy.get('.search-details').should( + 'contain', + `Search results: ${results_number}`, + ); + // test searching for Event cy.get('.search-wrapper .search-input input').focus().type('Event'); cy.get('#page-document .listing-item:first-of-type a').should( @@ -237,6 +257,12 @@ describe('Search Block Tests', () => { ); cy.url().should('not.contain', '%22SearchableText%22'); + // test search results number + cy.get('.search-details').should( + 'contain', + `Search results: ${results_number}`, + ); + // test searching for Event cy.get('.search-wrapper .search-input input').focus().type('Event'); cy.get('#page-document .listing-item:first-of-type a').should( @@ -253,6 +279,9 @@ describe('Search Block Tests', () => { '%7B%22i%22%3A%22SearchableText%22%2C%22o%22%3A%22paqo.string.contains%22%2C%22v%22%3A%22Event%22%7D', ); + // test search results number + cy.get('.search-details').should('contain', 'Search results: 1'); + // test removing one char cy.get('.search-wrapper .search-input input').focus().type('{backspace}'); cy.get('.search-results-count-sort .search-details em') @@ -319,6 +348,12 @@ describe('Search Block Tests', () => { cy.wait(500); + // test search results number + cy.get('.search-details').should( + 'contain', + `Search results: ${results_number}`, + ); + // test searching for Event cy.get('.search-wrapper .search-input input').focus().type('Event'); cy.get('.search-wrapper > .ui.button').click(); @@ -337,6 +372,9 @@ describe('Search Block Tests', () => { '%7B%22i%22%3A%22SearchableText%22%2C%22o%22%3A%22paqo.string.contains%22%2C%22v%22%3A%22Event%22%7D', ); + // test search results number + cy.get('.search-details').should('contain', 'Search results: 1'); + // test removing one char cy.get('.search-wrapper .search-input input').focus().type('{backspace}'); cy.get('.search-wrapper > .ui.button').click(); @@ -359,6 +397,12 @@ describe('Search Block Tests', () => { ); cy.url().should('not.contain', '%22SearchableText%22'); + // test search results number + cy.get('.search-details').should( + 'contain', + `Search results: ${results_number}`, + ); + // test searching for Event cy.get('.search-wrapper .search-input input').focus().type('Event'); cy.get('.search-wrapper > .ui.button').click(); @@ -376,6 +420,9 @@ describe('Search Block Tests', () => { '%7B%22i%22%3A%22SearchableText%22%2C%22o%22%3A%22paqo.string.contains%22%2C%22v%22%3A%22Event%22%7D', ); + // test search results number + cy.get('.search-details').should('contain', 'Search results: 1'); + // test removing one char cy.get('.search-wrapper .search-input input').focus().type('{backspace}'); cy.get('.search-wrapper > .ui.button').click(); @@ -397,5 +444,11 @@ describe('Search Block Tests', () => { 'Searched for:', ); cy.url().should('not.contain', '%22SearchableText%22'); + + // test search results number + cy.get('.search-details').should( + 'contain', + `Search results: ${results_number}`, + ); }); }); diff --git a/news/5171.bugfix b/news/5171.bugfix new file mode 100644 index 0000000000..545a94c8ea --- /dev/null +++ b/news/5171.bugfix @@ -0,0 +1 @@ +Fix search block search results number @ionlizarazu \ No newline at end of file diff --git a/news/5171.feature b/news/5171.feature new file mode 100644 index 0000000000..0caad91658 --- /dev/null +++ b/news/5171.feature @@ -0,0 +1 @@ +Cypress test to test if 'Search results: number' text is present @ionlizarazu \ No newline at end of file diff --git a/src/components/manage/Blocks/Listing/withQuerystringResults.jsx b/src/components/manage/Blocks/Listing/withQuerystringResults.jsx index 8c4fae2c33..6dd025769b 100644 --- a/src/components/manage/Blocks/Listing/withQuerystringResults.jsx +++ b/src/components/manage/Blocks/Listing/withQuerystringResults.jsx @@ -23,7 +23,7 @@ export default function withQuerystringResults(WrappedComponent) { } = props; const { settings } = config; const querystring = data.querystring || data; // For backwards compat with data saved before Blocks schema. Note, this is also how the Search block passes data to ListingBody - const subrequestID = content?.UID + '-' + id; + const subrequestID = content?.UID ? `${content?.UID}-${id}` : id; const { b_size = settings.defaultPageSize } = querystring; // batchsize // save the path so it won't trigger dispatch on eager router location change From e9cce0deb3043bf6b4473fb2d6146f18356111da Mon Sep 17 00:00:00 2001 From: Tisha Soumya Date: Mon, 11 Sep 2023 17:20:50 +0530 Subject: [PATCH 04/12] view cypress test (#5149) --- cypress/tests/core/basic/view.js | 55 ++++++++++++++++++++++++++++++++ news/5149.feature | 1 + 2 files changed, 56 insertions(+) create mode 100644 cypress/tests/core/basic/view.js create mode 100644 news/5149.feature diff --git a/cypress/tests/core/basic/view.js b/cypress/tests/core/basic/view.js new file mode 100644 index 0000000000..00cc061e25 --- /dev/null +++ b/cypress/tests/core/basic/view.js @@ -0,0 +1,55 @@ +describe('Add Content Tests', () => { + beforeEach(() => { + cy.intercept('GET', `/**/*?expand*`).as('content'); + // give a logged in editor and the site root + cy.autologin(); + cy.visit('/'); + cy.wait('@content'); + }); + + it('As editor I can change the view to Listing View', function () { + + cy.visit('/events'); + cy.get('#toolbar-more').click(); + cy.findByText('Listing view').click(); + cy.findByText('Album view').click(); + cy.visit('/events'); + cy.wait('@content'); + cy.wait(2000); + cy.get('main').contains('Event').should('be.visible'); + }); + + it('As editor I can change the view to Summary View', function () { + + cy.visit('/events'); + cy.get('#toolbar-more').click(); + cy.findByText('Listing view').click(); + cy.findByText('Summary view').click(); + cy.visit('/events'); + cy.wait('@content'); + cy.wait(2000); + cy.get('main').contains('Event').should('be.visible'); + }); + it('As editor I can change the view to Tabular View', function () { + + cy.visit('/events'); + cy.get('#toolbar-more').click(); + cy.findByText('Listing view').click(); + cy.findByText('Tabular view').click(); + cy.visit('/events'); + cy.wait('@content'); + cy.wait(2000); + cy.get('main').contains('Event').should('be.visible'); + }); + it('As editor I can change the view to Album View', function () { + + cy.visit('/events'); + cy.get('#toolbar-more').click(); + cy.findByText('Listing view').click(); + cy.visit('/events'); + cy.wait('@content'); + cy.wait(2000); + cy.get('main').contains('Event').should('be.visible'); + }); + }); + \ No newline at end of file diff --git a/news/5149.feature b/news/5149.feature new file mode 100644 index 0000000000..8313f839f9 --- /dev/null +++ b/news/5149.feature @@ -0,0 +1 @@ +Views cypress test -@Tishasoumya \ No newline at end of file From d08f92affd5aba2a362a31f63f04fb412cd1a153 Mon Sep 17 00:00:00 2001 From: dobri1408 <50819975+dobri1408@users.noreply.github.com> Date: Mon, 11 Sep 2023 14:52:36 +0300 Subject: [PATCH 05/12] (feat):Update toc block entries (#5146) Co-authored-by: Tiberiu Ichim --- news/5146.feature | 1 + src/components/manage/Blocks/ToC/View.jsx | 88 +++++++++++++++++++---- 2 files changed, 76 insertions(+), 13 deletions(-) create mode 100644 news/5146.feature diff --git a/news/5146.feature b/news/5146.feature new file mode 100644 index 0000000000..105a9b9e0c --- /dev/null +++ b/news/5146.feature @@ -0,0 +1 @@ +(feat): Update toc block entries @dobri1408 diff --git a/src/components/manage/Blocks/ToC/View.jsx b/src/components/manage/Blocks/ToC/View.jsx index a0cd337f53..2ba31d12a2 100644 --- a/src/components/manage/Blocks/ToC/View.jsx +++ b/src/components/manage/Blocks/ToC/View.jsx @@ -16,16 +16,79 @@ import { getBlocksLayoutFieldname, } from '@plone/volto/helpers'; +export const getBlocksTocEntries = (properties, tocData) => { + const blocksFieldName = getBlocksFieldname(properties); + const blocksLayoutFieldname = getBlocksLayoutFieldname(properties); + + const blocks = properties[blocksFieldName]; + const blocks_layout = properties[blocksLayoutFieldname]; + + const levels = + tocData.levels?.length > 0 + ? tocData.levels.map((l) => parseInt(l.slice(1))) + : [1, 2, 3, 4, 5, 6]; + let rootLevel = Infinity; + let blocksFormEntries = []; + let tocEntries = {}; + let tocEntriesLayout = []; + + blocks_layout.items.forEach((id) => { + const block = blocks[id]; + const blockConfig = config.blocks.blocksConfig[block['@type']]; + + if (!block || !blockConfig) { + return null; + } + if (!blockConfig.tocEntries && !blockConfig.tocEntry) { + return null; + } + + const blockTocEntry = blockConfig.tocEntry?.(block, tocData); + + const blockTocEntries = [ + ...(blockConfig.tocEntries?.(block, tocData) || + (blockTocEntry ? [blockTocEntry] : [])), + ]; + + blocksFormEntries = [...blocksFormEntries, ...blockTocEntries]; + + blockTocEntries.forEach((entry, index) => { + const i = `${id}-${index}`; + const level = entry[0]; + const title = entry[1]; + const items = []; + if (!level || !levels.includes(level)) return; + tocEntriesLayout.push(i); + tocEntries[i] = { + level, + title: title || block.plaintext, + items, + id: i, + }; + if (level < rootLevel) { + rootLevel = level; + } + }); + }); + + return { + rootLevel, + blocksFormEntries, + tocEntries, + tocEntriesLayout, + }; +}; + /** * View toc block class. * @class View * @extends Component */ const View = (props) => { - const { properties, data } = props; + const { data } = props; const { variation } = props; - const blocksFieldname = getBlocksFieldname(properties); - const blocksLayoutFieldname = getBlocksLayoutFieldname(properties); + const metadata = props.metadata || props.properties; + const blocksFieldname = getBlocksFieldname(metadata); const levels = React.useMemo( () => data.levels?.length > 0 @@ -34,14 +97,15 @@ const View = (props) => { [data], ); const tocEntries = React.useMemo(() => { - let rootLevel = Infinity; let entries = []; let prevEntry = {}; - let tocEntries = {}; - let tocEntriesLayout = []; + const { rootLevel, tocEntries, tocEntriesLayout } = getBlocksTocEntries( + metadata, + data, + ); - properties[blocksLayoutFieldname].items.forEach((id) => { - const block = properties[blocksFieldname][id]; + tocEntriesLayout.forEach((id) => { + const block = metadata[blocksFieldname][id]; if (typeof block === 'undefined') { return null; } @@ -50,6 +114,7 @@ const View = (props) => { block, data, ); + if (entry) { const level = entry[0]; const title = entry[1]; @@ -64,9 +129,6 @@ const View = (props) => { override_toc: block.override_toc, plaintext: block.plaintext, }; - if (level < rootLevel) { - rootLevel = level; - } } }); @@ -98,7 +160,7 @@ const View = (props) => { }); return entries; - }, [data, levels, properties, blocksFieldname, blocksLayoutFieldname]); + }, [data, levels, metadata, blocksFieldname]); const Renderer = variation?.view; return ( @@ -108,7 +170,7 @@ const View = (props) => { )} {Renderer ? ( - + ) : (
View extension not found
)} From bed71f5e2ba768293ee6724422c5f2db5c925900 Mon Sep 17 00:00:00 2001 From: Tisha Soumya Date: Mon, 11 Sep 2023 19:55:11 +0530 Subject: [PATCH 06/12] Refactor Navigation (#4876) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Nilesh Co-authored-by: Víctor Fernández de Alba --- news/4076.feature | 1 + .../theme/Navigation/Navigation.jsx | 257 ++++++------------ 2 files changed, 87 insertions(+), 171 deletions(-) create mode 100644 news/4076.feature diff --git a/news/4076.feature b/news/4076.feature new file mode 100644 index 0000000000..c88e5b0c7b --- /dev/null +++ b/news/4076.feature @@ -0,0 +1 @@ +Refactor Navigation -@Tishasoumya-02 diff --git a/src/components/theme/Navigation/Navigation.jsx b/src/components/theme/Navigation/Navigation.jsx index 1856eb6189..7650f87e88 100644 --- a/src/components/theme/Navigation/Navigation.jsx +++ b/src/components/theme/Navigation/Navigation.jsx @@ -1,14 +1,9 @@ -/** - * Navigation components. - * @module components/theme/Navigation/Navigation - */ - -import React, { Component } from 'react'; +import { useEffect, useState } from 'react'; import PropTypes from 'prop-types'; -import { connect } from 'react-redux'; -import { compose } from 'redux'; -import { defineMessages, injectIntl } from 'react-intl'; +import { useDispatch, useSelector, shallowEqual } from 'react-redux'; +import { defineMessages, useIntl } from 'react-intl'; import { Menu } from 'semantic-ui-react'; + import cx from 'classnames'; import { BodyClass, getBaseUrl, hasApiExpander } from '@plone/volto/helpers'; import config from '@plone/volto/registry'; @@ -27,176 +22,96 @@ const messages = defineMessages({ }, }); -/** - * Navigation container class. - * @class Navigation - * @extends Component - */ -class Navigation extends Component { - /** - * Property types. - * @property {Object} propTypes Property types. - * @static - */ - static propTypes = { - getNavigation: PropTypes.func.isRequired, - pathname: PropTypes.string.isRequired, - items: PropTypes.arrayOf( - PropTypes.shape({ - title: PropTypes.string, - url: PropTypes.string, - }), - ).isRequired, - lang: PropTypes.string.isRequired, - }; - - static defaultProps = { - token: null, - }; - - /** - * Constructor - * @method constructor - * @param {Object} props Component properties - * @constructs Navigation - */ - constructor(props) { - super(props); - this.toggleMobileMenu = this.toggleMobileMenu.bind(this); - this.closeMobileMenu = this.closeMobileMenu.bind(this); - this.state = { - isMobileMenuOpen: false, - }; - } +const Navigation = (props) => { + const intl = useIntl(); + const dispatch = useDispatch(); + const { pathname, type } = props; + const [isMobileMenuOpen, setisMobileMenuOpen] = useState(false); + const token = useSelector((state) => state.userSession.token, shallowEqual); + const items = useSelector((state) => state.navigation.items, shallowEqual); + const lang = useSelector((state) => state.intl.locale); - componentDidMount() { + useEffect(() => { const { settings } = config; - if (!hasApiExpander('navigation', getBaseUrl(this.props.pathname))) { - this.props.getNavigation( - getBaseUrl(this.props.pathname), - settings.navDepth, - ); + if (!hasApiExpander('navigation', getBaseUrl(pathname))) { + dispatch(getNavigation(getBaseUrl(pathname), settings.navDepth)); } - } + }, [pathname, token, dispatch]); - /** - * Component will receive props - * @method componentWillReceiveProps - * @param {Object} nextProps Next properties - * @returns {undefined} - */ - UNSAFE_componentWillReceiveProps(nextProps) { - const { settings } = config; - if ( - nextProps.pathname !== this.props.pathname || - nextProps.token !== this.props.token - ) { - if (!hasApiExpander('navigation', getBaseUrl(this.props.pathname))) { - this.props.getNavigation( - getBaseUrl(nextProps.pathname), - settings.navDepth, - ); - } - } - } - - /** - * Toggle mobile menu's open state - * @method toggleMobileMenu - * @returns {undefined} - */ - toggleMobileMenu() { - this.setState({ isMobileMenuOpen: !this.state.isMobileMenuOpen }); - } + const toggleMobileMenu = () => { + setisMobileMenuOpen(!isMobileMenuOpen); + }; - /** - * Close mobile menu - * @method closeMobileMenu - * @returns {undefined} - */ - closeMobileMenu() { - if (!this.state.isMobileMenuOpen) { + const closeMobileMenu = () => { + if (!isMobileMenuOpen) { return; } - this.setState({ isMobileMenuOpen: false }); - } + setisMobileMenuOpen(false); + }; - /** - * Render method. - * @method render - * @returns {string} Markup for the component. - */ - render() { - return ( - - ); - } -} + + + + ); +}; + +Navigation.propTypes = { + pathname: PropTypes.string.isRequired, +}; -export default compose( - injectIntl, - connect( - (state) => ({ - token: state.userSession.token, - items: state.navigation.items, - lang: state.intl.locale, - }), - { getNavigation }, - ), -)(Navigation); +export default Navigation; From 2e547d19b0a87d00e90af86ba7713b27d2e87686 Mon Sep 17 00:00:00 2001 From: Tisha Soumya Date: Mon, 11 Sep 2023 19:57:00 +0530 Subject: [PATCH 07/12] Refactor Messages (#4926) Co-authored-by: Nilesh --- news/4926.feature | 1 + src/components/manage/Messages/Messages.jsx | 131 +++++------------- .../manage/Messages/Messages.test.jsx | 1 - 3 files changed, 33 insertions(+), 100 deletions(-) create mode 100644 news/4926.feature diff --git a/news/4926.feature b/news/4926.feature new file mode 100644 index 0000000000..b08a69246b --- /dev/null +++ b/news/4926.feature @@ -0,0 +1 @@ +Messages Component Refactor - @Tishasoumya-02 \ No newline at end of file diff --git a/src/components/manage/Messages/Messages.jsx b/src/components/manage/Messages/Messages.jsx index 17818d5be9..9bc536b93b 100644 --- a/src/components/manage/Messages/Messages.jsx +++ b/src/components/manage/Messages/Messages.jsx @@ -1,107 +1,40 @@ -/** - * Messages component. - * @module components/manage/Messages/Messages - */ - -import React, { Component } from 'react'; -import PropTypes from 'prop-types'; -import { connect } from 'react-redux'; +import { useDispatch, useSelector, shallowEqual } from 'react-redux'; import { Message, Container } from 'semantic-ui-react'; import { map } from 'lodash'; import { removeMessage } from '@plone/volto/actions'; -/** - * Messages container class. - * @class Messages - * @extends Component - */ -class Messages extends Component { - /** - * Property types. - * @property {Object} propTypes Property types. - * @static - */ - static propTypes = { - removeMessage: PropTypes.func.isRequired, - messages: PropTypes.arrayOf( - PropTypes.shape({ - title: PropTypes.string, - body: PropTypes.string, - level: PropTypes.string, - }), - ).isRequired, - }; - - /** - * Constructor - * @method constructor - * @param {Object} props Component properties - * @constructs Messages - */ - constructor(props) { - super(props); - this.onDismiss = this.onDismiss.bind(this); - } +const Messages = () => { + const dispatch = useDispatch(); - // /** - // * Component will receive props - // * @method componentWillReceiveProps - // * @param {Object} nextProps Next properties - // * @returns {undefined} - // */ - // componentWillReceiveProps(nextProps) { - // if (nextProps.messages.length > this.props.messages.length) { - // window.setTimeout(() => { - // if (this.props.messages.length > 0) { - // this.props.removeMessage(-1); - // } - // }, 6000); - // } - // } + const messages = useSelector( + (state) => state.messages.messages, + shallowEqual, + ); - /** - * On dismiss - * @method onDismiss - * @param {Object} event Event object - * @param {number} value Index of message - * @returns {undefined} - */ - onDismiss(event, { value }) { - this.props.removeMessage(value); - } - - /** - * Render method. - * @method render - * @returns {string} Markup for the component. - */ - render() { - return ( - this.props.messages && ( - - {map(this.props.messages, (message, index) => ( - - ))} - - ) - ); - } -} + const onDismiss = (event, { value }) => { + dispatch(removeMessage(value)); + }; -export default connect( - (state) => ({ - messages: state.messages.messages, - }), - { removeMessage }, -)(Messages); + return ( + messages && ( + + {map(messages, (message, index) => ( + + ))} + + ) + ); +}; + +export default Messages; diff --git a/src/components/manage/Messages/Messages.test.jsx b/src/components/manage/Messages/Messages.test.jsx index 6f0ac40a09..1037771926 100644 --- a/src/components/manage/Messages/Messages.test.jsx +++ b/src/components/manage/Messages/Messages.test.jsx @@ -1,4 +1,3 @@ -import React from 'react'; import renderer from 'react-test-renderer'; import configureStore from 'redux-mock-store'; import { Provider } from 'react-redux'; From 244daf8affb599f24bae545c38980c3c1d2400ad Mon Sep 17 00:00:00 2001 From: Tisha Soumya Date: Mon, 11 Sep 2023 21:28:40 +0530 Subject: [PATCH 08/12] Refactor Login (#4933) Co-authored-by: nileshgulia1 Co-authored-by: Victor Fernandez de Alba --- news/4933.feature | 1 + src/actions/index.js | 1 + src/actions/userSession/userSession.js | 18 +- src/components/theme/Login/Login.jsx | 400 +++++++++-------------- src/components/theme/Logout/Logout.jsx | 2 +- src/constants/ActionTypes.js | 1 + src/reducers/userSession/userSession.js | 16 +- theme/themes/pastanaga/extras/login.less | 1 + 8 files changed, 196 insertions(+), 244 deletions(-) create mode 100644 news/4933.feature diff --git a/news/4933.feature b/news/4933.feature new file mode 100644 index 0000000000..4eed79a508 --- /dev/null +++ b/news/4933.feature @@ -0,0 +1 @@ +Refactor Login -@Tishasoumya-02 diff --git a/src/actions/index.js b/src/actions/index.js index c556018d21..289ffd34b9 100644 --- a/src/actions/index.js +++ b/src/actions/index.js @@ -138,6 +138,7 @@ export { login, loginRenew, logout, + resetLoginRequest, } from '@plone/volto/actions/userSession/userSession'; export { getVocabulary, diff --git a/src/actions/userSession/userSession.js b/src/actions/userSession/userSession.js index 8ecfbe1589..7ecada53b0 100644 --- a/src/actions/userSession/userSession.js +++ b/src/actions/userSession/userSession.js @@ -3,7 +3,12 @@ * @module actions/search/search */ -import { LOGIN, LOGIN_RENEW, LOGOUT } from '@plone/volto/constants/ActionTypes'; +import { + LOGIN, + LOGIN_RENEW, + LOGOUT, + RESET_LOGIN_REQUEST, +} from '@plone/volto/constants/ActionTypes'; /** * Login function. @@ -52,3 +57,14 @@ export function logout() { }, }; } + +/** + * Reset login request data function + * @function resetLoginRequest + * @returns {Object} Get content action + */ +export function resetLoginRequest() { + return { + type: RESET_LOGIN_REQUEST, + }; +} diff --git a/src/components/theme/Login/Login.jsx b/src/components/theme/Login/Login.jsx index 02649a92df..83ed6ca750 100644 --- a/src/components/theme/Login/Login.jsx +++ b/src/components/theme/Login/Login.jsx @@ -1,14 +1,6 @@ -/** - * Login container. - * @module components/theme/Login/Login - */ - -import React, { Component } from 'react'; -import PropTypes from 'prop-types'; -import { Helmet } from '@plone/volto/helpers'; -import { connect } from 'react-redux'; -import { compose } from 'redux'; -import { Link } from 'react-router-dom'; +import { useEffect } from 'react'; +import { useDispatch, useSelector, shallowEqual } from 'react-redux'; +import { Link, useHistory, useLocation } from 'react-router-dom'; import { Container, Button, @@ -17,20 +9,18 @@ import { Segment, Grid, } from 'semantic-ui-react'; -import { FormattedMessage, defineMessages, injectIntl } from 'react-intl'; +import { FormattedMessage, defineMessages, useIntl } from 'react-intl'; import qs from 'query-string'; -import { withRouter } from 'react-router-dom'; +import { Helmet } from '@plone/volto/helpers'; +import config from '@plone/volto/registry'; import { Icon } from '@plone/volto/components'; -import { login } from '@plone/volto/actions'; +import { login, resetLoginRequest } from '@plone/volto/actions'; import { toast } from 'react-toastify'; import { Toast } from '@plone/volto/components'; - import aheadSVG from '@plone/volto/icons/ahead.svg'; import clearSVG from '@plone/volto/icons/clear.svg'; -import config from '@plone/volto/registry'; - const messages = defineMessages({ login: { id: 'Log in', @@ -76,59 +66,21 @@ const messages = defineMessages({ }, }); -/** - * Login class. - * @class Login - * @extends Component - */ -class Login extends Component { - /** - * Property types. - * @property {Object} propTypes Property types. - * @static - */ - static propTypes = { - login: PropTypes.func.isRequired, - error: PropTypes.shape({ - message: PropTypes.string, - }), - loading: PropTypes.bool, - token: PropTypes.string, // eslint-disable-line react/no-unused-prop-types - returnUrl: PropTypes.string, - }; - - /** - * Default properties. - * @property {Object} defaultProps Default properties. - * @static - */ - static defaultProps = { - error: null, - loading: null, - token: null, - returnUrl: null, - }; - - /** - * Constructor - * @method constructor - * @param {Object} props Component properties - * @constructs WysiwygEditor - */ - constructor(props) { - super(props); - this.onLogin = this.onLogin.bind(this); - } - - /** - * Component will receive props - * @method componentWillReceiveProps - * @param {Object} nextProps Next properties - * @returns {undefined} - */ - UNSAFE_componentWillReceiveProps(nextProps) { - if (nextProps.token) { - this.props.history.push(this.props.returnUrl || '/'); +const Login = (props) => { + const intl = useIntl(); + const history = useHistory(); + const location = useLocation(); + const dispatch = useDispatch(); + const token = useSelector((state) => state.userSession.token, shallowEqual); + const error = useSelector((state) => state.userSession.login.error); + const loading = useSelector((state) => state.userSession.login.loading); + const returnUrl = + qs.parse(props.location.search ?? location.search).return_url || + location.pathname.replace(/\/login\/?$/, '').replace(/\/logout\/?$/, '') || + '/'; + useEffect(() => { + if (token && !props.isLogout) { + history.push(returnUrl || '/'); if (toast.isActive('loggedOut')) { toast.dismiss('loggedOut'); } @@ -136,7 +88,7 @@ class Login extends Component { toast.dismiss('loginFailed'); } } - if (nextProps.error) { + if (error) { if (toast.isActive('loggedOut')) { toast.dismiss('loggedOut'); } @@ -144,189 +96,155 @@ class Login extends Component { toast.error( , { autoClose: false, toastId: 'loginFailed' }, ); } } - } - - componentWillUnmount() { - if (toast.isActive('loginFailed')) { - toast.dismiss('loginFailed'); - } - } + return () => { + if (toast.isActive('loginFailed')) { + toast.dismiss('loginFailed'); + dispatch(resetLoginRequest()); + } + }; + }, [dispatch, token, error, intl, history, returnUrl, props.isLogout]); - /** - * On login handler - * @method onLogin - * @param {Object} event Event object. - * @returns {undefined} - */ - onLogin(event) { - this.props.login( - document.getElementsByName('login')[0].value, - document.getElementsByName('password')[0].value, + const onLogin = (event) => { + dispatch( + login( + document.getElementsByName('login')[0].value, + document.getElementsByName('password')[0].value, + ), ); event.preventDefault(); - } + }; - /** - * Render method. - * @method render - * @returns {string} Markup for the component. - */ - render() { - return ( -
- - -
- - - - - - - - - - - - -
- -
-
- - {/* eslint-disable jsx-a11y/no-autofocus */} - - -
-
-
- - - - -
- -
-
- - - -
-
-
- - - - {config.settings.showSelfRegistration && ( - -

- - {this.props.intl.formatMessage(messages.register)} - -

-
- )} + return ( +
+ + + + + + + + + + + + + + + +
+ +
+
+ + {/* eslint-disable jsx-a11y/no-autofocus */} + + +
+
+
+ + + + +
+ +
+
+ + + +
+
+
+ + + + {config.settings.showSelfRegistration && (

- - {this.props.intl.formatMessage( - messages.forgotPassword, - )} + + {intl.formatMessage(messages.register)}

-
-
-
-
- - + )} + +

+ + {intl.formatMessage(messages.forgotPassword)} + +

+
+ + + +
+ + - - -
- -
-
- ); - } -} + +
+
+ +
+
+ ); +}; -export default compose( - withRouter, - injectIntl, - connect( - (state, props) => ({ - error: state.userSession.login.error, - loading: state.userSession.login.loading, - token: state.userSession.token, - returnUrl: - qs.parse(props.location.search).return_url || - props.location.pathname - .replace(/\/login\/?$/, '') - .replace(/\/logout\/?$/, '') || - '/', - }), - { login }, - ), -)(Login); +export default Login; diff --git a/src/components/theme/Logout/Logout.jsx b/src/components/theme/Logout/Logout.jsx index 812d15ca75..70ad7bf472 100644 --- a/src/components/theme/Logout/Logout.jsx +++ b/src/components/theme/Logout/Logout.jsx @@ -55,7 +55,7 @@ const Logout = ({ location }) => { } }, [history, returnUrl, intl, token]); - return ; + return ; }; export default Logout; diff --git a/src/constants/ActionTypes.js b/src/constants/ActionTypes.js index bdd9b64c34..426569f3a2 100644 --- a/src/constants/ActionTypes.js +++ b/src/constants/ActionTypes.js @@ -138,3 +138,4 @@ export const REMOVE_ALIASES = 'REMOVE_ALIASES'; export const GET_USERSCHEMA = 'GET_USERSCHEMA'; export const GET_UPGRADE = 'GET_UPGRADE'; export const POST_UPGRADE = 'POST_UPGRADE'; +export const RESET_LOGIN_REQUEST = 'RESET_LOGIN_REQUEST'; diff --git a/src/reducers/userSession/userSession.js b/src/reducers/userSession/userSession.js index f750c2d38d..d515576d0b 100644 --- a/src/reducers/userSession/userSession.js +++ b/src/reducers/userSession/userSession.js @@ -3,7 +3,12 @@ * @module reducers/userSession/userSession */ -import { LOGIN, LOGIN_RENEW, LOGOUT } from '@plone/volto/constants/ActionTypes'; +import { + LOGIN, + LOGIN_RENEW, + LOGOUT, + RESET_LOGIN_REQUEST, +} from '@plone/volto/constants/ActionTypes'; const initialState = { token: null, @@ -61,6 +66,15 @@ export default function userSession(state = initialState, action = {}) { ...state, token: null, }; + case `${RESET_LOGIN_REQUEST}`: + return { + ...state, + login: { + loading: false, + loaded: false, + error: null, + }, + }; default: return state; } diff --git a/theme/themes/pastanaga/extras/login.less b/theme/themes/pastanaga/extras/login.less index 95026a6db0..dcb7687dd4 100644 --- a/theme/themes/pastanaga/extras/login.less +++ b/theme/themes/pastanaga/extras/login.less @@ -1,6 +1,7 @@ #page-login { display: flex; justify-content: center; + .help { a { &:hover, From adda341fe973651dc3a1dd2e4220ffbe90ee50a4 Mon Sep 17 00:00:00 2001 From: Alok Kumar Date: Tue, 12 Sep 2023 12:41:20 +0530 Subject: [PATCH 09/12] Add external className to UniversalLink for external link. (#5110) Co-authored-by: Victor Fernandez de Alba --- news/5109.feature | 1 + .../__snapshots__/LeadImageSidebar.test.jsx.snap | 4 ++-- .../manage/LinksToItem/LinksToItem.test.jsx | 5 ++++- .../__snapshots__/LinksToItem.test.jsx.snap | 12 ++++++------ .../manage/UniversalLink/UniversalLink.jsx | 10 ++++------ .../__snapshots__/UniversalLink.test.jsx.snap | 10 +++++----- .../Image/__snapshots__/Image.test.jsx.snap | 16 ++++++++-------- .../Widgets/__snapshots__/UrlWidget.test.js.snap | 4 ++-- test-setup-config.js | 1 + 9 files changed, 33 insertions(+), 30 deletions(-) create mode 100644 news/5109.feature diff --git a/news/5109.feature b/news/5109.feature new file mode 100644 index 0000000000..14b3858788 --- /dev/null +++ b/news/5109.feature @@ -0,0 +1 @@ +Add external className to UniversalLink for external link. @iFlameing \ No newline at end of file diff --git a/src/components/manage/Blocks/LeadImage/__snapshots__/LeadImageSidebar.test.jsx.snap b/src/components/manage/Blocks/LeadImage/__snapshots__/LeadImageSidebar.test.jsx.snap index 0ba1de4ab6..175dfb089e 100644 --- a/src/components/manage/Blocks/LeadImage/__snapshots__/LeadImageSidebar.test.jsx.snap +++ b/src/components/manage/Blocks/LeadImage/__snapshots__/LeadImageSidebar.test.jsx.snap @@ -20,8 +20,8 @@ exports[`renders a Lead Image block Sidebar component 1`] = ` fetchpriority="high" height={400} sizes="188px" - src="http://localhost:3000/image.png" - srcSet="http://localhost:3000/image.png/@@images/image/image-400.png 400w" + src="/image.png" + srcSet="/image.png/@@images/image/image-400.png 400w" style={ Object { "aspectRatio": "400 / 400", diff --git a/src/components/manage/LinksToItem/LinksToItem.test.jsx b/src/components/manage/LinksToItem/LinksToItem.test.jsx index 31cf6b5ce4..0ec7dd61f6 100644 --- a/src/components/manage/LinksToItem/LinksToItem.test.jsx +++ b/src/components/manage/LinksToItem/LinksToItem.test.jsx @@ -3,6 +3,7 @@ import renderer from 'react-test-renderer'; import { Provider } from 'react-intl-redux'; import configureMockStore from 'redux-mock-store'; import thunk from 'redux-thunk'; +import { MemoryRouter } from 'react-router-dom'; import LinksToItem from './LinksToItem'; @@ -88,7 +89,9 @@ describe('LinksToItem', () => { }); const component = renderer.create( - + + + , ); const json = component.toJSON(); diff --git a/src/components/manage/LinksToItem/__snapshots__/LinksToItem.test.jsx.snap b/src/components/manage/LinksToItem/__snapshots__/LinksToItem.test.jsx.snap index 23d7280351..71a4163128 100644 --- a/src/components/manage/LinksToItem/__snapshots__/LinksToItem.test.jsx.snap +++ b/src/components/manage/LinksToItem/__snapshots__/LinksToItem.test.jsx.snap @@ -49,9 +49,9 @@ exports[`LinksToItem renders "links and references" view 1`] = ` > {children} diff --git a/src/components/manage/UniversalLink/__snapshots__/UniversalLink.test.jsx.snap b/src/components/manage/UniversalLink/__snapshots__/UniversalLink.test.jsx.snap index e9f0f1d40d..863e4bb130 100644 --- a/src/components/manage/UniversalLink/__snapshots__/UniversalLink.test.jsx.snap +++ b/src/components/manage/UniversalLink/__snapshots__/UniversalLink.test.jsx.snap @@ -17,9 +17,9 @@ exports[`UniversalLink check UniversalLink does not break with error in item 1`] exports[`UniversalLink renders a UniversalLink component if no external(href) link passed 1`] = `

@@ -30,7 +30,7 @@ exports[`UniversalLink renders a UniversalLink component if no external(href) li exports[`UniversalLink renders a UniversalLink component with external link 1`] = ` Date: Tue, 12 Sep 2023 10:13:25 +0300 Subject: [PATCH 10/12] Fix toc accessibility issue (#5058) --- cypress/tests/core/blocks/block-anchors.js | 4 ++-- news/5058.bugfix | 1 + packages/volto-slate/src/editor/render.jsx | 5 ++--- .../Blocks/Title/__snapshots__/View.test.jsx.snap | 1 + .../Blocks/ToC/variations/DefaultTocRenderer.jsx | 14 ++------------ .../__snapshots__/DefaultTocRenderer.test.jsx.snap | 10 ++++++++-- 6 files changed, 16 insertions(+), 19 deletions(-) create mode 100644 news/5058.bugfix diff --git a/cypress/tests/core/blocks/block-anchors.js b/cypress/tests/core/blocks/block-anchors.js index 1166b0ce26..91fe8ed989 100644 --- a/cypress/tests/core/blocks/block-anchors.js +++ b/cypress/tests/core/blocks/block-anchors.js @@ -63,9 +63,9 @@ describe('Block Tests: Anchors', () => { cy.contains('Slate Heading Anchors'); cy.get('h2[id="title-1"]').contains('Title 1'); cy.get('h2[id="title-2"]').contains('Title 2'); - cy.get('a[href="#title-1"]').click(); + cy.get('.table-of-contents a[href="/my-page#title-1"]').click(); cy.get('h2[id="title-1"]').scrollIntoView().should('be.visible'); - cy.get('a[href="#title-2"]').click(); + cy.get('.table-of-contents a[href="/my-page#title-2"]').click(); cy.get('h2[id="title-2"]').scrollIntoView().should('be.visible'); }); }); diff --git a/news/5058.bugfix b/news/5058.bugfix new file mode 100644 index 0000000000..2a67cc6d3e --- /dev/null +++ b/news/5058.bugfix @@ -0,0 +1 @@ +Fix toc accessibility issue @dobri1408 diff --git a/packages/volto-slate/src/editor/render.jsx b/packages/volto-slate/src/editor/render.jsx index 45ab42ca75..5b5542e4f0 100644 --- a/packages/volto-slate/src/editor/render.jsx +++ b/packages/volto-slate/src/editor/render.jsx @@ -174,13 +174,12 @@ export const renderLinkElement = (tagName) => { appPathname.concat(`#${slug}`), ); const intl = useIntl(); - return slate.useLinkedHeadings === false ? ( - + {children} ) : ( - + {children} {mode === 'view' && slug && ( My Title { - const history = useHistory(); - return map(items, (item) => { const { id, level, title, override_toc, plaintext } = item; const slug = override_toc @@ -23,14 +20,7 @@ const RenderListItems = ({ items, data }) => { return ( item && ( - { - history.push({ hash: slug }); - }} - > - {title} - + {title} {item.items?.length > 0 && ( Hello this is a sample page @@ -28,8 +31,11 @@ Array [ role="listitem" > Test level 3 From 71882fbb8f6238030c34e6af74fa084672af3fdf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cre=C8=9Bu=20Mihaela?= <68827085+MihaelaCretu11@users.noreply.github.com> Date: Tue, 12 Sep 2023 10:39:07 +0300 Subject: [PATCH 11/12] fix back button on search block to update the search results for #4402 (#4879) Co-authored-by: Andrei Grigore <44702393+andreiggr@users.noreply.github.com> Co-authored-by: Alexandru Ghica Co-authored-by: Mikel Larreategi Co-authored-by: Ion Lizarazu --- news/4402.bugfix | 1 + .../manage/Blocks/Search/hocs/withSearch.jsx | 67 ++++++++++++------- 2 files changed, 43 insertions(+), 25 deletions(-) create mode 100644 news/4402.bugfix diff --git a/news/4402.bugfix b/news/4402.bugfix new file mode 100644 index 0000000000..aee68dbeb1 --- /dev/null +++ b/news/4402.bugfix @@ -0,0 +1 @@ +Fix back button in the search block to execute the search by adding two useEffects that update the facets and search data based on the current URL. @MihaelaCretu11 \ No newline at end of file diff --git a/src/components/manage/Blocks/Search/hocs/withSearch.jsx b/src/components/manage/Blocks/Search/hocs/withSearch.jsx index 1fb910b2aa..2965ba4b93 100644 --- a/src/components/manage/Blocks/Search/hocs/withSearch.jsx +++ b/src/components/manage/Blocks/Search/hocs/withSearch.jsx @@ -5,6 +5,8 @@ import { useLocation, useHistory } from 'react-router-dom'; import { resolveExtension } from '@plone/volto/helpers/Extensions/withBlockExtensions'; import config from '@plone/volto/registry'; +import { usePrevious } from '@plone/volto/helpers'; +import { isEqual } from 'lodash'; function getDisplayName(WrappedComponent) { return WrappedComponent.displayName || WrappedComponent.name || 'Component'; @@ -253,35 +255,50 @@ const withSearch = (options) => (WrappedComponent) => { const multiFacets = data.facets ?.filter((facet) => facet?.multiple) .map((facet) => facet?.field?.value); - const [facets, setFacets] = React.useState( - Object.assign( - {}, - ...urlQuery.map(({ i, v }) => ({ [i]: v })), // TODO: the 'o' should be kept. This would be a major refactoring of the facets - - // support for simple filters like ?Subject=something - // TODO: since the move to hash params this is no longer working. - // We'd have to treat the location.search and manage it just like the - // hash, to support it. We can read it, but we'd have to reset it as - // well, so at that point what's the difference to the hash? - ...configuredFacets.map((f) => - locationSearchData[f] - ? { - [f]: - multiFacets.indexOf(f) > -1 - ? [locationSearchData[f]] - : locationSearchData[f], - } - : {}, - ), - ), - ); + const [facets, setFacets] = React.useState({}); + const previousUrlQuery = usePrevious(urlQuery); + + React.useEffect(() => { + if (!isEqual(urlQuery, previousUrlQuery)) { + setFacets( + Object.assign( + {}, + ...urlQuery.map(({ i, v }) => ({ [i]: v })), // TODO: the 'o' should be kept. This would be a major refactoring of the facets + + // support for simple filters like ?Subject=something + // TODO: since the move to hash params this is no longer working. + // We'd have to treat the location.search and manage it just like the + // hash, to support it. We can read it, but we'd have to reset it as + // well, so at that point what's the difference to the hash? + ...configuredFacets.map((f) => + locationSearchData[f] + ? { + [f]: + multiFacets.indexOf(f) > -1 + ? [locationSearchData[f]] + : locationSearchData[f], + } + : {}, + ), + ), + ); + } + }, [ + urlQuery, + configuredFacets, + locationSearchData, + multiFacets, + previousUrlQuery, + ]); const [sortOn, setSortOn] = React.useState(data?.query?.sort_on); const [sortOrder, setSortOrder] = React.useState(data?.query?.sort_order); - const [searchData, setSearchData] = React.useState( - getInitialState(data, facets, urlSearchText, id), - ); + const [searchData, setSearchData] = React.useState({}); + + React.useEffect(() => { + setSearchData(getInitialState(data, facets, urlSearchText, id)); + }, [facets, data, urlSearchText, id]); const timeoutRef = React.useRef(); const facetSettings = data?.facets; From f205332d494fb99f826f9fe2afd1f2eba4a70907 Mon Sep 17 00:00:00 2001 From: Wesley Barroso Lopes Date: Tue, 12 Sep 2023 04:39:26 -0300 Subject: [PATCH 12/12] Fix use of CSS modules in webpack 5 (#5165) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Víctor Fernández de Alba --- news/5019.bugfix | 1 + webpack-plugins/webpack-less-plugin.js | 19 +++++++++++++++++++ 2 files changed, 20 insertions(+) create mode 100644 news/5019.bugfix diff --git a/news/5019.bugfix b/news/5019.bugfix new file mode 100644 index 0000000000..f3a5d4a243 --- /dev/null +++ b/news/5019.bugfix @@ -0,0 +1 @@ +Fix use of CSS modules in webpack 5. @wesleybl diff --git a/webpack-plugins/webpack-less-plugin.js b/webpack-plugins/webpack-less-plugin.js index eed28455a5..1b35d87e46 100644 --- a/webpack-plugins/webpack-less-plugin.js +++ b/webpack-plugins/webpack-less-plugin.js @@ -4,6 +4,24 @@ const MiniCssExtractPlugin = require('mini-css-extract-plugin'); const PostCssFlexBugFixes = require('postcss-flexbugs-fixes'); const postcssLoadConfig = require('postcss-load-config'); +const interpolateName = require('loader-utils').interpolateName; + +function normalizePath(file) { + return path.sep === '\\' ? file.replace(/\\/g, '/') : file; +} + +// Custom function to not use 'loaderContext._module.matchResource' in hashing CSS class name. +function getLocalIdent(loaderContext, localIdentName, localName, options) { + const relativeResourcePath = normalizePath( + path.relative(options.context, loaderContext.resourcePath), + ); + + // eslint-disable-next-line no-param-reassign + options.content = `${options.hashPrefix}${relativeResourcePath}\x00${localName}`; + + return interpolateName(loaderContext, localIdentName, options); +} + const hasPostCssConfig = () => { try { return !!postcssLoadConfig.sync(); @@ -52,6 +70,7 @@ const defaultOptions = { modules: { auto: true, localIdentName: '[name]__[local]___[hash:base64:5]', + getLocalIdent: getLocalIdent, }, }, },